@moxt-ai/mobius 0.0.7 → 0.0.8

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/index.js CHANGED
@@ -20988,7 +20988,7 @@ var AcpActivity = class _AcpActivity {
20988
20988
  toolKind;
20989
20989
  content;
20990
20990
  detail;
20991
- constructor(activityId, activityType, input2, locations, name, output2, sequence, status, title, toolKind, content = [], detail = captureActivityDetail(
20991
+ constructor(activityId, activityType, input2, locations, name, output2, sequence, status, title2, toolKind, content = [], detail = captureActivityDetail(
20992
20992
  content,
20993
20993
  input2,
20994
20994
  output2
@@ -21001,7 +21001,7 @@ var AcpActivity = class _AcpActivity {
21001
21001
  this.output = output2;
21002
21002
  this.sequence = sequence;
21003
21003
  this.status = status;
21004
- this.title = title;
21004
+ this.title = title2;
21005
21005
  this.toolKind = toolKind;
21006
21006
  this.content = content;
21007
21007
  this.detail = detail;
@@ -21217,8 +21217,8 @@ function normalizeToolStatus(status, fallback) {
21217
21217
  }
21218
21218
  return fallback;
21219
21219
  }
21220
- function normalizeTitle(title, fallback) {
21221
- const normalized = title.trim();
21220
+ function normalizeTitle(title2, fallback) {
21221
+ const normalized = title2.trim();
21222
21222
  return truncate(normalized.length === 0 ? fallback : normalized, 500);
21223
21223
  }
21224
21224
  function formatPlanEntries(entries) {
@@ -21464,12 +21464,13 @@ var AcpActivityTracker = class {
21464
21464
 
21465
21465
  // src/acp/native-session.ts
21466
21466
  var path = external_exports.string().min(1).max(2048).refine((value) => !value.includes("\0"));
21467
+ var title = external_exports.string().transform((value) => value.slice(0, 500));
21467
21468
  var nativeSessionIdSchema = external_exports.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,255}$/);
21468
21469
  var nativeSessionInfoSchema = external_exports.object({
21469
21470
  sessionId: nativeSessionIdSchema,
21470
21471
  cwd: path,
21471
21472
  additionalDirectories: external_exports.array(path).max(16).default([]).readonly(),
21472
- title: external_exports.string().max(500).nullish(),
21473
+ title: title.nullish(),
21473
21474
  updatedAt: external_exports.iso.datetime({ offset: true }).nullish()
21474
21475
  }).readonly();
21475
21476
  var nativeSessionPageSchema = external_exports.object({
@@ -21792,6 +21793,12 @@ var AcpExecutionError = class extends Error {
21792
21793
  this.name = "AcpExecutionError";
21793
21794
  }
21794
21795
  };
21796
+ var RetryableAcpInitializationError = class extends AcpExecutionError {
21797
+ constructor(cause) {
21798
+ super("ACP agent initialization failed", { cause });
21799
+ this.name = "RetryableAcpInitializationError";
21800
+ }
21801
+ };
21795
21802
  function readableWebStream(input2) {
21796
21803
  let streamOpen = true;
21797
21804
  return new ReadableStream({
@@ -22421,42 +22428,63 @@ var AcpProcessSession = class _AcpProcessSession {
22421
22428
  );
22422
22429
  this.#connection = createAcpClient(this).connect(stream);
22423
22430
  }
22424
- static start = async (options, getObserver, store) => {
22425
- options.signal.throwIfAborted();
22426
- const [adapterUnchanged, agentUnchanged] = await Promise.all([
22427
- revalidateExecutable(options.agent.adapterIdentity),
22428
- revalidateExecutable(options.agent.agentIdentity)
22429
- ]);
22430
- options.signal.throwIfAborted();
22431
- if (!adapterUnchanged || !agentUnchanged) {
22432
- throw new AcpExecutionError(
22433
- "The local Agent runtime changed; restart Mobius before starting a new conversation",
22434
- {},
22435
- "agent_runtime_changed"
22436
- );
22437
- }
22438
- const runtime = new _AcpProcessSession(
22439
- options.agent,
22440
- options.cwd,
22441
- options.additionalDirectories,
22442
- options.sessionId,
22443
- getObserver,
22444
- store
22445
- );
22446
- try {
22447
- await runtime.initialize(options.signal, options.origin);
22448
- return runtime;
22449
- } catch (error61) {
22450
- await runtime.closeProcess();
22431
+ static async #start(options, getObserver, store, initialize) {
22432
+ for (let attempt = 1; attempt <= 2; attempt += 1) {
22451
22433
  options.signal.throwIfAborted();
22452
- if (error61 instanceof AcpExecutionError) {
22453
- throw error61;
22434
+ const [adapterUnchanged, agentUnchanged] = await Promise.all([
22435
+ revalidateExecutable(options.agent.adapterIdentity),
22436
+ revalidateExecutable(options.agent.agentIdentity)
22437
+ ]);
22438
+ options.signal.throwIfAborted();
22439
+ if (!adapterUnchanged || !agentUnchanged) {
22440
+ throw new AcpExecutionError(
22441
+ "The local Agent runtime changed; restart Mobius before starting a new conversation",
22442
+ {},
22443
+ "agent_runtime_changed"
22444
+ );
22445
+ }
22446
+ const runtime = new _AcpProcessSession(
22447
+ options.agent,
22448
+ options.cwd,
22449
+ options.additionalDirectories,
22450
+ options.sessionId,
22451
+ getObserver,
22452
+ store
22453
+ );
22454
+ try {
22455
+ await initialize(runtime);
22456
+ return runtime;
22457
+ } catch (error61) {
22458
+ await runtime.closeProcess();
22459
+ options.signal.throwIfAborted();
22460
+ if (error61 instanceof RetryableAcpInitializationError && attempt === 1) {
22461
+ console.warn(
22462
+ `[${options.agent.id}-acp] ACP agent initialization failed; retrying once`
22463
+ );
22464
+ continue;
22465
+ }
22466
+ if (error61 instanceof AcpExecutionError) {
22467
+ throw error61;
22468
+ }
22469
+ throw new AcpExecutionError("ACP agent initialization failed", {
22470
+ cause: error61
22471
+ });
22454
22472
  }
22455
- throw new AcpExecutionError("ACP agent initialization failed", {
22456
- cause: error61
22457
- });
22458
22473
  }
22459
- };
22474
+ throw new AcpExecutionError("ACP agent initialization failed");
22475
+ }
22476
+ static start = async (options, getObserver, store) => await _AcpProcessSession.#start(
22477
+ options,
22478
+ getObserver,
22479
+ store,
22480
+ async (runtime) => await runtime.initialize(options.signal, options.origin)
22481
+ );
22482
+ static startNativeSessionBrowser = async (options, getObserver, store) => await _AcpProcessSession.#start(
22483
+ options,
22484
+ getObserver,
22485
+ store,
22486
+ async (runtime) => await runtime.#initializeAgent(options.signal)
22487
+ );
22460
22488
  belongsTo = (agentId, cwd, additionalDirectories) => this.#agentId === agentId && this.#cwd === cwd && arraysEqual(this.#additionalDirectories, additionalDirectories);
22461
22489
  canRebind = () => !this.#prompted && !this.#turn.running;
22462
22490
  prepared = () => new AcpPreparedSession(
@@ -22493,7 +22521,7 @@ var AcpProcessSession = class _AcpProcessSession {
22493
22521
  this.#replay = { kind: "idle" };
22494
22522
  }
22495
22523
  };
22496
- initialize = async (signal, origin) => {
22524
+ async #initializeAgent(signal) {
22497
22525
  const initialized = await this.race(
22498
22526
  this.#connection.agent.request(
22499
22527
  methods2.agent.initialize,
@@ -22510,7 +22538,10 @@ var AcpProcessSession = class _AcpProcessSession {
22510
22538
  ),
22511
22539
  "ACP agent exited during initialization",
22512
22540
  signal
22513
- );
22541
+ ).catch((cause) => {
22542
+ signal.throwIfAborted();
22543
+ throw new RetryableAcpInitializationError(cause);
22544
+ });
22514
22545
  if (initialized.protocolVersion !== PROTOCOL_VERSION) {
22515
22546
  throw new AcpExecutionError(
22516
22547
  "ACP agent selected an unsupported protocol version",
@@ -22525,6 +22556,9 @@ var AcpProcessSession = class _AcpProcessSession {
22525
22556
  255
22526
22557
  );
22527
22558
  this.#agentVersion = truncate2(initialized.agentInfo?.version ?? "", 128);
22559
+ }
22560
+ initialize = async (signal, origin) => {
22561
+ await this.#initializeAgent(signal);
22528
22562
  const stored = origin?.kind === "import" ? new FoundAcpStoredSession(
22529
22563
  new AcpStoredSession(
22530
22564
  this.#mobiusSessionId,
@@ -23349,6 +23383,10 @@ var AcpProcessSession = class _AcpProcessSession {
23349
23383
  };
23350
23384
  var AcpSessionManager = class {
23351
23385
  #nativeOperations = /* @__PURE__ */ new Set();
23386
+ #nativeBrowserObserver = new NullAcpSessionObserver();
23387
+ #nativeBrowserPreparing = /* @__PURE__ */ new Map();
23388
+ #nativeBrowserSessions = /* @__PURE__ */ new Map();
23389
+ #nativeBrowserStore = new MemoryAcpSessionStore();
23352
23390
  #activeSessionIds = /* @__PURE__ */ new Set();
23353
23391
  #cancellationRequests = /* @__PURE__ */ new Set();
23354
23392
  #preparing = /* @__PURE__ */ new Map();
@@ -23362,6 +23400,43 @@ var AcpSessionManager = class {
23362
23400
  setObserver = (observer) => {
23363
23401
  this.#observer = observer;
23364
23402
  };
23403
+ async #startNativeBrowserPreparation(options) {
23404
+ const operation = (async () => {
23405
+ try {
23406
+ const runtime = await AcpProcessSession.startNativeSessionBrowser(
23407
+ options,
23408
+ () => this.#nativeBrowserObserver,
23409
+ this.#nativeBrowserStore
23410
+ );
23411
+ this.#nativeBrowserSessions.set(options.sessionId, runtime);
23412
+ return runtime;
23413
+ } finally {
23414
+ this.#nativeBrowserPreparing.delete(options.sessionId);
23415
+ }
23416
+ })();
23417
+ this.#nativeBrowserPreparing.set(options.sessionId, operation);
23418
+ return await operation;
23419
+ }
23420
+ async #replaceNativeBrowserPreparation(existing, options) {
23421
+ const operation = (async () => {
23422
+ try {
23423
+ this.#nativeBrowserSessions.delete(options.sessionId);
23424
+ await existing.close();
23425
+ this.#nativeBrowserStore.remove(options.sessionId);
23426
+ const runtime = await AcpProcessSession.startNativeSessionBrowser(
23427
+ options,
23428
+ () => this.#nativeBrowserObserver,
23429
+ this.#nativeBrowserStore
23430
+ );
23431
+ this.#nativeBrowserSessions.set(options.sessionId, runtime);
23432
+ return runtime;
23433
+ } finally {
23434
+ this.#nativeBrowserPreparing.delete(options.sessionId);
23435
+ }
23436
+ })();
23437
+ this.#nativeBrowserPreparing.set(options.sessionId, operation);
23438
+ return await operation;
23439
+ }
23365
23440
  async #startPreparation(options) {
23366
23441
  const operation = (async () => {
23367
23442
  try {
@@ -23449,6 +23524,44 @@ var AcpSessionManager = class {
23449
23524
  const runtime = await this.#startPreparation(options);
23450
23525
  return runtime.prepared();
23451
23526
  };
23527
+ prepareNativeSessionBrowser = async (options) => {
23528
+ const pending = this.#nativeBrowserPreparing.get(options.sessionId);
23529
+ if (pending !== void 0) {
23530
+ const runtime2 = await pending;
23531
+ if (runtime2.belongsTo(
23532
+ options.agent.id,
23533
+ options.cwd,
23534
+ options.additionalDirectories
23535
+ )) {
23536
+ return runtime2.prepared();
23537
+ }
23538
+ return await this.prepareNativeSessionBrowser(options);
23539
+ }
23540
+ const existing = this.#nativeBrowserSessions.get(options.sessionId);
23541
+ if (existing !== void 0) {
23542
+ if (existing.belongsTo(
23543
+ options.agent.id,
23544
+ options.cwd,
23545
+ options.additionalDirectories
23546
+ )) {
23547
+ return existing.prepared();
23548
+ }
23549
+ if (!existing.canRebind()) {
23550
+ throw new AcpExecutionError(
23551
+ "The agent or workspace cannot change after a conversation has started",
23552
+ {},
23553
+ "session_identity_mismatch"
23554
+ );
23555
+ }
23556
+ const runtime2 = await this.#replaceNativeBrowserPreparation(
23557
+ existing,
23558
+ options
23559
+ );
23560
+ return runtime2.prepared();
23561
+ }
23562
+ const runtime = await this.#startNativeBrowserPreparation(options);
23563
+ return runtime.prepared();
23564
+ };
23452
23565
  configureSession = async (options) => {
23453
23566
  const runtime = await this.ensureSession(options);
23454
23567
  return await runtime.configure(options);
@@ -23537,8 +23650,14 @@ var AcpSessionManager = class {
23537
23650
  };
23538
23651
  close = async () => {
23539
23652
  const sessions = [...this.#sessions.values()];
23653
+ const nativeBrowserSessions = [...this.#nativeBrowserSessions.values()];
23540
23654
  this.#sessions.clear();
23541
- await Promise.all(sessions.map(async (session) => await session.close()));
23655
+ this.#nativeBrowserSessions.clear();
23656
+ await Promise.all(
23657
+ [...sessions, ...nativeBrowserSessions].map(
23658
+ async (session) => await session.close()
23659
+ )
23660
+ );
23542
23661
  };
23543
23662
  ensureSession = async (options) => {
23544
23663
  const existing = this.#sessions.get(options.sessionId);
@@ -23563,7 +23682,30 @@ var AcpSessionManager = class {
23563
23682
  }
23564
23683
  return started;
23565
23684
  };
23566
- listNativeSessions = async (options, cursor) => await (await this.ensureSession(options)).listNativeSessions(
23685
+ async #ensureNativeSessionBrowser(options) {
23686
+ const existing = this.#nativeBrowserSessions.get(options.sessionId);
23687
+ if (existing !== void 0) {
23688
+ if (!existing.belongsTo(
23689
+ options.agent.id,
23690
+ options.cwd,
23691
+ options.additionalDirectories
23692
+ )) {
23693
+ throw new AcpExecutionError(
23694
+ "The agent or workspace cannot change after a conversation has started",
23695
+ {},
23696
+ "session_identity_mismatch"
23697
+ );
23698
+ }
23699
+ return existing;
23700
+ }
23701
+ await this.prepareNativeSessionBrowser(options);
23702
+ const started = this.#nativeBrowserSessions.get(options.sessionId);
23703
+ if (started === void 0) {
23704
+ throw new AcpExecutionError("ACP native session browser did not start");
23705
+ }
23706
+ return started;
23707
+ }
23708
+ listNativeSessions = async (options, cursor) => await (await this.#ensureNativeSessionBrowser(options)).listNativeSessions(
23567
23709
  cursor,
23568
23710
  options.signal
23569
23711
  );
@@ -23646,7 +23788,7 @@ var AcpSessionManager = class {
23646
23788
  }
23647
23789
  };
23648
23790
  deleteNativeSession = async (options, nativeSessionId) => {
23649
- const runtime = await this.ensureSession(options);
23791
+ const runtime = await this.#ensureNativeSessionBrowser(options);
23650
23792
  const key = `${options.agent.id}:${nativeSessionId}`;
23651
23793
  const linked = this.#store.findNative(options.agent.id, nativeSessionId);
23652
23794
  if (this.#nativeOperations.has(key) || linked.some(
@@ -23673,7 +23815,8 @@ var AcpSessionManager = class {
23673
23815
  nativeSessionId
23674
23816
  );
23675
23817
  if (runtime.nativeSessionId() === nativeSessionId) {
23676
- this.#sessions.delete(options.sessionId);
23818
+ this.#nativeBrowserSessions.delete(options.sessionId);
23819
+ this.#nativeBrowserStore.remove(options.sessionId);
23677
23820
  await runtime.close();
23678
23821
  }
23679
23822
  return deleted;
@@ -26693,7 +26836,7 @@ var NativeSessionService = class {
26693
26836
  sessionId: command.sessionId,
26694
26837
  signal
26695
26838
  };
26696
- const prepared = await this.#sessions.prepareSession(options);
26839
+ const prepared = await this.#sessions.prepareNativeSessionBrowser(options);
26697
26840
  if (!prepared.capabilities.listSessions)
26698
26841
  throw new AcpExecutionError(
26699
26842
  "This Agent does not support native session listing",
@@ -27755,6 +27898,15 @@ async function executeSessionPrepare(outbox, socket, command, config2, directori
27755
27898
  })
27756
27899
  );
27757
27900
  } catch (error61) {
27901
+ audit.record({
27902
+ commandId: command.requestId,
27903
+ details: {
27904
+ agentId: command.agentId,
27905
+ code: operationErrorCode(error61)
27906
+ },
27907
+ event: "session_prepare_failed",
27908
+ sessionId: command.sessionId
27909
+ });
27758
27910
  reportOperationFailure(socket, command.requestId, command.sessionId, error61);
27759
27911
  }
27760
27912
  }