@oharness/engine 0.9.3 → 0.11.0

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 (170) hide show
  1. package/dist/acp/claude.d.ts +34 -0
  2. package/dist/acp/claude.js +122 -0
  3. package/dist/acp/claude.js.map +1 -0
  4. package/dist/acp/client.d.ts +193 -0
  5. package/dist/acp/client.js +279 -0
  6. package/dist/acp/client.js.map +1 -0
  7. package/dist/acp/runner.d.ts +80 -0
  8. package/dist/acp/runner.js +159 -0
  9. package/dist/acp/runner.js.map +1 -0
  10. package/dist/agent/agent.d.ts +258 -2
  11. package/dist/agent/agent.js +1010 -53
  12. package/dist/agent/agent.js.map +1 -1
  13. package/dist/agent/background.d.ts +135 -0
  14. package/dist/agent/background.js +307 -0
  15. package/dist/agent/background.js.map +1 -0
  16. package/dist/agent/compaction.d.ts +7 -0
  17. package/dist/agent/compaction.js +11 -3
  18. package/dist/agent/compaction.js.map +1 -1
  19. package/dist/agent/goal.d.ts +36 -0
  20. package/dist/agent/goal.js +71 -0
  21. package/dist/agent/goal.js.map +1 -0
  22. package/dist/agent/hooks.js +6 -6
  23. package/dist/agent/hooks.js.map +1 -1
  24. package/dist/agent/permissions.d.ts +6 -0
  25. package/dist/agent/permissions.js +2 -1
  26. package/dist/agent/permissions.js.map +1 -1
  27. package/dist/agent/session.d.ts +38 -0
  28. package/dist/agent/session.js +91 -2
  29. package/dist/agent/session.js.map +1 -1
  30. package/dist/agent/store.d.ts +25 -0
  31. package/dist/agent/store.js +21 -0
  32. package/dist/agent/store.js.map +1 -1
  33. package/dist/agent/subagent.d.ts +21 -0
  34. package/dist/agent/subagent.js +17 -1
  35. package/dist/agent/subagent.js.map +1 -1
  36. package/dist/agent/workspace.d.ts +9 -0
  37. package/dist/agent/workspace.js +59 -5
  38. package/dist/agent/workspace.js.map +1 -1
  39. package/dist/auth/index.d.ts +3 -1
  40. package/dist/auth/index.js +3 -1
  41. package/dist/auth/index.js.map +1 -1
  42. package/dist/auth/manager.d.ts +9 -0
  43. package/dist/auth/manager.js +71 -6
  44. package/dist/auth/manager.js.map +1 -1
  45. package/dist/auth/oauth.d.ts +33 -0
  46. package/dist/auth/oauth.js +59 -8
  47. package/dist/auth/oauth.js.map +1 -1
  48. package/dist/auth/providers/account.js +5 -4
  49. package/dist/auth/providers/account.js.map +1 -1
  50. package/dist/auth/providers/anthropic.d.ts +25 -5
  51. package/dist/auth/providers/anthropic.js +47 -6
  52. package/dist/auth/providers/anthropic.js.map +1 -1
  53. package/dist/auth/providers/chatgpt.d.ts +8 -0
  54. package/dist/auth/providers/chatgpt.js +180 -0
  55. package/dist/auth/providers/chatgpt.js.map +1 -0
  56. package/dist/auth/providers/openrouter.d.ts +2 -0
  57. package/dist/auth/providers/openrouter.js +101 -0
  58. package/dist/auth/providers/openrouter.js.map +1 -0
  59. package/dist/auth/types.d.ts +15 -0
  60. package/dist/auth/types.js.map +1 -1
  61. package/dist/browser/index.d.ts +1 -1
  62. package/dist/browser/plugin.d.ts +6 -1
  63. package/dist/browser/plugin.js.map +1 -1
  64. package/dist/browser/session.d.ts +47 -0
  65. package/dist/browser/session.js +177 -2
  66. package/dist/browser/session.js.map +1 -1
  67. package/dist/browser/tools.js +142 -18
  68. package/dist/browser/tools.js.map +1 -1
  69. package/dist/computer/arbiter.d.ts +69 -0
  70. package/dist/computer/arbiter.js +128 -0
  71. package/dist/computer/arbiter.js.map +1 -0
  72. package/dist/computer/cua-driver.d.ts +174 -0
  73. package/dist/computer/cua-driver.js +597 -0
  74. package/dist/computer/cua-driver.js.map +1 -0
  75. package/dist/computer/helper-client.d.ts +80 -0
  76. package/dist/computer/helper-client.js +166 -0
  77. package/dist/computer/helper-client.js.map +1 -0
  78. package/dist/computer/index.d.ts +16 -0
  79. package/dist/computer/index.js +9 -0
  80. package/dist/computer/index.js.map +1 -0
  81. package/dist/computer/mode.d.ts +34 -0
  82. package/dist/computer/mode.js +52 -0
  83. package/dist/computer/mode.js.map +1 -0
  84. package/dist/computer/plugin.d.ts +24 -0
  85. package/dist/computer/plugin.js +17 -0
  86. package/dist/computer/plugin.js.map +1 -0
  87. package/dist/computer/policy.d.ts +29 -0
  88. package/dist/computer/policy.js +127 -0
  89. package/dist/computer/policy.js.map +1 -0
  90. package/dist/computer/session.d.ts +228 -0
  91. package/dist/computer/session.js +493 -0
  92. package/dist/computer/session.js.map +1 -0
  93. package/dist/computer/target.d.ts +206 -0
  94. package/dist/computer/target.js +31 -0
  95. package/dist/computer/target.js.map +1 -0
  96. package/dist/computer/tools.d.ts +8 -0
  97. package/dist/computer/tools.js +664 -0
  98. package/dist/computer/tools.js.map +1 -0
  99. package/dist/config.d.ts +7 -0
  100. package/dist/config.js.map +1 -1
  101. package/dist/core/tokens.js +4 -0
  102. package/dist/core/tokens.js.map +1 -1
  103. package/dist/core/types.d.ts +16 -1
  104. package/dist/core/types.js.map +1 -1
  105. package/dist/harness.d.ts +128 -1
  106. package/dist/harness.js +287 -30
  107. package/dist/harness.js.map +1 -1
  108. package/dist/index.d.ts +3 -0
  109. package/dist/index.js +2 -0
  110. package/dist/index.js.map +1 -1
  111. package/dist/mcp/manager.d.ts +15 -0
  112. package/dist/mcp/manager.js +28 -1
  113. package/dist/mcp/manager.js.map +1 -1
  114. package/dist/mcp/transport.js +3 -0
  115. package/dist/mcp/transport.js.map +1 -1
  116. package/dist/providers/catalog.js +6 -0
  117. package/dist/providers/catalog.js.map +1 -1
  118. package/dist/providers/catalog.json +14 -3
  119. package/dist/providers/discovery.js +10 -2
  120. package/dist/providers/discovery.js.map +1 -1
  121. package/dist/providers/models-dev.d.ts +15 -0
  122. package/dist/providers/models-dev.js +15 -0
  123. package/dist/providers/models-dev.js.map +1 -1
  124. package/dist/providers/models-dev.json +114 -102
  125. package/dist/providers/piai.d.ts +54 -2
  126. package/dist/providers/piai.js +154 -9
  127. package/dist/providers/piai.js.map +1 -1
  128. package/dist/providers/registry.d.ts +16 -1
  129. package/dist/providers/registry.js +42 -11
  130. package/dist/providers/registry.js.map +1 -1
  131. package/dist/providers/types.d.ts +6 -0
  132. package/dist/providers/types.js.map +1 -1
  133. package/dist/runtime-plugins/builtin/studio.d.ts +7 -0
  134. package/dist/runtime-plugins/builtin/studio.js +69 -4
  135. package/dist/runtime-plugins/builtin/studio.js.map +1 -1
  136. package/dist/runtime-plugins/cloud-connector.js +5 -0
  137. package/dist/runtime-plugins/cloud-connector.js.map +1 -1
  138. package/dist/schedule/scheduler.d.ts +38 -0
  139. package/dist/schedule/scheduler.js +101 -1
  140. package/dist/schedule/scheduler.js.map +1 -1
  141. package/dist/tools/builtin/bash.d.ts +6 -0
  142. package/dist/tools/builtin/bash.js +8 -11
  143. package/dist/tools/builtin/bash.js.map +1 -1
  144. package/dist/tools/builtin/recall.js +4 -0
  145. package/dist/tools/builtin/recall.js.map +1 -1
  146. package/dist/tools/builtin/routine.d.ts +9 -0
  147. package/dist/tools/builtin/routine.js +23 -2
  148. package/dist/tools/builtin/routine.js.map +1 -1
  149. package/dist/tools/builtin/task-control.d.ts +21 -0
  150. package/dist/tools/builtin/task-control.js +120 -0
  151. package/dist/tools/builtin/task-control.js.map +1 -0
  152. package/dist/tools/builtin/task.js +50 -9
  153. package/dist/tools/builtin/task.js.map +1 -1
  154. package/dist/tools/builtin/todo.d.ts +1 -1
  155. package/dist/tools/builtin/worktree.d.ts +10 -0
  156. package/dist/tools/builtin/worktree.js +52 -0
  157. package/dist/tools/builtin/worktree.js.map +1 -0
  158. package/dist/tools/define.d.ts +4 -1
  159. package/dist/tools/define.js +2 -0
  160. package/dist/tools/define.js.map +1 -1
  161. package/dist/tools/types.d.ts +112 -0
  162. package/dist/tools/types.js.map +1 -1
  163. package/dist/util/shell.d.ts +30 -0
  164. package/dist/util/shell.js +70 -0
  165. package/dist/util/shell.js.map +1 -1
  166. package/dist/worktree/index.d.ts +109 -0
  167. package/dist/worktree/index.js +463 -0
  168. package/dist/worktree/index.js.map +1 -0
  169. package/package.json +3 -3
  170. package/skills/media-generation/SKILL.md +22 -1
@@ -0,0 +1,80 @@
1
+ import type { PermissionAnswer } from "../agent/permissions.ts";
2
+ import type { AcpFileSystem, AcpMcpServer, AcpStopReason, AcpUpdate } from "./client.ts";
3
+ /**
4
+ * A subagent whose loop is someone else's: an external agent reached over ACP.
5
+ *
6
+ * Declared on a subagent definition. The harness keeps everything around the
7
+ * run — the `task` tool, background tasks, worktrees, permission cards — and
8
+ * hands the turn itself to the agent named here.
9
+ */
10
+ export interface AcpRuntime {
11
+ kind: "acp";
12
+ command: string;
13
+ args?: string[];
14
+ env?: Record<string, string>;
15
+ /**
16
+ * What to tell the person when the agent says it needs signing in. The
17
+ * agent's own login is the only one offered: this is the sentence that
18
+ * sends them to it.
19
+ */
20
+ signInHint?: string;
21
+ /**
22
+ * Why this agent cannot run here — Node too old, say. Set at detection, so
23
+ * a task gets this sentence as its answer instead of a process that dies.
24
+ */
25
+ unavailable?: string;
26
+ }
27
+ /** The agent cannot run on this machine; the message says why. */
28
+ export declare class AcpUnavailable extends Error {
29
+ constructor(message: string);
30
+ }
31
+ export declare function looksLikeSignIn(text: string): boolean;
32
+ /** The agent refused to start a session until it is signed in. */
33
+ export declare class AcpSignInRequired extends Error {
34
+ constructor(message: string);
35
+ }
36
+ export interface AcpRunOptions {
37
+ runtime: AcpRuntime;
38
+ cwd: string;
39
+ /** The prompt for a fresh session — a follow-up's carries what came before. */
40
+ prompt: string;
41
+ /**
42
+ * An earlier session of this task to pick up, and the prompt to send when
43
+ * it is picked up (the new message alone: the agent has the rest). Falls
44
+ * back to a fresh session and `prompt` when the agent cannot load it.
45
+ */
46
+ resume?: {
47
+ sessionId: string;
48
+ prompt: string;
49
+ };
50
+ /** MCP servers to give the agent, so it has this conversation's tools. */
51
+ mcpServers?: AcpMcpServer[];
52
+ /** Route the agent's file reads and writes through the workspace policy. */
53
+ fs?: AcpFileSystem;
54
+ signal?: AbortSignal;
55
+ /** Put one of the agent's tool calls to the person. */
56
+ askPermission(title: string, input: unknown, toolCallId: string): Promise<boolean | PermissionAnswer>;
57
+ /** What the agent is doing now, for a background task's status line. */
58
+ onActivity?(title: string): void;
59
+ /** Every update as it arrives, for a caller that shows the turn live. */
60
+ onUpdate?(update: AcpUpdate): void;
61
+ }
62
+ export interface AcpRunResult {
63
+ /** The agent's last say: what it wrote after its final tool call. */
64
+ text: string;
65
+ stopReason: AcpStopReason;
66
+ toolCalls: number;
67
+ /** The session this turn ran in, for the next follow-up to resume. */
68
+ sessionId: string;
69
+ /** Whether it continued an earlier session rather than starting one. */
70
+ resumed: boolean;
71
+ }
72
+ /**
73
+ * One turn of an external agent, start to finish: a process, a session, the
74
+ * prompt, and the process gone again.
75
+ *
76
+ * A process per turn rather than one kept warm: a task's follow-up may come
77
+ * after a restart, and the same path serving both is what keeps them alike.
78
+ * The conversation so far rides in the prompt instead.
79
+ */
80
+ export declare function runAcpTurn(opts: AcpRunOptions): Promise<AcpRunResult>;
@@ -0,0 +1,159 @@
1
+ import { AcpClient, AcpError, ACP_AUTH_REQUIRED, allowOnce, refuse } from "./client.js";
2
+ /** The agent cannot run on this machine; the message says why. */
3
+ export class AcpUnavailable extends Error {
4
+ constructor(message) {
5
+ super(message);
6
+ this.name = "AcpUnavailable";
7
+ }
8
+ }
9
+ /**
10
+ * Replies that mean "not signed in" whatever form they arrive in.
11
+ *
12
+ * ACP has an error code for it, and an agent may use it — or may start the
13
+ * session anyway and answer the first prompt with its own login complaint,
14
+ * as text or as an error. All of them become the same sentence pointing at
15
+ * the agent's own login, so what the person reads does not depend on which
16
+ * an adapter version happened to do.
17
+ */
18
+ const SIGN_IN_TEXT = /please run \/login|run `?claude`? (?:to )?(?:log|sign) ?in|invalid api key|not (?:logged|signed) in|authentication[_ ](?:error|required|failed)|oauth token (?:has )?expired/i;
19
+ export function looksLikeSignIn(text) {
20
+ return SIGN_IN_TEXT.test(text);
21
+ }
22
+ /** The agent refused to start a session until it is signed in. */
23
+ export class AcpSignInRequired extends Error {
24
+ constructor(message) {
25
+ super(message);
26
+ this.name = "AcpSignInRequired";
27
+ }
28
+ }
29
+ /**
30
+ * One turn of an external agent, start to finish: a process, a session, the
31
+ * prompt, and the process gone again.
32
+ *
33
+ * A process per turn rather than one kept warm: a task's follow-up may come
34
+ * after a restart, and the same path serving both is what keeps them alike.
35
+ * The conversation so far rides in the prompt instead.
36
+ */
37
+ export async function runAcpTurn(opts) {
38
+ if (opts.runtime.unavailable)
39
+ throw new AcpUnavailable(opts.runtime.unavailable);
40
+ const signIn = () => new AcpSignInRequired(opts.runtime.signInHint ?? "The agent needs signing in. Run it in a terminal, sign in there, then try again.");
41
+ // Said before anything else: the first run fetches the adapter, which can
42
+ // take half a minute with nothing else to show for it.
43
+ opts.onActivity?.("Starting the agent…");
44
+ const client = new AcpClient({
45
+ command: opts.runtime.command,
46
+ ...(opts.runtime.args ? { args: opts.runtime.args } : {}),
47
+ ...(opts.runtime.env ? { env: opts.runtime.env } : {}),
48
+ cwd: opts.cwd,
49
+ ...(opts.fs ? { fs: opts.fs } : {}),
50
+ });
51
+ // A stop is first a `session/cancel`, which lets the agent end its turn
52
+ // tidily; an agent that has not ended it a few seconds later is closed.
53
+ const kill = () => setTimeout(() => client.close(), 3_000).unref?.();
54
+ opts.signal?.addEventListener("abort", kill, { once: true });
55
+ try {
56
+ await client.initialize();
57
+ const servers = opts.mcpServers ?? [];
58
+ let sessionId;
59
+ let prompt = opts.prompt;
60
+ let resumed = false;
61
+ try {
62
+ if (opts.resume && client.capabilities.loadSession) {
63
+ try {
64
+ await client.loadSession(opts.resume.sessionId, opts.cwd, servers);
65
+ sessionId = opts.resume.sessionId;
66
+ prompt = opts.resume.prompt;
67
+ resumed = true;
68
+ }
69
+ catch (err) {
70
+ // Gone from the agent's side — cleared, or another machine's. A
71
+ // fresh session with the history in its prompt is the fallback.
72
+ if (err instanceof AcpError && err.code === ACP_AUTH_REQUIRED)
73
+ throw err;
74
+ }
75
+ }
76
+ sessionId ??= await client.newSession(opts.cwd, servers);
77
+ }
78
+ catch (err) {
79
+ if (err instanceof AcpError && (err.code === ACP_AUTH_REQUIRED || looksLikeSignIn(err.message)))
80
+ throw signIn();
81
+ throw err;
82
+ }
83
+ // Text arrives in chunks between tool calls. What the parent wants is the
84
+ // agent's conclusion, so each tool call starts a fresh segment and the
85
+ // last one with anything in it is the answer.
86
+ const segments = [""];
87
+ const titles = new Map();
88
+ let toolCalls = 0;
89
+ let stopReason;
90
+ try {
91
+ stopReason = await client.prompt(sessionId, prompt, {
92
+ onUpdate(update) {
93
+ opts.onUpdate?.(update);
94
+ switch (update.sessionUpdate) {
95
+ case "agent_message_chunk": {
96
+ const content = update.content;
97
+ if (content?.type === "text" && content.text)
98
+ segments[segments.length - 1] += content.text;
99
+ break;
100
+ }
101
+ case "tool_call": {
102
+ const call = update;
103
+ toolCalls++;
104
+ const title = call.title || call.kind || "tool";
105
+ titles.set(call.toolCallId, title);
106
+ opts.onActivity?.(title);
107
+ if (segments[segments.length - 1].trim())
108
+ segments.push("");
109
+ break;
110
+ }
111
+ case "tool_call_update": {
112
+ const call = update;
113
+ if (call.title)
114
+ titles.set(call.toolCallId, call.title);
115
+ break;
116
+ }
117
+ case "plan": {
118
+ const entries = update.entries ?? [];
119
+ const current = entries.find((entry) => entry.status === "in_progress") ?? entries[0];
120
+ if (current)
121
+ opts.onActivity?.(current.content);
122
+ break;
123
+ }
124
+ }
125
+ },
126
+ async onPermission(request) {
127
+ const title = request.toolCall.title || titles.get(request.toolCall.toolCallId) || "a tool call";
128
+ const answer = await opts.askPermission(title, request.toolCall.rawInput, request.toolCall.toolCallId);
129
+ const allowed = typeof answer === "boolean" ? answer : answer.allow;
130
+ if (!allowed)
131
+ return refuse(request.options);
132
+ // "Always" is the person's to give, and only when they gave it: it
133
+ // is remembered on the agent's side, beyond this card.
134
+ const always = typeof answer === "object" && answer.remember
135
+ ? request.options.find((option) => option.kind === "allow_always")
136
+ : undefined;
137
+ return always ? { outcome: "selected", optionId: always.optionId } : allowOnce(request.options);
138
+ },
139
+ }, opts.signal);
140
+ }
141
+ catch (err) {
142
+ // A login complaint can also come back as the prompt's error.
143
+ if (err instanceof AcpError && (err.code === ACP_AUTH_REQUIRED || looksLikeSignIn(err.message)))
144
+ throw signIn();
145
+ throw err;
146
+ }
147
+ const text = [...segments].reverse().find((segment) => segment.trim())?.trim() ?? "";
148
+ // Or as the whole of its answer, before it ever got to a tool: a short
149
+ // reply that is only a login complaint is the sign-in, not a result.
150
+ if (toolCalls === 0 && text.length < 400 && looksLikeSignIn(text))
151
+ throw signIn();
152
+ return { text, stopReason, toolCalls, sessionId, resumed };
153
+ }
154
+ finally {
155
+ opts.signal?.removeEventListener("abort", kill);
156
+ client.close();
157
+ }
158
+ }
159
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/acp/runner.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,10 @@
1
+ import type { SessionGoal } from "./goal.ts";
1
2
  import type { RuntimeAuditEvent } from "../core/audit.ts";
2
3
  import type { Message, StopReason, Usage } from "../core/types.ts";
3
4
  import type { McpManager } from "../mcp/manager.ts";
4
5
  import type { ThinkingConfig } from "../providers/types.ts";
5
6
  import type { ToolFilter, ToolRegistry } from "../tools/registry.ts";
6
- import type { SubagentRunOptions, SubagentRunResult, ToolHost, ToolProgress, ToolResult } from "../tools/types.ts";
7
+ import type { BackgroundTaskHost, BackgroundTaskView, SubagentRunOptions, SubagentRunResult, ToolHost, ToolProgress, ToolResult, WorktreeLauncher, WorktreeStartOptions, WorktreeStartResult } from "../tools/types.ts";
7
8
  import type { ArtifactDescriptor } from "../artifacts/store.ts";
8
9
  import type { Logger } from "../util/logger.ts";
9
10
  import type { WorkspacePolicy } from "./workspace.ts";
@@ -12,7 +13,8 @@ import { MemoryStore } from "./memory.ts";
12
13
  import type { ExtractedSummary, MemoryProvider, MemoryRecallItem } from "./memory-provider.ts";
13
14
  import type { CompactionOptions } from "./compaction.ts";
14
15
  import { HookRegistry } from "./hooks.ts";
15
- import type { PermissionPrompt, PermissionRequest } from "./permissions.ts";
16
+ import type { AcpFileSystem } from "../acp/client.ts";
17
+ import type { PermissionAnswer, PermissionPrompt, PermissionRequest } from "./permissions.ts";
16
18
  import type { QuestionPrompt, QuestionRequest, QuestionResult } from "../tools/questions.ts";
17
19
  import type { Session } from "./session.ts";
18
20
  import { SubagentRegistry } from "./subagent.ts";
@@ -89,6 +91,8 @@ export type AgentEvent = {
89
91
  reason?: string;
90
92
  /** Pattern written to settings, when the approval was persisted. */
91
93
  remembered?: string;
94
+ /** Held back by plan mode: the mode doing its job, not a refusal. */
95
+ plan?: boolean;
92
96
  }
93
97
  /**
94
98
  * Something the user said while the turn was already running has just been
@@ -99,6 +103,15 @@ export type AgentEvent = {
99
103
  type: "interjected";
100
104
  id: string;
101
105
  text: string;
106
+ }
107
+ /**
108
+ * Background tasks have ended and their results were just read into the
109
+ * conversation, as `text`. Emitted where they enter, like an interjection.
110
+ */
111
+ | {
112
+ type: "task_notification";
113
+ tasks: BackgroundTaskView[];
114
+ text: string;
102
115
  } | {
103
116
  type: "compacted";
104
117
  tokensBefore: number;
@@ -130,6 +143,11 @@ export type AgentEvent = {
130
143
  type: "notice";
131
144
  message: string;
132
145
  }
146
+ /** The session's goal was set, nudged, achieved or reported blocked. */
147
+ | {
148
+ type: "goal";
149
+ goal: SessionGoal;
150
+ }
133
151
  /**
134
152
  * `status` is the HTTP status behind a provider failure, when one could be
135
153
  * recovered. It travels beside the message because some statuses are not
@@ -191,6 +209,11 @@ export interface AgentOptions {
191
209
  onSkillsChanged?: () => Promise<unknown>;
192
210
  /** Restricts where writes may land. A policy gate, not an OS sandbox. */
193
211
  workspace?: WorkspacePolicy;
212
+ /**
213
+ * Who can host a session in a new worktree. A getter, because the frontend
214
+ * wires it after the harness — and so the agent it builds — already exists.
215
+ */
216
+ worktreeLauncher?: () => WorktreeLauncher | undefined;
194
217
  /** Enable provider prompt caching where the model supports it. */
195
218
  cache?: boolean;
196
219
  agentId?: string;
@@ -200,8 +223,38 @@ export interface AgentOptions {
200
223
  onAudit?: (event: RuntimeAuditEvent) => void;
201
224
  /** Internal host lifecycle accounting; inherited by subagents. */
202
225
  onRunStart?: () => () => void;
226
+ /**
227
+ * Who starts a turn to read in background results that end while this agent
228
+ * is idle. A getter, like worktreeLauncher, because the frontend wires it
229
+ * after the agent exists. Without one, background tasks are not offered:
230
+ * a result arriving after the run had ended would reach nobody.
231
+ */
232
+ taskWaker?: () => ((sessionId: string) => void) | undefined;
233
+ /** How many background tasks run at once; the rest queue. */
234
+ maxBackgroundTasks?: number;
235
+ /**
236
+ * Give a subagent its own browser and computer, so it never drives the
237
+ * parent's tabs or acts under the parent's window leases. Rebinds the
238
+ * per-conversation tools already in `tools`; `release` closes them again.
239
+ */
240
+ equipSubagent?: (sessionId: string, label: string, tools: ToolRegistry) => SubagentEquipment;
241
+ /**
242
+ * The conversation this agent's permission cards belong to. A subagent's
243
+ * own session is invisible to every frontend, so its questions are placed
244
+ * in the conversation that started it.
245
+ */
246
+ interactionSessionId?: string;
247
+ /** Who is asking, on those cards: "general: fix the flaky test". */
248
+ interactionLabel?: string;
203
249
  logger?: Logger;
204
250
  }
251
+ export interface SubagentEquipment {
252
+ /** Replaces the parent's run accounting, which would release the parent's leases. */
253
+ onRunStart?: () => () => void;
254
+ /** Rebind its tools into another registry: the same browser and computer, for a later run. */
255
+ bind?(tools: ToolRegistry): void;
256
+ release(): Promise<void>;
257
+ }
205
258
  /**
206
259
  * Notes attached to messages still in the transcript.
207
260
  *
@@ -218,6 +271,22 @@ export declare function recalledInTranscript(messages: readonly Message[]): Set<
218
271
  * same regardless of which model is selected — including when the model
219
272
  * changes partway through a session.
220
273
  */
274
+ /** How a conversation fills the model's window; see Agent.contextBreakdown(). */
275
+ export interface ContextBreakdown {
276
+ /** Tokens in use: measured from the last request when there was one. */
277
+ total: number;
278
+ window: number;
279
+ /** Estimated: the system prompt, with skills, memory and project notes. */
280
+ system: number;
281
+ /** Estimated: the definitions of the tools offered to the model. */
282
+ tools: number;
283
+ /** The rest of the total: the conversation itself. */
284
+ messages: number;
285
+ /** Whether `total` came from the provider rather than an estimate. */
286
+ measured: boolean;
287
+ /** Tokens at which automatic compaction fires; absent when it is off. */
288
+ compactAt?: number;
289
+ }
221
290
  export declare class Agent implements ToolHost {
222
291
  readonly session: Session;
223
292
  readonly tools: ToolRegistry;
@@ -248,6 +317,18 @@ export declare class Agent implements ToolHost {
248
317
  private pluginSections;
249
318
  /** Recall over `memory` for agents embedded without a plugin host. */
250
319
  private legacyMemory?;
320
+ /** Subagents running in the background; made on first use. */
321
+ private background?;
322
+ private wakeTimer?;
323
+ /** Frontends watching background tasks, kept until the tasks exist. */
324
+ private readonly changeListeners;
325
+ /** What each background task was asked, and its subagent once it has one. */
326
+ private readonly taskStates;
327
+ private restoring?;
328
+ private saveTimer?;
329
+ /** Closed or deleted: nothing more is saved, and nothing more starts. */
330
+ private tasksClosed;
331
+ private saveChain;
251
332
  constructor(opts: AgentOptions);
252
333
  /**
253
334
  * Announce a model switch so a UI can render it and hooks can react.
@@ -295,14 +376,155 @@ export declare class Agent implements ToolHost {
295
376
  * tools ask rather than each re-deriving a notion of "inside the project".
296
377
  */
297
378
  resolvePath(input: string, access: "read" | "write"): string;
379
+ startWorktree(opts: WorktreeStartOptions): Promise<WorktreeStartResult>;
298
380
  listSubagentTypes(): Array<{
299
381
  name: string;
300
382
  description: string;
383
+ readOnly?: boolean;
384
+ isolation?: "worktree";
301
385
  }>;
302
386
  runSubagent(opts: SubagentRunOptions): Promise<SubagentRunResult>;
387
+ /**
388
+ * Subagents running behind this conversation, offered only while someone
389
+ * can start a turn to read their results in. Once any exist they stay
390
+ * reachable, so they can still be listed, messaged and stopped.
391
+ */
392
+ get backgroundTasks(): BackgroundTaskHost | undefined;
393
+ /** A task's conversation so far, for a frontend to show. */
394
+ backgroundTranscript(id: string): readonly Message[] | undefined;
395
+ /** Every change to a background task, for a frontend to redraw from. */
396
+ onBackgroundChange(listener: (task: BackgroundTaskView) => void): () => void;
397
+ /**
398
+ * The conversation is being closed, not ended: write its tasks down as they
399
+ * stand, then stop them. Opened again, the ones that were running come back
400
+ * interrupted and can be followed up — as after a restart.
401
+ */
402
+ closeBackgroundTasks(): Promise<void>;
403
+ /**
404
+ * The conversation is being deleted: stop its tasks and write nothing more.
405
+ * Resolves once a write already under way has landed, so deleting the
406
+ * store afterwards cannot be undone by it.
407
+ */
408
+ discardBackgroundTasks(): Promise<void>;
409
+ private endBackgroundTasks;
410
+ private backgroundAvailable;
411
+ private tasks;
412
+ /**
413
+ * A background task's subagent, made for each run and let go after it.
414
+ *
415
+ * Between runs a task holds only its conversation and, if it changed
416
+ * anything, its worktree: no browser, no claim on the computer, no agent.
417
+ * A follow-up — or the first one after a restart — builds the subagent
418
+ * again from those, so both paths are the same path.
419
+ */
420
+ private backgroundSpec;
421
+ /**
422
+ * Put back the background tasks this conversation had before a restart.
423
+ *
424
+ * Called by a frontend when it opens the conversation; safe to call again.
425
+ * A task that was still running when the app closed comes back as failed
426
+ * and says why — its subagent's process is gone — but keeps its
427
+ * conversation, so a follow-up carries on from where it stopped. A result
428
+ * nobody had been told about is still read in with the next turn.
429
+ */
430
+ restoreBackgroundTasks(): Promise<number>;
431
+ /** Write the tasks down a moment after they change, so a burst is one write. */
432
+ private scheduleSave;
433
+ /**
434
+ * One write at a time, in order. Each takes its snapshot when its turn
435
+ * comes, so a later state is never overwritten by an earlier one landing
436
+ * last — a task that ended would come back as running.
437
+ */
438
+ private saveTasks;
439
+ private writeTasks;
440
+ private scheduleWake;
441
+ /**
442
+ * Read the results of background tasks that have ended into the
443
+ * conversation, as one message saying what is still running.
444
+ *
445
+ * Synthetic, like a goal nudge: nobody typed it, so it skips the prompt hook
446
+ * and memory recall, and never titles the session.
447
+ */
448
+ private takeNotices;
449
+ /** Where this agent's permission cards go, and who they say is asking. */
450
+ private interactionPlace;
451
+ /** A subagent ready to run: its agent, the tree it works in, what it holds. */
452
+ private prepareSubagent;
453
+ /**
454
+ * One run of a subagent, to its end: its first prompt, or a later message.
455
+ *
456
+ * `report` is there only for a background task: it is what lets a look at
457
+ * the task say what the subagent is doing now.
458
+ */
459
+ private runChild;
460
+ /**
461
+ * One run of a subagent whose loop is an external agent's (ACP).
462
+ *
463
+ * The child session is still kept, as the record of the task: the prompt
464
+ * and the agent's answer go into it, so a background task's transcript and
465
+ * a follow-up after a restart read the same as any other subagent's. The
466
+ * agent itself starts fresh each run, so what came before rides in the
467
+ * prompt.
468
+ */
469
+ private runExternalChild;
470
+ /**
471
+ * File access for an external agent, through this agent's workspace policy:
472
+ * reads where ours may read, writes where ours may write, nowhere else.
473
+ */
474
+ externalFs(): AcpFileSystem;
475
+ /**
476
+ * `@claude …`: a message addressed to an external agent by name.
477
+ *
478
+ * Only an agent with an ACP runtime answers to this, and only at the start
479
+ * of what was typed — or of the paragraph after a reference note, which the
480
+ * page puts above the prompt. The note stays with the message; the name
481
+ * does not.
482
+ */
483
+ private directTarget;
484
+ /**
485
+ * A turn answered by an external agent instead of the model.
486
+ *
487
+ * What makes `@claude` worth having: the message goes straight to the
488
+ * user's own Claude Code, so it is paid for by their Claude account and
489
+ * nothing is spent on this harness's model in between. The agent's reply
490
+ * streams into the conversation as text, its tool calls as tool cards, its
491
+ * questions as the usual permission card; the exchange is kept as an
492
+ * ordinary user/assistant pair, and the agent's session id rides on the
493
+ * reply so the next `@claude` picks up where this one left off.
494
+ */
495
+ private runDirect;
496
+ /**
497
+ * This conversation's MCP servers, in the shape ACP's `session/new` takes,
498
+ * so an external agent works with the same tools. HTTP ones are filtered
499
+ * out later for an agent that does not take them.
500
+ */
501
+ private forwardedMcpServers;
502
+ /**
503
+ * An external agent's own tool call, put to the person the way this
504
+ * harness's calls are — the same card, placed in the conversation that
505
+ * started the task and labelled with who is asking. Plan mode and a
506
+ * read-only workspace refuse; bypass allows, as it would for our own tools.
507
+ */
508
+ askForExternal(title: string, input: unknown, toolCallId: string, signal: AbortSignal | undefined, from?: string): Promise<boolean | PermissionAnswer>;
509
+ /** What a subagent left in its worktree, when it left anything. */
510
+ private worktreeNote;
511
+ /**
512
+ * A subagent is finished with: its browser and computer go, and a worktree
513
+ * it changed nothing in is removed. One that it changed is kept — the
514
+ * parent has to decide what happens to that work.
515
+ */
516
+ private disposeChild;
517
+ private dropIfUntouched;
303
518
  run(input: string | Message[], runOpts?: {
304
519
  signal?: AbortSignal;
305
520
  }): AsyncGenerator<AgentEvent, void, void>;
521
+ /**
522
+ * Where a reply ends with a goal still active: ask for more work.
523
+ *
524
+ * Returns whether the loop should go on. A model that keeps stopping short
525
+ * of its goal gets a bounded number of reminders, not an endless supply.
526
+ */
527
+ private pushTowardGoal;
306
528
  private ingestInput;
307
529
  /**
308
530
  * Put what the user said into the conversation, as its own message.
@@ -343,12 +565,46 @@ export declare class Agent implements ToolHost {
343
565
  private scheduleExtraction;
344
566
  /** Where the next end-of-run extraction starts, clamped to the transcript. */
345
567
  private extractedUpTo;
568
+ /**
569
+ * How full the model's window is, in tokens: what the last request measured,
570
+ * or, before one has (a new or reopened conversation), an estimate of the
571
+ * next request — system prompt and tools included, which are a large share
572
+ * of a short conversation.
573
+ */
574
+ contextTokens(): number;
575
+ /**
576
+ * The window, split the way the context panel draws it. Providers report one
577
+ * number for the prompt, so the system prompt and the tool definitions are
578
+ * estimated and the messages are what is left of the measured total; until
579
+ * something is measured all three are estimates.
580
+ */
581
+ contextBreakdown(): ContextBreakdown;
582
+ private contextEstimate;
583
+ /**
584
+ * Compact now, whatever the window says: the /compact command. Goes through
585
+ * the same path as the automatic kind, so what it drops is archived for
586
+ * recall and handed to memory extraction rather than simply discarded.
587
+ * Returns what happened, or undefined when there was nothing safe to cut.
588
+ */
589
+ compactNow(): Promise<AgentEvent | undefined>;
346
590
  private maybeCompact;
591
+ /**
592
+ * The tools offered to the model: the goal tool only while there is a goal,
593
+ * and the computer tools only while this conversation has Computer Use on.
594
+ */
595
+ private visibleTools;
347
596
  private systemPrompt;
348
597
  private buildRequest;
349
598
  /** Consume the provider stream, emitting deltas and assembling the message. */
350
599
  private streamAssistant;
351
600
  private executeCalls;
352
601
  private executeOne;
602
+ /**
603
+ * Ask about a write the workspace policy would refuse.
604
+ *
605
+ * Bypass mode approves it as it approves everything else. Read-only and plan
606
+ * mode refuse it, as does a frontend with no way to ask.
607
+ */
608
+ private askOutsideRoots;
353
609
  private checkPermission;
354
610
  }