@dimi-agent/cli 0.6.6 → 0.6.8
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/dist/main.mjs +2383 -94
- package/package.json +4 -4
package/dist/main.mjs
CHANGED
|
@@ -34346,7 +34346,7 @@ var init_telemetry$2 = __esmMin((() => {
|
|
|
34346
34346
|
};
|
|
34347
34347
|
ITelemetryService = createDecorator("agentTelemetryService");
|
|
34348
34348
|
}));
|
|
34349
|
-
var init_events$
|
|
34349
|
+
var init_events$8 = __esmMin((() => {}));
|
|
34350
34350
|
//#endregion
|
|
34351
34351
|
//#region ../../packages/agent-core-v2/src/app/telemetry/telemetryService.ts
|
|
34352
34352
|
var TelemetryService, TelemetryContextView;
|
|
@@ -99307,6 +99307,11 @@ function loadNative() {
|
|
|
99307
99307
|
function coldRebuild(recordsJson) {
|
|
99308
99308
|
return loadNative().coldRebuild(recordsJson);
|
|
99309
99309
|
}
|
|
99310
|
+
/** Release an agent's scoped subagent registry (tasks + steering queues).
|
|
99311
|
+
* Call when the owning agent scope is disposed. */
|
|
99312
|
+
function dropTaskRegistry(registryId) {
|
|
99313
|
+
loadNative().dropTaskRegistry(registryId);
|
|
99314
|
+
}
|
|
99310
99315
|
/** `RustHostProcess.spawn` — the M2 exec spawn socket. */
|
|
99311
99316
|
async function rustHostProcessSpawn(command, args, options) {
|
|
99312
99317
|
return loadNative().RustHostProcess.spawn(command, [...args], options);
|
|
@@ -99337,7 +99342,7 @@ function rustHostEnvironmentProbe() {
|
|
|
99337
99342
|
function rustTerminalSpawn(options) {
|
|
99338
99343
|
return loadNative().RustTerminal.spawn(options);
|
|
99339
99344
|
}
|
|
99340
|
-
var nodeRequire$4, binding, PLATFORM_SUBPACKAGE, RustAgentTranscript, RustFileSystem;
|
|
99345
|
+
var nodeRequire$4, binding, PLATFORM_SUBPACKAGE, RustAgentTranscript, RustFileSystem, RustTurnSession;
|
|
99341
99346
|
var init_src$7 = __esmMin((() => {
|
|
99342
99347
|
nodeRequire$4 = createRequire(import.meta.url);
|
|
99343
99348
|
PLATFORM_SUBPACKAGE = `@dimi-agent/dimi-native-${process.platform}-${process.arch}`;
|
|
@@ -99397,6 +99402,89 @@ var init_src$7 = __esmMin((() => {
|
|
|
99397
99402
|
return loadNative().RustFileSystem.realpath(path);
|
|
99398
99403
|
}
|
|
99399
99404
|
};
|
|
99405
|
+
RustTurnSession = class {
|
|
99406
|
+
#inner;
|
|
99407
|
+
constructor(inputJson, policyJson, scriptedSegmentsJson, registryId) {
|
|
99408
|
+
const NativeClass = loadNative().RustTurnSession;
|
|
99409
|
+
this.#inner = new NativeClass(inputJson, policyJson, scriptedSegmentsJson ?? null, registryId);
|
|
99410
|
+
}
|
|
99411
|
+
/** Release the agent-scoped subagent registry (tasks + steering queues).
|
|
99412
|
+
* Call when the owning agent scope is disposed. */
|
|
99413
|
+
static dropTaskRegistry(registryId) {
|
|
99414
|
+
dropTaskRegistry(registryId);
|
|
99415
|
+
}
|
|
99416
|
+
/** Register the per-event callback: every engine event emitted by `run()` /
|
|
99417
|
+
* `resume()` is pushed through it as a JSON string, in emission order, as
|
|
99418
|
+
* it happens. Register before the first `run()`. */
|
|
99419
|
+
setOnEvent(callback) {
|
|
99420
|
+
this.#inner.setOnEvent(callback);
|
|
99421
|
+
}
|
|
99422
|
+
async run() {
|
|
99423
|
+
return this.#inner.run();
|
|
99424
|
+
}
|
|
99425
|
+
async resume(decisionJson) {
|
|
99426
|
+
return this.#inner.resume(decisionJson);
|
|
99427
|
+
}
|
|
99428
|
+
/** Record a session-scope approval (P1-6): the engine's policy is re-read
|
|
99429
|
+
* on every run/resume, so a pattern approved for the session mid-turn is
|
|
99430
|
+
* honored by the SAME turn's remaining batch. */
|
|
99431
|
+
addSessionApproval(pattern) {
|
|
99432
|
+
this.#inner.addSessionApproval(pattern);
|
|
99433
|
+
}
|
|
99434
|
+
/** Register the native-tool PreToolUse gate (A2 review): every registry
|
|
99435
|
+
* tool call is announced through `callback` (`{requestId, toolName,
|
|
99436
|
+
* arguments}` JSON); answer with `completeToolGate(requestId,
|
|
99437
|
+
* {decision:'allow'|'block', reason?})`. A block short-circuits the call. */
|
|
99438
|
+
setToolGate(callback) {
|
|
99439
|
+
this.#inner.setToolGate(callback);
|
|
99440
|
+
}
|
|
99441
|
+
/** Answer a pending gate request (see `setToolGate`). */
|
|
99442
|
+
completeToolGate(requestId, verdictJson) {
|
|
99443
|
+
this.#inner.completeToolGate(requestId, verdictJson);
|
|
99444
|
+
}
|
|
99445
|
+
/** Register a TS-side tool; `completeToolCall` finishes each call. The
|
|
99446
|
+
* definition (description + JSON parameters schema) is advertised to the
|
|
99447
|
+
* model from the next request on. */
|
|
99448
|
+
registerExternalTool(name, description, parametersJson, callback) {
|
|
99449
|
+
this.#inner.registerExternalTool(name, description, parametersJson, callback);
|
|
99450
|
+
}
|
|
99451
|
+
/** Advertise the LLM-facing definition (description + JSON parameters
|
|
99452
|
+
* schema) of a Rust-native tool (Agent / AgentOutput / WaitFor) registered
|
|
99453
|
+
* executor-first at construction. The executor stays the same; only the
|
|
99454
|
+
* def is updated, so the engine's request `tools` field carries it from
|
|
99455
|
+
* the next request on. */
|
|
99456
|
+
registerNativeToolDef(name, description, parametersJson) {
|
|
99457
|
+
this.#inner.registerNativeToolDef(name, description, parametersJson);
|
|
99458
|
+
}
|
|
99459
|
+
/** Steer the running turn (drained into its next LLM request). Returns
|
|
99460
|
+
* `false` when the turn has already finished — the caller must start a
|
|
99461
|
+
* new turn instead (the steer is never dropped). */
|
|
99462
|
+
steer(message) {
|
|
99463
|
+
return this.#inner.steer(message);
|
|
99464
|
+
}
|
|
99465
|
+
/** Steer a background subagent spawned by the `Agent` tool. */
|
|
99466
|
+
steerSubagent(agentId, message) {
|
|
99467
|
+
this.#inner.steerSubagent(agentId, message);
|
|
99468
|
+
}
|
|
99469
|
+
/** Cancel the running turn (engine stops at the next boundary). */
|
|
99470
|
+
cancel() {
|
|
99471
|
+
this.#inner.cancel();
|
|
99472
|
+
}
|
|
99473
|
+
/** Cancel a background task (TaskStop parity): the engine kills the
|
|
99474
|
+
* subagent nested turn / backgrounded bash command and settles "killed",
|
|
99475
|
+
* carrying the stop reason on the wire. */
|
|
99476
|
+
cancelTask(taskId, reason) {
|
|
99477
|
+
this.#inner.cancelTask(taskId, reason);
|
|
99478
|
+
}
|
|
99479
|
+
/** Close the session (agent dispose): task events stop forwarding, the
|
|
99480
|
+
* in-flight turn is cancelled. Background workers observe the close. */
|
|
99481
|
+
close() {
|
|
99482
|
+
this.#inner.close();
|
|
99483
|
+
}
|
|
99484
|
+
completeToolCall(requestId, resultJson) {
|
|
99485
|
+
this.#inner.completeToolCall(requestId, resultJson);
|
|
99486
|
+
}
|
|
99487
|
+
};
|
|
99400
99488
|
}));
|
|
99401
99489
|
//#endregion
|
|
99402
99490
|
//#region ../../packages/agent-core-v2/src/os/backends/rust-local/rustHostEnvironmentService.ts
|
|
@@ -104346,7 +104434,7 @@ var init_abort = __esmMin((() => {
|
|
|
104346
104434
|
//#region ../../packages/agent-core-v2/src/agent/tools/os/bash/bash.md?raw
|
|
104347
104435
|
var bash_default;
|
|
104348
104436
|
var init_bash = __esmMin((() => {
|
|
104349
|
-
bash_default = "Execute a `${SHELL_NAME}` command. Use this for shell semantics — pipes, env, processes, git, package managers, build/test runners, anything genuinely interactive or multi-step.\n\n**Translate these to a dedicated tool instead:**\n- `cat` / `head` / `tail` (known path) → `Read`\n- `sed` / `awk` (in-place edit) → `Edit`\n- `echo > file` / `cat <<EOF` → `Write`\n- `find` / recursive `ls` to locate files by name pattern → `Glob` (plain `ls <known-directory>` is fine for listing a directory)\n- `grep` / `rg` (search file contents) → `Grep`\n- `echo` / `printf` (talk to the user) → just output text directly\n\nThe dedicated tools render in the per-tool permission UI and keep raw stdout out of the conversation; that is why they are worth reaching for whenever one fits.\n\n**Output:**\nThe stdout and stderr will be combined and returned as a string. The output may be truncated if it is too long. If the command exits non-zero, the output ends with a `Command failed with exit code: N` line; a command killed by its timeout or interrupted by the user ends with its own message instead.\n\nIf `run_in_background=true`, the command will be started as a background task and this tool will return a task ID instead of waiting for command completion. When doing that, you must provide a short `description`. Background commands default to a ${DEFAULT_BACKGROUND_TIMEOUT_S}s timeout and `timeout` is capped at ${MAX_BACKGROUND_TIMEOUT_S}s; set `disable_timeout=true` only when the task should run without a timeout. You will be automatically notified when the task completes. After starting one, default to returning control to the user instead of immediately waiting on it. Use `TaskOutput` only for a non-blocking status/output snapshot — do not wait on a task you just launched, since its completion arrives automatically. Use `TaskStop` only if the task must be cancelled. If a human user wants to inspect background tasks themselves, point them to the `/tasks` command, which opens an interactive panel; it has no subcommands.\n\n**Guidelines for safety and security:**\n- Each shell tool call will be executed in a fresh shell environment. The shell variables, current working directory changes, and the shell history is not preserved between calls. To run a command in a particular directory, pass the `cwd` argument (or use absolute paths) rather than relying on a `cd` from an earlier call.\n- The tool call will return after the command is finished. You shall not use this tool to execute an interactive command or a command that may run forever. For possibly long-running foreground commands, set the `timeout` argument in seconds. Foreground commands default to ${DEFAULT_TIMEOUT_S}s and allow up to ${MAX_TIMEOUT_S}s. When a foreground command hits its timeout it is moved to the background instead of being killed, and you will be automatically notified when it completes.\n- Avoid using `..` to access files or directories outside of the working directory.\n- Avoid modifying files outside of the working directory unless explicitly instructed to do so.\n- Never run commands that require superuser privileges unless explicitly instructed to do so.\n\n**Guidelines for efficiency:**\n- Use `&&` to chain commands that genuinely depend on each other, e.g. `npm install && npm test`. Independent read-only commands (separate `git show`, `ls`, or status checks) should be issued as separate parallel Bash calls in one response, not chained into a single call — chaining serializes their execution and mixes their output. Do not stitch outputs together with `echo` separators.\n- Use `;` to run commands sequentially regardless of success/failure\n- Use `||` for conditional execution (run second command only if first fails)\n- Use pipe operations (`|`) and redirections (`>`, `>>`) to chain input and output between commands\n- Always quote file paths containing spaces with double quotes (e.g., cd \"/path with spaces/\")\n- Compose multi-step logic in a single call with `if` / `case` / `for` / `while` control flows.\n- Prefer `run_in_background=true` for long-running builds, tests, watchers, or servers when you need the conversation to continue before the command finishes.\n\n**Commands available:**\nThe following common command categories are usually available. Availability still depends on the host, so when in doubt run `which <command>` first to confirm a command exists before relying on it.\n- Navigation and inspection: `ls`, `pwd`, `cd`, `stat`, `file`, `du`, `df`, `tree`\n- File and directory management: `cp`, `mv`, `rm`, `mkdir`, `touch`, `ln`, `chmod`, `chown`\n- Text and data processing: `wc`, `sort`, `uniq`, `cut`, `tr`, `diff`, `xargs`\n- Archives and compression: `tar`, `gzip`, `gunzip`, `zip`, `unzip`\n- Networking and transfer: `curl`, `wget`, `ping`, `ssh`, `scp`\n- Version control: `git`; for GitHub-hosted work (PRs, issues, CI runs, API queries) prefer the `gh` CLI when installed — it carries the user's GitHub auth and can return structured JSON\n- Process and system: `ps`, `kill`, `top`, `env`, `date`, `uname`, `whoami`\n- Language and package toolchains: `node`, `npm`, `pnpm`, `yarn`, `python`, `pip` (use whichever the project actually relies on)\n";
|
|
104437
|
+
bash_default = "Execute a `${SHELL_NAME}` command. Use this for shell semantics — pipes, env, processes, git, package managers, build/test runners, anything genuinely interactive or multi-step.\n\n**Translate these to a dedicated tool instead:**\n- `cat` / `head` / `tail` (known path) → `Read`\n- `sed` / `awk` (in-place edit) → `Edit`\n- `echo > file` / `cat <<EOF` → `Write`\n- `find` / recursive `ls` to locate files by name pattern → `Glob` (plain `ls <known-directory>` is fine for listing a directory)\n- `grep` / `rg` (search file contents) → `Grep`\n- `echo` / `printf` (talk to the user) → just output text directly\n\nThe dedicated tools render in the per-tool permission UI and keep raw stdout out of the conversation; that is why they are worth reaching for whenever one fits.\n\n**Output:**\nThe stdout and stderr will be combined and returned as a string. The output may be truncated if it is too long. If the command exits non-zero, the output ends with a `Command failed with exit code: N` line; a command killed by its timeout or interrupted by the user ends with its own message instead.\n\nIf `run_in_background=true`, the command will be started as a background task and this tool will return a task ID instead of waiting for command completion. When doing that, you must provide a short `description`. Background commands default to a ${DEFAULT_BACKGROUND_TIMEOUT_S}s timeout and `timeout` is capped at ${MAX_BACKGROUND_TIMEOUT_S}s; set `disable_timeout=true` only when the task should run without a timeout. You will be automatically notified when the task completes. After starting one, default to returning control to the user instead of immediately waiting on it. Use `TaskOutput` only for a non-blocking status/output snapshot — do not wait on a task you just launched, since its completion arrives automatically. Use `TaskStop` only if the task must be cancelled. If a human user wants to inspect background tasks themselves, point them to the `/tasks` command, which opens an interactive panel; it has no subcommands.\n\n**Detached processes:** If a command leaves processes running in its process group after the shell exits (e.g. `nohup … &`, `… &`, `disown`), the result includes a notice listing them. Those processes are not tracked by dimi: you will not be notified when they finish, `TaskStop` cannot stop them, and a `WaitFor` only wakes on timeout. If the detach was intentional (e.g. starting a daemon), you may ignore the notice; otherwise prefer `run_in_background=true` so dimi manages the process and notifies you. Note this detection covers processes that stayed in the command's process group; a process that deliberately escapes to its own session (e.g. daemonizers, `setsid`) is not detectable after the command exits and is typically intentional.\n\n**Guidelines for safety and security:**\n- Each shell tool call will be executed in a fresh shell environment. The shell variables, current working directory changes, and the shell history is not preserved between calls. To run a command in a particular directory, pass the `cwd` argument (or use absolute paths) rather than relying on a `cd` from an earlier call.\n- The tool call will return after the command is finished. You shall not use this tool to execute an interactive command or a command that may run forever. For possibly long-running foreground commands, set the `timeout` argument in seconds. Foreground commands default to ${DEFAULT_TIMEOUT_S}s and allow up to ${MAX_TIMEOUT_S}s. When a foreground command hits its timeout it is moved to the background instead of being killed, and you will be automatically notified when it completes.\n- Avoid using `..` to access files or directories outside of the working directory.\n- Avoid modifying files outside of the working directory unless explicitly instructed to do so.\n- Never run commands that require superuser privileges unless explicitly instructed to do so.\n\n**Guidelines for efficiency:**\n- Use `&&` to chain commands that genuinely depend on each other, e.g. `npm install && npm test`. Independent read-only commands (separate `git show`, `ls`, or status checks) should be issued as separate parallel Bash calls in one response, not chained into a single call — chaining serializes their execution and mixes their output. Do not stitch outputs together with `echo` separators.\n- Use `;` to run commands sequentially regardless of success/failure\n- Use `||` for conditional execution (run second command only if first fails)\n- Use pipe operations (`|`) and redirections (`>`, `>>`) to chain input and output between commands\n- Always quote file paths containing spaces with double quotes (e.g., cd \"/path with spaces/\")\n- Compose multi-step logic in a single call with `if` / `case` / `for` / `while` control flows.\n- Prefer `run_in_background=true` for long-running builds, tests, watchers, or servers when you need the conversation to continue before the command finishes.\n\n**Commands available:**\nThe following common command categories are usually available. Availability still depends on the host, so when in doubt run `which <command>` first to confirm a command exists before relying on it.\n- Navigation and inspection: `ls`, `pwd`, `cd`, `stat`, `file`, `du`, `df`, `tree`\n- File and directory management: `cp`, `mv`, `rm`, `mkdir`, `touch`, `ln`, `chmod`, `chown`\n- Text and data processing: `wc`, `sort`, `uniq`, `cut`, `tr`, `diff`, `xargs`\n- Archives and compression: `tar`, `gzip`, `gunzip`, `zip`, `unzip`\n- Networking and transfer: `curl`, `wget`, `ping`, `ssh`, `scp`\n- Version control: `git`; for GitHub-hosted work (PRs, issues, CI runs, API queries) prefer the `gh` CLI when installed — it carries the user's GitHub auth and can return structured JSON\n- Process and system: `ps`, `kill`, `top`, `env`, `date`, `uname`, `whoami`\n- Language and package toolchains: `node`, `npm`, `pnpm`, `yarn`, `python`, `pip` (use whichever the project actually relies on)\n";
|
|
104350
104438
|
}));
|
|
104351
104439
|
//#endregion
|
|
104352
104440
|
//#region ../../packages/agent-core-v2/src/agent/tools/os/bash/process-task.ts
|
|
@@ -104571,6 +104659,75 @@ function foregroundDescription(args) {
|
|
|
104571
104659
|
if (explicit !== void 0 && explicit.length > 0) return explicit;
|
|
104572
104660
|
return `Bash: ${args.command.length > 60 ? `${args.command.slice(0, 60)}…` : args.command}`;
|
|
104573
104661
|
}
|
|
104662
|
+
/**
|
|
104663
|
+
* Detect processes that outlived the command's process group on Unix.
|
|
104664
|
+
*
|
|
104665
|
+
* dimi spawns every shell in its own session/process group (`setsid`, pid ==
|
|
104666
|
+
* sid == pgid), so `nohup`/`&`/`disown` children that survive the shell stay
|
|
104667
|
+
* in that same process group. Probing `kill(-pid, 0)` (process-group kill)
|
|
104668
|
+
* tells us whether any process is still there after the command finished;
|
|
104669
|
+
* `ps -g <pid>` then lists who.
|
|
104670
|
+
*
|
|
104671
|
+
* Scope: this covers processes that stayed in the command's process group
|
|
104672
|
+
* (the common accidental detach: `nohup … &`, `… &`, `disown`). A process
|
|
104673
|
+
* that actively escapes (calls `setsid`, or moves to its own group with
|
|
104674
|
+
* `setpgid`/`setpgrp`, e.g. daemonizers, `start_new_session=True`, node
|
|
104675
|
+
* `{detached:true}`) leaves the group entirely and cannot be attributed back
|
|
104676
|
+
* after the shell exits — such escapes are typically intentional and are out
|
|
104677
|
+
* of scope here. Windows has no session/process-group kill, so detection is
|
|
104678
|
+
* skipped there (returns []).
|
|
104679
|
+
*/
|
|
104680
|
+
async function detectDetachedProcesses(pid) {
|
|
104681
|
+
if (process.platform === "win32" || !Number.isInteger(pid) || pid <= 0) return [];
|
|
104682
|
+
let alive = false;
|
|
104683
|
+
try {
|
|
104684
|
+
process.kill(-pid, 0);
|
|
104685
|
+
alive = true;
|
|
104686
|
+
} catch (error) {
|
|
104687
|
+
alive = error.code === "EPERM";
|
|
104688
|
+
}
|
|
104689
|
+
if (!alive) return [];
|
|
104690
|
+
return listProcessGroupProcesses(pid);
|
|
104691
|
+
}
|
|
104692
|
+
async function listProcessGroupProcesses(pid) {
|
|
104693
|
+
const { execFile } = await import("node:child_process");
|
|
104694
|
+
const ps = await new Promise((resolve) => {
|
|
104695
|
+
execFile("ps", [
|
|
104696
|
+
"-o",
|
|
104697
|
+
"pid=,ppid=,command=",
|
|
104698
|
+
"-g",
|
|
104699
|
+
String(pid)
|
|
104700
|
+
], (error, stdout) => {
|
|
104701
|
+
resolve(error === null ? stdout : "");
|
|
104702
|
+
});
|
|
104703
|
+
});
|
|
104704
|
+
const infos = [];
|
|
104705
|
+
for (const line of ps.split("\n")) {
|
|
104706
|
+
const trimmed = line.trim();
|
|
104707
|
+
if (trimmed.length === 0) continue;
|
|
104708
|
+
const match = /^(\d+)\s+(\d+)\s+(.*)$/.exec(trimmed);
|
|
104709
|
+
if (match === null) continue;
|
|
104710
|
+
const childPid = Number(match[1]);
|
|
104711
|
+
if (childPid === pid) continue;
|
|
104712
|
+
infos.push({
|
|
104713
|
+
pid: childPid,
|
|
104714
|
+
ppid: Number(match[2]),
|
|
104715
|
+
command: match[3] ?? ""
|
|
104716
|
+
});
|
|
104717
|
+
}
|
|
104718
|
+
return infos;
|
|
104719
|
+
}
|
|
104720
|
+
/**
|
|
104721
|
+
* Rendered guidance appended to a Bash result when the finished command left
|
|
104722
|
+
* detached processes behind. Informational only — the command result itself
|
|
104723
|
+
* is unchanged; the agent decides whether the detach was intended.
|
|
104724
|
+
*/
|
|
104725
|
+
function formatDetachedProcessNotice(infos) {
|
|
104726
|
+
return `
|
|
104727
|
+
|
|
104728
|
+
⚠ Command left processes running outside dimi control:
|
|
104729
|
+
${infos.map((info) => ` - pid ${String(info.pid)} (ppid ${String(info.ppid)}): ${info.command}`).join("\n")}\nThese processes are NOT tracked by dimi: dimi cannot notify you when they finish, cannot stop them with TaskStop, and a WaitFor will only wake on timeout. If this was intentional (e.g. starting a daemon), ignore this notice. Otherwise, prefer running the command with run_in_background=true so dimi manages it.`;
|
|
104730
|
+
}
|
|
104574
104731
|
async function killSpawnedProcess(proc) {
|
|
104575
104732
|
try {
|
|
104576
104733
|
await proc.kill("SIGTERM");
|
|
@@ -104581,6 +104738,15 @@ async function killSpawnedProcess(proc) {
|
|
|
104581
104738
|
function shellQuote(s) {
|
|
104582
104739
|
return `'${s.replaceAll("'", "'\\''")}'`;
|
|
104583
104740
|
}
|
|
104741
|
+
function partToResultText(part) {
|
|
104742
|
+
switch (part.type) {
|
|
104743
|
+
case "text": return part.text;
|
|
104744
|
+
case "think": return part.think;
|
|
104745
|
+
case "image_url": return "[image]";
|
|
104746
|
+
case "audio_url": return "[audio]";
|
|
104747
|
+
case "video_url": return "[video]";
|
|
104748
|
+
}
|
|
104749
|
+
}
|
|
104584
104750
|
function windowsPathToPosixPath(path) {
|
|
104585
104751
|
if (path.startsWith("\\\\")) return path.replaceAll("\\", "/");
|
|
104586
104752
|
const driveMatch = /^([A-Za-z]):(?:[\\/]|$)/.exec(path);
|
|
@@ -104819,7 +104985,31 @@ var init_bashTool = __esmMin((() => {
|
|
|
104819
104985
|
if (builder.nChars === 0) builder.write(`Process exited with code ${String(exitCode)}`);
|
|
104820
104986
|
result = builder.error(`Command failed with exit code: ${String(exitCode)}.`, { brief: `Failed with exit code: ${String(exitCode)}` });
|
|
104821
104987
|
}
|
|
104822
|
-
|
|
104988
|
+
const withReference = await this.addForegroundOutputReference(taskId, result);
|
|
104989
|
+
return this.addDetachedProcessNotice(proc, withReference);
|
|
104990
|
+
}
|
|
104991
|
+
/**
|
|
104992
|
+
* After a foreground command finishes, check whether it left processes
|
|
104993
|
+
* running in the command's process group (e.g. `nohup … &`) that dimi can
|
|
104994
|
+
* no longer track. When it did, append an informational notice to the
|
|
104995
|
+
* result — the exit code / error status is untouched, and the agent
|
|
104996
|
+
* decides whether the detach was intended. Processes that actively escape
|
|
104997
|
+
* to their own session/group (setsid, daemonizers) cannot be detected
|
|
104998
|
+
* after the shell exits and are out of scope.
|
|
104999
|
+
*/
|
|
105000
|
+
async addDetachedProcessNotice(proc, result) {
|
|
105001
|
+
const infos = await this.detectDetached(proc.pid);
|
|
105002
|
+
if (infos.length === 0) return result;
|
|
105003
|
+
const output = result.output;
|
|
105004
|
+
const text = typeof output === "string" ? output : output.map(partToResultText).join("");
|
|
105005
|
+
return {
|
|
105006
|
+
...result,
|
|
105007
|
+
output: `${text}${formatDetachedProcessNotice(infos)}`
|
|
105008
|
+
};
|
|
105009
|
+
}
|
|
105010
|
+
/** Overridable seam for tests: probe for processes that escaped the session. */
|
|
105011
|
+
detectDetached(pid) {
|
|
105012
|
+
return detectDetachedProcesses(pid);
|
|
104823
105013
|
}
|
|
104824
105014
|
async addForegroundOutputReference(taskId, result) {
|
|
104825
105015
|
if (!result.truncated) return result;
|
|
@@ -121834,7 +122024,7 @@ function emptyOutputSnapshot() {
|
|
|
121834
122024
|
function agentTaskNotificationChildren(output) {
|
|
121835
122025
|
if (output.fullOutputAvailable && output.outputPath !== void 0) return [renderOutputFileBlock(output.outputPath, output.outputSizeBytes)];
|
|
121836
122026
|
if (output.preview.length === 0) return void 0;
|
|
121837
|
-
return [renderOutputPreviewBlock(output)];
|
|
122027
|
+
return [renderOutputPreviewBlock$1(output)];
|
|
121838
122028
|
}
|
|
121839
122029
|
function renderOutputFileBlock(outputPath, outputSizeBytes) {
|
|
121840
122030
|
return [
|
|
@@ -121843,7 +122033,7 @@ function renderOutputFileBlock(outputPath, outputSizeBytes) {
|
|
|
121843
122033
|
"</output-file>"
|
|
121844
122034
|
].join("\n");
|
|
121845
122035
|
}
|
|
121846
|
-
function renderOutputPreviewBlock(output) {
|
|
122036
|
+
function renderOutputPreviewBlock$1(output) {
|
|
121847
122037
|
return [
|
|
121848
122038
|
`<output-preview bytes="${String(output.previewBytes)}" total_bytes="${String(output.outputSizeBytes)}" truncated="${String(output.truncated)}">`,
|
|
121849
122039
|
output.truncated ? `Showing the last ${String(output.previewBytes)} bytes. No persisted full output is available.` : "No persisted full output is available; this preview is the currently buffered task output.",
|
|
@@ -121925,7 +122115,7 @@ function errorMessage$7(error) {
|
|
|
121925
122115
|
if (error instanceof Error) return error.message;
|
|
121926
122116
|
return String(error);
|
|
121927
122117
|
}
|
|
121928
|
-
var TaskNotificationDeliveryModel, MAX_OUTPUT_BYTES, TERMINAL_OUTPUT_TAIL_BYTES, MAX_TASK_OUTPUT_BYTES,
|
|
122118
|
+
var TaskNotificationDeliveryModel, MAX_OUTPUT_BYTES, TERMINAL_OUTPUT_TAIL_BYTES, MAX_TASK_OUTPUT_BYTES, TASK_ID_ALPHABET, SESSION_CLOSED_REASON, NOTIFICATION_FALLBACK_PREVIEW_BYTES, ACTIVE_BACKGROUND_TASK_INJECTION_VARIANT, ACTIVE_BACKGROUND_TASK_GUIDANCE, TaskNotificationStepRequest, taskGhostsKey, taskScheduledNotificationKeysKey, taskDeliveredNotificationKeysKey, taskActiveTaskReminderPendingKey, AgentTaskService;
|
|
121929
122119
|
var init_taskService = __esmMin((() => {
|
|
121930
122120
|
init_dist$5();
|
|
121931
122121
|
init_scope();
|
|
@@ -121973,7 +122163,6 @@ var init_taskService = __esmMin((() => {
|
|
|
121973
122163
|
MAX_OUTPUT_BYTES = 1024 * 1024;
|
|
121974
122164
|
TERMINAL_OUTPUT_TAIL_BYTES = 4 * 1024;
|
|
121975
122165
|
MAX_TASK_OUTPUT_BYTES = 16 * 1024 * 1024;
|
|
121976
|
-
SIGTERM_GRACE_MS = 5e3;
|
|
121977
122166
|
TASK_ID_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyz";
|
|
121978
122167
|
SESSION_CLOSED_REASON = "Session closed";
|
|
121979
122168
|
NOTIFICATION_FALLBACK_PREVIEW_BYTES = 3e3;
|
|
@@ -122172,7 +122361,7 @@ var init_taskService = __esmMin((() => {
|
|
|
122172
122361
|
};
|
|
122173
122362
|
this.assertCanRegister(detached);
|
|
122174
122363
|
const entry = {
|
|
122175
|
-
taskId: generateTaskId(task.idPrefix),
|
|
122364
|
+
taskId: options.taskId ?? generateTaskId(task.idPrefix),
|
|
122176
122365
|
task,
|
|
122177
122366
|
handle: void 0,
|
|
122178
122367
|
outputChunks: [],
|
|
@@ -122482,7 +122671,7 @@ var init_taskService = __esmMin((() => {
|
|
|
122482
122671
|
entry.stopReason = options.stopReason;
|
|
122483
122672
|
if (entry.handle) entry.handle.cancel();
|
|
122484
122673
|
else entry.abortController.abort(options.abortReason);
|
|
122485
|
-
const graceMs = resolveAgentTaskConfig(this.config)?.killGracePeriodMs ??
|
|
122674
|
+
const graceMs = resolveAgentTaskConfig(this.config)?.killGracePeriodMs ?? 5e3;
|
|
122486
122675
|
let graceTimer;
|
|
122487
122676
|
const graceful = await Promise.race([entry.lifecyclePromise.then(() => true, () => true), new Promise((resolve) => {
|
|
122488
122677
|
graceTimer = setTimeout(() => {
|
|
@@ -123160,6 +123349,258 @@ var init_waitForTool = __esmMin((() => {
|
|
|
123160
123349
|
});
|
|
123161
123350
|
}));
|
|
123162
123351
|
//#endregion
|
|
123352
|
+
//#region ../../packages/agent-core-v2/src/agent/tools/agent-output/agent-output.ts
|
|
123353
|
+
var AgentOutputInputSchema, AGENT_NOT_FOUND_MESSAGE, IAgentOutputTool;
|
|
123354
|
+
var init_agent_output$1 = __esmMin((() => {
|
|
123355
|
+
init_zod$1();
|
|
123356
|
+
init_instantiation();
|
|
123357
|
+
AgentOutputInputSchema = object({
|
|
123358
|
+
agent_id: string$2().describe("Agent ID of the subagent to inspect (returned by the Agent tool)."),
|
|
123359
|
+
tail_lines: number$2().int().min(1).max(500).optional().describe("How many of the most recent renderable records to show. Defaults to 60. The output is a transcript-style view of the subagent's latest activity.")
|
|
123360
|
+
});
|
|
123361
|
+
AGENT_NOT_FOUND_MESSAGE = "Agent instance not found.";
|
|
123362
|
+
IAgentOutputTool = createDecorator("agentOutputTool");
|
|
123363
|
+
}));
|
|
123364
|
+
//#endregion
|
|
123365
|
+
//#region ../../packages/agent-core-v2/src/agent/contextSize/contextSize.ts
|
|
123366
|
+
var IAgentContextSizeService;
|
|
123367
|
+
var init_contextSize = __esmMin((() => {
|
|
123368
|
+
init_instantiation();
|
|
123369
|
+
IAgentContextSizeService = createDecorator("agentContextSizeService");
|
|
123370
|
+
}));
|
|
123371
|
+
//#endregion
|
|
123372
|
+
//#region ../../packages/agent-core-v2/src/agent/tools/agent-output/agent-output.md?raw
|
|
123373
|
+
var agent_output_default;
|
|
123374
|
+
var init_agent_output = __esmMin((() => {
|
|
123375
|
+
agent_output_default = "Read the recent rendered output of a subagent — the same transcript-style view a human sees in the TUI: its latest assistant text, thinking, tool calls, and task progress, in time order.\n\nSubagents run fully asynchronously. Use this tool to check on one:\n\n- While you still have other work, do that work instead — the subagent's result (and completion notification) arrives on its own.\n- When you have nothing else to do and want to see what the subagent is doing, call this tool with the `agent_id` returned by the Agent tool.\n- If it is still working and you want to park until it progresses, call `WaitFor` with a reasonable `timeout_seconds` instead of polling this tool in a loop; the wait wakes you on the completion notification or the timeout, then check again with this tool.\n\nPass `tail_lines` to control how much of the recent activity to show (default 60). The `agent_id` is the Agent tool's `agent_id` parameter value (e.g. \"agent-6\"), NOT the `task_id` from its output.\n";
|
|
123376
|
+
}));
|
|
123377
|
+
//#endregion
|
|
123378
|
+
//#region ../../packages/agent-core-v2/src/agent/tools/agent-output/agentOutputTool.ts
|
|
123379
|
+
/**
|
|
123380
|
+
* `tools` domain (L7) — `AgentOutputTool` implementation (the `AgentOutput`
|
|
123381
|
+
* tool).
|
|
123382
|
+
*
|
|
123383
|
+
* Returns a transcript-style view of a subagent's recent activity by reading
|
|
123384
|
+
* the tail of its `wire.jsonl` journal (`<sessionDir>/agents/<agentId>/`):
|
|
123385
|
+
* assistant text, thinking, tool calls, and task progress in time order —
|
|
123386
|
+
* the same surface a human sees in the TUI. Subagents run fully
|
|
123387
|
+
* asynchronously, so this is the primary progress-check tool for the calling
|
|
123388
|
+
* agent (park with `WaitFor` instead of polling when there is nothing else
|
|
123389
|
+
* to do).
|
|
123390
|
+
*
|
|
123391
|
+
* Registered via the module-level `registerAgentToolService(IAgentOutputTool,
|
|
123392
|
+
* AgentOutputTool)` at the bottom of this file — the same "import = register"
|
|
123393
|
+
* pattern used by every agent tool. Bound at Agent scope.
|
|
123394
|
+
*/
|
|
123395
|
+
function toRenderable(line) {
|
|
123396
|
+
const trimmed = line.trim();
|
|
123397
|
+
if (trimmed.length === 0) return void 0;
|
|
123398
|
+
let parsed;
|
|
123399
|
+
try {
|
|
123400
|
+
parsed = JSON.parse(trimmed);
|
|
123401
|
+
} catch {
|
|
123402
|
+
return;
|
|
123403
|
+
}
|
|
123404
|
+
if (typeof parsed !== "object" || parsed === null) return void 0;
|
|
123405
|
+
const record = parsed;
|
|
123406
|
+
const timeMs = typeof record.time === "number" ? normalizeTimestampMs$1(record.time) : void 0;
|
|
123407
|
+
const turnStep = turnStepLabel(record.event);
|
|
123408
|
+
switch (record.type) {
|
|
123409
|
+
case "turn.prompt": return {
|
|
123410
|
+
timeMs: timeMs ?? 0,
|
|
123411
|
+
turnStep: "",
|
|
123412
|
+
lines: [`user: ${clip(textOfPrompt(record.input), PROMPT_MAX_CHARS)}`]
|
|
123413
|
+
};
|
|
123414
|
+
case "context.append_loop_event": {
|
|
123415
|
+
const event = record.event;
|
|
123416
|
+
const eventType = event?.type;
|
|
123417
|
+
if (eventType === "content.part" && typeof event?.part?.type === "string") {
|
|
123418
|
+
const partType = event.part.type;
|
|
123419
|
+
const text = partType === "think" ? typeof event.part.think === "string" ? event.part.think : "" : typeof event.part.text === "string" ? event.part.text : "";
|
|
123420
|
+
return {
|
|
123421
|
+
timeMs: timeMs ?? 0,
|
|
123422
|
+
turnStep,
|
|
123423
|
+
lines: [`${partType === "think" ? "think" : "assistant"}: ${clip(text, LINE_MAX_CHARS)}`]
|
|
123424
|
+
};
|
|
123425
|
+
}
|
|
123426
|
+
if (eventType === "tool.call" && typeof event?.name === "string") return {
|
|
123427
|
+
timeMs: timeMs ?? 0,
|
|
123428
|
+
turnStep,
|
|
123429
|
+
lines: [`tool: ${event.name}${argsLabel(event.args)}`]
|
|
123430
|
+
};
|
|
123431
|
+
if (eventType === "tool.result") {
|
|
123432
|
+
const done = event?.isError === true ? "error" : "done";
|
|
123433
|
+
return {
|
|
123434
|
+
timeMs: timeMs ?? 0,
|
|
123435
|
+
turnStep,
|
|
123436
|
+
lines: [` → ${done}`]
|
|
123437
|
+
};
|
|
123438
|
+
}
|
|
123439
|
+
return;
|
|
123440
|
+
}
|
|
123441
|
+
case "task.started":
|
|
123442
|
+
case "task.terminated": {
|
|
123443
|
+
const info = record.info;
|
|
123444
|
+
if (info === void 0) return void 0;
|
|
123445
|
+
const description = typeof info.description === "string" ? info.description : "";
|
|
123446
|
+
const taskId = typeof info.taskId === "string" ? info.taskId : "";
|
|
123447
|
+
const status = typeof info.status === "string" ? info.status : "";
|
|
123448
|
+
const label = record.type === "task.started" ? `task: ${clip(description, LINE_MAX_CHARS)} (running, ${taskId})` : `task: ${clip(description, LINE_MAX_CHARS)} (${status}, ${taskId})`;
|
|
123449
|
+
return {
|
|
123450
|
+
timeMs: timeMs ?? 0,
|
|
123451
|
+
turnStep: "",
|
|
123452
|
+
lines: [label]
|
|
123453
|
+
};
|
|
123454
|
+
}
|
|
123455
|
+
default: return;
|
|
123456
|
+
}
|
|
123457
|
+
}
|
|
123458
|
+
function turnStepLabel(event) {
|
|
123459
|
+
if (event === void 0) return "";
|
|
123460
|
+
const turn = typeof event.turnId === "string" ? event.turnId : void 0;
|
|
123461
|
+
const step = typeof event.step === "number" ? event.step : void 0;
|
|
123462
|
+
if (turn === void 0 && step === void 0) return "";
|
|
123463
|
+
return `[turn ${turn ?? "?"} step ${step ?? "?"}] `;
|
|
123464
|
+
}
|
|
123465
|
+
function argsLabel(args) {
|
|
123466
|
+
if (typeof args !== "object" || args === null) return "";
|
|
123467
|
+
return `(${clip(JSON.stringify(args), ARGS_MAX_CHARS)})`;
|
|
123468
|
+
}
|
|
123469
|
+
function textOfPrompt(input) {
|
|
123470
|
+
if (!Array.isArray(input)) return "";
|
|
123471
|
+
return input.flatMap((part) => typeof part === "object" && part !== null && part.type === "text" && typeof part.text === "string" ? [part.text] : []).join("").replaceAll(/\s+/g, " ").trim();
|
|
123472
|
+
}
|
|
123473
|
+
function clip(text, max) {
|
|
123474
|
+
const collapsed = text.replaceAll(/\s+/g, " ").trim();
|
|
123475
|
+
if (collapsed.length <= max) return collapsed;
|
|
123476
|
+
return `${collapsed.slice(0, max)}…`;
|
|
123477
|
+
}
|
|
123478
|
+
function normalizeTimestampMs$1(value) {
|
|
123479
|
+
return value > 0xe8d4a51000 ? Math.floor(value) : Math.floor(value * 1e3);
|
|
123480
|
+
}
|
|
123481
|
+
function formatTime(timeMs) {
|
|
123482
|
+
if (timeMs <= 0) return "";
|
|
123483
|
+
const date = new Date(timeMs);
|
|
123484
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
123485
|
+
return `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
|
|
123486
|
+
}
|
|
123487
|
+
function formatTokens$2(size) {
|
|
123488
|
+
if (size < 1024) return `${String(size)} tokens`;
|
|
123489
|
+
return `${(size / 1024).toFixed(1)}k tokens`;
|
|
123490
|
+
}
|
|
123491
|
+
function isMissingPath$3(error) {
|
|
123492
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
123493
|
+
}
|
|
123494
|
+
var WIRE_FILENAME$1, TAIL_READ_BYTES, LINE_MAX_CHARS, ARGS_MAX_CHARS, PROMPT_MAX_CHARS, AgentOutputTool;
|
|
123495
|
+
var init_agentOutputTool = __esmMin((() => {
|
|
123496
|
+
init_dist$5();
|
|
123497
|
+
init_input_schema();
|
|
123498
|
+
init_rule_match();
|
|
123499
|
+
init_toolContribution();
|
|
123500
|
+
init_contextSize();
|
|
123501
|
+
init_loop();
|
|
123502
|
+
init_profile();
|
|
123503
|
+
init_agentLifecycle();
|
|
123504
|
+
init_sessionContext();
|
|
123505
|
+
init_agent_output$1();
|
|
123506
|
+
init_agent_output();
|
|
123507
|
+
init_decorateParam();
|
|
123508
|
+
init_decorate();
|
|
123509
|
+
WIRE_FILENAME$1 = "wire.jsonl";
|
|
123510
|
+
TAIL_READ_BYTES = 256 * 1024;
|
|
123511
|
+
LINE_MAX_CHARS = 240;
|
|
123512
|
+
ARGS_MAX_CHARS = 120;
|
|
123513
|
+
PROMPT_MAX_CHARS = 300;
|
|
123514
|
+
AgentOutputTool = class AgentOutputTool {
|
|
123515
|
+
lifecycle;
|
|
123516
|
+
session;
|
|
123517
|
+
name = "AgentOutput";
|
|
123518
|
+
description = agent_output_default;
|
|
123519
|
+
parameters = toInputJsonSchema(AgentOutputInputSchema);
|
|
123520
|
+
constructor(lifecycle, session) {
|
|
123521
|
+
this.lifecycle = lifecycle;
|
|
123522
|
+
this.session = session;
|
|
123523
|
+
}
|
|
123524
|
+
resolveExecution(args) {
|
|
123525
|
+
return {
|
|
123526
|
+
description: `Reading output of agent ${args.agent_id}`,
|
|
123527
|
+
taskMode: "control",
|
|
123528
|
+
approvalRule: this.name,
|
|
123529
|
+
matchesRule: (ruleArgs) => matchesGlobRuleSubject(ruleArgs, args.agent_id),
|
|
123530
|
+
execute: () => this.execute(args)
|
|
123531
|
+
};
|
|
123532
|
+
}
|
|
123533
|
+
async execute(args) {
|
|
123534
|
+
const target = this.lifecycle.get(args.agent_id);
|
|
123535
|
+
if (target === void 0) return {
|
|
123536
|
+
isError: true,
|
|
123537
|
+
output: `${AGENT_NOT_FOUND_MESSAGE} agent_id=${args.agent_id}`
|
|
123538
|
+
};
|
|
123539
|
+
const records = await this.readRecentRecords(args.agent_id, args.tail_lines ?? 60);
|
|
123540
|
+
const profileName = target.accessor.get(IAgentProfileService).data().profileName ?? "agent";
|
|
123541
|
+
const status = target.accessor.get(IAgentLoopService).status();
|
|
123542
|
+
const contextSize = target.accessor.get(IAgentContextSizeService)?.get().size ?? 0;
|
|
123543
|
+
const lines = [[
|
|
123544
|
+
`agent_id: ${args.agent_id}`,
|
|
123545
|
+
`type: ${profileName}`,
|
|
123546
|
+
`status: ${status.state}${status.activeTurnId !== void 0 ? ` · turn ${String(status.activeTurnId)}` : ""}`,
|
|
123547
|
+
`context: ${formatTokens$2(contextSize)}`
|
|
123548
|
+
].join(" · "), ""];
|
|
123549
|
+
if (records.length === 0) lines.push("(no activity recorded yet)");
|
|
123550
|
+
else for (const record of records) {
|
|
123551
|
+
const stamp = formatTime(record.timeMs);
|
|
123552
|
+
for (const line of record.lines) lines.push(`${stamp} ${record.turnStep}${line}`);
|
|
123553
|
+
}
|
|
123554
|
+
return {
|
|
123555
|
+
output: lines.join("\n"),
|
|
123556
|
+
isError: false
|
|
123557
|
+
};
|
|
123558
|
+
}
|
|
123559
|
+
async readRecentRecords(agentId, tailLines) {
|
|
123560
|
+
const path = join$5(this.session.sessionDir, "agents", agentId, WIRE_FILENAME$1);
|
|
123561
|
+
let file;
|
|
123562
|
+
try {
|
|
123563
|
+
file = await open(path, "r");
|
|
123564
|
+
} catch (error) {
|
|
123565
|
+
if (isMissingPath$3(error)) return [];
|
|
123566
|
+
throw error;
|
|
123567
|
+
}
|
|
123568
|
+
let input;
|
|
123569
|
+
try {
|
|
123570
|
+
const size = (await file.stat()).size;
|
|
123571
|
+
const start = Math.max(0, size - TAIL_READ_BYTES);
|
|
123572
|
+
input = size === 0 ? Readable.from([]) : file.createReadStream({
|
|
123573
|
+
encoding: "utf8",
|
|
123574
|
+
autoClose: false,
|
|
123575
|
+
start,
|
|
123576
|
+
end: size - 1
|
|
123577
|
+
});
|
|
123578
|
+
const lines = createInterface({
|
|
123579
|
+
input,
|
|
123580
|
+
crlfDelay: Infinity
|
|
123581
|
+
});
|
|
123582
|
+
const rendered = [];
|
|
123583
|
+
for await (const line of lines) {
|
|
123584
|
+
const record = toRenderable(line);
|
|
123585
|
+
if (record === void 0) continue;
|
|
123586
|
+
rendered.push(record);
|
|
123587
|
+
if (rendered.length > tailLines) rendered.shift();
|
|
123588
|
+
}
|
|
123589
|
+
return rendered;
|
|
123590
|
+
} finally {
|
|
123591
|
+
input?.destroy();
|
|
123592
|
+
if (input !== void 0) await finished(input, { cleanup: true }).catch(() => {});
|
|
123593
|
+
await file.close();
|
|
123594
|
+
}
|
|
123595
|
+
}
|
|
123596
|
+
};
|
|
123597
|
+
AgentOutputTool = __decorate$1([__decorateParam(0, IAgentLifecycleService), __decorateParam(1, ISessionContext)], AgentOutputTool);
|
|
123598
|
+
registerAgentToolService(IAgentOutputTool, AgentOutputTool, {
|
|
123599
|
+
name: "AgentOutput",
|
|
123600
|
+
domain: "subagent"
|
|
123601
|
+
});
|
|
123602
|
+
}));
|
|
123603
|
+
//#endregion
|
|
123163
123604
|
//#region ../../packages/agent-core-v2/src/agent/tools/all-done/all-done.md?raw
|
|
123164
123605
|
var all_done_default;
|
|
123165
123606
|
var init_all_done = __esmMin((() => {
|
|
@@ -139187,13 +139628,6 @@ var init_subagent_task = __esmMin((() => {
|
|
|
139187
139628
|
};
|
|
139188
139629
|
}));
|
|
139189
139630
|
//#endregion
|
|
139190
|
-
//#region ../../packages/agent-core-v2/src/agent/contextSize/contextSize.ts
|
|
139191
|
-
var IAgentContextSizeService;
|
|
139192
|
-
var init_contextSize = __esmMin((() => {
|
|
139193
|
-
init_instantiation();
|
|
139194
|
-
IAgentContextSizeService = createDecorator("agentContextSizeService");
|
|
139195
|
-
}));
|
|
139196
|
-
//#endregion
|
|
139197
139631
|
//#region ../../packages/agent-core-v2/src/session/subagent/mirrorAgentRun.ts
|
|
139198
139632
|
function emitAgentRunSpawned(requester, targetAgentId, meta) {
|
|
139199
139633
|
requester.accessor.get(IEventBus)?.publish({
|
|
@@ -208443,7 +208877,7 @@ function turnPromptText(input) {
|
|
|
208443
208877
|
const text = input.filter((part) => part.type === "text").map((part) => part.text).join("");
|
|
208444
208878
|
return text.length > 0 ? text : void 0;
|
|
208445
208879
|
}
|
|
208446
|
-
function isDisplayablePromptOrigin(origin) {
|
|
208880
|
+
function isDisplayablePromptOrigin$1(origin) {
|
|
208447
208881
|
if (origin.kind === "user") return true;
|
|
208448
208882
|
return (origin.kind === "skill_activation" || origin.kind === "plugin_command") && origin.trigger === "user-slash";
|
|
208449
208883
|
}
|
|
@@ -208905,7 +209339,7 @@ var init_loopService = __esmMin((() => {
|
|
|
208905
209339
|
type: "turn.started",
|
|
208906
209340
|
turnId: job.turn.id,
|
|
208907
209341
|
origin,
|
|
208908
|
-
prompt: isDisplayablePromptOrigin(origin) ? turnPromptText(job.seed.input) : void 0
|
|
209342
|
+
prompt: isDisplayablePromptOrigin$1(origin) ? turnPromptText(job.seed.input) : void 0
|
|
208909
209343
|
});
|
|
208910
209344
|
this.runTurn(job.turn, job.ready).then(job.result.resolve, job.result.reject);
|
|
208911
209345
|
}
|
|
@@ -213499,6 +213933,1504 @@ var init_rpc$2 = __esmMin((() => {
|
|
|
213499
213933
|
createDecorator("agentSessionRPCService");
|
|
213500
213934
|
}));
|
|
213501
213935
|
//#endregion
|
|
213936
|
+
//#region ../../packages/agent-core-v2/src/agent/loop/engineTaskAdapter.ts
|
|
213937
|
+
/** Extract a human-readable stop reason from an AbortSignal's abort reason:
|
|
213938
|
+
* TaskStop aborts with the normalized reason string; `stopByUser` aborts
|
|
213939
|
+
* with a `UserCancellationError` (its `.message` is the user-facing reason);
|
|
213940
|
+
* anything else (undefined / session close) yields no reason — the engine
|
|
213941
|
+
* falls back to "Stopped by TaskStop". An empty reason (e.g. an Error with
|
|
213942
|
+
* an empty message) counts as "no reason" too, so the wire settle carries
|
|
213943
|
+
* the documented fallback instead of an empty `error` string. */
|
|
213944
|
+
function abortReasonString(reason) {
|
|
213945
|
+
if (typeof reason === "string") return reason === "" ? void 0 : reason;
|
|
213946
|
+
if (reason instanceof Error) return reason.message === "" ? void 0 : reason.message;
|
|
213947
|
+
}
|
|
213948
|
+
var EngineTaskAdapter;
|
|
213949
|
+
var init_engineTaskAdapter = __esmMin((() => {
|
|
213950
|
+
EngineTaskAdapter = class {
|
|
213951
|
+
options;
|
|
213952
|
+
idPrefix;
|
|
213953
|
+
kind;
|
|
213954
|
+
description;
|
|
213955
|
+
sink;
|
|
213956
|
+
pendingOutput = "";
|
|
213957
|
+
pendingSettlement;
|
|
213958
|
+
pendingExitCode;
|
|
213959
|
+
exitCode;
|
|
213960
|
+
settleResolve;
|
|
213961
|
+
settled;
|
|
213962
|
+
removeAbortListener;
|
|
213963
|
+
/** UTF-8 bytes already pushed to the sink (or buffered pre-start). The
|
|
213964
|
+
* engine guarantees its `task.output` deltas concatenate byte-for-byte to
|
|
213965
|
+
* the settle's full output — the bash poller seeds a backgrounded command
|
|
213966
|
+
* with its pre-timeout foreground output as the FIRST delta, and the
|
|
213967
|
+
* subagent worker streams the nested turn's assistant deltas verbatim —
|
|
213968
|
+
* so `complete` appends only the not-yet-streamed tail. */
|
|
213969
|
+
streamedBytes = 0;
|
|
213970
|
+
constructor(options) {
|
|
213971
|
+
this.options = options;
|
|
213972
|
+
this.idPrefix = options.kind === "agent" ? "agent" : "bash";
|
|
213973
|
+
this.kind = options.kind;
|
|
213974
|
+
this.description = options.description;
|
|
213975
|
+
this.settled = new Promise((resolve) => {
|
|
213976
|
+
this.settleResolve = resolve;
|
|
213977
|
+
});
|
|
213978
|
+
}
|
|
213979
|
+
async start(sink) {
|
|
213980
|
+
this.sink = sink;
|
|
213981
|
+
const requestStop = () => {
|
|
213982
|
+
this.options.forceStop(abortReasonString(sink.signal.reason));
|
|
213983
|
+
};
|
|
213984
|
+
if (sink.signal.aborted) requestStop();
|
|
213985
|
+
else {
|
|
213986
|
+
sink.signal.addEventListener("abort", requestStop, { once: true });
|
|
213987
|
+
this.removeAbortListener = () => {
|
|
213988
|
+
sink.signal.removeEventListener("abort", requestStop);
|
|
213989
|
+
};
|
|
213990
|
+
}
|
|
213991
|
+
this.flush();
|
|
213992
|
+
await this.settled;
|
|
213993
|
+
}
|
|
213994
|
+
async forceStop() {
|
|
213995
|
+
this.options.forceStop();
|
|
213996
|
+
}
|
|
213997
|
+
/** Runner-side live output (engine `task.output` events): stream the delta
|
|
213998
|
+
* straight into the service sink so TaskOutput shows partial output while
|
|
213999
|
+
* the task runs. Deltas racing `start()` (settle/stream before the
|
|
214000
|
+
* service invoked start) are buffered and flushed with the settle. */
|
|
214001
|
+
appendOutput(delta) {
|
|
214002
|
+
this.streamedBytes += Buffer.byteLength(delta, "utf-8");
|
|
214003
|
+
if (this.sink !== void 0) this.sink.appendOutput(delta);
|
|
214004
|
+
else this.pendingOutput += delta;
|
|
214005
|
+
}
|
|
214006
|
+
/** Runner-side settle: record the final output/exit code and settle the
|
|
214007
|
+
* registry entry (the runner dispatches the wire `task.terminated` and
|
|
214008
|
+
* delivers the notification itself — the service's `recorded: false`
|
|
214009
|
+
* entry only drives TaskList/TaskStop). The settle output is the engine's
|
|
214010
|
+
* full accumulated output; the deltas streamed during the run already
|
|
214011
|
+
* landed in the sink, so only the not-yet-streamed tail is appended (the
|
|
214012
|
+
* concatenated deltas equal the settle output byte-for-byte). */
|
|
214013
|
+
complete(output, settlement, exitCode) {
|
|
214014
|
+
this.pendingSettlement = settlement;
|
|
214015
|
+
this.pendingExitCode = exitCode ?? null;
|
|
214016
|
+
const fullBytes = Buffer.byteLength(output, "utf-8");
|
|
214017
|
+
const streamed = this.streamedBytes;
|
|
214018
|
+
if (streamed < fullBytes) {
|
|
214019
|
+
const tail = Buffer.from(output, "utf-8").subarray(streamed).toString("utf-8");
|
|
214020
|
+
if (this.sink !== void 0) this.sink.appendOutput(tail);
|
|
214021
|
+
else this.pendingOutput += tail;
|
|
214022
|
+
}
|
|
214023
|
+
this.flush();
|
|
214024
|
+
}
|
|
214025
|
+
toInfo(base) {
|
|
214026
|
+
if (this.kind === "agent") return {
|
|
214027
|
+
...base,
|
|
214028
|
+
kind: "agent",
|
|
214029
|
+
agentId: this.options.agentId ?? "",
|
|
214030
|
+
subagentType: this.options.subagentType ?? this.options.description,
|
|
214031
|
+
detached: true
|
|
214032
|
+
};
|
|
214033
|
+
return {
|
|
214034
|
+
...base,
|
|
214035
|
+
kind: "process",
|
|
214036
|
+
command: this.description,
|
|
214037
|
+
pid: this.options.pid ?? 0,
|
|
214038
|
+
exitCode: this.exitCode ?? null,
|
|
214039
|
+
detached: true
|
|
214040
|
+
};
|
|
214041
|
+
}
|
|
214042
|
+
flush() {
|
|
214043
|
+
const sink = this.sink;
|
|
214044
|
+
const settlement = this.pendingSettlement;
|
|
214045
|
+
if (sink === void 0 || settlement === void 0) return;
|
|
214046
|
+
this.exitCode = this.pendingExitCode ?? null;
|
|
214047
|
+
if (this.pendingOutput.length > 0) sink.appendOutput(this.pendingOutput);
|
|
214048
|
+
this.pendingOutput = "";
|
|
214049
|
+
this.pendingSettlement = void 0;
|
|
214050
|
+
this.removeAbortListener?.();
|
|
214051
|
+
this.removeAbortListener = void 0;
|
|
214052
|
+
sink.settle(settlement);
|
|
214053
|
+
this.settleResolve?.();
|
|
214054
|
+
}
|
|
214055
|
+
};
|
|
214056
|
+
}));
|
|
214057
|
+
//#endregion
|
|
214058
|
+
//#region ../../packages/agent-core-v2/src/agent/toolResultTruncation/toolResultTruncation.ts
|
|
214059
|
+
var IAgentToolResultTruncationService;
|
|
214060
|
+
var init_toolResultTruncation = __esmMin((() => {
|
|
214061
|
+
init_instantiation();
|
|
214062
|
+
IAgentToolResultTruncationService = createDecorator("agentToolResultTruncationService");
|
|
214063
|
+
}));
|
|
214064
|
+
//#endregion
|
|
214065
|
+
//#region ../../packages/agent-core-v2/src/agent/loop/rustEngineTurnRunner.ts
|
|
214066
|
+
/**
|
|
214067
|
+
* `rustEngineTurnRunner` — the default turn runner: one turn through the Rust
|
|
214068
|
+
* engine (`RustTurnSession` napi socket) instead of the TS loop.
|
|
214069
|
+
*
|
|
214070
|
+
* Enabled by default; the CLI `--legacy` flag sets `DIMI_LEGACY=1` to keep
|
|
214071
|
+
* the TS loop. The runner:
|
|
214072
|
+
* 1. records `turn.prompt` (turn clock) and appends the user message;
|
|
214073
|
+
* 2. assembles the LLM messages from the context (context assembly stays
|
|
214074
|
+
* on the TS side until slice 3);
|
|
214075
|
+
* 3. runs `RustTurnSession` (aimux-backed LLM in production, scripted
|
|
214076
|
+
* segments under test);
|
|
214077
|
+
* 4. streams the engine events onto the event bus as they happen (the
|
|
214078
|
+
* bridge pushes each event through a per-event callback while the turn
|
|
214079
|
+
* is in flight) — the transcript projection layer (`coreEventMap`)
|
|
214080
|
+
* folds them into wire ops exactly as it does for the TS loop — and
|
|
214081
|
+
* mirrors them into the context (`step.begin` / `content.part` /
|
|
214082
|
+
* `tool.call` / `tool.result` / `step.end` + the assistant message) so
|
|
214083
|
+
* the next turn's history is intact.
|
|
214084
|
+
*
|
|
214085
|
+
* Slice-1 scope: single turn, no queue/cancellation/undo (those land with
|
|
214086
|
+
* later slices). The runner is a parallel path — `loopService` is untouched.
|
|
214087
|
+
*/
|
|
214088
|
+
function wrapSystemReminder(text) {
|
|
214089
|
+
const trimmed = text.trim();
|
|
214090
|
+
if (trimmed.startsWith("<system-reminder>") && trimmed.endsWith("</system-reminder>")) return trimmed;
|
|
214091
|
+
return `<system-reminder>\n${trimmed}\n</system-reminder>`;
|
|
214092
|
+
}
|
|
214093
|
+
/**
|
|
214094
|
+
* The Rust engine is the default runtime; the CLI `--legacy` flag sets
|
|
214095
|
+
* `DIMI_LEGACY=1` to keep the TS loop (and the node-local OS backends).
|
|
214096
|
+
*/
|
|
214097
|
+
function rustEngineEnabled() {
|
|
214098
|
+
return process.env["DIMI_LEGACY"] !== "1";
|
|
214099
|
+
}
|
|
214100
|
+
/** Render an engine event/tool value as text (strings pass through). */
|
|
214101
|
+
function toText(value) {
|
|
214102
|
+
return typeof value === "string" ? value : JSON.stringify(value) ?? "";
|
|
214103
|
+
}
|
|
214104
|
+
/**
|
|
214105
|
+
* Serialize a TS `PromptOrigin` into the wire `TurnOrigin` JSON shape the
|
|
214106
|
+
* engine deserializes (`{ kind: 'user' }` / `{ kind: 'task', taskId }` /
|
|
214107
|
+
* … — see `dimi-wire` `model.rs`). Unknown kinds fall back to a plain user
|
|
214108
|
+
* origin (the wire default).
|
|
214109
|
+
*/
|
|
214110
|
+
function toEngineTurnOrigin(origin) {
|
|
214111
|
+
switch (origin.kind) {
|
|
214112
|
+
case "task": return {
|
|
214113
|
+
kind: "task",
|
|
214114
|
+
taskId: origin.taskId
|
|
214115
|
+
};
|
|
214116
|
+
case "cron_job": return {
|
|
214117
|
+
kind: "cron",
|
|
214118
|
+
taskId: origin.jobId
|
|
214119
|
+
};
|
|
214120
|
+
case "cron_missed": return { kind: "cron" };
|
|
214121
|
+
case "hook_result": return { kind: "hook" };
|
|
214122
|
+
case "compaction_summary": return { kind: "compaction" };
|
|
214123
|
+
default: return { kind: "user" };
|
|
214124
|
+
}
|
|
214125
|
+
}
|
|
214126
|
+
/**
|
|
214127
|
+
* TS `isDisplayablePromptOrigin` parity: only user-origin (and user-slash
|
|
214128
|
+
* skill/plugin) turns expose their prompt on `turn.started`; task/cron/hook
|
|
214129
|
+
* steering text must never leak into the transcript.
|
|
214130
|
+
*/
|
|
214131
|
+
function isDisplayablePromptOrigin(origin) {
|
|
214132
|
+
if (origin.kind === "user") return true;
|
|
214133
|
+
return (origin.kind === "skill_activation" || origin.kind === "plugin_command") && origin.trigger === "user-slash";
|
|
214134
|
+
}
|
|
214135
|
+
/**
|
|
214136
|
+
* Build a DimiErrorPayload-shaped error from the engine's `{ message, code }`
|
|
214137
|
+
* payload (TS `toDimiErrorPayload` parity): always carries `name` (the error
|
|
214138
|
+
* class name, mapped from the code when the engine omitted it), `retryable`
|
|
214139
|
+
* (mapped from the code per the TS registry) and `message`.
|
|
214140
|
+
*/
|
|
214141
|
+
function buildErrorPayload(rawError) {
|
|
214142
|
+
const error = { ...rawError };
|
|
214143
|
+
if (error["name"] === void 0 || error["name"] === null) error["name"] = error["code"] === "PROVIDER_FILTERED" ? "ProviderFilteredError" : "Error";
|
|
214144
|
+
if (error["retryable"] === void 0) error["retryable"] = typeof error["code"] === "string" && RETRYABLE_ERROR_CODES.has(error["code"]);
|
|
214145
|
+
return error;
|
|
214146
|
+
}
|
|
214147
|
+
/** Optional numeric engine field (pid / exitCode). */
|
|
214148
|
+
function toOptionalNumber(value) {
|
|
214149
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
214150
|
+
}
|
|
214151
|
+
/** Mirrors the task domain's `buildAgentTaskNotificationBody` (minus the
|
|
214152
|
+
* output-file block — the engine carries the tail inline). */
|
|
214153
|
+
function buildTaskNotificationBody(task) {
|
|
214154
|
+
const baseLine = task.status === "timed_out" ? `${task.description} timed out.` : task.status === "killed" && task.error !== void 0 ? `${task.description} was stopped. Reason: ${task.error}` : task.status === "failed" && task.error !== void 0 ? `${task.description} failed. Reason: ${task.error}` : `${task.description} ${task.status}.`;
|
|
214155
|
+
if (task.kind !== "agent" || task.status === "completed") return baseLine;
|
|
214156
|
+
return `${baseLine}${[
|
|
214157
|
+
"",
|
|
214158
|
+
`To recover or continue this subagent, call Agent(resume="${task.agentId}", prompt="Pick up where you left off; redo the last tool call if its result was never observed.").`,
|
|
214159
|
+
`Use agent_id ("${task.agentId}"), NOT source_id / task_id ("${task.taskId}") — the two look alike but only agent_id is accepted by the resume parameter.`,
|
|
214160
|
+
"Add run_in_background=true to keep it backgrounded, or omit it to take the result inline in the current turn.",
|
|
214161
|
+
"The subagent retains its full prior context across the restart, but any in-flight tool call lost its result and may need to be redone."
|
|
214162
|
+
].join("\n")}`;
|
|
214163
|
+
}
|
|
214164
|
+
/** Mirrors the task domain's `renderOutputPreviewBlock` (tail inline): the
|
|
214165
|
+
* engine's accumulated output is the "currently buffered" output, so the
|
|
214166
|
+
* preview is the last `NOTIFICATION_OUTPUT_PREVIEW_BYTES` bytes with the
|
|
214167
|
+
* same heading / `truncated` / `bytes` semantics the TS service renders. */
|
|
214168
|
+
function renderOutputPreviewBlock(output) {
|
|
214169
|
+
const fullBytes = Buffer.byteLength(output, "utf-8");
|
|
214170
|
+
const previewBytes = Math.min(NOTIFICATION_OUTPUT_PREVIEW_BYTES, fullBytes);
|
|
214171
|
+
const truncated = fullBytes > previewBytes;
|
|
214172
|
+
const preview = previewBytes > 0 ? Buffer.from(output, "utf-8").subarray(fullBytes - previewBytes).toString("utf-8") : "";
|
|
214173
|
+
return [
|
|
214174
|
+
`<output-preview bytes="${String(previewBytes)}" total_bytes="${String(fullBytes)}" truncated="${String(truncated)}">`,
|
|
214175
|
+
truncated ? `Showing the last ${String(previewBytes)} bytes. No persisted full output is available.` : "No persisted full output is available; this preview is the currently buffered task output.",
|
|
214176
|
+
escapeXml$1(preview),
|
|
214177
|
+
"</output-preview>"
|
|
214178
|
+
].join("\n");
|
|
214179
|
+
}
|
|
214180
|
+
/** Resolve once the signal aborts (used to race an approval wait). */
|
|
214181
|
+
function abortOnSignal(signal) {
|
|
214182
|
+
return new Promise((resolve) => {
|
|
214183
|
+
if (signal.aborted) {
|
|
214184
|
+
resolve();
|
|
214185
|
+
return;
|
|
214186
|
+
}
|
|
214187
|
+
signal.addEventListener("abort", () => {
|
|
214188
|
+
resolve();
|
|
214189
|
+
}, { once: true });
|
|
214190
|
+
});
|
|
214191
|
+
}
|
|
214192
|
+
var WAIT_FOR_NATIVE_DESCRIPTION, ENGINE_NATIVE_TOOLS, WAIT_FOR_NATIVE_PARAMETERS, IRustEngineTurnRunner, RETRYABLE_ERROR_CODES, TERMINAL_OUTPUT_TAIL_CHARS, NOTIFICATION_OUTPUT_PREVIEW_BYTES, RustEngineTurnRunner;
|
|
214193
|
+
var init_rustEngineTurnRunner = __esmMin((() => {
|
|
214194
|
+
init_src$7();
|
|
214195
|
+
init_xml_escape();
|
|
214196
|
+
init_contextMemory();
|
|
214197
|
+
init_permissionMode();
|
|
214198
|
+
init_toolRegistry();
|
|
214199
|
+
init_toolPolicy();
|
|
214200
|
+
init_permissionRules();
|
|
214201
|
+
init_engineTaskAdapter();
|
|
214202
|
+
init_notificationXml();
|
|
214203
|
+
init_taskOps();
|
|
214204
|
+
init_task$5();
|
|
214205
|
+
init_configSection$12();
|
|
214206
|
+
init_turnOps();
|
|
214207
|
+
init_eventBus();
|
|
214208
|
+
init_config$5();
|
|
214209
|
+
init_log();
|
|
214210
|
+
init_canonical_args();
|
|
214211
|
+
init_errors$11();
|
|
214212
|
+
init_externalHooksRunner();
|
|
214213
|
+
init_toolResultTruncation();
|
|
214214
|
+
init_approval$4();
|
|
214215
|
+
init_usage();
|
|
214216
|
+
init_profile();
|
|
214217
|
+
init_scopeContext();
|
|
214218
|
+
init_catalog$1();
|
|
214219
|
+
init_providerRuntime();
|
|
214220
|
+
init_sessionContext();
|
|
214221
|
+
init_sessionMetadata();
|
|
214222
|
+
init_usage$1();
|
|
214223
|
+
init_wire();
|
|
214224
|
+
init_compactionHandoff();
|
|
214225
|
+
init_compactionOps();
|
|
214226
|
+
init_completion();
|
|
214227
|
+
init_decorateParam();
|
|
214228
|
+
init_decorate();
|
|
214229
|
+
init_instantiation();
|
|
214230
|
+
init_scope();
|
|
214231
|
+
WAIT_FOR_NATIVE_DESCRIPTION = [
|
|
214232
|
+
"Wait for a background subagent task to finish (or time out).",
|
|
214233
|
+
"Pass the `agent_id` of a subagent launched by the Agent tool (from its launch output).",
|
|
214234
|
+
"The call blocks until that subagent completes, fails, or the timeout expires, then returns its final status and output.",
|
|
214235
|
+
"This waits on a specific subagent task, NOT on the user: user-wait (waking on user notifications) is not implemented.",
|
|
214236
|
+
"Prefer AgentOutput for a quick status check; use WaitFor when the turn should pause until the subagent finishes."
|
|
214237
|
+
].join(" ");
|
|
214238
|
+
ENGINE_NATIVE_TOOLS = new Set([
|
|
214239
|
+
"Bash",
|
|
214240
|
+
"Agent",
|
|
214241
|
+
"AgentOutput",
|
|
214242
|
+
"WaitFor"
|
|
214243
|
+
]);
|
|
214244
|
+
WAIT_FOR_NATIVE_PARAMETERS = {
|
|
214245
|
+
type: "object",
|
|
214246
|
+
properties: {
|
|
214247
|
+
agent_id: {
|
|
214248
|
+
type: "string",
|
|
214249
|
+
description: "Agent id of the running subagent task to wait for, as returned by the Agent tool launch output."
|
|
214250
|
+
},
|
|
214251
|
+
timeout_seconds: {
|
|
214252
|
+
type: "integer",
|
|
214253
|
+
minimum: 1,
|
|
214254
|
+
maximum: 1800,
|
|
214255
|
+
description: "How long to wait for the subagent before giving up. Defaults to 60; maximum 1800."
|
|
214256
|
+
}
|
|
214257
|
+
},
|
|
214258
|
+
required: ["agent_id"],
|
|
214259
|
+
additionalProperties: false
|
|
214260
|
+
};
|
|
214261
|
+
IRustEngineTurnRunner = createDecorator("rustEngineTurnRunner");
|
|
214262
|
+
RETRYABLE_ERROR_CODES = new Set([
|
|
214263
|
+
"provider.rate_limit",
|
|
214264
|
+
"provider.connection_error",
|
|
214265
|
+
"provider.overloaded",
|
|
214266
|
+
"context.overflow"
|
|
214267
|
+
]);
|
|
214268
|
+
TERMINAL_OUTPUT_TAIL_CHARS = 4 * 1024;
|
|
214269
|
+
NOTIFICATION_OUTPUT_PREVIEW_BYTES = 3e3;
|
|
214270
|
+
RustEngineTurnRunner = class RustEngineTurnRunner {
|
|
214271
|
+
context;
|
|
214272
|
+
eventBus;
|
|
214273
|
+
wire;
|
|
214274
|
+
config;
|
|
214275
|
+
modeService;
|
|
214276
|
+
rulesService;
|
|
214277
|
+
toolRegistry;
|
|
214278
|
+
usageService;
|
|
214279
|
+
profile;
|
|
214280
|
+
scopeContext;
|
|
214281
|
+
sessionContext;
|
|
214282
|
+
sessionMetadata;
|
|
214283
|
+
tasks;
|
|
214284
|
+
modelCatalog;
|
|
214285
|
+
providerRuntime;
|
|
214286
|
+
instantiation;
|
|
214287
|
+
toolPolicy;
|
|
214288
|
+
log;
|
|
214289
|
+
/** The in-flight Rust session, while a turn is running (steer/cancel target). */
|
|
214290
|
+
activeSession;
|
|
214291
|
+
/** FIFO queue of turns waiting behind the running one (TS loop queue
|
|
214292
|
+
* parity): prompts during an active turn wait for it to finish. */
|
|
214293
|
+
queued = [];
|
|
214294
|
+
/** Whether a turn is currently executing (queue gate). */
|
|
214295
|
+
turnRunning = false;
|
|
214296
|
+
/** turnId of the executing turn (cancel validation). */
|
|
214297
|
+
executingTurnId;
|
|
214298
|
+
/** Aborts the in-flight approval wait on cancel. */
|
|
214299
|
+
approvalAbort;
|
|
214300
|
+
/**
|
|
214301
|
+
* Rust-side task registry mirror: taskId → launch facts (description /
|
|
214302
|
+
* startedAt / pid) recorded from `task.started`, used to build the
|
|
214303
|
+
* terminal `task.terminated` info from `task.settled`. Entries are removed
|
|
214304
|
+
* once the settle is handled (a task settles exactly once), so the map
|
|
214305
|
+
* stays bounded by the number of tasks in flight.
|
|
214306
|
+
*/
|
|
214307
|
+
taskInfos = /* @__PURE__ */ new Map();
|
|
214308
|
+
/** Notification dedupe (TS `deliveredNotificationKeys` parity): guards a
|
|
214309
|
+
* single settle from being delivered twice. Keys are removed after the
|
|
214310
|
+
* delivery completes — a settled task never settles again — so the set
|
|
214311
|
+
* stays bounded; the mid-turn+idle double-delivery guard is the
|
|
214312
|
+
* single-call structure of `deliverTaskNotification`, not this set. */
|
|
214313
|
+
deliveredNotificationKeys = /* @__PURE__ */ new Set();
|
|
214314
|
+
/** Registry entries for engine background tasks (TaskList/TaskStop parity):
|
|
214315
|
+
* taskId → adapter registered with `IAgentTaskService`. Removed once the
|
|
214316
|
+
* task settles (a task settles exactly once), so the map stays bounded. */
|
|
214317
|
+
engineTaskAdapters = /* @__PURE__ */ new Map();
|
|
214318
|
+
/** Owning RustTurnSession per engine task id (F1): recorded at
|
|
214319
|
+
* `task.started` from the session whose EventSink delivered the event.
|
|
214320
|
+
* Tasks launched from background workers (a subagent spawning a
|
|
214321
|
+
* sub-subagent, or a subagent launching a backgrounded bash) emit their
|
|
214322
|
+
* start AFTER the launching turn ended, when `activeSession` is undefined
|
|
214323
|
+
* or a newer turn's session — and the engine's per-task cancel signal
|
|
214324
|
+
* lives on the OWNING session's task map (`RustTurnSession::new` creates
|
|
214325
|
+
* a fresh map per turn), so TaskStop must cancel through this session.
|
|
214326
|
+
* Removed once the task settles, so the map stays bounded. */
|
|
214327
|
+
taskSessions = /* @__PURE__ */ new Map();
|
|
214328
|
+
/** Every subagent agent id this runner has handed out (the engine's
|
|
214329
|
+
* `agent-<n>` ids across turns): the next-turn seed must continue past
|
|
214330
|
+
* them so ids stay monotonic within the session (TS
|
|
214331
|
+
* `nextAvailableAgentId` parity). */
|
|
214332
|
+
engineAgentIds = /* @__PURE__ */ new Set();
|
|
214333
|
+
/** Every RustTurnSession this runner created. Held until the agent scope
|
|
214334
|
+
* is disposed so a session's EventSink stays open while its background
|
|
214335
|
+
* tasks are still settling (a subagent launched in turn 1 must be able to
|
|
214336
|
+
* notify after turn 1 ends), and so teardown can close them all at once
|
|
214337
|
+
* (TS `taskService.dispose` parity). */
|
|
214338
|
+
sessions = /* @__PURE__ */ new Set();
|
|
214339
|
+
/** Whether the agent scope was disposed: late engine events (background
|
|
214340
|
+
* task settles racing the teardown) are ignored instead of dispatching
|
|
214341
|
+
* wire ops on a disposed wire / appending to a disposed context. */
|
|
214342
|
+
disposed = false;
|
|
214343
|
+
constructor(context, eventBus, wire, config, modeService, rulesService, toolRegistry, usageService, profile, scopeContext, sessionContext, sessionMetadata, tasks, modelCatalog, providerRuntime, instantiation, toolPolicy, log) {
|
|
214344
|
+
this.context = context;
|
|
214345
|
+
this.eventBus = eventBus;
|
|
214346
|
+
this.wire = wire;
|
|
214347
|
+
this.config = config;
|
|
214348
|
+
this.modeService = modeService;
|
|
214349
|
+
this.rulesService = rulesService;
|
|
214350
|
+
this.toolRegistry = toolRegistry;
|
|
214351
|
+
this.usageService = usageService;
|
|
214352
|
+
this.profile = profile;
|
|
214353
|
+
this.scopeContext = scopeContext;
|
|
214354
|
+
this.sessionContext = sessionContext;
|
|
214355
|
+
this.sessionMetadata = sessionMetadata;
|
|
214356
|
+
this.tasks = tasks;
|
|
214357
|
+
this.modelCatalog = modelCatalog;
|
|
214358
|
+
this.providerRuntime = providerRuntime;
|
|
214359
|
+
this.instantiation = instantiation;
|
|
214360
|
+
this.toolPolicy = toolPolicy;
|
|
214361
|
+
this.log = log;
|
|
214362
|
+
this.registryId = randomUUID();
|
|
214363
|
+
}
|
|
214364
|
+
/** Agent-scoped Rust subagent registry id (see constructor). */
|
|
214365
|
+
registryId;
|
|
214366
|
+
/** TS `stopHookContinuationUsed` parity: the Stop hook fires at most once
|
|
214367
|
+
* after a continuation was delivered. */
|
|
214368
|
+
stopHookContinuationUsed = false;
|
|
214369
|
+
static isEnabled() {
|
|
214370
|
+
return rustEngineEnabled();
|
|
214371
|
+
}
|
|
214372
|
+
/**
|
|
214373
|
+
* Steer the running turn. Mirrors the TS steer path (`steerTurn` op +
|
|
214374
|
+
* user message in the context) and forwards the text into the engine's
|
|
214375
|
+
* steer queue, where it is drained into the next LLM request. Returns
|
|
214376
|
+
* `false` when there is no steerable turn: either no session is active
|
|
214377
|
+
* (the caller starts a new turn) or the engine's turn already finished
|
|
214378
|
+
* (a steer racing the teardown — between the engine's final steer check
|
|
214379
|
+
* and this runner clearing `activeSession` — would land in a queue that
|
|
214380
|
+
* is never drained again; the caller's `runTurn` fallback queues it as
|
|
214381
|
+
* the next turn instead, so it is never lost).
|
|
214382
|
+
*/
|
|
214383
|
+
steer(payload) {
|
|
214384
|
+
if (this.disposed) return false;
|
|
214385
|
+
const session = this.activeSession;
|
|
214386
|
+
if (session === void 0) return false;
|
|
214387
|
+
const text = payload.input.filter((part) => part.type === "text").map((part) => part.text ?? "").join("");
|
|
214388
|
+
if (text.length === 0) return false;
|
|
214389
|
+
if (!session.steer(text)) return false;
|
|
214390
|
+
this.wire.dispatch(steerTurn({
|
|
214391
|
+
input: [...payload.input],
|
|
214392
|
+
origin: payload.origin
|
|
214393
|
+
}));
|
|
214394
|
+
this.context.append({
|
|
214395
|
+
role: "user",
|
|
214396
|
+
content: [...payload.input],
|
|
214397
|
+
toolCalls: [],
|
|
214398
|
+
origin: payload.origin,
|
|
214399
|
+
id: randomUUID()
|
|
214400
|
+
});
|
|
214401
|
+
return true;
|
|
214402
|
+
}
|
|
214403
|
+
/**
|
|
214404
|
+
* Run one turn through the Rust engine. The turn clock advances at enqueue
|
|
214405
|
+
* time (TS parity); the turn itself either starts immediately (resolves
|
|
214406
|
+
* with its id) or waits behind the running turn (resolves `undefined`,
|
|
214407
|
+
* like TS `state === 'pending'`).
|
|
214408
|
+
*/
|
|
214409
|
+
async runTurn(payload) {
|
|
214410
|
+
if (this.disposed) return void 0;
|
|
214411
|
+
this.wire.dispatch(promptTurn({
|
|
214412
|
+
input: [...payload.input],
|
|
214413
|
+
origin: payload.origin
|
|
214414
|
+
}));
|
|
214415
|
+
const turnId = this.wire.getModel(TurnModel).nextTurnId - 1;
|
|
214416
|
+
const userMessage = {
|
|
214417
|
+
role: "user",
|
|
214418
|
+
content: [...payload.input],
|
|
214419
|
+
toolCalls: [],
|
|
214420
|
+
origin: payload.origin,
|
|
214421
|
+
id: randomUUID()
|
|
214422
|
+
};
|
|
214423
|
+
this.context.append(userMessage);
|
|
214424
|
+
if (this.turnRunning) {
|
|
214425
|
+
this.queued.push({
|
|
214426
|
+
turnId,
|
|
214427
|
+
payload,
|
|
214428
|
+
cancelled: false
|
|
214429
|
+
});
|
|
214430
|
+
return;
|
|
214431
|
+
}
|
|
214432
|
+
this.startQueuedTurn({
|
|
214433
|
+
turnId,
|
|
214434
|
+
payload,
|
|
214435
|
+
cancelled: false
|
|
214436
|
+
});
|
|
214437
|
+
return { turnId };
|
|
214438
|
+
}
|
|
214439
|
+
/** Cancel the active turn; with `turnId`, also cancels a queued turn. */
|
|
214440
|
+
cancel(turnId) {
|
|
214441
|
+
const session = this.activeSession;
|
|
214442
|
+
if (session !== void 0 && (turnId === void 0 || turnId === this.executingTurnId)) {
|
|
214443
|
+
this.approvalAbort?.abort();
|
|
214444
|
+
session.cancel();
|
|
214445
|
+
return true;
|
|
214446
|
+
}
|
|
214447
|
+
let cancelled = false;
|
|
214448
|
+
for (const entry of this.queued) if (entry.turnId === turnId) {
|
|
214449
|
+
entry.cancelled = true;
|
|
214450
|
+
this.wire.dispatch(cancelTurn({ turnId }));
|
|
214451
|
+
cancelled = true;
|
|
214452
|
+
}
|
|
214453
|
+
return cancelled;
|
|
214454
|
+
}
|
|
214455
|
+
/**
|
|
214456
|
+
* Agent-scope teardown (TS `taskService.dispose` parity): every Rust
|
|
214457
|
+
* session is closed — its EventSink stops forwarding, the in-flight turn
|
|
214458
|
+
* is cancelled, and background workers/pollers observe the closed flag and
|
|
214459
|
+
* kill their processes — and late engine events are ignored instead of
|
|
214460
|
+
* dispatching wire ops on a disposed wire. The DI container invokes this
|
|
214461
|
+
* when the agent scope is disposed.
|
|
214462
|
+
*/
|
|
214463
|
+
dispose() {
|
|
214464
|
+
this.disposed = true;
|
|
214465
|
+
this.approvalAbort?.abort();
|
|
214466
|
+
for (const session of this.sessions) session.close();
|
|
214467
|
+
this.sessions.clear();
|
|
214468
|
+
this.taskSessions.clear();
|
|
214469
|
+
this.engineTaskAdapters.clear();
|
|
214470
|
+
RustTurnSession.dropTaskRegistry(this.registryId);
|
|
214471
|
+
}
|
|
214472
|
+
startQueuedTurn(entry) {
|
|
214473
|
+
this.turnRunning = true;
|
|
214474
|
+
this.executingTurnId = entry.turnId;
|
|
214475
|
+
this.runTurnNow(entry.turnId, entry.payload.origin).catch(() => void 0).finally(() => {
|
|
214476
|
+
this.turnRunning = false;
|
|
214477
|
+
this.executingTurnId = void 0;
|
|
214478
|
+
if (this.disposed) {
|
|
214479
|
+
this.queued.length = 0;
|
|
214480
|
+
return;
|
|
214481
|
+
}
|
|
214482
|
+
const next = this.queued.find((queued) => !queued.cancelled);
|
|
214483
|
+
if (next === void 0) return;
|
|
214484
|
+
this.queued.splice(this.queued.indexOf(next), 1);
|
|
214485
|
+
this.startQueuedTurn(next);
|
|
214486
|
+
});
|
|
214487
|
+
}
|
|
214488
|
+
async runTurnNow(turnId, origin) {
|
|
214489
|
+
if (this.disposed) return { turnId };
|
|
214490
|
+
const messages = [{
|
|
214491
|
+
role: "system",
|
|
214492
|
+
content: this.profile.getSystemPrompt()
|
|
214493
|
+
}, ...this.context.get().map((message) => this.toLlmMessage(message))];
|
|
214494
|
+
const provider = await this.providerConfig();
|
|
214495
|
+
const inputJson = JSON.stringify({
|
|
214496
|
+
turnId,
|
|
214497
|
+
origin: toEngineTurnOrigin(origin),
|
|
214498
|
+
usesWorkerRejectionGuidance: this.scopeContext.agentId !== "main",
|
|
214499
|
+
activeTools: this.effectiveActiveTools() ?? null,
|
|
214500
|
+
messages,
|
|
214501
|
+
tools: [],
|
|
214502
|
+
provider,
|
|
214503
|
+
maxStepsPerTurn: this.maxStepsPerTurn() ?? null,
|
|
214504
|
+
maxRetriesPerStep: this.maxRetriesPerStep() ?? null,
|
|
214505
|
+
maxContextTokens: this.maxContextTokens() ?? null,
|
|
214506
|
+
nextAgentId: await this.computeNextAgentId(),
|
|
214507
|
+
killGraceMs: this.killGracePeriodMs(),
|
|
214508
|
+
completionReview: {
|
|
214509
|
+
minSteps: 10,
|
|
214510
|
+
reminder: completion_review_default
|
|
214511
|
+
},
|
|
214512
|
+
cwd: this.profile.data().cwd ?? process.cwd()
|
|
214513
|
+
});
|
|
214514
|
+
const policyJson = JSON.stringify({
|
|
214515
|
+
mode: this.modeService.mode,
|
|
214516
|
+
rules: this.rulesService.rules,
|
|
214517
|
+
sessionApprovedPatterns: this.rulesService.sessionApprovalRulePatterns
|
|
214518
|
+
});
|
|
214519
|
+
const scripted = process.env["DIMI_RUST_ENGINE_SCRIPTED"];
|
|
214520
|
+
const session = new RustTurnSession(inputJson, policyJson, scripted ?? void 0, this.registryId);
|
|
214521
|
+
this.sessions.add(session);
|
|
214522
|
+
this.activeSession = session;
|
|
214523
|
+
session.setToolGate((payloadJson) => {
|
|
214524
|
+
(async () => {
|
|
214525
|
+
const payload = JSON.parse(payloadJson);
|
|
214526
|
+
let verdict = { decision: "allow" };
|
|
214527
|
+
try {
|
|
214528
|
+
const hooksRunner = this.instantiation.invokeFunction((accessor) => accessor.get(IExternalHooksRunnerService));
|
|
214529
|
+
if (hooksRunner !== void 0 && ENGINE_NATIVE_TOOLS.has(payload.toolName)) {
|
|
214530
|
+
const block = await hooksRunner.triggerBlock("PreToolUse", {
|
|
214531
|
+
matcherValue: payload.toolName,
|
|
214532
|
+
signal: new AbortController().signal,
|
|
214533
|
+
sessionId: this.sessionContext.sessionId,
|
|
214534
|
+
inputData: {
|
|
214535
|
+
toolName: payload.toolName,
|
|
214536
|
+
toolInput: isPlainRecord(payload.arguments) ? payload.arguments : {},
|
|
214537
|
+
toolCallId: `native-${payload.toolName}`
|
|
214538
|
+
}
|
|
214539
|
+
});
|
|
214540
|
+
if (block !== void 0) verdict = {
|
|
214541
|
+
decision: "block",
|
|
214542
|
+
reason: block.reason
|
|
214543
|
+
};
|
|
214544
|
+
}
|
|
214545
|
+
} catch {}
|
|
214546
|
+
session.completeToolGate(payload.requestId, JSON.stringify(verdict));
|
|
214547
|
+
})();
|
|
214548
|
+
});
|
|
214549
|
+
try {
|
|
214550
|
+
await this.runEngineSession(session, turnId, provider["model"], origin);
|
|
214551
|
+
} finally {
|
|
214552
|
+
this.activeSession = void 0;
|
|
214553
|
+
}
|
|
214554
|
+
return { turnId };
|
|
214555
|
+
}
|
|
214556
|
+
/**
|
|
214557
|
+
* Run one engine session to completion: register the TS tool ecosystem,
|
|
214558
|
+
* drive the approval loop, mirror the engine events into the context.
|
|
214559
|
+
*/
|
|
214560
|
+
async runEngineSession(session, turnId, providerModel, origin) {
|
|
214561
|
+
const engineNativeTools = ENGINE_NATIVE_TOOLS;
|
|
214562
|
+
const activeSet = this.effectiveActiveTools();
|
|
214563
|
+
const isToolActiveForRunner = (name) => activeSet === void 0 || activeSet.includes(name);
|
|
214564
|
+
for (const info of this.toolRegistry.list()) {
|
|
214565
|
+
if (!isToolActiveForRunner(info.name)) continue;
|
|
214566
|
+
try {
|
|
214567
|
+
if (engineNativeTools.has(info.name)) {
|
|
214568
|
+
if (info.name !== "Bash") if (info.name === "WaitFor") session.registerNativeToolDef(info.name, WAIT_FOR_NATIVE_DESCRIPTION, JSON.stringify(WAIT_FOR_NATIVE_PARAMETERS));
|
|
214569
|
+
else session.registerNativeToolDef(info.name, info.description, JSON.stringify(info.parameters ?? {
|
|
214570
|
+
type: "object",
|
|
214571
|
+
properties: {}
|
|
214572
|
+
}));
|
|
214573
|
+
continue;
|
|
214574
|
+
}
|
|
214575
|
+
const tool = this.toolRegistry.resolve(info.name);
|
|
214576
|
+
if (tool === void 0) continue;
|
|
214577
|
+
session.registerExternalTool(info.name, info.description, JSON.stringify(info.parameters ?? {
|
|
214578
|
+
type: "object",
|
|
214579
|
+
properties: {}
|
|
214580
|
+
}), (payloadJson) => {
|
|
214581
|
+
(async () => {
|
|
214582
|
+
const payload = JSON.parse(payloadJson);
|
|
214583
|
+
try {
|
|
214584
|
+
const toolCalls = (payload.toolCalls ?? []).map((call) => ({
|
|
214585
|
+
type: "function",
|
|
214586
|
+
id: call.id ?? payload.toolCallId ?? payload.requestId,
|
|
214587
|
+
name: call.name,
|
|
214588
|
+
arguments: typeof call.arguments === "string" ? call.arguments : JSON.stringify(call.arguments) ?? "null"
|
|
214589
|
+
}));
|
|
214590
|
+
const execution = await tool.resolveExecution(payload.arguments, { toolCalls });
|
|
214591
|
+
if (execution.isError === true) {
|
|
214592
|
+
session.completeToolCall(payload.requestId, JSON.stringify({
|
|
214593
|
+
toolCallId: payload.toolCallId ?? payload.requestId,
|
|
214594
|
+
toolName: payload.name,
|
|
214595
|
+
output: toText(execution.output),
|
|
214596
|
+
isError: true,
|
|
214597
|
+
stopTurn: execution.stopTurn === true,
|
|
214598
|
+
updates: []
|
|
214599
|
+
}));
|
|
214600
|
+
return;
|
|
214601
|
+
}
|
|
214602
|
+
const signal = new AbortController().signal;
|
|
214603
|
+
const hooksRunner = this.instantiation.invokeFunction((accessor) => accessor.get(IExternalHooksRunnerService));
|
|
214604
|
+
const toolInput = isPlainRecord(payload.arguments) ? payload.arguments : {};
|
|
214605
|
+
const toolCallId = payload.toolCallId ?? payload.requestId;
|
|
214606
|
+
if (hooksRunner !== void 0) {
|
|
214607
|
+
const block = await hooksRunner.triggerBlock("PreToolUse", {
|
|
214608
|
+
matcherValue: payload.name,
|
|
214609
|
+
signal,
|
|
214610
|
+
sessionId: this.sessionContext.sessionId,
|
|
214611
|
+
inputData: {
|
|
214612
|
+
toolName: payload.name,
|
|
214613
|
+
toolInput,
|
|
214614
|
+
toolCallId
|
|
214615
|
+
}
|
|
214616
|
+
});
|
|
214617
|
+
if (block !== void 0) {
|
|
214618
|
+
session.completeToolCall(payload.requestId, JSON.stringify({
|
|
214619
|
+
toolCallId,
|
|
214620
|
+
toolName: payload.name,
|
|
214621
|
+
output: block.reason,
|
|
214622
|
+
isError: true,
|
|
214623
|
+
stopTurn: false,
|
|
214624
|
+
updates: []
|
|
214625
|
+
}));
|
|
214626
|
+
return;
|
|
214627
|
+
}
|
|
214628
|
+
}
|
|
214629
|
+
const result = await execution.execute({
|
|
214630
|
+
turnId: 0,
|
|
214631
|
+
toolCallId,
|
|
214632
|
+
signal,
|
|
214633
|
+
onUpdate: (update) => {
|
|
214634
|
+
if (signal.aborted) return;
|
|
214635
|
+
this.eventBus.publish({
|
|
214636
|
+
type: "tool.progress",
|
|
214637
|
+
turnId,
|
|
214638
|
+
toolCallId,
|
|
214639
|
+
update
|
|
214640
|
+
});
|
|
214641
|
+
}
|
|
214642
|
+
});
|
|
214643
|
+
let finalResult = result;
|
|
214644
|
+
const truncation = this.instantiation.invokeFunction((accessor) => accessor.get(IAgentToolResultTruncationService));
|
|
214645
|
+
if (truncation !== void 0) try {
|
|
214646
|
+
finalResult = await truncation.truncateForModel({
|
|
214647
|
+
toolName: payload.name,
|
|
214648
|
+
toolCallId,
|
|
214649
|
+
result
|
|
214650
|
+
});
|
|
214651
|
+
} catch {}
|
|
214652
|
+
session.completeToolCall(payload.requestId, JSON.stringify({
|
|
214653
|
+
toolCallId,
|
|
214654
|
+
toolName: payload.name,
|
|
214655
|
+
output: toText(finalResult.output),
|
|
214656
|
+
isError: finalResult.isError === true,
|
|
214657
|
+
stopTurn: finalResult.stopTurn === true,
|
|
214658
|
+
updates: []
|
|
214659
|
+
}));
|
|
214660
|
+
if (hooksRunner !== void 0) {
|
|
214661
|
+
const outputText = toText(finalResult.output);
|
|
214662
|
+
const isError = finalResult.isError === true;
|
|
214663
|
+
hooksRunner.fireAndForgetTrigger(isError ? "PostToolUseFailure" : "PostToolUse", {
|
|
214664
|
+
matcherValue: payload.name,
|
|
214665
|
+
signal,
|
|
214666
|
+
sessionId: this.sessionContext.sessionId,
|
|
214667
|
+
inputData: {
|
|
214668
|
+
toolName: payload.name,
|
|
214669
|
+
toolInput,
|
|
214670
|
+
toolCallId,
|
|
214671
|
+
error: isError ? toDimiErrorPayload(outputText) : void 0,
|
|
214672
|
+
toolOutput: isError ? void 0 : outputText.slice(0, 2e3)
|
|
214673
|
+
}
|
|
214674
|
+
});
|
|
214675
|
+
}
|
|
214676
|
+
} catch (error) {
|
|
214677
|
+
session.completeToolCall(payload.requestId, JSON.stringify({
|
|
214678
|
+
toolCallId: payload.toolCallId ?? payload.requestId,
|
|
214679
|
+
toolName: payload.name,
|
|
214680
|
+
output: `Tool "${payload.name}" failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
214681
|
+
isError: true,
|
|
214682
|
+
stopTurn: false,
|
|
214683
|
+
updates: []
|
|
214684
|
+
}));
|
|
214685
|
+
}
|
|
214686
|
+
})();
|
|
214687
|
+
});
|
|
214688
|
+
} catch (error) {
|
|
214689
|
+
if (engineNativeTools.has(info.name) && info.name !== "Bash") {
|
|
214690
|
+
this.log.error("[rustEngineTurnRunner] failed to register native tool def", {
|
|
214691
|
+
name: info.name,
|
|
214692
|
+
error
|
|
214693
|
+
});
|
|
214694
|
+
this.eventBus.publish({
|
|
214695
|
+
type: "turn.ended",
|
|
214696
|
+
turnId,
|
|
214697
|
+
reason: "failed",
|
|
214698
|
+
error: {
|
|
214699
|
+
name: "ToolRegistrationError",
|
|
214700
|
+
message: `Failed to register native tool def "${info.name}"`
|
|
214701
|
+
}
|
|
214702
|
+
});
|
|
214703
|
+
this.eventBus.publish({
|
|
214704
|
+
type: "error",
|
|
214705
|
+
name: "ToolRegistrationError",
|
|
214706
|
+
message: `Failed to register native tool def "${info.name}"`
|
|
214707
|
+
});
|
|
214708
|
+
throw error;
|
|
214709
|
+
}
|
|
214710
|
+
this.log.error("[rustEngineTurnRunner] failed to register external tool", {
|
|
214711
|
+
name: info.name,
|
|
214712
|
+
error
|
|
214713
|
+
});
|
|
214714
|
+
}
|
|
214715
|
+
}
|
|
214716
|
+
let stepUuid;
|
|
214717
|
+
const segments = [];
|
|
214718
|
+
let stepSawToolCall = false;
|
|
214719
|
+
const nativeToolCalls = /* @__PURE__ */ new Map();
|
|
214720
|
+
let usage = emptyUsage();
|
|
214721
|
+
const publish = (event) => {
|
|
214722
|
+
const { type, ...rest } = event;
|
|
214723
|
+
this.eventBus.publish({
|
|
214724
|
+
type,
|
|
214725
|
+
...rest
|
|
214726
|
+
});
|
|
214727
|
+
};
|
|
214728
|
+
const flushParts = (turnId, step) => {
|
|
214729
|
+
for (const segment of segments.splice(0)) {
|
|
214730
|
+
const part = segment.type === "think" ? {
|
|
214731
|
+
type: "think",
|
|
214732
|
+
think: segment.text
|
|
214733
|
+
} : {
|
|
214734
|
+
type: "text",
|
|
214735
|
+
text: segment.text
|
|
214736
|
+
};
|
|
214737
|
+
this.context.appendLoopEvent({
|
|
214738
|
+
type: "content.part",
|
|
214739
|
+
stepUuid,
|
|
214740
|
+
part,
|
|
214741
|
+
uuid: randomUUID(),
|
|
214742
|
+
turnId: String(turnId),
|
|
214743
|
+
step
|
|
214744
|
+
});
|
|
214745
|
+
}
|
|
214746
|
+
};
|
|
214747
|
+
const handleEngineEvent = (event) => {
|
|
214748
|
+
if (this.disposed) return;
|
|
214749
|
+
if (event["type"] === "task.started") {
|
|
214750
|
+
this.taskSessions.set(toText(event["taskId"]), session);
|
|
214751
|
+
this.handleTaskStarted(event);
|
|
214752
|
+
return;
|
|
214753
|
+
}
|
|
214754
|
+
if (event["type"] === "task.output") {
|
|
214755
|
+
this.handleTaskOutput(event);
|
|
214756
|
+
return;
|
|
214757
|
+
}
|
|
214758
|
+
if (event["type"] === "task.settled") {
|
|
214759
|
+
this.handleTaskSettled(event);
|
|
214760
|
+
return;
|
|
214761
|
+
}
|
|
214762
|
+
if (event["type"] === "completion.review.injected") {
|
|
214763
|
+
this.context.append({
|
|
214764
|
+
role: "user",
|
|
214765
|
+
content: [{
|
|
214766
|
+
type: "text",
|
|
214767
|
+
text: wrapSystemReminder(toText(event["reminder"]))
|
|
214768
|
+
}],
|
|
214769
|
+
toolCalls: [],
|
|
214770
|
+
origin: {
|
|
214771
|
+
kind: "system_trigger",
|
|
214772
|
+
name: "completion_review"
|
|
214773
|
+
},
|
|
214774
|
+
id: randomUUID()
|
|
214775
|
+
});
|
|
214776
|
+
return;
|
|
214777
|
+
}
|
|
214778
|
+
const busEvent = { ...event };
|
|
214779
|
+
if (event["type"] === "turn.step.completed") {
|
|
214780
|
+
const engineUsage = event["usage"];
|
|
214781
|
+
if (engineUsage !== void 0) {
|
|
214782
|
+
const inputCacheRead = engineUsage.cachedTokens ?? 0;
|
|
214783
|
+
busEvent["usage"] = {
|
|
214784
|
+
inputOther: Math.max((engineUsage.inputTokens ?? 0) - inputCacheRead, 0),
|
|
214785
|
+
output: engineUsage.outputTokens ?? 0,
|
|
214786
|
+
inputCacheRead,
|
|
214787
|
+
inputCacheCreation: 0
|
|
214788
|
+
};
|
|
214789
|
+
} else busEvent["usage"] = emptyUsage();
|
|
214790
|
+
} else if (event["type"] === "turn.ended" && event["reason"] === "failed") {
|
|
214791
|
+
const rawError = event["error"];
|
|
214792
|
+
if (rawError !== void 0) busEvent["error"] = buildErrorPayload(rawError);
|
|
214793
|
+
} else if (event["type"] === "turn.started" && !isDisplayablePromptOrigin(origin)) delete busEvent["prompt"];
|
|
214794
|
+
publish(busEvent);
|
|
214795
|
+
switch (event["type"]) {
|
|
214796
|
+
case "turn.step.started": {
|
|
214797
|
+
const stepNumber = Number(event["step"] ?? 1);
|
|
214798
|
+
stepUuid = randomUUID();
|
|
214799
|
+
stepSawToolCall = false;
|
|
214800
|
+
this.context.appendLoopEvent({
|
|
214801
|
+
type: "step.begin",
|
|
214802
|
+
uuid: stepUuid,
|
|
214803
|
+
turnId: String(turnId),
|
|
214804
|
+
step: stepNumber
|
|
214805
|
+
});
|
|
214806
|
+
break;
|
|
214807
|
+
}
|
|
214808
|
+
case "thinking.delta": {
|
|
214809
|
+
const last = segments[segments.length - 1];
|
|
214810
|
+
if (last?.type === "think") last.text += toText(event["delta"]);
|
|
214811
|
+
else segments.push({
|
|
214812
|
+
type: "think",
|
|
214813
|
+
text: toText(event["delta"])
|
|
214814
|
+
});
|
|
214815
|
+
break;
|
|
214816
|
+
}
|
|
214817
|
+
case "assistant.delta": {
|
|
214818
|
+
const last = segments[segments.length - 1];
|
|
214819
|
+
if (last?.type === "text") last.text += toText(event["delta"]);
|
|
214820
|
+
else segments.push({
|
|
214821
|
+
type: "text",
|
|
214822
|
+
text: toText(event["delta"])
|
|
214823
|
+
});
|
|
214824
|
+
break;
|
|
214825
|
+
}
|
|
214826
|
+
case "tool.call.delta": break;
|
|
214827
|
+
case "tool.call.started": {
|
|
214828
|
+
const id = toText(event["toolCallId"]);
|
|
214829
|
+
const name = toText(event["name"]);
|
|
214830
|
+
stepSawToolCall = true;
|
|
214831
|
+
if (ENGINE_NATIVE_TOOLS.has(name)) nativeToolCalls.set(id, {
|
|
214832
|
+
name,
|
|
214833
|
+
input: event["args"]
|
|
214834
|
+
});
|
|
214835
|
+
this.context.appendLoopEvent({
|
|
214836
|
+
type: "tool.call",
|
|
214837
|
+
stepUuid,
|
|
214838
|
+
toolCallId: id,
|
|
214839
|
+
name,
|
|
214840
|
+
args: event["args"],
|
|
214841
|
+
uuid: randomUUID(),
|
|
214842
|
+
turnId: String(turnId),
|
|
214843
|
+
step: Number(event["step"] ?? 1)
|
|
214844
|
+
});
|
|
214845
|
+
break;
|
|
214846
|
+
}
|
|
214847
|
+
case "tool.result": {
|
|
214848
|
+
const id = toText(event["toolCallId"]);
|
|
214849
|
+
const output = toText(event["output"]);
|
|
214850
|
+
const isError = event["isError"] === true;
|
|
214851
|
+
const native = nativeToolCalls.get(id);
|
|
214852
|
+
if (native !== void 0) {
|
|
214853
|
+
nativeToolCalls.delete(id);
|
|
214854
|
+
const hooksRunner = this.instantiation.invokeFunction((accessor) => accessor.get(IExternalHooksRunnerService));
|
|
214855
|
+
if (hooksRunner !== void 0) hooksRunner.fireAndForgetTrigger(isError ? "PostToolUseFailure" : "PostToolUse", {
|
|
214856
|
+
matcherValue: native.name,
|
|
214857
|
+
signal: new AbortController().signal,
|
|
214858
|
+
sessionId: this.sessionContext.sessionId,
|
|
214859
|
+
inputData: {
|
|
214860
|
+
toolName: native.name,
|
|
214861
|
+
toolInput: isPlainRecord(native.input) ? native.input : {},
|
|
214862
|
+
toolCallId: id,
|
|
214863
|
+
error: isError ? toDimiErrorPayload(output) : void 0,
|
|
214864
|
+
toolOutput: isError ? void 0 : output.slice(0, 2e3)
|
|
214865
|
+
}
|
|
214866
|
+
});
|
|
214867
|
+
}
|
|
214868
|
+
this.context.appendLoopEvent({
|
|
214869
|
+
type: "tool.result",
|
|
214870
|
+
toolCallId: id,
|
|
214871
|
+
result: {
|
|
214872
|
+
output,
|
|
214873
|
+
isError
|
|
214874
|
+
},
|
|
214875
|
+
parentUuid: stepUuid
|
|
214876
|
+
});
|
|
214877
|
+
break;
|
|
214878
|
+
}
|
|
214879
|
+
case "context.compacted": {
|
|
214880
|
+
const summary = toText(event["summary"]);
|
|
214881
|
+
const tokensBefore = Number(event["tokensBefore"] ?? 0);
|
|
214882
|
+
const compactedCount = Number(event["compactedCount"] ?? 0);
|
|
214883
|
+
this.wire.dispatch(fullCompactionBegin({ source: "auto" }));
|
|
214884
|
+
const result = this.context.applyCompaction({
|
|
214885
|
+
summary,
|
|
214886
|
+
contextSummary: buildCompactionSummaryText(summary),
|
|
214887
|
+
compactedCount,
|
|
214888
|
+
tokensBefore
|
|
214889
|
+
});
|
|
214890
|
+
this.wire.dispatch(fullCompactionComplete({}));
|
|
214891
|
+
this.eventBus.publish({
|
|
214892
|
+
type: "compaction.completed",
|
|
214893
|
+
result
|
|
214894
|
+
});
|
|
214895
|
+
break;
|
|
214896
|
+
}
|
|
214897
|
+
case "turn.step.interrupted":
|
|
214898
|
+
if (stepSawToolCall) flushParts(turnId, Number(event["step"] ?? 1));
|
|
214899
|
+
break;
|
|
214900
|
+
case "turn.step.completed": {
|
|
214901
|
+
const stepFinish = toText(event["finishReason"] ?? "end_turn");
|
|
214902
|
+
const stepNumber = Number(event["step"] ?? 1);
|
|
214903
|
+
flushParts(turnId, stepNumber);
|
|
214904
|
+
const engineUsage = event["usage"];
|
|
214905
|
+
if (engineUsage !== void 0) {
|
|
214906
|
+
const inputCacheRead = engineUsage.cachedTokens ?? 0;
|
|
214907
|
+
usage = {
|
|
214908
|
+
inputOther: Math.max((engineUsage.inputTokens ?? 0) - inputCacheRead, 0),
|
|
214909
|
+
output: engineUsage.outputTokens ?? 0,
|
|
214910
|
+
inputCacheRead,
|
|
214911
|
+
inputCacheCreation: 0
|
|
214912
|
+
};
|
|
214913
|
+
} else usage = emptyUsage();
|
|
214914
|
+
this.usageService.record(providerModel, usage, {
|
|
214915
|
+
kind: "loop",
|
|
214916
|
+
turnId: String(turnId),
|
|
214917
|
+
step: stepNumber
|
|
214918
|
+
});
|
|
214919
|
+
this.context.appendLoopEvent({
|
|
214920
|
+
type: "step.end",
|
|
214921
|
+
uuid: stepUuid,
|
|
214922
|
+
turnId: String(turnId),
|
|
214923
|
+
step: stepNumber,
|
|
214924
|
+
finishReason: stepFinish,
|
|
214925
|
+
usage
|
|
214926
|
+
});
|
|
214927
|
+
if (stepFinish !== "tool_use" && stepFinish !== "filtered") this.runStopHook(turnId);
|
|
214928
|
+
break;
|
|
214929
|
+
}
|
|
214930
|
+
case "turn.ended":
|
|
214931
|
+
this.stopHookContinuationUsed = false;
|
|
214932
|
+
if (event["reason"] === "failed" && event["error"] !== void 0) this.eventBus.publish({
|
|
214933
|
+
type: "error",
|
|
214934
|
+
...buildErrorPayload(event["error"])
|
|
214935
|
+
});
|
|
214936
|
+
break;
|
|
214937
|
+
default: break;
|
|
214938
|
+
}
|
|
214939
|
+
};
|
|
214940
|
+
session.setOnEvent((eventJson) => {
|
|
214941
|
+
try {
|
|
214942
|
+
handleEngineEvent(JSON.parse(eventJson));
|
|
214943
|
+
} catch (error) {
|
|
214944
|
+
this.log.error("[rustEngineTurnRunner] failed to process engine event", { error });
|
|
214945
|
+
}
|
|
214946
|
+
});
|
|
214947
|
+
let progress = JSON.parse(await session.run());
|
|
214948
|
+
while (progress.progress.status === "needsApproval") {
|
|
214949
|
+
const approval = progress.progress.approval;
|
|
214950
|
+
const approvalRequest = {
|
|
214951
|
+
sessionId: this.sessionContext.sessionId,
|
|
214952
|
+
agentId: this.scopeContext.agentId,
|
|
214953
|
+
turnId,
|
|
214954
|
+
toolCallId: approval.toolCallId,
|
|
214955
|
+
toolName: approval.toolName,
|
|
214956
|
+
action: `Approve ${approval.toolName}`,
|
|
214957
|
+
display: {
|
|
214958
|
+
kind: "generic",
|
|
214959
|
+
summary: `Approve ${approval.toolName}`,
|
|
214960
|
+
detail: approval.toolInput
|
|
214961
|
+
}
|
|
214962
|
+
};
|
|
214963
|
+
this.eventBus.publish({
|
|
214964
|
+
type: "permission.approval.requested",
|
|
214965
|
+
...approvalRequest
|
|
214966
|
+
});
|
|
214967
|
+
let response = { decision: "approved" };
|
|
214968
|
+
const approvalController = new AbortController();
|
|
214969
|
+
this.approvalAbort = approvalController;
|
|
214970
|
+
try {
|
|
214971
|
+
const approvalService = this.instantiation.invokeFunction((accessor) => accessor.get(ISessionApprovalService));
|
|
214972
|
+
response = approvalService !== void 0 ? await Promise.race([approvalService.request(approvalRequest), abortOnSignal(approvalController.signal).then(() => ({ decision: "cancelled" }))]) : { decision: "approved" };
|
|
214973
|
+
} catch {
|
|
214974
|
+
response = { decision: "rejected" };
|
|
214975
|
+
} finally {
|
|
214976
|
+
this.approvalAbort = void 0;
|
|
214977
|
+
}
|
|
214978
|
+
this.eventBus.publish({
|
|
214979
|
+
type: "permission.approval.resolved",
|
|
214980
|
+
...approvalRequest,
|
|
214981
|
+
decision: response.decision
|
|
214982
|
+
});
|
|
214983
|
+
this.rulesService.recordApprovalResult({
|
|
214984
|
+
turnId,
|
|
214985
|
+
toolCallId: approvalRequest.toolCallId,
|
|
214986
|
+
toolName: approvalRequest.toolName,
|
|
214987
|
+
action: approvalRequest.action,
|
|
214988
|
+
sessionApprovalRule: response.decision === "approved" && response.scope === "session" ? approvalRequest.toolName : void 0,
|
|
214989
|
+
result: response
|
|
214990
|
+
});
|
|
214991
|
+
if (response.decision === "approved" && response.scope === "session") session.addSessionApproval(approvalRequest.toolName);
|
|
214992
|
+
progress = JSON.parse(await session.resume(JSON.stringify(response)));
|
|
214993
|
+
}
|
|
214994
|
+
}
|
|
214995
|
+
/**
|
|
214996
|
+
* TS `externalHooksService.runStop` parity (P1-3): after a non-tool step,
|
|
214997
|
+
* fire the Stop hook; a returned reason becomes a continuation message
|
|
214998
|
+
* (origin `system_trigger`/`stop_hook`) that keeps the turn alive —
|
|
214999
|
+
* steered into the running turn, or launched as a fresh turn when the
|
|
215000
|
+
* engine already finished (the task-notification fallback). Fires at most
|
|
215001
|
+
* once after a continuation was used, mirroring `stopHookContinuationUsed`.
|
|
215002
|
+
*/
|
|
215003
|
+
runStopHook(turnId) {
|
|
215004
|
+
if (this.stopHookContinuationUsed) return;
|
|
215005
|
+
this.stopHookContinuationUsed = true;
|
|
215006
|
+
const hooksRunner = this.instantiation.invokeFunction((accessor) => accessor.get(IExternalHooksRunnerService));
|
|
215007
|
+
if (hooksRunner === void 0) return;
|
|
215008
|
+
(async () => {
|
|
215009
|
+
try {
|
|
215010
|
+
const reason = (await hooksRunner.triggerBlock("Stop", {
|
|
215011
|
+
signal: new AbortController().signal,
|
|
215012
|
+
sessionId: this.sessionContext.sessionId,
|
|
215013
|
+
inputData: { stopHookActive: false }
|
|
215014
|
+
}))?.reason;
|
|
215015
|
+
if (reason === void 0 || reason.length === 0) return;
|
|
215016
|
+
const origin = {
|
|
215017
|
+
kind: "system_trigger",
|
|
215018
|
+
name: "stop_hook"
|
|
215019
|
+
};
|
|
215020
|
+
if (this.turnRunning && this.activeSession !== void 0 && this.activeSession.steer(reason)) {
|
|
215021
|
+
this.context.append({
|
|
215022
|
+
role: "user",
|
|
215023
|
+
content: [{
|
|
215024
|
+
type: "text",
|
|
215025
|
+
text: reason
|
|
215026
|
+
}],
|
|
215027
|
+
toolCalls: [],
|
|
215028
|
+
origin,
|
|
215029
|
+
id: randomUUID()
|
|
215030
|
+
});
|
|
215031
|
+
this.wire.dispatch(steerTurn({
|
|
215032
|
+
input: [{
|
|
215033
|
+
type: "text",
|
|
215034
|
+
text: reason
|
|
215035
|
+
}],
|
|
215036
|
+
origin
|
|
215037
|
+
}));
|
|
215038
|
+
} else this.runTurn({
|
|
215039
|
+
input: [{
|
|
215040
|
+
type: "text",
|
|
215041
|
+
text: reason
|
|
215042
|
+
}],
|
|
215043
|
+
origin
|
|
215044
|
+
}).catch(() => void 0);
|
|
215045
|
+
} catch {}
|
|
215046
|
+
})();
|
|
215047
|
+
}
|
|
215048
|
+
/**
|
|
215049
|
+
* `task.started` (engine transport) → TS records: the persisted
|
|
215050
|
+
* `task.started` wire op (TaskModel / transcript / TaskList) plus the
|
|
215051
|
+
* `subagent.spawned` session event for subagent launches.
|
|
215052
|
+
*/
|
|
215053
|
+
handleTaskStarted(event) {
|
|
215054
|
+
const taskId = toText(event["taskId"]);
|
|
215055
|
+
const agentId = toText(event["agentId"]);
|
|
215056
|
+
const kind = toText(event["kind"]);
|
|
215057
|
+
const description = toText(event["description"]);
|
|
215058
|
+
const startedAt = Date.now();
|
|
215059
|
+
const pid = toOptionalNumber(event["pid"]);
|
|
215060
|
+
this.taskInfos.set(taskId, {
|
|
215061
|
+
description,
|
|
215062
|
+
startedAt,
|
|
215063
|
+
pid
|
|
215064
|
+
});
|
|
215065
|
+
if (kind === "agent" && agentId !== "") this.engineAgentIds.add(agentId);
|
|
215066
|
+
const info = kind === "agent" ? {
|
|
215067
|
+
taskId,
|
|
215068
|
+
kind: "agent",
|
|
215069
|
+
agentId,
|
|
215070
|
+
subagentType: description,
|
|
215071
|
+
description,
|
|
215072
|
+
status: "running",
|
|
215073
|
+
detached: true,
|
|
215074
|
+
startedAt,
|
|
215075
|
+
endedAt: null
|
|
215076
|
+
} : {
|
|
215077
|
+
taskId,
|
|
215078
|
+
kind: "process",
|
|
215079
|
+
command: description,
|
|
215080
|
+
pid: pid ?? 0,
|
|
215081
|
+
exitCode: null,
|
|
215082
|
+
description,
|
|
215083
|
+
status: "running",
|
|
215084
|
+
detached: true,
|
|
215085
|
+
startedAt,
|
|
215086
|
+
endedAt: null
|
|
215087
|
+
};
|
|
215088
|
+
this.wire.dispatch(taskStarted({ info }));
|
|
215089
|
+
this.registerEngineTask(taskId, agentId, kind, description, pid);
|
|
215090
|
+
if (kind === "agent") {
|
|
215091
|
+
this.eventBus.publish({
|
|
215092
|
+
type: "subagent.spawned",
|
|
215093
|
+
subagentId: agentId,
|
|
215094
|
+
subagentName: description,
|
|
215095
|
+
parentToolCallId: toText(event["parentToolCallId"]),
|
|
215096
|
+
parentAgentId: this.scopeContext.agentId,
|
|
215097
|
+
callerAgentId: this.scopeContext.agentId,
|
|
215098
|
+
description,
|
|
215099
|
+
runInBackground: false
|
|
215100
|
+
});
|
|
215101
|
+
this.eventBus.publish({
|
|
215102
|
+
type: "subagent.started",
|
|
215103
|
+
subagentId: agentId
|
|
215104
|
+
});
|
|
215105
|
+
}
|
|
215106
|
+
}
|
|
215107
|
+
/**
|
|
215108
|
+
* `task.output` (engine transport) → the task-service entry's live sink:
|
|
215109
|
+
* append the streamed delta so TaskOutput shows partial output while the
|
|
215110
|
+
* engine task is still running (TS ProcessTask parity — TS streams chunks
|
|
215111
|
+
* as they arrive; the adapter's settle also appends only the not-yet-
|
|
215112
|
+
* streamed tail, so nothing is duplicated). No wire op / bus event: the
|
|
215113
|
+
* live output is the service's retained buffer, the wire `task.terminated`
|
|
215114
|
+
* tail comes from the settle's full output.
|
|
215115
|
+
*/
|
|
215116
|
+
handleTaskOutput(event) {
|
|
215117
|
+
const taskId = toText(event["taskId"]);
|
|
215118
|
+
const delta = toText(event["delta"]);
|
|
215119
|
+
if (delta.length === 0) return;
|
|
215120
|
+
const adapter = this.engineTaskAdapters.get(taskId);
|
|
215121
|
+
if (adapter !== void 0) {
|
|
215122
|
+
adapter.appendOutput(delta);
|
|
215123
|
+
return;
|
|
215124
|
+
}
|
|
215125
|
+
this.log.debug("[rustEngineTurnRunner] task.output for unregistered task", { taskId });
|
|
215126
|
+
}
|
|
215127
|
+
/**
|
|
215128
|
+
* Register an engine background task with `IAgentTaskService` (TaskList /
|
|
215129
|
+
* TaskStop / TaskOutput parity). The adapter bridges TaskStop into the
|
|
215130
|
+
* engine's per-task cancel (`session.cancelTask`) — the launching session's
|
|
215131
|
+
* worker/poller kills its work and settles "killed" — and its `start`
|
|
215132
|
+
* streams the settle output into the service's sink so TaskOutput and the
|
|
215133
|
+
* terminal info see it.
|
|
215134
|
+
*/
|
|
215135
|
+
registerEngineTask(taskId, agentId, kind, description, pid) {
|
|
215136
|
+
const session = this.taskSessions.get(taskId) ?? this.activeSession;
|
|
215137
|
+
const adapter = new EngineTaskAdapter({
|
|
215138
|
+
taskId,
|
|
215139
|
+
agentId,
|
|
215140
|
+
kind: kind === "agent" ? "agent" : "process",
|
|
215141
|
+
description,
|
|
215142
|
+
pid,
|
|
215143
|
+
subagentType: kind === "agent" ? description : void 0,
|
|
215144
|
+
forceStop: (reason) => {
|
|
215145
|
+
try {
|
|
215146
|
+
session?.cancelTask(taskId, reason);
|
|
215147
|
+
} catch (error) {
|
|
215148
|
+
this.log.error("[rustEngineTurnRunner] failed to cancel engine task", {
|
|
215149
|
+
taskId,
|
|
215150
|
+
error
|
|
215151
|
+
});
|
|
215152
|
+
}
|
|
215153
|
+
}
|
|
215154
|
+
});
|
|
215155
|
+
this.engineTaskAdapters.set(taskId, adapter);
|
|
215156
|
+
try {
|
|
215157
|
+
this.tasks.registerTask(adapter, {
|
|
215158
|
+
taskId,
|
|
215159
|
+
detached: false
|
|
215160
|
+
});
|
|
215161
|
+
} catch (error) {
|
|
215162
|
+
this.log.error("[rustEngineTurnRunner] failed to register engine task", {
|
|
215163
|
+
taskId,
|
|
215164
|
+
error
|
|
215165
|
+
});
|
|
215166
|
+
this.engineTaskAdapters.delete(taskId);
|
|
215167
|
+
}
|
|
215168
|
+
}
|
|
215169
|
+
/**
|
|
215170
|
+
* `task.settled` (engine transport) → TS records: the persisted
|
|
215171
|
+
* `task.terminated` wire op (bounded output tail), the `subagent.completed`
|
|
215172
|
+
* / `subagent.failed` session events, and the completion notification
|
|
215173
|
+
* delivered to the model (context message + `task.notified` + steer/new
|
|
215174
|
+
* turn — TS `activeOrNewTurn` parity).
|
|
215175
|
+
*/
|
|
215176
|
+
handleTaskSettled(event) {
|
|
215177
|
+
const taskId = toText(event["taskId"]);
|
|
215178
|
+
const agentId = toText(event["agentId"]);
|
|
215179
|
+
const kind = toText(event["kind"]);
|
|
215180
|
+
const status = toText(event["status"]);
|
|
215181
|
+
const output = toText(event["output"]);
|
|
215182
|
+
const error = event["error"] === void 0 || event["error"] === null ? void 0 : toText(event["error"]);
|
|
215183
|
+
const launch = this.taskInfos.get(taskId);
|
|
215184
|
+
const endedAt = Date.now();
|
|
215185
|
+
const stopReason = status === "failed" || status === "timed_out" || status === "killed" ? error : void 0;
|
|
215186
|
+
const base = {
|
|
215187
|
+
taskId,
|
|
215188
|
+
description: launch?.description ?? "",
|
|
215189
|
+
status,
|
|
215190
|
+
detached: true,
|
|
215191
|
+
startedAt: launch?.startedAt ?? endedAt,
|
|
215192
|
+
endedAt,
|
|
215193
|
+
stopReason
|
|
215194
|
+
};
|
|
215195
|
+
const info = kind === "agent" ? {
|
|
215196
|
+
...base,
|
|
215197
|
+
kind: "agent",
|
|
215198
|
+
agentId,
|
|
215199
|
+
subagentType: launch?.description ?? ""
|
|
215200
|
+
} : {
|
|
215201
|
+
...base,
|
|
215202
|
+
kind: "process",
|
|
215203
|
+
command: launch?.description ?? "",
|
|
215204
|
+
pid: launch?.pid ?? 0,
|
|
215205
|
+
exitCode: toOptionalNumber(event["exitCode"]) ?? null
|
|
215206
|
+
};
|
|
215207
|
+
this.wire.dispatch(taskTerminated({
|
|
215208
|
+
info,
|
|
215209
|
+
outputTail: output.slice(-TERMINAL_OUTPUT_TAIL_CHARS)
|
|
215210
|
+
}));
|
|
215211
|
+
if (kind === "agent") {
|
|
215212
|
+
if (status === "completed") this.eventBus.publish({
|
|
215213
|
+
type: "subagent.completed",
|
|
215214
|
+
subagentId: agentId,
|
|
215215
|
+
resultSummary: output
|
|
215216
|
+
});
|
|
215217
|
+
else if (status === "failed") this.eventBus.publish({
|
|
215218
|
+
type: "subagent.failed",
|
|
215219
|
+
subagentId: agentId,
|
|
215220
|
+
error: error ?? status
|
|
215221
|
+
});
|
|
215222
|
+
}
|
|
215223
|
+
const adapter = this.engineTaskAdapters.get(taskId);
|
|
215224
|
+
if (adapter !== void 0) {
|
|
215225
|
+
adapter.complete(output, {
|
|
215226
|
+
status,
|
|
215227
|
+
stopReason
|
|
215228
|
+
}, toOptionalNumber(event["exitCode"]));
|
|
215229
|
+
this.engineTaskAdapters.delete(taskId);
|
|
215230
|
+
}
|
|
215231
|
+
this.taskInfos.delete(taskId);
|
|
215232
|
+
this.taskSessions.delete(taskId);
|
|
215233
|
+
if (this.tasks.getTask(taskId)?.terminalNotificationSuppressed === true) return;
|
|
215234
|
+
this.deliverTaskNotification({
|
|
215235
|
+
taskId,
|
|
215236
|
+
agentId,
|
|
215237
|
+
kind,
|
|
215238
|
+
status,
|
|
215239
|
+
description: launch?.description ?? "",
|
|
215240
|
+
output,
|
|
215241
|
+
error
|
|
215242
|
+
});
|
|
215243
|
+
}
|
|
215244
|
+
/**
|
|
215245
|
+
* Deliver a task completion notification to the model — the Rust-engine
|
|
215246
|
+
* equivalent of the TS task domain's detached-task notification
|
|
215247
|
+
* (`TaskNotificationStepRequest`, `activeOrNewTurn` admission): append the
|
|
215248
|
+
* `<notification>` XML as a task-origin user message, fire the
|
|
215249
|
+
* `task.notified` hook event, then fold it into the running turn's next
|
|
215250
|
+
* step (steer) or launch a notification turn when idle.
|
|
215251
|
+
*/
|
|
215252
|
+
deliverTaskNotification(task) {
|
|
215253
|
+
const key = `task:${task.taskId}:${task.status}`;
|
|
215254
|
+
if (this.deliveredNotificationKeys.has(key)) return;
|
|
215255
|
+
this.deliveredNotificationKeys.add(key);
|
|
215256
|
+
const kindLabel = task.kind === "agent" ? "agent" : "process";
|
|
215257
|
+
const notification = {
|
|
215258
|
+
id: key,
|
|
215259
|
+
category: "task",
|
|
215260
|
+
type: `task.${task.status}`,
|
|
215261
|
+
source_kind: "background_task",
|
|
215262
|
+
source_id: task.taskId,
|
|
215263
|
+
agent_id: task.kind === "agent" ? task.agentId : void 0,
|
|
215264
|
+
title: `Background ${kindLabel} ${task.status}`,
|
|
215265
|
+
severity: task.status === "completed" ? "info" : "warning",
|
|
215266
|
+
body: buildTaskNotificationBody(task),
|
|
215267
|
+
children: task.output.length > 0 ? [renderOutputPreviewBlock(task.output)] : void 0
|
|
215268
|
+
};
|
|
215269
|
+
const xml = renderNotificationXml(notification);
|
|
215270
|
+
const origin = {
|
|
215271
|
+
kind: "task",
|
|
215272
|
+
taskId: task.taskId,
|
|
215273
|
+
status: task.status,
|
|
215274
|
+
notificationId: key
|
|
215275
|
+
};
|
|
215276
|
+
try {
|
|
215277
|
+
if (this.turnRunning && this.activeSession !== void 0 && this.activeSession.steer(xml)) {
|
|
215278
|
+
this.context.append({
|
|
215279
|
+
role: "user",
|
|
215280
|
+
content: [{
|
|
215281
|
+
type: "text",
|
|
215282
|
+
text: xml
|
|
215283
|
+
}],
|
|
215284
|
+
toolCalls: [],
|
|
215285
|
+
origin,
|
|
215286
|
+
id: randomUUID()
|
|
215287
|
+
});
|
|
215288
|
+
this.wire.dispatch(steerTurn({
|
|
215289
|
+
input: [{
|
|
215290
|
+
type: "text",
|
|
215291
|
+
text: xml
|
|
215292
|
+
}],
|
|
215293
|
+
origin
|
|
215294
|
+
}));
|
|
215295
|
+
} else this.runTurn({
|
|
215296
|
+
input: [{
|
|
215297
|
+
type: "text",
|
|
215298
|
+
text: xml
|
|
215299
|
+
}],
|
|
215300
|
+
origin
|
|
215301
|
+
}).catch(() => void 0);
|
|
215302
|
+
this.eventBus.publish({
|
|
215303
|
+
type: "task.notified",
|
|
215304
|
+
notificationType: `task.${task.status}`,
|
|
215305
|
+
title: notification.title,
|
|
215306
|
+
body: notification.body,
|
|
215307
|
+
severity: notification.severity,
|
|
215308
|
+
sourceKind: notification.source_kind,
|
|
215309
|
+
sourceId: notification.source_id
|
|
215310
|
+
});
|
|
215311
|
+
} finally {
|
|
215312
|
+
this.deliveredNotificationKeys.delete(key);
|
|
215313
|
+
}
|
|
215314
|
+
}
|
|
215315
|
+
toLlmMessage(message) {
|
|
215316
|
+
const text = message.content.filter((part) => part.type === "text").map((part) => part.text ?? "").join("");
|
|
215317
|
+
const media = message.content.filter((part) => part.type === "image_url" || part.type === "audio_url" || part.type === "video_url").map((part) => {
|
|
215318
|
+
return {
|
|
215319
|
+
type: "media_url",
|
|
215320
|
+
url: part.imageUrl?.url ?? part.audioUrl?.url ?? part.videoUrl?.url
|
|
215321
|
+
};
|
|
215322
|
+
}).filter((part) => part.url !== void 0);
|
|
215323
|
+
const toolCalls = message.toolCalls.map((call) => ({
|
|
215324
|
+
id: call.id,
|
|
215325
|
+
type: "function",
|
|
215326
|
+
function: {
|
|
215327
|
+
name: call.name,
|
|
215328
|
+
arguments: call.arguments
|
|
215329
|
+
}
|
|
215330
|
+
}));
|
|
215331
|
+
return {
|
|
215332
|
+
role: message.role,
|
|
215333
|
+
content: media.length > 0 ? [...media, ...text.length > 0 ? [{
|
|
215334
|
+
type: "text",
|
|
215335
|
+
text
|
|
215336
|
+
}] : []] : text,
|
|
215337
|
+
...message.role === "assistant" && toolCalls.length > 0 ? { toolCalls } : {},
|
|
215338
|
+
...message.role === "tool" && message.toolCallId !== void 0 ? { toolCallId: message.toolCallId } : {}
|
|
215339
|
+
};
|
|
215340
|
+
}
|
|
215341
|
+
/**
|
|
215342
|
+
* The next subagent agent-id number to hand to the engine for this turn
|
|
215343
|
+
* (TS `nextAvailableAgentId` parity): the max known `agent-<n>` suffix
|
|
215344
|
+
* among (a) the ids this runner's engine has already handed out across
|
|
215345
|
+
* turns and (b) the session's persisted agents, plus one. The engine seeds
|
|
215346
|
+
* its per-session counter from it, so ids stay monotonic across turns and
|
|
215347
|
+
* server restarts and never collide with TS-assigned ids.
|
|
215348
|
+
*/
|
|
215349
|
+
async computeNextAgentId() {
|
|
215350
|
+
let maxSuffix = -1;
|
|
215351
|
+
const consider = (id) => {
|
|
215352
|
+
const match = /^agent-(\d+)$/.exec(id);
|
|
215353
|
+
if (match !== null) maxSuffix = Math.max(maxSuffix, Number(match[1]));
|
|
215354
|
+
};
|
|
215355
|
+
for (const id of this.engineAgentIds) consider(id);
|
|
215356
|
+
try {
|
|
215357
|
+
const persisted = (await this.sessionMetadata.read()).agents ?? {};
|
|
215358
|
+
for (const id of Object.keys(persisted)) consider(id);
|
|
215359
|
+
} catch {
|
|
215360
|
+
this.log.warn("[rustEngineTurnRunner] failed to read session metadata; seeding next agent id from in-session engine ids only");
|
|
215361
|
+
}
|
|
215362
|
+
return maxSuffix + 1;
|
|
215363
|
+
}
|
|
215364
|
+
maxStepsPerTurn() {
|
|
215365
|
+
return this.config.get("loop_control")?.maxStepsPerTurn;
|
|
215366
|
+
}
|
|
215367
|
+
/**
|
|
215368
|
+
* The effective engine-side tool allowlist (TS `isToolActiveComposed`
|
|
215369
|
+
* parity): the runner's `IAgentToolPolicyService.isToolActive` composes
|
|
215370
|
+
* the profile allowlist/denylist, the global `[tools]` config, and the
|
|
215371
|
+
* session denylist — with MCP glob semantics for `mcp__*` tools. AllDone
|
|
215372
|
+
* stays active regardless (the completion-review protocol needs it).
|
|
215373
|
+
* `undefined` = unconstrained (all tools).
|
|
215374
|
+
*/
|
|
215375
|
+
effectiveActiveTools() {
|
|
215376
|
+
const all = this.toolRegistry.list().map((info) => info.name);
|
|
215377
|
+
const active = all.filter((name) => {
|
|
215378
|
+
if (name === "AllDone") return true;
|
|
215379
|
+
return this.toolPolicy.isToolActive(name);
|
|
215380
|
+
});
|
|
215381
|
+
return active.length === all.length ? void 0 : active;
|
|
215382
|
+
}
|
|
215383
|
+
maxRetriesPerStep() {
|
|
215384
|
+
return this.config.get("loop_control")?.maxRetriesPerStep;
|
|
215385
|
+
}
|
|
215386
|
+
killGracePeriodMs() {
|
|
215387
|
+
return resolveAgentTaskConfig(this.config)?.killGracePeriodMs ?? 5e3;
|
|
215388
|
+
}
|
|
215389
|
+
maxContextTokens() {
|
|
215390
|
+
const capability = this.profile.data().modelCapabilities;
|
|
215391
|
+
const max = capability.max_input_tokens ?? capability.max_context_tokens;
|
|
215392
|
+
return max > 0 ? max : void 0;
|
|
215393
|
+
}
|
|
215394
|
+
async providerConfig() {
|
|
215395
|
+
const modelAlias = this.profile.data().modelAlias ?? this.profile.getModel();
|
|
215396
|
+
let baseUrl = "";
|
|
215397
|
+
let apiKey = "";
|
|
215398
|
+
try {
|
|
215399
|
+
const model = this.modelCatalog.get(modelAlias);
|
|
215400
|
+
baseUrl = model.baseUrl;
|
|
215401
|
+
apiKey = (await this.providerRuntime.getAuth(model))?.auth.apiKey ?? "";
|
|
215402
|
+
} catch {}
|
|
215403
|
+
return {
|
|
215404
|
+
baseUrl: baseUrl || "https://api.openai.com/v1",
|
|
215405
|
+
apiKey,
|
|
215406
|
+
model: modelAlias || "gpt-4o",
|
|
215407
|
+
thinkingEffort: this.profile.getEffectiveThinkingLevel()
|
|
215408
|
+
};
|
|
215409
|
+
}
|
|
215410
|
+
};
|
|
215411
|
+
RustEngineTurnRunner = __decorate$1([
|
|
215412
|
+
__decorateParam(0, IAgentContextMemoryService),
|
|
215413
|
+
__decorateParam(1, IEventBus),
|
|
215414
|
+
__decorateParam(2, IWireService),
|
|
215415
|
+
__decorateParam(3, IConfigService),
|
|
215416
|
+
__decorateParam(4, IAgentPermissionModeService),
|
|
215417
|
+
__decorateParam(5, IAgentPermissionRulesService),
|
|
215418
|
+
__decorateParam(6, IAgentToolRegistryService),
|
|
215419
|
+
__decorateParam(7, IAgentUsageService),
|
|
215420
|
+
__decorateParam(8, IAgentProfileService),
|
|
215421
|
+
__decorateParam(9, IAgentScopeContext),
|
|
215422
|
+
__decorateParam(10, ISessionContext),
|
|
215423
|
+
__decorateParam(11, ISessionMetadata),
|
|
215424
|
+
__decorateParam(12, IAgentTaskService),
|
|
215425
|
+
__decorateParam(13, IModelCatalog),
|
|
215426
|
+
__decorateParam(14, IProviderRuntime),
|
|
215427
|
+
__decorateParam(15, IInstantiationService),
|
|
215428
|
+
__decorateParam(16, IAgentToolPolicyService),
|
|
215429
|
+
__decorateParam(17, ILogService)
|
|
215430
|
+
], RustEngineTurnRunner);
|
|
215431
|
+
registerScopedService(2, IRustEngineTurnRunner, RustEngineTurnRunner, 0, "rustEngineTurnRunner");
|
|
215432
|
+
}));
|
|
215433
|
+
//#endregion
|
|
213502
215434
|
//#region ../../packages/agent-core-v2/src/agent/rpc/prompt-metadata.ts
|
|
213503
215435
|
function promptMetadataTextFromPayload(payload) {
|
|
213504
215436
|
return promptMetadataTextFromContentParts(payload.input);
|
|
@@ -213567,6 +215499,7 @@ var init_rpcService = __esmMin((() => {
|
|
|
213567
215499
|
init_telemetry$2();
|
|
213568
215500
|
init_toolRegistry();
|
|
213569
215501
|
init_loop();
|
|
215502
|
+
init_rustEngineTurnRunner();
|
|
213570
215503
|
init_rpc$2();
|
|
213571
215504
|
init_prompt_metadata();
|
|
213572
215505
|
init_decorateParam();
|
|
@@ -213590,7 +215523,8 @@ var init_rpcService = __esmMin((() => {
|
|
|
213590
215523
|
sessionContext;
|
|
213591
215524
|
scopeContext;
|
|
213592
215525
|
agentLifecycle;
|
|
213593
|
-
|
|
215526
|
+
rustEngineTurnRunner;
|
|
215527
|
+
constructor(promptService, conversationUndo, loop, toolPolicy, permissionMode, fullCompaction, toolRegistry, context, contextSize, skills, telemetry, eventBus, eventService, plugins, metadata, sessionContext, scopeContext, agentLifecycle, rustEngineTurnRunner) {
|
|
213594
215528
|
this.promptService = promptService;
|
|
213595
215529
|
this.conversationUndo = conversationUndo;
|
|
213596
215530
|
this.loop = loop;
|
|
@@ -213609,6 +215543,7 @@ var init_rpcService = __esmMin((() => {
|
|
|
213609
215543
|
this.sessionContext = sessionContext;
|
|
213610
215544
|
this.scopeContext = scopeContext;
|
|
213611
215545
|
this.agentLifecycle = agentLifecycle;
|
|
215546
|
+
this.rustEngineTurnRunner = rustEngineTurnRunner;
|
|
213612
215547
|
}
|
|
213613
215548
|
async prompt(payload) {
|
|
213614
215549
|
if (payload.disabledTools !== void 0) try {
|
|
@@ -213618,6 +215553,13 @@ var init_rpcService = __esmMin((() => {
|
|
|
213618
215553
|
throw error;
|
|
213619
215554
|
}
|
|
213620
215555
|
await this.updatePromptMetadata(promptMetadataTextFromPayload(payload));
|
|
215556
|
+
if (RustEngineTurnRunner.isEnabled()) {
|
|
215557
|
+
const launched = await this.rustEngineTurnRunner.runTurn({
|
|
215558
|
+
input: [...payload.input],
|
|
215559
|
+
origin: { kind: "user" }
|
|
215560
|
+
});
|
|
215561
|
+
return launched === void 0 ? void 0 : { turn_id: launched.turnId };
|
|
215562
|
+
}
|
|
213621
215563
|
const handle = await this.promptService.enqueue({ message: {
|
|
213622
215564
|
role: "user",
|
|
213623
215565
|
content: [...payload.input],
|
|
@@ -213630,6 +215572,17 @@ var init_rpcService = __esmMin((() => {
|
|
|
213630
215572
|
}
|
|
213631
215573
|
async steer(payload) {
|
|
213632
215574
|
this.telemetry.track2("input_steer", { parts: payload.input.length });
|
|
215575
|
+
if (RustEngineTurnRunner.isEnabled()) {
|
|
215576
|
+
if (this.rustEngineTurnRunner.steer({
|
|
215577
|
+
input: [...payload.input],
|
|
215578
|
+
origin: { kind: "user" }
|
|
215579
|
+
})) return { turn_id: 0 };
|
|
215580
|
+
const launched = await this.rustEngineTurnRunner.runTurn({
|
|
215581
|
+
input: [...payload.input],
|
|
215582
|
+
origin: { kind: "user" }
|
|
215583
|
+
});
|
|
215584
|
+
return launched === void 0 ? void 0 : { turn_id: launched.turnId };
|
|
215585
|
+
}
|
|
213633
215586
|
const submitted = await this.promptService.enqueueOrSteer({ message: {
|
|
213634
215587
|
role: "user",
|
|
213635
215588
|
content: [...payload.input],
|
|
@@ -213640,6 +215593,10 @@ var init_rpcService = __esmMin((() => {
|
|
|
213640
215593
|
return turn === void 0 ? void 0 : { turn_id: turn.id };
|
|
213641
215594
|
}
|
|
213642
215595
|
cancel({ turnId }) {
|
|
215596
|
+
if (RustEngineTurnRunner.isEnabled()) {
|
|
215597
|
+
this.rustEngineTurnRunner.cancel(turnId);
|
|
215598
|
+
return;
|
|
215599
|
+
}
|
|
213643
215600
|
if (this.loop.status().state === "running") this.telemetry.track2("cancel", {
|
|
213644
215601
|
from: "streaming",
|
|
213645
215602
|
trace_id: this.loop.status().activeTraceId
|
|
@@ -213744,7 +215701,8 @@ var init_rpcService = __esmMin((() => {
|
|
|
213744
215701
|
__decorateParam(14, ISessionMetadata),
|
|
213745
215702
|
__decorateParam(15, ISessionContext),
|
|
213746
215703
|
__decorateParam(16, IAgentScopeContext),
|
|
213747
|
-
__decorateParam(17, IAgentLifecycleService)
|
|
215704
|
+
__decorateParam(17, IAgentLifecycleService),
|
|
215705
|
+
__decorateParam(18, IRustEngineTurnRunner)
|
|
213748
215706
|
], AgentRPCService);
|
|
213749
215707
|
registerScopedService(2, IAgentRPCService, AgentRPCService, 0, "rpc");
|
|
213750
215708
|
}));
|
|
@@ -216321,13 +218279,6 @@ var init_args_validator = __esmMin((() => {
|
|
|
216321
218279
|
]);
|
|
216322
218280
|
}));
|
|
216323
218281
|
//#endregion
|
|
216324
|
-
//#region ../../packages/agent-core-v2/src/agent/toolResultTruncation/toolResultTruncation.ts
|
|
216325
|
-
var IAgentToolResultTruncationService;
|
|
216326
|
-
var init_toolResultTruncation = __esmMin((() => {
|
|
216327
|
-
init_instantiation();
|
|
216328
|
-
IAgentToolResultTruncationService = createDecorator("agentToolResultTruncationService");
|
|
216329
|
-
}));
|
|
216330
|
-
//#endregion
|
|
216331
218282
|
//#region ../../packages/agent-core-v2/src/agent/toolExecutor/toolScheduler.ts
|
|
216332
218283
|
function createControlledPromise() {
|
|
216333
218284
|
let resolve;
|
|
@@ -217391,7 +219342,7 @@ var init_src$6 = __esmMin((() => {
|
|
|
217391
219342
|
init_migration();
|
|
217392
219343
|
init_sessionLogService();
|
|
217393
219344
|
init_telemetry$2();
|
|
217394
|
-
init_events$
|
|
219345
|
+
init_events$8();
|
|
217395
219346
|
init_telemetryService();
|
|
217396
219347
|
init_agentTelemetryContext();
|
|
217397
219348
|
init_agentTelemetryContextService();
|
|
@@ -217586,6 +219537,8 @@ var init_src$6 = __esmMin((() => {
|
|
|
217586
219537
|
init_wait();
|
|
217587
219538
|
init_waitService();
|
|
217588
219539
|
init_waitForTool();
|
|
219540
|
+
init_agent_output$1();
|
|
219541
|
+
init_agentOutputTool();
|
|
217589
219542
|
init_completion();
|
|
217590
219543
|
init_allDoneTool();
|
|
217591
219544
|
init_configSection$4();
|
|
@@ -218476,7 +220429,7 @@ var modelCatalogItemSchema$1, providerCatalogStatusSchema$1, providerCatalogItem
|
|
|
218476
220429
|
provider: string$2().min(1),
|
|
218477
220430
|
reason: string$2().min(1)
|
|
218478
220431
|
});
|
|
218479
|
-
})), tokenUsageSchema$2, finishReasonSchema$1, usageStatusSchema$2, permissionModeSchema$2, skillSourceSchema$2, userPromptOriginSchema$1, skillActivationOriginSchema$1, pluginCommandOriginSchema$1, injectionOriginSchema$1, shellCommandOriginSchema$1, compactionSummaryOriginSchema$1, systemTriggerOriginSchema$1, taskLifecycleStatusSchema$2, taskOriginSchema$1, cronJobOriginSchema$1, cronMissedOriginSchema$1, hookResultOriginSchema$1, retryOriginSchema$1, promptOriginSchema$1, dimiErrorCodeSchema$1, dimiErrorPayloadSchema$1, dimiErrorPayloadObjectSchema$1, taskInfoBaseSchema$1, processTaskInfoSchema$1, agentTaskInfoSchema$2, questionTaskInfoSchema$1, toolTaskInfoSchema$1, taskInfoSchema$1, compactionResultSchema$1, toolUpdateSchema$1, turnEndReasonSchema$2, agentPhaseSchema$1, agentStatusUpdatedEventSchema$2, sessionMetaUpdatedEventSchema$1, sessionCreatedEventSchema$1, workspaceCreatedEventSchema$1, workspaceUpdatedEventSchema$1, workspaceDeletedEventSchema$1, sessionWorkChangedEventSchema$1, sessionStatusChangedEventSchema$1, modelCatalogChangedEventSchema, skillActivatedEventSchema$1, pluginCommandActivatedEventSchema$1, errorEventSchema$2, warningEventSchema$2, turnStartedEventSchema$2, turnEndedEventSchema$2, turnStepStartedEventSchema$1, turnStepCompletedEventSchema$1, turnStepRetryingEventSchema$1, turnStepInterruptedEventSchema$1, assistantDeltaEventSchema$2, hookResultEventSchema$1, thinkingDeltaEventSchema$2, toolCallDeltaEventSchema$1, toolCallStartedEventSchema$2, toolProgressEventSchema$1, shellOutputEventSchema$1, shellStartedEventSchema$1, shellCompletedEventSchema$1, toolResultEventSchema$2, subagentSpawnedEventSchema$1, subagentStartedEventSchema$1, subagentSuspendedEventSchema$1, subagentCompletedEventSchema$1, subagentFailedEventSchema$1, compactionStartedEventSchema$1, compactionBlockedEventSchema$1, compactionCancelledEventSchema$1, compactionCompletedEventSchema$1, taskStartedEventSchema$1, taskTerminatedEventSchema$1, cronFiredEventSchema$1, promptSubmittedEventSchema$1, promptCompletedEventSchema$2, promptAbortedEventSchema$2, promptSteeredEventSchema$1, toolListUpdatedReasonSchema$1, toolListUpdatedEventSchema$1, mcpServerStatusPayloadSchema$1, mcpServerStatusEventSchema$1, agentEventSchema$1, eventSchema$1, VOLATILE_EVENT_TYPES$1, init_events$
|
|
220432
|
+
})), tokenUsageSchema$2, finishReasonSchema$1, usageStatusSchema$2, permissionModeSchema$2, skillSourceSchema$2, userPromptOriginSchema$1, skillActivationOriginSchema$1, pluginCommandOriginSchema$1, injectionOriginSchema$1, shellCommandOriginSchema$1, compactionSummaryOriginSchema$1, systemTriggerOriginSchema$1, taskLifecycleStatusSchema$2, taskOriginSchema$1, cronJobOriginSchema$1, cronMissedOriginSchema$1, hookResultOriginSchema$1, retryOriginSchema$1, promptOriginSchema$1, dimiErrorCodeSchema$1, dimiErrorPayloadSchema$1, dimiErrorPayloadObjectSchema$1, taskInfoBaseSchema$1, processTaskInfoSchema$1, agentTaskInfoSchema$2, questionTaskInfoSchema$1, toolTaskInfoSchema$1, taskInfoSchema$1, compactionResultSchema$1, toolUpdateSchema$1, turnEndReasonSchema$2, agentPhaseSchema$1, agentStatusUpdatedEventSchema$2, sessionMetaUpdatedEventSchema$1, sessionCreatedEventSchema$1, workspaceCreatedEventSchema$1, workspaceUpdatedEventSchema$1, workspaceDeletedEventSchema$1, sessionWorkChangedEventSchema$1, sessionStatusChangedEventSchema$1, modelCatalogChangedEventSchema, skillActivatedEventSchema$1, pluginCommandActivatedEventSchema$1, errorEventSchema$2, warningEventSchema$2, turnStartedEventSchema$2, turnEndedEventSchema$2, turnStepStartedEventSchema$1, turnStepCompletedEventSchema$1, turnStepRetryingEventSchema$1, turnStepInterruptedEventSchema$1, assistantDeltaEventSchema$2, hookResultEventSchema$1, thinkingDeltaEventSchema$2, toolCallDeltaEventSchema$1, toolCallStartedEventSchema$2, toolProgressEventSchema$1, shellOutputEventSchema$1, shellStartedEventSchema$1, shellCompletedEventSchema$1, toolResultEventSchema$2, subagentSpawnedEventSchema$1, subagentStartedEventSchema$1, subagentSuspendedEventSchema$1, subagentCompletedEventSchema$1, subagentFailedEventSchema$1, compactionStartedEventSchema$1, compactionBlockedEventSchema$1, compactionCancelledEventSchema$1, compactionCompletedEventSchema$1, taskStartedEventSchema$1, taskTerminatedEventSchema$1, cronFiredEventSchema$1, promptSubmittedEventSchema$1, promptCompletedEventSchema$2, promptAbortedEventSchema$2, promptSteeredEventSchema$1, toolListUpdatedReasonSchema$1, toolListUpdatedEventSchema$1, mcpServerStatusPayloadSchema$1, mcpServerStatusEventSchema$1, agentEventSchema$1, eventSchema$1, VOLATILE_EVENT_TYPES$1, init_events$7 = __esmMin((() => {
|
|
218480
220433
|
init_zod$1();
|
|
218481
220434
|
init_display$1();
|
|
218482
220435
|
init_message$1();
|
|
@@ -219250,7 +221203,7 @@ var modelCatalogItemSchema$1, providerCatalogStatusSchema$1, providerCatalogItem
|
|
|
219250
221203
|
})), sessionCursorSchema$1, cursorsBySessionSchema$1, wsEventEnvelopeSchema$1, wsAckEnvelopeSchema$1, serverHelloPayloadSchema$1, serverHelloMessageSchema$1, agentFilterSchema$1, clientHelloPayloadSchema$1, clientHelloMessageSchema$1, clientHelloAckPayloadSchema$1, clientHelloAckMessageSchema$1, watchFsConfigSchema$1, subscribePayloadSchema$1, subscribeMessageSchema$1, subscribeAckPayloadSchema$1, subscribeAckMessageSchema$1, unsubscribePayloadSchema$1, unsubscribeMessageSchema$1, unsubscribeAckPayloadSchema$1, unsubscribeAckMessageSchema$1, watchFsAddPayloadSchema$1, watchFsAddMessageSchema$1, watchFsRemovePayloadSchema$1, watchFsRemoveMessageSchema$1, watchFsAckPayloadSchema$1, watchFsAckMessageSchema$1, abortPayloadSchema$1, abortMessageSchema$1, abortAckPayloadSchema$1, abortAckMessageSchema$1, terminalAttachPayloadSchema$1, terminalAttachMessageSchema$1, terminalAttachAckPayloadSchema$1, terminalAttachAckMessageSchema$1, terminalDetachPayloadSchema$1, terminalDetachMessageSchema$1, terminalDetachAckPayloadSchema$1, terminalDetachAckMessageSchema$1, terminalInputPayloadSchema$1, terminalInputMessageSchema$1, terminalInputAckPayloadSchema$1, terminalInputAckMessageSchema$1, terminalResizePayloadSchema$1, terminalResizeMessageSchema$1, terminalResizeAckPayloadSchema$1, terminalResizeAckMessageSchema$1, terminalClosePayloadSchema$1, terminalCloseMessageSchema$1, terminalCloseAckPayloadSchema$1, terminalCloseAckMessageSchema$1, pingPayloadSchema$1, pingMessageSchema$1, pongPayloadSchema$1, pongMessageSchema$1, resyncRequiredPayloadSchema$1, resyncRequiredMessageSchema$1, wsErrorPayloadSchema$1, wsErrorMessageSchema$1, terminalOutputPayloadSchema$1, terminalExitPayloadSchema$1, clientControlOperations$1, serverSystemOperations$1;
|
|
219251
221204
|
var init_ws_control$1 = __esmMin((() => {
|
|
219252
221205
|
init_zod$1();
|
|
219253
|
-
init_events$
|
|
221206
|
+
init_events$7();
|
|
219254
221207
|
init_time();
|
|
219255
221208
|
sessionCursorSchema$1 = object({
|
|
219256
221209
|
seq: number$2().int().nonnegative(),
|
|
@@ -219795,7 +221748,7 @@ var init_tool$2 = __esmMin((() => {
|
|
|
219795
221748
|
var skillDescriptorSchema$1;
|
|
219796
221749
|
var init_skill$2 = __esmMin((() => {
|
|
219797
221750
|
init_zod$1();
|
|
219798
|
-
init_events$
|
|
221751
|
+
init_events$7();
|
|
219799
221752
|
skillDescriptorSchema$1 = object({
|
|
219800
221753
|
name: string$2().min(1),
|
|
219801
221754
|
description: string$2(),
|
|
@@ -220528,7 +222481,7 @@ var init_src$5 = __esmMin((() => {
|
|
|
220528
222481
|
init_pagination$1();
|
|
220529
222482
|
init_time();
|
|
220530
222483
|
init_request_id$2();
|
|
220531
|
-
init_events$
|
|
222484
|
+
init_events$7();
|
|
220532
222485
|
init_display$1();
|
|
220533
222486
|
init_ws_control$1();
|
|
220534
222487
|
init_asyncapi$1();
|
|
@@ -220567,7 +222520,7 @@ var init_src$5 = __esmMin((() => {
|
|
|
220567
222520
|
}));
|
|
220568
222521
|
//#endregion
|
|
220569
222522
|
//#region ../../packages/node-sdk/src/events.ts
|
|
220570
|
-
var init_events$
|
|
222523
|
+
var init_events$6 = __esmMin((() => {
|
|
220571
222524
|
init_src$5();
|
|
220572
222525
|
}));
|
|
220573
222526
|
//#endregion
|
|
@@ -220622,7 +222575,7 @@ var MAIN_AGENT_ID$6, Session;
|
|
|
220622
222575
|
var init_session$3 = __esmMin((() => {
|
|
220623
222576
|
init_src$6();
|
|
220624
222577
|
init_errors$3();
|
|
220625
|
-
init_events$
|
|
222578
|
+
init_events$6();
|
|
220626
222579
|
MAIN_AGENT_ID$6 = "main";
|
|
220627
222580
|
Session = class {
|
|
220628
222581
|
id;
|
|
@@ -221651,7 +223604,7 @@ var init_helpers = __esmMin((() => {
|
|
|
221651
223604
|
removed: array$2(string$2()),
|
|
221652
223605
|
changed: array$2(string$2())
|
|
221653
223606
|
});
|
|
221654
|
-
})), textPartSchema, imageUrlPartSchema, videoUrlPartSchema, promptPartSchema, emptyPayloadSchema, promptPayloadSchema, steerPayloadSchema, promptLaunchResultSchema, cancelPayloadSchema, runShellCommandPayloadSchema, shellCommandResultSchema, setModelResultSchema, permissionModeSchema$1, setPermissionPayloadSchema, tokenUsageSchema$1, usageStatusSchema$1, agentContextDataSchema, planDataSchema, taskLifecycleStatusSchema$1, taskInfoBaseFields, agentTaskInfoSchema$1, agentRpcContract;
|
|
223607
|
+
})), textPartSchema, imageUrlPartSchema, videoUrlPartSchema, promptPartSchema, emptyPayloadSchema, promptPayloadSchema, steerPayloadSchema, promptLaunchResultSchema, cancelPayloadSchema, runShellCommandPayloadSchema, shellCommandResultSchema$1, setModelResultSchema, permissionModeSchema$1, setPermissionPayloadSchema, tokenUsageSchema$1, usageStatusSchema$1, agentContextDataSchema, planDataSchema, taskLifecycleStatusSchema$1, taskInfoBaseFields, agentTaskInfoSchema$1, agentRpcContract;
|
|
221655
223608
|
var init_rpc$1 = __esmMin((() => {
|
|
221656
223609
|
init_zod$1();
|
|
221657
223610
|
init_helpers();
|
|
@@ -221690,7 +223643,7 @@ var init_rpc$1 = __esmMin((() => {
|
|
|
221690
223643
|
command: string$2(),
|
|
221691
223644
|
commandId: string$2().optional()
|
|
221692
223645
|
});
|
|
221693
|
-
shellCommandResultSchema = object({
|
|
223646
|
+
shellCommandResultSchema$1 = object({
|
|
221694
223647
|
stdout: string$2(),
|
|
221695
223648
|
stderr: string$2(),
|
|
221696
223649
|
isError: boolean$2().optional(),
|
|
@@ -221822,7 +223775,7 @@ var init_services = __esmMin((() => {
|
|
|
221822
223775
|
agentShellCommandContract = {
|
|
221823
223776
|
run: {
|
|
221824
223777
|
input: tuple([runShellCommandPayloadSchema]),
|
|
221825
|
-
output: shellCommandResultSchema
|
|
223778
|
+
output: shellCommandResultSchema$1
|
|
221826
223779
|
},
|
|
221827
223780
|
cancel: {
|
|
221828
223781
|
input: tuple([string$2()]),
|
|
@@ -222766,7 +224719,7 @@ var init_contract$1 = __esmMin((() => {
|
|
|
222766
224719
|
//#endregion
|
|
222767
224720
|
//#region ../../packages/klient/src/contract/global/events.ts
|
|
222768
224721
|
var configChangedSchema, reloadSummarySchema, sessionMetaUpdatedSchema, globalEvents;
|
|
222769
|
-
var init_events$
|
|
224722
|
+
var init_events$5 = __esmMin((() => {
|
|
222770
224723
|
init_zod$1();
|
|
222771
224724
|
configChangedSchema = object({
|
|
222772
224725
|
domain: string$2(),
|
|
@@ -222830,7 +224783,7 @@ var init_events$4 = __esmMin((() => {
|
|
|
222830
224783
|
//#endregion
|
|
222831
224784
|
//#region ../../packages/klient/src/contract/session/events.ts
|
|
222832
224785
|
var sessionEvents;
|
|
222833
|
-
var init_events$
|
|
224786
|
+
var init_events$4 = __esmMin((() => {
|
|
222834
224787
|
init_zod$1();
|
|
222835
224788
|
init_interaction$1();
|
|
222836
224789
|
init_metadata();
|
|
@@ -222856,7 +224809,7 @@ var init_events$3 = __esmMin((() => {
|
|
|
222856
224809
|
//#endregion
|
|
222857
224810
|
//#region ../../packages/klient/src/contract/agent/events.ts
|
|
222858
224811
|
var turnStartedEventSchema$1, turnEndedEventSchema$1, assistantDeltaEventSchema$1, thinkingDeltaEventSchema$1, toolCallStartedEventSchema$1, toolResultEventSchema$1, promptCompletedEventSchema$1, promptAbortedEventSchema$1, permissionApprovalRequestedEventSchema, permissionApprovalResolvedEventSchema, errorEventSchema$1, warningEventSchema$1, agentStatusUpdatedEventSchema$1, agentEvents;
|
|
222859
|
-
var init_events$
|
|
224812
|
+
var init_events$3 = __esmMin((() => {
|
|
222860
224813
|
init_zod$1();
|
|
222861
224814
|
turnStartedEventSchema$1 = object({
|
|
222862
224815
|
type: literal("turn.started"),
|
|
@@ -223490,9 +225443,9 @@ function createKlientFromChannel(channel, options = {}) {
|
|
|
223490
225443
|
}
|
|
223491
225444
|
var init_klient = __esmMin((() => {
|
|
223492
225445
|
init_contract$1();
|
|
225446
|
+
init_events$5();
|
|
223493
225447
|
init_events$4();
|
|
223494
225448
|
init_events$3();
|
|
223495
|
-
init_events$2();
|
|
223496
225449
|
init_hub();
|
|
223497
225450
|
init_global();
|
|
223498
225451
|
init_session$2();
|
|
@@ -225918,7 +227871,7 @@ var init_src$4 = __esmMin((() => {
|
|
|
225918
227871
|
init_errors$3();
|
|
225919
227872
|
init_logging();
|
|
225920
227873
|
init_src$6();
|
|
225921
|
-
init_events$
|
|
227874
|
+
init_events$6();
|
|
225922
227875
|
}));
|
|
225923
227876
|
//#endregion
|
|
225924
227877
|
//#region ../../packages/telemetry/src/index.ts
|
|
@@ -232170,7 +234123,7 @@ var init_schema$1 = __esmMin((() => {
|
|
|
232170
234123
|
seq: transcriptSeqSchema.optional()
|
|
232171
234124
|
});
|
|
232172
234125
|
})), transcriptResetEventSchema, transcriptOpsEventSchema;
|
|
232173
|
-
var init_events$
|
|
234126
|
+
var init_events$2 = __esmMin((() => {
|
|
232174
234127
|
init_zod$1();
|
|
232175
234128
|
init_schema$1();
|
|
232176
234129
|
transcriptResetEventSchema = transcriptResetPayloadSchema.extend({ type: literal("transcript.reset") });
|
|
@@ -232201,7 +234154,7 @@ var init_src$2 = __esmMin((() => {
|
|
|
232201
234154
|
init_groupTurns();
|
|
232202
234155
|
init_foldFacts();
|
|
232203
234156
|
init_schema$1();
|
|
232204
|
-
init_events$
|
|
234157
|
+
init_events$2();
|
|
232205
234158
|
}));
|
|
232206
234159
|
//#endregion
|
|
232207
234160
|
//#region ../../packages/agent-core-v2/src/agent/contextMemory/protocolMessage.ts
|
|
@@ -259004,7 +260957,7 @@ function isVolatileEventType(type) {
|
|
|
259004
260957
|
return volatileEventTypeSet.has(type);
|
|
259005
260958
|
}
|
|
259006
260959
|
var VOLATILE_EVENT_TYPES, volatileEventTypeSet;
|
|
259007
|
-
var init_events = __esmMin((() => {
|
|
260960
|
+
var init_events$1 = __esmMin((() => {
|
|
259008
260961
|
VOLATILE_EVENT_TYPES = [
|
|
259009
260962
|
"assistant.delta",
|
|
259010
260963
|
"thinking.delta",
|
|
@@ -259242,11 +261195,11 @@ function registerApprovalsRoutes(app, core) {
|
|
|
259242
261195
|
const listRoute = defineRoute({
|
|
259243
261196
|
method: "GET",
|
|
259244
261197
|
path: "/sessions/{session_id}/approvals",
|
|
259245
|
-
params: sessionIdParamSchema$
|
|
261198
|
+
params: sessionIdParamSchema$10,
|
|
259246
261199
|
querystring: listPendingApprovalsQuerySchema,
|
|
259247
261200
|
success: { data: listPendingApprovalsResponseSchema },
|
|
259248
261201
|
errors: {
|
|
259249
|
-
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$
|
|
261202
|
+
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$8 },
|
|
259250
261203
|
[ErrorCode.SESSION_NOT_FOUND]: {}
|
|
259251
261204
|
},
|
|
259252
261205
|
description: "List pending approval requests for a session",
|
|
@@ -259269,7 +261222,7 @@ function registerApprovalsRoutes(app, core) {
|
|
|
259269
261222
|
body: approvalResolveRequestSchema,
|
|
259270
261223
|
success: { data: approvalResolveResultSchema },
|
|
259271
261224
|
errors: {
|
|
259272
|
-
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$
|
|
261225
|
+
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$8 },
|
|
259273
261226
|
[ErrorCode.SESSION_NOT_FOUND]: {},
|
|
259274
261227
|
[ErrorCode.APPROVAL_NOT_FOUND]: {},
|
|
259275
261228
|
[ErrorCode.APPROVAL_ALREADY_RESOLVED]: { dataSchema: approvalAlreadyResolvedDataSchema }
|
|
@@ -259332,7 +261285,7 @@ function toWireApproval(interaction, sessionId) {
|
|
|
259332
261285
|
expires_at: new Date(interaction.createdAt + APPROVAL_EXPIRY_MS).toISOString()
|
|
259333
261286
|
};
|
|
259334
261287
|
}
|
|
259335
|
-
var sessionIdParamSchema$
|
|
261288
|
+
var sessionIdParamSchema$10, approvalParamsSchema, detailsSchema$8, APPROVAL_EXPIRY_MS;
|
|
259336
261289
|
var init_approvals = __esmMin((() => {
|
|
259337
261290
|
init_src$6();
|
|
259338
261291
|
init_error_codes();
|
|
@@ -259341,12 +261294,12 @@ var init_approvals = __esmMin((() => {
|
|
|
259341
261294
|
init_envelope();
|
|
259342
261295
|
init_requestLog();
|
|
259343
261296
|
init_defineRoute();
|
|
259344
|
-
sessionIdParamSchema$
|
|
261297
|
+
sessionIdParamSchema$10 = object({ session_id: string$2().min(1) });
|
|
259345
261298
|
approvalParamsSchema = object({
|
|
259346
261299
|
session_id: string$2().min(1),
|
|
259347
261300
|
approval_id: string$2().min(1)
|
|
259348
261301
|
});
|
|
259349
|
-
detailsSchema$
|
|
261302
|
+
detailsSchema$8 = array$2(object({
|
|
259350
261303
|
path: string$2(),
|
|
259351
261304
|
message: string$2()
|
|
259352
261305
|
}));
|
|
@@ -259405,11 +261358,11 @@ function registerQuestionsRoutes(app, core) {
|
|
|
259405
261358
|
const listRoute = defineRoute({
|
|
259406
261359
|
method: "GET",
|
|
259407
261360
|
path: "/sessions/{session_id}/questions",
|
|
259408
|
-
params: sessionIdParamSchema$
|
|
261361
|
+
params: sessionIdParamSchema$9,
|
|
259409
261362
|
querystring: listPendingQuestionsQuerySchema,
|
|
259410
261363
|
success: { data: listPendingQuestionsResponseSchema },
|
|
259411
261364
|
errors: {
|
|
259412
|
-
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$
|
|
261365
|
+
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$7 },
|
|
259413
261366
|
[ErrorCode.SESSION_NOT_FOUND]: {}
|
|
259414
261367
|
},
|
|
259415
261368
|
description: "List pending question requests for a session",
|
|
@@ -259431,7 +261384,7 @@ function registerQuestionsRoutes(app, core) {
|
|
|
259431
261384
|
params: tailParamsSchema,
|
|
259432
261385
|
success: { data: questionResolveResultSchema },
|
|
259433
261386
|
errors: {
|
|
259434
|
-
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$
|
|
261387
|
+
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$7 },
|
|
259435
261388
|
[ErrorCode.SESSION_NOT_FOUND]: {},
|
|
259436
261389
|
[ErrorCode.QUESTION_NOT_FOUND]: {},
|
|
259437
261390
|
[ErrorCode.APPROVAL_ALREADY_RESOLVED]: { dataSchema: questionAlreadyResolvedDataSchema },
|
|
@@ -259615,7 +261568,7 @@ function toInProcessResponse(resp, request) {
|
|
|
259615
261568
|
if (resp.method !== void 0 && resp.method !== "click") out.method = resp.method;
|
|
259616
261569
|
return out;
|
|
259617
261570
|
}
|
|
259618
|
-
var sessionIdParamSchema$
|
|
261571
|
+
var sessionIdParamSchema$9, tailParamsSchema, detailsSchema$7;
|
|
259619
261572
|
var init_questions = __esmMin((() => {
|
|
259620
261573
|
init_src$6();
|
|
259621
261574
|
init_error_codes();
|
|
@@ -259626,12 +261579,12 @@ var init_questions = __esmMin((() => {
|
|
|
259626
261579
|
init_requestLog();
|
|
259627
261580
|
init_defineRoute();
|
|
259628
261581
|
init_action_suffix();
|
|
259629
|
-
sessionIdParamSchema$
|
|
261582
|
+
sessionIdParamSchema$9 = object({ session_id: string$2().min(1) });
|
|
259630
261583
|
tailParamsSchema = object({
|
|
259631
261584
|
session_id: string$2().min(1),
|
|
259632
261585
|
tail: string$2().min(1)
|
|
259633
261586
|
});
|
|
259634
|
-
detailsSchema$
|
|
261587
|
+
detailsSchema$7 = array$2(object({
|
|
259635
261588
|
path: string$2(),
|
|
259636
261589
|
message: string$2()
|
|
259637
261590
|
}));
|
|
@@ -260309,7 +262262,7 @@ function sessionCreatedPayload(payload) {
|
|
|
260309
262262
|
var GLOBAL_SESSION_ID, TRANSCRIPT_RESET_TAIL_TURNS, SessionEventBroadcaster, volatileSignalTypeSet, TRANSCRIPT_PROJECTED_EVENT_TYPES;
|
|
260310
262263
|
var init_sessionEventBroadcaster = __esmMin((() => {
|
|
260311
262264
|
init_src$6();
|
|
260312
|
-
init_events();
|
|
262265
|
+
init_events$1();
|
|
260313
262266
|
init_src$2();
|
|
260314
262267
|
init_approvals();
|
|
260315
262268
|
init_questions();
|
|
@@ -264859,11 +266812,11 @@ function registerMessagesRoutes(app, core) {
|
|
|
264859
266812
|
const listRoute = defineRoute({
|
|
264860
266813
|
method: "GET",
|
|
264861
266814
|
path: "/sessions/{session_id}/messages",
|
|
264862
|
-
params: sessionIdParamSchema$
|
|
266815
|
+
params: sessionIdParamSchema$8,
|
|
264863
266816
|
querystring: messagesListQueryCoercion,
|
|
264864
266817
|
success: { data: listMessagesResponseSchema },
|
|
264865
266818
|
errors: {
|
|
264866
|
-
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$
|
|
266819
|
+
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$6 },
|
|
264867
266820
|
[ErrorCode.SESSION_NOT_FOUND]: {}
|
|
264868
266821
|
},
|
|
264869
266822
|
description: "List messages for a session",
|
|
@@ -264884,7 +266837,7 @@ function registerMessagesRoutes(app, core) {
|
|
|
264884
266837
|
params: messageIdParamSchema,
|
|
264885
266838
|
success: { data: getMessageResponseSchema },
|
|
264886
266839
|
errors: {
|
|
264887
|
-
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$
|
|
266840
|
+
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$6 },
|
|
264888
266841
|
[ErrorCode.SESSION_NOT_FOUND]: {},
|
|
264889
266842
|
[ErrorCode.MESSAGE_NOT_FOUND]: {}
|
|
264890
266843
|
},
|
|
@@ -264921,7 +266874,7 @@ function sendMappedError$7(reply, req, err) {
|
|
|
264921
266874
|
log?.error({ err }, "message request failed");
|
|
264922
266875
|
reply.send(errEnvelope(ErrorCode.INTERNAL_ERROR, err instanceof Error ? err.message : String(err), requestId, err instanceof Error ? err.stack : void 0));
|
|
264923
266876
|
}
|
|
264924
|
-
var messagesListQueryCoercion, sessionIdParamSchema$
|
|
266877
|
+
var messagesListQueryCoercion, sessionIdParamSchema$8, messageIdParamSchema, detailsSchema$6;
|
|
264925
266878
|
var init_messages = __esmMin((() => {
|
|
264926
266879
|
init_src$6();
|
|
264927
266880
|
init_protocolMessage();
|
|
@@ -264945,12 +266898,12 @@ var init_messages = __esmMin((() => {
|
|
|
264945
266898
|
params: { code: ErrorCode.VALIDATION_FAILED }
|
|
264946
266899
|
});
|
|
264947
266900
|
});
|
|
264948
|
-
sessionIdParamSchema$
|
|
266901
|
+
sessionIdParamSchema$8 = object({ session_id: string$2().min(1) });
|
|
264949
266902
|
messageIdParamSchema = object({
|
|
264950
266903
|
session_id: string$2().min(1),
|
|
264951
266904
|
message_id: string$2().min(1)
|
|
264952
266905
|
});
|
|
264953
|
-
detailsSchema$
|
|
266906
|
+
detailsSchema$6 = array$2(object({
|
|
264954
266907
|
path: string$2(),
|
|
264955
266908
|
message: string$2()
|
|
264956
266909
|
}));
|
|
@@ -265303,6 +267256,107 @@ var init_registerDebugRoutes = __esmMin((() => {
|
|
|
265303
267256
|
init_serviceDispatcherRoutes();
|
|
265304
267257
|
}));
|
|
265305
267258
|
//#endregion
|
|
267259
|
+
//#region ../../packages/kap-server/src/routes/events.ts
|
|
267260
|
+
function registerEventsRoute(app, opts) {
|
|
267261
|
+
app.get("/sessions/:session_id/events", { schema: {
|
|
267262
|
+
params: {
|
|
267263
|
+
type: "object",
|
|
267264
|
+
properties: { session_id: { type: "string" } },
|
|
267265
|
+
required: ["session_id"]
|
|
267266
|
+
},
|
|
267267
|
+
querystring: {
|
|
267268
|
+
type: "object",
|
|
267269
|
+
properties: { event_seq: { type: "string" } },
|
|
267270
|
+
required: []
|
|
267271
|
+
}
|
|
267272
|
+
} }, async (req, reply) => {
|
|
267273
|
+
const { session_id } = req.params;
|
|
267274
|
+
if (!session_id) {
|
|
267275
|
+
await reply.code(400).send({
|
|
267276
|
+
code: 4e4,
|
|
267277
|
+
msg: "session_id required",
|
|
267278
|
+
data: null,
|
|
267279
|
+
request_id: req.id
|
|
267280
|
+
});
|
|
267281
|
+
return;
|
|
267282
|
+
}
|
|
267283
|
+
const eventSeq = parseEventSeq(req.query.event_seq);
|
|
267284
|
+
if (eventSeq !== void 0 && (!Number.isInteger(eventSeq) || eventSeq < 0)) {
|
|
267285
|
+
await reply.code(400).send({
|
|
267286
|
+
code: 4e4,
|
|
267287
|
+
msg: "event_seq must be a non-negative integer",
|
|
267288
|
+
data: null,
|
|
267289
|
+
request_id: req.id
|
|
267290
|
+
});
|
|
267291
|
+
return;
|
|
267292
|
+
}
|
|
267293
|
+
reply.hijack();
|
|
267294
|
+
const raw = reply.raw;
|
|
267295
|
+
raw.writeHead(200, SSE_HEADERS);
|
|
267296
|
+
raw.write(": connected\n\n");
|
|
267297
|
+
let closed = false;
|
|
267298
|
+
const target = { send(envelope) {
|
|
267299
|
+
if (closed) return;
|
|
267300
|
+
raw.write(`event: ${envelope.type}\ndata: ${JSON.stringify(envelope)}\n\n`);
|
|
267301
|
+
} };
|
|
267302
|
+
if (!await opts.broadcaster.subscribe(session_id, target)) {
|
|
267303
|
+
if (await opts.core.accessor.get(ISessionLifecycleService).resume(session_id) === void 0) {
|
|
267304
|
+
closed = true;
|
|
267305
|
+
raw.write("event: error\ndata: {\"code\":40401,\"msg\":\"session not found\"}\n\n");
|
|
267306
|
+
raw.end();
|
|
267307
|
+
return;
|
|
267308
|
+
}
|
|
267309
|
+
if (!await opts.broadcaster.subscribe(session_id, target)) {
|
|
267310
|
+
closed = true;
|
|
267311
|
+
raw.write("event: error\ndata: {\"code\":40401,\"msg\":\"session not found\"}\n\n");
|
|
267312
|
+
raw.end();
|
|
267313
|
+
return;
|
|
267314
|
+
}
|
|
267315
|
+
}
|
|
267316
|
+
if (eventSeq !== void 0) {
|
|
267317
|
+
const result = await opts.broadcaster.getBufferedSince(session_id, { seq: eventSeq });
|
|
267318
|
+
if (result.resyncRequired !== false) raw.write(`event: resync_required\ndata: ${JSON.stringify({
|
|
267319
|
+
type: "resync_required",
|
|
267320
|
+
session_id,
|
|
267321
|
+
reason: result.resyncRequired,
|
|
267322
|
+
current_seq: result.currentSeq,
|
|
267323
|
+
epoch: result.epoch
|
|
267324
|
+
})}\n\n`);
|
|
267325
|
+
else for (const { envelope } of result.events) target.send(envelope);
|
|
267326
|
+
}
|
|
267327
|
+
const heartbeat = setInterval(() => {
|
|
267328
|
+
if (!closed) raw.write(": ping\n\n");
|
|
267329
|
+
}, HEARTBEAT_INTERVAL_MS);
|
|
267330
|
+
req.raw.on("close", () => {
|
|
267331
|
+
closed = true;
|
|
267332
|
+
clearInterval(heartbeat);
|
|
267333
|
+
opts.broadcaster.unsubscribe(session_id, target);
|
|
267334
|
+
});
|
|
267335
|
+
});
|
|
267336
|
+
}
|
|
267337
|
+
/**
|
|
267338
|
+
* Parse the optional `?event_seq=` replay cursor. `undefined` = absent
|
|
267339
|
+
* (live-only stream); `NaN` = present but malformed — the caller rejects it
|
|
267340
|
+
* with a 400. A valid cursor is a non-negative integer (the journal seq
|
|
267341
|
+
* domain, matching `sessionCursorSchema.seq`).
|
|
267342
|
+
*/
|
|
267343
|
+
function parseEventSeq(raw) {
|
|
267344
|
+
if (raw === void 0) return void 0;
|
|
267345
|
+
if (typeof raw !== "string" || !/^\d+$/.test(raw)) return NaN;
|
|
267346
|
+
return Number(raw);
|
|
267347
|
+
}
|
|
267348
|
+
var SSE_HEADERS, HEARTBEAT_INTERVAL_MS;
|
|
267349
|
+
var init_events = __esmMin((() => {
|
|
267350
|
+
init_src$6();
|
|
267351
|
+
SSE_HEADERS = {
|
|
267352
|
+
"Content-Type": "text/event-stream",
|
|
267353
|
+
"Cache-Control": "no-cache",
|
|
267354
|
+
Connection: "keep-alive",
|
|
267355
|
+
"X-Accel-Buffering": "no"
|
|
267356
|
+
};
|
|
267357
|
+
HEARTBEAT_INTERVAL_MS = 15e3;
|
|
267358
|
+
}));
|
|
267359
|
+
//#endregion
|
|
265306
267360
|
//#region ../../packages/kap-server/src/protocol/rest-meta.ts
|
|
265307
267361
|
var metaCapabilitiesSchema, metaResponseSchema;
|
|
265308
267362
|
var init_rest_meta = __esmMin((() => {
|
|
@@ -265908,7 +267962,7 @@ function registerPromptsRoutes(app, core) {
|
|
|
265908
267962
|
const listRoute = defineRoute({
|
|
265909
267963
|
method: "GET",
|
|
265910
267964
|
path: "/sessions/{session_id}/prompts",
|
|
265911
|
-
params: sessionIdParamSchema$
|
|
267965
|
+
params: sessionIdParamSchema$7,
|
|
265912
267966
|
success: { data: promptListResponseSchema },
|
|
265913
267967
|
errors: { [ErrorCode.SESSION_NOT_FOUND]: {} },
|
|
265914
267968
|
description: "List the active prompt and queued prompts for a session",
|
|
@@ -265928,7 +267982,7 @@ function registerPromptsRoutes(app, core) {
|
|
|
265928
267982
|
method: "POST",
|
|
265929
267983
|
path: "/sessions/{session_id}/prompts",
|
|
265930
267984
|
body: promptSubmissionSchema,
|
|
265931
|
-
params: sessionIdParamSchema$
|
|
267985
|
+
params: sessionIdParamSchema$7,
|
|
265932
267986
|
success: { data: promptSubmitResultSchema },
|
|
265933
267987
|
errors: {
|
|
265934
267988
|
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: validationDetailsSchema },
|
|
@@ -265994,7 +268048,7 @@ function registerPromptsRoutes(app, core) {
|
|
|
265994
268048
|
method: "POST",
|
|
265995
268049
|
path: "/sessions/{session_id}/prompts::steer",
|
|
265996
268050
|
body: promptSteerRequestSchema,
|
|
265997
|
-
params: sessionIdParamSchema$
|
|
268051
|
+
params: sessionIdParamSchema$7,
|
|
265998
268052
|
success: { data: promptSteerResultSchema },
|
|
265999
268053
|
errors: {
|
|
266000
268054
|
[ErrorCode.VALIDATION_FAILED]: {},
|
|
@@ -266486,7 +268540,7 @@ function authModelDetails(err) {
|
|
|
266486
268540
|
if (typeof providerId === "string") details.provider_id = providerId;
|
|
266487
268541
|
return Object.keys(details).length === 0 ? null : details;
|
|
266488
268542
|
}
|
|
266489
|
-
var sessionIdParamSchema$
|
|
268543
|
+
var sessionIdParamSchema$7, validationDetailsSchema, authProviderDetailsSchema, authModelDetailsSchema, VIDEO_EXT_BY_MIME, ATTACHMENT_NAME_MAX;
|
|
266490
268544
|
var init_prompts$1 = __esmMin((() => {
|
|
266491
268545
|
init_src$6();
|
|
266492
268546
|
init_error_codes();
|
|
@@ -266497,7 +268551,7 @@ var init_prompts$1 = __esmMin((() => {
|
|
|
266497
268551
|
init_defineRoute();
|
|
266498
268552
|
init_mainAgent();
|
|
266499
268553
|
init_action_suffix();
|
|
266500
|
-
sessionIdParamSchema$
|
|
268554
|
+
sessionIdParamSchema$7 = object({ session_id: string$2().min(1) });
|
|
266501
268555
|
validationDetailsSchema = array$2(object({
|
|
266502
268556
|
path: string$2(),
|
|
266503
268557
|
message: string$2()
|
|
@@ -266779,7 +268833,7 @@ function registerSessionsRoutes(app, core) {
|
|
|
266779
268833
|
body: createSessionRequestSchema,
|
|
266780
268834
|
success: { data: sessionSchema },
|
|
266781
268835
|
errors: {
|
|
266782
|
-
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$
|
|
268836
|
+
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$5 },
|
|
266783
268837
|
[ErrorCode.WORKSPACE_NOT_FOUND]: {},
|
|
266784
268838
|
[ErrorCode.FS_PATH_NOT_FOUND]: {}
|
|
266785
268839
|
},
|
|
@@ -266817,6 +268871,7 @@ function registerSessionsRoutes(app, core) {
|
|
|
266817
268871
|
const touched = await registry.createOrTouch(workDir);
|
|
266818
268872
|
const handle = await core.accessor.get(ISessionLifecycleService).create({ workDir });
|
|
266819
268873
|
if (typeof body.title === "string") await handle.accessor.get(ISessionMetadata).setTitle(body.title);
|
|
268874
|
+
if (body.metadata !== void 0 && Object.keys(body.metadata).length > 0) await handle.accessor.get(ISessionMetadata).update({ custom: { ...body.metadata } });
|
|
266820
268875
|
const session = toWireSession({
|
|
266821
268876
|
...await handle.accessor.get(ISessionMetadata).read(),
|
|
266822
268877
|
workspaceId: touched.id
|
|
@@ -266845,7 +268900,7 @@ function registerSessionsRoutes(app, core) {
|
|
|
266845
268900
|
querystring: sessionsListQueryCoercion,
|
|
266846
268901
|
success: { data: pageResponseSchema(sessionSchema) },
|
|
266847
268902
|
errors: {
|
|
266848
|
-
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$
|
|
268903
|
+
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$5 },
|
|
266849
268904
|
[ErrorCode.WORKSPACE_NOT_FOUND]: {}
|
|
266850
268905
|
},
|
|
266851
268906
|
description: "List sessions",
|
|
@@ -266913,10 +268968,10 @@ function registerSessionsRoutes(app, core) {
|
|
|
266913
268968
|
const getRoute = defineRoute({
|
|
266914
268969
|
method: "GET",
|
|
266915
268970
|
path: "/sessions/{session_id}",
|
|
266916
|
-
params: sessionIdParamSchema$
|
|
268971
|
+
params: sessionIdParamSchema$6,
|
|
266917
268972
|
success: { data: sessionSchema },
|
|
266918
268973
|
errors: {
|
|
266919
|
-
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$
|
|
268974
|
+
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$5 },
|
|
266920
268975
|
[ErrorCode.SESSION_NOT_FOUND]: {}
|
|
266921
268976
|
},
|
|
266922
268977
|
description: "Get a session by ID",
|
|
@@ -266939,10 +268994,10 @@ function registerSessionsRoutes(app, core) {
|
|
|
266939
268994
|
const getProfileRoute = defineRoute({
|
|
266940
268995
|
method: "GET",
|
|
266941
268996
|
path: "/sessions/{session_id}/profile",
|
|
266942
|
-
params: sessionIdParamSchema$
|
|
268997
|
+
params: sessionIdParamSchema$6,
|
|
266943
268998
|
success: { data: sessionSchema },
|
|
266944
268999
|
errors: {
|
|
266945
|
-
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$
|
|
269000
|
+
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$5 },
|
|
266946
269001
|
[ErrorCode.SESSION_NOT_FOUND]: {}
|
|
266947
269002
|
},
|
|
266948
269003
|
description: "Get session profile",
|
|
@@ -266965,11 +269020,11 @@ function registerSessionsRoutes(app, core) {
|
|
|
266965
269020
|
const updateProfileRoute = defineRoute({
|
|
266966
269021
|
method: "POST",
|
|
266967
269022
|
path: "/sessions/{session_id}/profile",
|
|
266968
|
-
params: sessionIdParamSchema$
|
|
269023
|
+
params: sessionIdParamSchema$6,
|
|
266969
269024
|
body: updateSessionProfileRequestSchema,
|
|
266970
269025
|
success: { data: sessionSchema },
|
|
266971
269026
|
errors: {
|
|
266972
|
-
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$
|
|
269027
|
+
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$5 },
|
|
266973
269028
|
[ErrorCode.SESSION_NOT_FOUND]: {}
|
|
266974
269029
|
},
|
|
266975
269030
|
description: "Update session profile (title, metadata, agent_config)",
|
|
@@ -267011,7 +269066,7 @@ function registerSessionsRoutes(app, core) {
|
|
|
267011
269066
|
archiveSessionResponseSchema
|
|
267012
269067
|
]) },
|
|
267013
269068
|
errors: {
|
|
267014
|
-
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$
|
|
269069
|
+
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$5 },
|
|
267015
269070
|
[ErrorCode.SESSION_NOT_FOUND]: {},
|
|
267016
269071
|
[ErrorCode.SESSION_BUSY]: {},
|
|
267017
269072
|
[ErrorCode.COMPACTION_UNABLE]: {},
|
|
@@ -267150,11 +269205,11 @@ function registerSessionsRoutes(app, core) {
|
|
|
267150
269205
|
const listChildrenRoute = defineRoute({
|
|
267151
269206
|
method: "GET",
|
|
267152
269207
|
path: "/sessions/{session_id}/children",
|
|
267153
|
-
params: sessionIdParamSchema$
|
|
269208
|
+
params: sessionIdParamSchema$6,
|
|
267154
269209
|
querystring: sessionChildrenListQueryCoercion,
|
|
267155
269210
|
success: { data: listSessionChildrenResponseSchema },
|
|
267156
269211
|
errors: {
|
|
267157
|
-
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$
|
|
269212
|
+
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$5 },
|
|
267158
269213
|
[ErrorCode.SESSION_NOT_FOUND]: {}
|
|
267159
269214
|
},
|
|
267160
269215
|
description: "List child sessions",
|
|
@@ -267188,11 +269243,11 @@ function registerSessionsRoutes(app, core) {
|
|
|
267188
269243
|
const createChildRoute = defineRoute({
|
|
267189
269244
|
method: "POST",
|
|
267190
269245
|
path: "/sessions/{session_id}/children",
|
|
267191
|
-
params: sessionIdParamSchema$
|
|
269246
|
+
params: sessionIdParamSchema$6,
|
|
267192
269247
|
body: createSessionChildRequestSchema,
|
|
267193
269248
|
success: { data: sessionSchema },
|
|
267194
269249
|
errors: {
|
|
267195
|
-
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$
|
|
269250
|
+
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$5 },
|
|
267196
269251
|
[ErrorCode.SESSION_NOT_FOUND]: {},
|
|
267197
269252
|
[ErrorCode.SESSION_BUSY]: {}
|
|
267198
269253
|
},
|
|
@@ -267229,10 +269284,10 @@ function registerSessionsRoutes(app, core) {
|
|
|
267229
269284
|
const statusRoute = defineRoute({
|
|
267230
269285
|
method: "GET",
|
|
267231
269286
|
path: "/sessions/{session_id}/status",
|
|
267232
|
-
params: sessionIdParamSchema$
|
|
269287
|
+
params: sessionIdParamSchema$6,
|
|
267233
269288
|
success: { data: sessionStatusResponseSchema },
|
|
267234
269289
|
errors: {
|
|
267235
|
-
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$
|
|
269290
|
+
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$5 },
|
|
267236
269291
|
[ErrorCode.SESSION_NOT_FOUND]: {}
|
|
267237
269292
|
},
|
|
267238
269293
|
description: "Get realtime session status (best-effort in this slice)",
|
|
@@ -267250,10 +269305,10 @@ function registerSessionsRoutes(app, core) {
|
|
|
267250
269305
|
const sessionWarningsRoute = defineRoute({
|
|
267251
269306
|
method: "GET",
|
|
267252
269307
|
path: "/sessions/{session_id}/warnings",
|
|
267253
|
-
params: sessionIdParamSchema$
|
|
269308
|
+
params: sessionIdParamSchema$6,
|
|
267254
269309
|
success: { data: sessionWarningsResponseSchema },
|
|
267255
269310
|
errors: {
|
|
267256
|
-
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$
|
|
269311
|
+
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$5 },
|
|
267257
269312
|
[ErrorCode.SESSION_NOT_FOUND]: {}
|
|
267258
269313
|
},
|
|
267259
269314
|
description: "Get session-level warnings (e.g. oversized AGENTS.md)",
|
|
@@ -267409,7 +269464,7 @@ function sendMappedError$4(reply, req, err) {
|
|
|
267409
269464
|
log?.error({ err }, "session request failed");
|
|
267410
269465
|
reply.send(errEnvelope(ErrorCode.INTERNAL_ERROR, err instanceof Error ? err.message : String(err), requestId, err instanceof Error ? err.stack : void 0));
|
|
267411
269466
|
}
|
|
267412
|
-
var booleanQueryParam, DEFAULT_SESSION_LIST_PAGE_SIZE, sessionsListQueryCoercion, sessionIdParamSchema$
|
|
269467
|
+
var booleanQueryParam, DEFAULT_SESSION_LIST_PAGE_SIZE, sessionsListQueryCoercion, sessionIdParamSchema$6, sessionChildrenListQueryCoercion, sessionActionTailParamSchema, sessionActionRequestSchema, detailsSchema$5, DEFAULT_UNDO_MESSAGE_PAGE_SIZE, MAX_UNDO_MESSAGE_PAGE_SIZE;
|
|
267413
269468
|
var init_sessions = __esmMin((() => {
|
|
267414
269469
|
init_src$6();
|
|
267415
269470
|
init_error_codes();
|
|
@@ -267453,7 +269508,7 @@ var init_sessions = __esmMin((() => {
|
|
|
267453
269508
|
params: { code: ErrorCode.VALIDATION_FAILED }
|
|
267454
269509
|
});
|
|
267455
269510
|
});
|
|
267456
|
-
sessionIdParamSchema$
|
|
269511
|
+
sessionIdParamSchema$6 = object({ session_id: string$2().min(1) });
|
|
267457
269512
|
sessionChildrenListQueryCoercion = object({
|
|
267458
269513
|
before_id: string$2().min(1).optional(),
|
|
267459
269514
|
after_id: string$2().min(1).optional(),
|
|
@@ -267475,7 +269530,7 @@ var init_sessions = __esmMin((() => {
|
|
|
267475
269530
|
count: number$2().int().positive().optional(),
|
|
267476
269531
|
page_size: number$2().int().min(1).max(100).optional()
|
|
267477
269532
|
}));
|
|
267478
|
-
detailsSchema$
|
|
269533
|
+
detailsSchema$5 = array$2(object({
|
|
267479
269534
|
path: string$2(),
|
|
267480
269535
|
message: string$2()
|
|
267481
269536
|
}));
|
|
@@ -267483,6 +269538,60 @@ var init_sessions = __esmMin((() => {
|
|
|
267483
269538
|
MAX_UNDO_MESSAGE_PAGE_SIZE = 100;
|
|
267484
269539
|
}));
|
|
267485
269540
|
//#endregion
|
|
269541
|
+
//#region ../../packages/kap-server/src/routes/shell.ts
|
|
269542
|
+
function registerShellRoute(app, core) {
|
|
269543
|
+
const runShellCommandRoute = defineRoute({
|
|
269544
|
+
method: "POST",
|
|
269545
|
+
path: "/sessions/{session_id}/shell",
|
|
269546
|
+
params: sessionIdParamSchema$5,
|
|
269547
|
+
body: shellCommandRequestSchema,
|
|
269548
|
+
success: { data: shellCommandResultSchema },
|
|
269549
|
+
errors: {
|
|
269550
|
+
[ErrorCode.VALIDATION_FAILED]: { detailsSchema: detailsSchema$4 },
|
|
269551
|
+
[ErrorCode.SESSION_NOT_FOUND]: {}
|
|
269552
|
+
},
|
|
269553
|
+
description: "Run a user-initiated `!` shell command in a session",
|
|
269554
|
+
tags: ["sessions"]
|
|
269555
|
+
}, async (req, reply) => {
|
|
269556
|
+
const { session_id } = req.params;
|
|
269557
|
+
const session = await core.accessor.get(ISessionLifecycleService).resume(session_id);
|
|
269558
|
+
if (session === void 0) {
|
|
269559
|
+
reply.send(errEnvelope(ErrorCode.SESSION_NOT_FOUND, `session ${session_id} does not exist`, req.id));
|
|
269560
|
+
return;
|
|
269561
|
+
}
|
|
269562
|
+
const result = await (await ensureMainAgent(session)).accessor.get(IAgentShellCommandService).run({
|
|
269563
|
+
command: req.body.command,
|
|
269564
|
+
commandId: req.body.commandId
|
|
269565
|
+
});
|
|
269566
|
+
reply.send(okEnvelope(result, req.id));
|
|
269567
|
+
});
|
|
269568
|
+
app.post(runShellCommandRoute.path, runShellCommandRoute.options, runShellCommandRoute.handler);
|
|
269569
|
+
}
|
|
269570
|
+
var sessionIdParamSchema$5, shellCommandRequestSchema, shellCommandResultSchema, detailsSchema$4;
|
|
269571
|
+
var init_shell = __esmMin((() => {
|
|
269572
|
+
init_src$6();
|
|
269573
|
+
init_zod$1();
|
|
269574
|
+
init_envelope();
|
|
269575
|
+
init_defineRoute();
|
|
269576
|
+
init_error_codes();
|
|
269577
|
+
init_mainAgent();
|
|
269578
|
+
sessionIdParamSchema$5 = object({ session_id: string$2().min(1) });
|
|
269579
|
+
shellCommandRequestSchema = object({
|
|
269580
|
+
command: string$2(),
|
|
269581
|
+
commandId: string$2().optional()
|
|
269582
|
+
});
|
|
269583
|
+
shellCommandResultSchema = object({
|
|
269584
|
+
stdout: string$2(),
|
|
269585
|
+
stderr: string$2(),
|
|
269586
|
+
isError: boolean$2().optional(),
|
|
269587
|
+
backgrounded: boolean$2().optional()
|
|
269588
|
+
});
|
|
269589
|
+
detailsSchema$4 = array$2(object({
|
|
269590
|
+
path: string$2(),
|
|
269591
|
+
message: string$2()
|
|
269592
|
+
}));
|
|
269593
|
+
}));
|
|
269594
|
+
//#endregion
|
|
267486
269595
|
//#region ../../packages/kap-server/src/routes/shutdown.ts
|
|
267487
269596
|
function registerShutdownRoutes(app, opts) {
|
|
267488
269597
|
const route = defineRoute({
|
|
@@ -269718,6 +271827,11 @@ async function registerApiV1Routes(app, core, opts) {
|
|
|
269718
271827
|
registerConfigRoutes(apiV1, core);
|
|
269719
271828
|
registerModelCatalogRoutes(apiV1, core);
|
|
269720
271829
|
registerSessionsRoutes(apiV1, core);
|
|
271830
|
+
registerShellRoute(apiV1, core);
|
|
271831
|
+
registerEventsRoute(apiV1, {
|
|
271832
|
+
broadcaster: opts.broadcaster,
|
|
271833
|
+
core
|
|
271834
|
+
});
|
|
269721
271835
|
registerSessionExportRoute(apiV1, core, { serverVersion: opts.serverVersion });
|
|
269722
271836
|
registerSkillsRoutes(apiV1, core);
|
|
269723
271837
|
registerMessagesRoutes(apiV1, core);
|
|
@@ -269776,6 +271890,7 @@ var init_registerApiV1Routes = __esmMin((() => {
|
|
|
269776
271890
|
init_guiStore();
|
|
269777
271891
|
init_messages();
|
|
269778
271892
|
init_registerDebugRoutes();
|
|
271893
|
+
init_events();
|
|
269779
271894
|
init_meta();
|
|
269780
271895
|
init_modelCatalog();
|
|
269781
271896
|
init_oauth();
|
|
@@ -269783,6 +271898,7 @@ var init_registerApiV1Routes = __esmMin((() => {
|
|
|
269783
271898
|
init_questions();
|
|
269784
271899
|
init_sessionExport();
|
|
269785
271900
|
init_sessions();
|
|
271901
|
+
init_shell();
|
|
269786
271902
|
init_shutdown();
|
|
269787
271903
|
init_snapshot();
|
|
269788
271904
|
init_skills$1();
|
|
@@ -273744,7 +275860,9 @@ var DEFAULT_MAX_BUFFER_SIZE, DEFAULT_FLUSH_INTERVAL_MS, DEFAULT_MAX_BATCH_SIZE,
|
|
|
273744
275860
|
var init_wsConnectionV1 = __esmMin((() => {
|
|
273745
275861
|
init_ws_control();
|
|
273746
275862
|
init_src$2();
|
|
275863
|
+
init_src$6();
|
|
273747
275864
|
init_node$3();
|
|
275865
|
+
init_error_codes();
|
|
273748
275866
|
init_protocol();
|
|
273749
275867
|
init_sessionEventBroadcaster();
|
|
273750
275868
|
init_fsWatchBridge();
|
|
@@ -273762,6 +275880,7 @@ var init_wsConnectionV1 = __esmMin((() => {
|
|
|
273762
275880
|
socket;
|
|
273763
275881
|
broadcaster;
|
|
273764
275882
|
fsWatchBridge;
|
|
275883
|
+
core;
|
|
273765
275884
|
validateCredential;
|
|
273766
275885
|
maxBufferSize;
|
|
273767
275886
|
flushIntervalMs;
|
|
@@ -273773,6 +275892,12 @@ var init_wsConnectionV1 = __esmMin((() => {
|
|
|
273773
275892
|
/** Per-session subscription state: legacy agent allowlist + opt-in transcript grades. */
|
|
273774
275893
|
subscriptions = /* @__PURE__ */ new Map();
|
|
273775
275894
|
/**
|
|
275895
|
+
* Terminal services this connection has attached to (one per session,
|
|
275896
|
+
* resolved lazily). Tracked so teardown can detach every terminal sink
|
|
275897
|
+
* the connection owns.
|
|
275898
|
+
*/
|
|
275899
|
+
terminalServices = /* @__PURE__ */ new Set();
|
|
275900
|
+
/**
|
|
273776
275901
|
* Serializes control-frame handling in receive order. Frames arrive
|
|
273777
275902
|
* back-to-back (e.g. `client_hello` immediately followed by
|
|
273778
275903
|
* `subscribe_v2`), and a later handler reads subscription state the
|
|
@@ -273794,6 +275919,7 @@ var init_wsConnectionV1 = __esmMin((() => {
|
|
|
273794
275919
|
this.socket = opts.socket;
|
|
273795
275920
|
this.broadcaster = opts.broadcaster;
|
|
273796
275921
|
this.fsWatchBridge = opts.fsWatchBridge;
|
|
275922
|
+
this.core = opts.core;
|
|
273797
275923
|
this.validateCredential = opts.validateCredential;
|
|
273798
275924
|
this.logger = opts.logger;
|
|
273799
275925
|
this.maxBufferSize = opts.maxBufferSize ?? DEFAULT_MAX_BUFFER_SIZE;
|
|
@@ -273857,6 +275983,21 @@ var init_wsConnectionV1 = __esmMin((() => {
|
|
|
273857
275983
|
case "watch_fs_remove":
|
|
273858
275984
|
this.enqueueControl(() => this.onWatchFs(frame, false));
|
|
273859
275985
|
return;
|
|
275986
|
+
case "terminal_attach":
|
|
275987
|
+
this.enqueueControl(() => this.onTerminalAttach(frame));
|
|
275988
|
+
return;
|
|
275989
|
+
case "terminal_input":
|
|
275990
|
+
this.enqueueControl(() => this.onTerminalInput(frame));
|
|
275991
|
+
return;
|
|
275992
|
+
case "terminal_resize":
|
|
275993
|
+
this.enqueueControl(() => this.onTerminalResize(frame));
|
|
275994
|
+
return;
|
|
275995
|
+
case "terminal_close":
|
|
275996
|
+
this.enqueueControl(() => this.onTerminalClose(frame));
|
|
275997
|
+
return;
|
|
275998
|
+
case "terminal_detach":
|
|
275999
|
+
this.enqueueControl(() => this.onTerminalDetach(frame));
|
|
276000
|
+
return;
|
|
273860
276001
|
default: return;
|
|
273861
276002
|
}
|
|
273862
276003
|
}
|
|
@@ -274002,6 +276143,120 @@ var init_wsConnectionV1 = __esmMin((() => {
|
|
|
274002
276143
|
}));
|
|
274003
276144
|
}
|
|
274004
276145
|
/**
|
|
276146
|
+
* `terminal_attach` — attach this connection's sink to a session terminal
|
|
276147
|
+
* stream. The sink's frames (`terminal_output` / `terminal_exit`) are
|
|
276148
|
+
* delivered over the same subscription buffer as session events (coalesced
|
|
276149
|
+
* only when mergeable — terminal frames never merge, they just share the
|
|
276150
|
+
* flush window). `since_seq` replays buffered frames past the cursor, like
|
|
276151
|
+
* the REST/WS attach contract.
|
|
276152
|
+
*/
|
|
276153
|
+
async onTerminalAttach(frame) {
|
|
276154
|
+
const parsed = terminalAttachMessageSchema.safeParse(frame);
|
|
276155
|
+
if (!parsed.success) {
|
|
276156
|
+
this.sendImmediateFrame(buildAck(frame.id ?? "", 1, "invalid terminal_attach payload", {}));
|
|
276157
|
+
return;
|
|
276158
|
+
}
|
|
276159
|
+
const { session_id, terminal_id, since_seq } = parsed.data.payload;
|
|
276160
|
+
try {
|
|
276161
|
+
const terminals = await this.resolveTerminalService(session_id);
|
|
276162
|
+
const sink = {
|
|
276163
|
+
id: this.id,
|
|
276164
|
+
send: (terminalFrame) => this.sendSubscribedFrame(terminalFrame)
|
|
276165
|
+
};
|
|
276166
|
+
const { replayed } = await terminals.attach(terminal_id, sink, { sinceSeq: since_seq });
|
|
276167
|
+
this.sendImmediateFrame(buildAck(frame.id ?? "", 0, "success", {
|
|
276168
|
+
attached: true,
|
|
276169
|
+
replayed
|
|
276170
|
+
}));
|
|
276171
|
+
} catch (error) {
|
|
276172
|
+
this.sendTerminalErrorAck(frame.id, error);
|
|
276173
|
+
}
|
|
276174
|
+
}
|
|
276175
|
+
/** `terminal_input` — write bytes to the attached terminal's pty. */
|
|
276176
|
+
async onTerminalInput(frame) {
|
|
276177
|
+
const parsed = terminalInputMessageSchema.safeParse(frame);
|
|
276178
|
+
if (!parsed.success) {
|
|
276179
|
+
this.sendImmediateFrame(buildAck(frame.id ?? "", 1, "invalid terminal_input payload", {}));
|
|
276180
|
+
return;
|
|
276181
|
+
}
|
|
276182
|
+
const { session_id, terminal_id, data } = parsed.data.payload;
|
|
276183
|
+
try {
|
|
276184
|
+
await (await this.resolveTerminalService(session_id)).write(terminal_id, data);
|
|
276185
|
+
this.sendImmediateFrame(buildAck(frame.id ?? "", 0, "success", { accepted: true }));
|
|
276186
|
+
} catch (error) {
|
|
276187
|
+
this.sendTerminalErrorAck(frame.id, error);
|
|
276188
|
+
}
|
|
276189
|
+
}
|
|
276190
|
+
/** `terminal_resize` — resize the attached terminal's pty. */
|
|
276191
|
+
async onTerminalResize(frame) {
|
|
276192
|
+
const parsed = terminalResizeMessageSchema.safeParse(frame);
|
|
276193
|
+
if (!parsed.success) {
|
|
276194
|
+
this.sendImmediateFrame(buildAck(frame.id ?? "", 1, "invalid terminal_resize payload", {}));
|
|
276195
|
+
return;
|
|
276196
|
+
}
|
|
276197
|
+
const { session_id, terminal_id, cols, rows } = parsed.data.payload;
|
|
276198
|
+
try {
|
|
276199
|
+
await (await this.resolveTerminalService(session_id)).resize(terminal_id, cols, rows);
|
|
276200
|
+
this.sendImmediateFrame(buildAck(frame.id ?? "", 0, "success", { resized: true }));
|
|
276201
|
+
} catch (error) {
|
|
276202
|
+
this.sendTerminalErrorAck(frame.id, error);
|
|
276203
|
+
}
|
|
276204
|
+
}
|
|
276205
|
+
/** `terminal_close` — close the terminal's pty (idempotent). */
|
|
276206
|
+
async onTerminalClose(frame) {
|
|
276207
|
+
const parsed = terminalCloseMessageSchema.safeParse(frame);
|
|
276208
|
+
if (!parsed.success) {
|
|
276209
|
+
this.sendImmediateFrame(buildAck(frame.id ?? "", 1, "invalid terminal_close payload", {}));
|
|
276210
|
+
return;
|
|
276211
|
+
}
|
|
276212
|
+
const { session_id, terminal_id } = parsed.data.payload;
|
|
276213
|
+
try {
|
|
276214
|
+
await (await this.resolveTerminalService(session_id)).close(terminal_id);
|
|
276215
|
+
this.sendImmediateFrame(buildAck(frame.id ?? "", 0, "success", { closed: true }));
|
|
276216
|
+
} catch (error) {
|
|
276217
|
+
this.sendTerminalErrorAck(frame.id, error);
|
|
276218
|
+
}
|
|
276219
|
+
}
|
|
276220
|
+
/** `terminal_detach` — detach this connection's sink from a terminal stream. */
|
|
276221
|
+
async onTerminalDetach(frame) {
|
|
276222
|
+
const parsed = terminalDetachMessageSchema.safeParse(frame);
|
|
276223
|
+
if (!parsed.success) {
|
|
276224
|
+
this.sendImmediateFrame(buildAck(frame.id ?? "", 1, "invalid terminal_detach payload", {}));
|
|
276225
|
+
return;
|
|
276226
|
+
}
|
|
276227
|
+
const { session_id, terminal_id } = parsed.data.payload;
|
|
276228
|
+
try {
|
|
276229
|
+
(await this.resolveTerminalService(session_id)).detach(terminal_id, this.id);
|
|
276230
|
+
this.sendImmediateFrame(buildAck(frame.id ?? "", 0, "success", { detached: true }));
|
|
276231
|
+
} catch (error) {
|
|
276232
|
+
this.sendTerminalErrorAck(frame.id, error);
|
|
276233
|
+
}
|
|
276234
|
+
}
|
|
276235
|
+
/**
|
|
276236
|
+
* Resolve a session's `ISessionTerminalService` (cold-loading a
|
|
276237
|
+
* persisted-but-not-live session, matching the REST terminal route).
|
|
276238
|
+
* The resolved service is remembered so `onClose` can detach every sink
|
|
276239
|
+
* this connection owns.
|
|
276240
|
+
*/
|
|
276241
|
+
async resolveTerminalService(sessionId) {
|
|
276242
|
+
const session = await this.core.accessor.get(ISessionLifecycleService).resume(sessionId);
|
|
276243
|
+
if (session === void 0) throw new Error2(ErrorCodes.SESSION_NOT_FOUND, `session ${sessionId} does not exist`);
|
|
276244
|
+
const terminals = session.accessor.get(ISessionTerminalService);
|
|
276245
|
+
this.terminalServices.add(terminals);
|
|
276246
|
+
return terminals;
|
|
276247
|
+
}
|
|
276248
|
+
/** Ack a terminal control failure with the wire error code when known. */
|
|
276249
|
+
sendTerminalErrorAck(id, error) {
|
|
276250
|
+
let code = 1;
|
|
276251
|
+
let msg = "internal error";
|
|
276252
|
+
if (isError2(error)) {
|
|
276253
|
+
if (error.code === ErrorCodes.SESSION_NOT_FOUND) code = ErrorCode.SESSION_NOT_FOUND;
|
|
276254
|
+
else if (error.code === ErrorCodes.TERMINAL_NOT_FOUND) code = ErrorCode.TERMINAL_NOT_FOUND;
|
|
276255
|
+
msg = error.message;
|
|
276256
|
+
} else if (error instanceof Error) msg = error.message;
|
|
276257
|
+
this.sendImmediateFrame(buildAck(id ?? "", code, msg, {}));
|
|
276258
|
+
}
|
|
276259
|
+
/**
|
|
274005
276260
|
* Shared attach path behind `client_hello` (legacy inline subscriptions)
|
|
274006
276261
|
* and `subscribe`. Subscribes the connection via the broadcaster, then
|
|
274007
276262
|
* either replays durable events since the client's cursor (with the
|
|
@@ -274146,6 +276401,7 @@ var init_wsConnectionV1 = __esmMin((() => {
|
|
|
274146
276401
|
this.outbound = [];
|
|
274147
276402
|
this.broadcaster.removeGlobalTarget(this);
|
|
274148
276403
|
for (const sid of this.subscriptions.keys()) this.broadcaster.unsubscribe(sid, this);
|
|
276404
|
+
for (const terminals of this.terminalServices) terminals.detachAllForSink(this.id);
|
|
274149
276405
|
this.fsWatchBridge?.detachConnection(this);
|
|
274150
276406
|
}
|
|
274151
276407
|
};
|
|
@@ -274164,6 +276420,7 @@ function registerWsV1(core, opts) {
|
|
|
274164
276420
|
broadcaster,
|
|
274165
276421
|
fsWatchBridge: opts.fsWatchBridge,
|
|
274166
276422
|
connectionRegistry: registry,
|
|
276423
|
+
core,
|
|
274167
276424
|
validateCredential: opts.validateCredential,
|
|
274168
276425
|
remoteAddress: req.socket.remoteAddress ?? null,
|
|
274169
276426
|
userAgent: req.headers["user-agent"] ?? null,
|
|
@@ -296465,6 +298722,15 @@ function stringifyToolOutput(output) {
|
|
|
296465
298722
|
if (typeof output === "string") return output;
|
|
296466
298723
|
return JSON.stringify(output) ?? String(output);
|
|
296467
298724
|
}
|
|
298725
|
+
function stringifyToolArgs(args) {
|
|
298726
|
+
if (typeof args === "string") return args;
|
|
298727
|
+
return JSON.stringify(args) ?? String(args);
|
|
298728
|
+
}
|
|
298729
|
+
function truncateChars(text, max) {
|
|
298730
|
+
if (text.length <= max) return text;
|
|
298731
|
+
const suffix = `… (${text.length - max} more chars)`;
|
|
298732
|
+
return `${text.slice(0, max - suffix.length)}${suffix}`;
|
|
298733
|
+
}
|
|
296468
298734
|
function writeVersion(version, outputFormat, stdout, stderr) {
|
|
296469
298735
|
if (outputFormat === "stream-json") {
|
|
296470
298736
|
const message = {
|
|
@@ -296493,16 +298759,23 @@ function writeResumeHint(sessionId, outputFormat, stdout, stderr) {
|
|
|
296493
298759
|
}
|
|
296494
298760
|
stderr.write(`${content}\n`);
|
|
296495
298761
|
}
|
|
296496
|
-
var PROMPT_BLOCK_BULLET, PROMPT_BLOCK_INDENT, PromptTranscriptWriter, PromptJsonWriter, PromptBlockWriter;
|
|
298762
|
+
var PROMPT_BLOCK_BULLET, PROMPT_BLOCK_INDENT, TOOL_CALL_MARK, TOOL_RESULT_MARK, RETRY_MARK, MAX_TOOL_CALL_ARGS_CHARS, MAX_TOOL_RESULT_CHARS, PromptTranscriptWriter, PromptJsonWriter, PromptBlockWriter;
|
|
296497
298763
|
var init_prompt_render = __esmMin((() => {
|
|
296498
298764
|
PROMPT_BLOCK_BULLET = "• ";
|
|
296499
298765
|
PROMPT_BLOCK_INDENT = " ";
|
|
298766
|
+
TOOL_CALL_MARK = "⚒ ";
|
|
298767
|
+
TOOL_RESULT_MARK = "⚒ result: ";
|
|
298768
|
+
RETRY_MARK = "↻ retry";
|
|
298769
|
+
MAX_TOOL_CALL_ARGS_CHARS = 500;
|
|
298770
|
+
MAX_TOOL_RESULT_CHARS = 2e3;
|
|
296500
298771
|
PromptTranscriptWriter = class {
|
|
296501
298772
|
assistantWriter;
|
|
296502
298773
|
thinkingWriter;
|
|
298774
|
+
toolWriter;
|
|
296503
298775
|
constructor(stdout, stderr) {
|
|
296504
298776
|
this.assistantWriter = new PromptBlockWriter(stdout);
|
|
296505
298777
|
this.thinkingWriter = new PromptBlockWriter(stderr);
|
|
298778
|
+
this.toolWriter = new PromptBlockWriter(stderr);
|
|
296506
298779
|
}
|
|
296507
298780
|
writeAssistantDelta(delta) {
|
|
296508
298781
|
this.thinkingWriter.finish();
|
|
@@ -296517,10 +298790,25 @@ var init_prompt_render = __esmMin((() => {
|
|
|
296517
298790
|
writeThinkingDelta(delta) {
|
|
296518
298791
|
this.thinkingWriter.write(delta);
|
|
296519
298792
|
}
|
|
296520
|
-
writeToolCall() {
|
|
298793
|
+
writeToolCall(toolCallId, name, args) {
|
|
298794
|
+
this.thinkingWriter.finish();
|
|
298795
|
+
this.assistantWriter.finish();
|
|
298796
|
+
this.toolWriter.write(`${TOOL_CALL_MARK}${name}(${truncateChars(stringifyToolArgs(args), MAX_TOOL_CALL_ARGS_CHARS)})`);
|
|
298797
|
+
this.toolWriter.finish();
|
|
298798
|
+
}
|
|
296521
298799
|
writeToolCallDelta() {}
|
|
296522
|
-
writeToolResult() {
|
|
296523
|
-
|
|
298800
|
+
writeToolResult(toolCallId, output) {
|
|
298801
|
+
this.toolWriter.finish();
|
|
298802
|
+
this.toolWriter.write(`${TOOL_RESULT_MARK}${truncateChars(stringifyToolOutput(output), MAX_TOOL_RESULT_CHARS)}`);
|
|
298803
|
+
this.toolWriter.finish();
|
|
298804
|
+
}
|
|
298805
|
+
writeRetrying(event) {
|
|
298806
|
+
this.thinkingWriter.finish();
|
|
298807
|
+
this.assistantWriter.finish();
|
|
298808
|
+
const error = [event.errorName, event.errorMessage].filter(Boolean).join(": ");
|
|
298809
|
+
this.toolWriter.write(`${RETRY_MARK} ${event.failedAttempt}/${event.maxAttempts} (${error}) — ${event.delayMs}ms`);
|
|
298810
|
+
this.toolWriter.finish();
|
|
298811
|
+
}
|
|
296524
298812
|
flushAssistant() {
|
|
296525
298813
|
this.assistantWriter.finish();
|
|
296526
298814
|
}
|
|
@@ -296528,6 +298816,7 @@ var init_prompt_render = __esmMin((() => {
|
|
|
296528
298816
|
finish() {
|
|
296529
298817
|
this.thinkingWriter.finish();
|
|
296530
298818
|
this.assistantWriter.finish();
|
|
298819
|
+
this.toolWriter.finish();
|
|
296531
298820
|
}
|
|
296532
298821
|
};
|
|
296533
298822
|
PromptJsonWriter = class {
|