@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/runtime.js CHANGED
@@ -32545,7 +32545,7 @@ import { fetch as fetch3 } from "undici";
32545
32545
  // package.json
32546
32546
  var package_default = {
32547
32547
  name: "@moxt-ai/mobius",
32548
- version: "0.0.331",
32548
+ version: "0.0.332",
32549
32549
  description: "Mobius CLI for pairing and running local AI agent services.",
32550
32550
  type: "module",
32551
32551
  bin: {
@@ -83682,6 +83682,7 @@ var executionReceipt = sqliteTable("execution_receipt", {
83682
83682
  sessionId: text("session_id").notNull(),
83683
83683
  commandHash: text("command_hash").notNull(),
83684
83684
  attemptId: text("attempt_id").notNull(),
83685
+ // Compatibility projection for older Runtimes; started and outcome own the facts.
83685
83686
  state: text("state").notNull(),
83686
83687
  started: integer2("started", { mode: "boolean" }).notNull(),
83687
83688
  outcome: text("outcome"),
@@ -83730,23 +83731,23 @@ var AcpSessionTable = class {
83730
83731
  };
83731
83732
 
83732
83733
  // src/storage/session/execution-receipt-table.ts
83733
- var receiptFields = external_exports.object({
83734
+ var receiptSchema = external_exports.object({
83734
83735
  commandId: external_exports.string(),
83735
83736
  sessionId: external_exports.string(),
83736
83737
  commandHash: external_exports.string(),
83737
83738
  attemptId: external_exports.string(),
83738
- updatedAt: external_exports.string()
83739
- });
83740
- var receiptSchema = external_exports.discriminatedUnion("state", [
83741
- receiptFields.extend({ state: external_exports.literal("dispatching"), started: external_exports.literal(false), outcome: external_exports.null() }),
83742
- receiptFields.extend({ state: external_exports.literal("running"), started: external_exports.literal(true), outcome: external_exports.string().nullable() }),
83743
- receiptFields.extend({
83744
- state: external_exports.enum(["succeeded", "failed", "cancelled"]),
83745
- started: external_exports.boolean(),
83746
- outcome: external_exports.string().nullable()
83747
- })
83748
- ]).readonly();
83739
+ updatedAt: external_exports.string(),
83740
+ started: external_exports.boolean(),
83741
+ outcome: external_exports.string().nullable()
83742
+ }).readonly();
83749
83743
  var identitySchema = external_exports.object({ sessionId: external_exports.string(), commandHash: external_exports.string() }).readonly();
83744
+ function legacyState(receipt) {
83745
+ if (receipt.outcome === null) {
83746
+ return receipt.started ? "running" : "dispatching";
83747
+ }
83748
+ const event = sessionEventPayloadSchema.parse(JSON.parse(receipt.outcome));
83749
+ return event.type === "lifecycle-metadata" && event.payload.kind === "prompt.completed" ? event.payload.stopReason === "cancelled" ? "cancelled" : "succeeded" : "failed";
83750
+ }
83750
83751
  var ExecutionReceiptTable = class {
83751
83752
  #database;
83752
83753
  constructor(database) {
@@ -83759,32 +83760,27 @@ var ExecutionReceiptTable = class {
83759
83760
  list = () => receiptSchema.array().parse(
83760
83761
  this.#database.orm.select().from(executionReceipt).orderBy(asc(executionReceipt.updatedAt), asc(executionReceipt.commandId)).all()
83761
83762
  );
83762
- save = (receipt) => {
83763
- this.#database.transaction(() => {
83764
- this.#database.orm.insert(executionReceipt).values(receipt).onConflictDoUpdate({ target: executionReceipt.commandId, set: receipt }).run();
83765
- if (receipt.state === "dispatching" || receipt.state === "running") {
83766
- return;
83767
- }
83768
- const retained = this.#database.orm.select({ commandId: executionReceipt.commandId }).from(executionReceipt).where(
83763
+ save = (receipt, terminalLimit) => this.#database.transaction(() => {
83764
+ const row = { ...receipt, state: legacyState(receipt) };
83765
+ this.#database.orm.insert(executionReceipt).values(row).onConflictDoUpdate({ target: executionReceipt.commandId, set: row }).run();
83766
+ if (receipt.outcome === null) {
83767
+ return [];
83768
+ }
83769
+ const retained = this.#database.orm.select({ commandId: executionReceipt.commandId }).from(executionReceipt).where(and(eq(executionReceipt.sessionId, receipt.sessionId), isNotNull(executionReceipt.outcome))).orderBy(desc(executionReceipt.updatedAt), desc(executionReceipt.commandId)).limit(terminalLimit).all();
83770
+ if (retained.length === terminalLimit) {
83771
+ return this.#remove(
83769
83772
  and(
83770
83773
  eq(executionReceipt.sessionId, receipt.sessionId),
83771
- inArray(executionReceipt.state, ["succeeded", "failed", "cancelled"])
83772
- )
83773
- ).orderBy(desc(executionReceipt.updatedAt), desc(executionReceipt.commandId)).limit(1024).all();
83774
- if (retained.length === 1024) {
83775
- this.#remove(
83776
- and(
83777
- eq(executionReceipt.sessionId, receipt.sessionId),
83778
- inArray(executionReceipt.state, ["succeeded", "failed", "cancelled"]),
83779
- notInArray(
83780
- executionReceipt.commandId,
83781
- retained.map((row) => row.commandId)
83782
- )
83774
+ isNotNull(executionReceipt.outcome),
83775
+ notInArray(
83776
+ executionReceipt.commandId,
83777
+ retained.map((row2) => row2.commandId)
83783
83778
  )
83784
- );
83785
- }
83786
- });
83787
- };
83779
+ )
83780
+ );
83781
+ }
83782
+ return [];
83783
+ });
83788
83784
  remove = (commandId) => {
83789
83785
  this.#database.transaction(() => this.#remove(eq(executionReceipt.commandId, commandId)));
83790
83786
  };
@@ -83799,7 +83795,7 @@ var ExecutionReceiptTable = class {
83799
83795
  commandHash: executionReceipt.commandHash
83800
83796
  }).from(executionReceipt).where(and(condition, eq(executionReceipt.started, true)))
83801
83797
  ).onConflictDoNothing().run();
83802
- this.#database.orm.delete(executionReceipt).where(condition).run();
83798
+ return this.#database.orm.delete(executionReceipt).where(condition).returning({ commandId: executionReceipt.commandId }).all().map((row) => row.commandId);
83803
83799
  };
83804
83800
  };
83805
83801
 
@@ -87006,20 +87002,15 @@ async function settleAbandonedTurn(projection, operations, cancellation) {
87006
87002
  "agent_execution_abandoned",
87007
87003
  "The local Agent execution was abandoned before it completed"
87008
87004
  );
87009
- operations.transitionExecution(cancellation.commandId, "failed");
87010
87005
  projection.publishTerminal(cancellation.sessionId, cancellation.commandId);
87011
87006
  }
87012
87007
 
87013
87008
  // src/session/turn/execution-receipts.ts
87014
87009
  import { createHash as createHash6, randomUUID as randomUUID15 } from "node:crypto";
87015
87010
  var MAX_TERMINAL_RECEIPTS = 1024;
87016
- function isTerminal(state) {
87017
- return state === "succeeded" || state === "failed" || state === "cancelled";
87018
- }
87019
87011
  var ExecutionReceipts = class {
87020
87012
  #executions = /* @__PURE__ */ new Map();
87021
87013
  #recoveredCommands = /* @__PURE__ */ new Set();
87022
- #terminalCountBySession = /* @__PURE__ */ new Map();
87023
87014
  #table;
87024
87015
  #closing = false;
87025
87016
  #activeCount = 0;
@@ -87030,36 +87021,22 @@ var ExecutionReceipts = class {
87030
87021
  for (const row of table.list()) {
87031
87022
  this.#executions.set(row.commandId, row);
87032
87023
  this.#recoveredCommands.add(row.commandId);
87033
- if (!isTerminal(row.state)) {
87024
+ if (row.outcome === null) {
87034
87025
  this.#activeCount += 1;
87035
87026
  }
87036
- if (isTerminal(row.state)) {
87037
- this.#terminalCountBySession.set(
87038
- row.sessionId,
87039
- (this.#terminalCountBySession.get(row.sessionId) ?? 0) + 1
87040
- );
87041
- }
87042
87027
  }
87043
87028
  }
87044
87029
  #save = (commandId, receipt) => {
87045
- if (!this.#closing) {
87046
- this.#table.save({ ...receipt, commandId, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
87047
- }
87030
+ const evicted = this.#closing ? [] : this.#table.save({ ...receipt, commandId, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, MAX_TERMINAL_RECEIPTS);
87048
87031
  const previous = this.#executions.get(commandId);
87049
- const wasActive = previous !== void 0 && !isTerminal(previous.state);
87050
- if (isTerminal(receipt.state)) {
87051
- this.#executions.delete(commandId);
87052
- }
87032
+ const wasActive = previous?.outcome === null;
87053
87033
  this.#executions.set(commandId, receipt);
87054
- this.#activeCount += Number(!isTerminal(receipt.state)) - Number(wasActive);
87055
- this.#onCount(this.#activeCount);
87056
- if (isTerminal(receipt.state) && (previous === void 0 || !isTerminal(previous.state))) {
87057
- this.#terminalCountBySession.set(
87058
- receipt.sessionId,
87059
- (this.#terminalCountBySession.get(receipt.sessionId) ?? 0) + 1
87060
- );
87061
- this.pruneTerminalReceipts(receipt.sessionId);
87034
+ for (const evictedCommandId of evicted) {
87035
+ this.#executions.delete(evictedCommandId);
87036
+ this.#recoveredCommands.delete(evictedCommandId);
87062
87037
  }
87038
+ this.#activeCount += Number(receipt.outcome === null) - Number(wasActive);
87039
+ this.#onCount(this.#activeCount);
87063
87040
  };
87064
87041
  beginShutdown = () => {
87065
87042
  this.#closing = true;
@@ -87072,7 +87049,7 @@ var ExecutionReceipts = class {
87072
87049
  recordCancellationBeforeAdmission = (commandId, sessionId) => {
87073
87050
  const existing = this.#executions.get(commandId);
87074
87051
  if (existing !== void 0) {
87075
- return existing.sessionId === sessionId && isTerminal(existing.state) ? this.outcome(commandId) : void 0;
87052
+ return existing.sessionId === sessionId ? this.outcome(commandId) : void 0;
87076
87053
  }
87077
87054
  const outcome = {
87078
87055
  type: "lifecycle-metadata",
@@ -87089,7 +87066,6 @@ var ExecutionReceipts = class {
87089
87066
  attemptId: randomUUID15(),
87090
87067
  commandHash,
87091
87068
  sessionId,
87092
- state: "cancelled",
87093
87069
  started: false,
87094
87070
  outcome: JSON.stringify({ ...outcome, recordedAt: (/* @__PURE__ */ new Date()).toISOString() })
87095
87071
  });
@@ -87110,7 +87086,6 @@ var ExecutionReceipts = class {
87110
87086
  const sanitized = payload.kind === "prompt.completed" ? payload : { ...payload, message: "The local Agent could not complete the request" };
87111
87087
  this.#save(payload.commandId, {
87112
87088
  ...receipt,
87113
- state: payload.kind === "prompt.completed" ? payload.stopReason === "cancelled" ? "cancelled" : "succeeded" : "failed",
87114
87089
  outcome: JSON.stringify({ type: "lifecycle-metadata", payload: sanitized, recordedAt: event.recordedAt })
87115
87090
  });
87116
87091
  };
@@ -87134,9 +87109,8 @@ var ExecutionReceipts = class {
87134
87109
  } : sessionEventPayloadSchema.parse(JSON.parse(receipt.outcome));
87135
87110
  const recordedAt = receipt.outcome === null ? (/* @__PURE__ */ new Date()).toISOString() : external_exports.object({ recordedAt: external_exports.string() }).parse(JSON.parse(receipt.outcome)).recordedAt;
87136
87111
  recovered.push({ sessionId: receipt.sessionId, event, recordedAt });
87137
- if (!isTerminal(receipt.state)) {
87138
- const state = event.type === "lifecycle-metadata" && event.payload.kind === "prompt.completed" ? event.payload.stopReason === "cancelled" ? "cancelled" : "succeeded" : "failed";
87139
- this.#save(commandId, { ...receipt, state, outcome: JSON.stringify({ ...event, recordedAt }) });
87112
+ if (receipt.outcome === null) {
87113
+ this.#save(commandId, { ...receipt, outcome: JSON.stringify({ ...event, recordedAt }) });
87140
87114
  }
87141
87115
  }
87142
87116
  return recovered;
@@ -87149,10 +87123,6 @@ var ExecutionReceipts = class {
87149
87123
  this.#table.remove(commandId);
87150
87124
  this.#executions.delete(commandId);
87151
87125
  this.#recoveredCommands.delete(commandId);
87152
- this.#terminalCountBySession.set(
87153
- sessionId,
87154
- Math.max(0, (this.#terminalCountBySession.get(sessionId) ?? 1) - 1)
87155
- );
87156
87126
  existing = void 0;
87157
87127
  }
87158
87128
  if (existing !== void 0) {
@@ -87163,7 +87133,6 @@ var ExecutionReceipts = class {
87163
87133
  attemptId: existing.attemptId,
87164
87134
  commandId,
87165
87135
  kind: "duplicate",
87166
- state: existing.state,
87167
87136
  outcome: this.#recoveredCommands.has(commandId) ? this.outcome(commandId) : void 0
87168
87137
  };
87169
87138
  }
@@ -87176,66 +87145,37 @@ var ExecutionReceipts = class {
87176
87145
  attemptId,
87177
87146
  commandHash,
87178
87147
  sessionId,
87179
- state: "dispatching",
87180
87148
  started: false,
87181
87149
  outcome: null
87182
87150
  });
87183
- return { attemptId, commandId, kind: "accepted", state: "dispatching" };
87151
+ return { attemptId, commandId, kind: "accepted" };
87184
87152
  };
87185
- transitionExecution = (commandId, state) => {
87153
+ markExecutionStarted = (commandId) => {
87186
87154
  const current = this.#executions.get(commandId);
87187
87155
  if (current === void 0) {
87188
87156
  throw new Error("The runtime execution receipt does not exist");
87189
87157
  }
87190
- if (current.state === state) {
87191
- return;
87192
- }
87193
- const allowed = current.state === "dispatching" && (state === "running" || state === "failed" || state === "cancelled") || current.state === "running" && isTerminal(state);
87194
- if (!allowed) {
87158
+ if (current.outcome !== null) {
87195
87159
  throw new Error("The runtime execution transition is invalid");
87196
87160
  }
87197
- if (state === "running") {
87198
- this.#save(commandId, { ...current, state, started: true });
87199
- } else if (isTerminal(state)) {
87200
- this.#save(commandId, { ...current, state });
87161
+ if (!current.started) {
87162
+ this.#save(commandId, { ...current, started: true });
87201
87163
  }
87202
87164
  };
87203
87165
  /** Only commands without a terminal result can still be cancelled. */
87204
87166
  findUnsettledAttemptId = (commandId, sessionId) => {
87205
87167
  const receipt = this.#executions.get(commandId);
87206
- return receipt?.sessionId === sessionId && !isTerminal(receipt.state) ? receipt.attemptId : null;
87168
+ return receipt?.sessionId === sessionId && receipt.outcome === null ? receipt.attemptId : null;
87207
87169
  };
87208
87170
  isTerminalExecution = (commandId, sessionId) => {
87209
87171
  const receipt = this.#executions.get(commandId);
87210
- return receipt?.sessionId === sessionId && isTerminal(receipt.state);
87172
+ return receipt?.sessionId === sessionId && receipt.outcome !== null;
87211
87173
  };
87212
87174
  close = () => {
87213
87175
  this.#executions.clear();
87214
87176
  this.#recoveredCommands.clear();
87215
- this.#terminalCountBySession.clear();
87216
87177
  this.#activeCount = 0;
87217
87178
  };
87218
- pruneTerminalReceipts = (sessionId) => {
87219
- if ((this.#terminalCountBySession.get(sessionId) ?? 0) <= MAX_TERMINAL_RECEIPTS) {
87220
- return;
87221
- }
87222
- for (const [commandId, receipt] of this.#executions) {
87223
- if (receipt.sessionId === sessionId && isTerminal(receipt.state)) {
87224
- this.#table.remove(commandId);
87225
- this.#executions.delete(commandId);
87226
- this.#recoveredCommands.delete(commandId);
87227
- const remaining = (this.#terminalCountBySession.get(sessionId) ?? 1) - 1;
87228
- if (remaining > 0) {
87229
- this.#terminalCountBySession.set(sessionId, remaining);
87230
- } else {
87231
- this.#terminalCountBySession.delete(sessionId);
87232
- }
87233
- if ((this.#terminalCountBySession.get(sessionId) ?? 0) <= MAX_TERMINAL_RECEIPTS) {
87234
- return;
87235
- }
87236
- }
87237
- }
87238
- };
87239
87179
  };
87240
87180
 
87241
87181
  // src/session/turn/runtime-turn-activity.ts
@@ -90364,7 +90304,7 @@ async function executePrompt({
90364
90304
  );
90365
90305
  prepared = await sessions.prepareExecutionSession(preparation);
90366
90306
  }
90367
- operations.transitionExecution(command.commandId, "running");
90307
+ operations.markExecutionStarted(command.commandId);
90368
90308
  if (availability.disposition === SessionPromptDisposition.Steer) {
90369
90309
  if (!recordSteeringPrompt()) {
90370
90310
  throw new AcpExecutionError(
@@ -90420,18 +90360,15 @@ async function executePrompt({
90420
90360
  stopReason = result.stopReason;
90421
90361
  }
90422
90362
  await eventProjection.completed(command.sessionId, command.commandId, stopReason);
90423
- operations.transitionExecution(command.commandId, stopReason === "cancelled" ? "cancelled" : "succeeded");
90424
90363
  } catch (error62) {
90425
90364
  if (signal.aborted && cancellationRequested()) {
90426
90365
  await eventProjection.completed(command.sessionId, command.commandId, "cancelled");
90427
- operations.transitionExecution(command.commandId, "cancelled");
90428
90366
  return;
90429
90367
  }
90430
90368
  const code = operationErrorCode(error62);
90431
90369
  const failureCode = code === "session_operation_failed" ? "agent_execution_failed" : code;
90432
90370
  const failureMessage = code === "session_operation_failed" ? "The local agent could not complete the request" : operationErrorMessage(error62);
90433
90371
  await eventProjection.failed(command.sessionId, command.commandId, failureCode, failureMessage);
90434
- operations.transitionExecution(command.commandId, "failed");
90435
90372
  reportFailure("session_prompt_failed", command.commandId, {
90436
90373
  agentId: command.agentId,
90437
90374
  code: failureCode,