@botbotgo/agent-harness 0.0.309 → 0.0.310

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 (195) hide show
  1. package/README.md +14 -0
  2. package/README.zh.md +14 -0
  3. package/dist/acp.d.ts +1 -116
  4. package/dist/acp.js +1 -310
  5. package/dist/api.d.ts +1 -1
  6. package/dist/api.js +1 -1
  7. package/dist/cli/chat-interactive.d.ts +24 -0
  8. package/dist/cli/chat-interactive.js +244 -0
  9. package/dist/cli/chat-rendering.d.ts +9 -0
  10. package/dist/cli/chat-rendering.js +102 -0
  11. package/dist/cli/chat-stream.d.ts +23 -0
  12. package/dist/cli/chat-stream.js +330 -0
  13. package/dist/cli/chat-ui.d.ts +20 -0
  14. package/dist/cli/chat-ui.js +198 -0
  15. package/dist/cli/chat-workspace.d.ts +15 -0
  16. package/dist/cli/chat-workspace.js +205 -0
  17. package/dist/cli/main.d.ts +52 -0
  18. package/dist/cli/main.js +323 -0
  19. package/dist/cli/managed-service-commands.d.ts +23 -0
  20. package/dist/cli/managed-service-commands.js +63 -0
  21. package/dist/cli/managed-service.d.ts +27 -0
  22. package/dist/cli/managed-service.js +61 -0
  23. package/dist/cli/options-init-chat.d.ts +16 -0
  24. package/dist/cli/options-init-chat.js +108 -0
  25. package/dist/cli/options-runtime.d.ts +27 -0
  26. package/dist/cli/options-runtime.js +158 -0
  27. package/dist/cli/options-serve.d.ts +24 -0
  28. package/dist/cli/options-serve.js +166 -0
  29. package/dist/cli/options.d.ts +5 -0
  30. package/dist/cli/options.js +47 -0
  31. package/dist/cli/process-guards.d.ts +14 -0
  32. package/dist/cli/process-guards.js +139 -0
  33. package/dist/cli/request-tree.d.ts +12 -0
  34. package/dist/cli/request-tree.js +296 -0
  35. package/dist/cli/runtime-commands.d.ts +15 -0
  36. package/dist/cli/runtime-commands.js +247 -0
  37. package/dist/cli/runtime-output.d.ts +5 -0
  38. package/dist/cli/runtime-output.js +124 -0
  39. package/dist/cli/server-commands.d.ts +36 -0
  40. package/dist/cli/server-commands.js +250 -0
  41. package/dist/cli/workspace.d.ts +6 -0
  42. package/dist/cli/workspace.js +71 -0
  43. package/dist/cli.d.ts +1 -78
  44. package/dist/cli.js +2 -3024
  45. package/dist/client/acp.d.ts +1 -50
  46. package/dist/client/acp.js +1 -219
  47. package/dist/client/in-process.d.ts +5 -5
  48. package/dist/client/index.d.ts +2 -2
  49. package/dist/client/index.js +1 -1
  50. package/dist/contracts/runtime-evaluation.d.ts +103 -0
  51. package/dist/contracts/runtime-evaluation.js +1 -0
  52. package/dist/contracts/runtime-memory.d.ts +162 -0
  53. package/dist/contracts/runtime-memory.js +1 -0
  54. package/dist/contracts/runtime-observability.d.ts +248 -0
  55. package/dist/contracts/runtime-observability.js +1 -0
  56. package/dist/contracts/runtime-requests.d.ts +342 -0
  57. package/dist/contracts/runtime-requests.js +1 -0
  58. package/dist/contracts/runtime-scheduling.d.ts +146 -0
  59. package/dist/contracts/runtime-scheduling.js +1 -0
  60. package/dist/contracts/runtime.d.ts +5 -1042
  61. package/dist/contracts/runtime.js +27 -1
  62. package/dist/flow/build-flow-graph.js +4 -875
  63. package/dist/flow/flow-graph-normalization.d.ts +56 -0
  64. package/dist/flow/flow-graph-normalization.js +214 -0
  65. package/dist/flow/flow-graph-runtime.d.ts +8 -0
  66. package/dist/flow/flow-graph-runtime.js +107 -0
  67. package/dist/flow/flow-graph-upstream.d.ts +18 -0
  68. package/dist/flow/flow-graph-upstream.js +498 -0
  69. package/dist/flow/types.d.ts +1 -1
  70. package/dist/index.d.ts +3 -3
  71. package/dist/index.js +1 -1
  72. package/dist/init-project.d.ts +1 -12
  73. package/dist/init-project.js +1 -651
  74. package/dist/{procedural → knowledge/procedural}/manager.d.ts +3 -3
  75. package/dist/{procedural → knowledge/procedural}/manager.js +6 -6
  76. package/dist/mcp.d.ts +2 -76
  77. package/dist/mcp.js +2 -428
  78. package/dist/package-version.d.ts +1 -1
  79. package/dist/package-version.js +1 -1
  80. package/dist/persistence/file-store.js +1 -1
  81. package/dist/persistence/sqlite-runtime.d.ts +19 -0
  82. package/dist/persistence/sqlite-runtime.js +86 -0
  83. package/dist/persistence/sqlite-store.js +11 -99
  84. package/dist/{request-events.d.ts → projections/request-events.d.ts} +1 -1
  85. package/dist/{upstream-events.js → projections/upstream-events.js} +1 -1
  86. package/dist/protocol/a2a/http-discovery.d.ts +39 -0
  87. package/dist/protocol/a2a/http-discovery.js +178 -0
  88. package/dist/protocol/a2a/http-rpc.d.ts +28 -0
  89. package/dist/protocol/a2a/http-rpc.js +623 -0
  90. package/dist/protocol/a2a/http.d.ts +72 -1
  91. package/dist/protocol/a2a/http.js +14 -1124
  92. package/dist/protocol/a2a/task-state.d.ts +29 -0
  93. package/dist/protocol/a2a/task-state.js +317 -0
  94. package/dist/protocol/acp/client.js +1 -1
  95. package/dist/protocol/acp/harness-client.d.ts +50 -0
  96. package/dist/protocol/acp/harness-client.js +219 -0
  97. package/dist/protocol/acp/server.d.ts +116 -0
  98. package/dist/protocol/acp/server.js +310 -0
  99. package/dist/protocol/ag-ui/http.js +1 -1
  100. package/dist/protocol/mcp/server.d.ts +76 -0
  101. package/dist/protocol/mcp/server.js +428 -0
  102. package/dist/resource/backend/workspace-scoped-backend.d.ts +40 -0
  103. package/dist/resource/backend/workspace-scoped-backend.js +296 -0
  104. package/dist/resource/mcp/tool-support.d.ts +35 -0
  105. package/dist/resource/mcp/tool-support.js +296 -0
  106. package/dist/resource/mcp-tool-support.d.ts +2 -35
  107. package/dist/resource/mcp-tool-support.js +2 -296
  108. package/dist/resource/providers/resource-provider.d.ts +22 -0
  109. package/dist/resource/providers/resource-provider.js +215 -0
  110. package/dist/resource/resource-impl.d.ts +3 -33
  111. package/dist/resource/resource-impl.js +2 -808
  112. package/dist/resource/resource-types.d.ts +33 -0
  113. package/dist/resource/resource-types.js +1 -0
  114. package/dist/resource/tools/function-tool-resolver.d.ts +2 -0
  115. package/dist/resource/tools/function-tool-resolver.js +306 -0
  116. package/dist/runtime/adapter/middleware-assembly.js +1 -1
  117. package/dist/runtime/adapter/model/invocation-request.js +2 -2
  118. package/dist/runtime/adapter/model/message-assembly.js +1 -1
  119. package/dist/runtime/agent-runtime-adapter.d.ts +3 -63
  120. package/dist/runtime/agent-runtime-adapter.js +5 -233
  121. package/dist/runtime/agent-runtime-assembly.d.ts +67 -0
  122. package/dist/runtime/agent-runtime-assembly.js +211 -0
  123. package/dist/runtime/harness/background-runtime.d.ts +1 -1
  124. package/dist/runtime/harness/events/event-sink.js +1 -1
  125. package/dist/runtime/harness/events/runtime-event-operations.d.ts +1 -1
  126. package/dist/runtime/harness/events/streaming.js +1 -1
  127. package/dist/runtime/harness/public-shapes.d.ts +43 -0
  128. package/dist/runtime/harness/public-shapes.js +186 -0
  129. package/dist/runtime/harness/run/inspection.js +2 -2
  130. package/dist/runtime/harness/run/resources.js +1 -1
  131. package/dist/runtime/harness/run/surface-semantics.js +1 -1
  132. package/dist/runtime/harness/system/inventory.d.ts +1 -1
  133. package/dist/runtime/harness/system/inventory.js +2 -2
  134. package/dist/runtime/harness/system/policy-engine.js +1 -1
  135. package/dist/runtime/harness/system/runtime-memory-manager.js +1 -1
  136. package/dist/runtime/harness/system/skill-requirements.d.ts +1 -1
  137. package/dist/runtime/harness/system/skill-requirements.js +1 -1
  138. package/dist/runtime/harness.d.ts +2 -2
  139. package/dist/runtime/harness.js +7 -191
  140. package/dist/runtime/maintenance/checkpoint-maintenance.js +1 -1
  141. package/dist/runtime/maintenance/runtime-record-maintenance.js +1 -1
  142. package/dist/runtime/parsing/output-content.d.ts +11 -0
  143. package/dist/runtime/parsing/output-content.js +442 -0
  144. package/dist/runtime/parsing/output-parsing.d.ts +3 -29
  145. package/dist/runtime/parsing/output-parsing.js +3 -806
  146. package/dist/runtime/parsing/output-recovery.d.ts +14 -0
  147. package/dist/runtime/parsing/output-recovery.js +288 -0
  148. package/dist/runtime/parsing/output-tool-args.d.ts +4 -0
  149. package/dist/runtime/parsing/output-tool-args.js +120 -0
  150. package/dist/runtime/support/runtime-factories.js +1 -1
  151. package/dist/scaffold/init-project.d.ts +12 -0
  152. package/dist/scaffold/init-project.js +651 -0
  153. package/dist/{extensions.d.ts → tooling/extensions.d.ts} +1 -1
  154. package/dist/{extensions.js → tooling/extensions.js} +3 -3
  155. package/dist/{tool-modules.d.ts → tooling/module-loader.d.ts} +1 -1
  156. package/dist/{tool-modules.js → tooling/module-loader.js} +2 -2
  157. package/dist/workspace/agent-binding-compiler.js +2 -2
  158. package/dist/workspace/compile.js +2 -2
  159. package/dist/workspace/object-loader-paths.d.ts +11 -0
  160. package/dist/workspace/object-loader-paths.js +75 -0
  161. package/dist/workspace/object-loader-readers.d.ts +21 -0
  162. package/dist/workspace/object-loader-readers.js +187 -0
  163. package/dist/workspace/object-loader.d.ts +0 -1
  164. package/dist/workspace/object-loader.js +6 -260
  165. package/dist/workspace/resource-compilers.js +1 -1
  166. package/dist/workspace/support/discovery.js +1 -1
  167. package/package.json +1 -1
  168. package/dist/runtime/adapter/index.d.ts +0 -13
  169. package/dist/runtime/adapter/index.js +0 -13
  170. package/dist/runtime/harness/index.d.ts +0 -19
  171. package/dist/runtime/harness/index.js +0 -19
  172. package/dist/runtime/maintenance/index.d.ts +0 -4
  173. package/dist/runtime/maintenance/index.js +0 -4
  174. package/dist/runtime/parsing/index.d.ts +0 -2
  175. package/dist/runtime/parsing/index.js +0 -2
  176. package/dist/runtime/support/index.d.ts +0 -4
  177. package/dist/runtime/support/index.js +0 -4
  178. package/dist/workspace/support/index.d.ts +0 -2
  179. package/dist/workspace/support/index.js +0 -2
  180. /package/dist/{procedural → knowledge/procedural}/config.d.ts +0 -0
  181. /package/dist/{procedural → knowledge/procedural}/config.js +0 -0
  182. /package/dist/{procedural → knowledge/procedural}/index.d.ts +0 -0
  183. /package/dist/{procedural → knowledge/procedural}/index.js +0 -0
  184. /package/dist/{presentation.d.ts → projections/presentation.d.ts} +0 -0
  185. /package/dist/{presentation.js → projections/presentation.js} +0 -0
  186. /package/dist/{request-events.js → projections/request-events.js} +0 -0
  187. /package/dist/{upstream-events.d.ts → projections/upstream-events.d.ts} +0 -0
  188. /package/dist/runtime/{support → env}/runtime-env.d.ts +0 -0
  189. /package/dist/runtime/{support → env}/runtime-env.js +0 -0
  190. /package/dist/runtime/{support → layout}/runtime-layout.d.ts +0 -0
  191. /package/dist/runtime/{support → layout}/runtime-layout.js +0 -0
  192. /package/dist/runtime/{support → prompts}/runtime-prompts.d.ts +0 -0
  193. /package/dist/runtime/{support → prompts}/runtime-prompts.js +0 -0
  194. /package/dist/runtime/{support → skills}/skill-metadata.d.ts +0 -0
  195. /package/dist/runtime/{support → skills}/skill-metadata.js +0 -0
@@ -0,0 +1,139 @@
1
+ import { EventEmitter } from "node:events";
2
+ const CLI_IGNORED_STDERR_WARNING_SNIPPETS = [
3
+ "llamaindex was already imported. This breaks constructor checks and will lead to issues!",
4
+ "MaxListenersExceededWarning: Possible EventEmitter memory leak detected.",
5
+ "(Use `node --trace-warnings ...` to show where the warning was created)",
6
+ ];
7
+ export function isChatServerNoiseLine(line) {
8
+ const trimmed = line.trim();
9
+ if (!trimmed) {
10
+ return true;
11
+ }
12
+ return (trimmed.startsWith("Serving ACP over stdio from ") ||
13
+ trimmed === "langsmith/experimental/sandbox is in alpha. This feature is experimental, and breaking changes are expected." ||
14
+ trimmed === "llamaindex was already imported. This breaks constructor checks and will lead to issues!");
15
+ }
16
+ export function installCliWriteListenerGuard(streams, minimum = 64) {
17
+ const restore = [];
18
+ for (const stream of streams) {
19
+ if (!stream?.getMaxListeners || !stream?.setMaxListeners) {
20
+ continue;
21
+ }
22
+ const previous = stream.getMaxListeners();
23
+ if (previous === 0 || previous >= minimum) {
24
+ continue;
25
+ }
26
+ stream.setMaxListeners(minimum);
27
+ restore.push(() => stream.setMaxListeners?.(previous));
28
+ }
29
+ return () => {
30
+ for (const reset of restore.reverse()) {
31
+ reset();
32
+ }
33
+ };
34
+ }
35
+ export function installCliEmitterListenerGuard(minimum = 64) {
36
+ const previous = EventEmitter.defaultMaxListeners;
37
+ const hadPrototypeMaxListeners = Object.prototype.hasOwnProperty.call(EventEmitter.prototype, "_maxListeners");
38
+ const previousPrototypeMaxListeners = EventEmitter.prototype._maxListeners;
39
+ if (previous === 0 || previous >= minimum) {
40
+ return () => undefined;
41
+ }
42
+ EventEmitter.defaultMaxListeners = minimum;
43
+ EventEmitter.prototype._maxListeners = minimum;
44
+ return () => {
45
+ EventEmitter.defaultMaxListeners = previous;
46
+ if (hadPrototypeMaxListeners) {
47
+ EventEmitter.prototype._maxListeners = previousPrototypeMaxListeners;
48
+ return;
49
+ }
50
+ delete EventEmitter.prototype._maxListeners;
51
+ };
52
+ }
53
+ export function installCliStderrNoiseFilter(enabled) {
54
+ if (!enabled) {
55
+ return () => undefined;
56
+ }
57
+ const originalStderrWrite = process.stderr.write.bind(process.stderr);
58
+ process.stderr.write = ((chunk, encoding, callback) => {
59
+ const text = typeof chunk === "string"
60
+ ? chunk
61
+ : chunk instanceof Uint8Array
62
+ ? Buffer.from(chunk).toString(typeof encoding === "string" ? encoding : undefined)
63
+ : "";
64
+ if (CLI_IGNORED_STDERR_WARNING_SNIPPETS.some((snippet) => text.includes(snippet))) {
65
+ if (typeof encoding === "function") {
66
+ encoding();
67
+ }
68
+ else if (typeof callback === "function") {
69
+ callback();
70
+ }
71
+ return true;
72
+ }
73
+ if (typeof encoding === "function") {
74
+ return originalStderrWrite(chunk, encoding);
75
+ }
76
+ return originalStderrWrite(chunk, encoding, callback);
77
+ });
78
+ return () => {
79
+ process.stderr.write = originalStderrWrite;
80
+ };
81
+ }
82
+ export function installCliWarningFilter() {
83
+ const originalEmitWarning = process.emitWarning.bind(process);
84
+ process.emitWarning = ((warning, ...args) => {
85
+ const text = typeof warning === "string" ? warning : warning?.message ?? "";
86
+ const name = typeof warning === "string" ? String(args[1] ?? args[0] ?? "") : warning?.name ?? "";
87
+ if (CLI_IGNORED_STDERR_WARNING_SNIPPETS.some((snippet) => text.includes(snippet))
88
+ || name === "MaxListenersExceededWarning") {
89
+ return;
90
+ }
91
+ return originalEmitWarning(warning, ...args);
92
+ });
93
+ return () => {
94
+ process.emitWarning = originalEmitWarning;
95
+ };
96
+ }
97
+ function terminateChatSubprocess(child, signal = "SIGTERM") {
98
+ if (child.killed || child.exitCode !== null || child.signalCode !== null) {
99
+ return;
100
+ }
101
+ try {
102
+ child.kill(signal);
103
+ }
104
+ catch {
105
+ // Ignore termination races during shutdown.
106
+ }
107
+ }
108
+ export function installChatSubprocessExitGuard(child, host = process) {
109
+ let cleanedUp = false;
110
+ let forceKillTimer;
111
+ const handleParentExit = () => {
112
+ terminateChatSubprocess(child, "SIGTERM");
113
+ if (!forceKillTimer && child.exitCode === null && child.signalCode === null) {
114
+ forceKillTimer = setTimeout(() => {
115
+ terminateChatSubprocess(child, "SIGKILL");
116
+ }, 2_000);
117
+ forceKillTimer.unref?.();
118
+ }
119
+ };
120
+ const cleanup = () => {
121
+ if (cleanedUp) {
122
+ return;
123
+ }
124
+ cleanedUp = true;
125
+ if (forceKillTimer) {
126
+ clearTimeout(forceKillTimer);
127
+ forceKillTimer = undefined;
128
+ }
129
+ host.off("beforeExit", handleParentExit);
130
+ host.off("exit", handleParentExit);
131
+ child.off("close", cleanup);
132
+ child.off("exit", cleanup);
133
+ };
134
+ host.on("beforeExit", handleParentExit);
135
+ host.on("exit", handleParentExit);
136
+ child.on("close", cleanup);
137
+ child.on("exit", cleanup);
138
+ return cleanup;
139
+ }
@@ -0,0 +1,12 @@
1
+ import type { RequestEventSnapshot, RequestExecutionStep } from "../contracts/types.js";
2
+ export declare function flattenRequestExecutionSteps(snapshot: RequestEventSnapshot): RequestExecutionStep[];
3
+ export declare function renderRequestSnapshotTree(snapshot: RequestEventSnapshot, color?: boolean, timingSummary?: string): string;
4
+ export declare function renderRequestEventContinuation(snapshot: RequestEventSnapshot, fromIndex: number, color?: boolean): string;
5
+ export declare function buildTodoContinuationSignature(snapshot: RequestEventSnapshot): string;
6
+ export declare function renderRequestTodoContinuation(snapshot: RequestEventSnapshot, previousSignature: string, color?: boolean): string;
7
+ export declare function buildTerminalRequestSnapshot(snapshot: RequestEventSnapshot, result: {
8
+ state: string;
9
+ output: string;
10
+ }): RequestEventSnapshot;
11
+ export declare function summarizeRequestOutput(output: string, color: boolean): string;
12
+ export declare function buildExecutionStepContinuationKey(step: RequestExecutionStep): string;
@@ -0,0 +1,296 @@
1
+ const STEP_KIND_ICON = {
2
+ llm: "◆",
3
+ tool: "⚙",
4
+ skill: "★",
5
+ agent: "◉",
6
+ memory: "◈",
7
+ approval: "⚠",
8
+ };
9
+ function ellipsizeChatId(value, maxChars) {
10
+ if (value.length <= maxChars) {
11
+ return value;
12
+ }
13
+ if (maxChars <= 1) {
14
+ return "…";
15
+ }
16
+ return `${value.slice(0, maxChars - 1)}…`;
17
+ }
18
+ function formatTreeBranch(isLast) {
19
+ return isLast ? "└─" : "├─";
20
+ }
21
+ function formatTreeIndent(ancestorLast) {
22
+ return ancestorLast ? " " : "│ ";
23
+ }
24
+ function applyAnsi(text, code, enabled) {
25
+ if (!enabled) {
26
+ return text;
27
+ }
28
+ return `\x1b[${code}m${text}\x1b[0m`;
29
+ }
30
+ function renderRequestStateBadge(state, color) {
31
+ if (state === "completed") {
32
+ return color ? `\x1b[32;1m✔ DONE\x1b[0m` : "✔ DONE";
33
+ }
34
+ if (state === "running") {
35
+ return color ? `\x1b[36;1m▶ RUNNING\x1b[0m` : "▶ RUNNING";
36
+ }
37
+ if (state === "waiting" || state === "waiting_for_approval") {
38
+ return color ? `\x1b[33;1m⚠ WAITING\x1b[0m` : "⚠ WAITING";
39
+ }
40
+ if (state === "failed") {
41
+ return color ? `\x1b[31;1m✘ FAILED\x1b[0m` : "✘ FAILED";
42
+ }
43
+ if (state === "cancelled") {
44
+ return color ? `\x1b[31m○ CANCELLED\x1b[0m` : "○ CANCELLED";
45
+ }
46
+ if (state === "queued") {
47
+ return color ? `\x1b[38;5;242m· QUEUED\x1b[0m` : "· QUEUED";
48
+ }
49
+ return color ? `\x1b[37m${state.toUpperCase()}\x1b[0m` : state.toUpperCase();
50
+ }
51
+ function summarizeRequestPlan(snapshot) {
52
+ const summary = snapshot.plan.summary;
53
+ const eventCount = flattenRequestExecutionSteps(snapshot).length;
54
+ const parts = [
55
+ `${summary.total} todo${summary.total === 1 ? "" : "s"}`,
56
+ summary.inProgress > 0 ? `${summary.inProgress} active` : undefined,
57
+ summary.completed > 0 ? `${summary.completed} done` : undefined,
58
+ summary.failed > 0 ? `${summary.failed} failed` : undefined,
59
+ eventCount > 0 ? `${eventCount} event${eventCount === 1 ? "" : "s"}` : undefined,
60
+ ].filter((part) => typeof part === "string");
61
+ return parts.join(" · ");
62
+ }
63
+ function formatCompactClockTime(value) {
64
+ const date = new Date(value);
65
+ if (Number.isNaN(date.getTime())) {
66
+ return value;
67
+ }
68
+ return new Intl.DateTimeFormat("en-US", {
69
+ hour12: false,
70
+ hour: "2-digit",
71
+ minute: "2-digit",
72
+ second: "2-digit",
73
+ }).format(date);
74
+ }
75
+ function renderTimeRange(startedAt, endedAt, detail, color) {
76
+ if (!startedAt && !endedAt) {
77
+ return "";
78
+ }
79
+ const from = startedAt ? formatCompactClockTime(startedAt) : "?";
80
+ const to = endedAt ? formatCompactClockTime(endedAt) : "now";
81
+ const durationMs = typeof detail?.durationMs === "number" ? detail.durationMs : undefined;
82
+ const durationLabel = durationMs !== undefined
83
+ ? ` · ${(durationMs / 1000).toFixed(durationMs >= 10_000 ? 0 : durationMs >= 1_000 ? 1 : 3)}s`
84
+ : "";
85
+ return ` ${applyAnsi(`[${from} -> ${to}${durationLabel}]`, "2", color)}`;
86
+ }
87
+ function readStepSkillNames(step) {
88
+ const value = step.detail?.skillNames;
89
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string" && item.trim().length > 0) : [];
90
+ }
91
+ function buildRequestStepEventKey(step) {
92
+ return `${step.kind}:${step.id}`;
93
+ }
94
+ function resolveEventTimestamp(step) {
95
+ return step.occurredAt ?? step.endedAt ?? step.startedAt;
96
+ }
97
+ function summarizeRequestStepDetail(step, displayName, color) {
98
+ if (step.kind === "memory" && step.detail?.source === "runtime-durable-memory") {
99
+ const count = typeof step.detail.count === "number" ? step.detail.count : undefined;
100
+ const scopes = Array.isArray(step.detail.scopes)
101
+ ? step.detail.scopes.filter((item) => typeof item === "string" && item.trim().length > 0)
102
+ : [];
103
+ const countLabel = count !== undefined ? `${count} record${count === 1 ? "" : "s"}` : undefined;
104
+ const scopeLabel = scopes.length > 0 ? scopes.join(", ") : undefined;
105
+ const summary = typeof step.detail.summary === "string" ? step.detail.summary.trim() : "";
106
+ const detailLabel = [countLabel, scopeLabel].filter((value) => Boolean(value)).join(" · ");
107
+ if (detailLabel) {
108
+ return ` ${applyAnsi(`(${detailLabel})`, "2", color)}`;
109
+ }
110
+ if (summary && !summary.toLowerCase().includes(displayName.toLowerCase())) {
111
+ const preview = summary.length > 48 ? `${summary.slice(0, 45)}...` : summary;
112
+ return ` ${applyAnsi(`(${preview})`, "2", color)}`;
113
+ }
114
+ return "";
115
+ }
116
+ if (step.ownerAgentId && step.ownerAgentId !== step.agentId) {
117
+ return ` ${applyAnsi(`(from ${step.ownerAgentId})`, "2", color)}`;
118
+ }
119
+ return "";
120
+ }
121
+ function statusIcon(status, color) {
122
+ if (status === "completed" || status === "done")
123
+ return applyAnsi("✔", "32", color);
124
+ if (status === "in_progress" || status === "started")
125
+ return applyAnsi("▶", "36", color);
126
+ if (status === "failed")
127
+ return applyAnsi("✘", "31", color);
128
+ if (status === "cancelled")
129
+ return applyAnsi("○", "31", color);
130
+ if (status === "pending" || status === "queued")
131
+ return applyAnsi("·", "238", color);
132
+ return applyAnsi("?", "37", color);
133
+ }
134
+ function renderRequestStepLine(step, prefix, isLast, _activeEventId, color = false) {
135
+ const skillNames = step.kind === "skill" ? readStepSkillNames(step) : [];
136
+ const profileDisplayName = step.id.startsWith("profile:") && step.kind === "agent"
137
+ ? `${step.name} ${step.action ?? ""}`.trim()
138
+ : undefined;
139
+ const displayName = profileDisplayName
140
+ ? profileDisplayName
141
+ : step.kind === "skill" && skillNames.length === 1
142
+ ? skillNames[0]
143
+ : step.kind === "skill" && skillNames.length > 1
144
+ ? skillNames.join(", ")
145
+ : step.name;
146
+ const icon = STEP_KIND_ICON[step.kind] ?? "·";
147
+ const kindLabel = color
148
+ ? `\x1b[38;5;242m${icon} ${step.kind}\x1b[0m`
149
+ : `${icon} ${step.kind}`;
150
+ const stIcon = statusIcon(step.status === "started" ? "in_progress" : step.status, color);
151
+ const nameFormatted = color ? `\x1b[38;5;252m${displayName}\x1b[0m` : displayName;
152
+ const eventTime = resolveEventTimestamp(step);
153
+ const timeLabel = eventTime ? applyAnsi(`[${formatCompactClockTime(eventTime)}]`, "2", color) : applyAnsi("[time?]", "2", color);
154
+ const detailSuffix = summarizeRequestStepDetail(step, displayName, color);
155
+ return `${prefix}${formatTreeBranch(isLast)} ${timeLabel} ${stIcon} ${kindLabel} ${nameFormatted}${detailSuffix}`;
156
+ }
157
+ function isInternalAgentLifecycleStep(step) {
158
+ return step.kind === "agent" && step.id.startsWith("profile:agent:");
159
+ }
160
+ function isVisibleRequestTreeStep(step) {
161
+ if (step.kind === "skill") {
162
+ return false;
163
+ }
164
+ return !isInternalAgentLifecycleStep(step);
165
+ }
166
+ function getVisibleTodoEvents(todo) {
167
+ return todo.events.filter(isVisibleRequestTreeStep);
168
+ }
169
+ function getVisibleRootEvents(snapshot) {
170
+ return snapshot.events.filter(isVisibleRequestTreeStep);
171
+ }
172
+ export function flattenRequestExecutionSteps(snapshot) {
173
+ return [
174
+ ...snapshot.plan.items.flatMap((item) => getVisibleTodoEvents(item)),
175
+ ...getVisibleRootEvents(snapshot),
176
+ ];
177
+ }
178
+ function buildExecutionStepEventKey(step) {
179
+ return [
180
+ buildRequestStepEventKey(step),
181
+ step.status,
182
+ step.startedAt ?? "",
183
+ step.endedAt ?? "",
184
+ ].join("|");
185
+ }
186
+ export function renderRequestSnapshotTree(snapshot, color = false, timingSummary) {
187
+ const lines = [];
188
+ const rootEvents = getVisibleRootEvents(snapshot);
189
+ const badge = renderRequestStateBadge(snapshot.state, color);
190
+ const agentLabel = snapshot.agentId
191
+ ? (color ? `\x1b[38;5;33m${snapshot.agentId}\x1b[0m` : snapshot.agentId)
192
+ : applyAnsi("unknown", "2", color);
193
+ const headerLabel = color ? `\x1b[1;37mREQUEST\x1b[0m` : "REQUEST";
194
+ lines.push(`${headerLabel} ${badge} ${applyAnsi("agent:", "2", color)}${agentLabel}`);
195
+ const muted = (s) => applyAnsi(s, "2", color);
196
+ lines.push(`├─ ${muted("session")} ${applyAnsi(ellipsizeChatId(snapshot.sessionId, 24), "2", color)}`);
197
+ lines.push(`├─ ${muted("request")} ${applyAnsi(ellipsizeChatId(snapshot.requestId, 24), "2", color)}`);
198
+ const planSummary = summarizeRequestPlan(snapshot);
199
+ const timing = timingSummary ?? "collecting";
200
+ lines.push(`├─ ${muted("plan")} ${applyAnsi(`v${snapshot.plan.version}`, "2", color)} ${muted("·")} ${planSummary ? applyAnsi(planSummary, "2", color) : muted("no tracked work yet")}`);
201
+ lines.push(`├─ ${muted("timing")} ${applyAnsi(timing, "2", color)}`);
202
+ lines.push(`├─ ${muted("todos")}`);
203
+ const planPrefix = `${formatTreeIndent(false)}`;
204
+ if (snapshot.plan.items.length === 0) {
205
+ lines.push(`${planPrefix}└─ ${muted("none yet")}`);
206
+ }
207
+ else {
208
+ snapshot.plan.items.forEach((todo, todoIndex) => {
209
+ const todoEvents = getVisibleTodoEvents(todo);
210
+ const todoIsLast = todoIndex === snapshot.plan.items.length - 1 && rootEvents.length === 0 && !snapshot.approval;
211
+ const todoActive = todo.key === snapshot.activeTodoKey ? (color ? ` \x1b[36m●\x1b[0m` : " ●") : "";
212
+ const tIcon = statusIcon(todo.status, color);
213
+ const todoTimeRange = renderTimeRange(todo.startedAt, todo.endedAt, undefined, color);
214
+ const todoContent = color ? `\x1b[38;5;253m${todo.content}\x1b[0m` : todo.content;
215
+ lines.push(`${planPrefix}${formatTreeBranch(todoIsLast)} ${tIcon} ${todoContent}${todoTimeRange}${todoActive}`);
216
+ if (todoEvents.length > 0) {
217
+ const todoEventPrefix = `${planPrefix}${formatTreeIndent(todoIsLast)}`;
218
+ todoEvents.forEach((step, eventIndex) => {
219
+ lines.push(renderRequestStepLine(step, todoEventPrefix, eventIndex === todoEvents.length - 1, snapshot.activeEventId, color));
220
+ });
221
+ }
222
+ });
223
+ }
224
+ if (rootEvents.length > 0) {
225
+ lines.push(`├─ ${muted("events")}`);
226
+ rootEvents.forEach((step, index) => {
227
+ lines.push(renderRequestStepLine(step, `${formatTreeIndent(false)}`, index === rootEvents.length - 1 && !snapshot.approval, snapshot.activeEventId, color));
228
+ });
229
+ }
230
+ if (snapshot.approval) {
231
+ const approvalStatus = snapshot.approval.status ?? "pending";
232
+ const approvalColor = approvalStatus === "approved" ? "32" : approvalStatus === "rejected" ? "31" : "33";
233
+ lines.push(`└─ ${color ? `\x1b[33m⚠ approval\x1b[0m` : "⚠ approval"} ${muted("·")} ${snapshot.approval.toolName ?? "unknown-tool"} ${applyAnsi(`(${approvalStatus})`, approvalColor, color)}`);
234
+ }
235
+ return `${lines.join("\n")}\n`;
236
+ }
237
+ export function renderRequestEventContinuation(snapshot, fromIndex, color = false) {
238
+ const eventSteps = flattenRequestExecutionSteps(snapshot).slice(fromIndex);
239
+ if (eventSteps.length === 0) {
240
+ return "";
241
+ }
242
+ const muted = (s) => applyAnsi(s, "2", color);
243
+ const lines = [`${muted("events (continued)")}`];
244
+ eventSteps.forEach((step, index) => {
245
+ lines.push(renderRequestStepLine(step, "", index === eventSteps.length - 1, snapshot.activeEventId, color));
246
+ });
247
+ return `${lines.join("\n")}\n`;
248
+ }
249
+ export function buildTodoContinuationSignature(snapshot) {
250
+ return snapshot.plan.items
251
+ .map((item) => [
252
+ item.id ?? "",
253
+ item.content,
254
+ item.status,
255
+ item.ownerAgentId ?? "",
256
+ item.startedAt ?? "",
257
+ item.endedAt ?? "",
258
+ ].join("|"))
259
+ .join(";");
260
+ }
261
+ export function renderRequestTodoContinuation(snapshot, previousSignature, color = false) {
262
+ const nextSignature = buildTodoContinuationSignature(snapshot);
263
+ if (!nextSignature || nextSignature === previousSignature || snapshot.plan.items.length === 0) {
264
+ return "";
265
+ }
266
+ const muted = (s) => applyAnsi(s, "2", color);
267
+ const lines = [`${muted("todos (continued)")}`];
268
+ snapshot.plan.items.forEach((todo, index) => {
269
+ const tIcon = statusIcon(todo.status, color);
270
+ const todoTimeRange = renderTimeRange(todo.startedAt, todo.endedAt, undefined, color);
271
+ const todoContent = color ? `\x1b[38;5;253m${todo.content}\x1b[0m` : todo.content;
272
+ lines.push(`${formatTreeBranch(index === snapshot.plan.items.length - 1)} ${tIcon} ${todoContent}${todoTimeRange}`);
273
+ });
274
+ return `${lines.join("\n")}\n`;
275
+ }
276
+ export function buildTerminalRequestSnapshot(snapshot, result) {
277
+ return {
278
+ ...snapshot,
279
+ state: result.state,
280
+ updatedAt: new Date().toISOString(),
281
+ output: result.output,
282
+ activeEventId: undefined,
283
+ };
284
+ }
285
+ export function summarizeRequestOutput(output, color) {
286
+ const trimmed = output.trim();
287
+ if (!trimmed) {
288
+ return applyAnsi("empty", "2", color);
289
+ }
290
+ const normalized = trimmed.replace(/\s+/g, " ");
291
+ const preview = normalized.length > 72 ? `${normalized.slice(0, 69)}...` : normalized;
292
+ return applyAnsi(preview, "2", color);
293
+ }
294
+ export function buildExecutionStepContinuationKey(step) {
295
+ return buildExecutionStepEventKey(step);
296
+ }
@@ -0,0 +1,15 @@
1
+ import { createAgentHarness } from "../api.js";
2
+ import { createAgentHarnessClient } from "../client.js";
3
+ import { sleep } from "./managed-service.js";
4
+ type RuntimeCommandIo = {
5
+ cwd: string;
6
+ stdout: (message: string) => void;
7
+ stderr: (message: string) => void;
8
+ };
9
+ type RuntimeCommandDeps = {
10
+ createHarness: typeof createAgentHarness;
11
+ createClient?: typeof createAgentHarnessClient;
12
+ sleep: typeof sleep;
13
+ };
14
+ export declare function handleRuntimeCommand(subcommandAndArgs: string[], io: RuntimeCommandIo, deps: RuntimeCommandDeps): Promise<number>;
15
+ export {};