Files
claude-code/packages/builtin-tools/src/tools/PowerShellTool/__tests__/gitSafety.test.ts
claude-code-best bddd146f25 feat: 重构供应商层次 (#286)
* refactor: 创建 @anthropic-ai/model-provider 包骨架与类型定义

- 新建 workspace 包 packages/@anthropic-ai/model-provider
- 定义 ModelProviderHooks 接口(依赖注入:分析、成本、日志等)
- 定义 ClientFactories 接口(Anthropic/OpenAI/Gemini/Grok 客户端工厂)
- 搬入核心类型:Message 体系、NonNullableUsage、EMPTY_USAGE、SystemPrompt、错误常量
- 主项目 src/types/message.ts 等改为 re-export,保持向后兼容

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: 提升 OpenAI 转换器和模型映射到 model-provider 包

- 搬入 OpenAI 消息转换(convertMessages)、工具转换(convertTools)、流适配(streamAdapter)
- 搬入 OpenAI 和 Grok 模型映射(resolveOpenAIModel、resolveGrokModel)
- 主项目文件改为 thin re-export proxy

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: 搬入 Gemini 兼容层到 model-provider 包

- 搬入 Gemini 类型定义、消息转换、工具转换、流适配、模型映射
- 主项目 gemini/ 目录下文件改为 thin re-export proxy

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: 搬入 errorUtils 并迁移消费者导入到 model-provider

- 搬入 formatAPIError、extractConnectionErrorDetails 等 errorUtils
- 迁移 10 个消费者文件直接从 @anthropic-ai/model-provider 导入
- 更新 emptyUsage、sdkUtilityTypes、systemPromptType 为 re-export proxy

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: compact 模型降级为 -1 模式(Opus→Sonnet, Sonnet→Haiku)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 添加 agent-loop 绘图

* Revert "feat: compact 模型降级为 -1 模式(Opus→Sonnet, Sonnet→Haiku)"

This reverts commit e458d6391d.

* docs: 添加简化版 agent loop

* fix: 修复 n 快捷键导致关闭的问题

* fix: 修复 node 下 ws 没打包问题

* docs: 修复链接

* test: 添加测试支持

* fix: 修复类型问题(#267) (#271)

* fix: 修复 Bun 的 polyfill 问题

* fix: 类型修复完成

* feat: 统一所有包的类型文件

* fix: 修复构建问题

* test: 修复类型校验 (#279)

* fix: 修复 Bun 的 polyfill 问题

* fix: 类型修复完成

* feat: 统一所有包的类型文件

* fix: 修复构建问题

* fix(remote-control): harden self-hosted session flows (#278)

Co-authored-by: chengzifeng <chengzifeng@meituan.com>

* docs: update contributors

* build: 新增 vite 构建流程

* feat: 添加环境变量支持以覆盖 max_tokens 设置

* feat(langfuse): LLM generation 记录工具定义

将 Anthropic 格式的工具定义转换为 Langfuse 兼容的 OpenAI 格式,
并在 generation 的 input 中以 { messages, tools } 结构传入,
以便在 Langfuse UI 中查看完整的工具定义信息。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: 添加对 ACP 协议的支持 (#284)

* feat: 适配 zed acp 协议

* docs: 完善 acp 文档

* chore: 1.4.0

* conflict: 解决冲突

* feat: 添加测试覆盖率上报

* style: 改名加移动文件夹位置

* refactor: 移动测试用例及实现

* test: 修复测试用例完成

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Cheng Zi Feng <1154238323@qq.com>
Co-authored-by: chengzifeng <chengzifeng@meituan.com>
Co-authored-by: claude-code-best <272536312+claude-code-best@users.noreply.github.com>
2026-04-17 09:33:14 +08:00

143 lines
4.1 KiB
TypeScript

import { mock, describe, expect, test } from "bun:test";
// Mock dependencies before import
const mockCwd = "/Users/test/project";
mock.module("src/utils/cwd.js", () => ({
getCwd: () => mockCwd,
}));
// Defensive: agent.test.ts can corrupt Bun's src/* path alias at runtime.
mock.module("src/utils/powershell/parser.js", () => ({
PS_TOKENIZER_DASH_CHARS: new Set(['-', '\u2013', '\u2014', '\u2015']),
COMMON_ALIASES: {},
commandHasArgAbbreviation: () => false,
deriveSecurityFlags: () => ({}),
getAllCommands: () => [],
getVariablesByScope: () => [],
hasCommandNamed: () => false,
parsePowerShellCommandCached: () => ({ valid: false, errors: [], statements: [], variables: [], hasStopParsing: false, originalCommand: "" }),
}))
const { isGitInternalPathPS, isDotGitPathPS } = await import("../gitSafety");
describe("isGitInternalPathPS", () => {
test("detects .git/config", () => {
expect(isGitInternalPathPS(".git/config")).toBe(true);
});
test("detects .git/hooks/pre-commit", () => {
expect(isGitInternalPathPS(".git/hooks/pre-commit")).toBe(true);
});
test("detects HEAD", () => {
expect(isGitInternalPathPS("HEAD")).toBe(true);
});
test("detects refs/heads/main", () => {
expect(isGitInternalPathPS("refs/heads/main")).toBe(true);
});
test("detects objects/pack/abc.pack", () => {
expect(isGitInternalPathPS("objects/pack/abc.pack")).toBe(true);
});
test("detects hooks/pre-commit", () => {
expect(isGitInternalPathPS("hooks/pre-commit")).toBe(true);
});
test("detects .git", () => {
expect(isGitInternalPathPS(".git")).toBe(true);
});
test("detects .git/HEAD", () => {
expect(isGitInternalPathPS(".git/HEAD")).toBe(true);
});
test("normal file is not git-internal", () => {
expect(isGitInternalPathPS("src/main.ts")).toBe(false);
});
test("README.md is not git-internal", () => {
expect(isGitInternalPathPS("README.md")).toBe(false);
});
test("package.json is not git-internal", () => {
expect(isGitInternalPathPS("package.json")).toBe(false);
});
test("handles backslash paths (Windows)", () => {
expect(isGitInternalPathPS(".git\\config")).toBe(true);
});
test("handles .git with NTFS short name (git~1)", () => {
expect(isGitInternalPathPS("git~1/config")).toBe(true);
});
test("handles .git with NTFS short name variant (git~2)", () => {
expect(isGitInternalPathPS("git~2/HEAD")).toBe(true);
});
test("handles leading ./ prefix", () => {
expect(isGitInternalPathPS("./.git/config")).toBe(true);
});
test("handles quoted paths", () => {
expect(isGitInternalPathPS('".git/config"')).toBe(true);
});
test("handles backtick-escaped paths", () => {
expect(isGitInternalPathPS("`.gi`t/config")).toBe(true);
});
});
describe("isDotGitPathPS", () => {
test("detects .git/config", () => {
expect(isDotGitPathPS(".git/config")).toBe(true);
});
test("detects .git", () => {
expect(isDotGitPathPS(".git")).toBe(true);
});
test("detects .git/hooks/pre-commit", () => {
expect(isDotGitPathPS(".git/hooks/pre-commit")).toBe(true);
});
test(".gitignore is NOT a .git path", () => {
expect(isDotGitPathPS(".gitignore")).toBe(false);
});
test(".gitmodules is NOT a .git path", () => {
expect(isDotGitPathPS(".gitmodules")).toBe(false);
});
test("HEAD alone is NOT a .git path (could be non-git file)", () => {
expect(isDotGitPathPS("HEAD")).toBe(false);
});
test("refs/heads is NOT a .git path (bare-repo style)", () => {
expect(isDotGitPathPS("refs/heads/main")).toBe(false);
});
test("hooks/pre-commit is NOT a .git path (bare-repo style)", () => {
expect(isDotGitPathPS("hooks/pre-commit")).toBe(false);
});
test("handles NTFS short name git~1", () => {
expect(isDotGitPathPS("git~1/config")).toBe(true);
});
test("normal file is not .git path", () => {
expect(isDotGitPathPS("src/main.ts")).toBe(false);
});
test("handles backslash paths", () => {
expect(isDotGitPathPS(".git\\HEAD")).toBe(true);
});
test("handles quoted paths", () => {
expect(isDotGitPathPS('".git/HEAD"')).toBe(true);
});
});