@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/cli.js CHANGED
@@ -22338,7 +22338,7 @@ var AcpActivity = class _AcpActivity {
22338
22338
  toolKind;
22339
22339
  content;
22340
22340
  detail;
22341
- constructor(activityId, activityType, input2, locations, name, output2, sequence, status, title, toolKind, content = [], detail = captureActivityDetail(
22341
+ constructor(activityId, activityType, input2, locations, name, output2, sequence, status, title2, toolKind, content = [], detail = captureActivityDetail(
22342
22342
  content,
22343
22343
  input2,
22344
22344
  output2
@@ -22351,7 +22351,7 @@ var AcpActivity = class _AcpActivity {
22351
22351
  this.output = output2;
22352
22352
  this.sequence = sequence;
22353
22353
  this.status = status;
22354
- this.title = title;
22354
+ this.title = title2;
22355
22355
  this.toolKind = toolKind;
22356
22356
  this.content = content;
22357
22357
  this.detail = detail;
@@ -22567,8 +22567,8 @@ function normalizeToolStatus(status, fallback) {
22567
22567
  }
22568
22568
  return fallback;
22569
22569
  }
22570
- function normalizeTitle(title, fallback) {
22571
- const normalized = title.trim();
22570
+ function normalizeTitle(title2, fallback) {
22571
+ const normalized = title2.trim();
22572
22572
  return truncate(normalized.length === 0 ? fallback : normalized, 500);
22573
22573
  }
22574
22574
  function formatPlanEntries(entries) {
@@ -22814,12 +22814,13 @@ var AcpActivityTracker = class {
22814
22814
 
22815
22815
  // src/acp/native-session.ts
22816
22816
  var path = external_exports.string().min(1).max(2048).refine((value) => !value.includes("\0"));
22817
+ var title = external_exports.string().transform((value) => value.slice(0, 500));
22817
22818
  var nativeSessionIdSchema = external_exports.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,255}$/);
22818
22819
  var nativeSessionInfoSchema = external_exports.object({
22819
22820
  sessionId: nativeSessionIdSchema,
22820
22821
  cwd: path,
22821
22822
  additionalDirectories: external_exports.array(path).max(16).default([]).readonly(),
22822
- title: external_exports.string().max(500).nullish(),
22823
+ title: title.nullish(),
22823
22824
  updatedAt: external_exports.iso.datetime({ offset: true }).nullish()
22824
22825
  }).readonly();
22825
22826
  var nativeSessionPageSchema = external_exports.object({
@@ -23142,6 +23143,12 @@ var AcpExecutionError = class extends Error {
23142
23143
  this.name = "AcpExecutionError";
23143
23144
  }
23144
23145
  };
23146
+ var RetryableAcpInitializationError = class extends AcpExecutionError {
23147
+ constructor(cause) {
23148
+ super("ACP agent initialization failed", { cause });
23149
+ this.name = "RetryableAcpInitializationError";
23150
+ }
23151
+ };
23145
23152
  function readableWebStream(input2) {
23146
23153
  let streamOpen = true;
23147
23154
  return new ReadableStream({
@@ -23771,42 +23778,63 @@ var AcpProcessSession = class _AcpProcessSession {
23771
23778
  );
23772
23779
  this.#connection = createAcpClient(this).connect(stream);
23773
23780
  }
23774
- static start = async (options, getObserver, store) => {
23775
- options.signal.throwIfAborted();
23776
- const [adapterUnchanged, agentUnchanged] = await Promise.all([
23777
- revalidateExecutable(options.agent.adapterIdentity),
23778
- revalidateExecutable(options.agent.agentIdentity)
23779
- ]);
23780
- options.signal.throwIfAborted();
23781
- if (!adapterUnchanged || !agentUnchanged) {
23782
- throw new AcpExecutionError(
23783
- "The local Agent runtime changed; restart Mobius before starting a new conversation",
23784
- {},
23785
- "agent_runtime_changed"
23786
- );
23787
- }
23788
- const runtime = new _AcpProcessSession(
23789
- options.agent,
23790
- options.cwd,
23791
- options.additionalDirectories,
23792
- options.sessionId,
23793
- getObserver,
23794
- store
23795
- );
23796
- try {
23797
- await runtime.initialize(options.signal, options.origin);
23798
- return runtime;
23799
- } catch (error61) {
23800
- await runtime.closeProcess();
23781
+ static async #start(options, getObserver, store, initialize) {
23782
+ for (let attempt = 1; attempt <= 2; attempt += 1) {
23801
23783
  options.signal.throwIfAborted();
23802
- if (error61 instanceof AcpExecutionError) {
23803
- throw error61;
23784
+ const [adapterUnchanged, agentUnchanged] = await Promise.all([
23785
+ revalidateExecutable(options.agent.adapterIdentity),
23786
+ revalidateExecutable(options.agent.agentIdentity)
23787
+ ]);
23788
+ options.signal.throwIfAborted();
23789
+ if (!adapterUnchanged || !agentUnchanged) {
23790
+ throw new AcpExecutionError(
23791
+ "The local Agent runtime changed; restart Mobius before starting a new conversation",
23792
+ {},
23793
+ "agent_runtime_changed"
23794
+ );
23795
+ }
23796
+ const runtime = new _AcpProcessSession(
23797
+ options.agent,
23798
+ options.cwd,
23799
+ options.additionalDirectories,
23800
+ options.sessionId,
23801
+ getObserver,
23802
+ store
23803
+ );
23804
+ try {
23805
+ await initialize(runtime);
23806
+ return runtime;
23807
+ } catch (error61) {
23808
+ await runtime.closeProcess();
23809
+ options.signal.throwIfAborted();
23810
+ if (error61 instanceof RetryableAcpInitializationError && attempt === 1) {
23811
+ console.warn(
23812
+ `[${options.agent.id}-acp] ACP agent initialization failed; retrying once`
23813
+ );
23814
+ continue;
23815
+ }
23816
+ if (error61 instanceof AcpExecutionError) {
23817
+ throw error61;
23818
+ }
23819
+ throw new AcpExecutionError("ACP agent initialization failed", {
23820
+ cause: error61
23821
+ });
23804
23822
  }
23805
- throw new AcpExecutionError("ACP agent initialization failed", {
23806
- cause: error61
23807
- });
23808
23823
  }
23809
- };
23824
+ throw new AcpExecutionError("ACP agent initialization failed");
23825
+ }
23826
+ static start = async (options, getObserver, store) => await _AcpProcessSession.#start(
23827
+ options,
23828
+ getObserver,
23829
+ store,
23830
+ async (runtime) => await runtime.initialize(options.signal, options.origin)
23831
+ );
23832
+ static startNativeSessionBrowser = async (options, getObserver, store) => await _AcpProcessSession.#start(
23833
+ options,
23834
+ getObserver,
23835
+ store,
23836
+ async (runtime) => await runtime.#initializeAgent(options.signal)
23837
+ );
23810
23838
  belongsTo = (agentId, cwd, additionalDirectories) => this.#agentId === agentId && this.#cwd === cwd && arraysEqual(this.#additionalDirectories, additionalDirectories);
23811
23839
  canRebind = () => !this.#prompted && !this.#turn.running;
23812
23840
  prepared = () => new AcpPreparedSession(
@@ -23843,7 +23871,7 @@ var AcpProcessSession = class _AcpProcessSession {
23843
23871
  this.#replay = { kind: "idle" };
23844
23872
  }
23845
23873
  };
23846
- initialize = async (signal, origin) => {
23874
+ async #initializeAgent(signal) {
23847
23875
  const initialized = await this.race(
23848
23876
  this.#connection.agent.request(
23849
23877
  methods3.agent.initialize,
@@ -23860,7 +23888,10 @@ var AcpProcessSession = class _AcpProcessSession {
23860
23888
  ),
23861
23889
  "ACP agent exited during initialization",
23862
23890
  signal
23863
- );
23891
+ ).catch((cause) => {
23892
+ signal.throwIfAborted();
23893
+ throw new RetryableAcpInitializationError(cause);
23894
+ });
23864
23895
  if (initialized.protocolVersion !== PROTOCOL_VERSION2) {
23865
23896
  throw new AcpExecutionError(
23866
23897
  "ACP agent selected an unsupported protocol version",
@@ -23875,6 +23906,9 @@ var AcpProcessSession = class _AcpProcessSession {
23875
23906
  255
23876
23907
  );
23877
23908
  this.#agentVersion = truncate2(initialized.agentInfo?.version ?? "", 128);
23909
+ }
23910
+ initialize = async (signal, origin) => {
23911
+ await this.#initializeAgent(signal);
23878
23912
  const stored = origin?.kind === "import" ? new FoundAcpStoredSession(
23879
23913
  new AcpStoredSession(
23880
23914
  this.#mobiusSessionId,
@@ -24699,6 +24733,10 @@ var AcpProcessSession = class _AcpProcessSession {
24699
24733
  };
24700
24734
  var AcpSessionManager = class {
24701
24735
  #nativeOperations = /* @__PURE__ */ new Set();
24736
+ #nativeBrowserObserver = new NullAcpSessionObserver();
24737
+ #nativeBrowserPreparing = /* @__PURE__ */ new Map();
24738
+ #nativeBrowserSessions = /* @__PURE__ */ new Map();
24739
+ #nativeBrowserStore = new MemoryAcpSessionStore();
24702
24740
  #activeSessionIds = /* @__PURE__ */ new Set();
24703
24741
  #cancellationRequests = /* @__PURE__ */ new Set();
24704
24742
  #preparing = /* @__PURE__ */ new Map();
@@ -24712,6 +24750,43 @@ var AcpSessionManager = class {
24712
24750
  setObserver = (observer) => {
24713
24751
  this.#observer = observer;
24714
24752
  };
24753
+ async #startNativeBrowserPreparation(options) {
24754
+ const operation = (async () => {
24755
+ try {
24756
+ const runtime = await AcpProcessSession.startNativeSessionBrowser(
24757
+ options,
24758
+ () => this.#nativeBrowserObserver,
24759
+ this.#nativeBrowserStore
24760
+ );
24761
+ this.#nativeBrowserSessions.set(options.sessionId, runtime);
24762
+ return runtime;
24763
+ } finally {
24764
+ this.#nativeBrowserPreparing.delete(options.sessionId);
24765
+ }
24766
+ })();
24767
+ this.#nativeBrowserPreparing.set(options.sessionId, operation);
24768
+ return await operation;
24769
+ }
24770
+ async #replaceNativeBrowserPreparation(existing, options) {
24771
+ const operation = (async () => {
24772
+ try {
24773
+ this.#nativeBrowserSessions.delete(options.sessionId);
24774
+ await existing.close();
24775
+ this.#nativeBrowserStore.remove(options.sessionId);
24776
+ const runtime = await AcpProcessSession.startNativeSessionBrowser(
24777
+ options,
24778
+ () => this.#nativeBrowserObserver,
24779
+ this.#nativeBrowserStore
24780
+ );
24781
+ this.#nativeBrowserSessions.set(options.sessionId, runtime);
24782
+ return runtime;
24783
+ } finally {
24784
+ this.#nativeBrowserPreparing.delete(options.sessionId);
24785
+ }
24786
+ })();
24787
+ this.#nativeBrowserPreparing.set(options.sessionId, operation);
24788
+ return await operation;
24789
+ }
24715
24790
  async #startPreparation(options) {
24716
24791
  const operation = (async () => {
24717
24792
  try {
@@ -24799,6 +24874,44 @@ var AcpSessionManager = class {
24799
24874
  const runtime = await this.#startPreparation(options);
24800
24875
  return runtime.prepared();
24801
24876
  };
24877
+ prepareNativeSessionBrowser = async (options) => {
24878
+ const pending = this.#nativeBrowserPreparing.get(options.sessionId);
24879
+ if (pending !== void 0) {
24880
+ const runtime2 = await pending;
24881
+ if (runtime2.belongsTo(
24882
+ options.agent.id,
24883
+ options.cwd,
24884
+ options.additionalDirectories
24885
+ )) {
24886
+ return runtime2.prepared();
24887
+ }
24888
+ return await this.prepareNativeSessionBrowser(options);
24889
+ }
24890
+ const existing = this.#nativeBrowserSessions.get(options.sessionId);
24891
+ if (existing !== void 0) {
24892
+ if (existing.belongsTo(
24893
+ options.agent.id,
24894
+ options.cwd,
24895
+ options.additionalDirectories
24896
+ )) {
24897
+ return existing.prepared();
24898
+ }
24899
+ if (!existing.canRebind()) {
24900
+ throw new AcpExecutionError(
24901
+ "The agent or workspace cannot change after a conversation has started",
24902
+ {},
24903
+ "session_identity_mismatch"
24904
+ );
24905
+ }
24906
+ const runtime2 = await this.#replaceNativeBrowserPreparation(
24907
+ existing,
24908
+ options
24909
+ );
24910
+ return runtime2.prepared();
24911
+ }
24912
+ const runtime = await this.#startNativeBrowserPreparation(options);
24913
+ return runtime.prepared();
24914
+ };
24802
24915
  configureSession = async (options) => {
24803
24916
  const runtime = await this.ensureSession(options);
24804
24917
  return await runtime.configure(options);
@@ -24887,8 +25000,14 @@ var AcpSessionManager = class {
24887
25000
  };
24888
25001
  close = async () => {
24889
25002
  const sessions = [...this.#sessions.values()];
25003
+ const nativeBrowserSessions = [...this.#nativeBrowserSessions.values()];
24890
25004
  this.#sessions.clear();
24891
- await Promise.all(sessions.map(async (session) => await session.close()));
25005
+ this.#nativeBrowserSessions.clear();
25006
+ await Promise.all(
25007
+ [...sessions, ...nativeBrowserSessions].map(
25008
+ async (session) => await session.close()
25009
+ )
25010
+ );
24892
25011
  };
24893
25012
  ensureSession = async (options) => {
24894
25013
  const existing = this.#sessions.get(options.sessionId);
@@ -24913,7 +25032,30 @@ var AcpSessionManager = class {
24913
25032
  }
24914
25033
  return started;
24915
25034
  };
24916
- listNativeSessions = async (options, cursor) => await (await this.ensureSession(options)).listNativeSessions(
25035
+ async #ensureNativeSessionBrowser(options) {
25036
+ const existing = this.#nativeBrowserSessions.get(options.sessionId);
25037
+ if (existing !== void 0) {
25038
+ if (!existing.belongsTo(
25039
+ options.agent.id,
25040
+ options.cwd,
25041
+ options.additionalDirectories
25042
+ )) {
25043
+ throw new AcpExecutionError(
25044
+ "The agent or workspace cannot change after a conversation has started",
25045
+ {},
25046
+ "session_identity_mismatch"
25047
+ );
25048
+ }
25049
+ return existing;
25050
+ }
25051
+ await this.prepareNativeSessionBrowser(options);
25052
+ const started = this.#nativeBrowserSessions.get(options.sessionId);
25053
+ if (started === void 0) {
25054
+ throw new AcpExecutionError("ACP native session browser did not start");
25055
+ }
25056
+ return started;
25057
+ }
25058
+ listNativeSessions = async (options, cursor) => await (await this.#ensureNativeSessionBrowser(options)).listNativeSessions(
24917
25059
  cursor,
24918
25060
  options.signal
24919
25061
  );
@@ -24996,7 +25138,7 @@ var AcpSessionManager = class {
24996
25138
  }
24997
25139
  };
24998
25140
  deleteNativeSession = async (options, nativeSessionId) => {
24999
- const runtime = await this.ensureSession(options);
25141
+ const runtime = await this.#ensureNativeSessionBrowser(options);
25000
25142
  const key = `${options.agent.id}:${nativeSessionId}`;
25001
25143
  const linked = this.#store.findNative(options.agent.id, nativeSessionId);
25002
25144
  if (this.#nativeOperations.has(key) || linked.some(
@@ -25023,7 +25165,8 @@ var AcpSessionManager = class {
25023
25165
  nativeSessionId
25024
25166
  );
25025
25167
  if (runtime.nativeSessionId() === nativeSessionId) {
25026
- this.#sessions.delete(options.sessionId);
25168
+ this.#nativeBrowserSessions.delete(options.sessionId);
25169
+ this.#nativeBrowserStore.remove(options.sessionId);
25027
25170
  await runtime.close();
25028
25171
  }
25029
25172
  return deleted;
@@ -26712,7 +26855,7 @@ var NativeSessionService = class {
26712
26855
  sessionId: command.sessionId,
26713
26856
  signal
26714
26857
  };
26715
- const prepared = await this.#sessions.prepareSession(options);
26858
+ const prepared = await this.#sessions.prepareNativeSessionBrowser(options);
26716
26859
  if (!prepared.capabilities.listSessions)
26717
26860
  throw new AcpExecutionError(
26718
26861
  "This Agent does not support native session listing",
@@ -27774,6 +27917,15 @@ async function executeSessionPrepare(outbox, socket, command, config2, directori
27774
27917
  })
27775
27918
  );
27776
27919
  } catch (error61) {
27920
+ audit.record({
27921
+ commandId: command.requestId,
27922
+ details: {
27923
+ agentId: command.agentId,
27924
+ code: operationErrorCode(error61)
27925
+ },
27926
+ event: "session_prepare_failed",
27927
+ sessionId: command.sessionId
27928
+ });
27777
27929
  reportOperationFailure(socket, command.requestId, command.sessionId, error61);
27778
27930
  }
27779
27931
  }