@moxt-ai/mobius 0.0.331 → 0.0.332

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/cli.js CHANGED
@@ -2086,7 +2086,7 @@ var init_package = __esm({
2086
2086
  "package.json"() {
2087
2087
  package_default = {
2088
2088
  name: "@moxt-ai/mobius",
2089
- version: "0.0.331",
2089
+ version: "0.0.332",
2090
2090
  description: "Mobius CLI for pairing and running local AI agent services.",
2091
2091
  type: "module",
2092
2092
  bin: {
@@ -93687,6 +93687,7 @@ var init_execution_receipt = __esm({
93687
93687
  sessionId: text("session_id").notNull(),
93688
93688
  commandHash: text("command_hash").notNull(),
93689
93689
  attemptId: text("attempt_id").notNull(),
93690
+ // Compatibility projection for older Runtimes; started and outcome own the facts.
93690
93691
  state: text("state").notNull(),
93691
93692
  started: integer2("started", { mode: "boolean" }).notNull(),
93692
93693
  outcome: text("outcome"),
@@ -93764,29 +93765,30 @@ var init_acp_session_table = __esm({
93764
93765
  });
93765
93766
 
93766
93767
  // src/storage/session/execution-receipt-table.ts
93767
- var receiptFields, receiptSchema, identitySchema, ExecutionReceiptTable;
93768
+ function legacyState(receipt) {
93769
+ if (receipt.outcome === null) {
93770
+ return receipt.started ? "running" : "dispatching";
93771
+ }
93772
+ const event = sessionEventPayloadSchema.parse(JSON.parse(receipt.outcome));
93773
+ return event.type === "lifecycle-metadata" && event.payload.kind === "prompt.completed" ? event.payload.stopReason === "cancelled" ? "cancelled" : "succeeded" : "failed";
93774
+ }
93775
+ var receiptSchema, identitySchema, ExecutionReceiptTable;
93768
93776
  var init_execution_receipt_table = __esm({
93769
93777
  "src/storage/session/execution-receipt-table.ts"() {
93770
93778
  "use strict";
93779
+ init_protocol();
93771
93780
  init_drizzle_orm();
93772
93781
  init_zod();
93773
93782
  init_acp_session_store();
93774
- receiptFields = external_exports.object({
93783
+ receiptSchema = external_exports.object({
93775
93784
  commandId: external_exports.string(),
93776
93785
  sessionId: external_exports.string(),
93777
93786
  commandHash: external_exports.string(),
93778
93787
  attemptId: external_exports.string(),
93779
- updatedAt: external_exports.string()
93780
- });
93781
- receiptSchema = external_exports.discriminatedUnion("state", [
93782
- receiptFields.extend({ state: external_exports.literal("dispatching"), started: external_exports.literal(false), outcome: external_exports.null() }),
93783
- receiptFields.extend({ state: external_exports.literal("running"), started: external_exports.literal(true), outcome: external_exports.string().nullable() }),
93784
- receiptFields.extend({
93785
- state: external_exports.enum(["succeeded", "failed", "cancelled"]),
93786
- started: external_exports.boolean(),
93787
- outcome: external_exports.string().nullable()
93788
- })
93789
- ]).readonly();
93788
+ updatedAt: external_exports.string(),
93789
+ started: external_exports.boolean(),
93790
+ outcome: external_exports.string().nullable()
93791
+ }).readonly();
93790
93792
  identitySchema = external_exports.object({ sessionId: external_exports.string(), commandHash: external_exports.string() }).readonly();
93791
93793
  ExecutionReceiptTable = class {
93792
93794
  #database;
@@ -93800,32 +93802,27 @@ var init_execution_receipt_table = __esm({
93800
93802
  list = () => receiptSchema.array().parse(
93801
93803
  this.#database.orm.select().from(executionReceipt).orderBy(asc(executionReceipt.updatedAt), asc(executionReceipt.commandId)).all()
93802
93804
  );
93803
- save = (receipt) => {
93804
- this.#database.transaction(() => {
93805
- this.#database.orm.insert(executionReceipt).values(receipt).onConflictDoUpdate({ target: executionReceipt.commandId, set: receipt }).run();
93806
- if (receipt.state === "dispatching" || receipt.state === "running") {
93807
- return;
93808
- }
93809
- const retained = this.#database.orm.select({ commandId: executionReceipt.commandId }).from(executionReceipt).where(
93805
+ save = (receipt, terminalLimit) => this.#database.transaction(() => {
93806
+ const row = { ...receipt, state: legacyState(receipt) };
93807
+ this.#database.orm.insert(executionReceipt).values(row).onConflictDoUpdate({ target: executionReceipt.commandId, set: row }).run();
93808
+ if (receipt.outcome === null) {
93809
+ return [];
93810
+ }
93811
+ const retained = this.#database.orm.select({ commandId: executionReceipt.commandId }).from(executionReceipt).where(and(eq2(executionReceipt.sessionId, receipt.sessionId), isNotNull(executionReceipt.outcome))).orderBy(desc(executionReceipt.updatedAt), desc(executionReceipt.commandId)).limit(terminalLimit).all();
93812
+ if (retained.length === terminalLimit) {
93813
+ return this.#remove(
93810
93814
  and(
93811
93815
  eq2(executionReceipt.sessionId, receipt.sessionId),
93812
- inArray(executionReceipt.state, ["succeeded", "failed", "cancelled"])
93813
- )
93814
- ).orderBy(desc(executionReceipt.updatedAt), desc(executionReceipt.commandId)).limit(1024).all();
93815
- if (retained.length === 1024) {
93816
- this.#remove(
93817
- and(
93818
- eq2(executionReceipt.sessionId, receipt.sessionId),
93819
- inArray(executionReceipt.state, ["succeeded", "failed", "cancelled"]),
93820
- notInArray(
93821
- executionReceipt.commandId,
93822
- retained.map((row) => row.commandId)
93823
- )
93816
+ isNotNull(executionReceipt.outcome),
93817
+ notInArray(
93818
+ executionReceipt.commandId,
93819
+ retained.map((row2) => row2.commandId)
93824
93820
  )
93825
- );
93826
- }
93827
- });
93828
- };
93821
+ )
93822
+ );
93823
+ }
93824
+ return [];
93825
+ });
93829
93826
  remove = (commandId) => {
93830
93827
  this.#database.transaction(() => this.#remove(eq2(executionReceipt.commandId, commandId)));
93831
93828
  };
@@ -93840,7 +93837,7 @@ var init_execution_receipt_table = __esm({
93840
93837
  commandHash: executionReceipt.commandHash
93841
93838
  }).from(executionReceipt).where(and(condition, eq2(executionReceipt.started, true)))
93842
93839
  ).onConflictDoNothing().run();
93843
- this.#database.orm.delete(executionReceipt).where(condition).run();
93840
+ return this.#database.orm.delete(executionReceipt).where(condition).returning({ commandId: executionReceipt.commandId }).all().map((row) => row.commandId);
93844
93841
  };
93845
93842
  };
93846
93843
  }
@@ -97069,7 +97066,6 @@ async function settleAbandonedTurn(projection, operations, cancellation) {
97069
97066
  "agent_execution_abandoned",
97070
97067
  "The local Agent execution was abandoned before it completed"
97071
97068
  );
97072
- operations.transitionExecution(cancellation.commandId, "failed");
97073
97069
  projection.publishTerminal(cancellation.sessionId, cancellation.commandId);
97074
97070
  }
97075
97071
  var PromptLifecycle;
@@ -97216,9 +97212,6 @@ var init_prompt_lifecycle = __esm({
97216
97212
 
97217
97213
  // src/session/turn/execution-receipts.ts
97218
97214
  import { createHash as createHash7, randomUUID as randomUUID16 } from "node:crypto";
97219
- function isTerminal(state) {
97220
- return state === "succeeded" || state === "failed" || state === "cancelled";
97221
- }
97222
97215
  var MAX_TERMINAL_RECEIPTS, ExecutionReceipts;
97223
97216
  var init_execution_receipts = __esm({
97224
97217
  "src/session/turn/execution-receipts.ts"() {
@@ -97229,7 +97222,6 @@ var init_execution_receipts = __esm({
97229
97222
  ExecutionReceipts = class {
97230
97223
  #executions = /* @__PURE__ */ new Map();
97231
97224
  #recoveredCommands = /* @__PURE__ */ new Set();
97232
- #terminalCountBySession = /* @__PURE__ */ new Map();
97233
97225
  #table;
97234
97226
  #closing = false;
97235
97227
  #activeCount = 0;
@@ -97240,36 +97232,22 @@ var init_execution_receipts = __esm({
97240
97232
  for (const row of table.list()) {
97241
97233
  this.#executions.set(row.commandId, row);
97242
97234
  this.#recoveredCommands.add(row.commandId);
97243
- if (!isTerminal(row.state)) {
97235
+ if (row.outcome === null) {
97244
97236
  this.#activeCount += 1;
97245
97237
  }
97246
- if (isTerminal(row.state)) {
97247
- this.#terminalCountBySession.set(
97248
- row.sessionId,
97249
- (this.#terminalCountBySession.get(row.sessionId) ?? 0) + 1
97250
- );
97251
- }
97252
97238
  }
97253
97239
  }
97254
97240
  #save = (commandId, receipt) => {
97255
- if (!this.#closing) {
97256
- this.#table.save({ ...receipt, commandId, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
97257
- }
97241
+ const evicted = this.#closing ? [] : this.#table.save({ ...receipt, commandId, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, MAX_TERMINAL_RECEIPTS);
97258
97242
  const previous = this.#executions.get(commandId);
97259
- const wasActive = previous !== void 0 && !isTerminal(previous.state);
97260
- if (isTerminal(receipt.state)) {
97261
- this.#executions.delete(commandId);
97262
- }
97243
+ const wasActive = previous?.outcome === null;
97263
97244
  this.#executions.set(commandId, receipt);
97264
- this.#activeCount += Number(!isTerminal(receipt.state)) - Number(wasActive);
97265
- this.#onCount(this.#activeCount);
97266
- if (isTerminal(receipt.state) && (previous === void 0 || !isTerminal(previous.state))) {
97267
- this.#terminalCountBySession.set(
97268
- receipt.sessionId,
97269
- (this.#terminalCountBySession.get(receipt.sessionId) ?? 0) + 1
97270
- );
97271
- this.pruneTerminalReceipts(receipt.sessionId);
97245
+ for (const evictedCommandId of evicted) {
97246
+ this.#executions.delete(evictedCommandId);
97247
+ this.#recoveredCommands.delete(evictedCommandId);
97272
97248
  }
97249
+ this.#activeCount += Number(receipt.outcome === null) - Number(wasActive);
97250
+ this.#onCount(this.#activeCount);
97273
97251
  };
97274
97252
  beginShutdown = () => {
97275
97253
  this.#closing = true;
@@ -97282,7 +97260,7 @@ var init_execution_receipts = __esm({
97282
97260
  recordCancellationBeforeAdmission = (commandId, sessionId) => {
97283
97261
  const existing = this.#executions.get(commandId);
97284
97262
  if (existing !== void 0) {
97285
- return existing.sessionId === sessionId && isTerminal(existing.state) ? this.outcome(commandId) : void 0;
97263
+ return existing.sessionId === sessionId ? this.outcome(commandId) : void 0;
97286
97264
  }
97287
97265
  const outcome = {
97288
97266
  type: "lifecycle-metadata",
@@ -97299,7 +97277,6 @@ var init_execution_receipts = __esm({
97299
97277
  attemptId: randomUUID16(),
97300
97278
  commandHash,
97301
97279
  sessionId,
97302
- state: "cancelled",
97303
97280
  started: false,
97304
97281
  outcome: JSON.stringify({ ...outcome, recordedAt: (/* @__PURE__ */ new Date()).toISOString() })
97305
97282
  });
@@ -97320,7 +97297,6 @@ var init_execution_receipts = __esm({
97320
97297
  const sanitized = payload.kind === "prompt.completed" ? payload : { ...payload, message: "The local Agent could not complete the request" };
97321
97298
  this.#save(payload.commandId, {
97322
97299
  ...receipt,
97323
- state: payload.kind === "prompt.completed" ? payload.stopReason === "cancelled" ? "cancelled" : "succeeded" : "failed",
97324
97300
  outcome: JSON.stringify({ type: "lifecycle-metadata", payload: sanitized, recordedAt: event.recordedAt })
97325
97301
  });
97326
97302
  };
@@ -97344,9 +97320,8 @@ var init_execution_receipts = __esm({
97344
97320
  } : sessionEventPayloadSchema.parse(JSON.parse(receipt.outcome));
97345
97321
  const recordedAt = receipt.outcome === null ? (/* @__PURE__ */ new Date()).toISOString() : external_exports.object({ recordedAt: external_exports.string() }).parse(JSON.parse(receipt.outcome)).recordedAt;
97346
97322
  recovered.push({ sessionId: receipt.sessionId, event, recordedAt });
97347
- if (!isTerminal(receipt.state)) {
97348
- const state = event.type === "lifecycle-metadata" && event.payload.kind === "prompt.completed" ? event.payload.stopReason === "cancelled" ? "cancelled" : "succeeded" : "failed";
97349
- this.#save(commandId, { ...receipt, state, outcome: JSON.stringify({ ...event, recordedAt }) });
97323
+ if (receipt.outcome === null) {
97324
+ this.#save(commandId, { ...receipt, outcome: JSON.stringify({ ...event, recordedAt }) });
97350
97325
  }
97351
97326
  }
97352
97327
  return recovered;
@@ -97359,10 +97334,6 @@ var init_execution_receipts = __esm({
97359
97334
  this.#table.remove(commandId);
97360
97335
  this.#executions.delete(commandId);
97361
97336
  this.#recoveredCommands.delete(commandId);
97362
- this.#terminalCountBySession.set(
97363
- sessionId,
97364
- Math.max(0, (this.#terminalCountBySession.get(sessionId) ?? 1) - 1)
97365
- );
97366
97337
  existing = void 0;
97367
97338
  }
97368
97339
  if (existing !== void 0) {
@@ -97373,7 +97344,6 @@ var init_execution_receipts = __esm({
97373
97344
  attemptId: existing.attemptId,
97374
97345
  commandId,
97375
97346
  kind: "duplicate",
97376
- state: existing.state,
97377
97347
  outcome: this.#recoveredCommands.has(commandId) ? this.outcome(commandId) : void 0
97378
97348
  };
97379
97349
  }
@@ -97386,66 +97356,37 @@ var init_execution_receipts = __esm({
97386
97356
  attemptId,
97387
97357
  commandHash,
97388
97358
  sessionId,
97389
- state: "dispatching",
97390
97359
  started: false,
97391
97360
  outcome: null
97392
97361
  });
97393
- return { attemptId, commandId, kind: "accepted", state: "dispatching" };
97362
+ return { attemptId, commandId, kind: "accepted" };
97394
97363
  };
97395
- transitionExecution = (commandId, state) => {
97364
+ markExecutionStarted = (commandId) => {
97396
97365
  const current = this.#executions.get(commandId);
97397
97366
  if (current === void 0) {
97398
97367
  throw new Error("The runtime execution receipt does not exist");
97399
97368
  }
97400
- if (current.state === state) {
97401
- return;
97402
- }
97403
- const allowed = current.state === "dispatching" && (state === "running" || state === "failed" || state === "cancelled") || current.state === "running" && isTerminal(state);
97404
- if (!allowed) {
97369
+ if (current.outcome !== null) {
97405
97370
  throw new Error("The runtime execution transition is invalid");
97406
97371
  }
97407
- if (state === "running") {
97408
- this.#save(commandId, { ...current, state, started: true });
97409
- } else if (isTerminal(state)) {
97410
- this.#save(commandId, { ...current, state });
97372
+ if (!current.started) {
97373
+ this.#save(commandId, { ...current, started: true });
97411
97374
  }
97412
97375
  };
97413
97376
  /** Only commands without a terminal result can still be cancelled. */
97414
97377
  findUnsettledAttemptId = (commandId, sessionId) => {
97415
97378
  const receipt = this.#executions.get(commandId);
97416
- return receipt?.sessionId === sessionId && !isTerminal(receipt.state) ? receipt.attemptId : null;
97379
+ return receipt?.sessionId === sessionId && receipt.outcome === null ? receipt.attemptId : null;
97417
97380
  };
97418
97381
  isTerminalExecution = (commandId, sessionId) => {
97419
97382
  const receipt = this.#executions.get(commandId);
97420
- return receipt?.sessionId === sessionId && isTerminal(receipt.state);
97383
+ return receipt?.sessionId === sessionId && receipt.outcome !== null;
97421
97384
  };
97422
97385
  close = () => {
97423
97386
  this.#executions.clear();
97424
97387
  this.#recoveredCommands.clear();
97425
- this.#terminalCountBySession.clear();
97426
97388
  this.#activeCount = 0;
97427
97389
  };
97428
- pruneTerminalReceipts = (sessionId) => {
97429
- if ((this.#terminalCountBySession.get(sessionId) ?? 0) <= MAX_TERMINAL_RECEIPTS) {
97430
- return;
97431
- }
97432
- for (const [commandId, receipt] of this.#executions) {
97433
- if (receipt.sessionId === sessionId && isTerminal(receipt.state)) {
97434
- this.#table.remove(commandId);
97435
- this.#executions.delete(commandId);
97436
- this.#recoveredCommands.delete(commandId);
97437
- const remaining = (this.#terminalCountBySession.get(sessionId) ?? 1) - 1;
97438
- if (remaining > 0) {
97439
- this.#terminalCountBySession.set(sessionId, remaining);
97440
- } else {
97441
- this.#terminalCountBySession.delete(sessionId);
97442
- }
97443
- if ((this.#terminalCountBySession.get(sessionId) ?? 0) <= MAX_TERMINAL_RECEIPTS) {
97444
- return;
97445
- }
97446
- }
97447
- }
97448
- };
97449
97390
  };
97450
97391
  }
97451
97392
  });
@@ -100736,7 +100677,7 @@ async function executePrompt({
100736
100677
  );
100737
100678
  prepared = await sessions.prepareExecutionSession(preparation);
100738
100679
  }
100739
- operations.transitionExecution(command.commandId, "running");
100680
+ operations.markExecutionStarted(command.commandId);
100740
100681
  if (availability.disposition === SessionPromptDisposition.Steer) {
100741
100682
  if (!recordSteeringPrompt()) {
100742
100683
  throw new AcpExecutionError(
@@ -100792,18 +100733,15 @@ async function executePrompt({
100792
100733
  stopReason = result.stopReason;
100793
100734
  }
100794
100735
  await eventProjection.completed(command.sessionId, command.commandId, stopReason);
100795
- operations.transitionExecution(command.commandId, stopReason === "cancelled" ? "cancelled" : "succeeded");
100796
100736
  } catch (error62) {
100797
100737
  if (signal.aborted && cancellationRequested()) {
100798
100738
  await eventProjection.completed(command.sessionId, command.commandId, "cancelled");
100799
- operations.transitionExecution(command.commandId, "cancelled");
100800
100739
  return;
100801
100740
  }
100802
100741
  const code = operationErrorCode(error62);
100803
100742
  const failureCode = code === "session_operation_failed" ? "agent_execution_failed" : code;
100804
100743
  const failureMessage = code === "session_operation_failed" ? "The local agent could not complete the request" : operationErrorMessage(error62);
100805
100744
  await eventProjection.failed(command.sessionId, command.commandId, failureCode, failureMessage);
100806
- operations.transitionExecution(command.commandId, "failed");
100807
100745
  reportFailure("session_prompt_failed", command.commandId, {
100808
100746
  agentId: command.agentId,
100809
100747
  code: failureCode,