@moxt-ai/mobius 0.0.300 → 0.0.302
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/acp/harness/claude/endpoint.d.ts.map +1 -1
- package/dist/acp/harness/claude/endpoint.js +2 -0
- package/dist/acp/harness/claude/endpoint.js.map +1 -1
- package/dist/acp/harness/claude/parent-lifeline.d.ts +3 -0
- package/dist/acp/harness/claude/parent-lifeline.d.ts.map +1 -0
- package/dist/acp/harness/claude/parent-lifeline.js +73 -0
- package/dist/acp/harness/claude/parent-lifeline.js.map +1 -0
- package/dist/acp/harness/codex/agent.d.ts.map +1 -1
- package/dist/acp/harness/codex/agent.js +5 -1
- package/dist/acp/harness/codex/agent.js.map +1 -1
- package/dist/acp/harness/pi/endpoint.d.ts.map +1 -1
- package/dist/acp/harness/pi/endpoint.js +1 -0
- package/dist/acp/harness/pi/endpoint.js.map +1 -1
- package/dist/cli.js +595 -61
- package/dist/cli.js.map +4 -4
- package/dist/generated/acp-session-store-migrations.d.ts +3 -0
- package/dist/generated/acp-session-store-migrations.d.ts.map +1 -1
- package/dist/generated/acp-session-store-migrations.js +5 -1
- package/dist/generated/acp-session-store-migrations.js.map +1 -1
- package/dist/runtime/command/registry/prompt.d.ts.map +1 -1
- package/dist/runtime/command/registry/prompt.js +6 -0
- package/dist/runtime/command/registry/prompt.js.map +1 -1
- package/dist/runtime/engine.d.ts +1 -0
- package/dist/runtime/engine.d.ts.map +1 -1
- package/dist/runtime/engine.js +8 -0
- package/dist/runtime/engine.js.map +1 -1
- package/dist/runtime/run.d.ts +1 -0
- package/dist/runtime/run.d.ts.map +1 -1
- package/dist/runtime/run.js +3 -0
- package/dist/runtime/run.js.map +1 -1
- package/dist/runtime.js +560 -54
- package/dist/runtime.js.map +4 -4
- package/dist/schema/acp-session-store/execution-receipt.d.ts +136 -0
- package/dist/schema/acp-session-store/execution-receipt.d.ts.map +1 -0
- package/dist/schema/acp-session-store/execution-receipt.js +12 -0
- package/dist/schema/acp-session-store/execution-receipt.js.map +1 -0
- package/dist/schema/acp-session-store/index.d.ts +1 -0
- package/dist/schema/acp-session-store/index.d.ts.map +1 -1
- package/dist/schema/acp-session-store/index.js +1 -0
- package/dist/schema/acp-session-store/index.js.map +1 -1
- package/dist/session/api/session-api.d.ts +4 -0
- package/dist/session/api/session-api.d.ts.map +1 -1
- package/dist/session/api/session-api.js.map +1 -1
- package/dist/session/api/session-layer.d.ts +2 -0
- package/dist/session/api/session-layer.d.ts.map +1 -1
- package/dist/session/api/session-layer.js +25 -4
- package/dist/session/api/session-layer.js.map +1 -1
- package/dist/session/history/session-event-store.d.ts +7 -4
- package/dist/session/history/session-event-store.d.ts.map +1 -1
- package/dist/session/history/session-event-store.js +13 -7
- package/dist/session/history/session-event-store.js.map +1 -1
- package/dist/session/history/session-history.d.ts +1 -4
- package/dist/session/history/session-history.d.ts.map +1 -1
- package/dist/session/history/session-history.js +1 -4
- package/dist/session/history/session-history.js.map +1 -1
- package/dist/session/live/agent-session-restore.d.ts +1 -0
- package/dist/session/live/agent-session-restore.d.ts.map +1 -1
- package/dist/session/live/agent-session.d.ts +2 -0
- package/dist/session/live/agent-session.d.ts.map +1 -1
- package/dist/session/live/agent-session.js +15 -4
- package/dist/session/live/agent-session.js.map +1 -1
- package/dist/session/live/session-restore.d.ts.map +1 -1
- package/dist/session/live/session-restore.js +37 -0
- package/dist/session/live/session-restore.js.map +1 -1
- package/dist/session/manager/session-manager.d.ts.map +1 -1
- package/dist/session/manager/session-manager.js +11 -3
- package/dist/session/manager/session-manager.js.map +1 -1
- package/dist/session/prompt/execute-prompt.d.ts.map +1 -1
- package/dist/session/prompt/execute-prompt.js +6 -1
- package/dist/session/prompt/execute-prompt.js.map +1 -1
- package/dist/session/prompt/prompt-lifecycle.d.ts +1 -0
- package/dist/session/prompt/prompt-lifecycle.d.ts.map +1 -1
- package/dist/session/prompt/prompt-lifecycle.js +9 -1
- package/dist/session/prompt/prompt-lifecycle.js.map +1 -1
- package/dist/session/turn/execution-receipts.d.ts +23 -2
- package/dist/session/turn/execution-receipts.d.ts.map +1 -1
- package/dist/session/turn/execution-receipts.js +161 -10
- package/dist/session/turn/execution-receipts.js.map +1 -1
- package/dist/storage/session/execution-receipt-table.d.ts +45 -0
- package/dist/storage/session/execution-receipt-table.d.ts.map +1 -0
- package/dist/storage/session/execution-receipt-table.js +64 -0
- package/dist/storage/session/execution-receipt-table.js.map +1 -0
- package/package.json +2 -2
package/dist/runtime.js
CHANGED
|
@@ -21633,6 +21633,10 @@ var SessionPromptDisposition = Object.freeze({
|
|
|
21633
21633
|
Reject: "reject",
|
|
21634
21634
|
Steer: "steer"
|
|
21635
21635
|
});
|
|
21636
|
+
var SessionHistoryPolicy = Object.freeze({
|
|
21637
|
+
Eager: "eager",
|
|
21638
|
+
ExecutionOnly: "execution-only"
|
|
21639
|
+
});
|
|
21636
21640
|
var MAX_PROMPT_LENGTH = 1e5;
|
|
21637
21641
|
var MAX_PROMPT_ATTACHMENT_LENGTH = 6e6;
|
|
21638
21642
|
var promptImageSchema = external_exports.object({
|
|
@@ -21694,6 +21698,9 @@ function decodeSessionPromptCommand(encoded) {
|
|
|
21694
21698
|
directoryId: readDirectoryIdentifier(value, "directoryId"),
|
|
21695
21699
|
disposition,
|
|
21696
21700
|
images,
|
|
21701
|
+
...value["historyPolicy"] === void 0 ? {} : {
|
|
21702
|
+
historyPolicy: readHistoryPolicy(value)
|
|
21703
|
+
},
|
|
21697
21704
|
kind: SESSION_PROMPT_KIND,
|
|
21698
21705
|
prompt,
|
|
21699
21706
|
resources,
|
|
@@ -21702,6 +21709,13 @@ function decodeSessionPromptCommand(encoded) {
|
|
|
21702
21709
|
targetCommandId
|
|
21703
21710
|
};
|
|
21704
21711
|
}
|
|
21712
|
+
function readHistoryPolicy(value) {
|
|
21713
|
+
const field = value["historyPolicy"];
|
|
21714
|
+
if (field === SessionHistoryPolicy.Eager || field === SessionHistoryPolicy.ExecutionOnly) {
|
|
21715
|
+
return field;
|
|
21716
|
+
}
|
|
21717
|
+
throw new ProtocolMessageError("Invalid value field: historyPolicy");
|
|
21718
|
+
}
|
|
21705
21719
|
function decodeSessionCancelCommand(encoded) {
|
|
21706
21720
|
const value = parseJson(encoded);
|
|
21707
21721
|
assertKind(value, SESSION_CANCEL_KIND);
|
|
@@ -22627,16 +22641,28 @@ import { fetch as fetch3 } from "undici";
|
|
|
22627
22641
|
// package.json
|
|
22628
22642
|
var package_default = {
|
|
22629
22643
|
name: "@moxt-ai/mobius",
|
|
22630
|
-
version: "0.0.
|
|
22644
|
+
version: "0.0.302",
|
|
22631
22645
|
description: "Mobius CLI for pairing and running local AI agent services.",
|
|
22632
22646
|
type: "module",
|
|
22633
22647
|
bin: {
|
|
22634
22648
|
mobius: "dist/cli.js"
|
|
22635
22649
|
},
|
|
22636
22650
|
exports: {
|
|
22637
|
-
"./runtime":
|
|
22638
|
-
|
|
22639
|
-
|
|
22651
|
+
"./runtime": {
|
|
22652
|
+
"mobius-source": "./src/runtime.ts",
|
|
22653
|
+
types: "./dist/runtime.d.ts",
|
|
22654
|
+
default: "./dist/runtime.js"
|
|
22655
|
+
},
|
|
22656
|
+
"./process": {
|
|
22657
|
+
"mobius-source": "./src/util/process/executable.ts",
|
|
22658
|
+
types: "./dist/util/process/executable.d.ts",
|
|
22659
|
+
default: "./dist/util/process/executable.js"
|
|
22660
|
+
},
|
|
22661
|
+
"./filesystem": {
|
|
22662
|
+
"mobius-source": "./src/util/filesystem/private-path.ts",
|
|
22663
|
+
types: "./dist/util/filesystem/private-path.d.ts",
|
|
22664
|
+
default: "./dist/util/filesystem/private-path.js"
|
|
22665
|
+
}
|
|
22640
22666
|
},
|
|
22641
22667
|
files: [
|
|
22642
22668
|
"dist"
|
|
@@ -22718,6 +22744,78 @@ var package_default = {
|
|
|
22718
22744
|
homepage: "https://github.com/moxt-ai/mobius#readme"
|
|
22719
22745
|
};
|
|
22720
22746
|
|
|
22747
|
+
// src/acp/harness/claude/parent-lifeline.ts
|
|
22748
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
22749
|
+
import { Duplex } from "node:stream";
|
|
22750
|
+
var supervisor = `
|
|
22751
|
+
const { spawn, spawnSync } = require("node:child_process");
|
|
22752
|
+
const { Socket } = require("node:net");
|
|
22753
|
+
const [command, ...args] = process.argv.slice(1);
|
|
22754
|
+
const child = spawn(command, args, { stdio: ["pipe", "pipe", "pipe"], detached: process.platform !== "win32", windowsHide: true });
|
|
22755
|
+
const lifeline = new Socket({ fd: 3, readable: true, writable: false });
|
|
22756
|
+
let exited = false;
|
|
22757
|
+
function terminate() {
|
|
22758
|
+
if (exited || child.pid === undefined) return;
|
|
22759
|
+
if (process.platform === "win32") {
|
|
22760
|
+
spawnSync("taskkill", ["/pid", String(child.pid), "/T", "/F"], { timeout: 5000, windowsHide: true, stdio: "ignore" });
|
|
22761
|
+
} else {
|
|
22762
|
+
try { process.kill(-child.pid, "SIGKILL"); }
|
|
22763
|
+
catch (error) { if (error.code !== "ESRCH") throw error; }
|
|
22764
|
+
}
|
|
22765
|
+
}
|
|
22766
|
+
lifeline.on("end", terminate).on("error", terminate).resume();
|
|
22767
|
+
process.on("SIGTERM", terminate).on("SIGINT", terminate);
|
|
22768
|
+
process.stdin.pipe(child.stdin);
|
|
22769
|
+
child.stdin.on("error", () => {});
|
|
22770
|
+
child.stdout.pipe(process.stdout);
|
|
22771
|
+
child.stderr.pipe(process.stderr);
|
|
22772
|
+
child.once("error", (error) => { process.stderr.write(error.message); process.exitCode = 1; lifeline.destroy(); process.stdin.destroy(); });
|
|
22773
|
+
child.once("close", (code) => { exited = true; process.exitCode = code ?? 1; lifeline.destroy(); process.stdin.destroy(); });
|
|
22774
|
+
`;
|
|
22775
|
+
function spawnClaudeWithParentLifeline(options) {
|
|
22776
|
+
options.signal.throwIfAborted();
|
|
22777
|
+
const child = spawn2(process.execPath, ["-e", supervisor, "--", options.command, ...options.args], {
|
|
22778
|
+
cwd: options.cwd,
|
|
22779
|
+
env: options.env,
|
|
22780
|
+
stdio: ["pipe", "pipe", "pipe", "pipe"],
|
|
22781
|
+
windowsHide: true
|
|
22782
|
+
});
|
|
22783
|
+
const lifeline = child.stdio[3];
|
|
22784
|
+
if (child.stdin === null || child.stdout === null || child.stderr === null || !(lifeline instanceof Duplex)) {
|
|
22785
|
+
child.kill("SIGKILL");
|
|
22786
|
+
throw new Error("The Claude process supervisor has no parent lifeline");
|
|
22787
|
+
}
|
|
22788
|
+
let termination = "running";
|
|
22789
|
+
const stop = () => {
|
|
22790
|
+
termination = "requested";
|
|
22791
|
+
lifeline.end();
|
|
22792
|
+
return true;
|
|
22793
|
+
};
|
|
22794
|
+
options.signal.addEventListener("abort", stop, { once: true });
|
|
22795
|
+
if (options.signal.aborted) {
|
|
22796
|
+
stop();
|
|
22797
|
+
}
|
|
22798
|
+
child.once("close", () => options.signal.removeEventListener("abort", stop));
|
|
22799
|
+
child.stderr.pipe(process.stderr, { end: false });
|
|
22800
|
+
return {
|
|
22801
|
+
stdin: child.stdin,
|
|
22802
|
+
stdout: child.stdout,
|
|
22803
|
+
get killed() {
|
|
22804
|
+
return termination === "requested";
|
|
22805
|
+
},
|
|
22806
|
+
get exitCode() {
|
|
22807
|
+
return child.exitCode;
|
|
22808
|
+
},
|
|
22809
|
+
get signalCode() {
|
|
22810
|
+
return child.signalCode;
|
|
22811
|
+
},
|
|
22812
|
+
kill: stop,
|
|
22813
|
+
on: child.on.bind(child),
|
|
22814
|
+
once: child.once.bind(child),
|
|
22815
|
+
off: child.off.bind(child)
|
|
22816
|
+
};
|
|
22817
|
+
}
|
|
22818
|
+
|
|
22721
22819
|
// src/acp/harness/claude/upstream/dist/acp-agent.js
|
|
22722
22820
|
import { execFile as execFile3 } from "node:child_process";
|
|
22723
22821
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
@@ -62438,6 +62536,7 @@ async function waitForMcpAuthentication(sessions, sessionId, query, serverName,
|
|
|
62438
62536
|
return false;
|
|
62439
62537
|
}
|
|
62440
62538
|
var ClaudeAcpAgent = class {
|
|
62539
|
+
spawnClaudeCodeProcess;
|
|
62441
62540
|
sessions;
|
|
62442
62541
|
client;
|
|
62443
62542
|
clientCapabilities;
|
|
@@ -62454,7 +62553,8 @@ var ClaudeAcpAgent = class {
|
|
|
62454
62553
|
* return "cancelled". See {@link DEFAULT_FORCE_CANCEL_GRACE_MS}. Mutable so
|
|
62455
62554
|
* tests can shrink it. */
|
|
62456
62555
|
forceCancelGraceMs = DEFAULT_FORCE_CANCEL_GRACE_MS;
|
|
62457
|
-
constructor(client2, logger, environment = process.env) {
|
|
62556
|
+
constructor(client2, logger, environment = process.env, spawnClaudeCodeProcess) {
|
|
62557
|
+
this.spawnClaudeCodeProcess = spawnClaudeCodeProcess;
|
|
62458
62558
|
this.sessions = {};
|
|
62459
62559
|
this.client = client2;
|
|
62460
62560
|
this.logger = logger ?? console;
|
|
@@ -65031,6 +65131,7 @@ ${message.api_refusal_explanation}` : "";
|
|
|
65031
65131
|
supportedDialogKinds: [REFUSAL_FALLBACK_DIALOG_KIND]
|
|
65032
65132
|
} : {},
|
|
65033
65133
|
pathToClaudeCodeExecutable: this.environment.CLAUDE_CODE_EXECUTABLE ?? await claudeCliPath(),
|
|
65134
|
+
...this.spawnClaudeCodeProcess === void 0 ? {} : { spawnClaudeCodeProcess: this.spawnClaudeCodeProcess },
|
|
65034
65135
|
extraArgs: {
|
|
65035
65136
|
...userProvidedOptions?.extraArgs,
|
|
65036
65137
|
"replay-user-messages": ""
|
|
@@ -66449,7 +66550,7 @@ async function runPromptWithCancellation(agent, params, signal) {
|
|
|
66449
66550
|
function createClaudeAcpApp(options = {}) {
|
|
66450
66551
|
let agent = null;
|
|
66451
66552
|
const app = acpAgent({ name: "claude-code-acp" }).onConnect((connection) => {
|
|
66452
|
-
agent = new ClaudeAcpAgent(new ClientConnection(connection.client, options.onSessionUpdate), options.logger, options.environment);
|
|
66553
|
+
agent = new ClaudeAcpAgent(new ClientConnection(connection.client, options.onSessionUpdate), options.logger, options.environment, options.spawnClaudeCodeProcess);
|
|
66453
66554
|
options.onConnect?.(connection);
|
|
66454
66555
|
}).onRequest(methods.agent.initialize, (ctx) => requiredAgent(agent).initialize(ctx.params)).onRequest(methods.agent.session.new, (ctx) => requiredAgent(agent).newSession(ctx.params)).onRequest(methods.agent.session.load, (ctx) => requiredAgent(agent).loadSession(ctx.params, ctx.signal)).onRequest(methods.agent.session.fork, (ctx) => requiredAgent(agent).unstable_forkSession(ctx.params, ctx.signal)).onRequest(methods.agent.session.list, (ctx) => requiredAgent(agent).listSessions(ctx.params, ctx.signal)).onRequest(methods.agent.session.delete, (ctx) => requiredAgent(agent).deleteSession(ctx.params)).onRequest(methods.agent.session.resume, (ctx) => requiredAgent(agent).resumeSession(ctx.params)).onRequest(methods.agent.session.close, (ctx) => requiredAgent(agent).closeSession(ctx.params)).onRequest(methods.agent.session.setMode, (ctx) => requiredAgent(agent).setSessionMode(ctx.params)).onRequest(methods.agent.session.setConfigOption, (ctx) => requiredAgent(agent).setSessionConfigOption(ctx.params)).onRequest(methods.agent.authenticate, (ctx) => requiredAgent(agent).authenticate(ctx.params)).onRequest(methods.agent.providers.list, (ctx) => requiredAgent(agent).unstable_listProviders(ctx.params)).onRequest(methods.agent.providers.set, (ctx) => requiredAgent(agent).unstable_setProvider(ctx.params)).onRequest(methods.agent.providers.disable, (ctx) => requiredAgent(agent).unstable_disableProvider(ctx.params)).onRequest(methods.agent.logout, (ctx) => requiredAgent(agent).logout(ctx.params)).onRequest(methods.agent.session.prompt, (ctx) => runPromptWithCancellation(requiredAgent(agent), ctx.params, ctx.signal)).onNotification(methods.agent.session.cancel, (ctx) => requiredAgent(agent).cancel(ctx.params)).onRequest(STEER_METHOD, { parse: parseSteerRequest }, (ctx) => requiredAgent(agent).steer(ctx.params)).onRequest(RENAME_METHOD, { parse: parseRenameRequest }, (ctx) => requiredAgent(agent).renameSession(ctx.params)).onRequest(GOAL_CONTROL_METHOD, { parse: parseGoalRequest }, (ctx) => requiredAgent(agent).goal(ctx.params));
|
|
66455
66556
|
return { agent: () => agent, app };
|
|
@@ -66574,6 +66675,7 @@ var ClaudeAcpEndpoint = class {
|
|
|
66574
66675
|
this.terminated = termination.promise;
|
|
66575
66676
|
this.#resolveTermination = termination.resolve;
|
|
66576
66677
|
const claude = createClaudeAcpApp({
|
|
66678
|
+
spawnClaudeCodeProcess: spawnClaudeWithParentLifeline,
|
|
66577
66679
|
environment: Object.freeze({
|
|
66578
66680
|
...process.env,
|
|
66579
66681
|
...options.environment,
|
|
@@ -66724,7 +66826,7 @@ var AcpConfigurationValueUnavailableError = class extends AcpExecutionError {
|
|
|
66724
66826
|
};
|
|
66725
66827
|
|
|
66726
66828
|
// src/acp/harness/codex/app-server-client.ts
|
|
66727
|
-
import { spawn as
|
|
66829
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
66728
66830
|
|
|
66729
66831
|
// src/acp/agent/in-process-endpoint.ts
|
|
66730
66832
|
function acpEndpointTerminationError(termination) {
|
|
@@ -67057,7 +67159,7 @@ var CodexAppServerClient = class {
|
|
|
67057
67159
|
constructor(options) {
|
|
67058
67160
|
this.#handlers = options.handlers;
|
|
67059
67161
|
const launch = executableLaunch2(options.command, ["app-server"]);
|
|
67060
|
-
this.#child =
|
|
67162
|
+
this.#child = spawn4(launch.command, [...launch.arguments], {
|
|
67061
67163
|
cwd: options.cwd,
|
|
67062
67164
|
...platformSpawnOptions,
|
|
67063
67165
|
env: { ...process.env, ...options.environment },
|
|
@@ -67444,12 +67546,12 @@ function presentToolItem(item) {
|
|
|
67444
67546
|
};
|
|
67445
67547
|
}
|
|
67446
67548
|
if (item.type === "collabAgentToolCall") {
|
|
67447
|
-
const
|
|
67549
|
+
const spawn9 = item.tool === "spawnAgent";
|
|
67448
67550
|
return {
|
|
67449
67551
|
content: [],
|
|
67450
67552
|
kind: "other",
|
|
67451
67553
|
locations: [],
|
|
67452
|
-
rawInput:
|
|
67554
|
+
rawInput: spawn9 ? {
|
|
67453
67555
|
model: item.model,
|
|
67454
67556
|
prompt: item.prompt,
|
|
67455
67557
|
reasoningEffort: item.reasoningEffort,
|
|
@@ -67457,10 +67559,10 @@ function presentToolItem(item) {
|
|
|
67457
67559
|
} : { receiverThreadIds: item.receiverThreadIds, senderThreadId: item.senderThreadId },
|
|
67458
67560
|
rawOutput: {
|
|
67459
67561
|
agentsStates: item.agentsStates,
|
|
67460
|
-
...
|
|
67562
|
+
...spawn9 ? { receiverThreadIds: item.receiverThreadIds } : {}
|
|
67461
67563
|
},
|
|
67462
67564
|
status: collaborationStatus(item.status),
|
|
67463
|
-
title:
|
|
67565
|
+
title: spawn9 ? "Dispatch subagent" : "Wait for subagent"
|
|
67464
67566
|
};
|
|
67465
67567
|
}
|
|
67466
67568
|
if (item.type === "subAgentActivity" && item.kind === "started") {
|
|
@@ -68985,7 +69087,11 @@ var CodexAcpAgent = class {
|
|
|
68985
69087
|
const decoded = threadListResponseSchema.parse(
|
|
68986
69088
|
await this.#appServer.request(
|
|
68987
69089
|
"thread/list",
|
|
68988
|
-
{
|
|
69090
|
+
{
|
|
69091
|
+
cursor: context.params.cursor ?? null,
|
|
69092
|
+
// Codex defaults to interactive sources and otherwise hides exec handoffs.
|
|
69093
|
+
sourceKinds: ["cli", "vscode", "exec", "appServer"]
|
|
69094
|
+
},
|
|
68989
69095
|
AbortSignal.any([context.signal, AbortSignal.timeout(SESSION_LIST_TIMEOUT_MILLISECONDS2)])
|
|
68990
69096
|
)
|
|
68991
69097
|
);
|
|
@@ -69225,7 +69331,7 @@ import { basename as basename4, dirname as dirname7, isAbsolute as isAbsolute11,
|
|
|
69225
69331
|
import { RequestError as RequestError7 } from "@agentclientprotocol/sdk";
|
|
69226
69332
|
|
|
69227
69333
|
// src/acp/harness/pi/upstream/dist/pi-rpc/process.js
|
|
69228
|
-
import { spawn as
|
|
69334
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
69229
69335
|
import * as readline from "node:readline";
|
|
69230
69336
|
|
|
69231
69337
|
// src/acp/harness/pi/upstream/dist/pi-rpc/command.js
|
|
@@ -69342,7 +69448,7 @@ var PiRpcProcess = class _PiRpcProcess {
|
|
|
69342
69448
|
args.push("--fork", params.origin.sessionPath);
|
|
69343
69449
|
break;
|
|
69344
69450
|
}
|
|
69345
|
-
const child =
|
|
69451
|
+
const child = spawn5(cmd, args, {
|
|
69346
69452
|
cwd: params.cwd,
|
|
69347
69453
|
stdio: "pipe",
|
|
69348
69454
|
env: params.environment,
|
|
@@ -72342,6 +72448,77 @@ ${JSON.stringify(stats, null, 2)}`;
|
|
|
72342
72448
|
}, 0);
|
|
72343
72449
|
return { sessionId: session.sessionId, configOptions, modes };
|
|
72344
72450
|
}
|
|
72451
|
+
async resumeSession(params) {
|
|
72452
|
+
if (!isAbsolute11(params.cwd)) {
|
|
72453
|
+
throw RequestError7.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
|
|
72454
|
+
}
|
|
72455
|
+
this.sessions.close(params.sessionId);
|
|
72456
|
+
this.lastSessionCwd = params.cwd;
|
|
72457
|
+
const stored = this.findStoredSession(params.sessionId);
|
|
72458
|
+
if (!stored) {
|
|
72459
|
+
throw RequestError7.invalidParams(`Unknown sessionId: ${params.sessionId}`);
|
|
72460
|
+
}
|
|
72461
|
+
const session = await this.restoreSession(params.sessionId, {
|
|
72462
|
+
cwd: params.cwd,
|
|
72463
|
+
mcpServers: params.mcpServers
|
|
72464
|
+
});
|
|
72465
|
+
let configuration;
|
|
72466
|
+
try {
|
|
72467
|
+
configuration = await getSessionConfiguration(session.proc);
|
|
72468
|
+
} catch (err) {
|
|
72469
|
+
this.sessions.close(session.sessionId);
|
|
72470
|
+
throw err;
|
|
72471
|
+
}
|
|
72472
|
+
const { configOptions, models, modes } = configuration;
|
|
72473
|
+
const enableSkillCommands = getEnableSkillCommands(params.cwd, this.environment);
|
|
72474
|
+
const fileCommands = loadSlashCommands(params.cwd, this.environment);
|
|
72475
|
+
this.sessions.closeAllExcept?.(session.sessionId);
|
|
72476
|
+
this.store.upsert({
|
|
72477
|
+
sessionId: params.sessionId,
|
|
72478
|
+
cwd: params.cwd,
|
|
72479
|
+
sessionFile: stored.sessionFile
|
|
72480
|
+
});
|
|
72481
|
+
const response = {
|
|
72482
|
+
configOptions,
|
|
72483
|
+
models,
|
|
72484
|
+
modes,
|
|
72485
|
+
_meta: {
|
|
72486
|
+
piAcp: {
|
|
72487
|
+
startupInfo: null
|
|
72488
|
+
}
|
|
72489
|
+
}
|
|
72490
|
+
};
|
|
72491
|
+
setTimeout(() => {
|
|
72492
|
+
void (async () => {
|
|
72493
|
+
await session.publishContextUsage();
|
|
72494
|
+
try {
|
|
72495
|
+
const pi2 = await session.proc.getCommands();
|
|
72496
|
+
const { commands } = toAvailableCommandsFromPiGetCommands(pi2, {
|
|
72497
|
+
enableSkillCommands,
|
|
72498
|
+
includeExtensionCommands: false
|
|
72499
|
+
});
|
|
72500
|
+
await this.conn.sessionUpdate({
|
|
72501
|
+
sessionId: session.sessionId,
|
|
72502
|
+
update: {
|
|
72503
|
+
sessionUpdate: "available_commands_update",
|
|
72504
|
+
availableCommands: mergeCommands(commands, builtinAvailableCommands())
|
|
72505
|
+
}
|
|
72506
|
+
});
|
|
72507
|
+
return;
|
|
72508
|
+
} catch {
|
|
72509
|
+
}
|
|
72510
|
+
await this.conn.sessionUpdate({
|
|
72511
|
+
sessionId: session.sessionId,
|
|
72512
|
+
update: {
|
|
72513
|
+
sessionUpdate: "available_commands_update",
|
|
72514
|
+
availableCommands: mergeCommands(toAvailableCommands(fileCommands), builtinAvailableCommands())
|
|
72515
|
+
}
|
|
72516
|
+
});
|
|
72517
|
+
})().catch(() => {
|
|
72518
|
+
});
|
|
72519
|
+
}, 0);
|
|
72520
|
+
return response;
|
|
72521
|
+
}
|
|
72345
72522
|
async loadSession(params) {
|
|
72346
72523
|
if (!isAbsolute11(params.cwd)) {
|
|
72347
72524
|
throw RequestError7.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
|
|
@@ -72925,6 +73102,9 @@ var PiAcpEndpoint = class {
|
|
|
72925
73102
|
).onRequest(
|
|
72926
73103
|
methods5.agent.session.load,
|
|
72927
73104
|
async (context) => await piAgentOrThrow(piAgent).loadSession(context.params)
|
|
73105
|
+
).onRequest(
|
|
73106
|
+
methods5.agent.session.resume,
|
|
73107
|
+
async (context) => await piAgentOrThrow(piAgent).resumeSession(context.params)
|
|
72928
73108
|
).onRequest(
|
|
72929
73109
|
methods5.agent.session.list,
|
|
72930
73110
|
async (context) => await piAgentOrThrow(piAgent).listSessions(context.params)
|
|
@@ -73204,7 +73384,7 @@ var LocalAgentInventory = class {
|
|
|
73204
73384
|
};
|
|
73205
73385
|
|
|
73206
73386
|
// src/agent/discovery/acp-readiness-probe.ts
|
|
73207
|
-
import { spawn as
|
|
73387
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
73208
73388
|
import {
|
|
73209
73389
|
methods as methods8,
|
|
73210
73390
|
ndJsonStream as ndJsonStream2,
|
|
@@ -73395,7 +73575,7 @@ async function probeAcpReadiness(specification, agent, environment, defaultWorks
|
|
|
73395
73575
|
}
|
|
73396
73576
|
}
|
|
73397
73577
|
const launch = executableLaunch2(agent.adapterPath, agent.arguments);
|
|
73398
|
-
const child =
|
|
73578
|
+
const child = spawn6(launch.command, [...launch.arguments], {
|
|
73399
73579
|
cwd: defaultWorkspace,
|
|
73400
73580
|
...platformSpawnOptions,
|
|
73401
73581
|
env: { ...environment, ...agent.environment },
|
|
@@ -75008,7 +75188,7 @@ var ClaudeAdapter = class {
|
|
|
75008
75188
|
};
|
|
75009
75189
|
|
|
75010
75190
|
// src/acp/native-history/codex/codex-history.ts
|
|
75011
|
-
import { spawn as
|
|
75191
|
+
import { spawn as spawn7 } from "node:child_process";
|
|
75012
75192
|
|
|
75013
75193
|
// src/acp/protocol/native-session.ts
|
|
75014
75194
|
var path6 = external_exports.string().min(1).max(2048).refine((value) => !value.includes("\0"));
|
|
@@ -75705,7 +75885,7 @@ async function readCodexHistoryWithOptions(agent, cwd, nativeSessionId, signal,
|
|
|
75705
75885
|
}
|
|
75706
75886
|
signal.throwIfAborted();
|
|
75707
75887
|
const launch = executableLaunch2(agent.agentIdentity.realPath, ["app-server"]);
|
|
75708
|
-
const child =
|
|
75888
|
+
const child = spawn7(launch.command, [...launch.arguments], {
|
|
75709
75889
|
cwd,
|
|
75710
75890
|
env: { ...process.env, ...agent.environment },
|
|
75711
75891
|
...platformSpawnOptions,
|
|
@@ -81046,6 +81226,18 @@ var acpSession = sqliteTable("acp_session", {
|
|
|
81046
81226
|
updatedAt: text("updated_at").notNull()
|
|
81047
81227
|
});
|
|
81048
81228
|
|
|
81229
|
+
// src/schema/acp-session-store/execution-receipt.ts
|
|
81230
|
+
var executionReceipt = sqliteTable("execution_receipt", {
|
|
81231
|
+
commandId: text("command_id").primaryKey(),
|
|
81232
|
+
sessionId: text("session_id").notNull(),
|
|
81233
|
+
commandHash: text("command_hash").notNull(),
|
|
81234
|
+
attemptId: text("attempt_id").notNull(),
|
|
81235
|
+
state: text("state").notNull(),
|
|
81236
|
+
started: integer2("started", { mode: "boolean" }).notNull(),
|
|
81237
|
+
outcome: text("outcome"),
|
|
81238
|
+
updatedAt: text("updated_at").notNull()
|
|
81239
|
+
});
|
|
81240
|
+
|
|
81049
81241
|
// src/schema/acp-session-store/session-live-event-position-allocation.ts
|
|
81050
81242
|
var sessionLiveEventPositionAllocation = sqliteTable("session_live_event_position_allocation", {
|
|
81051
81243
|
allocatedPosition: integer2("allocated_position").notNull().default(1e4),
|
|
@@ -81087,6 +81279,62 @@ var AcpSessionTable = class {
|
|
|
81087
81279
|
};
|
|
81088
81280
|
};
|
|
81089
81281
|
|
|
81282
|
+
// src/storage/session/execution-receipt-table.ts
|
|
81283
|
+
var receiptFields = external_exports.object({
|
|
81284
|
+
commandId: external_exports.string(),
|
|
81285
|
+
sessionId: external_exports.string(),
|
|
81286
|
+
commandHash: external_exports.string(),
|
|
81287
|
+
attemptId: external_exports.string(),
|
|
81288
|
+
updatedAt: external_exports.string()
|
|
81289
|
+
});
|
|
81290
|
+
var receiptSchema = external_exports.discriminatedUnion("state", [
|
|
81291
|
+
receiptFields.extend({ state: external_exports.literal("dispatching"), started: external_exports.literal(false), outcome: external_exports.null() }),
|
|
81292
|
+
receiptFields.extend({ state: external_exports.literal("running"), started: external_exports.literal(true), outcome: external_exports.string().nullable() }),
|
|
81293
|
+
receiptFields.extend({
|
|
81294
|
+
state: external_exports.enum(["succeeded", "failed", "cancelled"]),
|
|
81295
|
+
started: external_exports.boolean(),
|
|
81296
|
+
outcome: external_exports.string().nullable()
|
|
81297
|
+
})
|
|
81298
|
+
]).readonly();
|
|
81299
|
+
var ExecutionReceiptTable = class {
|
|
81300
|
+
#database;
|
|
81301
|
+
constructor(database) {
|
|
81302
|
+
this.#database = database;
|
|
81303
|
+
}
|
|
81304
|
+
list = () => receiptSchema.array().parse(
|
|
81305
|
+
this.#database.orm.select().from(executionReceipt).orderBy(asc(executionReceipt.updatedAt), asc(executionReceipt.commandId)).all()
|
|
81306
|
+
);
|
|
81307
|
+
save = (receipt) => {
|
|
81308
|
+
this.#database.transaction(() => {
|
|
81309
|
+
this.#database.orm.insert(executionReceipt).values(receipt).onConflictDoUpdate({ target: executionReceipt.commandId, set: receipt }).run();
|
|
81310
|
+
if (receipt.state === "dispatching" || receipt.state === "running") {
|
|
81311
|
+
return;
|
|
81312
|
+
}
|
|
81313
|
+
const retained = this.#database.orm.select({ commandId: executionReceipt.commandId }).from(executionReceipt).where(
|
|
81314
|
+
and(
|
|
81315
|
+
eq2(executionReceipt.sessionId, receipt.sessionId),
|
|
81316
|
+
inArray(executionReceipt.state, ["succeeded", "failed", "cancelled"])
|
|
81317
|
+
)
|
|
81318
|
+
).orderBy(desc(executionReceipt.updatedAt), desc(executionReceipt.commandId)).limit(1024).all();
|
|
81319
|
+
if (retained.length === 1024) {
|
|
81320
|
+
this.#database.orm.delete(executionReceipt).where(
|
|
81321
|
+
and(
|
|
81322
|
+
eq2(executionReceipt.sessionId, receipt.sessionId),
|
|
81323
|
+
inArray(executionReceipt.state, ["succeeded", "failed", "cancelled"]),
|
|
81324
|
+
notInArray(
|
|
81325
|
+
executionReceipt.commandId,
|
|
81326
|
+
retained.map((row) => row.commandId)
|
|
81327
|
+
)
|
|
81328
|
+
)
|
|
81329
|
+
).run();
|
|
81330
|
+
}
|
|
81331
|
+
});
|
|
81332
|
+
};
|
|
81333
|
+
remove = (commandId) => {
|
|
81334
|
+
this.#database.orm.delete(executionReceipt).where(eq2(executionReceipt.commandId, commandId)).run();
|
|
81335
|
+
};
|
|
81336
|
+
};
|
|
81337
|
+
|
|
81090
81338
|
// src/storage/session/live-event-position-table.ts
|
|
81091
81339
|
var allocationRowSchema = external_exports.object({ allocatedPosition: external_exports.number().int().safe().nonnegative() });
|
|
81092
81340
|
var LiveEventPositionTable = class {
|
|
@@ -81306,6 +81554,10 @@ var acpSessionStoreMigrations = [
|
|
|
81306
81554
|
{
|
|
81307
81555
|
"name": "0006_live_event_position_allocation.sql",
|
|
81308
81556
|
"sql": "CREATE TABLE `session_live_event_position_allocation` (\n `allocated_position` integer DEFAULT 10000 NOT NULL,\n `session_id` text PRIMARY KEY NOT NULL\n);\n"
|
|
81557
|
+
},
|
|
81558
|
+
{
|
|
81559
|
+
"name": "0007_busy_excalibur.sql",
|
|
81560
|
+
"sql": "CREATE TABLE `execution_receipt` (\n `command_id` text PRIMARY KEY NOT NULL,\n `session_id` text NOT NULL,\n `command_hash` text NOT NULL,\n `attempt_id` text NOT NULL,\n `state` text NOT NULL,\n `started` integer NOT NULL,\n `outcome` text,\n `updated_at` text NOT NULL\n);\n"
|
|
81309
81561
|
}
|
|
81310
81562
|
];
|
|
81311
81563
|
|
|
@@ -81960,12 +82212,12 @@ var SessionEvents = class {
|
|
|
81960
82212
|
}
|
|
81961
82213
|
};
|
|
81962
82214
|
};
|
|
81963
|
-
function liveEvent(sessionId, sessionGenerationId, eventId, position, event) {
|
|
82215
|
+
function liveEvent(sessionId, sessionGenerationId, eventId, position, event, recordedAt = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
81964
82216
|
return {
|
|
81965
82217
|
eventId,
|
|
81966
82218
|
...event,
|
|
81967
82219
|
position: position.toString(),
|
|
81968
|
-
recordedAt
|
|
82220
|
+
recordedAt,
|
|
81969
82221
|
sessionGenerationId,
|
|
81970
82222
|
sessionId
|
|
81971
82223
|
};
|
|
@@ -82003,7 +82255,7 @@ var MemorySessionEventStore = class {
|
|
|
82003
82255
|
}
|
|
82004
82256
|
return resolved;
|
|
82005
82257
|
};
|
|
82006
|
-
append = (sessionId, event) => {
|
|
82258
|
+
append = (sessionId, event, recordedAt) => {
|
|
82007
82259
|
const session = this.#session(sessionId);
|
|
82008
82260
|
const allocatedPosition = this.#allocatedPositionBySession.get(sessionId) ?? 9999;
|
|
82009
82261
|
if (allocatedPosition === Number.MAX_SAFE_INTEGER) {
|
|
@@ -82016,7 +82268,8 @@ var MemorySessionEventStore = class {
|
|
|
82016
82268
|
session.sessionGenerationId,
|
|
82017
82269
|
this.#eventIds.allocate(sessionId, session.sessionGenerationId),
|
|
82018
82270
|
position,
|
|
82019
|
-
event
|
|
82271
|
+
event,
|
|
82272
|
+
recordedAt
|
|
82020
82273
|
);
|
|
82021
82274
|
session.apply(recorded, this.#resolver(session));
|
|
82022
82275
|
return recorded;
|
|
@@ -82057,12 +82310,14 @@ var MemorySessionEventStore = class {
|
|
|
82057
82310
|
};
|
|
82058
82311
|
};
|
|
82059
82312
|
var CachedSessionEventStore = class {
|
|
82313
|
+
#terminalOutcomes;
|
|
82060
82314
|
#cacheTable;
|
|
82061
82315
|
#eventIds;
|
|
82062
82316
|
#liveEventPositions;
|
|
82063
82317
|
#sessions = /* @__PURE__ */ new Map();
|
|
82064
82318
|
#flushSchedule = { kind: "idle" };
|
|
82065
|
-
constructor(cacheTable, liveEventPositions, eventIds = new InMemorySessionEventIdAllocator()) {
|
|
82319
|
+
constructor(cacheTable, liveEventPositions, eventIds = new InMemorySessionEventIdAllocator(), terminalOutcomes = () => []) {
|
|
82320
|
+
this.#terminalOutcomes = terminalOutcomes;
|
|
82066
82321
|
this.#eventIds = eventIds;
|
|
82067
82322
|
this.#liveEventPositions = liveEventPositions;
|
|
82068
82323
|
this.#cacheTable = cacheTable;
|
|
@@ -82095,7 +82350,7 @@ var CachedSessionEventStore = class {
|
|
|
82095
82350
|
}
|
|
82096
82351
|
return resolved;
|
|
82097
82352
|
};
|
|
82098
|
-
append = (sessionId, event) => {
|
|
82353
|
+
append = (sessionId, event, recordedAt) => {
|
|
82099
82354
|
if (this.#flushSchedule.kind === "closed") {
|
|
82100
82355
|
throw new Error("The V2 Session event store is closed");
|
|
82101
82356
|
}
|
|
@@ -82106,7 +82361,8 @@ var CachedSessionEventStore = class {
|
|
|
82106
82361
|
session.sessionGenerationId,
|
|
82107
82362
|
this.#eventIds.allocate(sessionId, session.sessionGenerationId),
|
|
82108
82363
|
position,
|
|
82109
|
-
event
|
|
82364
|
+
event,
|
|
82365
|
+
recordedAt
|
|
82110
82366
|
);
|
|
82111
82367
|
session.apply(recorded, this.#resolver(sessionId, session));
|
|
82112
82368
|
this.#sessions.set(sessionId, session);
|
|
@@ -82195,6 +82451,9 @@ var CachedSessionEventStore = class {
|
|
|
82195
82451
|
this.#deletePersisted(sessionId, previous?.sessionGenerationId);
|
|
82196
82452
|
const sessionGenerationId = randomUUID11();
|
|
82197
82453
|
this.#sessions.set(sessionId, new SessionEvents(sessionGenerationId));
|
|
82454
|
+
for (const { event, recordedAt } of this.#terminalOutcomes(sessionId)) {
|
|
82455
|
+
this.append(sessionId, event, recordedAt);
|
|
82456
|
+
}
|
|
82198
82457
|
};
|
|
82199
82458
|
materializedEventCount = (sessionId) => this.#sessions.get(sessionId)?.materializedCount ?? 0;
|
|
82200
82459
|
close = () => {
|
|
@@ -82308,7 +82567,7 @@ function buildPromptContent(options, capabilities) {
|
|
|
82308
82567
|
}
|
|
82309
82568
|
|
|
82310
82569
|
// src/acp/connection/agent-connection.ts
|
|
82311
|
-
import { spawn as
|
|
82570
|
+
import { spawn as spawn8 } from "node:child_process";
|
|
82312
82571
|
import { ndJsonStream as ndJsonStream3, RequestError as RequestError9 } from "@agentclientprotocol/sdk";
|
|
82313
82572
|
function requestErrorMessage(error62) {
|
|
82314
82573
|
const fallback = truncate(error62.message, 500);
|
|
@@ -82418,7 +82677,7 @@ var AgentConnection = class {
|
|
|
82418
82677
|
return;
|
|
82419
82678
|
}
|
|
82420
82679
|
const launch = executableLaunch2(agent.adapterPath, agent.arguments);
|
|
82421
|
-
const child =
|
|
82680
|
+
const child = spawn8(launch.command, [...launch.arguments], {
|
|
82422
82681
|
cwd,
|
|
82423
82682
|
...platformSpawnOptions,
|
|
82424
82683
|
env: { ...process.env, ...agent.environment },
|
|
@@ -83692,6 +83951,19 @@ var RunningAgentTurn = class extends AgentTurnState {
|
|
|
83692
83951
|
|
|
83693
83952
|
// src/session/live/session-restore.ts
|
|
83694
83953
|
import { methods as methods10 } from "@agentclientprotocol/sdk";
|
|
83954
|
+
function hasMethodNotFoundCode(cause) {
|
|
83955
|
+
const visited = /* @__PURE__ */ new Set();
|
|
83956
|
+
let current = cause;
|
|
83957
|
+
while ((current instanceof Error || typeof current === "object" && current !== null) && !visited.has(current)) {
|
|
83958
|
+
visited.add(current);
|
|
83959
|
+
const code = Reflect.get(current, "code");
|
|
83960
|
+
if (code === -32601 || code === "METHOD_NOT_FOUND" || code === "method_not_found") {
|
|
83961
|
+
return true;
|
|
83962
|
+
}
|
|
83963
|
+
current = current instanceof Error ? current.cause : void 0;
|
|
83964
|
+
}
|
|
83965
|
+
return false;
|
|
83966
|
+
}
|
|
83695
83967
|
async function restoreSession(session, signal, recovery, origin) {
|
|
83696
83968
|
if (origin !== void 0) {
|
|
83697
83969
|
session.setSessionTitle(origin.title);
|
|
@@ -83758,6 +84030,9 @@ async function restoreSession(session, signal, recovery, origin) {
|
|
|
83758
84030
|
}
|
|
83759
84031
|
session.setPrompted(true);
|
|
83760
84032
|
session.setRestored(true);
|
|
84033
|
+
if (recovery.kind === "execution-only") {
|
|
84034
|
+
session.startExecutionOnlyCapture();
|
|
84035
|
+
}
|
|
83761
84036
|
lifecycleResponse2 = forked;
|
|
83762
84037
|
} else if (stored instanceof FoundStoredSession && stored.session.agentId === session.agentId && stored.session.cwd === session.cwd && arraysEqual(stored.session.additionalDirectories, session.additionalDirectories)) {
|
|
83763
84038
|
session.selectNativeSession(stored.session.nativeSessionId);
|
|
@@ -83776,6 +84051,37 @@ async function restoreSession(session, signal, recovery, origin) {
|
|
|
83776
84051
|
"session-load",
|
|
83777
84052
|
async () => (await session.loadSession(signal, "ACP agent exited while loading a session")).response
|
|
83778
84053
|
);
|
|
84054
|
+
} else if (recovery.kind === "execution-only") {
|
|
84055
|
+
try {
|
|
84056
|
+
lifecycleResponse2 = await session.metrics.measure(
|
|
84057
|
+
"session-resume",
|
|
84058
|
+
async () => await session.race(
|
|
84059
|
+
session.agentRequest(
|
|
84060
|
+
methods10.agent.session.resume,
|
|
84061
|
+
{
|
|
84062
|
+
additionalDirectories: [...session.additionalDirectories],
|
|
84063
|
+
cwd: session.cwd,
|
|
84064
|
+
mcpServers: [],
|
|
84065
|
+
sessionId: session.nativeSessionId()
|
|
84066
|
+
},
|
|
84067
|
+
{ cancellationSignal: signal }
|
|
84068
|
+
),
|
|
84069
|
+
"ACP agent exited while resuming a session",
|
|
84070
|
+
signal
|
|
84071
|
+
)
|
|
84072
|
+
);
|
|
84073
|
+
} catch (cause) {
|
|
84074
|
+
signal.throwIfAborted();
|
|
84075
|
+
if (cause instanceof AcpExecutionError && !hasMethodNotFoundCode(cause)) {
|
|
84076
|
+
throw cause;
|
|
84077
|
+
}
|
|
84078
|
+
throw new AcpExecutionError(
|
|
84079
|
+
"This Agent cannot continue a persisted session without replaying native history",
|
|
84080
|
+
{ cause },
|
|
84081
|
+
"execution_only_unsupported"
|
|
84082
|
+
);
|
|
84083
|
+
}
|
|
84084
|
+
session.startExecutionOnlyCapture();
|
|
83779
84085
|
} else if (session.capabilities.resumeSession) {
|
|
83780
84086
|
lifecycleResponse2 = await session.metrics.measure(
|
|
83781
84087
|
"session-resume",
|
|
@@ -83835,6 +84141,9 @@ async function restoreSession(session, signal, recovery, origin) {
|
|
|
83835
84141
|
);
|
|
83836
84142
|
session.selectNativeSession(created.sessionId);
|
|
83837
84143
|
session.setNativeHistoryOwnership({ kind: "fresh-session" });
|
|
84144
|
+
if (recovery.kind === "execution-only") {
|
|
84145
|
+
session.startExecutionOnlyCapture();
|
|
84146
|
+
}
|
|
83838
84147
|
lifecycleResponse2 = created;
|
|
83839
84148
|
}
|
|
83840
84149
|
session.restrictSessionCapabilities(lifecycleResponse2);
|
|
@@ -84112,6 +84421,16 @@ var AgentSession = class _AgentSession {
|
|
|
84112
84421
|
}
|
|
84113
84422
|
await this.#completedHistory(signal, "ACP agent exited while loading history");
|
|
84114
84423
|
};
|
|
84424
|
+
/** Starts live event capture without asking the native Agent to replay its persisted history. */
|
|
84425
|
+
startExecutionOnlyCapture = () => {
|
|
84426
|
+
if (this.#sessionLoad.kind !== "not-requested") {
|
|
84427
|
+
return;
|
|
84428
|
+
}
|
|
84429
|
+
this.#sessionLoad = {
|
|
84430
|
+
history: new HistoryReplayCapture(this.#store.events, this.#mobiusSessionId),
|
|
84431
|
+
kind: "execution-only"
|
|
84432
|
+
};
|
|
84433
|
+
};
|
|
84115
84434
|
loadHistoryEvents = async (eventLimit, cursor, signal) => {
|
|
84116
84435
|
if (!this.#capabilities.loadSession) {
|
|
84117
84436
|
throw new AcpExecutionError(
|
|
@@ -84362,7 +84681,7 @@ var AgentSession = class _AgentSession {
|
|
|
84362
84681
|
response: {}
|
|
84363
84682
|
};
|
|
84364
84683
|
}
|
|
84365
|
-
if (this.#capabilities.loadSession) {
|
|
84684
|
+
if (this.#capabilities.loadSession && this.#sessionLoad.kind !== "execution-only") {
|
|
84366
84685
|
await this.#completedHistory(options.signal, "ACP agent exited while loading history before a prompt");
|
|
84367
84686
|
}
|
|
84368
84687
|
const prompt = this.buildPrompt(options);
|
|
@@ -84561,14 +84880,14 @@ var AgentSession = class _AgentSession {
|
|
|
84561
84880
|
onElicitationComplete = (notification) => this.#interactions.onElicitationComplete(notification);
|
|
84562
84881
|
onUpdate = (notification) => this.#updates.receive(notification);
|
|
84563
84882
|
recordControlEvent = async (event) => {
|
|
84564
|
-
if (this.#sessionLoad.kind !== "loaded") {
|
|
84883
|
+
if (this.#sessionLoad.kind !== "loaded" && this.#sessionLoad.kind !== "execution-only") {
|
|
84565
84884
|
return false;
|
|
84566
84885
|
}
|
|
84567
84886
|
await this.recordLifecycleEvent(event);
|
|
84568
84887
|
return true;
|
|
84569
84888
|
};
|
|
84570
84889
|
recordLifecycleEvent = async (event) => {
|
|
84571
|
-
if (event.type !== "lifecycle-metadata" || this.#sessionLoad.kind !== "loaded") {
|
|
84890
|
+
if (event.type !== "lifecycle-metadata" || this.#sessionLoad.kind !== "loaded" && this.#sessionLoad.kind !== "execution-only") {
|
|
84572
84891
|
return;
|
|
84573
84892
|
}
|
|
84574
84893
|
const liveEvent2 = this.#sessionLoad.history.recordLifecycle(event);
|
|
@@ -84589,7 +84908,7 @@ var AgentSession = class _AgentSession {
|
|
|
84589
84908
|
const rawUpdate = decodeAcpSessionUpdate(JSON.stringify(externalized.event));
|
|
84590
84909
|
if (this.#sessionLoad.kind === "capturing") {
|
|
84591
84910
|
await this.#sessionLoad.history.record(update, rawUpdate);
|
|
84592
|
-
} else if (this.#sessionLoad.kind === "loaded") {
|
|
84911
|
+
} else if (this.#sessionLoad.kind === "loaded" || this.#sessionLoad.kind === "execution-only") {
|
|
84593
84912
|
const onSessionEvent = this.#getObserver().onSessionEvent;
|
|
84594
84913
|
await this.#sessionLoad.history.record(update, rawUpdate, async (liveEvent2) => {
|
|
84595
84914
|
await onSessionEvent?.(liveEvent2);
|
|
@@ -85507,13 +85826,14 @@ var SessionManager2 = class {
|
|
|
85507
85826
|
}
|
|
85508
85827
|
async #replaceExecutionPreparation(existing, options) {
|
|
85509
85828
|
const desiredConfigOptions = existing.prepared().configOptions;
|
|
85829
|
+
const recovery = options.recovery ?? { kind: "interactive-only" };
|
|
85510
85830
|
return await this.#executionProcesses.prepare(options.sessionId, async () => {
|
|
85511
85831
|
await this.#retireSessionProcess(options.sessionId, existing, async () => await existing.close());
|
|
85512
85832
|
const runtime = await this.#startRetainedSessionProcess(
|
|
85513
85833
|
options,
|
|
85514
85834
|
async () => await AgentSession.start(
|
|
85515
85835
|
options,
|
|
85516
|
-
|
|
85836
|
+
recovery,
|
|
85517
85837
|
() => this.#observer,
|
|
85518
85838
|
this.#store,
|
|
85519
85839
|
unmeasuredOperationMetrics,
|
|
@@ -85691,6 +86011,7 @@ var SessionManager2 = class {
|
|
|
85691
86011
|
});
|
|
85692
86012
|
});
|
|
85693
86013
|
prepareExecutionSession = async (options) => this.#operations.run(options, async (options2) => {
|
|
86014
|
+
const recovery = options2.recovery ?? { kind: "interactive-only" };
|
|
85694
86015
|
this.#assertOpen(options2.sessionId);
|
|
85695
86016
|
const pending = this.#executionProcesses.pending(options2.sessionId);
|
|
85696
86017
|
if (pending !== void 0) {
|
|
@@ -85699,7 +86020,7 @@ var SessionManager2 = class {
|
|
|
85699
86020
|
}
|
|
85700
86021
|
const existing = this.#executionProcesses.get(options2.sessionId);
|
|
85701
86022
|
if (existing === void 0) {
|
|
85702
|
-
return (await this.#startPreparation(options2,
|
|
86023
|
+
return (await this.#startPreparation(options2, recovery)).prepared();
|
|
85703
86024
|
}
|
|
85704
86025
|
if (!existing.belongsTo(options2.agent.id, options2.cwd, options2.additionalDirectories)) {
|
|
85705
86026
|
throw new AcpExecutionError(
|
|
@@ -85709,6 +86030,9 @@ var SessionManager2 = class {
|
|
|
85709
86030
|
);
|
|
85710
86031
|
}
|
|
85711
86032
|
if (existing.usesEnvironment(options2.agent.environment)) {
|
|
86033
|
+
if (recovery.kind === "execution-only") {
|
|
86034
|
+
existing.startExecutionOnlyCapture();
|
|
86035
|
+
}
|
|
85712
86036
|
this.#executionProcesses.touch(options2.sessionId, existing);
|
|
85713
86037
|
return existing.prepared();
|
|
85714
86038
|
}
|
|
@@ -86003,10 +86327,13 @@ var SessionManager2 = class {
|
|
|
86003
86327
|
"session_identity_mismatch"
|
|
86004
86328
|
);
|
|
86005
86329
|
}
|
|
86330
|
+
if (options2.recovery?.kind === "execution-only") {
|
|
86331
|
+
existing.startExecutionOnlyCapture();
|
|
86332
|
+
}
|
|
86006
86333
|
this.#executionProcesses.touch(options2.sessionId, existing);
|
|
86007
86334
|
return existing;
|
|
86008
86335
|
}
|
|
86009
|
-
await this
|
|
86336
|
+
await this.#prepareSession(options2, options2.recovery ?? { kind: "interactive-only" }, "reopen");
|
|
86010
86337
|
const started = this.#executionProcesses.get(options2.sessionId);
|
|
86011
86338
|
if (started === void 0) {
|
|
86012
86339
|
throw new AcpExecutionError("ACP session did not start");
|
|
@@ -86609,6 +86936,13 @@ var PromptLifecycle = class {
|
|
|
86609
86936
|
}
|
|
86610
86937
|
this.#queued.delete(commandId);
|
|
86611
86938
|
};
|
|
86939
|
+
replayOutcome = async (sessionId, event) => {
|
|
86940
|
+
if (event.type !== "lifecycle-metadata" || !("commandId" in event.payload)) {
|
|
86941
|
+
return;
|
|
86942
|
+
}
|
|
86943
|
+
await this.#recordLifecycle(sessionId, event);
|
|
86944
|
+
this.publishTerminal(sessionId, event.payload.commandId);
|
|
86945
|
+
};
|
|
86612
86946
|
queueChanged = async (sessionId) => {
|
|
86613
86947
|
await this.#recordLifecycle(sessionId, {
|
|
86614
86948
|
type: "lifecycle-metadata",
|
|
@@ -86642,7 +86976,7 @@ var PromptLifecycle = class {
|
|
|
86642
86976
|
type: "lifecycle-metadata",
|
|
86643
86977
|
payload: { kind: "prompt.failed-before-start", commandId, code, message }
|
|
86644
86978
|
});
|
|
86645
|
-
if (!recorded) {
|
|
86979
|
+
if (!recorded || code === SESSION_CLOSED_ERROR_CODE) {
|
|
86646
86980
|
this.#sink.publishOperationFailure(sessionId, commandId, code, message);
|
|
86647
86981
|
}
|
|
86648
86982
|
};
|
|
@@ -86679,18 +87013,149 @@ function isTerminal(state) {
|
|
|
86679
87013
|
}
|
|
86680
87014
|
var ExecutionReceipts = class {
|
|
86681
87015
|
#executions = /* @__PURE__ */ new Map();
|
|
87016
|
+
#recoveredCommands = /* @__PURE__ */ new Set();
|
|
86682
87017
|
#terminalCountBySession = /* @__PURE__ */ new Map();
|
|
87018
|
+
#table;
|
|
87019
|
+
#closing = false;
|
|
87020
|
+
#activeCount = 0;
|
|
87021
|
+
#onCount;
|
|
87022
|
+
constructor(table, onCount = () => void 0) {
|
|
87023
|
+
this.#onCount = onCount;
|
|
87024
|
+
this.#table = table;
|
|
87025
|
+
for (const row of table?.list() ?? []) {
|
|
87026
|
+
this.#executions.set(row.commandId, row);
|
|
87027
|
+
this.#recoveredCommands.add(row.commandId);
|
|
87028
|
+
if (!isTerminal(row.state)) {
|
|
87029
|
+
this.#activeCount += 1;
|
|
87030
|
+
}
|
|
87031
|
+
if (isTerminal(row.state)) {
|
|
87032
|
+
this.#terminalCountBySession.set(
|
|
87033
|
+
row.sessionId,
|
|
87034
|
+
(this.#terminalCountBySession.get(row.sessionId) ?? 0) + 1
|
|
87035
|
+
);
|
|
87036
|
+
}
|
|
87037
|
+
}
|
|
87038
|
+
}
|
|
87039
|
+
#save = (commandId, receipt) => {
|
|
87040
|
+
if (!this.#closing) {
|
|
87041
|
+
this.#table?.save({ ...receipt, commandId, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
87042
|
+
}
|
|
87043
|
+
const previous = this.#executions.get(commandId);
|
|
87044
|
+
const wasActive = previous !== void 0 && !isTerminal(previous.state);
|
|
87045
|
+
if (isTerminal(receipt.state)) {
|
|
87046
|
+
this.#executions.delete(commandId);
|
|
87047
|
+
}
|
|
87048
|
+
this.#executions.set(commandId, receipt);
|
|
87049
|
+
this.#activeCount += Number(!isTerminal(receipt.state)) - Number(wasActive);
|
|
87050
|
+
this.#onCount(this.#activeCount);
|
|
87051
|
+
if (isTerminal(receipt.state) && (previous === void 0 || !isTerminal(previous.state))) {
|
|
87052
|
+
this.#terminalCountBySession.set(
|
|
87053
|
+
receipt.sessionId,
|
|
87054
|
+
(this.#terminalCountBySession.get(receipt.sessionId) ?? 0) + 1
|
|
87055
|
+
);
|
|
87056
|
+
this.pruneTerminalReceipts(receipt.sessionId);
|
|
87057
|
+
}
|
|
87058
|
+
};
|
|
87059
|
+
beginShutdown = () => {
|
|
87060
|
+
this.#closing = true;
|
|
87061
|
+
};
|
|
87062
|
+
outcome = (commandId) => {
|
|
87063
|
+
const receipt = this.#executions.get(commandId);
|
|
87064
|
+
return receipt?.outcome === null || receipt === void 0 ? void 0 : sessionEventPayloadSchema.parse(JSON.parse(receipt.outcome));
|
|
87065
|
+
};
|
|
87066
|
+
recordOutcome = (event) => {
|
|
87067
|
+
if (event.type !== "lifecycle-metadata") {
|
|
87068
|
+
return;
|
|
87069
|
+
}
|
|
87070
|
+
const payload = event.payload;
|
|
87071
|
+
if (payload.kind !== "prompt.completed" && payload.kind !== "prompt.failed" && payload.kind !== "prompt.failed-before-start") {
|
|
87072
|
+
return;
|
|
87073
|
+
}
|
|
87074
|
+
const receipt = this.#executions.get(payload.commandId);
|
|
87075
|
+
if (receipt === void 0) {
|
|
87076
|
+
return;
|
|
87077
|
+
}
|
|
87078
|
+
const sanitized = payload.kind === "prompt.completed" ? payload : { ...payload, message: "The local Agent could not complete the request" };
|
|
87079
|
+
this.#save(payload.commandId, {
|
|
87080
|
+
...receipt,
|
|
87081
|
+
state: payload.kind === "prompt.completed" ? payload.stopReason === "cancelled" ? "cancelled" : "succeeded" : "failed",
|
|
87082
|
+
outcome: JSON.stringify({ type: "lifecycle-metadata", payload: sanitized, recordedAt: event.recordedAt })
|
|
87083
|
+
});
|
|
87084
|
+
};
|
|
87085
|
+
recover = () => {
|
|
87086
|
+
const recovered = [];
|
|
87087
|
+
for (const [commandId, receipt] of [...this.#executions]) {
|
|
87088
|
+
const event = receipt.outcome === null ? {
|
|
87089
|
+
type: "lifecycle-metadata",
|
|
87090
|
+
payload: receipt.started ? {
|
|
87091
|
+
kind: "prompt.failed",
|
|
87092
|
+
commandId,
|
|
87093
|
+
attemptId: receipt.attemptId,
|
|
87094
|
+
code: "runtime_restarted",
|
|
87095
|
+
message: "The local runtime restarted while this request was running"
|
|
87096
|
+
} : {
|
|
87097
|
+
kind: "prompt.failed-before-start",
|
|
87098
|
+
commandId,
|
|
87099
|
+
code: "runtime_restarted",
|
|
87100
|
+
message: "The local runtime restarted before this request started"
|
|
87101
|
+
}
|
|
87102
|
+
} : sessionEventPayloadSchema.parse(JSON.parse(receipt.outcome));
|
|
87103
|
+
const recordedAt = receipt.outcome === null ? (/* @__PURE__ */ new Date()).toISOString() : external_exports.object({ recordedAt: external_exports.string() }).parse(JSON.parse(receipt.outcome)).recordedAt;
|
|
87104
|
+
recovered.push({ sessionId: receipt.sessionId, event, recordedAt });
|
|
87105
|
+
if (!isTerminal(receipt.state)) {
|
|
87106
|
+
const state = event.type === "lifecycle-metadata" && event.payload.kind === "prompt.completed" ? event.payload.stopReason === "cancelled" ? "cancelled" : "succeeded" : "failed";
|
|
87107
|
+
this.#save(commandId, { ...receipt, state, outcome: JSON.stringify({ ...event, recordedAt }) });
|
|
87108
|
+
}
|
|
87109
|
+
}
|
|
87110
|
+
return recovered;
|
|
87111
|
+
};
|
|
87112
|
+
terminalOutcomes = (sessionId) => [...this.#executions.values()].flatMap((receipt) => {
|
|
87113
|
+
if (receipt.sessionId !== sessionId || receipt.outcome === null) {
|
|
87114
|
+
return [];
|
|
87115
|
+
}
|
|
87116
|
+
const decoded = JSON.parse(receipt.outcome);
|
|
87117
|
+
return [
|
|
87118
|
+
{
|
|
87119
|
+
event: sessionEventPayloadSchema.parse(decoded),
|
|
87120
|
+
recordedAt: external_exports.object({ recordedAt: external_exports.string() }).parse(decoded).recordedAt
|
|
87121
|
+
}
|
|
87122
|
+
];
|
|
87123
|
+
});
|
|
86683
87124
|
claimExecution = (commandId, sessionId, commandJson) => {
|
|
86684
87125
|
const commandHash = createHash6("sha256").update(commandJson).digest("hex");
|
|
86685
|
-
|
|
87126
|
+
let existing = this.#executions.get(commandId);
|
|
87127
|
+
const previous = this.outcome(commandId);
|
|
87128
|
+
if (existing?.sessionId === sessionId && !existing.started && previous?.type === "lifecycle-metadata" && previous.payload.kind === "prompt.failed-before-start" && previous.payload.code === "runtime_restarted") {
|
|
87129
|
+
this.#executions.delete(commandId);
|
|
87130
|
+
this.#recoveredCommands.delete(commandId);
|
|
87131
|
+
this.#table?.remove(commandId);
|
|
87132
|
+
this.#terminalCountBySession.set(
|
|
87133
|
+
sessionId,
|
|
87134
|
+
Math.max(0, (this.#terminalCountBySession.get(sessionId) ?? 1) - 1)
|
|
87135
|
+
);
|
|
87136
|
+
existing = void 0;
|
|
87137
|
+
}
|
|
86686
87138
|
if (existing !== void 0) {
|
|
86687
87139
|
if (existing.sessionId !== sessionId || existing.commandHash !== commandHash) {
|
|
86688
87140
|
return { kind: "conflict" };
|
|
86689
87141
|
}
|
|
86690
|
-
return {
|
|
87142
|
+
return {
|
|
87143
|
+
attemptId: existing.attemptId,
|
|
87144
|
+
commandId,
|
|
87145
|
+
kind: "duplicate",
|
|
87146
|
+
state: existing.state,
|
|
87147
|
+
outcome: this.#recoveredCommands.has(commandId) ? this.outcome(commandId) : void 0
|
|
87148
|
+
};
|
|
86691
87149
|
}
|
|
86692
87150
|
const attemptId = randomUUID13();
|
|
86693
|
-
this.#
|
|
87151
|
+
this.#save(commandId, {
|
|
87152
|
+
attemptId,
|
|
87153
|
+
commandHash,
|
|
87154
|
+
sessionId,
|
|
87155
|
+
state: "dispatching",
|
|
87156
|
+
started: false,
|
|
87157
|
+
outcome: null
|
|
87158
|
+
});
|
|
86694
87159
|
return { attemptId, commandId, kind: "accepted", state: "dispatching" };
|
|
86695
87160
|
};
|
|
86696
87161
|
transitionExecution = (commandId, state) => {
|
|
@@ -86705,16 +87170,13 @@ var ExecutionReceipts = class {
|
|
|
86705
87170
|
if (!allowed) {
|
|
86706
87171
|
throw new Error("The runtime execution transition is invalid");
|
|
86707
87172
|
}
|
|
86708
|
-
|
|
86709
|
-
|
|
86710
|
-
|
|
86711
|
-
|
|
86712
|
-
(this.#terminalCountBySession.get(current.sessionId) ?? 0) + 1
|
|
86713
|
-
);
|
|
86714
|
-
this.pruneTerminalReceipts(current.sessionId);
|
|
87173
|
+
if (state === "running") {
|
|
87174
|
+
this.#save(commandId, { ...current, state, started: true });
|
|
87175
|
+
} else if (isTerminal(state)) {
|
|
87176
|
+
this.#save(commandId, { ...current, state });
|
|
86715
87177
|
}
|
|
86716
87178
|
};
|
|
86717
|
-
/**
|
|
87179
|
+
/** Only commands without a terminal result can still be cancelled. */
|
|
86718
87180
|
findUnsettledAttemptId = (commandId, sessionId) => {
|
|
86719
87181
|
const receipt = this.#executions.get(commandId);
|
|
86720
87182
|
return receipt?.sessionId === sessionId && !isTerminal(receipt.state) ? receipt.attemptId : null;
|
|
@@ -86725,7 +87187,9 @@ var ExecutionReceipts = class {
|
|
|
86725
87187
|
};
|
|
86726
87188
|
close = () => {
|
|
86727
87189
|
this.#executions.clear();
|
|
87190
|
+
this.#recoveredCommands.clear();
|
|
86728
87191
|
this.#terminalCountBySession.clear();
|
|
87192
|
+
this.#activeCount = 0;
|
|
86729
87193
|
};
|
|
86730
87194
|
pruneTerminalReceipts = (sessionId) => {
|
|
86731
87195
|
if ((this.#terminalCountBySession.get(sessionId) ?? 0) <= MAX_TERMINAL_RECEIPTS) {
|
|
@@ -86734,6 +87198,8 @@ var ExecutionReceipts = class {
|
|
|
86734
87198
|
for (const [commandId, receipt] of this.#executions) {
|
|
86735
87199
|
if (receipt.sessionId === sessionId && isTerminal(receipt.state)) {
|
|
86736
87200
|
this.#executions.delete(commandId);
|
|
87201
|
+
this.#recoveredCommands.delete(commandId);
|
|
87202
|
+
this.#table?.remove(commandId);
|
|
86737
87203
|
const remaining = (this.#terminalCountBySession.get(sessionId) ?? 1) - 1;
|
|
86738
87204
|
if (remaining > 0) {
|
|
86739
87205
|
this.#terminalCountBySession.set(sessionId, remaining);
|
|
@@ -87261,10 +87727,14 @@ function buildSessionLayer(options) {
|
|
|
87261
87727
|
const databases = channelSessionDatabasePaths(stateDirectory, channelId);
|
|
87262
87728
|
const sessionDatabase = openAcpSessionDatabase(databases.sessions);
|
|
87263
87729
|
let events;
|
|
87730
|
+
let operations;
|
|
87264
87731
|
try {
|
|
87732
|
+
operations = new ExecutionReceipts(new ExecutionReceiptTable(sessionDatabase), options.onExecutionCountChange);
|
|
87265
87733
|
events = new CachedSessionEventStore(
|
|
87266
87734
|
new SessionEventCacheTable(openSessionEventCacheDatabase(databases.events)),
|
|
87267
|
-
new SqliteSessionLiveEventPosition(new LiveEventPositionTable(sessionDatabase))
|
|
87735
|
+
new SqliteSessionLiveEventPosition(new LiveEventPositionTable(sessionDatabase)),
|
|
87736
|
+
void 0,
|
|
87737
|
+
(sessionId) => operations.terminalOutcomes(sessionId)
|
|
87268
87738
|
);
|
|
87269
87739
|
} catch (error62) {
|
|
87270
87740
|
sessionDatabase.close();
|
|
@@ -87272,11 +87742,13 @@ function buildSessionLayer(options) {
|
|
|
87272
87742
|
}
|
|
87273
87743
|
const sessionStore = new SqliteSessionStore(new AcpSessionTable(sessionDatabase), events);
|
|
87274
87744
|
const externalContent = new LocalExternalContentStore(stateDirectory);
|
|
87275
|
-
const operations = new ExecutionReceipts();
|
|
87276
87745
|
const activeSessions = new SessionTurns(operations, options.turnActivity);
|
|
87277
87746
|
const directories = new WorkspaceDirectoryService(bindingId, defaultWorkspace);
|
|
87278
87747
|
const manager = new SessionManager2({
|
|
87279
|
-
observer: new SessionLayerObserver((event) =>
|
|
87748
|
+
observer: new SessionLayerObserver((event) => {
|
|
87749
|
+
operations.recordOutcome(event);
|
|
87750
|
+
eventProjection.record(event);
|
|
87751
|
+
}, sink.publishInfo),
|
|
87280
87752
|
store: sessionStore,
|
|
87281
87753
|
adapters: harnessAdapters,
|
|
87282
87754
|
sessionIdentity: "native",
|
|
@@ -87297,7 +87769,15 @@ function buildSessionLayer(options) {
|
|
|
87297
87769
|
});
|
|
87298
87770
|
const eventProjection = new PromptLifecycle(
|
|
87299
87771
|
sink,
|
|
87300
|
-
(sessionId, event) =>
|
|
87772
|
+
async (sessionId, event) => {
|
|
87773
|
+
if (await manager.recordLifecycleEvent(sessionId, event)) {
|
|
87774
|
+
return true;
|
|
87775
|
+
}
|
|
87776
|
+
const recorded = events.append(sessionId, event);
|
|
87777
|
+
operations.recordOutcome(recorded);
|
|
87778
|
+
eventProjection.record(recorded);
|
|
87779
|
+
return true;
|
|
87780
|
+
},
|
|
87301
87781
|
activeSessions.recordSessionEvent
|
|
87302
87782
|
);
|
|
87303
87783
|
const nativeSessions = new NativeSessionService(
|
|
@@ -87320,7 +87800,13 @@ function buildSessionLayer(options) {
|
|
|
87320
87800
|
);
|
|
87321
87801
|
})
|
|
87322
87802
|
);
|
|
87803
|
+
const recoveredEvents = operations.recover().map(({ sessionId, event, recordedAt }) => events.append(sessionId, event, recordedAt));
|
|
87323
87804
|
return {
|
|
87805
|
+
publishRecoveredOutcomes: () => {
|
|
87806
|
+
for (const event of recoveredEvents) {
|
|
87807
|
+
sink.publish(event);
|
|
87808
|
+
}
|
|
87809
|
+
},
|
|
87324
87810
|
activeSessions,
|
|
87325
87811
|
directories,
|
|
87326
87812
|
eventProjection,
|
|
@@ -89117,12 +89603,14 @@ async function executePrompt({
|
|
|
89117
89603
|
const appliedSettings = command.sessionConfigurations === void 0 ? void 0 : agentForSessionConfiguration(agent, command.sessionConfigurations);
|
|
89118
89604
|
const executionAgent = appliedSettings?.agent ?? agent;
|
|
89119
89605
|
const sessionConfigurations = appliedSettings?.sessionConfigurations;
|
|
89606
|
+
const recovery = command.historyPolicy === SessionHistoryPolicy.ExecutionOnly ? { kind: "execution-only" } : { kind: "interactive-only" };
|
|
89120
89607
|
const preparation = {
|
|
89121
89608
|
additionalDirectories: resolved.additionalDirectories,
|
|
89122
89609
|
agent: executionAgent,
|
|
89123
89610
|
cwd: resolved.cwd,
|
|
89124
89611
|
sessionId: command.sessionId,
|
|
89125
|
-
signal
|
|
89612
|
+
signal,
|
|
89613
|
+
recovery
|
|
89126
89614
|
};
|
|
89127
89615
|
let prepared = await sessions.prepareExecutionSession(preparation);
|
|
89128
89616
|
if (command.sessionConfigurations !== void 0) {
|
|
@@ -89191,7 +89679,8 @@ async function executePrompt({
|
|
|
89191
89679
|
resources: attachments.resources,
|
|
89192
89680
|
sessionId: command.sessionId,
|
|
89193
89681
|
signal,
|
|
89194
|
-
targetCommandId: command.targetCommandId
|
|
89682
|
+
targetCommandId: command.targetCommandId,
|
|
89683
|
+
recovery
|
|
89195
89684
|
});
|
|
89196
89685
|
stopReason = result.stopReason;
|
|
89197
89686
|
}
|
|
@@ -89360,6 +89849,12 @@ var sessionPromptCommand = {
|
|
|
89360
89849
|
return;
|
|
89361
89850
|
}
|
|
89362
89851
|
if (receipt.kind === "duplicate") {
|
|
89852
|
+
const outcome = receipt.outcome;
|
|
89853
|
+
if (outcome !== void 0) {
|
|
89854
|
+
void context.eventProjection.replayOutcome(message.sessionId, outcome).catch((cause) => {
|
|
89855
|
+
console.error("Could not replay the persisted execution outcome", cause);
|
|
89856
|
+
});
|
|
89857
|
+
}
|
|
89363
89858
|
return;
|
|
89364
89859
|
}
|
|
89365
89860
|
const turn = context.sessionTurns.start(message, receipt.attemptId);
|
|
@@ -90485,7 +90980,8 @@ async function runRuntime(config2, parentSignal, timer = systemTimer, options =
|
|
|
90485
90980
|
resolveAgent: (agentId, resolveSignal) => resolveCatalogAgent(config2, agentId, resolveSignal),
|
|
90486
90981
|
sink: publisher,
|
|
90487
90982
|
stateDirectory: config2.localContext.stateDirectory,
|
|
90488
|
-
timer
|
|
90983
|
+
timer,
|
|
90984
|
+
onExecutionCountChange: options.onExecutionCountChange ?? (() => void 0)
|
|
90489
90985
|
});
|
|
90490
90986
|
const {
|
|
90491
90987
|
activeSessions,
|
|
@@ -90555,6 +91051,7 @@ async function runRuntime(config2, parentSignal, timer = systemTimer, options =
|
|
|
90555
91051
|
reportUpgradeAvailability,
|
|
90556
91052
|
diagnostics,
|
|
90557
91053
|
onConnected: () => {
|
|
91054
|
+
layer.publishRecoveredOutcomes();
|
|
90558
91055
|
if (catalogPublished) {
|
|
90559
91056
|
options.onConnectionStatus?.("online");
|
|
90560
91057
|
}
|
|
@@ -90577,6 +91074,7 @@ async function runRuntime(config2, parentSignal, timer = systemTimer, options =
|
|
|
90577
91074
|
}
|
|
90578
91075
|
} finally {
|
|
90579
91076
|
shutdown.abort();
|
|
91077
|
+
operations.beginShutdown();
|
|
90580
91078
|
await activeSessions.close();
|
|
90581
91079
|
try {
|
|
90582
91080
|
await catalogPublication;
|
|
@@ -90713,6 +91211,10 @@ async function createMobiusRuntimeEngine(connection, signal, environment = proce
|
|
|
90713
91211
|
var MobiusRuntimeEngine = class {
|
|
90714
91212
|
#config;
|
|
90715
91213
|
#options;
|
|
91214
|
+
#activeTurnCount = 0;
|
|
91215
|
+
get activeTurnCount() {
|
|
91216
|
+
return this.#activeTurnCount;
|
|
91217
|
+
}
|
|
90716
91218
|
#state = new IdleMobiusRuntimeState();
|
|
90717
91219
|
constructor(config2, options = {}) {
|
|
90718
91220
|
validateRuntimeConfiguration(config2);
|
|
@@ -90728,11 +91230,15 @@ var MobiusRuntimeEngine = class {
|
|
|
90728
91230
|
try {
|
|
90729
91231
|
await runRuntime(this.#config, signal, void 0, {
|
|
90730
91232
|
...this.#options.turnActivity === void 0 ? {} : { turnActivity: this.#options.turnActivity },
|
|
91233
|
+
onExecutionCountChange: (count) => {
|
|
91234
|
+
this.#activeTurnCount = count;
|
|
91235
|
+
},
|
|
90731
91236
|
...this.#options.onConnectionStatus === void 0 ? {} : { onConnectionStatus: this.#options.onConnectionStatus },
|
|
90732
91237
|
...this.#options.reportUpgradeAvailability === void 0 ? {} : { reportUpgradeAvailability: this.#options.reportUpgradeAvailability },
|
|
90733
91238
|
...this.#options.processLogsDirectory === void 0 ? {} : { processLogsDirectory: this.#options.processLogsDirectory }
|
|
90734
91239
|
});
|
|
90735
91240
|
} finally {
|
|
91241
|
+
this.#activeTurnCount = 0;
|
|
90736
91242
|
this.#state = new FinishedMobiusRuntimeState();
|
|
90737
91243
|
}
|
|
90738
91244
|
};
|