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,44 @@
1
+ import type {
2
+ createSkillCommand,
3
+ parseSkillFrontmatterFields,
4
+ } from './loadSkillsDir.js'
5
+
6
+ /**
7
+ * Write-once registry for the two loadSkillsDir functions that MCP skill
8
+ * discovery needs. This module is a dependency-graph leaf: it imports nothing
9
+ * but types, so both mcpSkills.ts and loadSkillsDir.ts can depend on it
10
+ * without forming a cycle (client.ts → mcpSkills.ts → loadSkillsDir.ts → …
11
+ * → client.ts).
12
+ *
13
+ * The non-literal dynamic-import approach ("await import(variable)") fails at
14
+ * runtime in Bun-bundled binaries — the specifier is resolved against the
15
+ * chunk's /$bunfs/root/… path, not the original source tree, yielding "Cannot
16
+ * find module './loadSkillsDir.js'". A literal dynamic import works in bunfs
17
+ * but dependency-cruiser tracks it, and because loadSkillsDir transitively
18
+ * reaches almost everything, the single new edge fans out into many new cycle
19
+ * violations in the diff check.
20
+ *
21
+ * Registration happens at loadSkillsDir.ts module init, which is eagerly
22
+ * evaluated at startup via the static import from commands.ts — long before
23
+ * any MCP server connects.
24
+ */
25
+
26
+ export type MCPSkillBuilders = {
27
+ createSkillCommand: typeof createSkillCommand
28
+ parseSkillFrontmatterFields: typeof parseSkillFrontmatterFields
29
+ }
30
+
31
+ let builders: MCPSkillBuilders | null = null
32
+
33
+ export function registerMCPSkillBuilders(b: MCPSkillBuilders): void {
34
+ builders = b
35
+ }
36
+
37
+ export function getMCPSkillBuilders(): MCPSkillBuilders {
38
+ if (!builders) {
39
+ throw new Error(
40
+ 'MCP skill builders not registered — loadSkillsDir.ts has not been evaluated yet',
41
+ )
42
+ }
43
+ return builders
44
+ }
@@ -0,0 +1,157 @@
1
+ // Background task entry for auto-dream (memory consolidation subagent).
2
+ // Makes the otherwise-invisible forked agent visible in the footer pill and
3
+ // Shift+Down dialog. The dream agent itself is unchanged — this is pure UI
4
+ // surfacing via the existing task registry.
5
+
6
+ import { rollbackConsolidationLock } from '../../services/autoDream/consolidationLock.js'
7
+ import type { SetAppState, Task, TaskStateBase } from '../../Task.js'
8
+ import { createTaskStateBase, generateTaskId } from '../../Task.js'
9
+ import { registerTask, updateTaskState } from '../../utils/task/framework.js'
10
+
11
+ // Keep only the N most recent turns for live display.
12
+ const MAX_TURNS = 30
13
+
14
+ // A single assistant turn from the dream agent, tool uses collapsed to a count.
15
+ export type DreamTurn = {
16
+ text: string
17
+ toolUseCount: number
18
+ }
19
+
20
+ // No phase detection — the dream prompt has a 4-stage structure
21
+ // (orient/gather/consolidate/prune) but we don't parse it. Just flip from
22
+ // 'starting' to 'updating' when the first Edit/Write tool_use lands.
23
+ export type DreamPhase = 'starting' | 'updating'
24
+
25
+ export type DreamTaskState = TaskStateBase & {
26
+ type: 'dream'
27
+ phase: DreamPhase
28
+ sessionsReviewing: number
29
+ /**
30
+ * Paths observed in Edit/Write tool_use blocks via onMessage. This is an
31
+ * INCOMPLETE reflection of what the dream agent actually changed — it misses
32
+ * any bash-mediated writes and only captures the tool calls we pattern-match.
33
+ * Treat as "at least these were touched", not "only these were touched".
34
+ */
35
+ filesTouched: string[]
36
+ /** Assistant text responses, tool uses collapsed. Prompt is NOT included. */
37
+ turns: DreamTurn[]
38
+ abortController?: AbortController
39
+ /** Stashed so kill can rewind the lock mtime (same path as fork-failure). */
40
+ priorMtime: number
41
+ }
42
+
43
+ export function isDreamTask(task: unknown): task is DreamTaskState {
44
+ return (
45
+ typeof task === 'object' &&
46
+ task !== null &&
47
+ 'type' in task &&
48
+ task.type === 'dream'
49
+ )
50
+ }
51
+
52
+ export function registerDreamTask(
53
+ setAppState: SetAppState,
54
+ opts: {
55
+ sessionsReviewing: number
56
+ priorMtime: number
57
+ abortController: AbortController
58
+ },
59
+ ): string {
60
+ const id = generateTaskId('dream')
61
+ const task: DreamTaskState = {
62
+ ...createTaskStateBase(id, 'dream', 'dreaming'),
63
+ type: 'dream',
64
+ status: 'running',
65
+ phase: 'starting',
66
+ sessionsReviewing: opts.sessionsReviewing,
67
+ filesTouched: [],
68
+ turns: [],
69
+ abortController: opts.abortController,
70
+ priorMtime: opts.priorMtime,
71
+ }
72
+ registerTask(task, setAppState)
73
+ return id
74
+ }
75
+
76
+ export function addDreamTurn(
77
+ taskId: string,
78
+ turn: DreamTurn,
79
+ touchedPaths: string[],
80
+ setAppState: SetAppState,
81
+ ): void {
82
+ updateTaskState<DreamTaskState>(taskId, setAppState, task => {
83
+ const seen = new Set(task.filesTouched)
84
+ const newTouched = touchedPaths.filter(p => !seen.has(p) && seen.add(p))
85
+ // Skip the update entirely if the turn is empty AND nothing new was
86
+ // touched. Avoids re-rendering on pure no-ops.
87
+ if (
88
+ turn.text === '' &&
89
+ turn.toolUseCount === 0 &&
90
+ newTouched.length === 0
91
+ ) {
92
+ return task
93
+ }
94
+ return {
95
+ ...task,
96
+ phase: newTouched.length > 0 ? 'updating' : task.phase,
97
+ filesTouched:
98
+ newTouched.length > 0
99
+ ? [...task.filesTouched, ...newTouched]
100
+ : task.filesTouched,
101
+ turns: task.turns.slice(-(MAX_TURNS - 1)).concat(turn),
102
+ }
103
+ })
104
+ }
105
+
106
+ export function completeDreamTask(
107
+ taskId: string,
108
+ setAppState: SetAppState,
109
+ ): void {
110
+ // notified: true immediately — dream has no model-facing notification path
111
+ // (it's UI-only), and eviction requires terminal + notified. The inline
112
+ // appendSystemMessage completion note IS the user surface.
113
+ updateTaskState<DreamTaskState>(taskId, setAppState, task => ({
114
+ ...task,
115
+ status: 'completed',
116
+ endTime: Date.now(),
117
+ notified: true,
118
+ abortController: undefined,
119
+ }))
120
+ }
121
+
122
+ export function failDreamTask(taskId: string, setAppState: SetAppState): void {
123
+ updateTaskState<DreamTaskState>(taskId, setAppState, task => ({
124
+ ...task,
125
+ status: 'failed',
126
+ endTime: Date.now(),
127
+ notified: true,
128
+ abortController: undefined,
129
+ }))
130
+ }
131
+
132
+ export const DreamTask: Task = {
133
+ name: 'DreamTask',
134
+ type: 'dream',
135
+
136
+ async kill(taskId, setAppState) {
137
+ let priorMtime: number | undefined
138
+ updateTaskState<DreamTaskState>(taskId, setAppState, task => {
139
+ if (task.status !== 'running') return task
140
+ task.abortController?.abort()
141
+ priorMtime = task.priorMtime
142
+ return {
143
+ ...task,
144
+ status: 'killed',
145
+ endTime: Date.now(),
146
+ notified: true,
147
+ abortController: undefined,
148
+ }
149
+ })
150
+ // Rewind the lock mtime so the next session can retry. Same path as the
151
+ // fork-failure catch in autoDream.ts. If updateTaskState was a no-op
152
+ // (already terminal), priorMtime stays undefined and we skip.
153
+ if (priorMtime !== undefined) {
154
+ await rollbackConsolidationLock(priorMtime)
155
+ }
156
+ },
157
+ }
@@ -0,0 +1,126 @@
1
+ /**
2
+ * InProcessTeammateTask - Manages in-process teammate lifecycle
3
+ *
4
+ * This component implements the Task interface for in-process teammates.
5
+ * Unlike LocalAgentTask (background agents), in-process teammates:
6
+ * 1. Run in the same Node.js process using AsyncLocalStorage for isolation
7
+ * 2. Have team-aware identity (agentName@teamName)
8
+ * 3. Support plan mode approval flow
9
+ * 4. Can be idle (waiting for work) or active (processing)
10
+ */
11
+
12
+ import { isTerminalTaskStatus, type SetAppState, type Task, type TaskStateBase } from '../../Task.js';
13
+ import type { Message } from '../../types/message.js';
14
+ import { logForDebugging } from '../../utils/debug.js';
15
+ import { createUserMessage } from '../../utils/messages.js';
16
+ import { killInProcessTeammate } from '../../utils/swarm/spawnInProcess.js';
17
+ import { updateTaskState } from '../../utils/task/framework.js';
18
+ import type { InProcessTeammateTaskState } from './types.js';
19
+ import { appendCappedMessage, isInProcessTeammateTask } from './types.js';
20
+
21
+ /**
22
+ * InProcessTeammateTask - Handles in-process teammate execution.
23
+ */
24
+ export const InProcessTeammateTask: Task = {
25
+ name: 'InProcessTeammateTask',
26
+ type: 'in_process_teammate',
27
+ async kill(taskId, setAppState) {
28
+ killInProcessTeammate(taskId, setAppState);
29
+ }
30
+ };
31
+
32
+ /**
33
+ * Request shutdown for a teammate.
34
+ */
35
+ export function requestTeammateShutdown(taskId: string, setAppState: SetAppState): void {
36
+ updateTaskState<InProcessTeammateTaskState>(taskId, setAppState, task => {
37
+ if (task.status !== 'running' || task.shutdownRequested) {
38
+ return task;
39
+ }
40
+ return {
41
+ ...task,
42
+ shutdownRequested: true
43
+ };
44
+ });
45
+ }
46
+
47
+ /**
48
+ * Append a message to a teammate's conversation history.
49
+ * Used for zoomed view to show the teammate's conversation.
50
+ */
51
+ export function appendTeammateMessage(taskId: string, message: Message, setAppState: SetAppState): void {
52
+ updateTaskState<InProcessTeammateTaskState>(taskId, setAppState, task => {
53
+ if (task.status !== 'running') {
54
+ return task;
55
+ }
56
+ return {
57
+ ...task,
58
+ messages: appendCappedMessage(task.messages, message)
59
+ };
60
+ });
61
+ }
62
+
63
+ /**
64
+ * Inject a user message to a teammate's pending queue.
65
+ * Used when viewing a teammate's transcript to send typed messages to them.
66
+ * Also adds the message to task.messages so it appears immediately in the transcript.
67
+ */
68
+ export function injectUserMessageToTeammate(taskId: string, message: string, setAppState: SetAppState): void {
69
+ updateTaskState<InProcessTeammateTaskState>(taskId, setAppState, task => {
70
+ // Allow message injection when teammate is running or idle (waiting for input)
71
+ // Only reject if teammate is in a terminal state
72
+ if (isTerminalTaskStatus(task.status)) {
73
+ logForDebugging(`Dropping message for teammate task ${taskId}: task status is "${task.status}"`);
74
+ return task;
75
+ }
76
+ return {
77
+ ...task,
78
+ pendingUserMessages: [...task.pendingUserMessages, message],
79
+ messages: appendCappedMessage(task.messages, createUserMessage({
80
+ content: message
81
+ }))
82
+ };
83
+ });
84
+ }
85
+
86
+ /**
87
+ * Get teammate task by agent ID from AppState.
88
+ * Prefers running tasks over killed/completed ones in case multiple tasks
89
+ * with the same agentId exist.
90
+ * Returns undefined if not found.
91
+ */
92
+ export function findTeammateTaskByAgentId(agentId: string, tasks: Record<string, TaskStateBase>): InProcessTeammateTaskState | undefined {
93
+ let fallback: InProcessTeammateTaskState | undefined;
94
+ for (const task of Object.values(tasks)) {
95
+ if (isInProcessTeammateTask(task) && task.identity.agentId === agentId) {
96
+ // Prefer running tasks in case old killed tasks still exist in AppState
97
+ // alongside new running ones with the same agentId
98
+ if (task.status === 'running') {
99
+ return task;
100
+ }
101
+ // Keep first match as fallback in case no running task exists
102
+ if (!fallback) {
103
+ fallback = task;
104
+ }
105
+ }
106
+ }
107
+ return fallback;
108
+ }
109
+
110
+ /**
111
+ * Get all in-process teammate tasks from AppState.
112
+ */
113
+ export function getAllInProcessTeammateTasks(tasks: Record<string, TaskStateBase>): InProcessTeammateTaskState[] {
114
+ return Object.values(tasks).filter(isInProcessTeammateTask);
115
+ }
116
+
117
+ /**
118
+ * Get running in-process teammates sorted alphabetically by agentName.
119
+ * Shared between TeammateSpinnerTree display, PromptInput footer selector,
120
+ * and useBackgroundTaskNavigation — selectedIPAgentIndex maps into this
121
+ * array, so all three must agree on sort order.
122
+ */
123
+ export function getRunningTeammatesSorted(tasks: Record<string, TaskStateBase>): InProcessTeammateTaskState[] {
124
+ return getAllInProcessTeammateTasks(tasks).filter(t => t.status === 'running').sort((a, b) => a.identity.agentName.localeCompare(b.identity.agentName));
125
+ }
126
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJpc1Rlcm1pbmFsVGFza1N0YXR1cyIsIlNldEFwcFN0YXRlIiwiVGFzayIsIlRhc2tTdGF0ZUJhc2UiLCJNZXNzYWdlIiwibG9nRm9yRGVidWdnaW5nIiwiY3JlYXRlVXNlck1lc3NhZ2UiLCJraWxsSW5Qcm9jZXNzVGVhbW1hdGUiLCJ1cGRhdGVUYXNrU3RhdGUiLCJJblByb2Nlc3NUZWFtbWF0ZVRhc2tTdGF0ZSIsImFwcGVuZENhcHBlZE1lc3NhZ2UiLCJpc0luUHJvY2Vzc1RlYW1tYXRlVGFzayIsIkluUHJvY2Vzc1RlYW1tYXRlVGFzayIsIm5hbWUiLCJ0eXBlIiwia2lsbCIsInRhc2tJZCIsInNldEFwcFN0YXRlIiwicmVxdWVzdFRlYW1tYXRlU2h1dGRvd24iLCJ0YXNrIiwic3RhdHVzIiwic2h1dGRvd25SZXF1ZXN0ZWQiLCJhcHBlbmRUZWFtbWF0ZU1lc3NhZ2UiLCJtZXNzYWdlIiwibWVzc2FnZXMiLCJpbmplY3RVc2VyTWVzc2FnZVRvVGVhbW1hdGUiLCJwZW5kaW5nVXNlck1lc3NhZ2VzIiwiY29udGVudCIsImZpbmRUZWFtbWF0ZVRhc2tCeUFnZW50SWQiLCJhZ2VudElkIiwidGFza3MiLCJSZWNvcmQiLCJmYWxsYmFjayIsIk9iamVjdCIsInZhbHVlcyIsImlkZW50aXR5IiwiZ2V0QWxsSW5Qcm9jZXNzVGVhbW1hdGVUYXNrcyIsImZpbHRlciIsImdldFJ1bm5pbmdUZWFtbWF0ZXNTb3J0ZWQiLCJ0Iiwic29ydCIsImEiLCJiIiwiYWdlbnROYW1lIiwibG9jYWxlQ29tcGFyZSJdLCJzb3VyY2VzIjpbIkluUHJvY2Vzc1RlYW1tYXRlVGFzay50c3giXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBJblByb2Nlc3NUZWFtbWF0ZVRhc2sgLSBNYW5hZ2VzIGluLXByb2Nlc3MgdGVhbW1hdGUgbGlmZWN5Y2xlXG4gKlxuICogVGhpcyBjb21wb25lbnQgaW1wbGVtZW50cyB0aGUgVGFzayBpbnRlcmZhY2UgZm9yIGluLXByb2Nlc3MgdGVhbW1hdGVzLlxuICogVW5saWtlIExvY2FsQWdlbnRUYXNrIChiYWNrZ3JvdW5kIGFnZW50cyksIGluLXByb2Nlc3MgdGVhbW1hdGVzOlxuICogMS4gUnVuIGluIHRoZSBzYW1lIE5vZGUuanMgcHJvY2VzcyB1c2luZyBBc3luY0xvY2FsU3RvcmFnZSBmb3IgaXNvbGF0aW9uXG4gKiAyLiBIYXZlIHRlYW0tYXdhcmUgaWRlbnRpdHkgKGFnZW50TmFtZUB0ZWFtTmFtZSlcbiAqIDMuIFN1cHBvcnQgcGxhbiBtb2RlIGFwcHJvdmFsIGZsb3dcbiAqIDQuIENhbiBiZSBpZGxlICh3YWl0aW5nIGZvciB3b3JrKSBvciBhY3RpdmUgKHByb2Nlc3NpbmcpXG4gKi9cblxuaW1wb3J0IHtcbiAgaXNUZXJtaW5hbFRhc2tTdGF0dXMsXG4gIHR5cGUgU2V0QXBwU3RhdGUsXG4gIHR5cGUgVGFzayxcbiAgdHlwZSBUYXNrU3RhdGVCYXNlLFxufSBmcm9tICcuLi8uLi9UYXNrLmpzJ1xuaW1wb3J0IHR5cGUgeyBNZXNzYWdlIH0gZnJvbSAnLi4vLi4vdHlwZXMvbWVzc2FnZS5qcydcbmltcG9ydCB7IGxvZ0ZvckRlYnVnZ2luZyB9IGZyb20gJy4uLy4uL3V0aWxzL2RlYnVnLmpzJ1xuaW1wb3J0IHsgY3JlYXRlVXNlck1lc3NhZ2UgfSBmcm9tICcuLi8uLi91dGlscy9tZXNzYWdlcy5qcydcbmltcG9ydCB7IGtpbGxJblByb2Nlc3NUZWFtbWF0ZSB9IGZyb20gJy4uLy4uL3V0aWxzL3N3YXJtL3NwYXduSW5Qcm9jZXNzLmpzJ1xuaW1wb3J0IHsgdXBkYXRlVGFza1N0YXRlIH0gZnJvbSAnLi4vLi4vdXRpbHMvdGFzay9mcmFtZXdvcmsuanMnXG5pbXBvcnQgdHlwZSB7IEluUHJvY2Vzc1RlYW1tYXRlVGFza1N0YXRlIH0gZnJvbSAnLi90eXBlcy5qcydcbmltcG9ydCB7IGFwcGVuZENhcHBlZE1lc3NhZ2UsIGlzSW5Qcm9jZXNzVGVhbW1hdGVUYXNrIH0gZnJvbSAnLi90eXBlcy5qcydcblxuLyoqXG4gKiBJblByb2Nlc3NUZWFtbWF0ZVRhc2sgLSBIYW5kbGVzIGluLXByb2Nlc3MgdGVhbW1hdGUgZXhlY3V0aW9uLlxuICovXG5leHBvcnQgY29uc3QgSW5Qcm9jZXNzVGVhbW1hdGVUYXNrOiBUYXNrID0ge1xuICBuYW1lOiAnSW5Qcm9jZXNzVGVhbW1hdGVUYXNrJyxcbiAgdHlwZTogJ2luX3Byb2Nlc3NfdGVhbW1hdGUnLFxuICBhc3luYyBraWxsKHRhc2tJZCwgc2V0QXBwU3RhdGUpIHtcbiAgICBraWxsSW5Qcm9jZXNzVGVhbW1hdGUodGFza0lkLCBzZXRBcHBTdGF0ZSlcbiAgfSxcbn1cblxuLyoqXG4gKiBSZXF1ZXN0IHNodXRkb3duIGZvciBhIHRlYW1tYXRlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVxdWVzdFRlYW1tYXRlU2h1dGRvd24oXG4gIHRhc2tJZDogc3RyaW5nLFxuICBzZXRBcHBTdGF0ZTogU2V0QXBwU3RhdGUsXG4pOiB2b2lkIHtcbiAgdXBkYXRlVGFza1N0YXRlPEluUHJvY2Vzc1RlYW1tYXRlVGFza1N0YXRlPih0YXNrSWQsIHNldEFwcFN0YXRlLCB0YXNrID0+IHtcbiAgICBpZiAodGFzay5zdGF0dXMgIT09ICdydW5uaW5nJyB8fCB0YXNrLnNodXRkb3duUmVxdWVzdGVkKSB7XG4gICAgICByZXR1cm4gdGFza1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAuLi50YXNrLFxuICAgICAgc2h1dGRvd25SZXF1ZXN0ZWQ6IHRydWUsXG4gICAgfVxuICB9KVxufVxuXG4vKipcbiAqIEFwcGVuZCBhIG1lc3NhZ2UgdG8gYSB0ZWFtbWF0ZSdzIGNvbnZlcnNhdGlvbiBoaXN0b3J5LlxuICogVXNlZCBmb3Igem9vbWVkIHZpZXcgdG8gc2hvdyB0aGUgdGVhbW1hdGUncyBjb252ZXJzYXRpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBlbmRUZWFtbWF0ZU1lc3NhZ2UoXG4gIHRhc2tJZDogc3RyaW5nLFxuICBtZXNzYWdlOiBNZXNzYWdlLFxuICBzZXRBcHBTdGF0ZTogU2V0QXBwU3RhdGUsXG4pOiB2b2lkIHtcbiAgdXBkYXRlVGFza1N0YXRlPEluUHJvY2Vzc1RlYW1tYXRlVGFza1N0YXRlPih0YXNrSWQsIHNldEFwcFN0YXRlLCB0YXNrID0+IHtcbiAgICBpZiAodGFzay5zdGF0dXMgIT09ICdydW5uaW5nJykge1xuICAgICAgcmV0dXJuIHRhc2tcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4udGFzayxcbiAgICAgIG1lc3NhZ2VzOiBhcHBlbmRDYXBwZWRNZXNzYWdlKHRhc2subWVzc2FnZXMsIG1lc3NhZ2UpLFxuICAgIH1cbiAgfSlcbn1cblxuLyoqXG4gKiBJbmplY3QgYSB1c2VyIG1lc3NhZ2UgdG8gYSB0ZWFtbWF0ZSdzIHBlbmRpbmcgcXVldWUuXG4gKiBVc2VkIHdoZW4gdmlld2luZyBhIHRlYW1tYXRlJ3MgdHJhbnNjcmlwdCB0byBzZW5kIHR5cGVkIG1lc3NhZ2VzIHRvIHRoZW0uXG4gKiBBbHNvIGFkZHMgdGhlIG1lc3NhZ2UgdG8gdGFzay5tZXNzYWdlcyBzbyBpdCBhcHBlYXJzIGltbWVkaWF0ZWx5IGluIHRoZSB0cmFuc2NyaXB0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gaW5qZWN0VXNlck1lc3NhZ2VUb1RlYW1tYXRlKFxuICB0YXNrSWQ6IHN0cmluZyxcbiAgbWVzc2FnZTogc3RyaW5nLFxuICBzZXRBcHBTdGF0ZTogU2V0QXBwU3RhdGUsXG4pOiB2b2lkIHtcbiAgdXBkYXRlVGFza1N0YXRlPEluUHJvY2Vzc1RlYW1tYXRlVGFza1N0YXRlPih0YXNrSWQsIHNldEFwcFN0YXRlLCB0YXNrID0+IHtcbiAgICAvLyBBbGxvdyBtZXNzYWdlIGluamVjdGlvbiB3aGVuIHRlYW1tYXRlIGlzIHJ1bm5pbmcgb3IgaWRsZSAod2FpdGluZyBmb3IgaW5wdXQpXG4gICAgLy8gT25seSByZWplY3QgaWYgdGVhbW1hdGUgaXMgaW4gYSB0ZXJtaW5hbCBzdGF0ZVxuICAgIGlmIChpc1Rlcm1pbmFsVGFza1N0YXR1cyh0YXNrLnN0YXR1cykpIHtcbiAgICAgIGxvZ0ZvckRlYnVnZ2luZyhcbiAgICAgICAgYERyb3BwaW5nIG1lc3NhZ2UgZm9yIHRlYW1tYXRlIHRhc2sgJHt0YXNrSWR9OiB0YXNrIHN0YXR1cyBpcyBcIiR7dGFzay5zdGF0dXN9XCJgLFxuICAgICAgKVxuICAgICAgcmV0dXJuIHRhc2tcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4udGFzayxcbiAgICAgIHBlbmRpbmdVc2VyTWVzc2FnZXM6IFsuLi50YXNrLnBlbmRpbmdVc2VyTWVzc2FnZXMsIG1lc3NhZ2VdLFxuICAgICAgbWVzc2FnZXM6IGFwcGVuZENhcHBlZE1lc3NhZ2UoXG4gICAgICAgIHRhc2subWVzc2FnZXMsXG4gICAgICAgIGNyZWF0ZVVzZXJNZXNzYWdlKHsgY29udGVudDogbWVzc2FnZSB9KSxcbiAgICAgICksXG4gICAgfVxuICB9KVxufVxuXG4vKipcbiAqIEdldCB0ZWFtbWF0ZSB0YXNrIGJ5IGFnZW50IElEIGZyb20gQXBwU3RhdGUuXG4gKiBQcmVmZXJzIHJ1bm5pbmcgdGFza3Mgb3ZlciBraWxsZWQvY29tcGxldGVkIG9uZXMgaW4gY2FzZSBtdWx0aXBsZSB0YXNrc1xuICogd2l0aCB0aGUgc2FtZSBhZ2VudElkIGV4aXN0LlxuICogUmV0dXJucyB1bmRlZmluZWQgaWYgbm90IGZvdW5kLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZFRlYW1tYXRlVGFza0J5QWdlbnRJZChcbiAgYWdlbnRJZDogc3RyaW5nLFxuICB0YXNrczogUmVjb3JkPHN0cmluZywgVGFza1N0YXRlQmFzZT4sXG4pOiBJblByb2Nlc3NUZWFtbWF0ZVRhc2tTdGF0ZSB8IHVuZGVmaW5lZCB7XG4gIGxldCBmYWxsYmFjazogSW5Qcm9jZXNzVGVhbW1hdGVUYXNrU3RhdGUgfCB1bmRlZmluZWRcbiAgZm9yIChjb25zdCB0YXNrIG9mIE9iamVjdC52YWx1ZXModGFza3MpKSB7XG4gICAgaWYgKGlzSW5Qcm9jZXNzVGVhbW1hdGVUYXNrKHRhc2spICYmIHRhc2suaWRlbnRpdHkuYWdlbnRJZCA9PT0gYWdlbnRJZCkge1xuICAgICAgLy8gUHJlZmVyIHJ1bm5pbmcgdGFza3MgaW4gY2FzZSBvbGQga2lsbGVkIHRhc2tzIHN0aWxsIGV4aXN0IGluIEFwcFN0YXRlXG4gICAgICAvLyBhbG9uZ3NpZGUgbmV3IHJ1bm5pbmcgb25lcyB3aXRoIHRoZSBzYW1lIGFnZW50SWRcbiAgICAgIGlmICh0YXNrLnN0YXR1cyA9PT0gJ3J1bm5pbmcnKSB7XG4gICAgICAgIHJldHVybiB0YXNrXG4gICAgICB9XG4gICAgICAvLyBLZWVwIGZpcnN0IG1hdGNoIGFzIGZhbGxiYWNrIGluIGNhc2Ugbm8gcnVubmluZyB0YXNrIGV4aXN0c1xuICAgICAgaWYgKCFmYWxsYmFjaykge1xuICAgICAgICBmYWxsYmFjayA9IHRhc2tcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZhbGxiYWNrXG59XG5cbi8qKlxuICogR2V0IGFsbCBpbi1wcm9jZXNzIHRlYW1tYXRlIHRhc2tzIGZyb20gQXBwU3RhdGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRBbGxJblByb2Nlc3NUZWFtbWF0ZVRhc2tzKFxuICB0YXNrczogUmVjb3JkPHN0cmluZywgVGFza1N0YXRlQmFzZT4sXG4pOiBJblByb2Nlc3NUZWFtbWF0ZVRhc2tTdGF0ZVtdIHtcbiAgcmV0dXJuIE9iamVjdC52YWx1ZXModGFza3MpLmZpbHRlcihpc0luUHJvY2Vzc1RlYW1tYXRlVGFzaylcbn1cblxuLyoqXG4gKiBHZXQgcnVubmluZyBpbi1wcm9jZXNzIHRlYW1tYXRlcyBzb3J0ZWQgYWxwaGFiZXRpY2FsbHkgYnkgYWdlbnROYW1lLlxuICogU2hhcmVkIGJldHdlZW4gVGVhbW1hdGVTcGlubmVyVHJlZSBkaXNwbGF5LCBQcm9tcHRJbnB1dCBmb290ZXIgc2VsZWN0b3IsXG4gKiBhbmQgdXNlQmFja2dyb3VuZFRhc2tOYXZpZ2F0aW9uIOKAlCBzZWxlY3RlZElQQWdlbnRJbmRleCBtYXBzIGludG8gdGhpc1xuICogYXJyYXksIHNvIGFsbCB0aHJlZSBtdXN0IGFncmVlIG9uIHNvcnQgb3JkZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRSdW5uaW5nVGVhbW1hdGVzU29ydGVkKFxuICB0YXNrczogUmVjb3JkPHN0cmluZywgVGFza1N0YXRlQmFzZT4sXG4pOiBJblByb2Nlc3NUZWFtbWF0ZVRhc2tTdGF0ZVtdIHtcbiAgcmV0dXJuIGdldEFsbEluUHJvY2Vzc1RlYW1tYXRlVGFza3ModGFza3MpXG4gICAgLmZpbHRlcih0ID0+IHQuc3RhdHVzID09PSAncnVubmluZycpXG4gICAgLnNvcnQoKGEsIGIpID0+IGEuaWRlbnRpdHkuYWdlbnROYW1lLmxvY2FsZUNvbXBhcmUoYi5pZGVudGl0eS5hZ2VudE5hbWUpKVxufVxuIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUNFQSxvQkFBb0IsRUFDcEIsS0FBS0MsV0FBVyxFQUNoQixLQUFLQyxJQUFJLEVBQ1QsS0FBS0MsYUFBYSxRQUNiLGVBQWU7QUFDdEIsY0FBY0MsT0FBTyxRQUFRLHdCQUF3QjtBQUNyRCxTQUFTQyxlQUFlLFFBQVEsc0JBQXNCO0FBQ3RELFNBQVNDLGlCQUFpQixRQUFRLHlCQUF5QjtBQUMzRCxTQUFTQyxxQkFBcUIsUUFBUSxxQ0FBcUM7QUFDM0UsU0FBU0MsZUFBZSxRQUFRLCtCQUErQjtBQUMvRCxjQUFjQywwQkFBMEIsUUFBUSxZQUFZO0FBQzVELFNBQVNDLG1CQUFtQixFQUFFQyx1QkFBdUIsUUFBUSxZQUFZOztBQUV6RTtBQUNBO0FBQ0E7QUFDQSxPQUFPLE1BQU1DLHFCQUFxQixFQUFFVixJQUFJLEdBQUc7RUFDekNXLElBQUksRUFBRSx1QkFBdUI7RUFDN0JDLElBQUksRUFBRSxxQkFBcUI7RUFDM0IsTUFBTUMsSUFBSUEsQ0FBQ0MsTUFBTSxFQUFFQyxXQUFXLEVBQUU7SUFDOUJWLHFCQUFxQixDQUFDUyxNQUFNLEVBQUVDLFdBQVcsQ0FBQztFQUM1QztBQUNGLENBQUM7O0FBRUQ7QUFD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
@@ -0,0 +1,121 @@
1
+ import type { TaskStateBase } from '../../Task.js'
2
+ import type { AgentToolResult } from '../../tools/AgentTool/agentToolUtils.js'
3
+ import type { AgentDefinition } from '../../tools/AgentTool/loadAgentsDir.js'
4
+ import type { Message } from '../../types/message.js'
5
+ import type { PermissionMode } from '../../utils/permissions/PermissionMode.js'
6
+ import type { AgentProgress } from '../LocalAgentTask/LocalAgentTask.js'
7
+
8
+ /**
9
+ * Teammate identity stored in task state.
10
+ * Same shape as TeammateContext (runtime) but stored as plain data.
11
+ * TeammateContext is for AsyncLocalStorage; this is for AppState persistence.
12
+ */
13
+ export type TeammateIdentity = {
14
+ agentId: string // e.g., "researcher@my-team"
15
+ agentName: string // e.g., "researcher"
16
+ teamName: string
17
+ color?: string
18
+ planModeRequired: boolean
19
+ parentSessionId: string // Leader's session ID
20
+ }
21
+
22
+ export type InProcessTeammateTaskState = TaskStateBase & {
23
+ type: 'in_process_teammate'
24
+
25
+ // Identity as sub-object (matches TeammateContext shape for consistency)
26
+ // Stored as plain data in AppState, NOT a reference to AsyncLocalStorage
27
+ identity: TeammateIdentity
28
+
29
+ // Execution
30
+ prompt: string
31
+ // Optional model override for this teammate
32
+ model?: string
33
+ // Optional: Only set if teammate uses a specific agent definition
34
+ // Many teammates run as general-purpose agents without a predefined definition
35
+ selectedAgent?: AgentDefinition
36
+ abortController?: AbortController // Runtime only, not serialized to disk - kills WHOLE teammate
37
+ currentWorkAbortController?: AbortController // Runtime only - aborts current turn without killing teammate
38
+ unregisterCleanup?: () => void // Runtime only
39
+
40
+ // Plan mode approval tracking (planModeRequired is in identity)
41
+ awaitingPlanApproval: boolean
42
+
43
+ // Permission mode for this teammate (cycled independently via Shift+Tab when viewing)
44
+ permissionMode: PermissionMode
45
+
46
+ // State
47
+ error?: string
48
+ result?: AgentToolResult // Reuse existing type since teammates run via runAgent()
49
+ progress?: AgentProgress
50
+
51
+ // Conversation history for zoomed view (NOT mailbox messages)
52
+ // Mailbox messages are stored separately in teamContext.inProcessMailboxes
53
+ messages?: Message[]
54
+
55
+ // Tool use IDs currently being executed (for animation in transcript view)
56
+ inProgressToolUseIDs?: Set<string>
57
+
58
+ // Queue of user messages to deliver when viewing teammate transcript
59
+ pendingUserMessages: string[]
60
+
61
+ // UI: random spinner verbs (stable across re-renders, shared between components)
62
+ spinnerVerb?: string
63
+ pastTenseVerb?: string
64
+
65
+ // Lifecycle
66
+ isIdle: boolean
67
+ shutdownRequested: boolean
68
+
69
+ // Callbacks to notify when teammate becomes idle (runtime only)
70
+ // Used by leader to efficiently wait without polling
71
+ onIdleCallbacks?: Array<() => void>
72
+
73
+ // Progress tracking (for computing deltas in notifications)
74
+ lastReportedToolCount: number
75
+ lastReportedTokenCount: number
76
+ }
77
+
78
+ export function isInProcessTeammateTask(
79
+ task: unknown,
80
+ ): task is InProcessTeammateTaskState {
81
+ return (
82
+ typeof task === 'object' &&
83
+ task !== null &&
84
+ 'type' in task &&
85
+ task.type === 'in_process_teammate'
86
+ )
87
+ }
88
+
89
+ /**
90
+ * Cap on the number of messages kept in task.messages (the AppState UI mirror).
91
+ *
92
+ * task.messages exists purely for the zoomed transcript dialog, which only
93
+ * needs recent context. The full conversation lives in the local allMessages
94
+ * array (inProcessRunner) and on disk at the agent transcript path.
95
+ *
96
+ * BQ analysis (round 9, 2026-03-20) showed ~20MB RSS per agent at 500+ turn
97
+ * sessions and ~125MB per concurrent agent in swarm bursts. Whale session
98
+ * 9a990de8 launched 292 agents in 2 minutes and reached 36.8GB. The dominant
99
+ * cost is this array holding a second full copy of every message.
100
+ */
101
+ export const TEAMMATE_MESSAGES_UI_CAP = 50
102
+
103
+ /**
104
+ * Append an item to a message array, capping the result at
105
+ * TEAMMATE_MESSAGES_UI_CAP entries by dropping the oldest. Always returns
106
+ * a new array (AppState immutability).
107
+ */
108
+ export function appendCappedMessage<T>(
109
+ prev: readonly T[] | undefined,
110
+ item: T,
111
+ ): T[] {
112
+ if (prev === undefined || prev.length === 0) {
113
+ return [item]
114
+ }
115
+ if (prev.length >= TEAMMATE_MESSAGES_UI_CAP) {
116
+ const next = prev.slice(-(TEAMMATE_MESSAGES_UI_CAP - 1))
117
+ next.push(item)
118
+ return next
119
+ }
120
+ return [...prev, item]
121
+ }