@moxt-ai/mobius 0.0.331 → 0.0.333

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
@@ -22484,6 +22484,37 @@ var sessionLiveEventSchema = external_exports.discriminatedUnion("type", [
22484
22484
  type: external_exports.literal("lifecycle-metadata")
22485
22485
  }).readonly()
22486
22486
  ]);
22487
+ var wireLifecyclePayloadSchema = external_exports.object({
22488
+ kind: identifierStringSchema,
22489
+ commandId: identifierStringSchema.optional(),
22490
+ context: promptExecutionContextSchema.unwrap().passthrough().readonly().optional(),
22491
+ event: external_exports.object({ interactionId: identifierStringSchema.optional() }).passthrough().readonly().optional()
22492
+ }).passthrough().readonly();
22493
+ var wireEventFields = {
22494
+ ...sessionLiveEventFields,
22495
+ mobiusMetadata: external_exports.object({ omitted: external_exports.literal(true).optional() }).passthrough().readonly().optional()
22496
+ };
22497
+ var sessionWireEventSchema = external_exports.union([
22498
+ external_exports.object({
22499
+ ...wireEventFields,
22500
+ type: external_exports.literal("acp"),
22501
+ payload: external_exports.object({ sessionUpdate: identifierStringSchema }).passthrough().readonly()
22502
+ }).passthrough().readonly(),
22503
+ external_exports.object({
22504
+ ...wireEventFields,
22505
+ type: external_exports.literal("lifecycle-metadata"),
22506
+ payload: wireLifecyclePayloadSchema
22507
+ }).passthrough().readonly(),
22508
+ external_exports.object({
22509
+ ...wireEventFields,
22510
+ type: identifierStringSchema.refine((type) => type !== "acp" && type !== "lifecycle-metadata"),
22511
+ payload: external_exports.record(external_exports.string(), external_exports.unknown()).readonly()
22512
+ }).passthrough().readonly()
22513
+ ]);
22514
+ var sessionWireEnvelopeSchema = external_exports.object({
22515
+ kind: external_exports.literal(SESSION_EVENT_KIND),
22516
+ events: external_exports.array(sessionWireEventSchema).min(1).max(SESSION_EVENT_BATCH_MAX_SIZE).readonly()
22517
+ }).readonly();
22487
22518
  var sessionEventBatchSchema = external_exports.array(sessionEventSchema).min(1).max(SESSION_EVENT_BATCH_MAX_SIZE).readonly();
22488
22519
  var sessionLiveEventBatchSchema = external_exports.array(sessionLiveEventSchema).min(1).max(SESSION_EVENT_BATCH_MAX_SIZE).readonly();
22489
22520
  var sessionExportSchema = external_exports.object({
@@ -32545,7 +32576,7 @@ import { fetch as fetch3 } from "undici";
32545
32576
  // package.json
32546
32577
  var package_default = {
32547
32578
  name: "@moxt-ai/mobius",
32548
- version: "0.0.331",
32579
+ version: "0.0.333",
32549
32580
  description: "Mobius CLI for pairing and running local AI agent services.",
32550
32581
  type: "module",
32551
32582
  bin: {
@@ -83682,6 +83713,7 @@ var executionReceipt = sqliteTable("execution_receipt", {
83682
83713
  sessionId: text("session_id").notNull(),
83683
83714
  commandHash: text("command_hash").notNull(),
83684
83715
  attemptId: text("attempt_id").notNull(),
83716
+ // Compatibility projection for older Runtimes; started and outcome own the facts.
83685
83717
  state: text("state").notNull(),
83686
83718
  started: integer2("started", { mode: "boolean" }).notNull(),
83687
83719
  outcome: text("outcome"),
@@ -83730,23 +83762,23 @@ var AcpSessionTable = class {
83730
83762
  };
83731
83763
 
83732
83764
  // src/storage/session/execution-receipt-table.ts
83733
- var receiptFields = external_exports.object({
83765
+ var receiptSchema = external_exports.object({
83734
83766
  commandId: external_exports.string(),
83735
83767
  sessionId: external_exports.string(),
83736
83768
  commandHash: external_exports.string(),
83737
83769
  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();
83770
+ updatedAt: external_exports.string(),
83771
+ started: external_exports.boolean(),
83772
+ outcome: external_exports.string().nullable()
83773
+ }).readonly();
83749
83774
  var identitySchema = external_exports.object({ sessionId: external_exports.string(), commandHash: external_exports.string() }).readonly();
83775
+ function legacyState(receipt) {
83776
+ if (receipt.outcome === null) {
83777
+ return receipt.started ? "running" : "dispatching";
83778
+ }
83779
+ const event = sessionEventPayloadSchema.parse(JSON.parse(receipt.outcome));
83780
+ return event.type === "lifecycle-metadata" && event.payload.kind === "prompt.completed" ? event.payload.stopReason === "cancelled" ? "cancelled" : "succeeded" : "failed";
83781
+ }
83750
83782
  var ExecutionReceiptTable = class {
83751
83783
  #database;
83752
83784
  constructor(database) {
@@ -83759,32 +83791,27 @@ var ExecutionReceiptTable = class {
83759
83791
  list = () => receiptSchema.array().parse(
83760
83792
  this.#database.orm.select().from(executionReceipt).orderBy(asc(executionReceipt.updatedAt), asc(executionReceipt.commandId)).all()
83761
83793
  );
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(
83794
+ save = (receipt, terminalLimit) => this.#database.transaction(() => {
83795
+ const row = { ...receipt, state: legacyState(receipt) };
83796
+ this.#database.orm.insert(executionReceipt).values(row).onConflictDoUpdate({ target: executionReceipt.commandId, set: row }).run();
83797
+ if (receipt.outcome === null) {
83798
+ return [];
83799
+ }
83800
+ 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();
83801
+ if (retained.length === terminalLimit) {
83802
+ return this.#remove(
83769
83803
  and(
83770
83804
  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
- )
83805
+ isNotNull(executionReceipt.outcome),
83806
+ notInArray(
83807
+ executionReceipt.commandId,
83808
+ retained.map((row2) => row2.commandId)
83783
83809
  )
83784
- );
83785
- }
83786
- });
83787
- };
83810
+ )
83811
+ );
83812
+ }
83813
+ return [];
83814
+ });
83788
83815
  remove = (commandId) => {
83789
83816
  this.#database.transaction(() => this.#remove(eq(executionReceipt.commandId, commandId)));
83790
83817
  };
@@ -83799,7 +83826,7 @@ var ExecutionReceiptTable = class {
83799
83826
  commandHash: executionReceipt.commandHash
83800
83827
  }).from(executionReceipt).where(and(condition, eq(executionReceipt.started, true)))
83801
83828
  ).onConflictDoNothing().run();
83802
- this.#database.orm.delete(executionReceipt).where(condition).run();
83829
+ return this.#database.orm.delete(executionReceipt).where(condition).returning({ commandId: executionReceipt.commandId }).all().map((row) => row.commandId);
83803
83830
  };
83804
83831
  };
83805
83832
 
@@ -87006,20 +87033,15 @@ async function settleAbandonedTurn(projection, operations, cancellation) {
87006
87033
  "agent_execution_abandoned",
87007
87034
  "The local Agent execution was abandoned before it completed"
87008
87035
  );
87009
- operations.transitionExecution(cancellation.commandId, "failed");
87010
87036
  projection.publishTerminal(cancellation.sessionId, cancellation.commandId);
87011
87037
  }
87012
87038
 
87013
87039
  // src/session/turn/execution-receipts.ts
87014
87040
  import { createHash as createHash6, randomUUID as randomUUID15 } from "node:crypto";
87015
87041
  var MAX_TERMINAL_RECEIPTS = 1024;
87016
- function isTerminal(state) {
87017
- return state === "succeeded" || state === "failed" || state === "cancelled";
87018
- }
87019
87042
  var ExecutionReceipts = class {
87020
87043
  #executions = /* @__PURE__ */ new Map();
87021
87044
  #recoveredCommands = /* @__PURE__ */ new Set();
87022
- #terminalCountBySession = /* @__PURE__ */ new Map();
87023
87045
  #table;
87024
87046
  #closing = false;
87025
87047
  #activeCount = 0;
@@ -87030,36 +87052,22 @@ var ExecutionReceipts = class {
87030
87052
  for (const row of table.list()) {
87031
87053
  this.#executions.set(row.commandId, row);
87032
87054
  this.#recoveredCommands.add(row.commandId);
87033
- if (!isTerminal(row.state)) {
87055
+ if (row.outcome === null) {
87034
87056
  this.#activeCount += 1;
87035
87057
  }
87036
- if (isTerminal(row.state)) {
87037
- this.#terminalCountBySession.set(
87038
- row.sessionId,
87039
- (this.#terminalCountBySession.get(row.sessionId) ?? 0) + 1
87040
- );
87041
- }
87042
87058
  }
87043
87059
  }
87044
87060
  #save = (commandId, receipt) => {
87045
- if (!this.#closing) {
87046
- this.#table.save({ ...receipt, commandId, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
87047
- }
87061
+ const evicted = this.#closing ? [] : this.#table.save({ ...receipt, commandId, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, MAX_TERMINAL_RECEIPTS);
87048
87062
  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
- }
87063
+ const wasActive = previous?.outcome === null;
87053
87064
  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);
87065
+ for (const evictedCommandId of evicted) {
87066
+ this.#executions.delete(evictedCommandId);
87067
+ this.#recoveredCommands.delete(evictedCommandId);
87062
87068
  }
87069
+ this.#activeCount += Number(receipt.outcome === null) - Number(wasActive);
87070
+ this.#onCount(this.#activeCount);
87063
87071
  };
87064
87072
  beginShutdown = () => {
87065
87073
  this.#closing = true;
@@ -87072,7 +87080,7 @@ var ExecutionReceipts = class {
87072
87080
  recordCancellationBeforeAdmission = (commandId, sessionId) => {
87073
87081
  const existing = this.#executions.get(commandId);
87074
87082
  if (existing !== void 0) {
87075
- return existing.sessionId === sessionId && isTerminal(existing.state) ? this.outcome(commandId) : void 0;
87083
+ return existing.sessionId === sessionId ? this.outcome(commandId) : void 0;
87076
87084
  }
87077
87085
  const outcome = {
87078
87086
  type: "lifecycle-metadata",
@@ -87089,7 +87097,6 @@ var ExecutionReceipts = class {
87089
87097
  attemptId: randomUUID15(),
87090
87098
  commandHash,
87091
87099
  sessionId,
87092
- state: "cancelled",
87093
87100
  started: false,
87094
87101
  outcome: JSON.stringify({ ...outcome, recordedAt: (/* @__PURE__ */ new Date()).toISOString() })
87095
87102
  });
@@ -87110,7 +87117,6 @@ var ExecutionReceipts = class {
87110
87117
  const sanitized = payload.kind === "prompt.completed" ? payload : { ...payload, message: "The local Agent could not complete the request" };
87111
87118
  this.#save(payload.commandId, {
87112
87119
  ...receipt,
87113
- state: payload.kind === "prompt.completed" ? payload.stopReason === "cancelled" ? "cancelled" : "succeeded" : "failed",
87114
87120
  outcome: JSON.stringify({ type: "lifecycle-metadata", payload: sanitized, recordedAt: event.recordedAt })
87115
87121
  });
87116
87122
  };
@@ -87134,9 +87140,8 @@ var ExecutionReceipts = class {
87134
87140
  } : sessionEventPayloadSchema.parse(JSON.parse(receipt.outcome));
87135
87141
  const recordedAt = receipt.outcome === null ? (/* @__PURE__ */ new Date()).toISOString() : external_exports.object({ recordedAt: external_exports.string() }).parse(JSON.parse(receipt.outcome)).recordedAt;
87136
87142
  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 }) });
87143
+ if (receipt.outcome === null) {
87144
+ this.#save(commandId, { ...receipt, outcome: JSON.stringify({ ...event, recordedAt }) });
87140
87145
  }
87141
87146
  }
87142
87147
  return recovered;
@@ -87149,10 +87154,6 @@ var ExecutionReceipts = class {
87149
87154
  this.#table.remove(commandId);
87150
87155
  this.#executions.delete(commandId);
87151
87156
  this.#recoveredCommands.delete(commandId);
87152
- this.#terminalCountBySession.set(
87153
- sessionId,
87154
- Math.max(0, (this.#terminalCountBySession.get(sessionId) ?? 1) - 1)
87155
- );
87156
87157
  existing = void 0;
87157
87158
  }
87158
87159
  if (existing !== void 0) {
@@ -87163,7 +87164,6 @@ var ExecutionReceipts = class {
87163
87164
  attemptId: existing.attemptId,
87164
87165
  commandId,
87165
87166
  kind: "duplicate",
87166
- state: existing.state,
87167
87167
  outcome: this.#recoveredCommands.has(commandId) ? this.outcome(commandId) : void 0
87168
87168
  };
87169
87169
  }
@@ -87176,66 +87176,37 @@ var ExecutionReceipts = class {
87176
87176
  attemptId,
87177
87177
  commandHash,
87178
87178
  sessionId,
87179
- state: "dispatching",
87180
87179
  started: false,
87181
87180
  outcome: null
87182
87181
  });
87183
- return { attemptId, commandId, kind: "accepted", state: "dispatching" };
87182
+ return { attemptId, commandId, kind: "accepted" };
87184
87183
  };
87185
- transitionExecution = (commandId, state) => {
87184
+ markExecutionStarted = (commandId) => {
87186
87185
  const current = this.#executions.get(commandId);
87187
87186
  if (current === void 0) {
87188
87187
  throw new Error("The runtime execution receipt does not exist");
87189
87188
  }
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) {
87189
+ if (current.outcome !== null) {
87195
87190
  throw new Error("The runtime execution transition is invalid");
87196
87191
  }
87197
- if (state === "running") {
87198
- this.#save(commandId, { ...current, state, started: true });
87199
- } else if (isTerminal(state)) {
87200
- this.#save(commandId, { ...current, state });
87192
+ if (!current.started) {
87193
+ this.#save(commandId, { ...current, started: true });
87201
87194
  }
87202
87195
  };
87203
87196
  /** Only commands without a terminal result can still be cancelled. */
87204
87197
  findUnsettledAttemptId = (commandId, sessionId) => {
87205
87198
  const receipt = this.#executions.get(commandId);
87206
- return receipt?.sessionId === sessionId && !isTerminal(receipt.state) ? receipt.attemptId : null;
87199
+ return receipt?.sessionId === sessionId && receipt.outcome === null ? receipt.attemptId : null;
87207
87200
  };
87208
87201
  isTerminalExecution = (commandId, sessionId) => {
87209
87202
  const receipt = this.#executions.get(commandId);
87210
- return receipt?.sessionId === sessionId && isTerminal(receipt.state);
87203
+ return receipt?.sessionId === sessionId && receipt.outcome !== null;
87211
87204
  };
87212
87205
  close = () => {
87213
87206
  this.#executions.clear();
87214
87207
  this.#recoveredCommands.clear();
87215
- this.#terminalCountBySession.clear();
87216
87208
  this.#activeCount = 0;
87217
87209
  };
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
87210
  };
87240
87211
 
87241
87212
  // src/session/turn/runtime-turn-activity.ts
@@ -90364,7 +90335,7 @@ async function executePrompt({
90364
90335
  );
90365
90336
  prepared = await sessions.prepareExecutionSession(preparation);
90366
90337
  }
90367
- operations.transitionExecution(command.commandId, "running");
90338
+ operations.markExecutionStarted(command.commandId);
90368
90339
  if (availability.disposition === SessionPromptDisposition.Steer) {
90369
90340
  if (!recordSteeringPrompt()) {
90370
90341
  throw new AcpExecutionError(
@@ -90420,18 +90391,15 @@ async function executePrompt({
90420
90391
  stopReason = result.stopReason;
90421
90392
  }
90422
90393
  await eventProjection.completed(command.sessionId, command.commandId, stopReason);
90423
- operations.transitionExecution(command.commandId, stopReason === "cancelled" ? "cancelled" : "succeeded");
90424
90394
  } catch (error62) {
90425
90395
  if (signal.aborted && cancellationRequested()) {
90426
90396
  await eventProjection.completed(command.sessionId, command.commandId, "cancelled");
90427
- operations.transitionExecution(command.commandId, "cancelled");
90428
90397
  return;
90429
90398
  }
90430
90399
  const code = operationErrorCode(error62);
90431
90400
  const failureCode = code === "session_operation_failed" ? "agent_execution_failed" : code;
90432
90401
  const failureMessage = code === "session_operation_failed" ? "The local agent could not complete the request" : operationErrorMessage(error62);
90433
90402
  await eventProjection.failed(command.sessionId, command.commandId, failureCode, failureMessage);
90434
- operations.transitionExecution(command.commandId, "failed");
90435
90403
  reportFailure("session_prompt_failed", command.commandId, {
90436
90404
  agentId: command.agentId,
90437
90405
  code: failureCode,