yzcode-cli 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/assistant/sessionHistory.ts +87 -0
  2. package/bootstrap/state.ts +1769 -0
  3. package/bridge/bridgeApi.ts +539 -0
  4. package/bridge/bridgeConfig.ts +48 -0
  5. package/bridge/bridgeDebug.ts +135 -0
  6. package/bridge/bridgeEnabled.ts +202 -0
  7. package/bridge/bridgeMain.ts +2999 -0
  8. package/bridge/bridgeMessaging.ts +461 -0
  9. package/bridge/bridgePermissionCallbacks.ts +43 -0
  10. package/bridge/bridgePointer.ts +210 -0
  11. package/bridge/bridgeStatusUtil.ts +163 -0
  12. package/bridge/bridgeUI.ts +530 -0
  13. package/bridge/capacityWake.ts +56 -0
  14. package/bridge/codeSessionApi.ts +168 -0
  15. package/bridge/createSession.ts +384 -0
  16. package/bridge/debugUtils.ts +141 -0
  17. package/bridge/envLessBridgeConfig.ts +165 -0
  18. package/bridge/flushGate.ts +71 -0
  19. package/bridge/inboundAttachments.ts +175 -0
  20. package/bridge/inboundMessages.ts +80 -0
  21. package/bridge/initReplBridge.ts +569 -0
  22. package/bridge/jwtUtils.ts +256 -0
  23. package/bridge/pollConfig.ts +110 -0
  24. package/bridge/pollConfigDefaults.ts +82 -0
  25. package/bridge/remoteBridgeCore.ts +1008 -0
  26. package/bridge/replBridge.ts +2406 -0
  27. package/bridge/replBridgeHandle.ts +36 -0
  28. package/bridge/replBridgeTransport.ts +370 -0
  29. package/bridge/sessionIdCompat.ts +57 -0
  30. package/bridge/sessionRunner.ts +550 -0
  31. package/bridge/trustedDevice.ts +210 -0
  32. package/bridge/types.ts +262 -0
  33. package/bridge/workSecret.ts +127 -0
  34. package/buddy/CompanionSprite.tsx +371 -0
  35. package/buddy/companion.ts +133 -0
  36. package/buddy/prompt.ts +36 -0
  37. package/buddy/sprites.ts +514 -0
  38. package/buddy/types.ts +148 -0
  39. package/buddy/useBuddyNotification.tsx +98 -0
  40. package/coordinator/coordinatorMode.ts +369 -0
  41. package/memdir/findRelevantMemories.ts +141 -0
  42. package/memdir/memdir.ts +507 -0
  43. package/memdir/memoryAge.ts +53 -0
  44. package/memdir/memoryScan.ts +94 -0
  45. package/memdir/memoryTypes.ts +271 -0
  46. package/memdir/paths.ts +278 -0
  47. package/memdir/teamMemPaths.ts +292 -0
  48. package/memdir/teamMemPrompts.ts +100 -0
  49. package/migrations/migrateAutoUpdatesToSettings.ts +61 -0
  50. package/migrations/migrateBypassPermissionsAcceptedToSettings.ts +40 -0
  51. package/migrations/migrateEnableAllProjectMcpServersToSettings.ts +118 -0
  52. package/migrations/migrateFennecToOpus.ts +45 -0
  53. package/migrations/migrateLegacyOpusToCurrent.ts +57 -0
  54. package/migrations/migrateOpusToOpus1m.ts +43 -0
  55. package/migrations/migrateReplBridgeEnabledToRemoteControlAtStartup.ts +22 -0
  56. package/migrations/migrateSonnet1mToSonnet45.ts +48 -0
  57. package/migrations/migrateSonnet45ToSonnet46.ts +67 -0
  58. package/migrations/resetAutoModeOptInForDefaultOffer.ts +51 -0
  59. package/migrations/resetProToOpusDefault.ts +51 -0
  60. package/native-ts/color-diff/index.ts +999 -0
  61. package/native-ts/file-index/index.ts +370 -0
  62. package/native-ts/yoga-layout/enums.ts +134 -0
  63. package/native-ts/yoga-layout/index.ts +2578 -0
  64. package/outputStyles/loadOutputStylesDir.ts +98 -0
  65. package/package.json +22 -5
  66. package/plugins/builtinPlugins.ts +159 -0
  67. package/plugins/bundled/index.ts +23 -0
  68. package/schemas/hooks.ts +222 -0
  69. package/screens/Doctor.tsx +575 -0
  70. package/screens/REPL.tsx +5006 -0
  71. package/screens/ResumeConversation.tsx +399 -0
  72. package/server/createDirectConnectSession.ts +88 -0
  73. package/server/directConnectManager.ts +213 -0
  74. package/server/types.ts +57 -0
  75. package/skills/bundled/batch.ts +124 -0
  76. package/skills/bundled/claudeApi.ts +196 -0
  77. package/skills/bundled/claudeApiContent.ts +75 -0
  78. package/skills/bundled/claudeInChrome.ts +34 -0
  79. package/skills/bundled/debug.ts +103 -0
  80. package/skills/bundled/index.ts +79 -0
  81. package/skills/bundled/keybindings.ts +339 -0
  82. package/skills/bundled/loop.ts +92 -0
  83. package/skills/bundled/loremIpsum.ts +282 -0
  84. package/skills/bundled/remember.ts +82 -0
  85. package/skills/bundled/scheduleRemoteAgents.ts +447 -0
  86. package/skills/bundled/simplify.ts +69 -0
  87. package/skills/bundled/skillify.ts +197 -0
  88. package/skills/bundled/stuck.ts +79 -0
  89. package/skills/bundled/updateConfig.ts +475 -0
  90. package/skills/bundled/verify/SKILL.md +3 -0
  91. package/skills/bundled/verify/examples/cli.md +3 -0
  92. package/skills/bundled/verify/examples/server.md +3 -0
  93. package/skills/bundled/verify.ts +30 -0
  94. package/skills/bundled/verifyContent.ts +13 -0
  95. package/skills/bundledSkills.ts +220 -0
  96. package/skills/loadSkillsDir.ts +1086 -0
  97. package/skills/mcpSkillBuilders.ts +44 -0
  98. package/tasks/DreamTask/DreamTask.ts +157 -0
  99. package/tasks/InProcessTeammateTask/InProcessTeammateTask.tsx +126 -0
  100. package/tasks/InProcessTeammateTask/types.ts +121 -0
  101. package/tasks/LocalAgentTask/LocalAgentTask.tsx +683 -0
  102. package/tasks/LocalMainSessionTask.ts +479 -0
  103. package/tasks/LocalShellTask/LocalShellTask.tsx +523 -0
  104. package/tasks/LocalShellTask/guards.ts +41 -0
  105. package/tasks/LocalShellTask/killShellTasks.ts +76 -0
  106. package/tasks/RemoteAgentTask/RemoteAgentTask.tsx +856 -0
  107. package/tasks/pillLabel.ts +82 -0
  108. package/tasks/stopTask.ts +100 -0
  109. package/tasks/types.ts +46 -0
  110. package/upstreamproxy/relay.ts +455 -0
  111. package/upstreamproxy/upstreamproxy.ts +285 -0
  112. package/vim/motions.ts +82 -0
  113. package/vim/operators.ts +556 -0
  114. package/vim/textObjects.ts +186 -0
  115. package/vim/transitions.ts +490 -0
  116. package/vim/types.ts +199 -0
  117. package/voice/voiceModeEnabled.ts +54 -0
@@ -0,0 +1,135 @@
1
+ import { logForDebugging } from '../utils/debug.js'
2
+ import { BridgeFatalError } from './bridgeApi.js'
3
+ import type { BridgeApiClient } from './types.js'
4
+
5
+ /**
6
+ * Ant-only fault injection for manually testing bridge recovery paths.
7
+ *
8
+ * Real failure modes this targets (BQ 2026-03-12, 7-day window):
9
+ * poll 404 not_found_error — 147K sessions/week, dead onEnvironmentLost gate
10
+ * ws_closed 1002/1006 — 22K sessions/week, zombie poll after close
11
+ * register transient failure — residual: network blips during doReconnect
12
+ *
13
+ * Usage: /bridge-kick <subcommand> from the REPL while Remote Control is
14
+ * connected, then tail debug.log to watch the recovery machinery react.
15
+ *
16
+ * Module-level state is intentional here: one bridge per REPL process, the
17
+ * /bridge-kick slash command has no other way to reach into initBridgeCore's
18
+ * closures, and teardown clears the slot.
19
+ */
20
+
21
+ /** One-shot fault to inject on the next matching api call. */
22
+ type BridgeFault = {
23
+ method:
24
+ | 'pollForWork'
25
+ | 'registerBridgeEnvironment'
26
+ | 'reconnectSession'
27
+ | 'heartbeatWork'
28
+ /** Fatal errors go through handleErrorStatus → BridgeFatalError. Transient
29
+ * errors surface as plain axios rejections (5xx / network). Recovery code
30
+ * distinguishes the two: fatal → teardown, transient → retry/backoff. */
31
+ kind: 'fatal' | 'transient'
32
+ status: number
33
+ errorType?: string
34
+ /** Remaining injections. Decremented on consume; removed at 0. */
35
+ count: number
36
+ }
37
+
38
+ export type BridgeDebugHandle = {
39
+ /** Invoke the transport's permanent-close handler directly. Tests the
40
+ * ws_closed → reconnectEnvironmentWithSession escalation (#22148). */
41
+ fireClose: (code: number) => void
42
+ /** Call reconnectEnvironmentWithSession() — same as SIGUSR2 but
43
+ * reachable from the slash command. */
44
+ forceReconnect: () => void
45
+ /** Queue a fault for the next N calls to the named api method. */
46
+ injectFault: (fault: BridgeFault) => void
47
+ /** Abort the at-capacity sleep so an injected poll fault lands
48
+ * immediately instead of up to 10min later. */
49
+ wakePollLoop: () => void
50
+ /** env/session IDs for the debug.log grep. */
51
+ describe: () => string
52
+ }
53
+
54
+ let debugHandle: BridgeDebugHandle | null = null
55
+ const faultQueue: BridgeFault[] = []
56
+
57
+ export function registerBridgeDebugHandle(h: BridgeDebugHandle): void {
58
+ debugHandle = h
59
+ }
60
+
61
+ export function clearBridgeDebugHandle(): void {
62
+ debugHandle = null
63
+ faultQueue.length = 0
64
+ }
65
+
66
+ export function getBridgeDebugHandle(): BridgeDebugHandle | null {
67
+ return debugHandle
68
+ }
69
+
70
+ export function injectBridgeFault(fault: BridgeFault): void {
71
+ faultQueue.push(fault)
72
+ logForDebugging(
73
+ `[bridge:debug] Queued fault: ${fault.method} ${fault.kind}/${fault.status}${fault.errorType ? `/${fault.errorType}` : ''} ×${fault.count}`,
74
+ )
75
+ }
76
+
77
+ /**
78
+ * Wrap a BridgeApiClient so each call first checks the fault queue. If a
79
+ * matching fault is queued, throw the specified error instead of calling
80
+ * through. Delegates everything else to the real client.
81
+ *
82
+ * Only called when USER_TYPE === 'ant' — zero overhead in external builds.
83
+ */
84
+ export function wrapApiForFaultInjection(
85
+ api: BridgeApiClient,
86
+ ): BridgeApiClient {
87
+ function consume(method: BridgeFault['method']): BridgeFault | null {
88
+ const idx = faultQueue.findIndex(f => f.method === method)
89
+ if (idx === -1) return null
90
+ const fault = faultQueue[idx]!
91
+ fault.count--
92
+ if (fault.count <= 0) faultQueue.splice(idx, 1)
93
+ return fault
94
+ }
95
+
96
+ function throwFault(fault: BridgeFault, context: string): never {
97
+ logForDebugging(
98
+ `[bridge:debug] Injecting ${fault.kind} fault into ${context}: status=${fault.status} errorType=${fault.errorType ?? 'none'}`,
99
+ )
100
+ if (fault.kind === 'fatal') {
101
+ throw new BridgeFatalError(
102
+ `[injected] ${context} ${fault.status}`,
103
+ fault.status,
104
+ fault.errorType,
105
+ )
106
+ }
107
+ // Transient: mimic an axios rejection (5xx / network). No .status on
108
+ // the error itself — that's how the catch blocks distinguish.
109
+ throw new Error(`[injected transient] ${context} ${fault.status}`)
110
+ }
111
+
112
+ return {
113
+ ...api,
114
+ async pollForWork(envId, secret, signal, reclaimMs) {
115
+ const f = consume('pollForWork')
116
+ if (f) throwFault(f, 'Poll')
117
+ return api.pollForWork(envId, secret, signal, reclaimMs)
118
+ },
119
+ async registerBridgeEnvironment(config) {
120
+ const f = consume('registerBridgeEnvironment')
121
+ if (f) throwFault(f, 'Registration')
122
+ return api.registerBridgeEnvironment(config)
123
+ },
124
+ async reconnectSession(envId, sessionId) {
125
+ const f = consume('reconnectSession')
126
+ if (f) throwFault(f, 'ReconnectSession')
127
+ return api.reconnectSession(envId, sessionId)
128
+ },
129
+ async heartbeatWork(envId, workId, token) {
130
+ const f = consume('heartbeatWork')
131
+ if (f) throwFault(f, 'Heartbeat')
132
+ return api.heartbeatWork(envId, workId, token)
133
+ },
134
+ }
135
+ }
@@ -0,0 +1,202 @@
1
+ import { feature } from 'bun:bundle'
2
+ import {
3
+ checkGate_CACHED_OR_BLOCKING,
4
+ getDynamicConfig_CACHED_MAY_BE_STALE,
5
+ getFeatureValue_CACHED_MAY_BE_STALE,
6
+ } from '../services/analytics/growthbook.js'
7
+ // Namespace import breaks the bridgeEnabled → auth → config → bridgeEnabled
8
+ // cycle — authModule.foo is a live binding, so by the time the helpers below
9
+ // call it, auth.js is fully loaded. Previously used require() for the same
10
+ // deferral, but require() hits a CJS cache that diverges from the ESM
11
+ // namespace after mock.module() (daemon/auth.test.ts), breaking spyOn.
12
+ import * as authModule from '../utils/auth.js'
13
+ import { isEnvTruthy } from '../utils/envUtils.js'
14
+ import { lt } from '../utils/semver.js'
15
+
16
+ /**
17
+ * Runtime check for bridge mode entitlement.
18
+ *
19
+ * Remote Control requires a claude.ai subscription (the bridge auths to CCR
20
+ * with the claude.ai OAuth token). isClaudeAISubscriber() excludes
21
+ * Bedrock/Vertex/Foundry, apiKeyHelper/gateway deployments, env-var API keys,
22
+ * and Console API logins — none of which have the OAuth token CCR needs.
23
+ * See github.com/deshaw/anthropic-issues/issues/24.
24
+ *
25
+ * The `feature('BRIDGE_MODE')` guard ensures the GrowthBook string literal
26
+ * is only referenced when bridge mode is enabled at build time.
27
+ */
28
+ export function isBridgeEnabled(): boolean {
29
+ // Positive ternary pattern — see docs/feature-gating.md.
30
+ // Negative pattern (if (!feature(...)) return) does not eliminate
31
+ // inline string literals from external builds.
32
+ return feature('BRIDGE_MODE')
33
+ ? isClaudeAISubscriber() &&
34
+ getFeatureValue_CACHED_MAY_BE_STALE('tengu_ccr_bridge', false)
35
+ : false
36
+ }
37
+
38
+ /**
39
+ * Blocking entitlement check for Remote Control.
40
+ *
41
+ * Returns cached `true` immediately (fast path). If the disk cache says
42
+ * `false` or is missing, awaits GrowthBook init and fetches the fresh
43
+ * server value (slow path, max ~5s), then writes it to disk.
44
+ *
45
+ * Use at entitlement gates where a stale `false` would unfairly block access.
46
+ * For user-facing error paths, prefer `getBridgeDisabledReason()` which gives
47
+ * a specific diagnostic. For render-body UI visibility checks, use
48
+ * `isBridgeEnabled()` instead.
49
+ */
50
+ export async function isBridgeEnabledBlocking(): Promise<boolean> {
51
+ return feature('BRIDGE_MODE')
52
+ ? isClaudeAISubscriber() &&
53
+ (await checkGate_CACHED_OR_BLOCKING('tengu_ccr_bridge'))
54
+ : false
55
+ }
56
+
57
+ /**
58
+ * Diagnostic message for why Remote Control is unavailable, or null if
59
+ * it's enabled. Call this instead of a bare `isBridgeEnabledBlocking()`
60
+ * check when you need to show the user an actionable error.
61
+ *
62
+ * The GrowthBook gate targets on organizationUUID, which comes from
63
+ * config.oauthAccount — populated by /api/oauth/profile during login.
64
+ * That endpoint requires the user:profile scope. Tokens without it
65
+ * (setup-token, CLAUDE_CODE_OAUTH_TOKEN env var, or pre-scope-expansion
66
+ * logins) leave oauthAccount unpopulated, so the gate falls back to
67
+ * false and users see a dead-end "not enabled" message with no hint
68
+ * that re-login would fix it. See CC-1165 / gh-33105.
69
+ */
70
+ export async function getBridgeDisabledReason(): Promise<string | null> {
71
+ if (feature('BRIDGE_MODE')) {
72
+ if (!isClaudeAISubscriber()) {
73
+ return 'Remote Control requires a claude.ai subscription. Run `claude auth login` to sign in with your claude.ai account.'
74
+ }
75
+ if (!hasProfileScope()) {
76
+ return 'Remote Control requires a full-scope login token. Long-lived tokens (from `claude setup-token` or CLAUDE_CODE_OAUTH_TOKEN) are limited to inference-only for security reasons. Run `claude auth login` to use Remote Control.'
77
+ }
78
+ if (!getOauthAccountInfo()?.organizationUuid) {
79
+ return 'Unable to determine your organization for Remote Control eligibility. Run `claude auth login` to refresh your account information.'
80
+ }
81
+ if (!(await checkGate_CACHED_OR_BLOCKING('tengu_ccr_bridge'))) {
82
+ return 'Remote Control is not yet enabled for your account.'
83
+ }
84
+ return null
85
+ }
86
+ return 'Remote Control is not available in this build.'
87
+ }
88
+
89
+ // try/catch: main.tsx:5698 calls isBridgeEnabled() while defining the Commander
90
+ // program, before enableConfigs() runs. isClaudeAISubscriber() → getGlobalConfig()
91
+ // throws "Config accessed before allowed" there. Pre-config, no OAuth token can
92
+ // exist anyway — false is correct. Same swallow getFeatureValue_CACHED_MAY_BE_STALE
93
+ // already does at growthbook.ts:775-780.
94
+ function isClaudeAISubscriber(): boolean {
95
+ try {
96
+ return authModule.isClaudeAISubscriber()
97
+ } catch {
98
+ return false
99
+ }
100
+ }
101
+ function hasProfileScope(): boolean {
102
+ try {
103
+ return authModule.hasProfileScope()
104
+ } catch {
105
+ return false
106
+ }
107
+ }
108
+ function getOauthAccountInfo(): ReturnType<
109
+ typeof authModule.getOauthAccountInfo
110
+ > {
111
+ try {
112
+ return authModule.getOauthAccountInfo()
113
+ } catch {
114
+ return undefined
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Runtime check for the env-less (v2) REPL bridge path.
120
+ * Returns true when the GrowthBook flag `tengu_bridge_repl_v2` is enabled.
121
+ *
122
+ * This gates which implementation initReplBridge uses — NOT whether bridge
123
+ * is available at all (see isBridgeEnabled above). Daemon/print paths stay
124
+ * on the env-based implementation regardless of this gate.
125
+ */
126
+ export function isEnvLessBridgeEnabled(): boolean {
127
+ return feature('BRIDGE_MODE')
128
+ ? getFeatureValue_CACHED_MAY_BE_STALE('tengu_bridge_repl_v2', false)
129
+ : false
130
+ }
131
+
132
+ /**
133
+ * Kill-switch for the `cse_*` → `session_*` client-side retag shim.
134
+ *
135
+ * The shim exists because compat/convert.go:27 validates TagSession and the
136
+ * claude.ai frontend routes on `session_*`, while v2 worker endpoints hand out
137
+ * `cse_*`. Once the server tags by environment_kind and the frontend accepts
138
+ * `cse_*` directly, flip this to false to make toCompatSessionId a no-op.
139
+ * Defaults to true — the shim stays active until explicitly disabled.
140
+ */
141
+ export function isCseShimEnabled(): boolean {
142
+ return feature('BRIDGE_MODE')
143
+ ? getFeatureValue_CACHED_MAY_BE_STALE(
144
+ 'tengu_bridge_repl_v2_cse_shim_enabled',
145
+ true,
146
+ )
147
+ : true
148
+ }
149
+
150
+ /**
151
+ * Returns an error message if the current CLI version is below the
152
+ * minimum required for the v1 (env-based) Remote Control path, or null if the
153
+ * version is fine. The v2 (env-less) path uses checkEnvLessBridgeMinVersion()
154
+ * in envLessBridgeConfig.ts instead — the two implementations have independent
155
+ * version floors.
156
+ *
157
+ * Uses cached (non-blocking) GrowthBook config. If GrowthBook hasn't
158
+ * loaded yet, the default '0.0.0' means the check passes — a safe fallback.
159
+ */
160
+ export function checkBridgeMinVersion(): string | null {
161
+ // Positive pattern — see docs/feature-gating.md.
162
+ // Negative pattern (if (!feature(...)) return) does not eliminate
163
+ // inline string literals from external builds.
164
+ if (feature('BRIDGE_MODE')) {
165
+ const config = getDynamicConfig_CACHED_MAY_BE_STALE<{
166
+ minVersion: string
167
+ }>('tengu_bridge_min_version', { minVersion: '0.0.0' })
168
+ if (config.minVersion && lt(MACRO.VERSION, config.minVersion)) {
169
+ return `Your version of Claude Code (${MACRO.VERSION}) is too old for Remote Control.\nVersion ${config.minVersion} or higher is required. Run \`claude update\` to update.`
170
+ }
171
+ }
172
+ return null
173
+ }
174
+
175
+ /**
176
+ * Default for remoteControlAtStartup when the user hasn't explicitly set it.
177
+ * When the CCR_AUTO_CONNECT build flag is present (ant-only) and the
178
+ * tengu_cobalt_harbor GrowthBook gate is on, all sessions connect to CCR by
179
+ * default — the user can still opt out by setting remoteControlAtStartup=false
180
+ * in config (explicit settings always win over this default).
181
+ *
182
+ * Defined here rather than in config.ts to avoid a direct
183
+ * config.ts → growthbook.ts import cycle (growthbook.ts → user.ts → config.ts).
184
+ */
185
+ export function getCcrAutoConnectDefault(): boolean {
186
+ return feature('CCR_AUTO_CONNECT')
187
+ ? getFeatureValue_CACHED_MAY_BE_STALE('tengu_cobalt_harbor', false)
188
+ : false
189
+ }
190
+
191
+ /**
192
+ * Opt-in CCR mirror mode — every local session spawns an outbound-only
193
+ * Remote Control session that receives forwarded events. Separate from
194
+ * getCcrAutoConnectDefault (bidirectional Remote Control). Env var wins for
195
+ * local opt-in; GrowthBook controls rollout.
196
+ */
197
+ export function isCcrMirrorEnabled(): boolean {
198
+ return feature('CCR_MIRROR')
199
+ ? isEnvTruthy(process.env.CLAUDE_CODE_CCR_MIRROR) ||
200
+ getFeatureValue_CACHED_MAY_BE_STALE('tengu_ccr_mirror', false)
201
+ : false
202
+ }