From 8258d9be596ebe3b7913cb406f8d16f53d66e438 Mon Sep 17 00:00:00 2001 From: yhangf Date: Fri, 10 Apr 2026 17:26:05 +0800 Subject: [PATCH 1/3] fix(agents): normalize tool name references in built-in agent prompts --- src/costrict/agents/requirement.ts | 8 ++++---- src/costrict/agents/strictPlan.ts | 10 +++++----- src/costrict/agents/subCoding.ts | 2 +- src/costrict/agents/taskCheck.ts | 2 +- src/costrict/agents/tddRunAndFix.ts | 4 ++-- src/costrict/agents/tddTestPrepare.ts | 14 +++++++------- src/costrict/agents/wikiCatalogueDesign.ts | 2 +- src/costrict/agents/wikiDocumentGenerate.ts | 4 ++-- src/costrict/agents/wikiProjectAnalyze.ts | 6 +++--- 9 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/costrict/agents/requirement.ts b/src/costrict/agents/requirement.ts index 80a395679..518f453a0 100644 --- a/src/costrict/agents/requirement.ts +++ b/src/costrict/agents/requirement.ts @@ -573,10 +573,10 @@ function getRequirementSystemPrompt(): string { --- # 工具使用策略 -1. 使用 read 读取文件内容 -2. 使用 write 创建新文件或覆盖已有文件 -3. 使用 edit 修改及追加内容到已有文件 -4. 禁止使用 bash 做新增、修改、追加内容等文件操作 +1. 使用 Read 读取文件内容 +2. 使用 Write 创建新文件或覆盖已有文件 +3. 使用 Edit 修改及追加内容到已有文件 +4. 禁止使用 Bash 做新增、修改、追加内容等文件操作 # 执行原则 diff --git a/src/costrict/agents/strictPlan.ts b/src/costrict/agents/strictPlan.ts index 6ddfd6b5f..55ef58686 100644 --- a/src/costrict/agents/strictPlan.ts +++ b/src/costrict/agents/strictPlan.ts @@ -33,7 +33,7 @@ function getStrictPlanSystemPrompt(): string { (2) 可复用的工具类/函数/已有实现机制、同类功能的代码组织模式和实现方案(学习实现方式) (3) 必须遵守的技术约束、架构规范、历史踩坑记录(识别风险和边界) - **SubAgent产出要求**:SubAgent必须提供可操作的技术决策依据,包括实现位置定位、可复用机制、技术约束、编码参考等有利于后续方案设计和编码的详细信息,而非泛泛的项目概况描述; - - **并行Agent调用**:在单条消息中多次调用\`task\`工具,并行启动 1~3 个QuickExplore SubAgent,高效完成项目探索工作; + - **并行Agent调用**:在单条消息中多次调用\`Agent\`工具,并行启动 1~3 个QuickExplore SubAgent,高效完成项目探索工作; - 质量优先原则:最多启用 3 个智能体,且优先使用完成任务所需的最少数量(通常仅需 1 个); - 单SubAgent适用场景:任务范围明确,仅涉及已知文件、用户已提供具体文件路径,或仅需执行小型定向修改; - 多SubAgent适用场景:任务范围模糊、涉及项目多个模块,或需要先梳理现有代码模式再开展方案规划; @@ -104,18 +104,18 @@ SubCodingAgent 只需理解与其任务直接相关的内容。分发任务时 ##### 任务执行流程 -使用 \`todowrite\` 工具列出 task.md 中的任务清单,作为待办事项跟踪。 +使用 \`TodoWrite\` 工具列出 task.md 中的任务清单,作为待办事项跟踪。 **按阶段执行任务**: -1. **分发任务**:调用 \`task\` 工具启动 SubCodingAgent 分发任务 +1. **分发任务**:调用 \`Agent\` 工具启动 SubCodingAgent 分发任务 2. **检查任务完成情况**: - 根据SubCodingAgent的任务完成情况,判断是否完成所有分配的任务 - 如果未完成任务,分析原因后指派新的 SubCodingAgent 进行改进 - 如果已完成任务: - - **立即更新 task.md**:使用 \`edit\` 更新 task.md 文件,将刚完成的任务标记为已完成(\`- [x]\`) - - **标记 todos 完成**:使用 \`todowrite\` 工具将当前任务标记为完成 + - **立即更新 task.md**:使用 \`Edit\` 更新 task.md 文件,将刚完成的任务标记为已完成(\`- [x]\`) + - **标记 todos 完成**:使用 \`TodoWrite\` 工具将当前任务标记为完成 - **重要顺序说明**:**必须先更新 task.md,最后标记 todos** 3. **循环执行**:重复上述步骤直到所有任务完成 diff --git a/src/costrict/agents/subCoding.ts b/src/costrict/agents/subCoding.ts index 6054628b1..8c979788b 100644 --- a/src/costrict/agents/subCoding.ts +++ b/src/costrict/agents/subCoding.ts @@ -16,7 +16,7 @@ function getSubCodingSystemPrompt(): string { - 代码现状:相关代码的结构、设计模式、编码风格是什么样的? - 影响范围:你的修改会影响哪些文件和模块? -理解方式:对目标文件做轻量、可控的探索(例如:通过 \`read\` 命令读取代码片段)。 +理解方式:对目标文件做轻量、可控的探索(例如:通过 \`Read\` 工具读取代码片段)。 ### 原则二:尊重项目架构 - 遵循目录结构:按照项目既定的目录结构、模块划分和包组织方式开展工作;不随意移动、重命名或重组文件/目录。 diff --git a/src/costrict/agents/taskCheck.ts b/src/costrict/agents/taskCheck.ts index 7c14dcbd7..9af765f16 100644 --- a/src/costrict/agents/taskCheck.ts +++ b/src/costrict/agents/taskCheck.ts @@ -50,7 +50,7 @@ function getTaskCheckSystemPrompt(): string { ### 阶段 3:完成门禁(唯一允许的用户交互点) 当 issues 清零后,执行: 1. 输出简短摘要(统计:阶段数/任务数/本轮主要修复点类型) -2. 仅在此处调用 \`question\` 工具 +2. 仅在此处调用 \`AskUserQuestion\` 工具 3. 若用户选择 continue 并给出反馈:把反馈当作新的输入,回到阶段 2 继续自动修复 ### 输出示例 diff --git a/src/costrict/agents/tddRunAndFix.ts b/src/costrict/agents/tddRunAndFix.ts index 0b431c3da..11860942d 100644 --- a/src/costrict/agents/tddRunAndFix.ts +++ b/src/costrict/agents/tddRunAndFix.ts @@ -99,7 +99,7 @@ Phase 6:修复编码问题 **修复策略:** - 如果编码错误在**当前修改的文件**或**最近修改的文件**中:直接修复,无需询问 -- 如果编码错误未在**最近修改的文件**中:使用 \`question\` 工具请求用户许可 +- 如果编码错误未在**最近修改的文件**中:使用 \`AskUserQuestion\` 工具请求用户许可 - 询问:"在 [文件名] 中发现错误:[错误描述]。该文件最近未修改,允许我修复吗?" - 等待用户确认后再继续 - 如果用户批准一次,记住此许可,后续对非最近文件的修复不再询问 @@ -214,7 +214,7 @@ Phase 9:完成验证 **需要用户确认**: - 非最近修改的文件中的错误 - - 使用 \`question\` 工具请求许可 + - 使用 \`AskUserQuestion\` 工具请求许可 - 描述错误和文件 - 等待用户确认 diff --git a/src/costrict/agents/tddTestPrepare.ts b/src/costrict/agents/tddTestPrepare.ts index 5bd666bff..1c825d011 100644 --- a/src/costrict/agents/tddTestPrepare.ts +++ b/src/costrict/agents/tddTestPrepare.ts @@ -24,8 +24,8 @@ function getTddTestPrepareSystemPrompt(): string { 4. **命令确认原则** - 只有从现有的 TEST_GUIDE.md 内容中直接提取的命令可以直接使用 - - 其他任何方式(搜索、推测、根据语言框架生成等)得到的命令都必须使用 \`question\` 工具向用户确认后才能使用 - - 对于查询不到的命令,根据语言/框架提供推荐命令,通过 question 工具询问用户确认 + - 其他任何方式(搜索、推测、根据语言框架生成等)得到的命令都必须使用 \`AskUserQuestion\` 工具向用户确认后才能使用 + - 对于查询不到的命令,根据语言/框架提供推荐命令,通过 AskUserQuestion 工具询问用户确认 - **严禁在 TEST_GUIDE.md 中写 TODO 注释** 5. **退出策略** @@ -36,15 +36,15 @@ function getTddTestPrepareSystemPrompt(): string { 执行流程: - **使用 todowrite 工具管理任务进度**: + **使用 TodoWrite 工具管理任务进度**: - 在开始工作前,必须使用 \`todowrite\` 工具创建任务列表: + 在开始工作前,必须使用 \`TodoWrite\` 工具创建任务列表: 1. Check TEST_GUIDE.md completeness 2. Ask user if auto-search needed 3. Identify runnability verification commands 4. Identify test case management methods 5. Identify test execution methods - 6. Confirm with user (question tool) + 6. Confirm with user (AskUserQuestion tool) 7. Update TEST_GUIDE.md 在每个 phase 执行时: @@ -63,7 +63,7 @@ Phase 1:检查 TEST_GUIDE.md 完整性并解析指引文档 5. 如果指引文档不存在或未指向任何文档,进入 Phase 1.5 Phase 1.5:询问是否自动搜索 -- 使用 \`question\` 工具询问用户是否需要自动搜索项目文件 +- 使用 \`AskUserQuestion\` 工具询问用户是否需要自动搜索项目文件 - header: "搜索方式" - question: "TEST_GUIDE.md 内容不完整,是否自动搜索项目文件以分析测试命令?(支持在后续确认时自定义输入)" - options: [ @@ -93,7 +93,7 @@ Phase 2:搜索项目文件(仅当用户选择"自动搜索"时执行,使 - 优先级2:CI/CD 配置文件(.github/workflows、.gitlab-ci.yml 等) - 优先级3:常见测试命令(jest、pytest、go test、npm test、bun test 等) -Phase 3:用户确认(使用 \`question\` 工具,三个问题作为独立数组提交) +Phase 3:用户确认(使用 \`AskUserQuestion\` 工具,三个问题作为独立数组提交) **问题1:可运行性验证命令** - header: "可运行性" diff --git a/src/costrict/agents/wikiCatalogueDesign.ts b/src/costrict/agents/wikiCatalogueDesign.ts index 1231481b2..7134699af 100644 --- a/src/costrict/agents/wikiCatalogueDesign.ts +++ b/src/costrict/agents/wikiCatalogueDesign.ts @@ -21,7 +21,7 @@ function getWikiCatalogueDesignSystemPrompt(): string { 深度解析目标代码库,生成动态适配项目特性的分层JSON文档结构,为后续深度分析与文档生成提供结构化指导框架。 ## 输入信息 -- **项目分类结果**: 通过 \`read\` 工具读取 \`.costrict/wiki/.staging/basic_analyze.json\` +- **项目分类结果**: 通过 \`Read\` 工具读取 \`.costrict/wiki/.staging/basic_analyze.json\` - **完整代码仓库**: 包含所有源代码、配置文件及项目文档 ## 分析流程 diff --git a/src/costrict/agents/wikiDocumentGenerate.ts b/src/costrict/agents/wikiDocumentGenerate.ts index a448407da..2b612aa97 100644 --- a/src/costrict/agents/wikiDocumentGenerate.ts +++ b/src/costrict/agents/wikiDocumentGenerate.ts @@ -104,7 +104,7 @@ function getWikiDocumentGenerateSystemPrompt(): string { ### 步骤3:深度代码分析 - 系统性文件审查 对所有提供的代码文件进行彻底的、任务驱动的深度分析。此阶段专注于理解而非文档化。 -1. **系统性文件审查**: 全面使用 \`read\` 工具读取每个关键文件 +1. **系统性文件审查**: 全面使用 \`Read\` 工具读取每个关键文件 2. **模式识别**: 识别: - 架构模式(MVC、微服务等) @@ -162,7 +162,7 @@ function getWikiDocumentGenerateSystemPrompt(): string { - 优先级4: 环境变量配置 **执行要求:** -- 使用 \`read\` 工具按优先级批量读取关键代码文件 +- 使用 \`Read\` 工具按优先级批量读取关键代码文件 - 分析文件的架构模式与设计决策 - 识别组件间的依赖关系 - 建立完整的技术理解 diff --git a/src/costrict/agents/wikiProjectAnalyze.ts b/src/costrict/agents/wikiProjectAnalyze.ts index a41769dfe..30a6b739b 100644 --- a/src/costrict/agents/wikiProjectAnalyze.ts +++ b/src/costrict/agents/wikiProjectAnalyze.ts @@ -19,7 +19,7 @@ function getWikiProjectAnalyzeSystemPrompt(): string { ### 必须读取的文件 - **项目根目录文件**: README.md、package.json、requirements.txt、Cargo.toml等核心配置 - **配置文件**: tsconfig.json、pyproject.toml、Dockerfile、CI/CD配置等 -- **完整目录结构**: 通过 \`list\` 工具获取的项目全貌 +- **完整目录结构**: 通过 \`Bash\` 工具获取的项目全貌 ## 项目特征分析框架 @@ -108,8 +108,8 @@ function getWikiProjectAnalyzeSystemPrompt(): string { ## 执行流程 ### 步骤1:项目概览分析 -- 使用 \`list\` 工具获取完整项目结构 -- 使用 \`read\` 工具解析关键配置文件 +- 使用 \`Bash\` 工具获取完整项目结构 +- 使用 \`Read\` 工具解析关键配置文件 - 识别项目技术栈与基本特征 ### 步骤2:深度结构分析 From 6fb91d2c28c0fa3fde4fca1c6ad6e4a5b91647ca Mon Sep 17 00:00:00 2001 From: Askhz <1361267452@qq.com> Date: Sat, 11 Apr 2026 01:41:55 +0800 Subject: [PATCH 2/3] feat(logo): show "Not logged in" state and provider display name in logo Add isNotLoggedIn() utility to detect unauthenticated state and display "Not logged in" message in both LogoV2 and CondensedLogo components. Replace billing type with provider display name (e.g. "OpenAI", "AWS Bedrock") when logged in. Subscribe to authVersion to re-render on login/logout. Add third-party provider model options for OpenAI, Gemini, Grok, Bedrock, Vertex, and Foundry. Disable biome formatter. --- src/components/LogoV2/CondensedLogo.tsx | 9 +++++-- src/components/LogoV2/LogoV2.tsx | 13 ++++++--- src/utils/logoV2Utils.ts | 36 +++++++++++++++++++++---- src/utils/model/providers.ts | 26 ++++++++++++++++++ 4 files changed, 73 insertions(+), 11 deletions(-) diff --git a/src/components/LogoV2/CondensedLogo.tsx b/src/components/LogoV2/CondensedLogo.tsx index 13419d62c..0e7891200 100644 --- a/src/components/LogoV2/CondensedLogo.tsx +++ b/src/components/LogoV2/CondensedLogo.tsx @@ -7,7 +7,7 @@ import { useAppState } from '../../state/AppState.js'; import { getEffortSuffix } from '../../utils/effort.js'; import { truncate } from '../../utils/format.js'; import { isFullscreenEnvEnabled } from '../../utils/fullscreen.js'; -import { formatModelAndBilling, getLogoDisplayData, truncatePath } from '../../utils/logoV2Utils.js'; +import { formatModelAndBilling, getLogoDisplayData, isNotLoggedIn, truncatePath } from '../../utils/logoV2Utils.js'; import { renderModelSetting } from '../../utils/model/model.js'; import { OffscreenFreeze } from '../OffscreenFreeze.js'; import { AnimatedClawd } from './AnimatedClawd.js'; @@ -23,7 +23,10 @@ export function CondensedLogo(): ReactNode { const { columns } = useTerminalSize(); const agent = useAppState(s => s.agent); const effortValue = useAppState(s => s.effortValue); + // Subscribe to authVersion to re-render after login/logout + useAppState(s => s.authVersion); const model = useMainLoopModel(); + const notLoggedIn = isNotLoggedIn(); const modelDisplayName = renderModelSetting(model); const { version, cwd, billingType, agentName: agentNameFromSettings } = getLogoDisplayData(); @@ -92,7 +95,9 @@ export function CondensedLogo(): ReactNode { {' '} v{truncatedVersion} - {shouldSplit ? ( + {notLoggedIn ? ( + Not logged in + ) : shouldSplit ? ( <> {truncatedModel} {truncatedBilling} diff --git a/src/components/LogoV2/LogoV2.tsx b/src/components/LogoV2/LogoV2.tsx index 2c998a224..cfec387fc 100644 --- a/src/components/LogoV2/LogoV2.tsx +++ b/src/components/LogoV2/LogoV2.tsx @@ -11,6 +11,7 @@ import { getRecentActivitySync, getRecentReleaseNotesSync, getLogoDisplayData, + isNotLoggedIn, } from '../../utils/logoV2Utils.js'; import { truncate } from '../../utils/format.js'; import { getDisplayPath } from '../../utils/file.js'; @@ -82,6 +83,8 @@ export function LogoV2(): React.ReactNode { const showOverageCreditUpsell = useShowOverageCreditUpsell(); const agent = useAppState(s => s.agent); const effortValue = useAppState(s => s.effortValue); + // Subscribe to authVersion to re-render after login/logout + useAppState(s => s.authVersion); const config = getGlobalConfig(); @@ -136,6 +139,7 @@ export function LogoV2(): React.ReactNode { }, [showOverageCreditUpsell, showOnboarding, showGuestPassesUpsell, isCondensedMode]); const model = useMainLoopModel(); + const notLoggedIn = isNotLoggedIn(); const fullModelDisplayName = renderModelSetting(model); const { version, cwd, billingType, agentName: agentNameFromSettings } = getLogoDisplayData(); // Prefer AppState.agent (set from --agent CLI flag) over settings @@ -247,8 +251,8 @@ export function LogoV2(): React.ReactNode { - {modelDisplayName} - {billingType} + {notLoggedIn ? 'Not logged in' : modelDisplayName} + {!notLoggedIn && {billingType}} {agentName ? `@${agentName} · ${truncatedCwd}` : truncatedCwd} @@ -269,8 +273,9 @@ export function LogoV2(): React.ReactNode { } const welcomeMessage = formatWelcomeMessage(username); - const modelLine = - !process.env.IS_DEMO && config.oauthAccount?.organizationName + const modelLine = notLoggedIn + ? 'Not logged in' + : !process.env.IS_DEMO && config.oauthAccount?.organizationName ? `${modelDisplayName} · ${billingType} · ${config.oauthAccount.organizationName}` : `${modelDisplayName} · ${billingType}`; // Calculate cwd width accounting for agent name if present diff --git a/src/utils/logoV2Utils.ts b/src/utils/logoV2Utils.ts index 4357119d7..861d45200 100644 --- a/src/utils/logoV2Utils.ts +++ b/src/utils/logoV2Utils.ts @@ -1,7 +1,8 @@ import { getDirectConnectServerUrl, getSessionId } from '../bootstrap/state.js' import { stringWidth } from '@anthropic/ink' import type { LogOption } from '../types/logs.js' -import { getSubscriptionName, isClaudeAISubscriber } from './auth.js' +import { getAnthropicApiKey } from './auth.js' +import { hasCoStrictCredentialsSync } from '../costrict/provider/credentials.js' import { getCwd } from './cwd.js' import { getDisplayPath } from './file.js' import { @@ -9,6 +10,7 @@ import { truncateToWidth, truncateToWidthNoEllipsis, } from './format.js' +import { getAPIProvider, getProviderDisplayName } from './model/providers.js' import { getStoredChangelogFromMemory, parseChangelog } from './releaseNotes.js' import { gt } from './semver.js' import { loadMessageLogs } from './sessionStorage.js' @@ -237,12 +239,33 @@ export function formatReleaseNoteForDisplay( } /** - * Gets the common logo display data used by both LogoV2 and CondensedLogo + * Check if user is not logged in + * User is considered logged in if they have CoStrict credentials or API key */ +export function isNotLoggedIn(): boolean { + // 1. CoStrict login (credentials file exists) + if (hasCoStrictCredentialsSync()) return false + + const settings = getInitialSettings() + + // 2. Any provider configured via modelType (包括 anthropic/openai/bedrock 等) + // 用户通过 /login 选择 provider 后会设置 modelType + if (settings.modelType) { + return false + } + + // 3. Anthropic API Key configured (legacy way without modelType) + if (getAnthropicApiKey() !== null) return false + + // None of the above - not logged in + return true +} + export function getLogoDisplayData(): { version: string cwd: string billingType: string + isLoggedIn: boolean agentName: string | undefined } { const version = process.env.DEMO_VERSION ?? MACRO.VERSION @@ -253,15 +276,18 @@ export function getLogoDisplayData(): { const cwd = serverUrl ? `${displayPath} in ${serverUrl.replace(/^https?:\/\//, '')}` : displayPath - const billingType = isClaudeAISubscriber() - ? getSubscriptionName() - : 'API Usage Billing' + + const loggedIn = !isNotLoggedIn() + const provider = getAPIProvider() + const providerName = getProviderDisplayName(provider) + const billingType = loggedIn ? providerName : 'Not logged in' const agentName = getInitialSettings().agent return { version, cwd, billingType, + isLoggedIn: loggedIn, agentName, } } diff --git a/src/utils/model/providers.ts b/src/utils/model/providers.ts index b5b55444c..45c76d3ca 100644 --- a/src/utils/model/providers.ts +++ b/src/utils/model/providers.ts @@ -35,6 +35,32 @@ export function getAPIProviderForStatsig(): AnalyticsMetadata_I_VERIFIED_THIS_IS return getAPIProvider() as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS } +/** + * Get a human-readable display name for the current API provider + */ +export function getProviderDisplayName(provider: APIProvider): string { + switch (provider) { + case 'firstParty': + return 'Anthropic' + case 'bedrock': + return 'AWS Bedrock' + case 'vertex': + return 'Google Vertex' + case 'foundry': + return 'Foundry' + case 'openai': + return 'OpenAI' + case 'gemini': + return 'Google Gemini' + case 'grok': + return 'xAI Grok' + case 'costrict': + return 'CoStrict' + default: + return provider + } +} + /** * Check if ANTHROPIC_BASE_URL is a first-party Anthropic API URL. * Returns true if not set (default API) or points to api.anthropic.com From 404e725c516896d2852c4c62ca709f8a9e33758b Mon Sep 17 00:00:00 2001 From: yhangf Date: Sat, 11 Apr 2026 11:49:05 +0800 Subject: [PATCH 3/3] refactor(AgentTool): disable STRICT_SPEC_AGENT from built-in agents --- src/tools/AgentTool/builtInAgents.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/AgentTool/builtInAgents.ts b/src/tools/AgentTool/builtInAgents.ts index df6c88299..b3ba393a9 100644 --- a/src/tools/AgentTool/builtInAgents.ts +++ b/src/tools/AgentTool/builtInAgents.ts @@ -6,7 +6,7 @@ import { DESIGN_AGENT } from '../../costrict/agents/designAgent.js' import { QUICK_EXPLORE_AGENT } from '../../costrict/agents/quickExplore.js' import { REQUIREMENT_AGENT } from '../../costrict/agents/requirement.js' import { STRICT_PLAN_AGENT } from '../../costrict/agents/strictPlan.js' -import { STRICT_SPEC_AGENT } from '../../costrict/agents/strictSpec.js' +// import { STRICT_SPEC_AGENT } from '../../costrict/agents/strictSpec.js' import { SUB_CODING_AGENT } from '../../costrict/agents/subCoding.js' import { TASK_CHECK_AGENT } from '../../costrict/agents/taskCheck.js' import { TASK_PLAN_AGENT } from '../../costrict/agents/taskPlan.js' @@ -64,7 +64,7 @@ export function getBuiltInAgents(): AgentDefinition[] { STATUSLINE_SETUP_AGENT, PLAN_AGENT, // StrictSpec workflow: 4-stage pipeline (Requirement → DesignAgent → TaskPlan → SubCoding) - STRICT_SPEC_AGENT, + // STRICT_SPEC_AGENT, REQUIREMENT_AGENT, DESIGN_AGENT, TASK_PLAN_AGENT,