@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/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.353",
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"() {
@@ -66262,14 +66139,16 @@ var init_environment_session_list = __esm({
66262
66139
  });
66263
66140
 
66264
66141
  // src/engine/acp/harness/claude/upstream/dist/environment-session-messages.js
66265
- function getEnvironmentSessionMessages(environment, sessionId, signal) {
66142
+ function getEnvironmentSessionMessages(environment, sessionId, cancellationSignal) {
66143
+ const signal = AbortSignal.any([cancellationSignal, AbortSignal.timeout(SESSION_MESSAGES_TIMEOUT_MILLISECONDS)]);
66266
66144
  return withEnvironment(environment, () => withDeadline(signal, SESSION_MESSAGES_TIMEOUT_MILLISECONDS, async () => {
66267
- const messages = await FZt(sessionId);
66268
66145
  const authenticationFailures = /* @__PURE__ */ new Set();
66146
+ const transcript = [];
66269
66147
  const nativeMetadata = /* @__PURE__ */ new Map();
66270
66148
  await GZt(sessionId, {
66271
66149
  append: async (_key, entries) => {
66272
66150
  signal.throwIfAborted();
66151
+ transcript.push(...entries);
66273
66152
  for (const entry of entries) {
66274
66153
  if (entry.type === "user" && typeof entry.uuid === "string") {
66275
66154
  nativeMetadata.set(entry.uuid, {
@@ -66285,16 +66164,151 @@ function getEnvironmentSessionMessages(environment, sessionId, signal) {
66285
66164
  load: async () => null
66286
66165
  }, { includeSubagents: false });
66287
66166
  signal.throwIfAborted();
66167
+ const messages = await readFullHistory(transcript, sessionId, signal) ?? await FZt(sessionId);
66288
66168
  return messages.filter((message) => !authenticationFailures.has(message.uuid)).map((message) => ({ ...message, ...nativeMetadata.get(message.uuid) }));
66289
66169
  }));
66290
66170
  }
66291
- var SESSION_MESSAGES_TIMEOUT_MILLISECONDS;
66171
+ async function readFullHistory(transcript, sessionId, signal) {
66172
+ const entries = /* @__PURE__ */ new Map();
66173
+ for (const [index2, raw] of transcript.entries()) {
66174
+ signal.throwIfAborted();
66175
+ if (typeof raw.uuid !== "string") {
66176
+ continue;
66177
+ }
66178
+ if (!["user", "assistant", "system", "progress", "attachment"].includes(raw.type)) {
66179
+ continue;
66180
+ }
66181
+ const parsed = chainEntrySchema.safeParse(raw);
66182
+ if (!parsed.success) {
66183
+ return null;
66184
+ }
66185
+ entries.set(parsed.data.uuid, { entry: parsed.data, index: index2 });
66186
+ }
66187
+ const validated = /* @__PURE__ */ new Set();
66188
+ for (const uuid3 of entries.keys()) {
66189
+ signal.throwIfAborted();
66190
+ const visiting = /* @__PURE__ */ new Set();
66191
+ let current = uuid3;
66192
+ while (current !== null && !validated.has(current)) {
66193
+ const node2 = entries.get(current);
66194
+ if (node2 === void 0 || visiting.has(current)) {
66195
+ return null;
66196
+ }
66197
+ visiting.add(current);
66198
+ const entry = node2.entry;
66199
+ current = entry.subtype === "compact_boundary" ? entry.logicalParentUuid ?? entry.parentUuid : entry.parentUuid;
66200
+ }
66201
+ for (const id of visiting) {
66202
+ validated.add(id);
66203
+ }
66204
+ }
66205
+ for (const { entry } of entries.values()) {
66206
+ if (entry.subtype !== "compact_boundary") {
66207
+ continue;
66208
+ }
66209
+ const preserved = entry.compactMetadata;
66210
+ const references = preserved?.preservedMessages !== void 0 ? [...preserved.preservedMessages.uuids, preserved.preservedMessages.anchorUuid] : preserved?.preservedSegment !== void 0 ? [
66211
+ preserved.preservedSegment.headUuid,
66212
+ preserved.preservedSegment.tailUuid,
66213
+ preserved.preservedSegment.anchorUuid
66214
+ ] : [];
66215
+ if (references.some((id) => !entries.has(id))) {
66216
+ return null;
66217
+ }
66218
+ }
66219
+ const project = async (source) => {
66220
+ signal.throwIfAborted();
66221
+ const messages = await FZt(sessionId, {
66222
+ includeSystemMessages: true,
66223
+ sessionStore: { append: async () => {
66224
+ }, load: async () => source }
66225
+ });
66226
+ signal.throwIfAborted();
66227
+ return messages;
66228
+ };
66229
+ const result = [];
66230
+ const seen = /* @__PURE__ */ new Set();
66231
+ const expanding = /* @__PURE__ */ new Set();
66232
+ const append = async (messages) => {
66233
+ let compactionId;
66234
+ for (const message of messages) {
66235
+ signal.throwIfAborted();
66236
+ const node2 = entries.get(message.uuid);
66237
+ if (node2 === void 0) {
66238
+ return false;
66239
+ }
66240
+ if (node2.entry.subtype === "compact_boundary") {
66241
+ compactionId = message.uuid;
66242
+ if (seen.has(message.uuid)) {
66243
+ continue;
66244
+ }
66245
+ if (expanding.has(message.uuid)) {
66246
+ return false;
66247
+ }
66248
+ expanding.add(message.uuid);
66249
+ const parent = node2.entry.logicalParentUuid;
66250
+ if (typeof parent === "string") {
66251
+ const ancestor = entries.get(parent);
66252
+ if (ancestor === void 0 || ancestor.index >= node2.index) {
66253
+ return false;
66254
+ }
66255
+ const anchor2 = `history-anchor-${message.uuid}`;
66256
+ if (entries.has(anchor2)) {
66257
+ return false;
66258
+ }
66259
+ const earlier = await project([
66260
+ ...transcript.slice(0, node2.index),
66261
+ {
66262
+ type: "user",
66263
+ uuid: anchor2,
66264
+ parentUuid: parent,
66265
+ sessionId,
66266
+ message: { role: "user", content: "" }
66267
+ }
66268
+ ]);
66269
+ if (!await append(earlier.filter((entry) => entry.uuid !== anchor2))) {
66270
+ return false;
66271
+ }
66272
+ }
66273
+ expanding.delete(message.uuid);
66274
+ seen.add(message.uuid);
66275
+ result.push({ ...message, nativeCompaction: { kind: "boundary", id: message.uuid } });
66276
+ } else if (!seen.has(message.uuid)) {
66277
+ seen.add(message.uuid);
66278
+ if (node2.entry.isCompactSummary === true) {
66279
+ if (compactionId === void 0) {
66280
+ return false;
66281
+ }
66282
+ result.push({ ...message, nativeCompaction: { kind: "summary", id: compactionId } });
66283
+ } else if (message.type !== "system") {
66284
+ result.push(message);
66285
+ }
66286
+ }
66287
+ }
66288
+ return true;
66289
+ };
66290
+ return await append(await project([...transcript])) ? result : null;
66291
+ }
66292
+ var SESSION_MESSAGES_TIMEOUT_MILLISECONDS, chainEntrySchema;
66292
66293
  var init_environment_session_messages = __esm({
66293
66294
  "src/engine/acp/harness/claude/upstream/dist/environment-session-messages.js"() {
66294
66295
  "use strict";
66295
66296
  init_sdk();
66297
+ init_zod();
66296
66298
  init_utils();
66297
66299
  SESSION_MESSAGES_TIMEOUT_MILLISECONDS = 3e4;
66300
+ chainEntrySchema = external_exports.object({
66301
+ type: external_exports.enum(["user", "assistant", "system", "progress", "attachment"]),
66302
+ uuid: external_exports.string(),
66303
+ parentUuid: external_exports.string().nullable(),
66304
+ logicalParentUuid: external_exports.string().nullable().optional(),
66305
+ subtype: external_exports.string().optional(),
66306
+ isCompactSummary: external_exports.boolean().optional(),
66307
+ compactMetadata: external_exports.object({
66308
+ preservedSegment: external_exports.object({ headUuid: external_exports.string(), tailUuid: external_exports.string(), anchorUuid: external_exports.string() }).optional(),
66309
+ preservedMessages: external_exports.object({ uuids: external_exports.array(external_exports.string()), anchorUuid: external_exports.string() }).optional()
66310
+ }).passthrough().optional()
66311
+ }).passthrough();
66298
66312
  }
66299
66313
  });
66300
66314
 
@@ -69215,9 +69229,16 @@ function stripMarkerTags(text2) {
69215
69229
  }
69216
69230
  return result + text2.slice(copiedUpTo);
69217
69231
  }
69218
- function stripLocalCommandMetadata(content) {
69232
+ function stripLocalCommandMetadata(content, options) {
69233
+ const strip = (text2) => {
69234
+ if (options?.preserveCompactionCommand === true && /<command-name>\/compact<\/command-name>/u.test(text2)) {
69235
+ const args = /<command-args>([\s\S]*?)<\/command-args>/u.exec(text2)?.[1]?.trim() ?? "";
69236
+ return stripMarkerTags(text2.replace(/<command-name>\/compact<\/command-name>/u, () => args.length > 0 ? `/compact ${args}` : "/compact")).trim();
69237
+ }
69238
+ return stripMarkerTags(text2);
69239
+ };
69219
69240
  if (typeof content === "string") {
69220
- const stripped = stripMarkerTags(content);
69241
+ const stripped = strip(content);
69221
69242
  return stripped.trim() === "" ? null : stripped;
69222
69243
  }
69223
69244
  if (!Array.isArray(content)) {
@@ -69226,7 +69247,7 @@ function stripLocalCommandMetadata(content) {
69226
69247
  const kept = [];
69227
69248
  for (const block of content) {
69228
69249
  if (block && typeof block === "object" && "type" in block && block.type === "text" && "text" in block && typeof block.text === "string") {
69229
- const stripped = stripMarkerTags(block.text);
69250
+ const stripped = strip(block.text);
69230
69251
  if (stripped.trim() === "") {
69231
69252
  continue;
69232
69253
  }
@@ -70158,13 +70179,8 @@ function toAcpNotifications(content, role, sessionId, toolUseCache, client2, log
70158
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;
70159
70180
  const toolResultMeta = parseToolResultMeta(options?.toolResultMeta);
70160
70181
  const output2 = [];
70161
- const replayedResources = role === "user" && options.historical === true ? replayContextResources(content) : null;
70162
- for (const [index2, chunk] of content.entries()) {
70163
- if (replayedResources !== null && index2 >= replayedResources.contextStart) {
70164
- break;
70165
- }
70182
+ for (const chunk of content) {
70166
70183
  let update = null;
70167
- const resource = replayedResources?.resources.get(index2);
70168
70184
  switch (chunk.type) {
70169
70185
  case "text":
70170
70186
  case "text_delta": {
@@ -70173,7 +70189,7 @@ function toAcpNotifications(content, role, sessionId, toolUseCache, client2, log
70173
70189
  update = {
70174
70190
  sessionUpdate: role === "assistant" ? "agent_message_chunk" : "user_message_chunk",
70175
70191
  messageId,
70176
- content: resource ?? {
70192
+ content: {
70177
70193
  type: "text",
70178
70194
  text: chunk.text
70179
70195
  }
@@ -72851,6 +72867,35 @@ ${message.api_refusal_explanation}` : "";
72851
72867
  const forwardSubagentText = this.sessions[sessionId]?.forwardSubagentText ?? supportsSubagentTranscript(this.clientCapabilities);
72852
72868
  const seenTools = /* @__PURE__ */ new Set();
72853
72869
  for (const message of messages) {
72870
+ signal.throwIfAborted();
72871
+ if (message.nativeCompaction !== void 0) {
72872
+ const compaction = message.nativeCompaction;
72873
+ if (compaction.kind === "boundary") {
72874
+ await this.client.sessionUpdate({
72875
+ sessionId,
72876
+ update: {
72877
+ sessionUpdate: "compaction_update",
72878
+ compactionId: compaction.id,
72879
+ status: "completed"
72880
+ }
72881
+ });
72882
+ } else {
72883
+ const body = message.message;
72884
+ const content2 = typeof body === "object" && body !== null && "content" in body ? body.content : void 0;
72885
+ 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") : "";
72886
+ if (text2.length > 0) {
72887
+ await this.client.sessionUpdate({
72888
+ sessionId,
72889
+ update: {
72890
+ sessionUpdate: "compaction_summary_chunk",
72891
+ compactionId: compaction.id,
72892
+ content: { type: "text", text: text2 }
72893
+ }
72894
+ });
72895
+ }
72896
+ }
72897
+ continue;
72898
+ }
72854
72899
  if (isTaskNotificationOrigin(message.nativeOrigin)) {
72855
72900
  const body = message.message;
72856
72901
  const content2 = typeof body === "object" && body !== null && "content" in body ? body.content : void 0;
@@ -72872,7 +72917,7 @@ ${message.api_refusal_explanation}` : "";
72872
72917
  }
72873
72918
  let content = message.message.content;
72874
72919
  if (message.message.role === "user") {
72875
- content = stripLocalCommandMetadata(content);
72920
+ content = stripLocalCommandMetadata(content, { preserveCompactionCommand: true });
72876
72921
  if (content === null) {
72877
72922
  continue;
72878
72923
  }
@@ -74121,9 +74166,11 @@ var init_process_error = __esm({
74121
74166
  "use strict";
74122
74167
  ProcessExecutionError = class extends Error {
74123
74168
  code;
74169
+ diagnosticDetails;
74124
74170
  constructor(code, message, options = {}) {
74125
74171
  super(message, options);
74126
74172
  this.code = code;
74173
+ this.diagnosticDetails = options.diagnosticDetails ?? {};
74127
74174
  this.name = "ProcessExecutionError";
74128
74175
  }
74129
74176
  };
@@ -74133,7 +74180,7 @@ var init_process_error = __esm({
74133
74180
  // src/engine/util/process/platform/windows.ts
74134
74181
  import { execFile as execFile4 } from "node:child_process";
74135
74182
  import { readFile as readFile6, realpath as realpath6 } from "node:fs/promises";
74136
- 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";
74137
74184
  function environmentValue2(environment, name2) {
74138
74185
  return Object.entries(environment).find(([key]) => key.toUpperCase() === name2.toUpperCase())?.[1];
74139
74186
  }
@@ -74148,14 +74195,14 @@ function executableExtensions(executableName, environment) {
74148
74195
  async function resolveExecutableTarget(path8) {
74149
74196
  let resolvedPath;
74150
74197
  try {
74151
- resolvedPath = await realpath6(extname2(path8) === "" ? `${path8}.cmd` : path8);
74198
+ resolvedPath = await realpath6(extname(path8) === "" ? `${path8}.cmd` : path8);
74152
74199
  } catch (cause) {
74153
- 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") {
74154
74201
  throw cause;
74155
74202
  }
74156
74203
  resolvedPath = await realpath6(path8);
74157
74204
  }
74158
- if (extname2(resolvedPath).toLowerCase() === ".cmd") {
74205
+ if (extname(resolvedPath).toLowerCase() === ".cmd") {
74159
74206
  const shim = await readFile6(resolvedPath, "utf8");
74160
74207
  if (shim.includes('SET "NPM_CLI_JS=%~dp0\\node_modules\\npm\\bin\\npm-cli.js"') && shim.includes('"%NODE_EXE%" "%NPM_CLI_JS%" %*')) {
74161
74208
  return await realpath6(resolve9(dirname7(resolvedPath), "node_modules/npm/bin/npm-cli.js"));
@@ -74520,11 +74567,16 @@ async function runBoundedProcess(options) {
74520
74567
  abort();
74521
74568
  }
74522
74569
  try {
74523
- const exit = new Promise((resolveExit, rejectExit) => {
74524
- child.once("error", rejectExit);
74525
- 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));
74526
74578
  });
74527
- const exitCode = await Promise.race([exit, interrupted.promise.then(() => -1)]);
74579
+ const exitCode = await Promise.race([completion, interrupted.promise.then(() => -1)]);
74528
74580
  if (interruptionCleanupFailure !== null) {
74529
74581
  throw interruptionCleanupFailure;
74530
74582
  }
@@ -74536,12 +74588,19 @@ async function runBoundedProcess(options) {
74536
74588
  }
74537
74589
  return new ProcessResult(Buffer.concat(stdout).toString("utf8"), Buffer.concat(stderr).toString("utf8"));
74538
74590
  } catch (error62) {
74539
- if (error62 instanceof ProcessExecutionError) {
74540
- throw error62;
74541
- }
74542
- 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", {
74543
74592
  cause: error62
74544
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
+ });
74545
74604
  } finally {
74546
74605
  clearTimeout(timeout);
74547
74606
  options.signal.removeEventListener("abort", abort);
@@ -82407,7 +82466,14 @@ async function probeVersion(executable, arguments_, environment, defaultWorkspac
82407
82466
  });
82408
82467
  const version2 = normalize4(result.stdout || result.stderr);
82409
82468
  if (version2.length === 0) {
82410
- 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
+ });
82411
82477
  }
82412
82478
  return version2;
82413
82479
  }
@@ -82436,9 +82502,27 @@ function isRetryableProbeFailure(error62) {
82436
82502
  }
82437
82503
  return error62 instanceof AgentProbeError && error62.code === "adapter_probe_timeout";
82438
82504
  }
82439
- 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
+ };
82440
82524
  try {
82441
- return await probe();
82525
+ return await run(1);
82442
82526
  } catch (error62) {
82443
82527
  if (signal.aborted) {
82444
82528
  signal.throwIfAborted();
@@ -82446,7 +82530,7 @@ async function probeWithRetry(signal, probe) {
82446
82530
  if (!isRetryableProbeFailure(error62)) {
82447
82531
  throw error62;
82448
82532
  }
82449
- return await probe();
82533
+ return await run(2);
82450
82534
  }
82451
82535
  }
82452
82536
  function integrationProbeFailure(specification, error62) {
@@ -82476,7 +82560,9 @@ async function discoverAgent(specification, context) {
82476
82560
  let agentVersion = "";
82477
82561
  try {
82478
82562
  agentVersion = await probeWithRetry(
82479
- context.signal,
82563
+ context,
82564
+ specification,
82565
+ "agent_version",
82480
82566
  async () => await probeVersion(
82481
82567
  agent,
82482
82568
  specification.agentVersionArguments,
@@ -82524,7 +82610,9 @@ async function discoverAgent(specification, context) {
82524
82610
  launchEnvironment = await specification.createLaunchEnvironment(agent, context);
82525
82611
  if (specification.adapterVersionArguments.length > 0) {
82526
82612
  adapterVersion = await probeWithRetry(
82527
- context.signal,
82613
+ context,
82614
+ specification,
82615
+ "adapter_version",
82528
82616
  async () => await probeVersion(
82529
82617
  adapter,
82530
82618
  specification.adapterVersionArguments,
@@ -82559,7 +82647,9 @@ async function discoverAgent(specification, context) {
82559
82647
  );
82560
82648
  try {
82561
82649
  const readiness = await probeWithRetry(
82562
- context.signal,
82650
+ context,
82651
+ specification,
82652
+ "acp_readiness",
82563
82653
  async () => await probeAcpReadiness(
82564
82654
  specification,
82565
82655
  buildDefinition(adapterVersion, unsupportedSessionCapabilities()),
@@ -91099,6 +91189,294 @@ var init_environment_proxy = __esm({
91099
91189
  }
91100
91190
  });
91101
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
+
91102
91480
  // src/engine/runtime/relay/relay-authentication.ts
91103
91481
  function runtimeCredential(relayUrl) {
91104
91482
  return relayUrl.searchParams.get("token") ?? "";
@@ -91573,21 +91951,27 @@ function buildSavedRuntimeConfig(connection, defaultWorkspace, inventory, localC
91573
91951
  localContext,
91574
91952
  new OpaqueRuntimeReconnectTarget(connection.connectionId),
91575
91953
  createCatalogAgentResolver(
91576
- (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
+ {
91577
91968
  defaultWorkspace,
91578
91969
  dataDirectory: localContext.stateDirectory,
91579
91970
  environment: localContext.agentLaunchEnvironment,
91580
91971
  signal: refreshSignal
91581
- }),
91582
- () => config2,
91583
- publishAgentCatalog
91584
- ),
91585
- (refreshSignal) => discoverLocalAgentInventory({
91586
- defaultWorkspace,
91587
- dataDirectory: localContext.stateDirectory,
91588
- environment: localContext.agentLaunchEnvironment,
91589
- signal: refreshSignal
91590
- }).then((inventory2) => inventory2.readyAgents())
91972
+ },
91973
+ connection.channelId
91974
+ ).then((inventory2) => inventory2.readyAgents())
91591
91975
  );
91592
91976
  return config2;
91593
91977
  }
@@ -91631,12 +92015,15 @@ async function pairRuntimeConnection(installation, options, signal, environment)
91631
92015
  async function prepareRuntimeConnection(installation, connection, signal, environment, maxAcpProcesses) {
91632
92016
  const localContext = new RuntimeLocalContext(installation.stateDirectory, environment, maxAcpProcesses);
91633
92017
  const defaultWorkspace = await resolveDefaultWorkspace(connection.defaultWorkspace);
91634
- const inventory = await discoverLocalAgentInventory({
91635
- defaultWorkspace,
91636
- dataDirectory: localContext.stateDirectory,
91637
- environment: localContext.agentLaunchEnvironment,
91638
- signal
91639
- });
92018
+ const inventory = await discoverRuntimeAgentInventory(
92019
+ {
92020
+ defaultWorkspace,
92021
+ dataDirectory: localContext.stateDirectory,
92022
+ environment: localContext.agentLaunchEnvironment,
92023
+ signal
92024
+ },
92025
+ connection.channelId
92026
+ );
91640
92027
  return buildSavedRuntimeConfig(connection, defaultWorkspace, inventory, localContext);
91641
92028
  }
91642
92029
  var PAIRING_TIMEOUT_MILLISECONDS, PAIRING_CODE_PATTERN, TOKEN_PATTERN, CLAIM_RESPONSE_KEYS, REDEEM_RESPONSE_KEYS, PairingClientError;
@@ -91649,6 +92036,7 @@ var init_pairing = __esm({
91649
92036
  init_local_files();
91650
92037
  init_environment_proxy();
91651
92038
  init_value_utils();
92039
+ init_discover_agent_catalog();
91652
92040
  init_publish_agent_catalog();
91653
92041
  init_resolve_catalog_agent();
91654
92042
  init_config();
@@ -96109,7 +96497,7 @@ var init_session_turns = __esm({
96109
96497
 
96110
96498
  // src/engine/session/workspace/workspace-directory.ts
96111
96499
  import { homedir as homedir4 } from "node:os";
96112
- 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";
96113
96501
  function encodePath(path8) {
96114
96502
  const encoded = Buffer.from(path8, "utf8").toString("base64url");
96115
96503
  if (path8.length === 0 || path8.length > MAX_WORKSPACE_PATH_LENGTH || encoded.length + "path-".length > MAX_DIRECTORY_IDENTIFIER_LENGTH) {
@@ -96239,7 +96627,7 @@ var init_workspace_directory = __esm({
96239
96627
  continue;
96240
96628
  }
96241
96629
  try {
96242
- const path8 = await this.resolvePath(join26(target, child.name), signal);
96630
+ const path8 = await this.resolvePath(join29(target, child.name), signal);
96243
96631
  entries.push({ directoryId: encodePath(path8), name: child.name });
96244
96632
  } catch (cause) {
96245
96633
  signal.throwIfAborted();
@@ -96419,7 +96807,7 @@ var init_session_layer = __esm({
96419
96807
  // src/engine/storage/files/scratch-directory.ts
96420
96808
  import { randomUUID as randomUUID17 } from "node:crypto";
96421
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";
96422
- import { dirname as dirname12, join as join27 } from "node:path";
96810
+ import { dirname as dirname12, join as join30 } from "node:path";
96423
96811
  async function atomicWrite(path8, bytes, signal) {
96424
96812
  const temporary = `${path8}.${randomUUID17()}.tmp`;
96425
96813
  try {
@@ -96437,7 +96825,7 @@ var init_scratch_directory = __esm({
96437
96825
  ScratchDirectory = class {
96438
96826
  #root;
96439
96827
  constructor(parent) {
96440
- this.#root = join27(parent, randomUUID17());
96828
+ this.#root = join30(parent, randomUUID17());
96441
96829
  }
96442
96830
  /** Refreshes this directory's lease and removes sibling directories whose lease is older than `leaseMilliseconds`. */
96443
96831
  refreshLease = async (leaseMilliseconds) => {
@@ -96448,7 +96836,7 @@ var init_scratch_directory = __esm({
96448
96836
  if (!directory.isDirectory() || !/^[a-f0-9-]{36}$/u.test(directory.name)) {
96449
96837
  continue;
96450
96838
  }
96451
- const path8 = join27(dirname12(this.#root), directory.name);
96839
+ const path8 = join30(dirname12(this.#root), directory.name);
96452
96840
  if (path8 === this.#root) {
96453
96841
  continue;
96454
96842
  }
@@ -96463,10 +96851,10 @@ var init_scratch_directory = __esm({
96463
96851
  };
96464
96852
  /** Writes `bytes` atomically to `<group>/<name>` with owner-only permissions and returns the path. */
96465
96853
  write = async (group, name2, bytes, signal) => {
96466
- const directory = join27(this.#root, group);
96854
+ const directory = join30(this.#root, group);
96467
96855
  await mkdir5(directory, { mode: 448, recursive: true });
96468
96856
  signal.throwIfAborted();
96469
- const path8 = join27(directory, name2);
96857
+ const path8 = join30(directory, name2);
96470
96858
  await atomicWrite(path8, bytes, signal);
96471
96859
  return path8;
96472
96860
  };
@@ -96501,9 +96889,9 @@ var init_scratch_directory = __esm({
96501
96889
 
96502
96890
  // src/engine/session/content/external-content-store.ts
96503
96891
  import { createHash as createHash8 } from "node:crypto";
96504
- import { extname as extname3, join as join28 } from "node:path";
96892
+ import { extname as extname2, join as join31 } from "node:path";
96505
96893
  function contentFileName(key, name2) {
96506
- const extension = extname3(name2).toLowerCase();
96894
+ const extension = extname2(name2).toLowerCase();
96507
96895
  return /^\.[a-z0-9]{1,16}$/u.test(extension) ? `${key}${extension}` : key;
96508
96896
  }
96509
96897
  var contentRequest, CONTENT_LIFETIME_MILLISECONDS, metadataSchema, LocalExternalContentStore;
@@ -96527,7 +96915,7 @@ var init_external_content_store = __esm({
96527
96915
  #expirationTimer;
96528
96916
  #cleanup = Promise.resolve();
96529
96917
  constructor(stateDirectory) {
96530
- this.#scratch = new ScratchDirectory(join28(stateDirectory, "tmp", "session-content"));
96918
+ this.#scratch = new ScratchDirectory(join31(stateDirectory, "tmp", "session-content"));
96531
96919
  this.#expirationTimer = setInterval(() => {
96532
96920
  void this.#expire().catch(() => void 0);
96533
96921
  }, 6e4);
@@ -96923,230 +97311,6 @@ var init_agent_process_pool = __esm({
96923
97311
  }
96924
97312
  });
96925
97313
 
96926
- // src/engine/storage/logs/bounded-log.ts
96927
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync9, renameSync as renameSync2, statSync as statSync5, writeFileSync as writeFileSync2 } from "node:fs";
96928
- import { join as join29 } from "node:path";
96929
- var BoundedLineLog;
96930
- var init_bounded_log = __esm({
96931
- "src/engine/storage/logs/bounded-log.ts"() {
96932
- "use strict";
96933
- BoundedLineLog = class {
96934
- #path;
96935
- #maximumBytes;
96936
- #directory;
96937
- #reportedFailure = false;
96938
- #onWriteFailure;
96939
- constructor(directory, filename, maximumBytes, onWriteFailure = () => void 0) {
96940
- this.#directory = directory;
96941
- this.#path = join29(directory, filename);
96942
- this.#maximumBytes = maximumBytes;
96943
- this.#onWriteFailure = onWriteFailure;
96944
- }
96945
- record = (line) => {
96946
- try {
96947
- mkdirSync4(this.#directory, { mode: 448, recursive: true });
96948
- this.#append(line);
96949
- } catch (cause) {
96950
- if (!this.#reportedFailure) {
96951
- this.#reportedFailure = true;
96952
- this.#onWriteFailure(cause);
96953
- }
96954
- }
96955
- };
96956
- #append = (line) => {
96957
- const encoded = `${line.replace(/[\r\n]+/gu, " ").trim()}
96958
- `;
96959
- const encodedBytes = Buffer.byteLength(encoded);
96960
- let existingBytes = 0;
96961
- try {
96962
- existingBytes = statSync5(this.#path).size;
96963
- } catch (cause) {
96964
- if (!(cause instanceof Error && Reflect.get(cause, "code") === "ENOENT")) {
96965
- throw cause;
96966
- }
96967
- }
96968
- if (existingBytes + encodedBytes <= this.#maximumBytes) {
96969
- appendFileSync2(this.#path, encoded, { encoding: "utf8", mode: 384 });
96970
- return;
96971
- }
96972
- const lines = `${existingBytes === 0 ? "" : readFileSync9(this.#path, "utf8")}${encoded}`.split("\n").filter((candidate) => candidate.length > 0);
96973
- let totalBytes = lines.reduce((total, candidate) => total + Buffer.byteLength(candidate) + 1, 0);
96974
- while (totalBytes > this.#maximumBytes && lines.length > 0) {
96975
- const oldest = lines.shift();
96976
- if (oldest !== void 0) {
96977
- totalBytes -= Buffer.byteLength(oldest) + 1;
96978
- }
96979
- }
96980
- const temporaryPath = `${this.#path}.tmp`;
96981
- writeFileSync2(temporaryPath, lines.length === 0 ? "" : `${lines.join("\n")}
96982
- `, {
96983
- encoding: "utf8",
96984
- mode: 384
96985
- });
96986
- renameSync2(temporaryPath, this.#path);
96987
- };
96988
- };
96989
- }
96990
- });
96991
-
96992
- // src/engine/storage/logs/log-files.ts
96993
- import { readFileSync as readFileSync10 } from "node:fs";
96994
- import { join as join30 } from "node:path";
96995
- function unhandledRejectionLogFilename(role) {
96996
- return `unhandled-rejections-${role}.log`;
96997
- }
96998
- function logDirectory(dataDirectory) {
96999
- return join30(dataDirectory, "logs");
97000
- }
97001
- function processLogPaths(dataDirectory) {
97002
- return [
97003
- WORKER_LIFECYCLE_LOG_FILENAME,
97004
- unhandledRejectionLogFilename("manager"),
97005
- unhandledRejectionLogFilename("worker")
97006
- ].map((filename) => join30(logDirectory(dataDirectory), filename));
97007
- }
97008
- function readLogText(path8) {
97009
- try {
97010
- return readFileSync10(path8, "utf8");
97011
- } catch {
97012
- return null;
97013
- }
97014
- }
97015
- var DAEMON_LOG_FILENAME, WORKER_LIFECYCLE_LOG_FILENAME;
97016
- var init_log_files = __esm({
97017
- "src/engine/storage/logs/log-files.ts"() {
97018
- "use strict";
97019
- DAEMON_LOG_FILENAME = "daemon.log";
97020
- WORKER_LIFECYCLE_LOG_FILENAME = "worker-lifecycle.log";
97021
- }
97022
- });
97023
-
97024
- // src/engine/runtime/observability/diagnostic-log.ts
97025
- import { join as join31 } from "node:path";
97026
- function exportedFields(value) {
97027
- const entry = {};
97028
- for (const field of REMOTE_DIAGNOSTIC_FIELDS) {
97029
- const item = Reflect.get(value, field);
97030
- if (typeof item === "string" && FIELD_VALUE_PATTERN.test(item)) {
97031
- entry[field] = item;
97032
- } else if (typeof item === "number" && Number.isFinite(item)) {
97033
- entry[field] = String(item);
97034
- }
97035
- }
97036
- return entry;
97037
- }
97038
- function compareTimestamp(left, right) {
97039
- const leftAt = left["timestamp"] ?? "";
97040
- const rightAt = right["timestamp"] ?? "";
97041
- return leftAt < rightAt ? -1 : leftAt > rightAt ? 1 : 0;
97042
- }
97043
- var MAXIMUM_RUNTIME_LOG_BYTES, MAXIMUM_ENTRIES, MAXIMUM_REPORT_BYTES, REMOTE_DIAGNOSTIC_FIELDS, FIELD_VALUE_PATTERN, RuntimeDiagnosticLog;
97044
- var init_diagnostic_log = __esm({
97045
- "src/engine/runtime/observability/diagnostic-log.ts"() {
97046
- "use strict";
97047
- init_bounded_log();
97048
- init_log_files();
97049
- MAXIMUM_RUNTIME_LOG_BYTES = 1 * 1024 * 1024;
97050
- MAXIMUM_ENTRIES = 200;
97051
- MAXIMUM_REPORT_BYTES = 6e4;
97052
- REMOTE_DIAGNOSTIC_FIELDS = [
97053
- "agentId",
97054
- "operation",
97055
- "runtimeId",
97056
- "closeCode",
97057
- "timeoutMilliseconds",
97058
- "proxyRoute",
97059
- "timestamp",
97060
- "event",
97061
- "channelId",
97062
- "requestId",
97063
- "commandId",
97064
- "sessionId",
97065
- "turnId",
97066
- "connectionEpoch",
97067
- "code",
97068
- "source",
97069
- "kind",
97070
- "pid",
97071
- "version",
97072
- "exitCode",
97073
- "signal",
97074
- "failureName",
97075
- "failureCode",
97076
- "failureStatusCode",
97077
- "cause1Name",
97078
- "cause1Code",
97079
- "cause2Name",
97080
- "cause2Code"
97081
- ];
97082
- FIELD_VALUE_PATTERN = /^[a-zA-Z0-9_.: -]{1,256}$/u;
97083
- RuntimeDiagnosticLog = class {
97084
- #log;
97085
- #maximumBytes;
97086
- #sources;
97087
- constructor(stateDirectory, options = {}) {
97088
- const maximumBytes = options.maximumBytes ?? MAXIMUM_RUNTIME_LOG_BYTES;
97089
- const directory = logDirectory(stateDirectory);
97090
- this.#log = new BoundedLineLog(directory, DAEMON_LOG_FILENAME, maximumBytes);
97091
- this.#maximumBytes = maximumBytes;
97092
- const processLogsDirectory = options.processLogsDirectory;
97093
- this.#sources = [
97094
- { maximumBytes, path: join31(directory, DAEMON_LOG_FILENAME) },
97095
- // The process logs a Runtime does not own, but must read to explain its own deaths.
97096
- ...processLogsDirectory === void 0 ? [] : processLogPaths(processLogsDirectory).map((path8) => ({ maximumBytes: null, path: path8 }))
97097
- ];
97098
- }
97099
- // Export only correlation and failure metadata. Local messages and paths stay local.
97100
- snapshot = () => {
97101
- const merged = [];
97102
- let truncated = false;
97103
- for (const source of this.#sources) {
97104
- const collected = this.#read(source);
97105
- merged.push(...collected.entries);
97106
- truncated ||= collected.truncated;
97107
- }
97108
- merged.sort(compareTimestamp);
97109
- const entries = merged.slice(-MAXIMUM_ENTRIES);
97110
- truncated ||= entries.length < merged.length;
97111
- while (JSON.stringify(entries).length > MAXIMUM_REPORT_BYTES && entries.length > 0) {
97112
- entries.shift();
97113
- truncated = true;
97114
- }
97115
- return { entries, truncated };
97116
- };
97117
- record = (diagnostic) => {
97118
- this.#log.record(diagnostic);
97119
- };
97120
- #read = (source) => {
97121
- const content = readLogText(source.path);
97122
- if (content === null) {
97123
- return { entries: [], truncated: false };
97124
- }
97125
- const lines = content.split("\n").filter((line) => line.length > 0);
97126
- const entries = [];
97127
- for (const line of lines.slice(-MAXIMUM_ENTRIES)) {
97128
- const start = line.indexOf("{");
97129
- if (start < 0) {
97130
- continue;
97131
- }
97132
- let value;
97133
- try {
97134
- value = JSON.parse(line.slice(start));
97135
- } catch {
97136
- continue;
97137
- }
97138
- if (typeof value !== "object" || value === null) {
97139
- continue;
97140
- }
97141
- entries.push(exportedFields(value));
97142
- }
97143
- const nearRotation = source.maximumBytes !== null && Buffer.byteLength(content) >= source.maximumBytes - 4096;
97144
- return { entries, truncated: lines.length > MAXIMUM_ENTRIES || nearRotation };
97145
- };
97146
- };
97147
- }
97148
- });
97149
-
97150
97314
  // src/engine/runtime/relay/diagnostics.ts
97151
97315
  function sanitizeDiagnosticText(value) {
97152
97316
  const printable = Array.from(value, (character) => {
@@ -98161,7 +98325,7 @@ var init_content_write = __esm({
98161
98325
  });
98162
98326
 
98163
98327
  // src/engine/session/content/session-files.ts
98164
- 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";
98165
98329
  import { fileURLToPath as fileURLToPath2 } from "node:url";
98166
98330
  function requestedPath(value) {
98167
98331
  if (value.includes("\0")) {
@@ -98217,7 +98381,7 @@ async function streamLocalFile(command, send2, sendChunk, signal, workingDirecto
98217
98381
  send2({
98218
98382
  byteLength: before.size,
98219
98383
  kind: FILE_BEGIN_KIND,
98220
- 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"),
98221
98385
  modifiedAt: before.modifiedAt.toISOString(),
98222
98386
  name: external?.name ?? (basename9(target) || "file"),
98223
98387
  requestId: command.requestId,
@@ -100734,13 +100898,16 @@ async function prepareProvidedRuntime({
100734
100898
  const defaultWorkspace = await resolveWorkspace(connection.defaultWorkspace);
100735
100899
  const specifications = supportedLocalAgentSpecifications();
100736
100900
  const discoveryEnvironment = localContext.agentLaunchEnvironment;
100737
- const discover = async (refreshSignal) => await discoverLocalAgentInventory({
100738
- defaultWorkspace,
100739
- dataDirectory: localContext.stateDirectory,
100740
- environment: discoveryEnvironment,
100741
- signal: refreshSignal,
100742
- specifications
100743
- });
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
+ );
100744
100911
  const inventory = await discover(signal);
100745
100912
  const config2 = createRuntimeConfig(
100746
100913
  {
@@ -100767,6 +100934,7 @@ var init_runtime_loop = __esm({
100767
100934
  init_discover_local_agents();
100768
100935
  init_runtime_agents();
100769
100936
  init_local_files();
100937
+ init_discover_agent_catalog();
100770
100938
  init_publish_agent_catalog();
100771
100939
  init_resolve_catalog_agent();
100772
100940
  init_config();