@moxt-ai/mobius 0.0.354 → 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 +407 -412
  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 +376 -393
  32. package/dist/engine.js.map +4 -4
  33. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -2086,7 +2086,7 @@ var init_package = __esm({
2086
2086
  "package.json"() {
2087
2087
  package_default = {
2088
2088
  name: "@moxt-ai/mobius",
2089
- version: "0.0.354",
2089
+ version: "0.0.355",
2090
2090
  description: "Mobius CLI for pairing and running local AI agent services.",
2091
2091
  type: "module",
2092
2092
  bin: {
@@ -26964,7 +26964,7 @@ function sanitizeConsumableNativeSessionEvents(value) {
26964
26964
  )
26965
26965
  };
26966
26966
  }
26967
- var MAX_EVENT_COUNT, MAX_COLLECTION_SIZE2, MAX_CONTENT_LENGTH2, SESSION_EVENT_KIND, SESSION_EVENT_BATCH_MAX_SIZE, boundedString2, shortString, externalContentKeySchema, annotationsSchema, contentFields, textContentSchema, imageContentSchema, audioContentSchema, externalImageContentSchema, externalAudioContentSchema, externalResourceContentSchema, resourceLinkSchema, textResourceSchema, blobResourceSchema, embeddedResourceSchema, contentBlockSchema, toolCallContentSchema, toolKindSchema, toolStatusSchema, backgroundTaskSchema, toolPatchFields, planEntrySchema, planContentSchema, commandSchema, configSelectOptionSchema, configSelectGroupSchema, configBaseFields, sessionConfigOptionSchema2, contentChunkFields, acpSessionUpdateSchema, lifecycleBase, promptExecutionContextSchema, lifecycleMetadataSchema, sessionEventPayloadSchema, positionSchema, sharedSessionEventFields, sessionLiveEventFields, sessionEventSchema, sessionLiveEventSchema, wireLifecyclePayloadSchema, wireEventFields, sessionWireEventSchema, sessionWireEnvelopeSchema, sessionEventBatchSchema, sessionLiveEventBatchSchema, sessionExportSchema, mobiusSessionExportSchema, sessionEventEnvelopeSchema, sessionEventLogPageSchema, sessionEventOmissionSchema, nativeEventPageRequestSchema, queuedPromptRequestEventLogSchema, nativeSessionEventsSchema, knownSessionLiveEventBatchSchema, decodeSessionEvent, decodeKnownSessionEventPayload, decodeSessionEventEnvelope, encodeSessionEventEnvelope, decodeAcpSessionUpdate, decodeKnownNativeSessionEvents;
26967
+ var MAX_EVENT_COUNT, MAX_COLLECTION_SIZE2, MAX_CONTENT_LENGTH2, SESSION_EVENT_KIND, SESSION_EVENT_BATCH_MAX_SIZE, boundedString2, shortString, externalContentKeySchema, annotationsSchema, contentFields, textContentSchema, imageContentSchema, audioContentSchema, externalImageContentSchema, externalAudioContentSchema, externalResourceContentSchema, resourceLinkSchema, textResourceSchema, blobResourceSchema, embeddedResourceSchema, contentBlockSchema, toolCallContentSchema, toolKindSchema, toolStatusSchema, backgroundTaskSchema, toolPatchFields, planEntrySchema, planContentSchema, commandSchema, configSelectOptionSchema, configSelectGroupSchema, configBaseFields, sessionConfigOptionSchema2, contentChunkFields, acpSessionUpdateSchema, lifecycleBase, promptExecutionContextSchema, lifecycleMetadataSchema, sessionEventPayloadSchema, positionSchema, sharedSessionEventFields, sessionLiveEventFields, sessionEventSchema, sessionLiveEventSchema, wireLifecyclePayloadSchema, wireEventFields, sessionWireEventSchema, sessionWireEnvelopeSchema, sessionEventBatchSchema, sessionLiveEventBatchSchema, sessionEventEnvelopeSchema, sessionEventLogPageSchema, nativeEventPageRequestSchema, queuedPromptRequestEventLogSchema, nativeSessionEventsSchema, knownSessionLiveEventBatchSchema, decodeSessionEvent, decodeKnownSessionEventPayload, decodeSessionEventEnvelope, encodeSessionEventEnvelope, decodeAcpSessionUpdate, decodeKnownNativeSessionEvents;
26968
26968
  var init_events = __esm({
26969
26969
  "../mobius-sdk/src/protocol/session/events/index.ts"() {
26970
26970
  "use strict";
@@ -27308,38 +27308,6 @@ var init_events = __esm({
27308
27308
  }).passthrough().readonly();
27309
27309
  sessionEventBatchSchema = external_exports.array(sessionEventSchema).min(1).max(SESSION_EVENT_BATCH_MAX_SIZE).readonly();
27310
27310
  sessionLiveEventBatchSchema = external_exports.array(sessionLiveEventSchema).min(1).max(SESSION_EVENT_BATCH_MAX_SIZE).readonly();
27311
- sessionExportSchema = external_exports.object({
27312
- binding: external_exports.object({
27313
- bindingId: identifierStringSchema,
27314
- runtimeId: identifierStringSchema
27315
- }).readonly(),
27316
- events: external_exports.array(sessionEventSchema).max(MAX_EVENT_COUNT).readonly(),
27317
- sessionId: identifierStringSchema,
27318
- truncated: external_exports.boolean()
27319
- }).readonly().superRefine((session, context) => {
27320
- const eventIds = /* @__PURE__ */ new Set();
27321
- for (const [index2, event] of session.events.entries()) {
27322
- if (event.sessionId !== session.sessionId) {
27323
- context.addIssue({
27324
- code: "custom",
27325
- message: "Exported event belongs to a different Session",
27326
- path: ["events", index2, "sessionId"]
27327
- });
27328
- }
27329
- if (eventIds.has(event.eventId)) {
27330
- context.addIssue({
27331
- code: "custom",
27332
- message: "Exported event identities are not unique",
27333
- path: ["events", index2, "eventId"]
27334
- });
27335
- }
27336
- eventIds.add(event.eventId);
27337
- }
27338
- });
27339
- mobiusSessionExportSchema = external_exports.object({
27340
- formatVersion: external_exports.literal("2"),
27341
- session: sessionExportSchema
27342
- }).readonly();
27343
27311
  sessionEventEnvelopeSchema = external_exports.object({ events: sessionLiveEventBatchSchema, kind: external_exports.literal(SESSION_EVENT_KIND) }).readonly();
27344
27312
  sessionEventLogPageSchema = external_exports.object({
27345
27313
  events: external_exports.array(sessionEventSchema).max(MAX_EVENT_COUNT).readonly(),
@@ -27352,12 +27320,9 @@ var init_events = __esm({
27352
27320
  truncated: external_exports.boolean(),
27353
27321
  version: external_exports.literal(2)
27354
27322
  }).readonly();
27355
- sessionEventOmissionSchema = external_exports.literal("agent-reasoning");
27356
27323
  nativeEventPageRequestSchema = external_exports.object({
27357
27324
  cursor: external_exports.string().min(1).max(512).nullable(),
27358
- eventLimit: external_exports.number().int().min(1).max(1e4),
27359
- // Legacy callers may still send this option; readers must ignore it.
27360
- omit: external_exports.array(sessionEventOmissionSchema).max(1).readonly().optional()
27325
+ eventLimit: external_exports.number().int().min(1).max(1e4)
27361
27326
  }).readonly();
27362
27327
  queuedPromptRequestEventLogSchema = external_exports.object({
27363
27328
  commandId: identifierStringSchema,
@@ -28066,8 +28031,6 @@ var init_history = __esm({
28066
28031
  pageRequestFields = {
28067
28032
  cursor: external_exports.string().min(1).max(512).nullable(),
28068
28033
  eventLimit: external_exports.number().int().min(1).max(1e4),
28069
- // Decode old clients without rejecting their request; omission has no effect.
28070
- omit: external_exports.array(sessionEventOmissionSchema).max(1).readonly().optional(),
28071
28034
  requestId: identifierStringSchema,
28072
28035
  sessionId: identifierStringSchema
28073
28036
  };
@@ -65844,7 +65807,6 @@ var init_background_task_notifications = __esm({
65844
65807
  });
65845
65808
 
65846
65809
  // src/engine/acp/harness/claude/upstream/dist/context-resources.js
65847
- import { extname } from "node:path";
65848
65810
  function formatUriAsLink(uri) {
65849
65811
  if (uri.startsWith("file://")) {
65850
65812
  const path8 = uri.slice(7);
@@ -65855,91 +65817,6 @@ function formatUriAsLink(uri) {
65855
65817
  }
65856
65818
  return uri;
65857
65819
  }
65858
- function parseContextBlock(block) {
65859
- if (block.type !== "text" || typeof block.text !== "string") {
65860
- return null;
65861
- }
65862
- const match = /^\n<context ref="([^"\r\n]+)">\n([\s\S]*)\n<\/context>$/u.exec(block.text);
65863
- const uri = match?.[1];
65864
- const text2 = match?.[2];
65865
- if (uri === void 0 || text2 === void 0 || formatContextBlock(uri, text2) !== block.text) {
65866
- return null;
65867
- }
65868
- return { uri, text: text2 };
65869
- }
65870
- function contextMimeType(uri) {
65871
- let pathname = uri;
65872
- try {
65873
- pathname = new URL(uri).pathname;
65874
- } catch {
65875
- }
65876
- switch (extname(pathname).toLowerCase()) {
65877
- case ".html":
65878
- case ".htm":
65879
- return "text/html";
65880
- case ".js":
65881
- case ".mjs":
65882
- case ".cjs":
65883
- return "text/javascript";
65884
- case ".css":
65885
- return "text/css";
65886
- case ".json":
65887
- return "application/json";
65888
- case ".md":
65889
- case ".markdown":
65890
- return "text/markdown";
65891
- case ".xml":
65892
- return "application/xml";
65893
- case ".svg":
65894
- return "image/svg+xml";
65895
- case ".csv":
65896
- return "text/csv";
65897
- default:
65898
- return "text/plain";
65899
- }
65900
- }
65901
- function replayContextResources(content) {
65902
- const contexts = [];
65903
- let contextStart = content.length;
65904
- for (let index2 = content.length - 1; index2 >= 0; index2 -= 1) {
65905
- const block = content[index2];
65906
- const parsed = block === void 0 ? null : parseContextBlock(block);
65907
- if (parsed === null) {
65908
- break;
65909
- }
65910
- contexts.push(parsed);
65911
- contextStart = index2;
65912
- }
65913
- if (contexts.length === 0) {
65914
- return null;
65915
- }
65916
- contexts.reverse();
65917
- const links = new Set(contexts.map(({ uri }) => formatUriAsLink(uri)));
65918
- const resources = /* @__PURE__ */ new Map();
65919
- let nextContext = 0;
65920
- for (let index2 = 0; index2 < contextStart; index2 += 1) {
65921
- const block = content[index2];
65922
- if (block?.type !== "text" || typeof block.text !== "string") {
65923
- continue;
65924
- }
65925
- if (block.text.startsWith('\n<context ref="')) {
65926
- return null;
65927
- }
65928
- if (!links.has(block.text)) {
65929
- continue;
65930
- }
65931
- const context = contexts[nextContext];
65932
- if (context === void 0 || block.text !== formatUriAsLink(context.uri)) {
65933
- return null;
65934
- }
65935
- resources.set(index2, {
65936
- type: "resource",
65937
- resource: { ...context, mimeType: contextMimeType(context.uri) }
65938
- });
65939
- nextContext += 1;
65940
- }
65941
- return nextContext === contexts.length ? { contextStart, resources } : null;
65942
- }
65943
65820
  var formatContextBlock;
65944
65821
  var init_context_resources = __esm({
65945
65822
  "src/engine/acp/harness/claude/upstream/dist/context-resources.js"() {
@@ -70302,13 +70179,8 @@ function toAcpNotifications(content, role, sessionId, toolUseCache, client2, log
70302
70179
  const toolUseResult = options?.toolUseResult !== void 0 && content.filter((c) => typeof c === "object" && c !== null && c.type === "tool_result").length === 1 ? options.toolUseResult : void 0;
70303
70180
  const toolResultMeta = parseToolResultMeta(options?.toolResultMeta);
70304
70181
  const output2 = [];
70305
- const replayedResources = role === "user" && options.historical === true ? replayContextResources(content) : null;
70306
- for (const [index2, chunk] of content.entries()) {
70307
- if (replayedResources !== null && index2 >= replayedResources.contextStart) {
70308
- break;
70309
- }
70182
+ for (const chunk of content) {
70310
70183
  let update = null;
70311
- const resource = replayedResources?.resources.get(index2);
70312
70184
  switch (chunk.type) {
70313
70185
  case "text":
70314
70186
  case "text_delta": {
@@ -70317,7 +70189,7 @@ function toAcpNotifications(content, role, sessionId, toolUseCache, client2, log
70317
70189
  update = {
70318
70190
  sessionUpdate: role === "assistant" ? "agent_message_chunk" : "user_message_chunk",
70319
70191
  messageId,
70320
- content: resource ?? {
70192
+ content: {
70321
70193
  type: "text",
70322
70194
  text: chunk.text
70323
70195
  }
@@ -74294,9 +74166,11 @@ var init_process_error = __esm({
74294
74166
  "use strict";
74295
74167
  ProcessExecutionError = class extends Error {
74296
74168
  code;
74169
+ diagnosticDetails;
74297
74170
  constructor(code, message, options = {}) {
74298
74171
  super(message, options);
74299
74172
  this.code = code;
74173
+ this.diagnosticDetails = options.diagnosticDetails ?? {};
74300
74174
  this.name = "ProcessExecutionError";
74301
74175
  }
74302
74176
  };
@@ -74306,7 +74180,7 @@ var init_process_error = __esm({
74306
74180
  // src/engine/util/process/platform/windows.ts
74307
74181
  import { execFile as execFile4 } from "node:child_process";
74308
74182
  import { readFile as readFile6, realpath as realpath6 } from "node:fs/promises";
74309
- import { dirname as dirname7, extname as extname2, join as join16, resolve as resolve9 } from "node:path";
74183
+ import { dirname as dirname7, extname, join as join16, resolve as resolve9 } from "node:path";
74310
74184
  function environmentValue2(environment, name2) {
74311
74185
  return Object.entries(environment).find(([key]) => key.toUpperCase() === name2.toUpperCase())?.[1];
74312
74186
  }
@@ -74321,14 +74195,14 @@ function executableExtensions(executableName, environment) {
74321
74195
  async function resolveExecutableTarget(path8) {
74322
74196
  let resolvedPath;
74323
74197
  try {
74324
- resolvedPath = await realpath6(extname2(path8) === "" ? `${path8}.cmd` : path8);
74198
+ resolvedPath = await realpath6(extname(path8) === "" ? `${path8}.cmd` : path8);
74325
74199
  } catch (cause) {
74326
- if (extname2(path8) !== "" || !(cause instanceof Error) || !("code" in cause) || cause.code !== "ENOENT") {
74200
+ if (extname(path8) !== "" || !(cause instanceof Error) || !("code" in cause) || cause.code !== "ENOENT") {
74327
74201
  throw cause;
74328
74202
  }
74329
74203
  resolvedPath = await realpath6(path8);
74330
74204
  }
74331
- if (extname2(resolvedPath).toLowerCase() === ".cmd") {
74205
+ if (extname(resolvedPath).toLowerCase() === ".cmd") {
74332
74206
  const shim = await readFile6(resolvedPath, "utf8");
74333
74207
  if (shim.includes('SET "NPM_CLI_JS=%~dp0\\node_modules\\npm\\bin\\npm-cli.js"') && shim.includes('"%NODE_EXE%" "%NPM_CLI_JS%" %*')) {
74334
74208
  return await realpath6(resolve9(dirname7(resolvedPath), "node_modules/npm/bin/npm-cli.js"));
@@ -74693,11 +74567,16 @@ async function runBoundedProcess(options) {
74693
74567
  abort();
74694
74568
  }
74695
74569
  try {
74696
- const exit = new Promise((resolveExit, rejectExit) => {
74697
- child.once("error", rejectExit);
74698
- child.once("exit", (code) => resolveExit(code ?? 1));
74570
+ const completion = new Promise((resolveCompletion, rejectCompletion) => {
74571
+ child.once("error", rejectCompletion);
74572
+ child.once("exit", (code) => {
74573
+ if (code !== 0) {
74574
+ resolveCompletion(code ?? 1);
74575
+ }
74576
+ });
74577
+ child.once("close", (code) => resolveCompletion(code ?? 1));
74699
74578
  });
74700
- const exitCode = await Promise.race([exit, interrupted.promise.then(() => -1)]);
74579
+ const exitCode = await Promise.race([completion, interrupted.promise.then(() => -1)]);
74701
74580
  if (interruptionCleanupFailure !== null) {
74702
74581
  throw interruptionCleanupFailure;
74703
74582
  }
@@ -74709,12 +74588,19 @@ async function runBoundedProcess(options) {
74709
74588
  }
74710
74589
  return new ProcessResult(Buffer.concat(stdout).toString("utf8"), Buffer.concat(stderr).toString("utf8"));
74711
74590
  } catch (error62) {
74712
- if (error62 instanceof ProcessExecutionError) {
74713
- throw error62;
74714
- }
74715
- throw new ProcessExecutionError("process_spawn_failed", "The executable could not be started", {
74591
+ const failure2 = error62 instanceof ProcessExecutionError ? error62 : new ProcessExecutionError("process_spawn_failed", "The executable could not be started", {
74716
74592
  cause: error62
74717
74593
  });
74594
+ throw new ProcessExecutionError(failure2.code, failure2.message, {
74595
+ cause: error62,
74596
+ diagnosticDetails: {
74597
+ stdoutBytes: stdoutBytes.toString(),
74598
+ stderrBytes: stderrBytes.toString(),
74599
+ outputLimitBytes: outputLimitBytes.toString(),
74600
+ ...child.exitCode === null ? {} : { exitCode: child.exitCode.toString() },
74601
+ ...child.signalCode === null ? {} : { signal: child.signalCode }
74602
+ }
74603
+ });
74718
74604
  } finally {
74719
74605
  clearTimeout(timeout);
74720
74606
  options.signal.removeEventListener("abort", abort);
@@ -82580,7 +82466,14 @@ async function probeVersion(executable, arguments_, environment, defaultWorkspac
82580
82466
  });
82581
82467
  const version2 = normalize4(result.stdout || result.stderr);
82582
82468
  if (version2.length === 0) {
82583
- throw new ProcessExecutionError("process_exit_failed", "The executable did not report a version");
82469
+ throw new ProcessExecutionError("process_exit_failed", "The executable did not report a version", {
82470
+ diagnosticDetails: {
82471
+ probeReason: "empty_version_output",
82472
+ exitCode: "0",
82473
+ stdoutBytes: Buffer.byteLength(result.stdout).toString(),
82474
+ stderrBytes: Buffer.byteLength(result.stderr).toString()
82475
+ }
82476
+ });
82584
82477
  }
82585
82478
  return version2;
82586
82479
  }
@@ -82609,9 +82502,27 @@ function isRetryableProbeFailure(error62) {
82609
82502
  }
82610
82503
  return error62 instanceof AgentProbeError && error62.code === "adapter_probe_timeout";
82611
82504
  }
82612
- async function probeWithRetry(signal, probe) {
82505
+ async function probeWithRetry(context, specification, source, probe) {
82506
+ const signal = context.signal;
82507
+ const run = async (attempt) => {
82508
+ const startedAt = performance.now();
82509
+ try {
82510
+ return await probe();
82511
+ } catch (failure2) {
82512
+ context.onProbeDiagnostic?.({
82513
+ agentId: specification.id,
82514
+ source,
82515
+ event: signal.aborted ? "agent_probe_cancelled" : "agent_probe_failed",
82516
+ attempt,
82517
+ elapsedMilliseconds: Math.round(performance.now() - startedAt),
82518
+ timeoutMilliseconds: source === "acp_readiness" ? specification.acpProbeTimeoutMilliseconds : specification.versionProbeTimeoutMilliseconds,
82519
+ failure: failure2
82520
+ });
82521
+ throw failure2;
82522
+ }
82523
+ };
82613
82524
  try {
82614
- return await probe();
82525
+ return await run(1);
82615
82526
  } catch (error62) {
82616
82527
  if (signal.aborted) {
82617
82528
  signal.throwIfAborted();
@@ -82619,7 +82530,7 @@ async function probeWithRetry(signal, probe) {
82619
82530
  if (!isRetryableProbeFailure(error62)) {
82620
82531
  throw error62;
82621
82532
  }
82622
- return await probe();
82533
+ return await run(2);
82623
82534
  }
82624
82535
  }
82625
82536
  function integrationProbeFailure(specification, error62) {
@@ -82649,7 +82560,9 @@ async function discoverAgent(specification, context) {
82649
82560
  let agentVersion = "";
82650
82561
  try {
82651
82562
  agentVersion = await probeWithRetry(
82652
- context.signal,
82563
+ context,
82564
+ specification,
82565
+ "agent_version",
82653
82566
  async () => await probeVersion(
82654
82567
  agent,
82655
82568
  specification.agentVersionArguments,
@@ -82697,7 +82610,9 @@ async function discoverAgent(specification, context) {
82697
82610
  launchEnvironment = await specification.createLaunchEnvironment(agent, context);
82698
82611
  if (specification.adapterVersionArguments.length > 0) {
82699
82612
  adapterVersion = await probeWithRetry(
82700
- context.signal,
82613
+ context,
82614
+ specification,
82615
+ "adapter_version",
82701
82616
  async () => await probeVersion(
82702
82617
  adapter,
82703
82618
  specification.adapterVersionArguments,
@@ -82732,7 +82647,9 @@ async function discoverAgent(specification, context) {
82732
82647
  );
82733
82648
  try {
82734
82649
  const readiness = await probeWithRetry(
82735
- context.signal,
82650
+ context,
82651
+ specification,
82652
+ "acp_readiness",
82736
82653
  async () => await probeAcpReadiness(
82737
82654
  specification,
82738
82655
  buildDefinition(adapterVersion, unsupportedSessionCapabilities()),
@@ -91272,6 +91189,294 @@ var init_environment_proxy = __esm({
91272
91189
  }
91273
91190
  });
91274
91191
 
91192
+ // src/engine/storage/logs/bounded-log.ts
91193
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync9, renameSync as renameSync2, statSync as statSync5, writeFileSync as writeFileSync2 } from "node:fs";
91194
+ import { join as join26 } from "node:path";
91195
+ var BoundedLineLog;
91196
+ var init_bounded_log = __esm({
91197
+ "src/engine/storage/logs/bounded-log.ts"() {
91198
+ "use strict";
91199
+ BoundedLineLog = class {
91200
+ #path;
91201
+ #maximumBytes;
91202
+ #directory;
91203
+ #reportedFailure = false;
91204
+ #onWriteFailure;
91205
+ constructor(directory, filename, maximumBytes, onWriteFailure = () => void 0) {
91206
+ this.#directory = directory;
91207
+ this.#path = join26(directory, filename);
91208
+ this.#maximumBytes = maximumBytes;
91209
+ this.#onWriteFailure = onWriteFailure;
91210
+ }
91211
+ record = (line) => {
91212
+ try {
91213
+ mkdirSync4(this.#directory, { mode: 448, recursive: true });
91214
+ this.#append(line);
91215
+ } catch (cause) {
91216
+ if (!this.#reportedFailure) {
91217
+ this.#reportedFailure = true;
91218
+ this.#onWriteFailure(cause);
91219
+ }
91220
+ }
91221
+ };
91222
+ #append = (line) => {
91223
+ const encoded = `${line.replace(/[\r\n]+/gu, " ").trim()}
91224
+ `;
91225
+ const encodedBytes = Buffer.byteLength(encoded);
91226
+ let existingBytes = 0;
91227
+ try {
91228
+ existingBytes = statSync5(this.#path).size;
91229
+ } catch (cause) {
91230
+ if (!(cause instanceof Error && Reflect.get(cause, "code") === "ENOENT")) {
91231
+ throw cause;
91232
+ }
91233
+ }
91234
+ if (existingBytes + encodedBytes <= this.#maximumBytes) {
91235
+ appendFileSync2(this.#path, encoded, { encoding: "utf8", mode: 384 });
91236
+ return;
91237
+ }
91238
+ const lines = `${existingBytes === 0 ? "" : readFileSync9(this.#path, "utf8")}${encoded}`.split("\n").filter((candidate) => candidate.length > 0);
91239
+ let totalBytes = lines.reduce((total, candidate) => total + Buffer.byteLength(candidate) + 1, 0);
91240
+ while (totalBytes > this.#maximumBytes && lines.length > 0) {
91241
+ const oldest = lines.shift();
91242
+ if (oldest !== void 0) {
91243
+ totalBytes -= Buffer.byteLength(oldest) + 1;
91244
+ }
91245
+ }
91246
+ const temporaryPath = `${this.#path}.tmp`;
91247
+ writeFileSync2(temporaryPath, lines.length === 0 ? "" : `${lines.join("\n")}
91248
+ `, {
91249
+ encoding: "utf8",
91250
+ mode: 384
91251
+ });
91252
+ renameSync2(temporaryPath, this.#path);
91253
+ };
91254
+ };
91255
+ }
91256
+ });
91257
+
91258
+ // src/engine/storage/logs/log-files.ts
91259
+ import { readFileSync as readFileSync10 } from "node:fs";
91260
+ import { join as join27 } from "node:path";
91261
+ function unhandledRejectionLogFilename(role) {
91262
+ return `unhandled-rejections-${role}.log`;
91263
+ }
91264
+ function logDirectory(dataDirectory) {
91265
+ return join27(dataDirectory, "logs");
91266
+ }
91267
+ function processLogPaths(dataDirectory) {
91268
+ return [
91269
+ WORKER_LIFECYCLE_LOG_FILENAME,
91270
+ unhandledRejectionLogFilename("manager"),
91271
+ unhandledRejectionLogFilename("worker")
91272
+ ].map((filename) => join27(logDirectory(dataDirectory), filename));
91273
+ }
91274
+ function readLogText(path8) {
91275
+ try {
91276
+ return readFileSync10(path8, "utf8");
91277
+ } catch {
91278
+ return null;
91279
+ }
91280
+ }
91281
+ var DAEMON_LOG_FILENAME, WORKER_LIFECYCLE_LOG_FILENAME;
91282
+ var init_log_files = __esm({
91283
+ "src/engine/storage/logs/log-files.ts"() {
91284
+ "use strict";
91285
+ DAEMON_LOG_FILENAME = "daemon.log";
91286
+ WORKER_LIFECYCLE_LOG_FILENAME = "worker-lifecycle.log";
91287
+ }
91288
+ });
91289
+
91290
+ // src/engine/runtime/observability/diagnostic-log.ts
91291
+ import { join as join28 } from "node:path";
91292
+ function exportedFields(value) {
91293
+ const entry = {};
91294
+ for (const field of REMOTE_DIAGNOSTIC_FIELDS) {
91295
+ const item = Reflect.get(value, field);
91296
+ if (typeof item === "string" && FIELD_VALUE_PATTERN.test(item)) {
91297
+ entry[field] = item;
91298
+ } else if (typeof item === "number" && Number.isFinite(item)) {
91299
+ entry[field] = String(item);
91300
+ }
91301
+ }
91302
+ return entry;
91303
+ }
91304
+ function compareTimestamp(left, right) {
91305
+ const leftAt = left["timestamp"] ?? "";
91306
+ const rightAt = right["timestamp"] ?? "";
91307
+ return leftAt < rightAt ? -1 : leftAt > rightAt ? 1 : 0;
91308
+ }
91309
+ var MAXIMUM_RUNTIME_LOG_BYTES, MAXIMUM_ENTRIES, MAXIMUM_REPORT_BYTES, REMOTE_DIAGNOSTIC_FIELDS, FIELD_VALUE_PATTERN, RuntimeDiagnosticLog;
91310
+ var init_diagnostic_log = __esm({
91311
+ "src/engine/runtime/observability/diagnostic-log.ts"() {
91312
+ "use strict";
91313
+ init_bounded_log();
91314
+ init_log_files();
91315
+ MAXIMUM_RUNTIME_LOG_BYTES = 1 * 1024 * 1024;
91316
+ MAXIMUM_ENTRIES = 200;
91317
+ MAXIMUM_REPORT_BYTES = 6e4;
91318
+ REMOTE_DIAGNOSTIC_FIELDS = [
91319
+ "agentId",
91320
+ "operation",
91321
+ "runtimeId",
91322
+ "closeCode",
91323
+ "timeoutMilliseconds",
91324
+ "attempt",
91325
+ "elapsedMilliseconds",
91326
+ "stdoutBytes",
91327
+ "stderrBytes",
91328
+ "outputLimitBytes",
91329
+ "probeReason",
91330
+ "proxyRoute",
91331
+ "timestamp",
91332
+ "event",
91333
+ "channelId",
91334
+ "requestId",
91335
+ "commandId",
91336
+ "sessionId",
91337
+ "turnId",
91338
+ "connectionEpoch",
91339
+ "code",
91340
+ "source",
91341
+ "kind",
91342
+ "pid",
91343
+ "version",
91344
+ "exitCode",
91345
+ "signal",
91346
+ "failureName",
91347
+ "failureCode",
91348
+ "failureStatusCode",
91349
+ "cause1Name",
91350
+ "cause1Code",
91351
+ "cause2Name",
91352
+ "cause2Code"
91353
+ ];
91354
+ FIELD_VALUE_PATTERN = /^[a-zA-Z0-9_.: -]{1,256}$/u;
91355
+ RuntimeDiagnosticLog = class {
91356
+ #log;
91357
+ #maximumBytes;
91358
+ #sources;
91359
+ constructor(stateDirectory, options = {}) {
91360
+ const maximumBytes = options.maximumBytes ?? MAXIMUM_RUNTIME_LOG_BYTES;
91361
+ const directory = logDirectory(stateDirectory);
91362
+ this.#log = new BoundedLineLog(directory, DAEMON_LOG_FILENAME, maximumBytes);
91363
+ this.#maximumBytes = maximumBytes;
91364
+ const processLogsDirectory = options.processLogsDirectory;
91365
+ this.#sources = [
91366
+ { maximumBytes, path: join28(directory, DAEMON_LOG_FILENAME) },
91367
+ // The process logs a Runtime does not own, but must read to explain its own deaths.
91368
+ ...processLogsDirectory === void 0 ? [] : processLogPaths(processLogsDirectory).map((path8) => ({ maximumBytes: null, path: path8 }))
91369
+ ];
91370
+ }
91371
+ // Export only correlation and failure metadata. Local messages and paths stay local.
91372
+ snapshot = () => {
91373
+ const merged = [];
91374
+ let truncated = false;
91375
+ for (const source of this.#sources) {
91376
+ const collected = this.#read(source);
91377
+ merged.push(...collected.entries);
91378
+ truncated ||= collected.truncated;
91379
+ }
91380
+ merged.sort(compareTimestamp);
91381
+ const entries = merged.slice(-MAXIMUM_ENTRIES);
91382
+ truncated ||= entries.length < merged.length;
91383
+ while (JSON.stringify(entries).length > MAXIMUM_REPORT_BYTES && entries.length > 0) {
91384
+ entries.shift();
91385
+ truncated = true;
91386
+ }
91387
+ return { entries, truncated };
91388
+ };
91389
+ record = (diagnostic) => {
91390
+ this.#log.record(diagnostic);
91391
+ };
91392
+ #read = (source) => {
91393
+ const content = readLogText(source.path);
91394
+ if (content === null) {
91395
+ return { entries: [], truncated: false };
91396
+ }
91397
+ const lines = content.split("\n").filter((line) => line.length > 0);
91398
+ const entries = [];
91399
+ for (const line of lines.slice(-MAXIMUM_ENTRIES)) {
91400
+ const start = line.indexOf("{");
91401
+ if (start < 0) {
91402
+ continue;
91403
+ }
91404
+ let value;
91405
+ try {
91406
+ value = JSON.parse(line.slice(start));
91407
+ } catch {
91408
+ continue;
91409
+ }
91410
+ if (typeof value !== "object" || value === null) {
91411
+ continue;
91412
+ }
91413
+ entries.push(exportedFields(value));
91414
+ }
91415
+ const nearRotation = source.maximumBytes !== null && Buffer.byteLength(content) >= source.maximumBytes - 4096;
91416
+ return { entries, truncated: lines.length > MAXIMUM_ENTRIES || nearRotation };
91417
+ };
91418
+ };
91419
+ }
91420
+ });
91421
+
91422
+ // src/engine/runtime/catalog/discover-agent-catalog.ts
91423
+ function failureDetails(failure2) {
91424
+ const fields = {};
91425
+ let current = failure2;
91426
+ for (let depth = 0; depth < 3 && current instanceof Error; depth += 1) {
91427
+ const prefix = depth === 0 ? "failure" : `cause${depth.toString()}`;
91428
+ if (current instanceof ProcessExecutionError || current instanceof AgentProbeError) {
91429
+ fields[`${prefix}Name`] = current instanceof ProcessExecutionError ? "ProcessExecutionError" : "AgentProbeError";
91430
+ fields[`${prefix}Code`] = current.code;
91431
+ } else {
91432
+ fields[`${prefix}Name`] = "Error";
91433
+ }
91434
+ if (depth === 0 && current instanceof ProcessExecutionError) {
91435
+ Object.assign(fields, current.diagnosticDetails);
91436
+ }
91437
+ current = current.cause;
91438
+ }
91439
+ return fields;
91440
+ }
91441
+ async function discoverRuntimeAgentInventory(options, channelId) {
91442
+ const log = new RuntimeDiagnosticLog(options.dataDirectory);
91443
+ const record2 = (details) => {
91444
+ log.record(
91445
+ `Mobius agent discovery diagnostic ${JSON.stringify({
91446
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
91447
+ channelId,
91448
+ ...details
91449
+ })}`
91450
+ );
91451
+ };
91452
+ const inventory = await discoverLocalAgentInventory({
91453
+ ...options,
91454
+ onProbeDiagnostic: ({ failure: failure2, ...diagnostic }) => {
91455
+ record2({ ...diagnostic, ...failureDetails(failure2) });
91456
+ }
91457
+ });
91458
+ for (const { discovery, detectionMilliseconds } of inventory.results) {
91459
+ record2({
91460
+ event: "agent_discovery_result",
91461
+ agentId: discovery.specification.id,
91462
+ code: discovery instanceof UnavailableAgent ? discovery.code : "ready",
91463
+ source: discovery.status,
91464
+ elapsedMilliseconds: detectionMilliseconds
91465
+ });
91466
+ }
91467
+ return inventory;
91468
+ }
91469
+ var init_discover_agent_catalog = __esm({
91470
+ "src/engine/runtime/catalog/discover-agent-catalog.ts"() {
91471
+ "use strict";
91472
+ init_agent_discovery();
91473
+ init_agent_probe_error();
91474
+ init_discover_local_agents();
91475
+ init_process_error();
91476
+ init_diagnostic_log();
91477
+ }
91478
+ });
91479
+
91275
91480
  // src/engine/runtime/relay/relay-authentication.ts
91276
91481
  function runtimeCredential(relayUrl) {
91277
91482
  return relayUrl.searchParams.get("token") ?? "";
@@ -91746,21 +91951,27 @@ function buildSavedRuntimeConfig(connection, defaultWorkspace, inventory, localC
91746
91951
  localContext,
91747
91952
  new OpaqueRuntimeReconnectTarget(connection.connectionId),
91748
91953
  createCatalogAgentResolver(
91749
- (refreshSignal) => discoverLocalAgentInventory({
91954
+ (refreshSignal) => discoverRuntimeAgentInventory(
91955
+ {
91956
+ defaultWorkspace,
91957
+ dataDirectory: localContext.stateDirectory,
91958
+ environment: localContext.agentLaunchEnvironment,
91959
+ signal: refreshSignal
91960
+ },
91961
+ connection.channelId
91962
+ ),
91963
+ () => config2,
91964
+ publishAgentCatalog
91965
+ ),
91966
+ (refreshSignal) => discoverRuntimeAgentInventory(
91967
+ {
91750
91968
  defaultWorkspace,
91751
91969
  dataDirectory: localContext.stateDirectory,
91752
91970
  environment: localContext.agentLaunchEnvironment,
91753
91971
  signal: refreshSignal
91754
- }),
91755
- () => config2,
91756
- publishAgentCatalog
91757
- ),
91758
- (refreshSignal) => discoverLocalAgentInventory({
91759
- defaultWorkspace,
91760
- dataDirectory: localContext.stateDirectory,
91761
- environment: localContext.agentLaunchEnvironment,
91762
- signal: refreshSignal
91763
- }).then((inventory2) => inventory2.readyAgents())
91972
+ },
91973
+ connection.channelId
91974
+ ).then((inventory2) => inventory2.readyAgents())
91764
91975
  );
91765
91976
  return config2;
91766
91977
  }
@@ -91804,12 +92015,15 @@ async function pairRuntimeConnection(installation, options, signal, environment)
91804
92015
  async function prepareRuntimeConnection(installation, connection, signal, environment, maxAcpProcesses) {
91805
92016
  const localContext = new RuntimeLocalContext(installation.stateDirectory, environment, maxAcpProcesses);
91806
92017
  const defaultWorkspace = await resolveDefaultWorkspace(connection.defaultWorkspace);
91807
- const inventory = await discoverLocalAgentInventory({
91808
- defaultWorkspace,
91809
- dataDirectory: localContext.stateDirectory,
91810
- environment: localContext.agentLaunchEnvironment,
91811
- signal
91812
- });
92018
+ const inventory = await discoverRuntimeAgentInventory(
92019
+ {
92020
+ defaultWorkspace,
92021
+ dataDirectory: localContext.stateDirectory,
92022
+ environment: localContext.agentLaunchEnvironment,
92023
+ signal
92024
+ },
92025
+ connection.channelId
92026
+ );
91813
92027
  return buildSavedRuntimeConfig(connection, defaultWorkspace, inventory, localContext);
91814
92028
  }
91815
92029
  var PAIRING_TIMEOUT_MILLISECONDS, PAIRING_CODE_PATTERN, TOKEN_PATTERN, CLAIM_RESPONSE_KEYS, REDEEM_RESPONSE_KEYS, PairingClientError;
@@ -91822,6 +92036,7 @@ var init_pairing = __esm({
91822
92036
  init_local_files();
91823
92037
  init_environment_proxy();
91824
92038
  init_value_utils();
92039
+ init_discover_agent_catalog();
91825
92040
  init_publish_agent_catalog();
91826
92041
  init_resolve_catalog_agent();
91827
92042
  init_config();
@@ -96282,7 +96497,7 @@ var init_session_turns = __esm({
96282
96497
 
96283
96498
  // src/engine/session/workspace/workspace-directory.ts
96284
96499
  import { homedir as homedir4 } from "node:os";
96285
- import { basename as basename8, dirname as dirname11, isAbsolute as isAbsolute15, join as join26, normalize as normalize2, relative as relative2 } from "node:path";
96500
+ import { basename as basename8, dirname as dirname11, isAbsolute as isAbsolute15, join as join29, normalize as normalize2, relative as relative2 } from "node:path";
96286
96501
  function encodePath(path8) {
96287
96502
  const encoded = Buffer.from(path8, "utf8").toString("base64url");
96288
96503
  if (path8.length === 0 || path8.length > MAX_WORKSPACE_PATH_LENGTH || encoded.length + "path-".length > MAX_DIRECTORY_IDENTIFIER_LENGTH) {
@@ -96412,7 +96627,7 @@ var init_workspace_directory = __esm({
96412
96627
  continue;
96413
96628
  }
96414
96629
  try {
96415
- const path8 = await this.resolvePath(join26(target, child.name), signal);
96630
+ const path8 = await this.resolvePath(join29(target, child.name), signal);
96416
96631
  entries.push({ directoryId: encodePath(path8), name: child.name });
96417
96632
  } catch (cause) {
96418
96633
  signal.throwIfAborted();
@@ -96592,7 +96807,7 @@ var init_session_layer = __esm({
96592
96807
  // src/engine/storage/files/scratch-directory.ts
96593
96808
  import { randomUUID as randomUUID17 } from "node:crypto";
96594
96809
  import { lstat as lstat4, mkdir as mkdir5, readdir as readdir6, readFile as readFile7, realpath as realpath8, rename as rename4, rm as rm3, stat as stat8, utimes, writeFile as writeFile2 } from "node:fs/promises";
96595
- import { dirname as dirname12, join as join27 } from "node:path";
96810
+ import { dirname as dirname12, join as join30 } from "node:path";
96596
96811
  async function atomicWrite(path8, bytes, signal) {
96597
96812
  const temporary = `${path8}.${randomUUID17()}.tmp`;
96598
96813
  try {
@@ -96610,7 +96825,7 @@ var init_scratch_directory = __esm({
96610
96825
  ScratchDirectory = class {
96611
96826
  #root;
96612
96827
  constructor(parent) {
96613
- this.#root = join27(parent, randomUUID17());
96828
+ this.#root = join30(parent, randomUUID17());
96614
96829
  }
96615
96830
  /** Refreshes this directory's lease and removes sibling directories whose lease is older than `leaseMilliseconds`. */
96616
96831
  refreshLease = async (leaseMilliseconds) => {
@@ -96621,7 +96836,7 @@ var init_scratch_directory = __esm({
96621
96836
  if (!directory.isDirectory() || !/^[a-f0-9-]{36}$/u.test(directory.name)) {
96622
96837
  continue;
96623
96838
  }
96624
- const path8 = join27(dirname12(this.#root), directory.name);
96839
+ const path8 = join30(dirname12(this.#root), directory.name);
96625
96840
  if (path8 === this.#root) {
96626
96841
  continue;
96627
96842
  }
@@ -96636,10 +96851,10 @@ var init_scratch_directory = __esm({
96636
96851
  };
96637
96852
  /** Writes `bytes` atomically to `<group>/<name>` with owner-only permissions and returns the path. */
96638
96853
  write = async (group, name2, bytes, signal) => {
96639
- const directory = join27(this.#root, group);
96854
+ const directory = join30(this.#root, group);
96640
96855
  await mkdir5(directory, { mode: 448, recursive: true });
96641
96856
  signal.throwIfAborted();
96642
- const path8 = join27(directory, name2);
96857
+ const path8 = join30(directory, name2);
96643
96858
  await atomicWrite(path8, bytes, signal);
96644
96859
  return path8;
96645
96860
  };
@@ -96674,9 +96889,9 @@ var init_scratch_directory = __esm({
96674
96889
 
96675
96890
  // src/engine/session/content/external-content-store.ts
96676
96891
  import { createHash as createHash8 } from "node:crypto";
96677
- import { extname as extname3, join as join28 } from "node:path";
96892
+ import { extname as extname2, join as join31 } from "node:path";
96678
96893
  function contentFileName(key, name2) {
96679
- const extension = extname3(name2).toLowerCase();
96894
+ const extension = extname2(name2).toLowerCase();
96680
96895
  return /^\.[a-z0-9]{1,16}$/u.test(extension) ? `${key}${extension}` : key;
96681
96896
  }
96682
96897
  var contentRequest, CONTENT_LIFETIME_MILLISECONDS, metadataSchema, LocalExternalContentStore;
@@ -96700,7 +96915,7 @@ var init_external_content_store = __esm({
96700
96915
  #expirationTimer;
96701
96916
  #cleanup = Promise.resolve();
96702
96917
  constructor(stateDirectory) {
96703
- this.#scratch = new ScratchDirectory(join28(stateDirectory, "tmp", "session-content"));
96918
+ this.#scratch = new ScratchDirectory(join31(stateDirectory, "tmp", "session-content"));
96704
96919
  this.#expirationTimer = setInterval(() => {
96705
96920
  void this.#expire().catch(() => void 0);
96706
96921
  }, 6e4);
@@ -97096,230 +97311,6 @@ var init_agent_process_pool = __esm({
97096
97311
  }
97097
97312
  });
97098
97313
 
97099
- // src/engine/storage/logs/bounded-log.ts
97100
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync9, renameSync as renameSync2, statSync as statSync5, writeFileSync as writeFileSync2 } from "node:fs";
97101
- import { join as join29 } from "node:path";
97102
- var BoundedLineLog;
97103
- var init_bounded_log = __esm({
97104
- "src/engine/storage/logs/bounded-log.ts"() {
97105
- "use strict";
97106
- BoundedLineLog = class {
97107
- #path;
97108
- #maximumBytes;
97109
- #directory;
97110
- #reportedFailure = false;
97111
- #onWriteFailure;
97112
- constructor(directory, filename, maximumBytes, onWriteFailure = () => void 0) {
97113
- this.#directory = directory;
97114
- this.#path = join29(directory, filename);
97115
- this.#maximumBytes = maximumBytes;
97116
- this.#onWriteFailure = onWriteFailure;
97117
- }
97118
- record = (line) => {
97119
- try {
97120
- mkdirSync4(this.#directory, { mode: 448, recursive: true });
97121
- this.#append(line);
97122
- } catch (cause) {
97123
- if (!this.#reportedFailure) {
97124
- this.#reportedFailure = true;
97125
- this.#onWriteFailure(cause);
97126
- }
97127
- }
97128
- };
97129
- #append = (line) => {
97130
- const encoded = `${line.replace(/[\r\n]+/gu, " ").trim()}
97131
- `;
97132
- const encodedBytes = Buffer.byteLength(encoded);
97133
- let existingBytes = 0;
97134
- try {
97135
- existingBytes = statSync5(this.#path).size;
97136
- } catch (cause) {
97137
- if (!(cause instanceof Error && Reflect.get(cause, "code") === "ENOENT")) {
97138
- throw cause;
97139
- }
97140
- }
97141
- if (existingBytes + encodedBytes <= this.#maximumBytes) {
97142
- appendFileSync2(this.#path, encoded, { encoding: "utf8", mode: 384 });
97143
- return;
97144
- }
97145
- const lines = `${existingBytes === 0 ? "" : readFileSync9(this.#path, "utf8")}${encoded}`.split("\n").filter((candidate) => candidate.length > 0);
97146
- let totalBytes = lines.reduce((total, candidate) => total + Buffer.byteLength(candidate) + 1, 0);
97147
- while (totalBytes > this.#maximumBytes && lines.length > 0) {
97148
- const oldest = lines.shift();
97149
- if (oldest !== void 0) {
97150
- totalBytes -= Buffer.byteLength(oldest) + 1;
97151
- }
97152
- }
97153
- const temporaryPath = `${this.#path}.tmp`;
97154
- writeFileSync2(temporaryPath, lines.length === 0 ? "" : `${lines.join("\n")}
97155
- `, {
97156
- encoding: "utf8",
97157
- mode: 384
97158
- });
97159
- renameSync2(temporaryPath, this.#path);
97160
- };
97161
- };
97162
- }
97163
- });
97164
-
97165
- // src/engine/storage/logs/log-files.ts
97166
- import { readFileSync as readFileSync10 } from "node:fs";
97167
- import { join as join30 } from "node:path";
97168
- function unhandledRejectionLogFilename(role) {
97169
- return `unhandled-rejections-${role}.log`;
97170
- }
97171
- function logDirectory(dataDirectory) {
97172
- return join30(dataDirectory, "logs");
97173
- }
97174
- function processLogPaths(dataDirectory) {
97175
- return [
97176
- WORKER_LIFECYCLE_LOG_FILENAME,
97177
- unhandledRejectionLogFilename("manager"),
97178
- unhandledRejectionLogFilename("worker")
97179
- ].map((filename) => join30(logDirectory(dataDirectory), filename));
97180
- }
97181
- function readLogText(path8) {
97182
- try {
97183
- return readFileSync10(path8, "utf8");
97184
- } catch {
97185
- return null;
97186
- }
97187
- }
97188
- var DAEMON_LOG_FILENAME, WORKER_LIFECYCLE_LOG_FILENAME;
97189
- var init_log_files = __esm({
97190
- "src/engine/storage/logs/log-files.ts"() {
97191
- "use strict";
97192
- DAEMON_LOG_FILENAME = "daemon.log";
97193
- WORKER_LIFECYCLE_LOG_FILENAME = "worker-lifecycle.log";
97194
- }
97195
- });
97196
-
97197
- // src/engine/runtime/observability/diagnostic-log.ts
97198
- import { join as join31 } from "node:path";
97199
- function exportedFields(value) {
97200
- const entry = {};
97201
- for (const field of REMOTE_DIAGNOSTIC_FIELDS) {
97202
- const item = Reflect.get(value, field);
97203
- if (typeof item === "string" && FIELD_VALUE_PATTERN.test(item)) {
97204
- entry[field] = item;
97205
- } else if (typeof item === "number" && Number.isFinite(item)) {
97206
- entry[field] = String(item);
97207
- }
97208
- }
97209
- return entry;
97210
- }
97211
- function compareTimestamp(left, right) {
97212
- const leftAt = left["timestamp"] ?? "";
97213
- const rightAt = right["timestamp"] ?? "";
97214
- return leftAt < rightAt ? -1 : leftAt > rightAt ? 1 : 0;
97215
- }
97216
- var MAXIMUM_RUNTIME_LOG_BYTES, MAXIMUM_ENTRIES, MAXIMUM_REPORT_BYTES, REMOTE_DIAGNOSTIC_FIELDS, FIELD_VALUE_PATTERN, RuntimeDiagnosticLog;
97217
- var init_diagnostic_log = __esm({
97218
- "src/engine/runtime/observability/diagnostic-log.ts"() {
97219
- "use strict";
97220
- init_bounded_log();
97221
- init_log_files();
97222
- MAXIMUM_RUNTIME_LOG_BYTES = 1 * 1024 * 1024;
97223
- MAXIMUM_ENTRIES = 200;
97224
- MAXIMUM_REPORT_BYTES = 6e4;
97225
- REMOTE_DIAGNOSTIC_FIELDS = [
97226
- "agentId",
97227
- "operation",
97228
- "runtimeId",
97229
- "closeCode",
97230
- "timeoutMilliseconds",
97231
- "proxyRoute",
97232
- "timestamp",
97233
- "event",
97234
- "channelId",
97235
- "requestId",
97236
- "commandId",
97237
- "sessionId",
97238
- "turnId",
97239
- "connectionEpoch",
97240
- "code",
97241
- "source",
97242
- "kind",
97243
- "pid",
97244
- "version",
97245
- "exitCode",
97246
- "signal",
97247
- "failureName",
97248
- "failureCode",
97249
- "failureStatusCode",
97250
- "cause1Name",
97251
- "cause1Code",
97252
- "cause2Name",
97253
- "cause2Code"
97254
- ];
97255
- FIELD_VALUE_PATTERN = /^[a-zA-Z0-9_.: -]{1,256}$/u;
97256
- RuntimeDiagnosticLog = class {
97257
- #log;
97258
- #maximumBytes;
97259
- #sources;
97260
- constructor(stateDirectory, options = {}) {
97261
- const maximumBytes = options.maximumBytes ?? MAXIMUM_RUNTIME_LOG_BYTES;
97262
- const directory = logDirectory(stateDirectory);
97263
- this.#log = new BoundedLineLog(directory, DAEMON_LOG_FILENAME, maximumBytes);
97264
- this.#maximumBytes = maximumBytes;
97265
- const processLogsDirectory = options.processLogsDirectory;
97266
- this.#sources = [
97267
- { maximumBytes, path: join31(directory, DAEMON_LOG_FILENAME) },
97268
- // The process logs a Runtime does not own, but must read to explain its own deaths.
97269
- ...processLogsDirectory === void 0 ? [] : processLogPaths(processLogsDirectory).map((path8) => ({ maximumBytes: null, path: path8 }))
97270
- ];
97271
- }
97272
- // Export only correlation and failure metadata. Local messages and paths stay local.
97273
- snapshot = () => {
97274
- const merged = [];
97275
- let truncated = false;
97276
- for (const source of this.#sources) {
97277
- const collected = this.#read(source);
97278
- merged.push(...collected.entries);
97279
- truncated ||= collected.truncated;
97280
- }
97281
- merged.sort(compareTimestamp);
97282
- const entries = merged.slice(-MAXIMUM_ENTRIES);
97283
- truncated ||= entries.length < merged.length;
97284
- while (JSON.stringify(entries).length > MAXIMUM_REPORT_BYTES && entries.length > 0) {
97285
- entries.shift();
97286
- truncated = true;
97287
- }
97288
- return { entries, truncated };
97289
- };
97290
- record = (diagnostic) => {
97291
- this.#log.record(diagnostic);
97292
- };
97293
- #read = (source) => {
97294
- const content = readLogText(source.path);
97295
- if (content === null) {
97296
- return { entries: [], truncated: false };
97297
- }
97298
- const lines = content.split("\n").filter((line) => line.length > 0);
97299
- const entries = [];
97300
- for (const line of lines.slice(-MAXIMUM_ENTRIES)) {
97301
- const start = line.indexOf("{");
97302
- if (start < 0) {
97303
- continue;
97304
- }
97305
- let value;
97306
- try {
97307
- value = JSON.parse(line.slice(start));
97308
- } catch {
97309
- continue;
97310
- }
97311
- if (typeof value !== "object" || value === null) {
97312
- continue;
97313
- }
97314
- entries.push(exportedFields(value));
97315
- }
97316
- const nearRotation = source.maximumBytes !== null && Buffer.byteLength(content) >= source.maximumBytes - 4096;
97317
- return { entries, truncated: lines.length > MAXIMUM_ENTRIES || nearRotation };
97318
- };
97319
- };
97320
- }
97321
- });
97322
-
97323
97314
  // src/engine/runtime/relay/diagnostics.ts
97324
97315
  function sanitizeDiagnosticText(value) {
97325
97316
  const printable = Array.from(value, (character) => {
@@ -98334,7 +98325,7 @@ var init_content_write = __esm({
98334
98325
  });
98335
98326
 
98336
98327
  // src/engine/session/content/session-files.ts
98337
- import { basename as basename9, extname as extname4, isAbsolute as isAbsolute16, join as join32, normalize as normalize3, resolve as resolve17 } from "node:path";
98328
+ import { basename as basename9, extname as extname3, isAbsolute as isAbsolute16, join as join32, normalize as normalize3, resolve as resolve17 } from "node:path";
98338
98329
  import { fileURLToPath as fileURLToPath2 } from "node:url";
98339
98330
  function requestedPath(value) {
98340
98331
  if (value.includes("\0")) {
@@ -98390,7 +98381,7 @@ async function streamLocalFile(command, send2, sendChunk, signal, workingDirecto
98390
98381
  send2({
98391
98382
  byteLength: before.size,
98392
98383
  kind: FILE_BEGIN_KIND,
98393
- mediaType: external?.mediaType ?? raster?.mimeType ?? (extname4(target).toLowerCase() === ".svg" ? "image/svg+xml" : "application/octet-stream"),
98384
+ mediaType: external?.mediaType ?? raster?.mimeType ?? (extname3(target).toLowerCase() === ".svg" ? "image/svg+xml" : "application/octet-stream"),
98394
98385
  modifiedAt: before.modifiedAt.toISOString(),
98395
98386
  name: external?.name ?? (basename9(target) || "file"),
98396
98387
  requestId: command.requestId,
@@ -100907,13 +100898,16 @@ async function prepareProvidedRuntime({
100907
100898
  const defaultWorkspace = await resolveWorkspace(connection.defaultWorkspace);
100908
100899
  const specifications = supportedLocalAgentSpecifications();
100909
100900
  const discoveryEnvironment = localContext.agentLaunchEnvironment;
100910
- const discover = async (refreshSignal) => await discoverLocalAgentInventory({
100911
- defaultWorkspace,
100912
- dataDirectory: localContext.stateDirectory,
100913
- environment: discoveryEnvironment,
100914
- signal: refreshSignal,
100915
- specifications
100916
- });
100901
+ const discover = async (refreshSignal) => await discoverRuntimeAgentInventory(
100902
+ {
100903
+ defaultWorkspace,
100904
+ dataDirectory: localContext.stateDirectory,
100905
+ environment: discoveryEnvironment,
100906
+ signal: refreshSignal,
100907
+ specifications
100908
+ },
100909
+ connection.channelId
100910
+ );
100917
100911
  const inventory = await discover(signal);
100918
100912
  const config2 = createRuntimeConfig(
100919
100913
  {
@@ -100940,6 +100934,7 @@ var init_runtime_loop = __esm({
100940
100934
  init_discover_local_agents();
100941
100935
  init_runtime_agents();
100942
100936
  init_local_files();
100937
+ init_discover_agent_catalog();
100943
100938
  init_publish_agent_catalog();
100944
100939
  init_resolve_catalog_agent();
100945
100940
  init_config();