@moxt-ai/mobius 0.0.389 → 0.0.391

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/{chunk-Z6ERJZ2H.js → chunk-4VUCI4MS.js} +2 -2
  2. package/dist/{chunk-Z6ERJZ2H.js.map → chunk-4VUCI4MS.js.map} +1 -1
  3. package/dist/{chunk-77O2RBRQ.js → chunk-TQJ2GJH7.js} +174 -59
  4. package/dist/{chunk-77O2RBRQ.js.map → chunk-TQJ2GJH7.js.map} +4 -4
  5. package/dist/{cli-I4NLPVNV.js → cli-FNJ2BQAZ.js} +3 -3
  6. package/dist/cli.js +2 -2
  7. package/dist/engine/generated/command-cancellation-migrations.d.ts +5 -0
  8. package/dist/engine/generated/command-cancellation-migrations.d.ts.map +1 -0
  9. package/dist/engine/generated/command-cancellation-migrations.js +9 -0
  10. package/dist/engine/generated/command-cancellation-migrations.js.map +1 -0
  11. package/dist/engine/runtime/command/registry/session.d.ts.map +1 -1
  12. package/dist/engine/runtime/command/registry/session.js +1 -2
  13. package/dist/engine/runtime/command/registry/session.js.map +1 -1
  14. package/dist/engine/schema/command-cancellation/cancelled-command.d.ts +41 -0
  15. package/dist/engine/schema/command-cancellation/cancelled-command.d.ts.map +1 -0
  16. package/dist/engine/schema/command-cancellation/cancelled-command.js +7 -0
  17. package/dist/engine/schema/command-cancellation/cancelled-command.js.map +1 -0
  18. package/dist/engine/schema/command-cancellation/index.d.ts +2 -0
  19. package/dist/engine/schema/command-cancellation/index.d.ts.map +1 -0
  20. package/dist/engine/schema/command-cancellation/index.js +2 -0
  21. package/dist/engine/schema/command-cancellation/index.js.map +1 -0
  22. package/dist/engine/session/api/session-api.d.ts +6 -3
  23. package/dist/engine/session/api/session-api.d.ts.map +1 -1
  24. package/dist/engine/session/api/session-api.js.map +1 -1
  25. package/dist/engine/session/api/session-layer.d.ts.map +1 -1
  26. package/dist/engine/session/api/session-layer.js +6 -2
  27. package/dist/engine/session/api/session-layer.js.map +1 -1
  28. package/dist/engine/session/live/agent-session.d.ts +3 -1
  29. package/dist/engine/session/live/agent-session.d.ts.map +1 -1
  30. package/dist/engine/session/live/agent-session.js +22 -17
  31. package/dist/engine/session/live/agent-session.js.map +1 -1
  32. package/dist/engine/session/live/configuration-revision.d.ts +11 -0
  33. package/dist/engine/session/live/configuration-revision.d.ts.map +1 -0
  34. package/dist/engine/session/live/configuration-revision.js +24 -0
  35. package/dist/engine/session/live/configuration-revision.js.map +1 -0
  36. package/dist/engine/session/manager/session-manager.d.ts +4 -1
  37. package/dist/engine/session/manager/session-manager.d.ts.map +1 -1
  38. package/dist/engine/session/manager/session-manager.js +11 -6
  39. package/dist/engine/session/manager/session-manager.js.map +1 -1
  40. package/dist/engine/session/prompt/apply-session-configuration.d.ts.map +1 -1
  41. package/dist/engine/session/prompt/apply-session-configuration.js +1 -2
  42. package/dist/engine/session/prompt/apply-session-configuration.js.map +1 -1
  43. package/dist/engine/session/turn/execution-receipts.d.ts +2 -1
  44. package/dist/engine/session/turn/execution-receipts.d.ts.map +1 -1
  45. package/dist/engine/session/turn/execution-receipts.js +91 -33
  46. package/dist/engine/session/turn/execution-receipts.js.map +1 -1
  47. package/dist/engine/storage/session/command-cancellation-table.d.ts +17 -0
  48. package/dist/engine/storage/session/command-cancellation-table.d.ts.map +1 -0
  49. package/dist/engine/storage/session/command-cancellation-table.js +28 -0
  50. package/dist/engine/storage/session/command-cancellation-table.js.map +1 -0
  51. package/dist/engine/storage/sqlite/local-databases.d.ts +3 -0
  52. package/dist/engine/storage/sqlite/local-databases.d.ts.map +1 -1
  53. package/dist/engine/storage/sqlite/local-databases.js +4 -0
  54. package/dist/engine/storage/sqlite/local-databases.js.map +1 -1
  55. package/dist/engine.js +2 -2
  56. package/package.json +1 -1
  57. /package/dist/{cli-I4NLPVNV.js.map → cli-FNJ2BQAZ.js.map} +0 -0
@@ -80,7 +80,7 @@ var __callDispose = (stack, error, hasError) => {
80
80
  // package.json
81
81
  var package_default = {
82
82
  name: "@moxt-ai/mobius",
83
- version: "0.0.389",
83
+ version: "0.0.391",
84
84
  description: "Mobius CLI for pairing and running local AI agent services.",
85
85
  type: "module",
86
86
  bin: {
@@ -171,4 +171,4 @@ export {
171
171
  __callDispose,
172
172
  package_default
173
173
  };
174
- //# sourceMappingURL=chunk-Z6ERJZ2H.js.map
174
+ //# sourceMappingURL=chunk-4VUCI4MS.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../package.json"],
4
- "sourcesContent": ["{\n \"name\": \"@moxt-ai/mobius\",\n \"version\": \"0.0.389\",\n \"description\": \"Mobius CLI for pairing and running local AI agent services.\",\n \"type\": \"module\",\n \"bin\": {\n \"mobius\": \"dist/cli.js\"\n },\n \"exports\": {\n \"./engine\": {\n \"mobius-source\": \"./src/exports/engine.ts\",\n \"types\": \"./dist/exports/engine.d.ts\",\n \"default\": \"./dist/engine.js\"\n }\n },\n \"files\": [\n \"dist\",\n \"NOTICE\",\n \"THIRD-PARTY-NOTICES.txt\"\n ],\n \"engines\": {\n \"node\": \">=22.19.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"exports\": {\n \"./engine\": {\n \"types\": \"./dist/exports/engine.d.ts\",\n \"import\": \"./dist/engine.js\",\n \"default\": \"./dist/engine.js\"\n }\n }\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/moxt-ai/mobius.git\",\n \"directory\": \"packages/cli\"\n },\n \"scripts\": {\n \"prebuild\": \"tsc --project src/engine/acp/harness/claude/upstream/tsconfig.json && tsc --project src/engine/acp/harness/pi/upstream/tsconfig.json\",\n \"build\": \"node scripts/build.ts && tsc --project tsconfig.build.json\",\n \"dev\": \"node --watch src/cli/entrypoint.ts\",\n \"pretypecheck\": \"tsc --project src/engine/acp/harness/claude/upstream/tsconfig.json && tsc --project src/engine/acp/harness/pi/upstream/tsconfig.json\",\n \"prepack\": \"pnpm build\",\n \"start\": \"node dist/cli.js\",\n \"typecheck\": \"tsc --project tsconfig.json && tsc --project tests/tsconfig.json\",\n \"pretest:controlled\": \"pnpm build\",\n \"test:controlled\": \"vitest run tests/sessions tests/runtime\",\n \"pretest:manual\": \"pnpm pretest:controlled\",\n \"test:manual\": \"vitest run tests/manual\",\n \"pretest:agents\": \"pnpm build\",\n \"test:agents\": \"vitest run tests/agents --maxWorkers=2\",\n \"pretest:pressure\": \"tsc --project src/engine/acp/harness/claude/upstream/tsconfig.json && tsc --project src/engine/acp/harness/pi/upstream/tsconfig.json\",\n \"test:pressure\": \"node tests/pressure/concurrent-sessions.mjs\"\n },\n \"dependencies\": {\n \"@agentclientprotocol/sdk\": \"^1.4.0\",\n \"@anthropic-ai/claude-agent-sdk\": \"0.3.257\",\n \"commander\": \"15.0.0\",\n \"semver\": \"^7.8.5\",\n \"undici\": \"8.12.2\",\n \"zod\": \"^4.6.7\"\n },\n \"devDependencies\": {\n \"@anthropic-ai/sdk\": \"0.122.0\",\n \"@moxt-ai/mobius-sdk\": \"workspace:*\",\n \"@moxt-ai/mobius-test\": \"workspace:*\",\n \"@types/node\": \"^24.13.5\",\n \"@types/semver\": \"^7.8.0\",\n \"@types/ws\": \"^8.18.1\",\n \"drizzle-kit\": \"1.0.0-rc.4\",\n \"drizzle-orm\": \"1.0.0-rc.4\",\n \"esbuild\": \"0.28.2\",\n \"valibot\": \"1.5.0\",\n \"ws\": \"^8.21.3\"\n },\n \"keywords\": [],\n \"author\": \"Moxt\",\n \"license\": \"Apache-2.0\",\n \"bugs\": {\n \"url\": \"https://github.com/moxt-ai/mobius/issues\"\n },\n \"homepage\": \"https://github.com/moxt-ai/mobius#readme\"\n}\n"],
4
+ "sourcesContent": ["{\n \"name\": \"@moxt-ai/mobius\",\n \"version\": \"0.0.391\",\n \"description\": \"Mobius CLI for pairing and running local AI agent services.\",\n \"type\": \"module\",\n \"bin\": {\n \"mobius\": \"dist/cli.js\"\n },\n \"exports\": {\n \"./engine\": {\n \"mobius-source\": \"./src/exports/engine.ts\",\n \"types\": \"./dist/exports/engine.d.ts\",\n \"default\": \"./dist/engine.js\"\n }\n },\n \"files\": [\n \"dist\",\n \"NOTICE\",\n \"THIRD-PARTY-NOTICES.txt\"\n ],\n \"engines\": {\n \"node\": \">=22.19.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"exports\": {\n \"./engine\": {\n \"types\": \"./dist/exports/engine.d.ts\",\n \"import\": \"./dist/engine.js\",\n \"default\": \"./dist/engine.js\"\n }\n }\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/moxt-ai/mobius.git\",\n \"directory\": \"packages/cli\"\n },\n \"scripts\": {\n \"prebuild\": \"tsc --project src/engine/acp/harness/claude/upstream/tsconfig.json && tsc --project src/engine/acp/harness/pi/upstream/tsconfig.json\",\n \"build\": \"node scripts/build.ts && tsc --project tsconfig.build.json\",\n \"dev\": \"node --watch src/cli/entrypoint.ts\",\n \"pretypecheck\": \"tsc --project src/engine/acp/harness/claude/upstream/tsconfig.json && tsc --project src/engine/acp/harness/pi/upstream/tsconfig.json\",\n \"prepack\": \"pnpm build\",\n \"start\": \"node dist/cli.js\",\n \"typecheck\": \"tsc --project tsconfig.json && tsc --project tests/tsconfig.json\",\n \"pretest:controlled\": \"pnpm build\",\n \"test:controlled\": \"vitest run tests/sessions tests/runtime\",\n \"pretest:manual\": \"pnpm pretest:controlled\",\n \"test:manual\": \"vitest run tests/manual\",\n \"pretest:agents\": \"pnpm build\",\n \"test:agents\": \"vitest run tests/agents --maxWorkers=2\",\n \"pretest:pressure\": \"tsc --project src/engine/acp/harness/claude/upstream/tsconfig.json && tsc --project src/engine/acp/harness/pi/upstream/tsconfig.json\",\n \"test:pressure\": \"node tests/pressure/concurrent-sessions.mjs\"\n },\n \"dependencies\": {\n \"@agentclientprotocol/sdk\": \"^1.4.0\",\n \"@anthropic-ai/claude-agent-sdk\": \"0.3.257\",\n \"commander\": \"15.0.0\",\n \"semver\": \"^7.8.5\",\n \"undici\": \"8.12.2\",\n \"zod\": \"^4.6.7\"\n },\n \"devDependencies\": {\n \"@anthropic-ai/sdk\": \"0.122.0\",\n \"@moxt-ai/mobius-sdk\": \"workspace:*\",\n \"@moxt-ai/mobius-test\": \"workspace:*\",\n \"@types/node\": \"^24.13.5\",\n \"@types/semver\": \"^7.8.0\",\n \"@types/ws\": \"^8.18.1\",\n \"drizzle-kit\": \"1.0.0-rc.4\",\n \"drizzle-orm\": \"1.0.0-rc.4\",\n \"esbuild\": \"0.28.2\",\n \"valibot\": \"1.5.0\",\n \"ws\": \"^8.21.3\"\n },\n \"keywords\": [],\n \"author\": \"Moxt\",\n \"license\": \"Apache-2.0\",\n \"bugs\": {\n \"url\": \"https://github.com/moxt-ai/mobius/issues\"\n },\n \"homepage\": \"https://github.com/moxt-ai/mobius#readme\"\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,EACI,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,aAAe;AAAA,EACf,MAAQ;AAAA,EACR,KAAO;AAAA,IACH,QAAU;AAAA,EACd;AAAA,EACA,SAAW;AAAA,IACP,YAAY;AAAA,MACR,iBAAiB;AAAA,MACjB,OAAS;AAAA,MACT,SAAW;AAAA,IACf;AAAA,EACJ;AAAA,EACA,OAAS;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACJ;AAAA,EACA,SAAW;AAAA,IACP,MAAQ;AAAA,EACZ;AAAA,EACA,eAAiB;AAAA,IACb,QAAU;AAAA,IACV,SAAW;AAAA,MACP,YAAY;AAAA,QACR,OAAS;AAAA,QACT,QAAU;AAAA,QACV,SAAW;AAAA,MACf;AAAA,IACJ;AAAA,EACJ;AAAA,EACA,YAAc;AAAA,IACV,MAAQ;AAAA,IACR,KAAO;AAAA,IACP,WAAa;AAAA,EACjB;AAAA,EACA,SAAW;AAAA,IACP,UAAY;AAAA,IACZ,OAAS;AAAA,IACT,KAAO;AAAA,IACP,cAAgB;AAAA,IAChB,SAAW;AAAA,IACX,OAAS;AAAA,IACT,WAAa;AAAA,IACb,sBAAsB;AAAA,IACtB,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,IAClB,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,eAAe;AAAA,IACf,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,EACrB;AAAA,EACA,cAAgB;AAAA,IACZ,4BAA4B;AAAA,IAC5B,kCAAkC;AAAA,IAClC,WAAa;AAAA,IACb,QAAU;AAAA,IACV,QAAU;AAAA,IACV,KAAO;AAAA,EACX;AAAA,EACA,iBAAmB;AAAA,IACf,qBAAqB;AAAA,IACrB,uBAAuB;AAAA,IACvB,wBAAwB;AAAA,IACxB,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,eAAe;AAAA,IACf,eAAe;AAAA,IACf,SAAW;AAAA,IACX,SAAW;AAAA,IACX,IAAM;AAAA,EACV;AAAA,EACA,UAAY,CAAC;AAAA,EACb,QAAU;AAAA,EACV,SAAW;AAAA,EACX,MAAQ;AAAA,IACJ,KAAO;AAAA,EACX;AAAA,EACA,UAAY;AAChB;",
6
6
  "names": []
7
7
  }
@@ -3,7 +3,7 @@ import {
3
3
  __export,
4
4
  __using,
5
5
  package_default
6
- } from "./chunk-Z6ERJZ2H.js";
6
+ } from "./chunk-4VUCI4MS.js";
7
7
 
8
8
  // src/engine/runtime/relay/runtime-revocation.ts
9
9
  var runtimeRevocationCloseCode = 1008;
@@ -78293,6 +78293,14 @@ var acpSessionStoreMigrations = [
78293
78293
  }
78294
78294
  ];
78295
78295
 
78296
+ // src/engine/generated/command-cancellation-migrations.ts
78297
+ var commandCancellationMigrations = [
78298
+ {
78299
+ "name": "0000_tired_cardiac.sql",
78300
+ "sql": "CREATE TABLE `cancelled_command` (\n `command_id` text PRIMARY KEY NOT NULL,\n `session_id` text NOT NULL\n);\n"
78301
+ }
78302
+ ];
78303
+
78296
78304
  // src/engine/generated/session-event-cache-migrations.ts
78297
78305
  var sessionEventCacheMigrations = [
78298
78306
  {
@@ -83232,6 +83240,7 @@ var LocalSqliteDatabase = class {
83232
83240
  function channelSessionDatabasePaths(stateDirectory, channelId) {
83233
83241
  const channelHash = createHash4("sha256").update(channelId).digest("hex");
83234
83242
  return {
83243
+ cancellations: join22(stateDirectory, "sessions", `${channelHash}.cancellations.sqlite`),
83235
83244
  events: join22(stateDirectory, "sessions", `${channelHash}.events.sqlite`),
83236
83245
  sessions: join22(stateDirectory, "sessions", `${channelHash}.sqlite`)
83237
83246
  };
@@ -83255,6 +83264,7 @@ var openAcpSessionDatabase = (path7) => {
83255
83264
  recordAppliedAdmissionOrder(path7);
83256
83265
  return new LocalSqliteDatabase(path7, "ACP Session database", acpSessionStoreMigrations);
83257
83266
  };
83267
+ var openCommandCancellationDatabase = (path7) => new LocalSqliteDatabase(path7, "Command cancellation database", commandCancellationMigrations);
83258
83268
  var openSessionEventCacheDatabase = (path7) => new LocalSqliteDatabase(path7, "V2 Session event cache", sessionEventCacheMigrations, [
83259
83269
  "PRAGMA journal_mode = WAL",
83260
83270
  "PRAGMA synchronous = OFF",
@@ -85045,6 +85055,33 @@ var AcpSessionTable = class {
85045
85055
  };
85046
85056
  };
85047
85057
 
85058
+ // src/engine/schema/command-cancellation/cancelled-command.ts
85059
+ var cancelledCommand = sqliteTable("cancelled_command", {
85060
+ commandId: text("command_id").primaryKey(),
85061
+ sessionId: text("session_id").notNull()
85062
+ });
85063
+
85064
+ // src/engine/storage/session/command-cancellation-table.ts
85065
+ var cancellationSchema = external_exports.object({ commandId: external_exports.string(), sessionId: external_exports.string() }).readonly();
85066
+ var CommandCancellationTable = class {
85067
+ #database;
85068
+ constructor(database) {
85069
+ this.#database = database;
85070
+ }
85071
+ close = () => this.#database.close();
85072
+ read = (commandId) => {
85073
+ const row = this.#database.orm.select().from(cancelledCommand).where(eq2(cancelledCommand.commandId, commandId)).get();
85074
+ return row === void 0 ? void 0 : cancellationSchema.parse(row);
85075
+ };
85076
+ retain = (cancellations) => {
85077
+ this.#database.transaction(() => {
85078
+ for (const cancellation of cancellations) {
85079
+ this.#database.orm.insert(cancelledCommand).values(cancellation).onConflictDoNothing().run();
85080
+ }
85081
+ });
85082
+ };
85083
+ };
85084
+
85048
85085
  // src/engine/storage/session/execution-receipt-table.ts
85049
85086
  var receiptSchema = external_exports.object({
85050
85087
  commandId: external_exports.string(),
@@ -85244,7 +85281,7 @@ var PreparedSession = class {
85244
85281
  prompted;
85245
85282
  restored;
85246
85283
  configurationRevision;
85247
- constructor(agentName, agentVersion, capabilities, commands, configOptions, prompted, restored, configurationRevision) {
85284
+ constructor(agentName, agentVersion, capabilities, commands, configOptions, prompted, restored, configurationRevision2) {
85248
85285
  this.agentName = agentName;
85249
85286
  this.agentVersion = agentVersion;
85250
85287
  this.capabilities = capabilities;
@@ -85252,7 +85289,7 @@ var PreparedSession = class {
85252
85289
  this.configOptions = configOptions;
85253
85290
  this.prompted = prompted;
85254
85291
  this.restored = restored;
85255
- this.configurationRevision = configurationRevision;
85292
+ this.configurationRevision = configurationRevision2;
85256
85293
  }
85257
85294
  };
85258
85295
  var AgentSettingsSnapshot = class {
@@ -86026,6 +86063,23 @@ var SqliteSessionStore = class {
86026
86063
  };
86027
86064
  };
86028
86065
 
86066
+ // src/engine/session/live/configuration-revision.ts
86067
+ import { createHash as createHash6 } from "node:crypto";
86068
+ var configurationRevision = (options) => {
86069
+ const canonical = options.map(
86070
+ (option) => JSON.stringify(
86071
+ option.type === "boolean" ? [option.id, option.type, option.category, option.booleanValue] : [
86072
+ option.id,
86073
+ option.type,
86074
+ option.category,
86075
+ option.currentValue,
86076
+ option.values.map((value) => value.value).toSorted()
86077
+ ]
86078
+ )
86079
+ ).toSorted();
86080
+ return createHash6("sha256").update(JSON.stringify(canonical)).digest("hex");
86081
+ };
86082
+
86029
86083
  // src/engine/session/live/session-restore.ts
86030
86084
  function hasMethodNotFoundCode(cause) {
86031
86085
  const visited = /* @__PURE__ */ new Set();
@@ -86229,7 +86283,6 @@ var AgentSession = class _AgentSession {
86229
86283
  #agentVersion = "";
86230
86284
  #capabilities = unsupportedSessionCapabilities();
86231
86285
  #commands = [];
86232
- #configRevision = crypto.randomUUID();
86233
86286
  #configurationChanges = new SerialTaskQueue();
86234
86287
  #configOptions = [];
86235
86288
  #sessionConfigurations = new SessionConfigurations();
@@ -86438,7 +86491,7 @@ var AgentSession = class _AgentSession {
86438
86491
  this.#configOptions,
86439
86492
  this.#prompted,
86440
86493
  this.#restored,
86441
- this.#configRevision
86494
+ configurationRevision(this.#configOptions)
86442
86495
  );
86443
86496
  ensureHistoryLoaded = async (signal) => {
86444
86497
  if (!this.#capabilities.loadSession) {
@@ -86623,38 +86676,45 @@ var AgentSession = class _AgentSession {
86623
86676
  this.#mobiusSessionId = sessionId;
86624
86677
  };
86625
86678
  #applyConfiguration = async (selection, signal) => {
86626
- const configRevision = this.#configRevision;
86679
+ const before = this.#configOptions;
86627
86680
  const configured = await this.#writeNativeHistory(
86628
86681
  async () => await this.#adapter.configureSession({ ...this.#target(), selection, signal })
86629
86682
  );
86630
- if (this.#configRevision === configRevision) {
86683
+ if (this.#configOptions === before) {
86631
86684
  this.#configOptions = configured;
86632
- this.#configRevision = crypto.randomUUID();
86633
86685
  await this.#publishConfiguration();
86634
86686
  }
86635
86687
  };
86636
- // The revision check and Agent mutation share one queue, including settings the Runtime applies itself.
86688
+ // The revision check and Agent mutation share one queue with the settings the Runtime applies itself.
86637
86689
  // A lost response may have committed: reread after a conflict, never replay an edit blindly.
86638
86690
  configure = async (options) => this.#configurationChanges.run(async (signal) => {
86639
- if (options.expectedConfigurationRevision !== null && options.expectedConfigurationRevision !== this.#configRevision) {
86691
+ if (options.expectedConfigurationRevision !== configurationRevision(this.#configOptions)) {
86640
86692
  throw new AcpExecutionError(
86641
86693
  "Session settings changed. Review the current settings before applying your selection again.",
86642
86694
  {},
86643
86695
  "session_configuration_conflict"
86644
86696
  );
86645
86697
  }
86698
+ return await this.#change(options, signal);
86699
+ }, options.signal);
86700
+ /** Applies a setting the Runtime owns, whatever the configuration's current revision. */
86701
+ applyConfiguration = async (change) => this.#configurationChanges.run(async (signal) => await this.#change(change, signal), change.signal);
86702
+ #change = async (change, signal) => {
86646
86703
  await this.#applyConfiguration(
86647
- options.valueType === "boolean" ? { type: "boolean", configId: options.configId, booleanValue: options.booleanValue } : { type: "select", configId: options.configId, value: options.value },
86704
+ change.valueType === "boolean" ? { type: "boolean", configId: change.configId, booleanValue: change.booleanValue } : { type: "select", configId: change.configId, value: change.value },
86648
86705
  signal
86649
86706
  );
86650
- const applied = this.#configOptions.find((option) => option.id === options.configId);
86707
+ const applied = this.#configOptions.find((option) => option.id === change.configId);
86651
86708
  if (applied === void 0) {
86652
86709
  throw new AcpExecutionError("The requested ACP configuration option is unavailable");
86653
86710
  }
86654
86711
  this.#sessionConfigurations.select(applied);
86655
86712
  this.writeStoredSession((/* @__PURE__ */ new Date()).toISOString());
86656
- return { configOptions: this.#configOptions, configurationRevision: this.#configRevision };
86657
- }, options.signal);
86713
+ return {
86714
+ configOptions: this.#configOptions,
86715
+ configurationRevision: configurationRevision(this.#configOptions)
86716
+ };
86717
+ };
86658
86718
  #publishConfiguration = async () => {
86659
86719
  const event = this.#store.events.append(this.#mobiusSessionId, {
86660
86720
  type: "acp",
@@ -86884,7 +86944,6 @@ var AgentSession = class _AgentSession {
86884
86944
  this.#configOptions = event.kind === "configuration" ? event.configOptions : this.#configOptions.map(
86885
86945
  (option) => option.category === "mode" ? { ...option, currentValue: event.modeId } : option
86886
86946
  );
86887
- this.#configRevision = crypto.randomUUID();
86888
86947
  this.#captureSelectedConfigurationValues();
86889
86948
  }
86890
86949
  if (this.#sessionLoad.kind === "capturing") {
@@ -86967,7 +87026,6 @@ var AgentSession = class _AgentSession {
86967
87026
  openSessionWithReplay = async (signal) => (await this.#loadSession(signal)).opened;
86968
87027
  setConfigOptions(options) {
86969
87028
  this.#configOptions = options;
86970
- this.#configRevision = crypto.randomUUID();
86971
87029
  }
86972
87030
  setNativeHistoryOwnership(ownership) {
86973
87031
  this.#nativeHistoryOwnership = ownership;
@@ -86989,7 +87047,7 @@ var AgentSession = class _AgentSession {
86989
87047
  emitConfigUpdate = async () => {
86990
87048
  await this.#getObserver().onConfig({
86991
87049
  configOptions: this.#configOptions,
86992
- configurationRevision: this.#configRevision,
87050
+ configurationRevision: configurationRevision(this.#configOptions),
86993
87051
  kind: SESSION_CONFIG_UPDATED_KIND,
86994
87052
  requestId: `agent-update-${crypto.randomUUID()}`,
86995
87053
  sessionId: this.#mobiusSessionId
@@ -87297,11 +87355,10 @@ var SessionManager2 = class {
87297
87355
  }
87298
87356
  if (desired.type === "boolean") {
87299
87357
  if (current.booleanValue !== desired.booleanValue) {
87300
- await runtime.configure({
87358
+ await runtime.applyConfiguration({
87301
87359
  ...options,
87302
87360
  booleanValue: desired.booleanValue,
87303
87361
  configId: desired.id,
87304
- expectedConfigurationRevision: null,
87305
87362
  requestId: `execution-prepare-${desired.id}`,
87306
87363
  value: "",
87307
87364
  valueType: "boolean"
@@ -87310,11 +87367,10 @@ var SessionManager2 = class {
87310
87367
  continue;
87311
87368
  }
87312
87369
  if (current.currentValue !== desired.currentValue && current.values.some((value) => value.value === desired.currentValue)) {
87313
- await runtime.configure({
87370
+ await runtime.applyConfiguration({
87314
87371
  ...options,
87315
87372
  booleanValue: false,
87316
87373
  configId: desired.id,
87317
- expectedConfigurationRevision: null,
87318
87374
  requestId: `execution-prepare-${desired.id}`,
87319
87375
  value: desired.currentValue,
87320
87376
  valueType: "select"
@@ -87458,11 +87514,10 @@ var SessionManager2 = class {
87458
87514
  (option) => option.id === "model" || option.category === "model"
87459
87515
  );
87460
87516
  const modelIsFixed = modelOption2?.type === "select" && modelOption2.values.length < 2 && modelOption2.currentValue === model;
87461
- const configOptions = model === void 0 || modelIsFixed ? prepared.configOptions : (await runtime.configure({
87517
+ const configOptions = model === void 0 || modelIsFixed ? prepared.configOptions : (await runtime.applyConfiguration({
87462
87518
  ...options2,
87463
87519
  booleanValue: false,
87464
87520
  configId: modelOption2?.id ?? "model",
87465
- expectedConfigurationRevision: null,
87466
87521
  requestId: "agent-settings-model",
87467
87522
  sessionId: `agent-settings-${crypto.randomUUID()}`,
87468
87523
  value: model,
@@ -87539,12 +87594,20 @@ var SessionManager2 = class {
87539
87594
  }
87540
87595
  return (await this.#replaceExecutionPreparation(existing, options2)).prepared();
87541
87596
  });
87597
+ /** Applies a client's edit only while the Session's configuration still has the revision the client read. */
87542
87598
  configureSession = async (options) => this.#operations.run(options, async (options2) => {
87543
87599
  return await this.#executionProcesses.use(options2.sessionId, async () => {
87544
87600
  const runtime = await this.ensureSession(options2);
87545
87601
  return await runtime.configure(options2);
87546
87602
  });
87547
87603
  });
87604
+ /** Applies a setting the Runtime owns, such as one a prompt or a preparation requested. */
87605
+ applySessionConfiguration = async (change) => this.#operations.run(change, async (change2) => {
87606
+ return await this.#executionProcesses.use(change2.sessionId, async () => {
87607
+ const runtime = await this.ensureSession(change2);
87608
+ return await runtime.applyConfiguration(change2);
87609
+ });
87610
+ });
87548
87611
  renameSession = async (options, title2) => await this.#executionProcesses.use(
87549
87612
  options.sessionId,
87550
87613
  async () => this.#operations.run(options, async (options2) => {
@@ -88326,7 +88389,7 @@ var NativeSessionService = class {
88326
88389
  };
88327
88390
 
88328
88391
  // src/engine/session/prompt/prompt-artifacts.ts
88329
- import { createHash as createHash6 } from "node:crypto";
88392
+ import { createHash as createHash7 } from "node:crypto";
88330
88393
  import { pathToFileURL as pathToFileURL2 } from "node:url";
88331
88394
  var PromptArtifactError = class extends OperationError {
88332
88395
  constructor(code, message, options = {}) {
@@ -88352,7 +88415,7 @@ async function resolvePromptArtifacts(read, attachments, signal) {
88352
88415
  signal.throwIfAborted();
88353
88416
  const artifact = await read(attachment, signal);
88354
88417
  const { bytes } = artifact;
88355
- if (bytes.byteLength !== attachment.byteLength || createHash6("sha256").update(bytes).digest("hex") !== attachment.contentKey) {
88418
+ if (bytes.byteLength !== attachment.byteLength || createHash7("sha256").update(bytes).digest("hex") !== attachment.contentKey) {
88356
88419
  throw new PromptArtifactError(
88357
88420
  "artifact_integrity_failed",
88358
88421
  "The prompt attachment failed integrity validation"
@@ -88574,7 +88637,7 @@ async function settleAbandonedTurn(projection, operations, cancellation) {
88574
88637
  }
88575
88638
 
88576
88639
  // src/engine/session/turn/execution-receipts.ts
88577
- import { createHash as createHash7, randomUUID as randomUUID15 } from "node:crypto";
88640
+ import { createHash as createHash8, randomUUID as randomUUID15 } from "node:crypto";
88578
88641
  var MAX_TERMINAL_RECEIPTS = 1024;
88579
88642
  function executionStarted(state) {
88580
88643
  switch (state.kind) {
@@ -88590,6 +88653,13 @@ function executionStarted(state) {
88590
88653
  }
88591
88654
  }
88592
88655
  }
88656
+ function cancelledBeforeStart(state) {
88657
+ if (state.kind !== "settled-before-start") {
88658
+ return false;
88659
+ }
88660
+ const outcome = decodeKnownSessionEventPayload(JSON.parse(state.outcome));
88661
+ return outcome?.type === "lifecycle-metadata" && outcome.payload.kind === "prompt.completed" && outcome.payload.stopReason === "cancelled";
88662
+ }
88593
88663
  function executionOutcome(state) {
88594
88664
  switch (state.kind) {
88595
88665
  case "pending":
@@ -88611,32 +88681,29 @@ var ExecutionReceipts = class {
88611
88681
  #executions = /* @__PURE__ */ new Map();
88612
88682
  #recoveredCommands = /* @__PURE__ */ new Set();
88613
88683
  #table;
88684
+ #cancellations;
88614
88685
  #closing = false;
88615
88686
  #onCount;
88616
- constructor(table, onCount = () => void 0) {
88687
+ constructor(table, cancellations, onCount = () => void 0) {
88617
88688
  this.#onCount = onCount;
88618
88689
  this.#table = table;
88690
+ this.#cancellations = cancellations;
88691
+ const retained = [];
88619
88692
  for (const { commandId, started, outcome, updatedAt: _updatedAt, ...identity2 } of table.list()) {
88620
- const state = { kind: started ? "started" : "pending" };
88693
+ const pending = { kind: started ? "started" : "pending" };
88694
+ const state = outcome === null ? pending : settledExecution(pending, outcome);
88621
88695
  this.#executions.set(commandId, {
88622
88696
  ...identity2,
88623
- state: outcome === null ? state : settledExecution(state, outcome)
88697
+ state
88624
88698
  });
88699
+ if (cancelledBeforeStart(state)) {
88700
+ retained.push({ commandId, sessionId: identity2.sessionId });
88701
+ }
88625
88702
  this.#recoveredCommands.add(commandId);
88626
88703
  }
88704
+ cancellations.retain(retained);
88627
88705
  }
88628
- #save = (commandId, receipt, durableOutcome = executionOutcome(receipt.state)) => {
88629
- const { state, ...identity2 } = receipt;
88630
- const evicted = this.#closing ? [] : this.#table.save(
88631
- {
88632
- ...identity2,
88633
- commandId,
88634
- started: executionStarted(state),
88635
- outcome: durableOutcome,
88636
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
88637
- },
88638
- MAX_TERMINAL_RECEIPTS
88639
- );
88706
+ #remember = (commandId, receipt, evicted) => {
88640
88707
  this.#executions.set(commandId, receipt);
88641
88708
  for (const evictedCommandId of evicted) {
88642
88709
  this.#executions.delete(evictedCommandId);
@@ -88650,6 +88717,24 @@ var ExecutionReceipts = class {
88650
88717
  }
88651
88718
  this.#onCount(activeCount);
88652
88719
  };
88720
+ #save = (commandId, receipt, durableOutcome = executionOutcome(receipt.state)) => {
88721
+ const { state, ...identity2 } = receipt;
88722
+ if (!this.#closing && cancelledBeforeStart(state)) {
88723
+ this.#cancellations.retain([{ commandId, sessionId: receipt.sessionId }]);
88724
+ this.#remember(commandId, receipt, []);
88725
+ }
88726
+ const evicted = this.#closing ? [] : this.#table.save(
88727
+ {
88728
+ ...identity2,
88729
+ commandId,
88730
+ started: executionStarted(state),
88731
+ outcome: durableOutcome,
88732
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
88733
+ },
88734
+ MAX_TERMINAL_RECEIPTS
88735
+ );
88736
+ this.#remember(commandId, receipt, evicted);
88737
+ };
88653
88738
  #nextAdmissionOrder = () => {
88654
88739
  let latest = 0;
88655
88740
  for (const receipt of this.#executions.values()) {
@@ -88669,7 +88754,7 @@ var ExecutionReceipts = class {
88669
88754
  delivery = (commandId, sessionId) => {
88670
88755
  const receipt = this.#executions.get(commandId);
88671
88756
  if (receipt === void 0) {
88672
- return this.#table.identity(commandId)?.sessionId === sessionId ? { state: "expired" } : { state: "unknown" };
88757
+ return this.#table.identity(commandId)?.sessionId === sessionId || this.#cancellations.read(commandId)?.sessionId === sessionId ? { state: "expired" } : { state: "unknown" };
88673
88758
  }
88674
88759
  if (receipt.sessionId !== sessionId) {
88675
88760
  return { state: "unknown" };
@@ -88743,11 +88828,23 @@ var ExecutionReceipts = class {
88743
88828
  payload: { kind: "prompt.completed", commandId, stopReason: "cancelled" }
88744
88829
  } : void 0;
88745
88830
  }
88831
+ const cancellation = this.#cancellations.read(commandId);
88832
+ if (cancellation !== void 0) {
88833
+ return cancellation.sessionId === sessionId ? {
88834
+ type: "lifecycle-metadata",
88835
+ payload: {
88836
+ kind: "prompt.completed",
88837
+ commandId,
88838
+ stopReason: "cancelled",
88839
+ execution: "not-started"
88840
+ }
88841
+ } : void 0;
88842
+ }
88746
88843
  const outcome = {
88747
88844
  type: "lifecycle-metadata",
88748
88845
  payload: { kind: "prompt.completed", commandId, stopReason: "cancelled", execution: "not-started" }
88749
88846
  };
88750
- const commandHash = createHash7("sha256").update(
88847
+ const commandHash = createHash8("sha256").update(
88751
88848
  encodeSessionCancelBeforeStartCommand({
88752
88849
  commandId,
88753
88850
  kind: "session.cancel-before-start",
@@ -88802,7 +88899,16 @@ var ExecutionReceipts = class {
88802
88899
  const recovered = [];
88803
88900
  for (const [commandId, receipt] of [...this.#executions]) {
88804
88901
  const outcome = executionOutcome(receipt.state);
88805
- const event = outcome === null ? {
88902
+ const restoreCancellation = !this.hasStarted(commandId, receipt.sessionId) && !cancelledBeforeStart(receipt.state) && this.#cancellations.read(commandId)?.sessionId === receipt.sessionId;
88903
+ const event = restoreCancellation ? {
88904
+ type: "lifecycle-metadata",
88905
+ payload: {
88906
+ kind: "prompt.completed",
88907
+ commandId,
88908
+ stopReason: "cancelled",
88909
+ execution: "not-started"
88910
+ }
88911
+ } : outcome === null ? {
88806
88912
  type: "lifecycle-metadata",
88807
88913
  payload: executionStarted(receipt.state) ? {
88808
88914
  kind: "prompt.failed",
@@ -88820,9 +88926,9 @@ var ExecutionReceipts = class {
88820
88926
  if (event === null) {
88821
88927
  continue;
88822
88928
  }
88823
- const recordedAt = outcome === null ? (/* @__PURE__ */ new Date()).toISOString() : external_exports.object({ recordedAt: external_exports.string() }).parse(JSON.parse(outcome)).recordedAt;
88929
+ const recordedAt = restoreCancellation || outcome === null ? (/* @__PURE__ */ new Date()).toISOString() : external_exports.object({ recordedAt: external_exports.string() }).parse(JSON.parse(outcome)).recordedAt;
88824
88930
  recovered.push({ sessionId: receipt.sessionId, event, recordedAt });
88825
- if (outcome === null) {
88931
+ if (restoreCancellation || outcome === null) {
88826
88932
  this.#save(commandId, {
88827
88933
  ...receipt,
88828
88934
  state: settledExecution(receipt.state, JSON.stringify({ ...event, recordedAt }))
@@ -88832,7 +88938,7 @@ var ExecutionReceipts = class {
88832
88938
  return recovered;
88833
88939
  };
88834
88940
  claimExecution = (commandId, sessionId, commandJson) => {
88835
- const commandHash = createHash7("sha256").update(commandJson).digest("hex");
88941
+ const commandHash = createHash8("sha256").update(commandJson).digest("hex");
88836
88942
  let existing = this.#executions.get(commandId);
88837
88943
  const previous = this.outcome(commandId);
88838
88944
  if (existing?.sessionId === sessionId && !executionStarted(existing.state) && previous?.type === "lifecycle-metadata" && previous.payload.kind === "prompt.failed-before-start" && previous.payload.code === "runtime_restarted") {
@@ -88856,6 +88962,9 @@ var ExecutionReceipts = class {
88856
88962
  if (identity2 !== void 0) {
88857
88963
  return identity2.sessionId === sessionId && identity2.commandHash === commandHash ? { kind: "expired" } : { kind: "conflict" };
88858
88964
  }
88965
+ if (this.#cancellations.read(commandId) !== void 0) {
88966
+ return { kind: "conflict" };
88967
+ }
88859
88968
  const attemptId = randomUUID15();
88860
88969
  this.#save(commandId, {
88861
88970
  admissionOrder: this.#nextAdmissionOrder(),
@@ -88878,6 +88987,7 @@ var ExecutionReceipts = class {
88878
88987
  close = () => {
88879
88988
  this.#executions.clear();
88880
88989
  this.#recoveredCommands.clear();
88990
+ this.#cancellations.close();
88881
88991
  };
88882
88992
  };
88883
88993
 
@@ -89473,13 +89583,20 @@ function buildSessionLayer(options) {
89473
89583
  const sessionDatabase = openAcpSessionDatabase(databases.sessions);
89474
89584
  let events;
89475
89585
  let operations;
89586
+ let cancellations;
89476
89587
  try {
89477
- operations = new ExecutionReceipts(new ExecutionReceiptTable(sessionDatabase), options.onExecutionCountChange);
89588
+ cancellations = new CommandCancellationTable(openCommandCancellationDatabase(databases.cancellations));
89589
+ operations = new ExecutionReceipts(
89590
+ new ExecutionReceiptTable(sessionDatabase),
89591
+ cancellations,
89592
+ options.onExecutionCountChange
89593
+ );
89478
89594
  events = new CachedSessionEventStore(
89479
89595
  new SessionEventCacheTable(openSessionEventCacheDatabase(databases.events)),
89480
89596
  new SqliteSessionLiveEventPosition(new LiveEventPositionTable(sessionDatabase))
89481
89597
  );
89482
89598
  } catch (error62) {
89599
+ cancellations?.close();
89483
89600
  sessionDatabase.close();
89484
89601
  throw error62;
89485
89602
  }
@@ -89570,7 +89687,7 @@ function buildSessionLayer(options) {
89570
89687
  }
89571
89688
 
89572
89689
  // src/engine/session/content/external-content-store.ts
89573
- import { createHash as createHash8 } from "node:crypto";
89690
+ import { createHash as createHash9 } from "node:crypto";
89574
89691
  import { extname as extname2, join as join29 } from "node:path";
89575
89692
  import { pathToFileURL as pathToFileURL3 } from "node:url";
89576
89693
 
@@ -89705,7 +89822,7 @@ var LocalExternalContentStore = class {
89705
89822
  const active = AbortSignal.any([signal, this.#lifetime.signal]);
89706
89823
  active.throwIfAborted();
89707
89824
  const metadata = metadataSchema.parse({ kind, mediaType, name: name2 });
89708
- const key = createHash8("sha256").update(bytes).digest("hex");
89825
+ const key = createHash9("sha256").update(bytes).digest("hex");
89709
89826
  const request = `mobius-content:${kind}:${key}`;
89710
89827
  const existing = this.#entries.get(request);
89711
89828
  if (existing !== void 0 && existing.expiresAt > Date.now()) {
@@ -90425,7 +90542,7 @@ var SessionError = class extends OperationError {
90425
90542
  };
90426
90543
 
90427
90544
  // src/engine/session/settings/discover-agent-settings.ts
90428
- import { createHash as createHash9 } from "node:crypto";
90545
+ import { createHash as createHash10 } from "node:crypto";
90429
90546
 
90430
90547
  // src/engine/agent/settings/agent-settings-base.ts
90431
90548
  var AgentSettingsLaunchSelectionResult = class {
@@ -90743,7 +90860,7 @@ function settingsRevision(agent, reportedAgentVersion, settings, modelEffort) {
90743
90860
  unsupportedModelIds: modelEffort.unsupportedModelIds,
90744
90861
  valuesByModel: {}
90745
90862
  };
90746
- return createHash9("sha256").update(
90863
+ return createHash10("sha256").update(
90747
90864
  JSON.stringify({
90748
90865
  adapterVersion: agent.adapterVersion,
90749
90866
  agentId: agent.id,
@@ -90899,7 +91016,7 @@ function createAgentSettingsCommands(context) {
90899
91016
  }
90900
91017
 
90901
91018
  // src/engine/runtime/command/registry/content-write/index.ts
90902
- import { createHash as createHash10 } from "node:crypto";
91019
+ import { createHash as createHash11 } from "node:crypto";
90903
91020
  function createContentWriteCommands(context) {
90904
91021
  const pending = /* @__PURE__ */ new Map();
90905
91022
  const operations = /* @__PURE__ */ new Set();
@@ -90929,7 +91046,7 @@ function createContentWriteCommands(context) {
90929
91046
  pending.set(message.requestId, {
90930
91047
  bytes: new Uint8Array(message.byteLength),
90931
91048
  command: message,
90932
- hash: createHash10("sha256"),
91049
+ hash: createHash11("sha256"),
90933
91050
  receivedBytes: 0,
90934
91051
  sequence: 0
90935
91052
  });
@@ -91749,13 +91866,12 @@ async function applySessionConfigurationSelection(sessions, options, selection,
91749
91866
  if (sessionConfigurationMatches(option, selection)) {
91750
91867
  return options;
91751
91868
  }
91752
- return (await sessions.configureSession({
91869
+ return (await sessions.applySessionConfiguration({
91753
91870
  adapter,
91754
91871
  additionalDirectories,
91755
91872
  agent,
91756
91873
  booleanValue: selection.booleanValue,
91757
91874
  configId: selection.configId,
91758
- expectedConfigurationRevision: null,
91759
91875
  cwd,
91760
91876
  requestId: `cfg_${randomUUID18()}`,
91761
91877
  sessionId,
@@ -92100,11 +92216,10 @@ async function prepareSession(command, recovery, closed, config2, resolveAgent,
92100
92216
  const configuration = command.configuration;
92101
92217
  const snapshot = configuration === void 0 ? prepared : await metrics.measure(
92102
92218
  "configuration",
92103
- async () => await sessions.configureSession({
92219
+ async () => await sessions.applySessionConfiguration({
92104
92220
  ...preparation,
92105
92221
  booleanValue: configuration.booleanValue,
92106
92222
  configId: configuration.configId,
92107
- expectedConfigurationRevision: null,
92108
92223
  requestId: command.requestId,
92109
92224
  value: configuration.value,
92110
92225
  valueType: configuration.valueType
@@ -93631,4 +93746,4 @@ export {
93631
93746
  * MIT Licensed
93632
93747
  *)
93633
93748
  */
93634
- //# sourceMappingURL=chunk-77O2RBRQ.js.map
93749
+ //# sourceMappingURL=chunk-TQJ2GJH7.js.map