@moxt-ai/mobius 0.0.353 → 0.0.355

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.
Files changed (33) hide show
  1. package/dist/cli.js +587 -419
  2. package/dist/cli.js.map +4 -4
  3. package/dist/engine/agent/discovery/agent-discovery-context.d.ts +10 -0
  4. package/dist/engine/agent/discovery/agent-discovery-context.d.ts.map +1 -1
  5. package/dist/engine/agent/discovery/discover-agent.d.ts.map +1 -1
  6. package/dist/engine/agent/discovery/discover-agent.js +27 -6
  7. package/dist/engine/agent/discovery/discover-agent.js.map +1 -1
  8. package/dist/engine/agent/discovery/executable-discovery.d.ts.map +1 -1
  9. package/dist/engine/agent/discovery/executable-discovery.js +8 -1
  10. package/dist/engine/agent/discovery/executable-discovery.js.map +1 -1
  11. package/dist/engine/runtime/catalog/discover-agent-catalog.d.ts +4 -0
  12. package/dist/engine/runtime/catalog/discover-agent-catalog.d.ts.map +1 -0
  13. package/dist/engine/runtime/catalog/discover-agent-catalog.js +54 -0
  14. package/dist/engine/runtime/catalog/discover-agent-catalog.js.map +1 -0
  15. package/dist/engine/runtime/observability/diagnostic-log.d.ts.map +1 -1
  16. package/dist/engine/runtime/observability/diagnostic-log.js +6 -0
  17. package/dist/engine/runtime/observability/diagnostic-log.js.map +1 -1
  18. package/dist/engine/runtime/pairing.d.ts.map +1 -1
  19. package/dist/engine/runtime/pairing.js +6 -5
  20. package/dist/engine/runtime/pairing.js.map +1 -1
  21. package/dist/engine/runtime/runtime-loop.d.ts.map +1 -1
  22. package/dist/engine/runtime/runtime-loop.js +4 -3
  23. package/dist/engine/runtime/runtime-loop.js.map +1 -1
  24. package/dist/engine/util/process/executable.d.ts.map +1 -1
  25. package/dist/engine/util/process/executable.js +26 -8
  26. package/dist/engine/util/process/executable.js.map +1 -1
  27. package/dist/engine/util/process/process-error.d.ts +6 -1
  28. package/dist/engine/util/process/process-error.d.ts.map +1 -1
  29. package/dist/engine/util/process/process-error.js +2 -0
  30. package/dist/engine/util/process/process-error.js.map +1 -1
  31. package/dist/engine.js +554 -399
  32. package/dist/engine.js.map +4 -4
  33. package/package.json +2 -2
package/dist/engine.js CHANGED
@@ -20794,38 +20794,6 @@ function isRecord2(value) {
20794
20794
  }
20795
20795
  var sessionEventBatchSchema = external_exports.array(sessionEventSchema).min(1).max(SESSION_EVENT_BATCH_MAX_SIZE).readonly();
20796
20796
  var sessionLiveEventBatchSchema = external_exports.array(sessionLiveEventSchema).min(1).max(SESSION_EVENT_BATCH_MAX_SIZE).readonly();
20797
- var sessionExportSchema = external_exports.object({
20798
- binding: external_exports.object({
20799
- bindingId: identifierStringSchema,
20800
- runtimeId: identifierStringSchema
20801
- }).readonly(),
20802
- events: external_exports.array(sessionEventSchema).max(MAX_EVENT_COUNT).readonly(),
20803
- sessionId: identifierStringSchema,
20804
- truncated: external_exports.boolean()
20805
- }).readonly().superRefine((session, context) => {
20806
- const eventIds = /* @__PURE__ */ new Set();
20807
- for (const [index2, event] of session.events.entries()) {
20808
- if (event.sessionId !== session.sessionId) {
20809
- context.addIssue({
20810
- code: "custom",
20811
- message: "Exported event belongs to a different Session",
20812
- path: ["events", index2, "sessionId"]
20813
- });
20814
- }
20815
- if (eventIds.has(event.eventId)) {
20816
- context.addIssue({
20817
- code: "custom",
20818
- message: "Exported event identities are not unique",
20819
- path: ["events", index2, "eventId"]
20820
- });
20821
- }
20822
- eventIds.add(event.eventId);
20823
- }
20824
- });
20825
- var mobiusSessionExportSchema = external_exports.object({
20826
- formatVersion: external_exports.literal("2"),
20827
- session: sessionExportSchema
20828
- }).readonly();
20829
20797
  var sessionEventEnvelopeSchema = external_exports.object({ events: sessionLiveEventBatchSchema, kind: external_exports.literal(SESSION_EVENT_KIND) }).readonly();
20830
20798
  var sessionEventLogPageSchema = external_exports.object({
20831
20799
  events: external_exports.array(sessionEventSchema).max(MAX_EVENT_COUNT).readonly(),
@@ -20838,12 +20806,9 @@ var sessionEventLogPageSchema = external_exports.object({
20838
20806
  truncated: external_exports.boolean(),
20839
20807
  version: external_exports.literal(2)
20840
20808
  }).readonly();
20841
- var sessionEventOmissionSchema = external_exports.literal("agent-reasoning");
20842
20809
  var nativeEventPageRequestSchema = external_exports.object({
20843
20810
  cursor: external_exports.string().min(1).max(512).nullable(),
20844
- eventLimit: external_exports.number().int().min(1).max(1e4),
20845
- // Legacy callers may still send this option; readers must ignore it.
20846
- omit: external_exports.array(sessionEventOmissionSchema).max(1).readonly().optional()
20811
+ eventLimit: external_exports.number().int().min(1).max(1e4)
20847
20812
  }).readonly();
20848
20813
  var queuedPromptRequestEventLogSchema = external_exports.object({
20849
20814
  commandId: identifierStringSchema,
@@ -21522,8 +21487,6 @@ var SESSION_PREVIEW_HISTORY_PAGE_LOADED_KIND = "session.preview-history.page.loa
21522
21487
  var pageRequestFields = {
21523
21488
  cursor: external_exports.string().min(1).max(512).nullable(),
21524
21489
  eventLimit: external_exports.number().int().min(1).max(1e4),
21525
- // Decode old clients without rejecting their request; omission has no effect.
21526
- omit: external_exports.array(sessionEventOmissionSchema).max(1).readonly().optional(),
21527
21490
  requestId: identifierStringSchema,
21528
21491
  sessionId: identifierStringSchema
21529
21492
  };
@@ -59518,7 +59481,6 @@ function backgroundTaskId(result) {
59518
59481
  }
59519
59482
 
59520
59483
  // src/engine/acp/harness/claude/upstream/dist/context-resources.js
59521
- import { extname } from "node:path";
59522
59484
  function formatUriAsLink(uri) {
59523
59485
  if (uri.startsWith("file://")) {
59524
59486
  const path7 = uri.slice(7);
@@ -59533,91 +59495,6 @@ var formatContextBlock = (uri, text2) => `
59533
59495
  <context ref="${uri}">
59534
59496
  ${text2}
59535
59497
  </context>`;
59536
- function parseContextBlock(block) {
59537
- if (block.type !== "text" || typeof block.text !== "string") {
59538
- return null;
59539
- }
59540
- const match = /^\n<context ref="([^"\r\n]+)">\n([\s\S]*)\n<\/context>$/u.exec(block.text);
59541
- const uri = match?.[1];
59542
- const text2 = match?.[2];
59543
- if (uri === void 0 || text2 === void 0 || formatContextBlock(uri, text2) !== block.text) {
59544
- return null;
59545
- }
59546
- return { uri, text: text2 };
59547
- }
59548
- function contextMimeType(uri) {
59549
- let pathname = uri;
59550
- try {
59551
- pathname = new URL(uri).pathname;
59552
- } catch {
59553
- }
59554
- switch (extname(pathname).toLowerCase()) {
59555
- case ".html":
59556
- case ".htm":
59557
- return "text/html";
59558
- case ".js":
59559
- case ".mjs":
59560
- case ".cjs":
59561
- return "text/javascript";
59562
- case ".css":
59563
- return "text/css";
59564
- case ".json":
59565
- return "application/json";
59566
- case ".md":
59567
- case ".markdown":
59568
- return "text/markdown";
59569
- case ".xml":
59570
- return "application/xml";
59571
- case ".svg":
59572
- return "image/svg+xml";
59573
- case ".csv":
59574
- return "text/csv";
59575
- default:
59576
- return "text/plain";
59577
- }
59578
- }
59579
- function replayContextResources(content) {
59580
- const contexts = [];
59581
- let contextStart = content.length;
59582
- for (let index2 = content.length - 1; index2 >= 0; index2 -= 1) {
59583
- const block = content[index2];
59584
- const parsed = block === void 0 ? null : parseContextBlock(block);
59585
- if (parsed === null) {
59586
- break;
59587
- }
59588
- contexts.push(parsed);
59589
- contextStart = index2;
59590
- }
59591
- if (contexts.length === 0) {
59592
- return null;
59593
- }
59594
- contexts.reverse();
59595
- const links = new Set(contexts.map(({ uri }) => formatUriAsLink(uri)));
59596
- const resources = /* @__PURE__ */ new Map();
59597
- let nextContext = 0;
59598
- for (let index2 = 0; index2 < contextStart; index2 += 1) {
59599
- const block = content[index2];
59600
- if (block?.type !== "text" || typeof block.text !== "string") {
59601
- continue;
59602
- }
59603
- if (block.text.startsWith('\n<context ref="')) {
59604
- return null;
59605
- }
59606
- if (!links.has(block.text)) {
59607
- continue;
59608
- }
59609
- const context = contexts[nextContext];
59610
- if (context === void 0 || block.text !== formatUriAsLink(context.uri)) {
59611
- return null;
59612
- }
59613
- resources.set(index2, {
59614
- type: "resource",
59615
- resource: { ...context, mimeType: contextMimeType(context.uri) }
59616
- });
59617
- nextContext += 1;
59618
- }
59619
- return nextContext === contexts.length ? { contextStart, resources } : null;
59620
- }
59621
59498
 
59622
59499
  // src/engine/acp/harness/claude/upstream/dist/elicitation.js
59623
59500
  import { randomUUID as randomUUID4 } from "node:crypto";
@@ -59903,14 +59780,16 @@ function listEnvironmentSessions(environment, cwd, signal) {
59903
59780
 
59904
59781
  // src/engine/acp/harness/claude/upstream/dist/environment-session-messages.js
59905
59782
  var SESSION_MESSAGES_TIMEOUT_MILLISECONDS = 3e4;
59906
- function getEnvironmentSessionMessages(environment, sessionId, signal) {
59783
+ function getEnvironmentSessionMessages(environment, sessionId, cancellationSignal) {
59784
+ const signal = AbortSignal.any([cancellationSignal, AbortSignal.timeout(SESSION_MESSAGES_TIMEOUT_MILLISECONDS)]);
59907
59785
  return withEnvironment(environment, () => withDeadline(signal, SESSION_MESSAGES_TIMEOUT_MILLISECONDS, async () => {
59908
- const messages = await FZt(sessionId);
59909
59786
  const authenticationFailures = /* @__PURE__ */ new Set();
59787
+ const transcript = [];
59910
59788
  const nativeMetadata = /* @__PURE__ */ new Map();
59911
59789
  await GZt(sessionId, {
59912
59790
  append: async (_key, entries) => {
59913
59791
  signal.throwIfAborted();
59792
+ transcript.push(...entries);
59914
59793
  for (const entry of entries) {
59915
59794
  if (entry.type === "user" && typeof entry.uuid === "string") {
59916
59795
  nativeMetadata.set(entry.uuid, {
@@ -59926,9 +59805,143 @@ function getEnvironmentSessionMessages(environment, sessionId, signal) {
59926
59805
  load: async () => null
59927
59806
  }, { includeSubagents: false });
59928
59807
  signal.throwIfAborted();
59808
+ const messages = await readFullHistory(transcript, sessionId, signal) ?? await FZt(sessionId);
59929
59809
  return messages.filter((message) => !authenticationFailures.has(message.uuid)).map((message) => ({ ...message, ...nativeMetadata.get(message.uuid) }));
59930
59810
  }));
59931
59811
  }
59812
+ var chainEntrySchema = external_exports.object({
59813
+ type: external_exports.enum(["user", "assistant", "system", "progress", "attachment"]),
59814
+ uuid: external_exports.string(),
59815
+ parentUuid: external_exports.string().nullable(),
59816
+ logicalParentUuid: external_exports.string().nullable().optional(),
59817
+ subtype: external_exports.string().optional(),
59818
+ isCompactSummary: external_exports.boolean().optional(),
59819
+ compactMetadata: external_exports.object({
59820
+ preservedSegment: external_exports.object({ headUuid: external_exports.string(), tailUuid: external_exports.string(), anchorUuid: external_exports.string() }).optional(),
59821
+ preservedMessages: external_exports.object({ uuids: external_exports.array(external_exports.string()), anchorUuid: external_exports.string() }).optional()
59822
+ }).passthrough().optional()
59823
+ }).passthrough();
59824
+ async function readFullHistory(transcript, sessionId, signal) {
59825
+ const entries = /* @__PURE__ */ new Map();
59826
+ for (const [index2, raw] of transcript.entries()) {
59827
+ signal.throwIfAborted();
59828
+ if (typeof raw.uuid !== "string") {
59829
+ continue;
59830
+ }
59831
+ if (!["user", "assistant", "system", "progress", "attachment"].includes(raw.type)) {
59832
+ continue;
59833
+ }
59834
+ const parsed = chainEntrySchema.safeParse(raw);
59835
+ if (!parsed.success) {
59836
+ return null;
59837
+ }
59838
+ entries.set(parsed.data.uuid, { entry: parsed.data, index: index2 });
59839
+ }
59840
+ const validated = /* @__PURE__ */ new Set();
59841
+ for (const uuid3 of entries.keys()) {
59842
+ signal.throwIfAborted();
59843
+ const visiting = /* @__PURE__ */ new Set();
59844
+ let current = uuid3;
59845
+ while (current !== null && !validated.has(current)) {
59846
+ const node2 = entries.get(current);
59847
+ if (node2 === void 0 || visiting.has(current)) {
59848
+ return null;
59849
+ }
59850
+ visiting.add(current);
59851
+ const entry = node2.entry;
59852
+ current = entry.subtype === "compact_boundary" ? entry.logicalParentUuid ?? entry.parentUuid : entry.parentUuid;
59853
+ }
59854
+ for (const id of visiting) {
59855
+ validated.add(id);
59856
+ }
59857
+ }
59858
+ for (const { entry } of entries.values()) {
59859
+ if (entry.subtype !== "compact_boundary") {
59860
+ continue;
59861
+ }
59862
+ const preserved = entry.compactMetadata;
59863
+ const references = preserved?.preservedMessages !== void 0 ? [...preserved.preservedMessages.uuids, preserved.preservedMessages.anchorUuid] : preserved?.preservedSegment !== void 0 ? [
59864
+ preserved.preservedSegment.headUuid,
59865
+ preserved.preservedSegment.tailUuid,
59866
+ preserved.preservedSegment.anchorUuid
59867
+ ] : [];
59868
+ if (references.some((id) => !entries.has(id))) {
59869
+ return null;
59870
+ }
59871
+ }
59872
+ const project = async (source) => {
59873
+ signal.throwIfAborted();
59874
+ const messages = await FZt(sessionId, {
59875
+ includeSystemMessages: true,
59876
+ sessionStore: { append: async () => {
59877
+ }, load: async () => source }
59878
+ });
59879
+ signal.throwIfAborted();
59880
+ return messages;
59881
+ };
59882
+ const result = [];
59883
+ const seen = /* @__PURE__ */ new Set();
59884
+ const expanding = /* @__PURE__ */ new Set();
59885
+ const append = async (messages) => {
59886
+ let compactionId;
59887
+ for (const message of messages) {
59888
+ signal.throwIfAborted();
59889
+ const node2 = entries.get(message.uuid);
59890
+ if (node2 === void 0) {
59891
+ return false;
59892
+ }
59893
+ if (node2.entry.subtype === "compact_boundary") {
59894
+ compactionId = message.uuid;
59895
+ if (seen.has(message.uuid)) {
59896
+ continue;
59897
+ }
59898
+ if (expanding.has(message.uuid)) {
59899
+ return false;
59900
+ }
59901
+ expanding.add(message.uuid);
59902
+ const parent = node2.entry.logicalParentUuid;
59903
+ if (typeof parent === "string") {
59904
+ const ancestor = entries.get(parent);
59905
+ if (ancestor === void 0 || ancestor.index >= node2.index) {
59906
+ return false;
59907
+ }
59908
+ const anchor2 = `history-anchor-${message.uuid}`;
59909
+ if (entries.has(anchor2)) {
59910
+ return false;
59911
+ }
59912
+ const earlier = await project([
59913
+ ...transcript.slice(0, node2.index),
59914
+ {
59915
+ type: "user",
59916
+ uuid: anchor2,
59917
+ parentUuid: parent,
59918
+ sessionId,
59919
+ message: { role: "user", content: "" }
59920
+ }
59921
+ ]);
59922
+ if (!await append(earlier.filter((entry) => entry.uuid !== anchor2))) {
59923
+ return false;
59924
+ }
59925
+ }
59926
+ expanding.delete(message.uuid);
59927
+ seen.add(message.uuid);
59928
+ result.push({ ...message, nativeCompaction: { kind: "boundary", id: message.uuid } });
59929
+ } else if (!seen.has(message.uuid)) {
59930
+ seen.add(message.uuid);
59931
+ if (node2.entry.isCompactSummary === true) {
59932
+ if (compactionId === void 0) {
59933
+ return false;
59934
+ }
59935
+ result.push({ ...message, nativeCompaction: { kind: "summary", id: compactionId } });
59936
+ } else if (message.type !== "system") {
59937
+ result.push(message);
59938
+ }
59939
+ }
59940
+ }
59941
+ return true;
59942
+ };
59943
+ return await append(await project([...transcript])) ? result : null;
59944
+ }
59932
59945
 
59933
59946
  // src/engine/acp/harness/claude/upstream/dist/session-config-ids.js
59934
59947
  var DEFAULT_MODEL_ID = "default";
@@ -62750,9 +62763,16 @@ function stripMarkerTags(text2) {
62750
62763
  }
62751
62764
  return result + text2.slice(copiedUpTo);
62752
62765
  }
62753
- function stripLocalCommandMetadata(content) {
62766
+ function stripLocalCommandMetadata(content, options) {
62767
+ const strip = (text2) => {
62768
+ if (options?.preserveCompactionCommand === true && /<command-name>\/compact<\/command-name>/u.test(text2)) {
62769
+ const args = /<command-args>([\s\S]*?)<\/command-args>/u.exec(text2)?.[1]?.trim() ?? "";
62770
+ return stripMarkerTags(text2.replace(/<command-name>\/compact<\/command-name>/u, () => args.length > 0 ? `/compact ${args}` : "/compact")).trim();
62771
+ }
62772
+ return stripMarkerTags(text2);
62773
+ };
62754
62774
  if (typeof content === "string") {
62755
- const stripped = stripMarkerTags(content);
62775
+ const stripped = strip(content);
62756
62776
  return stripped.trim() === "" ? null : stripped;
62757
62777
  }
62758
62778
  if (!Array.isArray(content)) {
@@ -62761,7 +62781,7 @@ function stripLocalCommandMetadata(content) {
62761
62781
  const kept = [];
62762
62782
  for (const block of content) {
62763
62783
  if (block && typeof block === "object" && "type" in block && block.type === "text" && "text" in block && typeof block.text === "string") {
62764
- const stripped = stripMarkerTags(block.text);
62784
+ const stripped = strip(block.text);
62765
62785
  if (stripped.trim() === "") {
62766
62786
  continue;
62767
62787
  }
@@ -65053,6 +65073,35 @@ ${message.api_refusal_explanation}` : "";
65053
65073
  const forwardSubagentText = this.sessions[sessionId]?.forwardSubagentText ?? supportsSubagentTranscript(this.clientCapabilities);
65054
65074
  const seenTools = /* @__PURE__ */ new Set();
65055
65075
  for (const message of messages) {
65076
+ signal.throwIfAborted();
65077
+ if (message.nativeCompaction !== void 0) {
65078
+ const compaction = message.nativeCompaction;
65079
+ if (compaction.kind === "boundary") {
65080
+ await this.client.sessionUpdate({
65081
+ sessionId,
65082
+ update: {
65083
+ sessionUpdate: "compaction_update",
65084
+ compactionId: compaction.id,
65085
+ status: "completed"
65086
+ }
65087
+ });
65088
+ } else {
65089
+ const body = message.message;
65090
+ const content2 = typeof body === "object" && body !== null && "content" in body ? body.content : void 0;
65091
+ const text2 = typeof content2 === "string" ? content2 : Array.isArray(content2) ? content2.flatMap((block) => typeof block === "object" && block !== null && "type" in block && block.type === "text" && "text" in block && typeof block.text === "string" ? [block.text] : []).join("\n") : "";
65092
+ if (text2.length > 0) {
65093
+ await this.client.sessionUpdate({
65094
+ sessionId,
65095
+ update: {
65096
+ sessionUpdate: "compaction_summary_chunk",
65097
+ compactionId: compaction.id,
65098
+ content: { type: "text", text: text2 }
65099
+ }
65100
+ });
65101
+ }
65102
+ }
65103
+ continue;
65104
+ }
65056
65105
  if (isTaskNotificationOrigin(message.nativeOrigin)) {
65057
65106
  const body = message.message;
65058
65107
  const content2 = typeof body === "object" && body !== null && "content" in body ? body.content : void 0;
@@ -65074,7 +65123,7 @@ ${message.api_refusal_explanation}` : "";
65074
65123
  }
65075
65124
  let content = message.message.content;
65076
65125
  if (message.message.role === "user") {
65077
- content = stripLocalCommandMetadata(content);
65126
+ content = stripLocalCommandMetadata(content, { preserveCompactionCommand: true });
65078
65127
  if (content === null) {
65079
65128
  continue;
65080
65129
  }
@@ -66760,13 +66809,8 @@ function toAcpNotifications(content, role, sessionId, toolUseCache, client2, log
66760
66809
  const toolUseResult = options?.toolUseResult !== void 0 && content.filter((c) => typeof c === "object" && c !== null && c.type === "tool_result").length === 1 ? options.toolUseResult : void 0;
66761
66810
  const toolResultMeta = parseToolResultMeta(options?.toolResultMeta);
66762
66811
  const output2 = [];
66763
- const replayedResources = role === "user" && options.historical === true ? replayContextResources(content) : null;
66764
- for (const [index2, chunk] of content.entries()) {
66765
- if (replayedResources !== null && index2 >= replayedResources.contextStart) {
66766
- break;
66767
- }
66812
+ for (const chunk of content) {
66768
66813
  let update = null;
66769
- const resource = replayedResources?.resources.get(index2);
66770
66814
  switch (chunk.type) {
66771
66815
  case "text":
66772
66816
  case "text_delta": {
@@ -66775,7 +66819,7 @@ function toAcpNotifications(content, role, sessionId, toolUseCache, client2, log
66775
66819
  update = {
66776
66820
  sessionUpdate: role === "assistant" ? "agent_message_chunk" : "user_message_chunk",
66777
66821
  messageId,
66778
- content: resource ?? {
66822
+ content: {
66779
66823
  type: "text",
66780
66824
  text: chunk.text
66781
66825
  }
@@ -67545,14 +67589,16 @@ var macosProcessPlatform = {
67545
67589
  // src/engine/util/process/platform/windows.ts
67546
67590
  import { execFile as execFile4 } from "node:child_process";
67547
67591
  import { readFile as readFile5, realpath as realpath6 } from "node:fs/promises";
67548
- import { dirname as dirname6, extname as extname2, join as join14, resolve as resolve8 } from "node:path";
67592
+ import { dirname as dirname6, extname, join as join14, resolve as resolve8 } from "node:path";
67549
67593
 
67550
67594
  // src/engine/util/process/process-error.ts
67551
67595
  var ProcessExecutionError = class extends Error {
67552
67596
  code;
67597
+ diagnosticDetails;
67553
67598
  constructor(code, message, options = {}) {
67554
67599
  super(message, options);
67555
67600
  this.code = code;
67601
+ this.diagnosticDetails = options.diagnosticDetails ?? {};
67556
67602
  this.name = "ProcessExecutionError";
67557
67603
  }
67558
67604
  };
@@ -67572,14 +67618,14 @@ function executableExtensions(executableName, environment) {
67572
67618
  async function resolveExecutableTarget(path7) {
67573
67619
  let resolvedPath;
67574
67620
  try {
67575
- resolvedPath = await realpath6(extname2(path7) === "" ? `${path7}.cmd` : path7);
67621
+ resolvedPath = await realpath6(extname(path7) === "" ? `${path7}.cmd` : path7);
67576
67622
  } catch (cause) {
67577
- if (extname2(path7) !== "" || !(cause instanceof Error) || !("code" in cause) || cause.code !== "ENOENT") {
67623
+ if (extname(path7) !== "" || !(cause instanceof Error) || !("code" in cause) || cause.code !== "ENOENT") {
67578
67624
  throw cause;
67579
67625
  }
67580
67626
  resolvedPath = await realpath6(path7);
67581
67627
  }
67582
- if (extname2(resolvedPath).toLowerCase() === ".cmd") {
67628
+ if (extname(resolvedPath).toLowerCase() === ".cmd") {
67583
67629
  const shim = await readFile5(resolvedPath, "utf8");
67584
67630
  if (shim.includes('SET "NPM_CLI_JS=%~dp0\\node_modules\\npm\\bin\\npm-cli.js"') && shim.includes('"%NODE_EXE%" "%NPM_CLI_JS%" %*')) {
67585
67631
  return await realpath6(resolve8(dirname6(resolvedPath), "node_modules/npm/bin/npm-cli.js"));
@@ -67963,11 +68009,16 @@ async function runBoundedProcess(options) {
67963
68009
  abort();
67964
68010
  }
67965
68011
  try {
67966
- const exit = new Promise((resolveExit, rejectExit) => {
67967
- child.once("error", rejectExit);
67968
- child.once("exit", (code) => resolveExit(code ?? 1));
68012
+ const completion = new Promise((resolveCompletion, rejectCompletion) => {
68013
+ child.once("error", rejectCompletion);
68014
+ child.once("exit", (code) => {
68015
+ if (code !== 0) {
68016
+ resolveCompletion(code ?? 1);
68017
+ }
68018
+ });
68019
+ child.once("close", (code) => resolveCompletion(code ?? 1));
67969
68020
  });
67970
- const exitCode = await Promise.race([exit, interrupted.promise.then(() => -1)]);
68021
+ const exitCode = await Promise.race([completion, interrupted.promise.then(() => -1)]);
67971
68022
  if (interruptionCleanupFailure !== null) {
67972
68023
  throw interruptionCleanupFailure;
67973
68024
  }
@@ -67979,12 +68030,19 @@ async function runBoundedProcess(options) {
67979
68030
  }
67980
68031
  return new ProcessResult(Buffer.concat(stdout).toString("utf8"), Buffer.concat(stderr).toString("utf8"));
67981
68032
  } catch (error62) {
67982
- if (error62 instanceof ProcessExecutionError) {
67983
- throw error62;
67984
- }
67985
- throw new ProcessExecutionError("process_spawn_failed", "The executable could not be started", {
68033
+ const failure2 = error62 instanceof ProcessExecutionError ? error62 : new ProcessExecutionError("process_spawn_failed", "The executable could not be started", {
67986
68034
  cause: error62
67987
68035
  });
68036
+ throw new ProcessExecutionError(failure2.code, failure2.message, {
68037
+ cause: error62,
68038
+ diagnosticDetails: {
68039
+ stdoutBytes: stdoutBytes.toString(),
68040
+ stderrBytes: stderrBytes.toString(),
68041
+ outputLimitBytes: outputLimitBytes.toString(),
68042
+ ...child.exitCode === null ? {} : { exitCode: child.exitCode.toString() },
68043
+ ...child.signalCode === null ? {} : { signal: child.signalCode }
68044
+ }
68045
+ });
67988
68046
  } finally {
67989
68047
  clearTimeout(timeout);
67990
68048
  options.signal.removeEventListener("abort", abort);
@@ -75451,7 +75509,14 @@ async function probeVersion(executable, arguments_, environment, defaultWorkspac
75451
75509
  });
75452
75510
  const version2 = normalize4(result.stdout || result.stderr);
75453
75511
  if (version2.length === 0) {
75454
- throw new ProcessExecutionError("process_exit_failed", "The executable did not report a version");
75512
+ throw new ProcessExecutionError("process_exit_failed", "The executable did not report a version", {
75513
+ diagnosticDetails: {
75514
+ probeReason: "empty_version_output",
75515
+ exitCode: "0",
75516
+ stdoutBytes: Buffer.byteLength(result.stdout).toString(),
75517
+ stderrBytes: Buffer.byteLength(result.stderr).toString()
75518
+ }
75519
+ });
75455
75520
  }
75456
75521
  return version2;
75457
75522
  }
@@ -75473,9 +75538,27 @@ function isRetryableProbeFailure(error62) {
75473
75538
  }
75474
75539
  return error62 instanceof AgentProbeError && error62.code === "adapter_probe_timeout";
75475
75540
  }
75476
- async function probeWithRetry(signal, probe) {
75541
+ async function probeWithRetry(context, specification, source, probe) {
75542
+ const signal = context.signal;
75543
+ const run = async (attempt) => {
75544
+ const startedAt = performance.now();
75545
+ try {
75546
+ return await probe();
75547
+ } catch (failure2) {
75548
+ context.onProbeDiagnostic?.({
75549
+ agentId: specification.id,
75550
+ source,
75551
+ event: signal.aborted ? "agent_probe_cancelled" : "agent_probe_failed",
75552
+ attempt,
75553
+ elapsedMilliseconds: Math.round(performance.now() - startedAt),
75554
+ timeoutMilliseconds: source === "acp_readiness" ? specification.acpProbeTimeoutMilliseconds : specification.versionProbeTimeoutMilliseconds,
75555
+ failure: failure2
75556
+ });
75557
+ throw failure2;
75558
+ }
75559
+ };
75477
75560
  try {
75478
- return await probe();
75561
+ return await run(1);
75479
75562
  } catch (error62) {
75480
75563
  if (signal.aborted) {
75481
75564
  signal.throwIfAborted();
@@ -75483,7 +75566,7 @@ async function probeWithRetry(signal, probe) {
75483
75566
  if (!isRetryableProbeFailure(error62)) {
75484
75567
  throw error62;
75485
75568
  }
75486
- return await probe();
75569
+ return await run(2);
75487
75570
  }
75488
75571
  }
75489
75572
  function integrationProbeFailure(specification, error62) {
@@ -75513,7 +75596,9 @@ async function discoverAgent(specification, context) {
75513
75596
  let agentVersion = "";
75514
75597
  try {
75515
75598
  agentVersion = await probeWithRetry(
75516
- context.signal,
75599
+ context,
75600
+ specification,
75601
+ "agent_version",
75517
75602
  async () => await probeVersion(
75518
75603
  agent,
75519
75604
  specification.agentVersionArguments,
@@ -75561,7 +75646,9 @@ async function discoverAgent(specification, context) {
75561
75646
  launchEnvironment = await specification.createLaunchEnvironment(agent, context);
75562
75647
  if (specification.adapterVersionArguments.length > 0) {
75563
75648
  adapterVersion = await probeWithRetry(
75564
- context.signal,
75649
+ context,
75650
+ specification,
75651
+ "adapter_version",
75565
75652
  async () => await probeVersion(
75566
75653
  adapter,
75567
75654
  specification.adapterVersionArguments,
@@ -75596,7 +75683,9 @@ async function discoverAgent(specification, context) {
75596
75683
  );
75597
75684
  try {
75598
75685
  const readiness = await probeWithRetry(
75599
- context.signal,
75686
+ context,
75687
+ specification,
75688
+ "acp_readiness",
75600
75689
  async () => await probeAcpReadiness(
75601
75690
  specification,
75602
75691
  buildDefinition(adapterVersion, unsupportedSessionCapabilities()),
@@ -83299,6 +83388,266 @@ function describeEnvironmentProxyRoute(target) {
83299
83388
  };
83300
83389
  }
83301
83390
 
83391
+ // src/engine/runtime/observability/diagnostic-log.ts
83392
+ import { join as join26 } from "node:path";
83393
+
83394
+ // src/engine/storage/logs/bounded-log.ts
83395
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync9, renameSync as renameSync2, statSync as statSync5, writeFileSync as writeFileSync2 } from "node:fs";
83396
+ import { join as join24 } from "node:path";
83397
+ var BoundedLineLog = class {
83398
+ #path;
83399
+ #maximumBytes;
83400
+ #directory;
83401
+ #reportedFailure = false;
83402
+ #onWriteFailure;
83403
+ constructor(directory, filename, maximumBytes, onWriteFailure = () => void 0) {
83404
+ this.#directory = directory;
83405
+ this.#path = join24(directory, filename);
83406
+ this.#maximumBytes = maximumBytes;
83407
+ this.#onWriteFailure = onWriteFailure;
83408
+ }
83409
+ record = (line) => {
83410
+ try {
83411
+ mkdirSync4(this.#directory, { mode: 448, recursive: true });
83412
+ this.#append(line);
83413
+ } catch (cause) {
83414
+ if (!this.#reportedFailure) {
83415
+ this.#reportedFailure = true;
83416
+ this.#onWriteFailure(cause);
83417
+ }
83418
+ }
83419
+ };
83420
+ #append = (line) => {
83421
+ const encoded = `${line.replace(/[\r\n]+/gu, " ").trim()}
83422
+ `;
83423
+ const encodedBytes = Buffer.byteLength(encoded);
83424
+ let existingBytes = 0;
83425
+ try {
83426
+ existingBytes = statSync5(this.#path).size;
83427
+ } catch (cause) {
83428
+ if (!(cause instanceof Error && Reflect.get(cause, "code") === "ENOENT")) {
83429
+ throw cause;
83430
+ }
83431
+ }
83432
+ if (existingBytes + encodedBytes <= this.#maximumBytes) {
83433
+ appendFileSync2(this.#path, encoded, { encoding: "utf8", mode: 384 });
83434
+ return;
83435
+ }
83436
+ const lines = `${existingBytes === 0 ? "" : readFileSync9(this.#path, "utf8")}${encoded}`.split("\n").filter((candidate) => candidate.length > 0);
83437
+ let totalBytes = lines.reduce((total, candidate) => total + Buffer.byteLength(candidate) + 1, 0);
83438
+ while (totalBytes > this.#maximumBytes && lines.length > 0) {
83439
+ const oldest = lines.shift();
83440
+ if (oldest !== void 0) {
83441
+ totalBytes -= Buffer.byteLength(oldest) + 1;
83442
+ }
83443
+ }
83444
+ const temporaryPath = `${this.#path}.tmp`;
83445
+ writeFileSync2(temporaryPath, lines.length === 0 ? "" : `${lines.join("\n")}
83446
+ `, {
83447
+ encoding: "utf8",
83448
+ mode: 384
83449
+ });
83450
+ renameSync2(temporaryPath, this.#path);
83451
+ };
83452
+ };
83453
+
83454
+ // src/engine/storage/logs/log-files.ts
83455
+ import { readFileSync as readFileSync10 } from "node:fs";
83456
+ import { join as join25 } from "node:path";
83457
+ var DAEMON_LOG_FILENAME = "daemon.log";
83458
+ var WORKER_LIFECYCLE_LOG_FILENAME = "worker-lifecycle.log";
83459
+ function unhandledRejectionLogFilename(role) {
83460
+ return `unhandled-rejections-${role}.log`;
83461
+ }
83462
+ function logDirectory(dataDirectory) {
83463
+ return join25(dataDirectory, "logs");
83464
+ }
83465
+ function processLogPaths(dataDirectory) {
83466
+ return [
83467
+ WORKER_LIFECYCLE_LOG_FILENAME,
83468
+ unhandledRejectionLogFilename("manager"),
83469
+ unhandledRejectionLogFilename("worker")
83470
+ ].map((filename) => join25(logDirectory(dataDirectory), filename));
83471
+ }
83472
+ function readLogText(path7) {
83473
+ try {
83474
+ return readFileSync10(path7, "utf8");
83475
+ } catch {
83476
+ return null;
83477
+ }
83478
+ }
83479
+
83480
+ // src/engine/runtime/observability/diagnostic-log.ts
83481
+ var MAXIMUM_RUNTIME_LOG_BYTES = 1 * 1024 * 1024;
83482
+ var MAXIMUM_ENTRIES = 200;
83483
+ var MAXIMUM_REPORT_BYTES = 6e4;
83484
+ var REMOTE_DIAGNOSTIC_FIELDS = [
83485
+ "agentId",
83486
+ "operation",
83487
+ "runtimeId",
83488
+ "closeCode",
83489
+ "timeoutMilliseconds",
83490
+ "attempt",
83491
+ "elapsedMilliseconds",
83492
+ "stdoutBytes",
83493
+ "stderrBytes",
83494
+ "outputLimitBytes",
83495
+ "probeReason",
83496
+ "proxyRoute",
83497
+ "timestamp",
83498
+ "event",
83499
+ "channelId",
83500
+ "requestId",
83501
+ "commandId",
83502
+ "sessionId",
83503
+ "turnId",
83504
+ "connectionEpoch",
83505
+ "code",
83506
+ "source",
83507
+ "kind",
83508
+ "pid",
83509
+ "version",
83510
+ "exitCode",
83511
+ "signal",
83512
+ "failureName",
83513
+ "failureCode",
83514
+ "failureStatusCode",
83515
+ "cause1Name",
83516
+ "cause1Code",
83517
+ "cause2Name",
83518
+ "cause2Code"
83519
+ ];
83520
+ var FIELD_VALUE_PATTERN = /^[a-zA-Z0-9_.: -]{1,256}$/u;
83521
+ var RuntimeDiagnosticLog = class {
83522
+ #log;
83523
+ #maximumBytes;
83524
+ #sources;
83525
+ constructor(stateDirectory, options = {}) {
83526
+ const maximumBytes = options.maximumBytes ?? MAXIMUM_RUNTIME_LOG_BYTES;
83527
+ const directory = logDirectory(stateDirectory);
83528
+ this.#log = new BoundedLineLog(directory, DAEMON_LOG_FILENAME, maximumBytes);
83529
+ this.#maximumBytes = maximumBytes;
83530
+ const processLogsDirectory = options.processLogsDirectory;
83531
+ this.#sources = [
83532
+ { maximumBytes, path: join26(directory, DAEMON_LOG_FILENAME) },
83533
+ // The process logs a Runtime does not own, but must read to explain its own deaths.
83534
+ ...processLogsDirectory === void 0 ? [] : processLogPaths(processLogsDirectory).map((path7) => ({ maximumBytes: null, path: path7 }))
83535
+ ];
83536
+ }
83537
+ // Export only correlation and failure metadata. Local messages and paths stay local.
83538
+ snapshot = () => {
83539
+ const merged = [];
83540
+ let truncated = false;
83541
+ for (const source of this.#sources) {
83542
+ const collected = this.#read(source);
83543
+ merged.push(...collected.entries);
83544
+ truncated ||= collected.truncated;
83545
+ }
83546
+ merged.sort(compareTimestamp);
83547
+ const entries = merged.slice(-MAXIMUM_ENTRIES);
83548
+ truncated ||= entries.length < merged.length;
83549
+ while (JSON.stringify(entries).length > MAXIMUM_REPORT_BYTES && entries.length > 0) {
83550
+ entries.shift();
83551
+ truncated = true;
83552
+ }
83553
+ return { entries, truncated };
83554
+ };
83555
+ record = (diagnostic) => {
83556
+ this.#log.record(diagnostic);
83557
+ };
83558
+ #read = (source) => {
83559
+ const content = readLogText(source.path);
83560
+ if (content === null) {
83561
+ return { entries: [], truncated: false };
83562
+ }
83563
+ const lines = content.split("\n").filter((line) => line.length > 0);
83564
+ const entries = [];
83565
+ for (const line of lines.slice(-MAXIMUM_ENTRIES)) {
83566
+ const start = line.indexOf("{");
83567
+ if (start < 0) {
83568
+ continue;
83569
+ }
83570
+ let value;
83571
+ try {
83572
+ value = JSON.parse(line.slice(start));
83573
+ } catch {
83574
+ continue;
83575
+ }
83576
+ if (typeof value !== "object" || value === null) {
83577
+ continue;
83578
+ }
83579
+ entries.push(exportedFields(value));
83580
+ }
83581
+ const nearRotation = source.maximumBytes !== null && Buffer.byteLength(content) >= source.maximumBytes - 4096;
83582
+ return { entries, truncated: lines.length > MAXIMUM_ENTRIES || nearRotation };
83583
+ };
83584
+ };
83585
+ function exportedFields(value) {
83586
+ const entry = {};
83587
+ for (const field of REMOTE_DIAGNOSTIC_FIELDS) {
83588
+ const item = Reflect.get(value, field);
83589
+ if (typeof item === "string" && FIELD_VALUE_PATTERN.test(item)) {
83590
+ entry[field] = item;
83591
+ } else if (typeof item === "number" && Number.isFinite(item)) {
83592
+ entry[field] = String(item);
83593
+ }
83594
+ }
83595
+ return entry;
83596
+ }
83597
+ function compareTimestamp(left, right) {
83598
+ const leftAt = left["timestamp"] ?? "";
83599
+ const rightAt = right["timestamp"] ?? "";
83600
+ return leftAt < rightAt ? -1 : leftAt > rightAt ? 1 : 0;
83601
+ }
83602
+
83603
+ // src/engine/runtime/catalog/discover-agent-catalog.ts
83604
+ function failureDetails(failure2) {
83605
+ const fields = {};
83606
+ let current = failure2;
83607
+ for (let depth = 0; depth < 3 && current instanceof Error; depth += 1) {
83608
+ const prefix = depth === 0 ? "failure" : `cause${depth.toString()}`;
83609
+ if (current instanceof ProcessExecutionError || current instanceof AgentProbeError) {
83610
+ fields[`${prefix}Name`] = current instanceof ProcessExecutionError ? "ProcessExecutionError" : "AgentProbeError";
83611
+ fields[`${prefix}Code`] = current.code;
83612
+ } else {
83613
+ fields[`${prefix}Name`] = "Error";
83614
+ }
83615
+ if (depth === 0 && current instanceof ProcessExecutionError) {
83616
+ Object.assign(fields, current.diagnosticDetails);
83617
+ }
83618
+ current = current.cause;
83619
+ }
83620
+ return fields;
83621
+ }
83622
+ async function discoverRuntimeAgentInventory(options, channelId) {
83623
+ const log = new RuntimeDiagnosticLog(options.dataDirectory);
83624
+ const record2 = (details) => {
83625
+ log.record(
83626
+ `Mobius agent discovery diagnostic ${JSON.stringify({
83627
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
83628
+ channelId,
83629
+ ...details
83630
+ })}`
83631
+ );
83632
+ };
83633
+ const inventory = await discoverLocalAgentInventory({
83634
+ ...options,
83635
+ onProbeDiagnostic: ({ failure: failure2, ...diagnostic }) => {
83636
+ record2({ ...diagnostic, ...failureDetails(failure2) });
83637
+ }
83638
+ });
83639
+ for (const { discovery, detectionMilliseconds } of inventory.results) {
83640
+ record2({
83641
+ event: "agent_discovery_result",
83642
+ agentId: discovery.specification.id,
83643
+ code: discovery instanceof UnavailableAgent ? discovery.code : "ready",
83644
+ source: discovery.status,
83645
+ elapsedMilliseconds: detectionMilliseconds
83646
+ });
83647
+ }
83648
+ return inventory;
83649
+ }
83650
+
83302
83651
  // src/engine/runtime/catalog/publish-agent-catalog.ts
83303
83652
  import { fetch as fetch2 } from "undici";
83304
83653
 
@@ -83745,21 +84094,27 @@ function buildSavedRuntimeConfig(connection, defaultWorkspace, inventory, localC
83745
84094
  localContext,
83746
84095
  new OpaqueRuntimeReconnectTarget(connection.connectionId),
83747
84096
  createCatalogAgentResolver(
83748
- (refreshSignal) => discoverLocalAgentInventory({
84097
+ (refreshSignal) => discoverRuntimeAgentInventory(
84098
+ {
84099
+ defaultWorkspace,
84100
+ dataDirectory: localContext.stateDirectory,
84101
+ environment: localContext.agentLaunchEnvironment,
84102
+ signal: refreshSignal
84103
+ },
84104
+ connection.channelId
84105
+ ),
84106
+ () => config2,
84107
+ publishAgentCatalog
84108
+ ),
84109
+ (refreshSignal) => discoverRuntimeAgentInventory(
84110
+ {
83749
84111
  defaultWorkspace,
83750
84112
  dataDirectory: localContext.stateDirectory,
83751
84113
  environment: localContext.agentLaunchEnvironment,
83752
84114
  signal: refreshSignal
83753
- }),
83754
- () => config2,
83755
- publishAgentCatalog
83756
- ),
83757
- (refreshSignal) => discoverLocalAgentInventory({
83758
- defaultWorkspace,
83759
- dataDirectory: localContext.stateDirectory,
83760
- environment: localContext.agentLaunchEnvironment,
83761
- signal: refreshSignal
83762
- }).then((inventory2) => inventory2.readyAgents())
84115
+ },
84116
+ connection.channelId
84117
+ ).then((inventory2) => inventory2.readyAgents())
83763
84118
  );
83764
84119
  return config2;
83765
84120
  }
@@ -83803,12 +84158,15 @@ async function pairRuntimeConnection(installation, options, signal, environment)
83803
84158
  async function prepareRuntimeConnection(installation, connection, signal, environment, maxAcpProcesses) {
83804
84159
  const localContext = new RuntimeLocalContext(installation.stateDirectory, environment, maxAcpProcesses);
83805
84160
  const defaultWorkspace = await resolveDefaultWorkspace(connection.defaultWorkspace);
83806
- const inventory = await discoverLocalAgentInventory({
83807
- defaultWorkspace,
83808
- dataDirectory: localContext.stateDirectory,
83809
- environment: localContext.agentLaunchEnvironment,
83810
- signal
83811
- });
84161
+ const inventory = await discoverRuntimeAgentInventory(
84162
+ {
84163
+ defaultWorkspace,
84164
+ dataDirectory: localContext.stateDirectory,
84165
+ environment: localContext.agentLaunchEnvironment,
84166
+ signal
84167
+ },
84168
+ connection.channelId
84169
+ );
83812
84170
  return buildSavedRuntimeConfig(connection, defaultWorkspace, inventory, localContext);
83813
84171
  }
83814
84172
 
@@ -87897,7 +88255,7 @@ var SessionTurns = class {
87897
88255
 
87898
88256
  // src/engine/session/workspace/workspace-directory.ts
87899
88257
  import { homedir as homedir3 } from "node:os";
87900
- import { basename as basename7, dirname as dirname10, isAbsolute as isAbsolute15, join as join24, normalize as normalize2, relative as relative2 } from "node:path";
88258
+ import { basename as basename7, dirname as dirname10, isAbsolute as isAbsolute15, join as join27, normalize as normalize2, relative as relative2 } from "node:path";
87901
88259
  var WorkspaceDirectoryListing = class {
87902
88260
  directoryId;
87903
88261
  directoryLabel;
@@ -88020,7 +88378,7 @@ var WorkspaceDirectoryService = class {
88020
88378
  continue;
88021
88379
  }
88022
88380
  try {
88023
- const path7 = await this.resolvePath(join24(target, child.name), signal);
88381
+ const path7 = await this.resolvePath(join27(target, child.name), signal);
88024
88382
  entries.push({ directoryId: encodePath(path7), name: child.name });
88025
88383
  } catch (cause) {
88026
88384
  signal.throwIfAborted();
@@ -88176,12 +88534,12 @@ function buildSessionLayer(options) {
88176
88534
 
88177
88535
  // src/engine/session/content/external-content-store.ts
88178
88536
  import { createHash as createHash8 } from "node:crypto";
88179
- import { extname as extname3, join as join26 } from "node:path";
88537
+ import { extname as extname2, join as join29 } from "node:path";
88180
88538
 
88181
88539
  // src/engine/storage/files/scratch-directory.ts
88182
88540
  import { randomUUID as randomUUID17 } from "node:crypto";
88183
88541
  import { lstat as lstat4, mkdir as mkdir5, readdir as readdir6, readFile as readFile6, realpath as realpath7, rename as rename4, rm as rm3, stat as stat6, utimes, writeFile as writeFile2 } from "node:fs/promises";
88184
- import { dirname as dirname11, join as join25 } from "node:path";
88542
+ import { dirname as dirname11, join as join28 } from "node:path";
88185
88543
  async function atomicWrite(path7, bytes, signal) {
88186
88544
  const temporary = `${path7}.${randomUUID17()}.tmp`;
88187
88545
  try {
@@ -88195,7 +88553,7 @@ async function atomicWrite(path7, bytes, signal) {
88195
88553
  var ScratchDirectory = class {
88196
88554
  #root;
88197
88555
  constructor(parent) {
88198
- this.#root = join25(parent, randomUUID17());
88556
+ this.#root = join28(parent, randomUUID17());
88199
88557
  }
88200
88558
  /** Refreshes this directory's lease and removes sibling directories whose lease is older than `leaseMilliseconds`. */
88201
88559
  refreshLease = async (leaseMilliseconds) => {
@@ -88206,7 +88564,7 @@ var ScratchDirectory = class {
88206
88564
  if (!directory.isDirectory() || !/^[a-f0-9-]{36}$/u.test(directory.name)) {
88207
88565
  continue;
88208
88566
  }
88209
- const path7 = join25(dirname11(this.#root), directory.name);
88567
+ const path7 = join28(dirname11(this.#root), directory.name);
88210
88568
  if (path7 === this.#root) {
88211
88569
  continue;
88212
88570
  }
@@ -88221,10 +88579,10 @@ var ScratchDirectory = class {
88221
88579
  };
88222
88580
  /** Writes `bytes` atomically to `<group>/<name>` with owner-only permissions and returns the path. */
88223
88581
  write = async (group, name2, bytes, signal) => {
88224
- const directory = join25(this.#root, group);
88582
+ const directory = join28(this.#root, group);
88225
88583
  await mkdir5(directory, { mode: 448, recursive: true });
88226
88584
  signal.throwIfAborted();
88227
- const path7 = join25(directory, name2);
88585
+ const path7 = join28(directory, name2);
88228
88586
  await atomicWrite(path7, bytes, signal);
88229
88587
  return path7;
88230
88588
  };
@@ -88264,7 +88622,7 @@ var metadataSchema = external_exports.strictObject({
88264
88622
  name: external_exports.string().min(1).max(500)
88265
88623
  });
88266
88624
  function contentFileName(key, name2) {
88267
- const extension = extname3(name2).toLowerCase();
88625
+ const extension = extname2(name2).toLowerCase();
88268
88626
  return /^\.[a-z0-9]{1,16}$/u.test(extension) ? `${key}${extension}` : key;
88269
88627
  }
88270
88628
  var LocalExternalContentStore = class {
@@ -88275,7 +88633,7 @@ var LocalExternalContentStore = class {
88275
88633
  #expirationTimer;
88276
88634
  #cleanup = Promise.resolve();
88277
88635
  constructor(stateDirectory) {
88278
- this.#scratch = new ScratchDirectory(join26(stateDirectory, "tmp", "session-content"));
88636
+ this.#scratch = new ScratchDirectory(join29(stateDirectory, "tmp", "session-content"));
88279
88637
  this.#expirationTimer = setInterval(() => {
88280
88638
  void this.#expire().catch(() => void 0);
88281
88639
  }, 6e4);
@@ -88649,212 +89007,6 @@ var AgentProcessPool = class {
88649
89007
  };
88650
89008
  };
88651
89009
 
88652
- // src/engine/runtime/observability/diagnostic-log.ts
88653
- import { join as join29 } from "node:path";
88654
-
88655
- // src/engine/storage/logs/bounded-log.ts
88656
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync9, renameSync as renameSync2, statSync as statSync5, writeFileSync as writeFileSync2 } from "node:fs";
88657
- import { join as join27 } from "node:path";
88658
- var BoundedLineLog = class {
88659
- #path;
88660
- #maximumBytes;
88661
- #directory;
88662
- #reportedFailure = false;
88663
- #onWriteFailure;
88664
- constructor(directory, filename, maximumBytes, onWriteFailure = () => void 0) {
88665
- this.#directory = directory;
88666
- this.#path = join27(directory, filename);
88667
- this.#maximumBytes = maximumBytes;
88668
- this.#onWriteFailure = onWriteFailure;
88669
- }
88670
- record = (line) => {
88671
- try {
88672
- mkdirSync4(this.#directory, { mode: 448, recursive: true });
88673
- this.#append(line);
88674
- } catch (cause) {
88675
- if (!this.#reportedFailure) {
88676
- this.#reportedFailure = true;
88677
- this.#onWriteFailure(cause);
88678
- }
88679
- }
88680
- };
88681
- #append = (line) => {
88682
- const encoded = `${line.replace(/[\r\n]+/gu, " ").trim()}
88683
- `;
88684
- const encodedBytes = Buffer.byteLength(encoded);
88685
- let existingBytes = 0;
88686
- try {
88687
- existingBytes = statSync5(this.#path).size;
88688
- } catch (cause) {
88689
- if (!(cause instanceof Error && Reflect.get(cause, "code") === "ENOENT")) {
88690
- throw cause;
88691
- }
88692
- }
88693
- if (existingBytes + encodedBytes <= this.#maximumBytes) {
88694
- appendFileSync2(this.#path, encoded, { encoding: "utf8", mode: 384 });
88695
- return;
88696
- }
88697
- const lines = `${existingBytes === 0 ? "" : readFileSync9(this.#path, "utf8")}${encoded}`.split("\n").filter((candidate) => candidate.length > 0);
88698
- let totalBytes = lines.reduce((total, candidate) => total + Buffer.byteLength(candidate) + 1, 0);
88699
- while (totalBytes > this.#maximumBytes && lines.length > 0) {
88700
- const oldest = lines.shift();
88701
- if (oldest !== void 0) {
88702
- totalBytes -= Buffer.byteLength(oldest) + 1;
88703
- }
88704
- }
88705
- const temporaryPath = `${this.#path}.tmp`;
88706
- writeFileSync2(temporaryPath, lines.length === 0 ? "" : `${lines.join("\n")}
88707
- `, {
88708
- encoding: "utf8",
88709
- mode: 384
88710
- });
88711
- renameSync2(temporaryPath, this.#path);
88712
- };
88713
- };
88714
-
88715
- // src/engine/storage/logs/log-files.ts
88716
- import { readFileSync as readFileSync10 } from "node:fs";
88717
- import { join as join28 } from "node:path";
88718
- var DAEMON_LOG_FILENAME = "daemon.log";
88719
- var WORKER_LIFECYCLE_LOG_FILENAME = "worker-lifecycle.log";
88720
- function unhandledRejectionLogFilename(role) {
88721
- return `unhandled-rejections-${role}.log`;
88722
- }
88723
- function logDirectory(dataDirectory) {
88724
- return join28(dataDirectory, "logs");
88725
- }
88726
- function processLogPaths(dataDirectory) {
88727
- return [
88728
- WORKER_LIFECYCLE_LOG_FILENAME,
88729
- unhandledRejectionLogFilename("manager"),
88730
- unhandledRejectionLogFilename("worker")
88731
- ].map((filename) => join28(logDirectory(dataDirectory), filename));
88732
- }
88733
- function readLogText(path7) {
88734
- try {
88735
- return readFileSync10(path7, "utf8");
88736
- } catch {
88737
- return null;
88738
- }
88739
- }
88740
-
88741
- // src/engine/runtime/observability/diagnostic-log.ts
88742
- var MAXIMUM_RUNTIME_LOG_BYTES = 1 * 1024 * 1024;
88743
- var MAXIMUM_ENTRIES = 200;
88744
- var MAXIMUM_REPORT_BYTES = 6e4;
88745
- var REMOTE_DIAGNOSTIC_FIELDS = [
88746
- "agentId",
88747
- "operation",
88748
- "runtimeId",
88749
- "closeCode",
88750
- "timeoutMilliseconds",
88751
- "proxyRoute",
88752
- "timestamp",
88753
- "event",
88754
- "channelId",
88755
- "requestId",
88756
- "commandId",
88757
- "sessionId",
88758
- "turnId",
88759
- "connectionEpoch",
88760
- "code",
88761
- "source",
88762
- "kind",
88763
- "pid",
88764
- "version",
88765
- "exitCode",
88766
- "signal",
88767
- "failureName",
88768
- "failureCode",
88769
- "failureStatusCode",
88770
- "cause1Name",
88771
- "cause1Code",
88772
- "cause2Name",
88773
- "cause2Code"
88774
- ];
88775
- var FIELD_VALUE_PATTERN = /^[a-zA-Z0-9_.: -]{1,256}$/u;
88776
- var RuntimeDiagnosticLog = class {
88777
- #log;
88778
- #maximumBytes;
88779
- #sources;
88780
- constructor(stateDirectory, options = {}) {
88781
- const maximumBytes = options.maximumBytes ?? MAXIMUM_RUNTIME_LOG_BYTES;
88782
- const directory = logDirectory(stateDirectory);
88783
- this.#log = new BoundedLineLog(directory, DAEMON_LOG_FILENAME, maximumBytes);
88784
- this.#maximumBytes = maximumBytes;
88785
- const processLogsDirectory = options.processLogsDirectory;
88786
- this.#sources = [
88787
- { maximumBytes, path: join29(directory, DAEMON_LOG_FILENAME) },
88788
- // The process logs a Runtime does not own, but must read to explain its own deaths.
88789
- ...processLogsDirectory === void 0 ? [] : processLogPaths(processLogsDirectory).map((path7) => ({ maximumBytes: null, path: path7 }))
88790
- ];
88791
- }
88792
- // Export only correlation and failure metadata. Local messages and paths stay local.
88793
- snapshot = () => {
88794
- const merged = [];
88795
- let truncated = false;
88796
- for (const source of this.#sources) {
88797
- const collected = this.#read(source);
88798
- merged.push(...collected.entries);
88799
- truncated ||= collected.truncated;
88800
- }
88801
- merged.sort(compareTimestamp);
88802
- const entries = merged.slice(-MAXIMUM_ENTRIES);
88803
- truncated ||= entries.length < merged.length;
88804
- while (JSON.stringify(entries).length > MAXIMUM_REPORT_BYTES && entries.length > 0) {
88805
- entries.shift();
88806
- truncated = true;
88807
- }
88808
- return { entries, truncated };
88809
- };
88810
- record = (diagnostic) => {
88811
- this.#log.record(diagnostic);
88812
- };
88813
- #read = (source) => {
88814
- const content = readLogText(source.path);
88815
- if (content === null) {
88816
- return { entries: [], truncated: false };
88817
- }
88818
- const lines = content.split("\n").filter((line) => line.length > 0);
88819
- const entries = [];
88820
- for (const line of lines.slice(-MAXIMUM_ENTRIES)) {
88821
- const start = line.indexOf("{");
88822
- if (start < 0) {
88823
- continue;
88824
- }
88825
- let value;
88826
- try {
88827
- value = JSON.parse(line.slice(start));
88828
- } catch {
88829
- continue;
88830
- }
88831
- if (typeof value !== "object" || value === null) {
88832
- continue;
88833
- }
88834
- entries.push(exportedFields(value));
88835
- }
88836
- const nearRotation = source.maximumBytes !== null && Buffer.byteLength(content) >= source.maximumBytes - 4096;
88837
- return { entries, truncated: lines.length > MAXIMUM_ENTRIES || nearRotation };
88838
- };
88839
- };
88840
- function exportedFields(value) {
88841
- const entry = {};
88842
- for (const field of REMOTE_DIAGNOSTIC_FIELDS) {
88843
- const item = Reflect.get(value, field);
88844
- if (typeof item === "string" && FIELD_VALUE_PATTERN.test(item)) {
88845
- entry[field] = item;
88846
- } else if (typeof item === "number" && Number.isFinite(item)) {
88847
- entry[field] = String(item);
88848
- }
88849
- }
88850
- return entry;
88851
- }
88852
- function compareTimestamp(left, right) {
88853
- const leftAt = left["timestamp"] ?? "";
88854
- const rightAt = right["timestamp"] ?? "";
88855
- return leftAt < rightAt ? -1 : leftAt > rightAt ? 1 : 0;
88856
- }
88857
-
88858
89010
  // src/engine/runtime/relay/diagnostics.ts
88859
89011
  var MAX_DIAGNOSTIC_TEXT_LENGTH = 256;
88860
89012
  function sanitizeDiagnosticText(value) {
@@ -89779,7 +89931,7 @@ function createContentWriteCommands(context) {
89779
89931
  import { WebSocket as WebSocket5 } from "undici";
89780
89932
 
89781
89933
  // src/engine/session/content/session-files.ts
89782
- import { basename as basename8, extname as extname4, isAbsolute as isAbsolute16, join as join30, normalize as normalize3, resolve as resolve16 } from "node:path";
89934
+ import { basename as basename8, extname as extname3, isAbsolute as isAbsolute16, join as join30, normalize as normalize3, resolve as resolve16 } from "node:path";
89783
89935
  import { fileURLToPath as fileURLToPath2 } from "node:url";
89784
89936
  function requestedPath(value) {
89785
89937
  if (value.includes("\0")) {
@@ -89835,7 +89987,7 @@ async function streamLocalFile(command, send2, sendChunk, signal, workingDirecto
89835
89987
  send2({
89836
89988
  byteLength: before.size,
89837
89989
  kind: FILE_BEGIN_KIND,
89838
- mediaType: external?.mediaType ?? raster?.mimeType ?? (extname4(target).toLowerCase() === ".svg" ? "image/svg+xml" : "application/octet-stream"),
89990
+ mediaType: external?.mediaType ?? raster?.mimeType ?? (extname3(target).toLowerCase() === ".svg" ? "image/svg+xml" : "application/octet-stream"),
89839
89991
  modifiedAt: before.modifiedAt.toISOString(),
89840
89992
  name: external?.name ?? (basename8(target) || "file"),
89841
89993
  requestId: command.requestId,
@@ -90797,7 +90949,7 @@ var sessionPromptCommand = {
90797
90949
  // package.json
90798
90950
  var package_default = {
90799
90951
  name: "@moxt-ai/mobius",
90800
- version: "0.0.353",
90952
+ version: "0.0.355",
90801
90953
  description: "Mobius CLI for pairing and running local AI agent services.",
90802
90954
  type: "module",
90803
90955
  bin: {
@@ -92254,13 +92406,16 @@ async function prepareProvidedRuntime({
92254
92406
  const defaultWorkspace = await resolveWorkspace(connection.defaultWorkspace);
92255
92407
  const specifications = supportedLocalAgentSpecifications();
92256
92408
  const discoveryEnvironment = localContext.agentLaunchEnvironment;
92257
- const discover = async (refreshSignal) => await discoverLocalAgentInventory({
92258
- defaultWorkspace,
92259
- dataDirectory: localContext.stateDirectory,
92260
- environment: discoveryEnvironment,
92261
- signal: refreshSignal,
92262
- specifications
92263
- });
92409
+ const discover = async (refreshSignal) => await discoverRuntimeAgentInventory(
92410
+ {
92411
+ defaultWorkspace,
92412
+ dataDirectory: localContext.stateDirectory,
92413
+ environment: discoveryEnvironment,
92414
+ signal: refreshSignal,
92415
+ specifications
92416
+ },
92417
+ connection.channelId
92418
+ );
92264
92419
  const inventory = await discover(signal);
92265
92420
  const config2 = createRuntimeConfig(
92266
92421
  {