@botbotgo/agent-harness 0.0.309 → 0.0.311
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.
- package/README.md +14 -0
- package/README.zh.md +14 -0
- package/dist/acp.d.ts +1 -116
- package/dist/acp.js +1 -310
- package/dist/api.d.ts +1 -1
- package/dist/api.js +1 -1
- package/dist/cli/chat-interactive.d.ts +24 -0
- package/dist/cli/chat-interactive.js +244 -0
- package/dist/cli/chat-rendering.d.ts +9 -0
- package/dist/cli/chat-rendering.js +102 -0
- package/dist/cli/chat-stream.d.ts +23 -0
- package/dist/cli/chat-stream.js +330 -0
- package/dist/cli/chat-ui.d.ts +20 -0
- package/dist/cli/chat-ui.js +198 -0
- package/dist/cli/chat-workspace.d.ts +15 -0
- package/dist/cli/chat-workspace.js +205 -0
- package/dist/cli/main.d.ts +52 -0
- package/dist/cli/main.js +323 -0
- package/dist/cli/managed-service-commands.d.ts +23 -0
- package/dist/cli/managed-service-commands.js +63 -0
- package/dist/cli/managed-service.d.ts +27 -0
- package/dist/cli/managed-service.js +61 -0
- package/dist/cli/options-init-chat.d.ts +16 -0
- package/dist/cli/options-init-chat.js +108 -0
- package/dist/cli/options-runtime.d.ts +27 -0
- package/dist/cli/options-runtime.js +158 -0
- package/dist/cli/options-serve.d.ts +24 -0
- package/dist/cli/options-serve.js +166 -0
- package/dist/cli/options.d.ts +5 -0
- package/dist/cli/options.js +47 -0
- package/dist/cli/process-guards.d.ts +14 -0
- package/dist/cli/process-guards.js +139 -0
- package/dist/cli/request-tree.d.ts +12 -0
- package/dist/cli/request-tree.js +296 -0
- package/dist/cli/runtime-commands.d.ts +15 -0
- package/dist/cli/runtime-commands.js +247 -0
- package/dist/cli/runtime-output.d.ts +5 -0
- package/dist/cli/runtime-output.js +124 -0
- package/dist/cli/server-commands.d.ts +36 -0
- package/dist/cli/server-commands.js +250 -0
- package/dist/cli/workspace.d.ts +6 -0
- package/dist/cli/workspace.js +71 -0
- package/dist/cli.d.ts +1 -77
- package/dist/cli.js +2 -3023
- package/dist/client/acp.d.ts +1 -50
- package/dist/client/acp.js +1 -219
- package/dist/client/in-process.d.ts +5 -5
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.js +1 -1
- package/dist/contracts/runtime-evaluation.d.ts +103 -0
- package/dist/contracts/runtime-evaluation.js +1 -0
- package/dist/contracts/runtime-memory.d.ts +162 -0
- package/dist/contracts/runtime-memory.js +1 -0
- package/dist/contracts/runtime-observability.d.ts +248 -0
- package/dist/contracts/runtime-observability.js +1 -0
- package/dist/contracts/runtime-requests.d.ts +342 -0
- package/dist/contracts/runtime-requests.js +1 -0
- package/dist/contracts/runtime-scheduling.d.ts +146 -0
- package/dist/contracts/runtime-scheduling.js +1 -0
- package/dist/contracts/runtime.d.ts +5 -1042
- package/dist/contracts/runtime.js +27 -1
- package/dist/flow/build-flow-graph.js +4 -875
- package/dist/flow/flow-graph-normalization.d.ts +56 -0
- package/dist/flow/flow-graph-normalization.js +214 -0
- package/dist/flow/flow-graph-runtime.d.ts +8 -0
- package/dist/flow/flow-graph-runtime.js +107 -0
- package/dist/flow/flow-graph-upstream.d.ts +18 -0
- package/dist/flow/flow-graph-upstream.js +498 -0
- package/dist/flow/types.d.ts +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/init-project.d.ts +1 -12
- package/dist/init-project.js +1 -651
- package/dist/{procedural → knowledge/procedural}/manager.d.ts +3 -3
- package/dist/{procedural → knowledge/procedural}/manager.js +6 -6
- package/dist/mcp.d.ts +2 -76
- package/dist/mcp.js +2 -428
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/persistence/file-store.js +1 -1
- package/dist/persistence/sqlite-runtime.d.ts +19 -0
- package/dist/persistence/sqlite-runtime.js +86 -0
- package/dist/persistence/sqlite-store.js +11 -99
- package/dist/{request-events.d.ts → projections/request-events.d.ts} +1 -1
- package/dist/{upstream-events.js → projections/upstream-events.js} +1 -1
- package/dist/protocol/a2a/http-discovery.d.ts +39 -0
- package/dist/protocol/a2a/http-discovery.js +178 -0
- package/dist/protocol/a2a/http-rpc.d.ts +28 -0
- package/dist/protocol/a2a/http-rpc.js +623 -0
- package/dist/protocol/a2a/http.d.ts +72 -1
- package/dist/protocol/a2a/http.js +14 -1124
- package/dist/protocol/a2a/task-state.d.ts +29 -0
- package/dist/protocol/a2a/task-state.js +317 -0
- package/dist/protocol/acp/client.js +1 -1
- package/dist/protocol/acp/harness-client.d.ts +50 -0
- package/dist/protocol/acp/harness-client.js +219 -0
- package/dist/protocol/acp/server.d.ts +116 -0
- package/dist/protocol/acp/server.js +310 -0
- package/dist/protocol/ag-ui/http.js +1 -1
- package/dist/protocol/mcp/server.d.ts +76 -0
- package/dist/protocol/mcp/server.js +428 -0
- package/dist/resource/backend/workspace-scoped-backend.d.ts +40 -0
- package/dist/resource/backend/workspace-scoped-backend.js +296 -0
- package/dist/resource/mcp/tool-support.d.ts +35 -0
- package/dist/resource/mcp/tool-support.js +296 -0
- package/dist/resource/mcp-tool-support.d.ts +2 -35
- package/dist/resource/mcp-tool-support.js +2 -296
- package/dist/resource/providers/resource-provider.d.ts +22 -0
- package/dist/resource/providers/resource-provider.js +215 -0
- package/dist/resource/resource-impl.d.ts +3 -33
- package/dist/resource/resource-impl.js +2 -808
- package/dist/resource/resource-types.d.ts +33 -0
- package/dist/resource/resource-types.js +1 -0
- package/dist/resource/tools/function-tool-resolver.d.ts +2 -0
- package/dist/resource/tools/function-tool-resolver.js +306 -0
- package/dist/runtime/adapter/middleware-assembly.js +1 -1
- package/dist/runtime/adapter/model/invocation-request.js +2 -2
- package/dist/runtime/adapter/model/message-assembly.js +1 -1
- package/dist/runtime/agent-runtime-adapter.d.ts +3 -63
- package/dist/runtime/agent-runtime-adapter.js +7 -235
- package/dist/runtime/agent-runtime-assembly.d.ts +67 -0
- package/dist/runtime/agent-runtime-assembly.js +211 -0
- package/dist/runtime/harness/background-runtime.d.ts +1 -1
- package/dist/runtime/harness/events/event-sink.js +1 -1
- package/dist/runtime/harness/events/runtime-event-operations.d.ts +1 -1
- package/dist/runtime/harness/events/streaming.js +1 -1
- package/dist/runtime/harness/public-shapes.d.ts +43 -0
- package/dist/runtime/harness/public-shapes.js +186 -0
- package/dist/runtime/harness/run/inspection.js +2 -2
- package/dist/runtime/harness/run/resources.js +1 -1
- package/dist/runtime/harness/run/surface-semantics.js +1 -1
- package/dist/runtime/harness/system/inventory.d.ts +1 -1
- package/dist/runtime/harness/system/inventory.js +2 -2
- package/dist/runtime/harness/system/policy-engine.js +1 -1
- package/dist/runtime/harness/system/runtime-memory-manager.js +1 -1
- package/dist/runtime/harness/system/skill-requirements.d.ts +1 -1
- package/dist/runtime/harness/system/skill-requirements.js +1 -1
- package/dist/runtime/harness.d.ts +2 -2
- package/dist/runtime/harness.js +7 -191
- package/dist/runtime/maintenance/checkpoint-maintenance.js +1 -1
- package/dist/runtime/maintenance/runtime-record-maintenance.js +1 -1
- package/dist/runtime/parsing/output-content.d.ts +11 -0
- package/dist/runtime/parsing/output-content.js +442 -0
- package/dist/runtime/parsing/output-parsing.d.ts +3 -29
- package/dist/runtime/parsing/output-parsing.js +3 -806
- package/dist/runtime/parsing/output-recovery.d.ts +14 -0
- package/dist/runtime/parsing/output-recovery.js +288 -0
- package/dist/runtime/parsing/output-tool-args.d.ts +4 -0
- package/dist/runtime/parsing/output-tool-args.js +120 -0
- package/dist/runtime/support/runtime-factories.js +1 -1
- package/dist/scaffold/init-project.d.ts +12 -0
- package/dist/scaffold/init-project.js +651 -0
- package/dist/{extensions.d.ts → tooling/extensions.d.ts} +1 -1
- package/dist/{extensions.js → tooling/extensions.js} +3 -3
- package/dist/{tool-modules.d.ts → tooling/module-loader.d.ts} +1 -1
- package/dist/{tool-modules.js → tooling/module-loader.js} +2 -2
- package/dist/workspace/agent-binding-compiler.js +2 -2
- package/dist/workspace/compile.js +2 -2
- package/dist/workspace/object-loader-paths.d.ts +11 -0
- package/dist/workspace/object-loader-paths.js +75 -0
- package/dist/workspace/object-loader-readers.d.ts +21 -0
- package/dist/workspace/object-loader-readers.js +187 -0
- package/dist/workspace/object-loader.d.ts +0 -1
- package/dist/workspace/object-loader.js +6 -260
- package/dist/workspace/resource-compilers.js +1 -1
- package/dist/workspace/support/discovery.js +1 -1
- package/package.json +1 -1
- package/dist/runtime/adapter/index.d.ts +0 -13
- package/dist/runtime/adapter/index.js +0 -13
- package/dist/runtime/harness/index.d.ts +0 -19
- package/dist/runtime/harness/index.js +0 -19
- package/dist/runtime/maintenance/index.d.ts +0 -4
- package/dist/runtime/maintenance/index.js +0 -4
- package/dist/runtime/parsing/index.d.ts +0 -2
- package/dist/runtime/parsing/index.js +0 -2
- package/dist/runtime/support/index.d.ts +0 -4
- package/dist/runtime/support/index.js +0 -4
- package/dist/workspace/support/index.d.ts +0 -2
- package/dist/workspace/support/index.js +0 -2
- /package/dist/{procedural → knowledge/procedural}/config.d.ts +0 -0
- /package/dist/{procedural → knowledge/procedural}/config.js +0 -0
- /package/dist/{procedural → knowledge/procedural}/index.d.ts +0 -0
- /package/dist/{procedural → knowledge/procedural}/index.js +0 -0
- /package/dist/{presentation.d.ts → projections/presentation.d.ts} +0 -0
- /package/dist/{presentation.js → projections/presentation.js} +0 -0
- /package/dist/{request-events.js → projections/request-events.js} +0 -0
- /package/dist/{upstream-events.d.ts → projections/upstream-events.d.ts} +0 -0
- /package/dist/runtime/{support → env}/runtime-env.d.ts +0 -0
- /package/dist/runtime/{support → env}/runtime-env.js +0 -0
- /package/dist/runtime/{support → layout}/runtime-layout.d.ts +0 -0
- /package/dist/runtime/{support → layout}/runtime-layout.js +0 -0
- /package/dist/runtime/{support → prompts}/runtime-prompts.d.ts +0 -0
- /package/dist/runtime/{support → prompts}/runtime-prompts.js +0 -0
- /package/dist/runtime/{support → skills}/skill-metadata.d.ts +0 -0
- /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 {};
|