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/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 ea27c9c55..dbd4cf1cc 100644
--- a/src/costrict/agents/strictPlan.ts
+++ b/src/costrict/agents/strictPlan.ts
@@ -53,7 +53,7 @@ function getStrictPlanSystemPrompt(): string {
(2) 可复用的工具类/函数/已有实现机制、同类功能的代码组织模式和实现方案(学习实现方式)
(3) 必须遵守的技术约束、架构规范、历史踩坑记录(识别风险和边界)
- **SubAgent产出要求**:SubAgent必须提供可操作的技术决策依据,包括实现位置定位、可复用机制、技术约束、编码参考等有利于后续方案设计和编码的详细信息,而非泛泛的项目概况描述;
- - **并行Agent调用**:在单条消息中多次调用\`task\`工具,并行启动 1~3 个QuickExplore SubAgent,高效完成项目探索工作;
+ - **并行Agent调用**:在单条消息中多次调用\`Agent\`工具,并行启动 1~3 个QuickExplore SubAgent,高效完成项目探索工作;
- 质量优先原则:最多启用 3 个智能体,且优先使用完成任务所需的最少数量(通常仅需 1 个);
- 单SubAgent适用场景:任务范围明确,仅涉及已知文件、用户已提供具体文件路径,或仅需执行小型定向修改;
- 多SubAgent适用场景:任务范围模糊、涉及项目多个模块,或需要先梳理现有代码模式再开展方案规划;
@@ -124,18 +124,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:深度结构分析
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,
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