瀏覽代碼

feat: reconstruct bun cli build

paoloanzn 2 月之前
父節點
當前提交
e878a7ce35
共有 39 個文件被更改,包括 1205 次插入30 次删除
  1. 3 0
      .gitignore
  2. 21 0
      app_structure_llm.txt
  3. 136 0
      bun.lock
  4. 14 0
      env.d.ts
  5. 119 0
      package.json
  6. 96 0
      scripts/build.ts
  7. 15 0
      src/assistant/AssistantSessionChooser.tsx
  8. 22 0
      src/commands/assistant/assistant.tsx
  9. 3 3
      src/components/StructuredDiff/colorDiff.ts
  10. 17 0
      src/components/agents/SnapshotUpdateDialog.tsx
  11. 169 0
      src/entrypoints/sdk/coreTypes.generated.ts
  12. 59 0
      src/entrypoints/sdk/runtimeTypes.ts
  13. 1 0
      src/entrypoints/sdk/toolTypes.ts
  14. 1 0
      src/ink/devtools.ts
  15. 1 0
      src/ink/global.d.ts
  16. 0 0
      src/main.tsx
  17. 19 0
      src/services/compact/cachedMCConfig.ts
  18. 104 0
      src/services/compact/cachedMicrocompact.ts
  19. 39 0
      src/services/compact/snipCompact.ts
  20. 16 0
      src/services/compact/snipProjection.ts
  21. 67 0
      src/services/contextCollapse/index.ts
  22. 3 0
      src/services/contextCollapse/operations.ts
  23. 4 0
      src/services/contextCollapse/persist.ts
  24. 4 2
      src/services/mcp/client.ts
  25. 6 6
      src/skills/bundled/claudeInChrome.ts
  26. 10 8
      src/skills/bundled/verifyContent.ts
  27. 3 0
      src/tools/TungstenTool/TungstenLiveMonitor.tsx
  28. 72 0
      src/tools/TungstenTool/TungstenTool.ts
  29. 67 0
      src/tools/VerifyPlanExecutionTool/VerifyPlanExecutionTool.ts
  30. 1 0
      src/tools/VerifyPlanExecutionTool/constants.ts
  31. 1 0
      src/tools/WorkflowTool/constants.ts
  32. 22 0
      src/types/connectorText.ts
  33. 6 8
      src/utils/claudeInChrome/mcpServer.ts
  34. 32 0
      src/utils/claudeInChrome/package.ts
  35. 2 2
      src/utils/claudeInChrome/setup.ts
  36. 1 1
      src/utils/debug.ts
  37. 20 0
      src/utils/filePersistence/types.ts
  38. 6 0
      src/utils/ultraplan/prompt.txt
  39. 23 0
      tsconfig.json

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+node_modules/
+dist/
+cli

+ 21 - 0
app_structure_llm.txt

@@ -0,0 +1,21 @@
+# App Structure - Claude Code Source Snapshot
+# Last updated: 2026-03-31
+
+## Repositories
+- GitHub: https://github.com/paoloanzn/claude-code
+
+## Backend (Supabase)
+- N/A
+
+## Deployed Services (Railway)
+- N/A
+
+## Environment Variables Required
+- USER_TYPE (optional; external/public build defaults to non-ant behavior)
+- CLAUDE_CODE_ENABLE_CFC (optional)
+- CLAUDE_CODE_REMOTE (optional)
+
+## Notes
+- This repository is a reconstructed Bun CLI workspace built from a leaked TypeScript source snapshot.
+- The source build targets `src/entrypoints/cli.tsx` and emits `cli.js` via `bun run build`.
+- Anthropic-internal `@ant/*` packages are treated as optional/external. Chrome integration is lazy-loaded so the default CLI startup path does not fail when those packages are unavailable.

文件差異過大導致無法顯示
+ 136 - 0
bun.lock


+ 14 - 0
env.d.ts

@@ -0,0 +1,14 @@
+declare const MACRO: {
+  VERSION: string
+  BUILD_TIME: string
+  PACKAGE_URL?: string
+  NATIVE_PACKAGE_URL?: string
+  FEEDBACK_CHANNEL?: string
+  ISSUES_EXPLAINER?: string
+  VERSION_CHANGELOG?: string
+}
+
+declare module '*.node' {
+  const value: unknown
+  export default value
+}

+ 119 - 0
package.json

@@ -0,0 +1,119 @@
+{
+  "name": "claude-code-source-snapshot",
+  "version": "0.1.0",
+  "private": true,
+  "description": "Reconstructed Bun CLI workspace for the Claude Code source snapshot.",
+  "type": "module",
+  "packageManager": "bun@1.3.11",
+  "bin": {
+    "claude": "./cli",
+    "claude-source": "./cli"
+  },
+  "engines": {
+    "bun": ">=1.3.11"
+  },
+  "scripts": {
+    "build": "bun run ./scripts/build.ts",
+    "compile": "bun run ./scripts/build.ts --compile",
+    "dev": "bun run ./src/entrypoints/cli.tsx"
+  },
+  "dependencies": {
+    "@alcalzone/ansi-tokenize": "^0.3.0",
+    "@anthropic-ai/bedrock-sdk": "^0.26.4",
+    "@anthropic-ai/claude-agent-sdk": "^0.2.87",
+    "@anthropic-ai/foundry-sdk": "^0.2.3",
+    "@anthropic-ai/mcpb": "^2.1.2",
+    "@anthropic-ai/sandbox-runtime": "^0.0.44",
+    "@anthropic-ai/sdk": "^0.80.0",
+    "@anthropic-ai/vertex-sdk": "^0.14.4",
+    "@aws-sdk/client-bedrock": "^3.1020.0",
+    "@aws-sdk/client-bedrock-runtime": "^3.1020.0",
+    "@aws-sdk/client-sts": "^3.1020.0",
+    "@aws-sdk/credential-provider-node": "^3.972.28",
+    "@aws-sdk/credential-providers": "^3.1020.0",
+    "@azure/identity": "^4.13.1",
+    "@commander-js/extra-typings": "^14.0.0",
+    "@growthbook/growthbook": "^1.6.5",
+    "@modelcontextprotocol/sdk": "^1.29.0",
+    "@opentelemetry/api": "^1.9.1",
+    "@opentelemetry/api-logs": "^0.214.0",
+    "@opentelemetry/core": "^2.6.1",
+    "@opentelemetry/exporter-logs-otlp-grpc": "^0.214.0",
+    "@opentelemetry/exporter-logs-otlp-http": "^0.214.0",
+    "@opentelemetry/exporter-logs-otlp-proto": "^0.214.0",
+    "@opentelemetry/exporter-metrics-otlp-grpc": "^0.214.0",
+    "@opentelemetry/exporter-metrics-otlp-http": "^0.214.0",
+    "@opentelemetry/exporter-metrics-otlp-proto": "^0.214.0",
+    "@opentelemetry/exporter-prometheus": "^0.214.0",
+    "@opentelemetry/exporter-trace-otlp-grpc": "^0.214.0",
+    "@opentelemetry/exporter-trace-otlp-http": "^0.214.0",
+    "@opentelemetry/exporter-trace-otlp-proto": "^0.214.0",
+    "@opentelemetry/resources": "^2.6.1",
+    "@opentelemetry/sdk-logs": "^0.214.0",
+    "@opentelemetry/sdk-metrics": "^2.6.1",
+    "@opentelemetry/sdk-trace-base": "^2.6.1",
+    "@opentelemetry/semantic-conventions": "^1.40.0",
+    "@smithy/core": "^3.23.13",
+    "@smithy/node-http-handler": "^4.5.1",
+    "ajv": "^8.18.0",
+    "asciichart": "^1.5.25",
+    "auto-bind": "^5.0.1",
+    "axios": "^1.14.0",
+    "bidi-js": "^1.0.3",
+    "cacache": "^20.0.4",
+    "chalk": "^5.6.2",
+    "chokidar": "^5.0.0",
+    "cli-boxes": "^4.0.1",
+    "cli-highlight": "^2.1.11",
+    "code-excerpt": "^4.0.0",
+    "diff": "^8.0.4",
+    "emoji-regex": "^10.6.0",
+    "env-paths": "^4.0.0",
+    "execa": "^9.6.1",
+    "fflate": "^0.8.2",
+    "figures": "^6.1.0",
+    "fuse.js": "^7.1.0",
+    "get-east-asian-width": "^1.5.0",
+    "google-auth-library": "^10.6.2",
+    "highlight.js": "^11.11.1",
+    "https-proxy-agent": "^8.0.0",
+    "ignore": "^7.0.5",
+    "indent-string": "^5.0.0",
+    "ink": "^6.8.0",
+    "jsonc-parser": "^3.3.1",
+    "lodash-es": "^4.17.23",
+    "lru-cache": "^11.2.7",
+    "marked": "^17.0.5",
+    "p-map": "^7.0.4",
+    "picomatch": "^4.0.4",
+    "plist": "^3.1.0",
+    "proper-lockfile": "^4.1.2",
+    "qrcode": "^1.5.4",
+    "react": "^19.2.4",
+    "react-reconciler": "^0.33.0",
+    "semver": "^7.7.4",
+    "sharp": "^0.34.5",
+    "shell-quote": "^1.8.3",
+    "signal-exit": "^4.1.0",
+    "stack-utils": "^2.0.6",
+    "strip-ansi": "^7.2.0",
+    "supports-hyperlinks": "^4.4.0",
+    "tree-kill": "^1.2.2",
+    "turndown": "^7.2.2",
+    "type-fest": "^5.5.0",
+    "undici": "^7.24.6",
+    "usehooks-ts": "^3.1.1",
+    "vscode-jsonrpc": "^8.2.1",
+    "vscode-languageserver-protocol": "^3.17.5",
+    "vscode-languageserver-types": "^3.17.5",
+    "wrap-ansi": "^10.0.0",
+    "ws": "^8.20.0",
+    "xss": "^1.0.15",
+    "yaml": "^2.8.3",
+    "zod": "^4.3.6"
+  },
+  "devDependencies": {
+    "@types/bun": "^1.3.11",
+    "typescript": "^6.0.2"
+  }
+}

+ 96 - 0
scripts/build.ts

@@ -0,0 +1,96 @@
+import { chmodSync, existsSync, mkdirSync } from 'fs'
+import { dirname } from 'path'
+
+const pkg = await Bun.file(new URL('../package.json', import.meta.url)).json() as {
+  name: string
+  version: string
+}
+
+const args = process.argv.slice(2)
+const compile = args.includes('--compile')
+
+const features: string[] = []
+for (let i = 0; i < args.length; i += 1) {
+  const arg = args[i]
+  if (arg === '--feature' && args[i + 1]) {
+    features.push(args[i + 1]!)
+    i += 1
+    continue
+  }
+  if (arg.startsWith('--feature=')) {
+    features.push(arg.slice('--feature='.length))
+  }
+}
+
+const outfile = compile ? './dist/cli' : './cli'
+const buildTime = new Date().toISOString()
+
+mkdirSync(dirname(outfile), { recursive: true })
+
+const externals = [
+  '@ant/*',
+  'audio-capture-napi',
+  'image-processor-napi',
+  'modifiers-napi',
+  'url-handler-napi',
+]
+
+const defines = {
+  'process.env.USER_TYPE': JSON.stringify('external'),
+  'process.env.CLAUDE_CODE_VERIFY_PLAN': JSON.stringify('false'),
+  'MACRO.VERSION': JSON.stringify(pkg.version),
+  'MACRO.BUILD_TIME': JSON.stringify(buildTime),
+  'MACRO.PACKAGE_URL': JSON.stringify(pkg.name),
+  'MACRO.NATIVE_PACKAGE_URL': 'undefined',
+  'MACRO.FEEDBACK_CHANNEL': JSON.stringify('github'),
+  'MACRO.ISSUES_EXPLAINER': JSON.stringify(
+    'This reconstructed source snapshot does not include Anthropic internal issue routing.',
+  ),
+  'MACRO.VERSION_CHANGELOG': JSON.stringify(
+    'https://github.com/paoloanzn/claude-code',
+  ),
+} as const
+
+const cmd = [
+  'bun',
+  'build',
+  './src/entrypoints/cli.tsx',
+  '--compile',
+  '--target',
+  'bun',
+  '--format',
+  'esm',
+  '--outfile',
+  outfile,
+  '--minify',
+  '--bytecode',
+  '--packages',
+  'bundle',
+  '--conditions',
+  'bun',
+]
+
+for (const external of externals) {
+  cmd.push('--external', external)
+}
+
+for (const [key, value] of Object.entries(defines)) {
+  cmd.push('--define', `${key}=${value}`)
+}
+
+const proc = Bun.spawnSync({
+  cmd,
+  cwd: process.cwd(),
+  stdout: 'inherit',
+  stderr: 'inherit',
+})
+
+if (proc.exitCode !== 0) {
+  process.exit(proc.exitCode ?? 1)
+}
+
+if (existsSync(outfile)) {
+  chmodSync(outfile, 0o755)
+}
+
+console.log(`Built ${outfile}`)

+ 15 - 0
src/assistant/AssistantSessionChooser.tsx

@@ -0,0 +1,15 @@
+import { useEffect } from 'react'
+
+type Props = {
+  sessions: unknown[]
+  onSelect: (sessionId: string) => void
+  onCancel: () => void
+}
+
+export function AssistantSessionChooser({ onCancel }: Props) {
+  useEffect(() => {
+    onCancel()
+  }, [onCancel])
+
+  return null
+}

+ 22 - 0
src/commands/assistant/assistant.tsx

@@ -0,0 +1,22 @@
+import { homedir } from 'os'
+import { join } from 'path'
+import { useEffect } from 'react'
+
+type Props = {
+  defaultDir: string
+  onInstalled: (dir: string) => void
+  onCancel: () => void
+  onError: (message: string) => void
+}
+
+export async function computeDefaultInstallDir(): Promise<string> {
+  return join(homedir(), '.claude', 'assistant')
+}
+
+export function NewInstallWizard({ onCancel }: Props) {
+  useEffect(() => {
+    onCancel()
+  }, [onCancel])
+
+  return null
+}

+ 3 - 3
src/components/StructuredDiff/colorDiff.ts

@@ -3,7 +3,7 @@ import {
   ColorFile,
   getSyntaxTheme as nativeGetSyntaxTheme,
   type SyntaxTheme,
-} from 'color-diff-napi'
+} from '../../native-ts/color-diff/index.js'
 import { isEnvDefinedFalsy } from '../../utils/envUtils.js'
 
 export type ColorModuleUnavailableReason = 'env'
@@ -12,8 +12,8 @@ export type ColorModuleUnavailableReason = 'env'
  * Returns a static reason why the color-diff module is unavailable, or null if available.
  * 'env' = disabled via CLAUDE_CODE_SYNTAX_HIGHLIGHT
  *
- * The TS port of color-diff works in all build modes, so the only way to
- * disable it is via the env var.
+ * The reconstructed project always uses the bundled TypeScript port, so the
+ * only way to disable syntax highlighting is via the env var.
  */
 export function getColorModuleUnavailableReason(): ColorModuleUnavailableReason | null {
   if (isEnvDefinedFalsy(process.env.CLAUDE_CODE_SYNTAX_HIGHLIGHT)) {

+ 17 - 0
src/components/agents/SnapshotUpdateDialog.tsx

@@ -0,0 +1,17 @@
+import { useEffect } from 'react'
+
+type Props = {
+  agentType: string
+  scope: unknown
+  snapshotTimestamp: string
+  onComplete: (choice: 'merge' | 'keep' | 'replace') => void
+  onCancel: () => void
+}
+
+export function SnapshotUpdateDialog({ onCancel }: Props) {
+  useEffect(() => {
+    onCancel()
+  }, [onCancel])
+
+  return null
+}

+ 169 - 0
src/entrypoints/sdk/coreTypes.generated.ts

@@ -0,0 +1,169 @@
+export type PermissionMode =
+  | 'default'
+  | 'acceptEdits'
+  | 'bypassPermissions'
+  | 'plan'
+
+export type ExitReason =
+  | 'clear'
+  | 'resume'
+  | 'logout'
+  | 'prompt_input_exit'
+  | 'other'
+  | 'bypass_permissions_disabled'
+
+export type HookEvent =
+  | 'PreToolUse'
+  | 'PostToolUse'
+  | 'PostToolUseFailure'
+  | 'Notification'
+  | 'UserPromptSubmit'
+  | 'SessionStart'
+  | 'SessionEnd'
+  | 'Stop'
+  | 'StopFailure'
+  | 'SubagentStart'
+  | 'SubagentStop'
+  | 'PreCompact'
+  | 'PostCompact'
+  | 'PermissionRequest'
+  | 'PermissionDenied'
+  | 'Setup'
+  | 'TeammateIdle'
+  | 'TaskCreated'
+  | 'TaskCompleted'
+  | 'Elicitation'
+  | 'ElicitationResult'
+  | 'ConfigChange'
+  | 'WorktreeCreate'
+  | 'WorktreeRemove'
+  | 'InstructionsLoaded'
+  | 'CwdChanged'
+  | 'FileChanged'
+
+export type ModelUsage = {
+  costUSD?: number
+  inputTokens?: number
+  outputTokens?: number
+  cacheCreationInputTokens?: number
+  cacheReadInputTokens?: number
+  [key: string]: number | undefined
+}
+
+export type SDKStatus = 'compacting' | string | null
+
+export type SDKBaseMessage = {
+  type: string
+  subtype?: string
+  uuid?: string
+  session_id?: string
+  [key: string]: unknown
+}
+
+export type SDKAssistantMessage = SDKBaseMessage & {
+  type: 'assistant'
+  message?: { content?: unknown[] }
+}
+
+export type SDKAssistantMessageError = SDKBaseMessage & {
+  type: 'assistant_error'
+  message?: string
+}
+
+export type SDKPartialAssistantMessage = SDKBaseMessage & {
+  type: 'assistant_partial'
+  delta?: string
+}
+
+export type SDKResultMessage = SDKBaseMessage & {
+  type: 'result'
+  is_error?: boolean
+  result?: string
+  duration_ms?: number
+  total_cost_usd?: number
+}
+
+export type SDKStatusMessage = SDKBaseMessage & {
+  type: 'status'
+  status: SDKStatus
+}
+
+export type SDKSystemMessage = SDKBaseMessage & {
+  type: 'system'
+  content?: string
+}
+
+export type SDKCompactBoundaryMessage = SDKSystemMessage & {
+  subtype: 'compact_boundary' | 'microcompact_boundary'
+}
+
+export type SDKToolProgressMessage = SDKBaseMessage & {
+  type: 'tool_progress'
+  data?: Record<string, unknown>
+}
+
+export type SDKPermissionDenial = SDKBaseMessage & {
+  type: 'permission_denial'
+  mode?: PermissionMode
+  toolName?: string
+}
+
+export type SDKRateLimitInfo = {
+  remaining?: number
+  resetAt?: string
+}
+
+export type SDKUserMessage = SDKBaseMessage & {
+  type: 'user'
+  message?: { content?: unknown }
+}
+
+export type SDKUserMessageReplay = SDKUserMessage & {
+  isReplay?: boolean
+}
+
+export type SDKSessionInfo = {
+  sessionId: string
+  summary?: string
+  cwd?: string
+  createdAt?: string
+  updatedAt?: string
+}
+
+export type PermissionResult =
+  | { behavior: 'allow'; updatedInput?: Record<string, unknown> }
+  | { behavior: 'deny'; message?: string }
+  | { behavior: 'ask'; updatedInput?: Record<string, unknown>; message?: string }
+
+export type HookInput = {
+  session_id?: string
+  event?: HookEvent
+  [key: string]: unknown
+}
+
+export type HookJSONOutput = {
+  continue?: boolean
+  stopReason?: string
+  message?: string
+  decision?: 'allow' | 'deny' | 'ask'
+  [key: string]: unknown
+}
+
+export type SyncHookJSONOutput = HookJSONOutput
+
+export type AsyncHookJSONOutput = HookJSONOutput & {
+  waitMs?: number
+}
+
+export type SDKMessage =
+  | SDKAssistantMessage
+  | SDKAssistantMessageError
+  | SDKCompactBoundaryMessage
+  | SDKPartialAssistantMessage
+  | SDKPermissionDenial
+  | SDKResultMessage
+  | SDKStatusMessage
+  | SDKSystemMessage
+  | SDKToolProgressMessage
+  | SDKUserMessage
+  | SDKUserMessageReplay

+ 59 - 0
src/entrypoints/sdk/runtimeTypes.ts

@@ -0,0 +1,59 @@
+import type { CallToolResult, ToolAnnotations } from '@modelcontextprotocol/sdk/types.js'
+import type { ZodTypeAny } from 'zod/v4'
+
+export type EffortLevel = 'low' | 'medium' | 'high' | 'max'
+
+export type AnyZodRawShape = Record<string, ZodTypeAny>
+
+export type InferShape<Schema extends AnyZodRawShape> = {
+  [K in keyof Schema]?: unknown
+}
+
+export type SdkMcpToolDefinition<Schema extends AnyZodRawShape> = {
+  name: string
+  description: string
+  inputSchema: Schema
+  handler: (args: InferShape<Schema>, extra: unknown) => Promise<CallToolResult>
+  annotations?: ToolAnnotations
+  searchHint?: string
+  alwaysLoad?: boolean
+}
+
+export type McpSdkServerConfigWithInstance = Record<string, unknown>
+
+export type Options = Record<string, unknown>
+export type InternalOptions = Options
+
+export type SDKSessionOptions = Options & {
+  model?: string
+}
+
+export type Query = AsyncIterable<unknown>
+export type InternalQuery = AsyncIterable<unknown>
+
+export type SessionMutationOptions = {
+  dir?: string
+}
+
+export type ListSessionsOptions = SessionMutationOptions & {
+  limit?: number
+  offset?: number
+}
+
+export type GetSessionInfoOptions = SessionMutationOptions
+
+export type GetSessionMessagesOptions = SessionMutationOptions & {
+  limit?: number
+  offset?: number
+  includeSystemMessages?: boolean
+}
+
+export type ForkSessionOptions = SessionMutationOptions
+
+export type ForkSessionResult = {
+  sessionId: string
+}
+
+export type SDKSession = {
+  id: string
+}

+ 1 - 0
src/entrypoints/sdk/toolTypes.ts

@@ -0,0 +1 @@
+export {}

+ 1 - 0
src/ink/devtools.ts

@@ -0,0 +1 @@
+export {}

+ 1 - 0
src/ink/global.d.ts

@@ -0,0 +1 @@
+export {}

文件差異過大導致無法顯示
+ 0 - 0
src/main.tsx


+ 19 - 0
src/services/compact/cachedMCConfig.ts

@@ -0,0 +1,19 @@
+export type CachedMCConfig = {
+  enabled: boolean
+  triggerThreshold: number
+  keepRecent: number
+  supportedModels: string[]
+  systemPromptSuggestSummaries: boolean
+}
+
+const DEFAULT_CACHED_MC_CONFIG: CachedMCConfig = {
+  enabled: false,
+  triggerThreshold: 12,
+  keepRecent: 3,
+  supportedModels: ['claude-opus-4-6', 'claude-sonnet-4-6'],
+  systemPromptSuggestSummaries: false,
+}
+
+export function getCachedMCConfig(): CachedMCConfig {
+  return DEFAULT_CACHED_MC_CONFIG
+}

+ 104 - 0
src/services/compact/cachedMicrocompact.ts

@@ -0,0 +1,104 @@
+import {
+  getCachedMCConfig,
+  type CachedMCConfig,
+} from './cachedMCConfig.js'
+
+export type CacheEditsBlock = {
+  type: 'cache_edits'
+  edits: { type: 'delete'; cache_reference: string }[]
+}
+
+export type PinnedCacheEdits = {
+  userMessageIndex: number
+  block: CacheEditsBlock
+}
+
+export type CachedMCState = {
+  pinnedEdits: PinnedCacheEdits[]
+  registeredTools: Set<string>
+  toolOrder: string[]
+  deletedRefs: Set<string>
+}
+
+export function createCachedMCState(): CachedMCState {
+  return {
+    pinnedEdits: [],
+    registeredTools: new Set(),
+    toolOrder: [],
+    deletedRefs: new Set(),
+  }
+}
+
+export function isCachedMicrocompactEnabled(): boolean {
+  return getCachedMCConfig().enabled
+}
+
+export function isModelSupportedForCacheEditing(model: string): boolean {
+  return getCachedMCConfig().supportedModels.some(pattern =>
+    model.includes(pattern),
+  )
+}
+
+export { getCachedMCConfig }
+export type { CachedMCConfig }
+
+export function registerToolResult(
+  state: CachedMCState,
+  toolUseId: string,
+): void {
+  if (state.registeredTools.has(toolUseId)) {
+    return
+  }
+
+  state.registeredTools.add(toolUseId)
+  state.toolOrder.push(toolUseId)
+}
+
+export function registerToolMessage(
+  _state: CachedMCState,
+  _toolUseIds: string[],
+): void {}
+
+export function getToolResultsToDelete(state: CachedMCState): string[] {
+  const config = getCachedMCConfig()
+  const activeRefs = state.toolOrder.filter(id => !state.deletedRefs.has(id))
+
+  if (!config.enabled || activeRefs.length < config.triggerThreshold) {
+    return []
+  }
+
+  return activeRefs.slice(0, Math.max(0, activeRefs.length - config.keepRecent))
+}
+
+export function createCacheEditsBlock(
+  state: CachedMCState,
+  toolUseIds: string[],
+): CacheEditsBlock | null {
+  const edits = toolUseIds
+    .filter(id => !state.deletedRefs.has(id))
+    .map(id => {
+      state.deletedRefs.add(id)
+      return {
+        type: 'delete' as const,
+        cache_reference: id,
+      }
+    })
+
+  if (edits.length === 0) {
+    return null
+  }
+
+  return {
+    type: 'cache_edits',
+    edits,
+  }
+}
+
+export function markToolsSentToAPI(_state: CachedMCState): void {}
+
+export function resetCachedMCState(state: CachedMCState): void {
+  state.pinnedEdits.length = 0
+  state.registeredTools.clear()
+  state.toolOrder.length = 0
+  state.deletedRefs.clear()
+}

+ 39 - 0
src/services/compact/snipCompact.ts

@@ -0,0 +1,39 @@
+type SnipLikeMessage = {
+  type?: string
+  subtype?: string
+}
+
+export const SNIP_NUDGE_TEXT =
+  'Context-efficiency hints are unavailable in this reconstructed source snapshot.'
+
+export function isSnipRuntimeEnabled(): boolean {
+  return false
+}
+
+export function shouldNudgeForSnips(_messages: readonly unknown[]): boolean {
+  return false
+}
+
+export function isSnipMarkerMessage(message: unknown): boolean {
+  return (
+    typeof message === 'object' &&
+    message !== null &&
+    (message as SnipLikeMessage).subtype === 'snip_marker'
+  )
+}
+
+export function snipCompactIfNeeded<T>(
+  messages: T[],
+  _options?: { force?: boolean },
+): {
+  messages: T[]
+  tokensFreed: number
+  boundaryMessage?: T
+  executed: boolean
+} {
+  return {
+    messages,
+    tokensFreed: 0,
+    executed: false,
+  }
+}

+ 16 - 0
src/services/compact/snipProjection.ts

@@ -0,0 +1,16 @@
+type BoundaryLikeMessage = {
+  type?: string
+  subtype?: string
+}
+
+export function isSnipBoundaryMessage(message: unknown): boolean {
+  return (
+    typeof message === 'object' &&
+    message !== null &&
+    (message as BoundaryLikeMessage).subtype === 'snip_boundary'
+  )
+}
+
+export function projectSnippedView<T>(messages: T[]): T[] {
+  return messages
+}

+ 67 - 0
src/services/contextCollapse/index.ts

@@ -0,0 +1,67 @@
+type ContextCollapseStats = {
+  collapsedSpans: number
+  collapsedMessages: number
+  stagedSpans: number
+  health: {
+    totalErrors: number
+    totalEmptySpawns: number
+    totalSpawns: number
+    emptySpawnWarningEmitted: boolean
+    lastError: string | null
+  }
+}
+
+const EMPTY_STATS: ContextCollapseStats = {
+  collapsedSpans: 0,
+  collapsedMessages: 0,
+  stagedSpans: 0,
+  health: {
+    totalErrors: 0,
+    totalEmptySpawns: 0,
+    totalSpawns: 0,
+    emptySpawnWarningEmitted: false,
+    lastError: null,
+  },
+}
+
+export function initContextCollapse(): void {}
+
+export function resetContextCollapse(): void {}
+
+export function isContextCollapseEnabled(): boolean {
+  return false
+}
+
+export function getStats(): ContextCollapseStats {
+  return EMPTY_STATS
+}
+
+export function subscribe(_callback: () => void): () => void {
+  return () => {}
+}
+
+export async function applyCollapsesIfNeeded<T>(
+  messages: T[],
+  _toolUseContext: unknown,
+  _querySource?: string,
+): Promise<{ messages: T[] }> {
+  return { messages }
+}
+
+export function recoverFromOverflow<T>(
+  messages: T[],
+  _querySource?: string,
+): { messages: T[]; committed: number } {
+  return {
+    messages,
+    committed: 0,
+  }
+}
+
+export function isWithheldPromptTooLong(
+  _message: unknown,
+  _isPromptTooLongMessage: (message: unknown) => boolean,
+  _querySource?: string,
+): boolean {
+  return false
+}

+ 3 - 0
src/services/contextCollapse/operations.ts

@@ -0,0 +1,3 @@
+export function projectView<T>(messages: T[]): T[] {
+  return messages
+}

+ 4 - 0
src/services/contextCollapse/persist.ts

@@ -0,0 +1,4 @@
+export function restoreFromEntries(
+  _commits: unknown[],
+  _snapshot: unknown,
+): void {}

+ 4 - 2
src/services/mcp/client.ts

@@ -910,9 +910,11 @@ export const connectToServer = memoize(
         const { createChromeContext } = await import(
           '../../utils/claudeInChrome/mcpServer.js'
         )
-        const { createClaudeForChromeMcpServer } = await import(
-          '@ant/claude-for-chrome-mcp'
+        const { importClaudeForChromePackage } = await import(
+          '../../utils/claudeInChrome/package.js'
         )
+        const { createClaudeForChromeMcpServer } =
+          await importClaudeForChromePackage()
         const { createLinkedTransportPair } = await import(
           './InProcessTransport.js'
         )

+ 6 - 6
src/skills/bundled/claudeInChrome.ts

@@ -1,12 +1,8 @@
-import { BROWSER_TOOLS } from '@ant/claude-for-chrome-mcp'
 import { BASE_CHROME_PROMPT } from '../../utils/claudeInChrome/prompt.js'
+import { getChromeBrowserTools } from '../../utils/claudeInChrome/package.js'
 import { shouldAutoEnableClaudeInChrome } from '../../utils/claudeInChrome/setup.js'
 import { registerBundledSkill } from '../bundledSkills.js'
 
-const CLAUDE_IN_CHROME_MCP_TOOLS = BROWSER_TOOLS.map(
-  tool => `mcp__claude-in-chrome__${tool.name}`,
-)
-
 const SKILL_ACTIVATION_MESSAGE = `
 Now that this skill is invoked, you have access to Chrome browser automation tools. You can now use the mcp__claude-in-chrome__* tools to interact with web pages.
 
@@ -14,13 +10,17 @@ IMPORTANT: Start by calling mcp__claude-in-chrome__tabs_context_mcp to get infor
 `
 
 export function registerClaudeInChromeSkill(): void {
+  const allowedTools = getChromeBrowserTools().map(
+    tool => `mcp__claude-in-chrome__${tool.name}`,
+  )
+
   registerBundledSkill({
     name: 'claude-in-chrome',
     description:
       'Automates your Chrome browser to interact with web pages - clicking elements, filling forms, capturing screenshots, reading console logs, and navigating sites. Opens pages in new tabs within your existing Chrome session. Requires site-level permissions before executing (configured in the extension).',
     whenToUse:
       'When the user wants to interact with web pages, automate browser tasks, capture screenshots, read console logs, or perform any browser-based actions. Always invoke BEFORE attempting to use any mcp__claude-in-chrome__* tools.',
-    allowedTools: CLAUDE_IN_CHROME_MCP_TOOLS,
+    allowedTools,
     userInvocable: true,
     isEnabled: () => shouldAutoEnableClaudeInChrome(),
     async getPromptForCommand(args) {

+ 10 - 8
src/skills/bundled/verifyContent.ts

@@ -1,13 +1,15 @@
-// Content for the verify bundled skill.
-// Each .md file is inlined as a string at build time via Bun's text loader.
+// The published snapshot is missing the bundled verify markdown assets.
+// Keep the module shape intact with minimal placeholder content so the CLI
+// can build and the feature can fail gracefully if reached.
 
-import cliMd from './verify/examples/cli.md'
-import serverMd from './verify/examples/server.md'
-import skillMd from './verify/SKILL.md'
+export const SKILL_MD = `# Verify
 
-export const SKILL_MD: string = skillMd
+This reconstructed source snapshot does not include the original bundled
+verify skill content.
+`
 
 export const SKILL_FILES: Record<string, string> = {
-  'examples/cli.md': cliMd,
-  'examples/server.md': serverMd,
+  'examples/cli.md': '# Verify CLI example\n\nUnavailable in this snapshot.\n',
+  'examples/server.md':
+    '# Verify server example\n\nUnavailable in this snapshot.\n',
 }

+ 3 - 0
src/tools/TungstenTool/TungstenLiveMonitor.tsx

@@ -0,0 +1,3 @@
+export function TungstenLiveMonitor() {
+  return null
+}

+ 72 - 0
src/tools/TungstenTool/TungstenTool.ts

@@ -0,0 +1,72 @@
+import { z } from 'zod/v4'
+import { buildTool, type ToolDef } from '../../Tool.js'
+import { lazySchema } from '../../utils/lazySchema.js'
+
+export const TUNGSTEN_TOOL_NAME = 'Tungsten'
+
+const inputSchema = lazySchema(() => z.strictObject({}))
+type InputSchema = ReturnType<typeof inputSchema>
+
+const outputSchema = lazySchema(() =>
+  z.object({
+    available: z.boolean(),
+    message: z.string(),
+  }),
+)
+type OutputSchema = ReturnType<typeof outputSchema>
+
+type Output = z.infer<OutputSchema>
+
+const UNAVAILABLE_MESSAGE =
+  'Tungsten is only available in Anthropic internal builds.'
+
+export function clearSessionsWithTungstenUsage(): void {}
+
+export function resetInitializationState(): void {}
+
+export const TungstenTool = buildTool({
+  name: TUNGSTEN_TOOL_NAME,
+  maxResultSizeChars: 4_096,
+  get inputSchema(): InputSchema {
+    return inputSchema()
+  },
+  get outputSchema(): OutputSchema {
+    return outputSchema()
+  },
+  isEnabled() {
+    return false
+  },
+  isConcurrencySafe() {
+    return false
+  },
+  isReadOnly() {
+    return true
+  },
+  async description() {
+    return UNAVAILABLE_MESSAGE
+  },
+  async prompt() {
+    return UNAVAILABLE_MESSAGE
+  },
+  mapToolResultToToolResultBlockParam(output: Output, toolUseID: string) {
+    return {
+      tool_use_id: toolUseID,
+      type: 'tool_result',
+      content: output.message,
+    }
+  },
+  renderToolUseMessage() {
+    return null
+  },
+  renderToolResultMessage() {
+    return null
+  },
+  async call() {
+    return {
+      data: {
+        available: false,
+        message: UNAVAILABLE_MESSAGE,
+      },
+    }
+  },
+} satisfies ToolDef<InputSchema, Output>)

+ 67 - 0
src/tools/VerifyPlanExecutionTool/VerifyPlanExecutionTool.ts

@@ -0,0 +1,67 @@
+import { z } from 'zod/v4'
+import { buildTool, type ToolDef } from '../../Tool.js'
+import { lazySchema } from '../../utils/lazySchema.js'
+import { VERIFY_PLAN_EXECUTION_TOOL_NAME } from './constants.js'
+
+const inputSchema = lazySchema(() => z.strictObject({}))
+type InputSchema = ReturnType<typeof inputSchema>
+
+const outputSchema = lazySchema(() =>
+  z.object({
+    verified: z.boolean(),
+    message: z.string(),
+  }),
+)
+type OutputSchema = ReturnType<typeof outputSchema>
+
+type Output = z.infer<OutputSchema>
+
+const UNAVAILABLE_MESSAGE =
+  'Plan execution verification is unavailable in this reconstructed build.'
+
+export const VerifyPlanExecutionTool = buildTool({
+  name: VERIFY_PLAN_EXECUTION_TOOL_NAME,
+  maxResultSizeChars: 4_096,
+  get inputSchema(): InputSchema {
+    return inputSchema()
+  },
+  get outputSchema(): OutputSchema {
+    return outputSchema()
+  },
+  isEnabled() {
+    return false
+  },
+  isConcurrencySafe() {
+    return true
+  },
+  isReadOnly() {
+    return true
+  },
+  async description() {
+    return UNAVAILABLE_MESSAGE
+  },
+  async prompt() {
+    return UNAVAILABLE_MESSAGE
+  },
+  mapToolResultToToolResultBlockParam(output: Output, toolUseID: string) {
+    return {
+      tool_use_id: toolUseID,
+      type: 'tool_result',
+      content: output.message,
+    }
+  },
+  renderToolUseMessage() {
+    return null
+  },
+  renderToolResultMessage() {
+    return null
+  },
+  async call() {
+    return {
+      data: {
+        verified: false,
+        message: UNAVAILABLE_MESSAGE,
+      },
+    }
+  },
+} satisfies ToolDef<InputSchema, Output>)

+ 1 - 0
src/tools/VerifyPlanExecutionTool/constants.ts

@@ -0,0 +1 @@
+export const VERIFY_PLAN_EXECUTION_TOOL_NAME = 'VerifyPlanExecution'

+ 1 - 0
src/tools/WorkflowTool/constants.ts

@@ -0,0 +1 @@
+export const WORKFLOW_TOOL_NAME = 'Workflow'

+ 22 - 0
src/types/connectorText.ts

@@ -0,0 +1,22 @@
+export type ConnectorTextBlock = {
+  type: 'connector_text'
+  connector_text: string
+}
+
+export type ConnectorTextDelta = {
+  type: 'connector_text_delta'
+  connector_text: string
+}
+
+export function isConnectorTextBlock(
+  value: unknown,
+): value is ConnectorTextBlock {
+  return (
+    typeof value === 'object' &&
+    value !== null &&
+    'type' in value &&
+    'connector_text' in value &&
+    (value as { type?: unknown }).type === 'connector_text' &&
+    typeof (value as { connector_text?: unknown }).connector_text === 'string'
+  )
+}

+ 6 - 8
src/utils/claudeInChrome/mcpServer.ts

@@ -1,9 +1,3 @@
-import {
-  type ClaudeForChromeContext,
-  createClaudeForChromeMcpServer,
-  type Logger,
-  type PermissionMode,
-} from '@ant/claude-for-chrome-mcp'
 import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
 import { format } from 'util'
 import { shutdownDatadog } from '../../services/analytics/datadog.js'
@@ -20,6 +14,7 @@ import { logForDebugging } from '../debug.js'
 import { isEnvTruthy } from '../envUtils.js'
 import { sideQuery } from '../sideQuery.js'
 import { getAllSocketPaths, getSecureSocketPath } from './common.js'
+import { importClaudeForChromePackage } from './package.js'
 
 const EXTENSION_DOWNLOAD_URL = 'https://claude.ai/chrome'
 const BUG_REPORT_URL =
@@ -39,6 +34,8 @@ const PERMISSION_MODES: readonly PermissionMode[] = [
   'follow_a_plan',
 ]
 
+type PermissionMode = (typeof PERMISSION_MODES)[number]
+
 function isPermissionMode(raw: string): raw is PermissionMode {
   return PERMISSION_MODES.some(m => m === raw)
 }
@@ -84,7 +81,7 @@ function isLocalBridge(): boolean {
  */
 export function createChromeContext(
   env?: Record<string, string>,
-): ClaudeForChromeContext {
+) {
   const logger = new DebugLogger()
   const chromeBridgeUrl = getChromeBridgeUrl()
   logger.info(`Bridge URL: ${chromeBridgeUrl ?? 'none (using native socket)'}`)
@@ -249,6 +246,7 @@ export async function runClaudeInChromeMcpServer(): Promise<void> {
   enableConfigs()
   initializeAnalyticsSink()
   const context = createChromeContext()
+  const { createClaudeForChromeMcpServer } = await importClaudeForChromePackage()
 
   const server = createClaudeForChromeMcpServer(context)
   const transport = new StdioServerTransport()
@@ -274,7 +272,7 @@ export async function runClaudeInChromeMcpServer(): Promise<void> {
   logForDebugging('[Claude in Chrome] MCP server started')
 }
 
-class DebugLogger implements Logger {
+class DebugLogger {
   silly(message: string, ...args: unknown[]): void {
     logForDebugging(format(message, ...args), { level: 'debug' })
   }

+ 32 - 0
src/utils/claudeInChrome/package.ts

@@ -0,0 +1,32 @@
+type BrowserTool = { name: string }
+
+type ClaudeForChromePackage = {
+  BROWSER_TOOLS?: BrowserTool[]
+  createClaudeForChromeMcpServer?: (...args: any[]) => any
+}
+
+let cachedPackage: ClaudeForChromePackage | null | undefined
+
+function loadClaudeForChromePackage(): ClaudeForChromePackage | null {
+  if (cachedPackage !== undefined) {
+    return cachedPackage
+  }
+
+  try {
+    /* eslint-disable @typescript-eslint/no-require-imports */
+    cachedPackage = require('@ant/claude-for-chrome-mcp') as ClaudeForChromePackage
+    /* eslint-enable @typescript-eslint/no-require-imports */
+  } catch {
+    cachedPackage = null
+  }
+
+  return cachedPackage
+}
+
+export function getChromeBrowserTools(): BrowserTool[] {
+  return loadClaudeForChromePackage()?.BROWSER_TOOLS ?? []
+}
+
+export async function importClaudeForChromePackage(): Promise<ClaudeForChromePackage> {
+  return (await import('@ant/claude-for-chrome-mcp')) as ClaudeForChromePackage
+}

+ 2 - 2
src/utils/claudeInChrome/setup.ts

@@ -1,4 +1,3 @@
-import { BROWSER_TOOLS } from '@ant/claude-for-chrome-mcp'
 import { chmod, mkdir, readFile, writeFile } from 'fs/promises'
 import { homedir } from 'os'
 import { join } from 'path'
@@ -28,6 +27,7 @@ import {
   getAllWindowsRegistryKeys,
   openInChrome,
 } from './common.js'
+import { getChromeBrowserTools } from './package.js'
 import { getChromeSystemPrompt } from './prompt.js'
 import { isChromeExtensionInstalledPortable } from './setupPortable.js'
 
@@ -94,7 +94,7 @@ export function setupClaudeInChrome(): {
   systemPrompt: string
 } {
   const isNativeBuild = isInBundledMode()
-  const allowedTools = BROWSER_TOOLS.map(
+  const allowedTools = getChromeBrowserTools().map(
     tool => `mcp__claude-in-chrome__${tool.name}`,
   )
 

+ 1 - 1
src/utils/debug.ts

@@ -84,7 +84,7 @@ export const getDebugFilter = memoize((): DebugFilter | null => {
 
 export const isDebugToStdErr = memoize((): boolean => {
   return (
-    process.argv.includes('--debug-to-stderr') || process.argv.includes('-d2e')
+    process.argv.includes('--debug-to-stderr') || process.argv.includes('-D')
   )
 })
 

+ 20 - 0
src/utils/filePersistence/types.ts

@@ -0,0 +1,20 @@
+export const DEFAULT_UPLOAD_CONCURRENCY = 4
+export const FILE_COUNT_LIMIT = 200
+export const OUTPUTS_SUBDIR = 'outputs'
+
+export type TurnStartTime = number
+
+export type PersistedFile = {
+  filename: string
+  file_id: string
+}
+
+export type FailedPersistence = {
+  filename: string
+  error: string
+}
+
+export type FilesPersistedEventData = {
+  files: PersistedFile[]
+  failed: FailedPersistence[]
+}

+ 6 - 0
src/utils/ultraplan/prompt.txt

@@ -0,0 +1,6 @@
+Create a concise, execution-ready plan for the user's request.
+
+Focus on:
+- The smallest set of steps that will actually unblock implementation
+- Clear assumptions and risks
+- Concrete deliverables instead of generic brainstorming

+ 23 - 0
tsconfig.json

@@ -0,0 +1,23 @@
+{
+  "compilerOptions": {
+    "lib": ["ESNext"],
+    "target": "ESNext",
+    "module": "Preserve",
+    "moduleDetection": "force",
+    "jsx": "react-jsx",
+    "allowJs": true,
+    "types": ["bun"],
+    "baseUrl": ".",
+    "paths": {
+      "src/*": ["src/*"]
+    },
+    "moduleResolution": "bundler",
+    "allowImportingTsExtensions": true,
+    "verbatimModuleSyntax": true,
+    "noEmit": true,
+    "strict": false,
+    "skipLibCheck": true,
+    "noFallthroughCasesInSwitch": true
+  },
+  "include": ["src", "scripts", "env.d.ts"]
+}

部分文件因文件數量過多而無法顯示