refactor: 重构 provider、agents、status 及相关工具模块

This commit is contained in:
Ubuntu 2026-04-14 14:19:27 +00:00
parent 3c41abe5ef
commit 88e2ce1e70
34 changed files with 301 additions and 311 deletions

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
#node_modules
node_modules
.DS_Store
dist
coverage

View File

@ -1,2 +0,0 @@
{"t":0,"agent":"a9f2b75","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"}
{"t":0,"agent":"a9f2b75","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":268224}

View File

@ -1,5 +1,5 @@
{
"name": "@costrict/csc-beta",
"name": "@costrict/csc",
"version": "4.0.4",
"description": "Reverse-engineered Anthropic Claude Code CLI — interactive AI coding assistant in the terminal",

View File

@ -2,27 +2,27 @@ import { feature } from 'bun:bundle'
import { getIsNonInteractiveSession } from 'src/bootstrap/state.js'
import { getFeatureValue_CACHED_MAY_BE_STALE } from 'src/services/analytics/growthbook.js'
import { isEnvTruthy } from 'src/utils/envUtils.js'
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 { 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'
import { DESIGN_AGENT } from 'src/costrict/agents/designAgent.js'
import { QUICK_EXPLORE_AGENT } from 'src/costrict/agents/quickExplore.js'
import { REQUIREMENT_AGENT } from 'src/costrict/agents/requirement.js'
import { STRICT_PLAN_AGENT } from 'src/costrict/agents/strictPlan.js'
// import { STRICT_SPEC_AGENT } from 'src/costrict/agents/strictSpec.js'
import { SUB_CODING_AGENT } from 'src/costrict/agents/subCoding.js'
import { TASK_CHECK_AGENT } from 'src/costrict/agents/taskCheck.js'
import { TASK_PLAN_AGENT } from 'src/costrict/agents/taskPlan.js'
import { CLAUDE_CODE_GUIDE_AGENT } from './built-in/claudeCodeGuideAgent.js'
import { EXPLORE_AGENT } from './built-in/exploreAgent.js'
import { GENERAL_PURPOSE_AGENT } from './built-in/generalPurposeAgent.js'
import { PLAN_AGENT } from './built-in/planAgent.js'
import { WIKI_PROJECT_ANALYZE_AGENT } from '../../costrict/agents/wikiProjectAnalyze.js'
import { WIKI_CATALOGUE_DESIGN_AGENT } from '../../costrict/agents/wikiCatalogueDesign.js'
import { WIKI_DOCUMENT_GENERATE_AGENT } from '../../costrict/agents/wikiDocumentGenerate.js'
import { WIKI_INDEX_GENERATION_AGENT } from '../../costrict/agents/wikiIndexGeneration.js'
import { TDD_RUN_AND_FIX_AGENT } from '../../costrict/agents/tddRunAndFix.js'
import { TDD_TEST_AND_FIX_AGENT } from '../../costrict/agents/tddTestAndFix.js'
import { TDD_TEST_DESIGN_AGENT } from '../../costrict/agents/tddTestDesign.js'
import { TDD_TEST_PREPARE_AGENT } from '../../costrict/agents/tddTestPrepare.js'
import { TDD_AGENT } from '../../costrict/backup/tdd.js'
import { WIKI_PROJECT_ANALYZE_AGENT } from 'src/costrict/agents/wikiProjectAnalyze.js'
import { WIKI_CATALOGUE_DESIGN_AGENT } from 'src/costrict/agents/wikiCatalogueDesign.js'
import { WIKI_DOCUMENT_GENERATE_AGENT } from 'src/costrict/agents/wikiDocumentGenerate.js'
import { WIKI_INDEX_GENERATION_AGENT } from 'src/costrict/agents/wikiIndexGeneration.js'
import { TDD_RUN_AND_FIX_AGENT } from 'src/costrict/agents/tddRunAndFix.js'
import { TDD_TEST_AND_FIX_AGENT } from 'src/costrict/agents/tddTestAndFix.js'
import { TDD_TEST_DESIGN_AGENT } from 'src/costrict/agents/tddTestDesign.js'
import { TDD_TEST_PREPARE_AGENT } from 'src/costrict/agents/tddTestPrepare.js'
import { TDD_AGENT } from 'src/costrict/backup/tdd.js'
import { STATUSLINE_SETUP_AGENT } from './built-in/statuslineSetup.js'
import { VERIFICATION_AGENT } from './built-in/verificationAgent.js'
import type { AgentDefinition } from './loadAgentsDir.js'

View File

@ -1,4 +1,5 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import type { Theme } from '@anthropic/ink';
import {
type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
logEvent,
@ -1251,7 +1252,7 @@ function OAuthStatusMessage({
<Box flexDirection="column" gap={1}>
<Text>Opening browser for CoStrict login. If it does not open automatically, copy and paste this URL:</Text>
<Box marginY={1}>
<Text color="cyan">{oauthStatus.url}</Text>
<Text color={'cyan' as keyof Theme}>{oauthStatus.url}</Text>
</Box>
<Text dimColor>Waiting for authentication...</Text>
</Box>

View File

@ -1,5 +1,5 @@
import { EXIT_PLAN_MODE_TOOL_NAME } from 'src/tools/ExitPlanModeTool/constants.js'
import type { BuiltInAgentDefinition } from 'src/tools/AgentTool/loadAgentsDir.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/ExitPlanModeTool/constants.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getDesignAgentSystemPrompt(): string {
return `你是 DesignAgent一名专业软件开发团队中的资深软件架构师。

View File

@ -1,9 +1,9 @@
import { EXIT_PLAN_MODE_TOOL_NAME } from 'src/tools/ExitPlanModeTool/constants.js'
import { FILE_EDIT_TOOL_NAME } from 'src/tools/FileEditTool/constants.js'
import { FILE_WRITE_TOOL_NAME } from 'src/tools/FileWriteTool/prompt.js'
import { NOTEBOOK_EDIT_TOOL_NAME } from 'src/tools/NotebookEditTool/constants.js'
import { AGENT_TOOL_NAME } from '../../tools/AgentTool/constants.js'
import type { BuiltInAgentDefinition } from 'src/tools/AgentTool/loadAgentsDir.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/ExitPlanModeTool/constants.js'
import { FILE_EDIT_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/FileEditTool/constants.js'
import { FILE_WRITE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/FileWriteTool/prompt.js'
import { NOTEBOOK_EDIT_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/NotebookEditTool/constants.js'
import { AGENT_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/AgentTool/constants.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getQuickExploreSystemPrompt(): string {

View File

@ -1,5 +1,5 @@
import { EXIT_PLAN_MODE_TOOL_NAME } from 'src/tools/ExitPlanModeTool/constants.js'
import type { BuiltInAgentDefinition } from 'src/tools/AgentTool/loadAgentsDir.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/ExitPlanModeTool/constants.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getRequirementSystemPrompt(): string {
return `# 角色

View File

@ -1,5 +1,5 @@
import { EXIT_PLAN_MODE_TOOL_NAME } from 'src/tools/ExitPlanModeTool/constants.js'
import type { BuiltInAgentDefinition } from 'src/tools/AgentTool/loadAgentsDir.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/ExitPlanModeTool/constants.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getStrictPlanSystemPrompt(): string {

View File

@ -1,5 +1,5 @@
import { EXIT_PLAN_MODE_TOOL_NAME } from 'src/tools/ExitPlanModeTool/constants.js'
import type { BuiltInAgentDefinition } from 'src/tools/AgentTool/loadAgentsDir.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/ExitPlanModeTool/constants.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getStrictSpecSystemPrompt(): string {
return `你是工作流编排专家负责将用户需求按照标准阶段分配到对应工作流Agent执行。

View File

@ -1,7 +1,7 @@
import { EXIT_PLAN_MODE_TOOL_NAME } from 'src/tools/ExitPlanModeTool/constants.js'
import { NOTEBOOK_EDIT_TOOL_NAME } from 'src/tools/NotebookEditTool/constants.js'
import { AGENT_TOOL_NAME } from '../../tools/AgentTool/constants.js'
import type { BuiltInAgentDefinition } from '../../tools/AgentTool/loadAgentsDir.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/ExitPlanModeTool/constants.js'
import { NOTEBOOK_EDIT_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/NotebookEditTool/constants.js'
import { AGENT_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/AgentTool/constants.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getSubCodingSystemPrompt(): string {
return `你是SubCodingAgent一名专业软件开发团队中的开发人员。

View File

@ -1,7 +1,7 @@
import { EXIT_PLAN_MODE_TOOL_NAME } from 'src/tools/ExitPlanModeTool/constants.js'
import { NOTEBOOK_EDIT_TOOL_NAME } from 'src/tools/NotebookEditTool/constants.js'
import { AGENT_TOOL_NAME } from '../../tools/AgentTool/constants.js'
import type { BuiltInAgentDefinition } from '../../tools/AgentTool/loadAgentsDir.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/ExitPlanModeTool/constants.js'
import { NOTEBOOK_EDIT_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/NotebookEditTool/constants.js'
import { AGENT_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/AgentTool/constants.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getTaskCheckSystemPrompt(): string {
return `你是 TaskCheckAgent一名专业的软件开发任务质量检查与修复专家。

View File

@ -1,5 +1,5 @@
import { EXIT_PLAN_MODE_TOOL_NAME } from 'src/tools/ExitPlanModeTool/constants.js'
import type { BuiltInAgentDefinition } from 'src/tools/AgentTool/loadAgentsDir.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/ExitPlanModeTool/constants.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getTaskPlanSystemPrompt(): string {
return `# 核心职责

View File

@ -1,5 +1,5 @@
import { AGENT_TOOL_NAME } from '../../tools/AgentTool/constants.js'
import type { BuiltInAgentDefinition } from '../../tools/AgentTool/loadAgentsDir.js'
import { AGENT_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/AgentTool/constants.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getTddRunAndFixSystemPrompt(): string {
return `<role>你是 RunAndFixAgent一名可运行性验证与代码修复专家擅长诊断和解决编译构建问题。</role>

View File

@ -1,4 +1,4 @@
import type { BuiltInAgentDefinition } from '../../tools/AgentTool/loadAgentsDir.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getTddTestAndFixSystemPrompt(): string {
return `<role>你是 TestAndFixAgent一名测试执行与自动修复专家擅长诊断和解决测试失败问题。</role>

View File

@ -1,5 +1,5 @@
import { BASH_TOOL_NAME } from '../../tools/BashTool/toolName.js'
import type { BuiltInAgentDefinition } from '../../tools/AgentTool/loadAgentsDir.js'
import { BASH_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/BashTool/toolName.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getTddTestDesignSystemPrompt(): string {
return `<role>你是 TestDesignAgent一名测试点设计与测试用例规划专家精通测试自动化。</role>

View File

@ -1,6 +1,6 @@
import { AGENT_TOOL_NAME } from '../../tools/AgentTool/constants.js'
import { BASH_TOOL_NAME } from '../../tools/BashTool/toolName.js'
import type { BuiltInAgentDefinition } from '../../tools/AgentTool/loadAgentsDir.js'
import { AGENT_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/AgentTool/constants.js'
import { BASH_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/BashTool/toolName.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getTddTestPrepareSystemPrompt(): string {
return `<role>你是 TestPrepareAgent一名测试配置检查与文档准备专家专注于项目的测试执行和管理方法识别。</role>

View File

@ -1,9 +1,9 @@
import { AGENT_TOOL_NAME } from '../../tools/AgentTool/constants.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '../../tools/ExitPlanModeTool/constants.js'
import { NOTEBOOK_EDIT_TOOL_NAME } from '../../tools/NotebookEditTool/constants.js'
import { SKILL_TOOL_NAME } from '../../tools/SkillTool/constants.js'
import { WEB_FETCH_TOOL_NAME } from '../../tools/WebFetchTool/prompt.js'
import type { BuiltInAgentDefinition } from '../../tools/AgentTool/loadAgentsDir.js'
import { AGENT_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/AgentTool/constants.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/ExitPlanModeTool/constants.js'
import { NOTEBOOK_EDIT_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/NotebookEditTool/constants.js'
import { SKILL_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/SkillTool/constants.js'
import { WEB_FETCH_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/WebFetchTool/prompt.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getWikiCatalogueDesignSystemPrompt(): string {
return `# 技术文档结构设计

View File

@ -1,9 +1,9 @@
import { AGENT_TOOL_NAME } from '../../tools/AgentTool/constants.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '../../tools/ExitPlanModeTool/constants.js'
import { NOTEBOOK_EDIT_TOOL_NAME } from '../../tools/NotebookEditTool/constants.js'
import { SKILL_TOOL_NAME } from '../../tools/SkillTool/constants.js'
import { WEB_FETCH_TOOL_NAME } from '../../tools/WebFetchTool/prompt.js'
import type { BuiltInAgentDefinition } from '../../tools/AgentTool/loadAgentsDir.js'
import { AGENT_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/AgentTool/constants.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/ExitPlanModeTool/constants.js'
import { NOTEBOOK_EDIT_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/NotebookEditTool/constants.js'
import { SKILL_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/SkillTool/constants.js'
import { WEB_FETCH_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/WebFetchTool/prompt.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getWikiDocumentGenerateSystemPrompt(): string {
return `# 技术文档生成

View File

@ -1,9 +1,9 @@
import { AGENT_TOOL_NAME } from '../../tools/AgentTool/constants.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '../../tools/ExitPlanModeTool/constants.js'
import { NOTEBOOK_EDIT_TOOL_NAME } from '../../tools/NotebookEditTool/constants.js'
import { SKILL_TOOL_NAME } from '../../tools/SkillTool/constants.js'
import { WEB_FETCH_TOOL_NAME } from '../../tools/WebFetchTool/prompt.js'
import type { BuiltInAgentDefinition } from '../../tools/AgentTool/loadAgentsDir.js'
import { AGENT_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/AgentTool/constants.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/ExitPlanModeTool/constants.js'
import { NOTEBOOK_EDIT_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/NotebookEditTool/constants.js'
import { SKILL_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/SkillTool/constants.js'
import { WEB_FETCH_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/WebFetchTool/prompt.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getWikiIndexGenerationSystemPrompt(): string {
return `# 索引文档生成

View File

@ -1,9 +1,9 @@
import { AGENT_TOOL_NAME } from '../../tools/AgentTool/constants.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '../../tools/ExitPlanModeTool/constants.js'
import { NOTEBOOK_EDIT_TOOL_NAME } from '../../tools/NotebookEditTool/constants.js'
import { SKILL_TOOL_NAME } from '../../tools/SkillTool/constants.js'
import { WEB_FETCH_TOOL_NAME } from '../../tools/WebFetchTool/prompt.js'
import type { BuiltInAgentDefinition } from '../../tools/AgentTool/loadAgentsDir.js'
import { AGENT_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/AgentTool/constants.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/ExitPlanModeTool/constants.js'
import { NOTEBOOK_EDIT_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/NotebookEditTool/constants.js'
import { SKILL_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/SkillTool/constants.js'
import { WEB_FETCH_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/WebFetchTool/prompt.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getWikiProjectAnalyzeSystemPrompt(): string {
return `# 项目基本分析

View File

@ -1,6 +1,6 @@
import { EXIT_PLAN_MODE_TOOL_NAME } from 'src/tools/ExitPlanModeTool/constants.js'
import { NOTEBOOK_EDIT_TOOL_NAME } from 'src/tools/NotebookEditTool/constants.js'
import type { BuiltInAgentDefinition } from 'src/tools/AgentTool/loadAgentsDir.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/ExitPlanModeTool/constants.js'
import { NOTEBOOK_EDIT_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/NotebookEditTool/constants.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getPlanApplySystemPrompt(): string {
return `你是 CodingAgent软件开发团队的项目管理者和技术架构师。

View File

@ -1,6 +1,6 @@
import { EXIT_PLAN_MODE_TOOL_NAME } from 'src/tools/ExitPlanModeTool/constants.js'
import { NOTEBOOK_EDIT_TOOL_NAME } from 'src/tools/NotebookEditTool/constants.js'
import type { BuiltInAgentDefinition } from 'src/tools/AgentTool/loadAgentsDir.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/ExitPlanModeTool/constants.js'
import { NOTEBOOK_EDIT_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/NotebookEditTool/constants.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getReviewAndFixSystemPrompt(): string {
return `你是ReviewAndFix Agent一名专业软件开发团队中的代码审查与修复专家。

View File

@ -1,4 +1,5 @@
import type { BuiltInAgentDefinition } from 'src/tools/AgentTool/loadAgentsDir.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/ExitPlanModeTool/constants.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getSpecPlanSystemPrompt(): string {
return `你是 SpecPlan软件开发团队的全流程实施协调者。

View File

@ -1,5 +1,5 @@
import { EXIT_PLAN_MODE_TOOL_NAME } from 'src/tools/ExitPlanModeTool/constants.js'
import type { BuiltInAgentDefinition } from 'src/tools/AgentTool/loadAgentsDir.js'
import { EXIT_PLAN_MODE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/ExitPlanModeTool/constants.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getStrictPlanSystemPrompt(): string {

View File

@ -1,4 +1,4 @@
import type { BuiltInAgentDefinition } from 'src/tools/AgentTool/loadAgentsDir.js'
import type { BuiltInAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
function getTddSystemPrompt(): string {
return `<role>你是 TestDrivenDevelopment Agent负责执行全面的测试工作流程以确保代码质量。</role>

View File

@ -19,7 +19,9 @@ import { createRequire } from 'module'
function getVersion(): string {
try {
if (typeof MACRO !== 'undefined' && MACRO.VERSION) return MACRO.VERSION
} catch { /* ignore */ }
} catch {
/* ignore */
}
try {
const require = createRequire(import.meta.url)
// eslint-disable-next-line @typescript-eslint/no-require-imports
@ -41,8 +43,11 @@ const VERSION = getVersion()
* 3. Authorization CoStrict headers
* 4. 401
*/
export function createCoStrictFetch(): typeof fetch {
return async (input: RequestInfo | URL, init?: RequestInit) => {
export function createCoStrictFetch() {
const costrictFetch = async (
input: RequestInfo | URL,
init?: RequestInit,
) => {
// ========== 步骤 1: 动态读取凭证 ==========
let creds = await loadCoStrictCredentials()
@ -119,4 +124,6 @@ export function createCoStrictFetch(): typeof fetch {
return response
}
costrictFetch.preconnect = fetch.preconnect.bind(fetch)
return costrictFetch
}

View File

@ -4,6 +4,7 @@
*/
import type { BetaToolUnion } from '@anthropic-ai/sdk/resources/beta/messages/messages.mjs'
import type { SDKAssistantMessageError } from '../../entrypoints/agentSdkTypes.js'
import type { SystemPrompt } from '../../utils/systemPromptType.js'
import type {
Message,
@ -46,7 +47,10 @@ export async function* queryModelCoStrict(
tools: Tools,
signal: AbortSignal,
options: Options,
): AsyncGenerator<StreamEvent | AssistantMessage | SystemAPIErrorMessage, void> {
): AsyncGenerator<
StreamEvent | AssistantMessage | SystemAPIErrorMessage,
void
> {
try {
// 1. 解析模型名
const costrictModel = resolveCoStrictModel(options.model)
@ -73,7 +77,7 @@ export async function* queryModelCoStrict(
)
const standardTools = toolSchemas.filter(
(t): t is BetaToolUnion & { type: string } => {
const anyT = t as Record<string, unknown>
const anyT = t as unknown as Record<string, unknown>
return (
anyT.type !== 'advisor_20260301' && anyT.type !== 'computer_20250124'
)
@ -81,7 +85,11 @@ export async function* queryModelCoStrict(
)
// 5. 转换为 OpenAI 格式
const openaiMessages = anthropicMessagesToOpenAI(messagesForAPI, systemPrompt, { enableThinking: true })
const openaiMessages = anthropicMessagesToOpenAI(
messagesForAPI,
systemPrompt,
{ enableThinking: true },
)
const openaiTools = anthropicToolsToOpenAI(standardTools)
const openaiToolChoice = anthropicToolChoiceToOpenAI(options.toolChoice)
@ -93,7 +101,9 @@ export async function* queryModelCoStrict(
maxRetries: 0,
timeout: parseInt(process.env.API_TIMEOUT_MS || String(600 * 1000), 10),
dangerouslyAllowBrowser: true,
fetchOptions: getProxyFetchOptions({ forAnthropicAPI: false }) as RequestInit,
fetchOptions: getProxyFetchOptions({
forAnthropicAPI: false,
}) as any,
fetch: costrictFetch as any,
})
@ -108,7 +118,10 @@ export async function* queryModelCoStrict(
messages: openaiMessages,
...(openaiTools.length > 0 && {
tools: openaiTools,
...(openaiToolChoice && { tool_choice: openaiToolChoice }),
...(openaiToolChoice && {
tool_choice:
openaiToolChoice as OpenAI.Chat.Completions.ChatCompletionToolChoiceOption,
}),
}),
stream: true,
stream_options: { include_usage: true },
@ -123,7 +136,7 @@ export async function* queryModelCoStrict(
const adaptedStream = adaptOpenAIStreamToAnthropic(stream, costrictModel)
const contentBlocks: Record<number, any> = {}
let partialMessage: any = undefined
let partialMessage: any
let usage = {
input_tokens: 0,
output_tokens: 0,
@ -139,7 +152,7 @@ export async function* queryModelCoStrict(
partialMessage = (event as any).message
ttftMs = Date.now() - start
if ((event as any).message?.usage) {
usage = { ...usage, ...((event as any).message.usage) }
usage = { ...usage, ...(event as any).message.usage }
}
break
}
@ -219,7 +232,10 @@ export async function* queryModelCoStrict(
yield createAssistantAPIErrorMessage({
content: `CoStrict API Error: ${errorMsg}`,
apiError: 'api_error',
error: error instanceof Error ? error : new Error(String(error)),
error:
error instanceof Error
? (error as unknown as SDKAssistantMessageError)
: undefined,
})
}
}

View File

@ -1,4 +1,4 @@
import { registerBundledSkill } from '../../skills/bundledSkills.js'
import { registerBundledSkill } from 'src/skills/bundledSkills.js'
import { BUNDLED_SKILLS } from './builtin.js'
export function registerCodeReviewSecuritySkill(): void {

View File

@ -1,5 +1,5 @@
import { getProjectRoot } from '../../bootstrap/state.js'
import { registerBundledSkill } from '../../skills/bundledSkills.js'
import { registerBundledSkill } from 'src/skills/bundledSkills.js'
// Orchestrator prompt for the /project-wiki skill.
// Uses `Agent` tool (CSC equivalent of opencode's `task` tool) to delegate

View File

@ -1,4 +1,4 @@
import { registerBundledSkill } from '../../skills/bundledSkills.js'
import { registerBundledSkill } from 'src/skills/bundledSkills.js'
export function registerStrictPlanSkill(): void {
registerBundledSkill({

View File

@ -1,4 +1,4 @@
import { registerBundledSkill } from '../../skills/bundledSkills.js'
import { registerBundledSkill } from 'src/skills/bundledSkills.js'
const TDD_PROMPT = `You are executing a comprehensive testing workflow to ensure code quality.

View File

@ -27,6 +27,8 @@ import { getModelBetas, modelSupportsStructuredOutputs } from './betas.js'
import { computeFingerprint } from './fingerprint.js'
import { normalizeModelStringForAPI } from './model/model.js'
import { getAPIProvider } from './model/providers.js'
import { asSystemPrompt } from './systemPromptType.js'
import type { UserMessage, AssistantMessage } from '../types/message.js'
type MessageParam = Anthropic.MessageParam
type TextBlockParam = Anthropic.TextBlockParam
@ -257,7 +259,9 @@ async function sideQueryCoStrict(opts: SideQueryOptions): Promise<BetaMessage> {
// Build system prompt
const systemContent = skipSystemPromptPrefix
? (typeof system === 'string' ? system : '')
? typeof system === 'string'
? system
: ''
: `${getCLISyspromptPrefix({ isNonInteractive: false, hasAppendSystemPrompt: false })}
${typeof system === 'string' ? system : ''}`
@ -275,18 +279,15 @@ ${typeof system === 'string' ? system : ''}`
maxRetries: 0,
timeout: parseInt(process.env.API_TIMEOUT_MS || String(600 * 1000), 10),
dangerouslyAllowBrowser: true,
fetchOptions: getProxyFetchOptions({ forAnthropicAPI: false }) as RequestInit,
fetchOptions: getProxyFetchOptions({ forAnthropicAPI: false }) as any,
fetch: costrictFetch as any,
})
// Convert messages to OpenAI format
const openaiMessages = anthropicMessagesToOpenAI(
messages.map(m => ({
...m,
content: typeof m.content === 'string' ? m.content : m.content,
})),
systemContent,
{ enableThinking: false }
messages as unknown as (UserMessage | AssistantMessage)[],
asSystemPrompt([systemContent]),
{ enableThinking: false },
)
// Build request
@ -299,7 +300,7 @@ ${typeof system === 'string' ? system : ''}`
// Add response_format for JSON schema if specified
if (output_format?.type === 'json_schema') {
(requestBody as any).response_format = {
;(requestBody as any).response_format = {
type: 'json_schema',
json_schema: {
name: 'response',
@ -333,15 +334,19 @@ ${typeof system === 'string' ? system : ''}`
const now = Date.now()
const lastCompletion = getLastApiCompletionTimestamp()
logEvent('tengu_api_success', {
requestId: response.id as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
querySource: opts.querySource as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
model: costrictModel as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
requestId:
response.id as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
querySource:
opts.querySource as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
model:
costrictModel as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
inputTokens: response.usage?.prompt_tokens || 0,
outputTokens: response.usage?.completion_tokens || 0,
cachedInputTokens: 0,
uncachedInputTokens: 0,
durationMsIncludingRetries: now - start,
timeSinceLastApiCallMs: lastCompletion !== null ? now - lastCompletion : undefined,
timeSinceLastApiCallMs:
lastCompletion !== null ? now - lastCompletion : undefined,
})
setLastApiCompletionTimestamp(now)
@ -365,7 +370,9 @@ async function sideQueryOpenAI(opts: SideQueryOptions): Promise<BetaMessage> {
// Build system prompt
const systemContent = skipSystemPromptPrefix
? (typeof system === 'string' ? system : '')
? typeof system === 'string'
? system
: ''
: `${getCLISyspromptPrefix({ isNonInteractive: false, hasAppendSystemPrompt: false })}
${typeof system === 'string' ? system : ''}`
@ -377,12 +384,9 @@ ${typeof system === 'string' ? system : ''}`
// Convert messages to OpenAI format
const openaiMessages = anthropicMessagesToOpenAI(
messages.map(m => ({
...m,
content: typeof m.content === 'string' ? m.content : m.content,
})),
systemContent,
{ enableThinking: false }
messages as unknown as (UserMessage | AssistantMessage)[],
asSystemPrompt([systemContent]),
{ enableThinking: false },
)
// Build request
@ -395,7 +399,7 @@ ${typeof system === 'string' ? system : ''}`
// Add response_format for JSON schema if specified
if (output_format?.type === 'json_schema') {
(requestBody as any).response_format = {
;(requestBody as any).response_format = {
type: 'json_schema',
json_schema: {
name: 'response',
@ -429,15 +433,19 @@ ${typeof system === 'string' ? system : ''}`
const now = Date.now()
const lastCompletion = getLastApiCompletionTimestamp()
logEvent('tengu_api_success', {
requestId: response.id as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
querySource: opts.querySource as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
model: openaiModel as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
requestId:
response.id as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
querySource:
opts.querySource as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
model:
openaiModel as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
inputTokens: response.usage?.prompt_tokens || 0,
outputTokens: response.usage?.completion_tokens || 0,
cachedInputTokens: 0,
uncachedInputTokens: 0,
durationMsIncludingRetries: now - start,
timeSinceLastApiCallMs: lastCompletion !== null ? now - lastCompletion : undefined,
timeSinceLastApiCallMs:
lastCompletion !== null ? now - lastCompletion : undefined,
})
setLastApiCompletionTimestamp(now)

View File

@ -1,69 +1,46 @@
import chalk from 'chalk'
import figures from 'figures'
import * as React from 'react'
import { color, Text } from '@anthropic/ink'
import type { MCPServerConnection } from '../services/mcp/types.js'
import { getAccountInformation, isClaudeAISubscriber } from './auth.js'
import {
getLargeMemoryFiles,
getMemoryFiles,
MAX_MEMORY_CHARACTER_COUNT,
} from './claudemd.js'
import { getDoctorDiagnostic } from './doctorDiagnostic.js'
import {
getAWSRegion,
getDefaultVertexRegion,
isEnvTruthy,
} from './envUtils.js'
import { getDisplayPath } from './file.js'
import { formatNumber } from './format.js'
import {
getIdeClientName,
type IDEExtensionInstallationStatus,
isJetBrainsIde,
toIDEDisplayName,
} from './ide.js'
import {
getClaudeAiUserDefaultModelDescription,
modelDisplayString,
} from './model/model.js'
import { getAPIProvider } from './model/providers.js'
import { getMTLSConfig } from './mtls.js'
import { checkInstall } from './nativeInstaller/index.js'
import { getProxyUrl } from './proxy.js'
import { SandboxManager } from './sandbox/sandbox-adapter.js'
import { getSettingsWithAllErrors } from './settings/allErrors.js'
import {
getEnabledSettingSources,
getSettingSourceDisplayNameCapitalized,
} from './settings/constants.js'
import {
getManagedFileSettingsPresence,
getPolicySettingsOrigin,
getSettingsForSource,
} from './settings/settings.js'
import type { ThemeName } from './theme.js'
import chalk from 'chalk';
import figures from 'figures';
import * as React from 'react';
import { color, Text } from '@anthropic/ink';
import type { MCPServerConnection } from '../services/mcp/types.js';
import { getAccountInformation, isClaudeAISubscriber } from './auth.js';
import { getLargeMemoryFiles, getMemoryFiles, MAX_MEMORY_CHARACTER_COUNT } from './claudemd.js';
import { getDoctorDiagnostic } from './doctorDiagnostic.js';
import { getAWSRegion, getDefaultVertexRegion, isEnvTruthy } from './envUtils.js';
import { getDisplayPath } from './file.js';
import { formatNumber } from './format.js';
import { getIdeClientName, type IDEExtensionInstallationStatus, isJetBrainsIde, toIDEDisplayName } from './ide.js';
import { getClaudeAiUserDefaultModelDescription, modelDisplayString } from './model/model.js';
import { getAPIProvider } from './model/providers.js';
import { getMTLSConfig } from './mtls.js';
import { checkInstall } from './nativeInstaller/index.js';
import { getProxyUrl } from './proxy.js';
import { SandboxManager } from './sandbox/sandbox-adapter.js';
import { getSettingsWithAllErrors } from './settings/allErrors.js';
import { getEnabledSettingSources, getSettingSourceDisplayNameCapitalized } from './settings/constants.js';
import { getManagedFileSettingsPresence, getPolicySettingsOrigin, getSettingsForSource } from './settings/settings.js';
import type { ThemeName } from './theme.js';
export type Property = {
label?: string
value: React.ReactNode | Array<string>
}
label?: string;
value: React.ReactNode | Array<string>;
};
export type Diagnostic = React.ReactNode
export type Diagnostic = React.ReactNode;
export function buildSandboxProperties(): Property[] {
if (process.env.USER_TYPE !== 'ant') {
return []
return [];
}
const isSandboxed = SandboxManager.isSandboxingEnabled()
const isSandboxed = SandboxManager.isSandboxingEnabled();
return [
{
label: 'Bash Sandbox',
value: isSandboxed ? 'Enabled' : 'Disabled',
},
]
];
}
export function buildIDEProperties(
@ -71,13 +48,11 @@ export function buildIDEProperties(
ideInstallationStatus: IDEExtensionInstallationStatus | null = null,
theme: ThemeName,
): Property[] {
const ideClient = mcpClients?.find(client => client.name === 'ide')
const ideClient = mcpClients?.find(client => client.name === 'ide');
if (ideInstallationStatus) {
const ideName = toIDEDisplayName(ideInstallationStatus.ideType)
const pluginOrExtension = isJetBrainsIde(ideInstallationStatus.ideType)
? 'plugin'
: 'extension'
const ideName = toIDEDisplayName(ideInstallationStatus.ideType);
const pluginOrExtension = isJetBrainsIde(ideInstallationStatus.ideType) ? 'plugin' : 'extension';
if (ideInstallationStatus.error) {
return [
@ -85,34 +60,31 @@ export function buildIDEProperties(
label: 'IDE',
value: (
<Text>
{color('error', theme)(figures.cross)} Error installing {ideName}{' '}
{pluginOrExtension}: {ideInstallationStatus.error}
{color('error', theme)(figures.cross)} Error installing {ideName} {pluginOrExtension}:{' '}
{ideInstallationStatus.error}
{'\n'}Please restart your IDE and try again.
</Text>
),
},
]
];
}
if (ideInstallationStatus.installed) {
if (ideClient && ideClient.type === 'connected') {
if (
ideInstallationStatus.installedVersion !==
ideClient.serverInfo?.version
) {
if (ideInstallationStatus.installedVersion !== ideClient.serverInfo?.version) {
return [
{
label: 'IDE',
value: `Connected to ${ideName} ${pluginOrExtension} version ${ideInstallationStatus.installedVersion} (server version: ${ideClient.serverInfo?.version})`,
},
]
];
} else {
return [
{
label: 'IDE',
value: `Connected to ${ideName} ${pluginOrExtension} version ${ideInstallationStatus.installedVersion}`,
},
]
];
}
} else {
return [
@ -120,196 +92,183 @@ export function buildIDEProperties(
label: 'IDE',
value: `Installed ${ideName} ${pluginOrExtension}`,
},
]
];
}
}
} else if (ideClient) {
const ideName = getIdeClientName(ideClient) ?? 'IDE'
const ideName = getIdeClientName(ideClient) ?? 'IDE';
if (ideClient.type === 'connected') {
return [
{
label: 'IDE',
value: `Connected to ${ideName} extension`,
},
]
];
} else {
return [
{
label: 'IDE',
value: `${color('error', theme)(figures.cross)} Not connected to ${ideName}`,
},
]
];
}
}
return []
return [];
}
export function buildMcpProperties(
clients: MCPServerConnection[] = [],
theme: ThemeName,
): Property[] {
const servers = clients.filter(client => client.name !== 'ide')
export function buildMcpProperties(clients: MCPServerConnection[] = [], theme: ThemeName): Property[] {
const servers = clients.filter(client => client.name !== 'ide');
if (!servers.length) {
return []
return [];
}
// Summary instead of a full server list — 20+ servers wrapped onto many
// rows, dominating the Status pane. Show counts by state + /mcp hint.
const byState = { connected: 0, pending: 0, needsAuth: 0, failed: 0 }
const byState = { connected: 0, pending: 0, needsAuth: 0, failed: 0 };
for (const s of servers) {
if (s.type === 'connected') byState.connected++
else if (s.type === 'pending') byState.pending++
else if (s.type === 'needs-auth') byState.needsAuth++
else byState.failed++
if (s.type === 'connected') byState.connected++;
else if (s.type === 'pending') byState.pending++;
else if (s.type === 'needs-auth') byState.needsAuth++;
else byState.failed++;
}
const parts: string[] = []
if (byState.connected)
parts.push(color('success', theme)(`${byState.connected} connected`))
if (byState.needsAuth)
parts.push(color('warning', theme)(`${byState.needsAuth} need auth`))
if (byState.pending)
parts.push(color('inactive', theme)(`${byState.pending} pending`))
if (byState.failed)
parts.push(color('error', theme)(`${byState.failed} failed`))
const parts: string[] = [];
if (byState.connected) parts.push(color('success', theme)(`${byState.connected} connected`));
if (byState.needsAuth) parts.push(color('warning', theme)(`${byState.needsAuth} need auth`));
if (byState.pending) parts.push(color('inactive', theme)(`${byState.pending} pending`));
if (byState.failed) parts.push(color('error', theme)(`${byState.failed} failed`));
return [
{
label: 'MCP servers',
value: `${parts.join(', ')} ${color('inactive', theme)('· /mcp')}`,
},
]
];
}
export async function buildMemoryDiagnostics(): Promise<Diagnostic[]> {
const files = await getMemoryFiles()
const largeFiles = getLargeMemoryFiles(files)
const files = await getMemoryFiles();
const largeFiles = getLargeMemoryFiles(files);
const diagnostics: Diagnostic[] = []
const diagnostics: Diagnostic[] = [];
largeFiles.forEach(file => {
const displayPath = getDisplayPath(file.path)
const displayPath = getDisplayPath(file.path);
diagnostics.push(
`Large ${displayPath} will impact performance (${formatNumber(file.content.length)} chars > ${formatNumber(MAX_MEMORY_CHARACTER_COUNT)})`,
)
})
);
});
return diagnostics
return diagnostics;
}
export function buildSettingSourcesProperties(): Property[] {
const enabledSources = getEnabledSettingSources()
const enabledSources = getEnabledSettingSources();
// Filter to only sources that actually have settings loaded
const sourcesWithSettings = enabledSources.filter(source => {
const settings = getSettingsForSource(source)
return settings !== null && Object.keys(settings).length > 0
})
const settings = getSettingsForSource(source);
return settings !== null && Object.keys(settings).length > 0;
});
// Map internal names to user-friendly names
// For policySettings, distinguish between remote and local (or skip if neither exists)
const sourceNames = sourcesWithSettings
.map(source => {
if (source === 'policySettings') {
const origin = getPolicySettingsOrigin()
const origin = getPolicySettingsOrigin();
if (origin === null) {
return null // Skip - no policy settings exist
return null; // Skip - no policy settings exist
}
switch (origin) {
case 'remote':
return 'Enterprise managed settings (remote)'
return 'Enterprise managed settings (remote)';
case 'plist':
return 'Enterprise managed settings (plist)'
return 'Enterprise managed settings (plist)';
case 'hklm':
return 'Enterprise managed settings (HKLM)'
return 'Enterprise managed settings (HKLM)';
case 'file': {
const { hasBase, hasDropIns } = getManagedFileSettingsPresence()
const { hasBase, hasDropIns } = getManagedFileSettingsPresence();
if (hasBase && hasDropIns) {
return 'Enterprise managed settings (file + drop-ins)'
return 'Enterprise managed settings (file + drop-ins)';
}
if (hasDropIns) {
return 'Enterprise managed settings (drop-ins)'
return 'Enterprise managed settings (drop-ins)';
}
return 'Enterprise managed settings (file)'
return 'Enterprise managed settings (file)';
}
case 'hkcu':
return 'Enterprise managed settings (HKCU)'
return 'Enterprise managed settings (HKCU)';
}
}
return getSettingSourceDisplayNameCapitalized(source)
return getSettingSourceDisplayNameCapitalized(source);
})
.filter((name): name is string => name !== null)
.filter((name): name is string => name !== null);
return [
{
label: 'Setting sources',
value: sourceNames,
},
]
];
}
export async function buildInstallationDiagnostics(): Promise<Diagnostic[]> {
const installWarnings = await checkInstall()
return installWarnings.map(warning => warning.message)
const installWarnings = await checkInstall();
return installWarnings.map(warning => warning.message);
}
export async function buildInstallationHealthDiagnostics(): Promise<
Diagnostic[]
> {
const diagnostic = await getDoctorDiagnostic()
const items: Diagnostic[] = []
export async function buildInstallationHealthDiagnostics(): Promise<Diagnostic[]> {
const diagnostic = await getDoctorDiagnostic();
const items: Diagnostic[] = [];
const { errors: validationErrors } = getSettingsWithAllErrors()
const { errors: validationErrors } = getSettingsWithAllErrors();
if (validationErrors.length > 0) {
const invalidFiles = Array.from(
new Set(validationErrors.map(error => error.file)),
)
const fileList = invalidFiles.join(', ')
const invalidFiles = Array.from(new Set(validationErrors.map(error => error.file)));
const fileList = invalidFiles.join(', ');
items.push(
`Found invalid settings files: ${fileList}. They will be ignored.`,
)
items.push(`Found invalid settings files: ${fileList}. They will be ignored.`);
}
// Add warnings from doctor diagnostic (includes leftover installations, config mismatches, etc.)
diagnostic.warnings.forEach(warning => {
items.push(warning.issue)
})
items.push(warning.issue);
});
if (diagnostic.hasUpdatePermissions === false) {
items.push('No write permissions for auto-updates (requires sudo)')
items.push('No write permissions for auto-updates (requires sudo)');
}
return items
return items;
}
export function buildAccountProperties(): Property[] {
const accountInfo = getAccountInformation()
const accountInfo = getAccountInformation();
if (!accountInfo) {
return []
return [];
}
const properties: Property[] = []
const properties: Property[] = [];
if (accountInfo.subscription) {
properties.push({
label: 'Login method',
value: `${accountInfo.subscription} Account`,
})
});
}
if (accountInfo.tokenSource) {
properties.push({
label: 'Auth token',
value: accountInfo.tokenSource,
})
});
}
if (accountInfo.apiKeySource) {
properties.push({
label: 'API key',
value: accountInfo.apiKeySource,
})
});
}
// Hide sensitive account info in demo mode
@ -317,22 +276,22 @@ export function buildAccountProperties(): Property[] {
properties.push({
label: 'Organization',
value: accountInfo.organization,
})
});
}
if (accountInfo.email && !process.env.IS_DEMO) {
properties.push({
label: 'Email',
value: accountInfo.email,
})
});
}
return properties
return properties;
}
export function buildAPIProviderProperties(): Property[] {
const apiProvider = getAPIProvider()
const apiProvider = getAPIProvider();
const properties: Property[] = []
const properties: Property[] = [];
if (apiProvider !== 'firstParty') {
const providerLabel = {
@ -342,152 +301,152 @@ export function buildAPIProviderProperties(): Property[] {
gemini: 'Gemini API',
grok: 'Grok API',
openai: 'OpenAI API',
}[apiProvider]
costrict: 'CoStrict API',
}[apiProvider];
properties.push({
label: 'API provider',
value: providerLabel,
})
});
}
if (apiProvider === 'firstParty') {
const anthropicBaseUrl = process.env.ANTHROPIC_BASE_URL
const anthropicBaseUrl = process.env.ANTHROPIC_BASE_URL;
if (anthropicBaseUrl) {
properties.push({
label: 'Anthropic base URL',
value: anthropicBaseUrl,
})
});
}
} else if (apiProvider === 'bedrock') {
const bedrockBaseUrl = process.env.BEDROCK_BASE_URL
const bedrockBaseUrl = process.env.BEDROCK_BASE_URL;
if (bedrockBaseUrl) {
properties.push({
label: 'Bedrock base URL',
value: bedrockBaseUrl,
})
});
}
properties.push({
label: 'AWS region',
value: getAWSRegion(),
})
});
if (isEnvTruthy(process.env.CLAUDE_CODE_SKIP_BEDROCK_AUTH)) {
properties.push({
value: 'AWS auth skipped',
})
});
}
} else if (apiProvider === 'vertex') {
const vertexBaseUrl = process.env.VERTEX_BASE_URL
const vertexBaseUrl = process.env.VERTEX_BASE_URL;
if (vertexBaseUrl) {
properties.push({
label: 'Vertex base URL',
value: vertexBaseUrl,
})
});
}
const gcpProject = process.env.ANTHROPIC_VERTEX_PROJECT_ID
const gcpProject = process.env.ANTHROPIC_VERTEX_PROJECT_ID;
if (gcpProject) {
properties.push({
label: 'GCP project',
value: gcpProject,
})
});
}
properties.push({
label: 'Default region',
value: getDefaultVertexRegion(),
})
});
if (isEnvTruthy(process.env.CLAUDE_CODE_SKIP_VERTEX_AUTH)) {
properties.push({
value: 'GCP auth skipped',
})
});
}
} else if (apiProvider === 'foundry') {
const foundryBaseUrl = process.env.ANTHROPIC_FOUNDRY_BASE_URL
const foundryBaseUrl = process.env.ANTHROPIC_FOUNDRY_BASE_URL;
if (foundryBaseUrl) {
properties.push({
label: 'Microsoft Foundry base URL',
value: foundryBaseUrl,
})
});
}
const foundryResource = process.env.ANTHROPIC_FOUNDRY_RESOURCE
const foundryResource = process.env.ANTHROPIC_FOUNDRY_RESOURCE;
if (foundryResource) {
properties.push({
label: 'Microsoft Foundry resource',
value: foundryResource,
})
});
}
if (isEnvTruthy(process.env.CLAUDE_CODE_SKIP_FOUNDRY_AUTH)) {
properties.push({
value: 'Microsoft Foundry auth skipped',
})
});
}
} else if (apiProvider === 'gemini') {
const geminiBaseUrl =
process.env.GEMINI_BASE_URL || 'https://generativelanguage.googleapis.com/v1beta'
const geminiBaseUrl = process.env.GEMINI_BASE_URL || 'https://generativelanguage.googleapis.com/v1beta';
properties.push({
label: 'Gemini base URL',
value: geminiBaseUrl,
})
});
} else if (apiProvider === 'grok') {
const grokBaseUrl = process.env.GROK_BASE_URL
const grokBaseUrl = process.env.GROK_BASE_URL;
properties.push({
label: 'Grok base URL',
value: grokBaseUrl,
})
});
} else if (apiProvider === 'openai') {
const openaiBaseUrl = process.env.OPENAI_BASE_URL
const openaiBaseUrl = process.env.OPENAI_BASE_URL;
properties.push({
label: 'OpenAI base URL',
value: openaiBaseUrl,
})
});
}
const proxyUrl = getProxyUrl()
const proxyUrl = getProxyUrl();
if (proxyUrl) {
properties.push({
label: 'Proxy',
value: proxyUrl,
})
});
}
const mtlsConfig = getMTLSConfig()
const mtlsConfig = getMTLSConfig();
if (process.env.NODE_EXTRA_CA_CERTS) {
properties.push({
label: 'Additional CA cert(s)',
value: process.env.NODE_EXTRA_CA_CERTS,
})
});
}
if (mtlsConfig) {
if (mtlsConfig.cert && process.env.CLAUDE_CODE_CLIENT_CERT) {
properties.push({
label: 'mTLS client cert',
value: process.env.CLAUDE_CODE_CLIENT_CERT,
})
});
}
if (mtlsConfig.key && process.env.CLAUDE_CODE_CLIENT_KEY) {
properties.push({
label: 'mTLS client key',
value: process.env.CLAUDE_CODE_CLIENT_KEY,
})
});
}
}
return properties
return properties;
}
export function getModelDisplayLabel(mainLoopModel: string | null): string {
let modelLabel = modelDisplayString(mainLoopModel)
let modelLabel = modelDisplayString(mainLoopModel);
if (mainLoopModel === null && isClaudeAISubscriber()) {
const description = getClaudeAiUserDefaultModelDescription()
const description = getClaudeAiUserDefaultModelDescription();
modelLabel = `${chalk.bold('Default')} ${description}`
modelLabel = `${chalk.bold('Default')} ${description}`;
}
return modelLabel
return modelLabel;
}