@moxt-ai/mobius 0.0.347 → 0.0.349

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 (31) hide show
  1. package/dist/cli.js +161 -104
  2. package/dist/cli.js.map +4 -4
  3. package/dist/engine/runtime/command/registry/prompt.js +4 -4
  4. package/dist/engine/runtime/command/registry/prompt.js.map +1 -1
  5. package/dist/engine/runtime/command/registry/session.d.ts.map +1 -1
  6. package/dist/engine/runtime/command/registry/session.js +8 -1
  7. package/dist/engine/runtime/command/registry/session.js.map +1 -1
  8. package/dist/engine/runtime/relay/session-event-publisher.d.ts.map +1 -1
  9. package/dist/engine/runtime/relay/session-event-publisher.js +22 -1
  10. package/dist/engine/runtime/relay/session-event-publisher.js.map +1 -1
  11. package/dist/engine/session/content/external-content-store.d.ts +4 -1
  12. package/dist/engine/session/content/external-content-store.d.ts.map +1 -1
  13. package/dist/engine/session/content/external-content-store.js +11 -3
  14. package/dist/engine/session/content/external-content-store.js.map +1 -1
  15. package/dist/engine/session/prompt/prompt-artifacts.d.ts +6 -1
  16. package/dist/engine/session/prompt/prompt-artifacts.d.ts.map +1 -1
  17. package/dist/engine/session/prompt/prompt-artifacts.js +12 -17
  18. package/dist/engine/session/prompt/prompt-artifacts.js.map +1 -1
  19. package/dist/engine/session/prompt/prompt-lifecycle.d.ts.map +1 -1
  20. package/dist/engine/session/prompt/prompt-lifecycle.js +2 -1
  21. package/dist/engine/session/prompt/prompt-lifecycle.js.map +1 -1
  22. package/dist/engine/session/turn/execution-receipts.d.ts.map +1 -1
  23. package/dist/engine/session/turn/execution-receipts.js +5 -6
  24. package/dist/engine/session/turn/execution-receipts.js.map +1 -1
  25. package/dist/engine/session/workspace/workspace-directory.d.ts +1 -0
  26. package/dist/engine/session/workspace/workspace-directory.d.ts.map +1 -1
  27. package/dist/engine/session/workspace/workspace-directory.js +2 -1
  28. package/dist/engine/session/workspace/workspace-directory.js.map +1 -1
  29. package/dist/engine.js +152 -96
  30. package/dist/engine.js.map +4 -4
  31. package/package.json +6 -6
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.347",
2089
+ version: "0.0.349",
2090
2090
  description: "Mobius CLI for pairing and running local AI agent services.",
2091
2091
  type: "module",
2092
2092
  bin: {
@@ -2128,13 +2128,13 @@ var init_package = __esm({
2128
2128
  prepack: "pnpm build",
2129
2129
  start: "node dist/cli.js",
2130
2130
  typecheck: "tsc --project tsconfig.json && tsc --project tests/tsconfig.json",
2131
- "pretest:controlled": "tsc --project src/engine/acp/harness/claude/upstream/tsconfig.json && tsc --project src/engine/acp/harness/pi/upstream/tsconfig.json",
2132
- "test:controlled": "vitest run tests/sessions tests/runtime --maxWorkers=4",
2131
+ "pretest:controlled": "pnpm build",
2132
+ "test:controlled": "vitest run tests/sessions tests/runtime",
2133
2133
  "pretest:manual": "pnpm pretest:controlled",
2134
2134
  "test:manual": "vitest run tests/manual",
2135
- "pretest:agents": "tsc --project src/engine/acp/harness/claude/upstream/tsconfig.json && tsc --project src/engine/acp/harness/pi/upstream/tsconfig.json",
2135
+ "pretest:agents": "pnpm build",
2136
2136
  "test:agents": "vitest run tests/agents --maxWorkers=2",
2137
- "pretest:npm-compatibility": "tsc --project src/engine/acp/harness/claude/upstream/tsconfig.json && tsc --project src/engine/acp/harness/pi/upstream/tsconfig.json",
2137
+ "pretest:npm-compatibility": "pnpm build",
2138
2138
  "test:npm-compatibility": "vitest run tests/runtime/daemon-upgrade.integration.test.ts",
2139
2139
  "pretest:pressure": "tsc --project src/engine/acp/harness/claude/upstream/tsconfig.json && tsc --project src/engine/acp/harness/pi/upstream/tsconfig.json",
2140
2140
  "test:pressure": "node tests/pressure/concurrent-sessions.mjs"
@@ -28217,7 +28217,8 @@ var init_workspace = __esm({
28217
28217
  bindingId: identifierStringSchema,
28218
28218
  directoryId: DIRECTORY_IDENTIFIER,
28219
28219
  kind: external_exports.literal(WORKSPACE_LIST_KIND),
28220
- requestId: identifierStringSchema
28220
+ requestId: identifierStringSchema,
28221
+ view: external_exports.literal("metadata").optional()
28221
28222
  }).readonly();
28222
28223
  workspaceEntriesEventSchema = external_exports.object({
28223
28224
  bindingId: identifierStringSchema,
@@ -71196,6 +71197,7 @@ var init_acp_agent = __esm({
71196
71197
  session.titles.onPrompt(params.prompt);
71197
71198
  const turn = {
71198
71199
  promptUuid,
71200
+ inputQueuedAt: performance.now(),
71199
71201
  isLocalOnlyCommand,
71200
71202
  settled: false,
71201
71203
  resolve: () => {
@@ -71681,6 +71683,15 @@ var init_acp_agent = __esm({
71681
71683
  case "started": {
71682
71684
  const queued = findUnsettledTurn(frame.command_uuid);
71683
71685
  if (queued) {
71686
+ if (!queued.commandStarted) {
71687
+ this.logger.log(JSON.stringify({
71688
+ event: "claude-sdk-command-start-timing",
71689
+ sessionId: params.sessionId,
71690
+ promptUuid: queued.promptUuid,
71691
+ observedAt: Date.now(),
71692
+ queuedToCommandStartMs: performance.now() - queued.inputQueuedAt
71693
+ }));
71694
+ }
71684
71695
  queued.commandStarted = true;
71685
71696
  }
71686
71697
  const state = session.orphanCommands?.get(frame.command_uuid);
@@ -72367,6 +72378,16 @@ ${message.api_refusal_explanation}` : "";
72367
72378
  }
72368
72379
  const queued = findUnsettledTurn(message.uuid);
72369
72380
  if (queued) {
72381
+ if (!queued.inputEchoObserved) {
72382
+ queued.inputEchoObserved = true;
72383
+ this.logger.log(JSON.stringify({
72384
+ event: "claude-sdk-input-echo-timing",
72385
+ sessionId: params.sessionId,
72386
+ promptUuid: queued.promptUuid,
72387
+ observedAt: Date.now(),
72388
+ queuedToEchoMs: performance.now() - queued.inputQueuedAt
72389
+ }));
72390
+ }
72370
72391
  if (session.activeTurn !== queued) {
72371
72392
  if (session.activeTurn) {
72372
72393
  if (session.cancelled) {
@@ -95134,6 +95155,71 @@ var init_native_session_browser = __esm({
95134
95155
  }
95135
95156
  });
95136
95157
 
95158
+ // src/engine/session/prompt/prompt-artifacts.ts
95159
+ import { createHash as createHash6 } from "node:crypto";
95160
+ import { pathToFileURL as pathToFileURL2 } from "node:url";
95161
+ function isTextPromptResourceMediaType(mediaType) {
95162
+ return mediaType.startsWith("text/") || mediaType === "application/json" || mediaType.endsWith("+json") || mediaType === "application/xml" || mediaType.endsWith("+xml");
95163
+ }
95164
+ async function resolvePromptArtifacts(read, attachments, signal) {
95165
+ const images = [];
95166
+ const resources = [];
95167
+ for (const attachment of attachments) {
95168
+ signal.throwIfAborted();
95169
+ const artifact = await read(attachment, signal);
95170
+ const { bytes } = artifact;
95171
+ if (bytes.byteLength !== attachment.byteLength || createHash6("sha256").update(bytes).digest("hex") !== attachment.contentKey) {
95172
+ throw new PromptArtifactError(
95173
+ "artifact_integrity_failed",
95174
+ "The prompt attachment failed integrity validation"
95175
+ );
95176
+ }
95177
+ if (attachment.kind === "image") {
95178
+ if (bytes.byteLength > PROMPT_IMAGE_MAX_BYTES || images.length >= 8) {
95179
+ continue;
95180
+ }
95181
+ images.push({
95182
+ data: Buffer.from(bytes).toString("base64"),
95183
+ mimeType: attachment.mimeType,
95184
+ name: attachment.name
95185
+ });
95186
+ continue;
95187
+ }
95188
+ if (bytes.byteLength > MAX_PROMPT_ATTACHMENT_BYTES || resources.length >= 16) {
95189
+ continue;
95190
+ }
95191
+ resources.push({
95192
+ mimeType: attachment.mimeType,
95193
+ name: attachment.name,
95194
+ type: "link",
95195
+ uri: pathToFileURL2(artifact.path).href
95196
+ });
95197
+ }
95198
+ return new ResolvedPromptArtifacts(images, resources);
95199
+ }
95200
+ var PromptArtifactError, ResolvedPromptArtifacts;
95201
+ var init_prompt_artifacts = __esm({
95202
+ "src/engine/session/prompt/prompt-artifacts.ts"() {
95203
+ "use strict";
95204
+ init_protocol();
95205
+ init_operation_error();
95206
+ PromptArtifactError = class extends OperationError {
95207
+ constructor(code, message, options = {}) {
95208
+ super(code, message, options);
95209
+ this.name = "PromptArtifactError";
95210
+ }
95211
+ };
95212
+ ResolvedPromptArtifacts = class {
95213
+ images;
95214
+ resources;
95215
+ constructor(images, resources) {
95216
+ this.images = images;
95217
+ this.resources = resources;
95218
+ }
95219
+ };
95220
+ }
95221
+ });
95222
+
95137
95223
  // src/engine/session/prompt/prompt-lifecycle.ts
95138
95224
  function promptContent(command) {
95139
95225
  const content = [];
@@ -95150,7 +95236,7 @@ function promptContent(command) {
95150
95236
  uri: attachment.uri
95151
95237
  } : {
95152
95238
  byteLength: attachment.byteLength,
95153
- encoding: "text",
95239
+ encoding: isTextPromptResourceMediaType(attachment.mimeType) ? "text" : "binary",
95154
95240
  mimeType: attachment.mimeType,
95155
95241
  resourceKey: attachment.contentKey,
95156
95242
  type: "external_resource",
@@ -95184,6 +95270,7 @@ var init_prompt_lifecycle = __esm({
95184
95270
  "src/engine/session/prompt/prompt-lifecycle.ts"() {
95185
95271
  "use strict";
95186
95272
  init_protocol();
95273
+ init_prompt_artifacts();
95187
95274
  PromptLifecycle = class {
95188
95275
  #sink;
95189
95276
  #terminal = /* @__PURE__ */ new Map();
@@ -95322,7 +95409,7 @@ var init_prompt_lifecycle = __esm({
95322
95409
  });
95323
95410
 
95324
95411
  // src/engine/session/turn/execution-receipts.ts
95325
- import { createHash as createHash6, randomUUID as randomUUID15 } from "node:crypto";
95412
+ import { createHash as createHash7, randomUUID as randomUUID15 } from "node:crypto";
95326
95413
  var MAX_TERMINAL_RECEIPTS, ExecutionReceipts;
95327
95414
  var init_execution_receipts = __esm({
95328
95415
  "src/engine/session/turn/execution-receipts.ts"() {
@@ -95348,11 +95435,11 @@ var init_execution_receipts = __esm({
95348
95435
  }
95349
95436
  }
95350
95437
  }
95351
- #save = (commandId, receipt) => {
95438
+ #save = (commandId, receipt, liveOutcome = receipt.outcome) => {
95352
95439
  const evicted = this.#closing ? [] : this.#table.save({ ...receipt, commandId, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, MAX_TERMINAL_RECEIPTS);
95353
95440
  const previous = this.#executions.get(commandId);
95354
95441
  const wasActive = previous?.outcome === null;
95355
- this.#executions.set(commandId, receipt);
95442
+ this.#executions.set(commandId, { ...receipt, outcome: liveOutcome });
95356
95443
  for (const evictedCommandId of evicted) {
95357
95444
  this.#executions.delete(evictedCommandId);
95358
95445
  this.#recoveredCommands.delete(evictedCommandId);
@@ -95440,7 +95527,7 @@ var init_execution_receipts = __esm({
95440
95527
  type: "lifecycle-metadata",
95441
95528
  payload: { kind: "prompt.completed", commandId, stopReason: "cancelled" }
95442
95529
  };
95443
- const commandHash = createHash6("sha256").update(
95530
+ const commandHash = createHash7("sha256").update(
95444
95531
  encodeSessionCancelBeforeStartCommand({
95445
95532
  commandId,
95446
95533
  kind: "session.cancel-before-start",
@@ -95469,10 +95556,12 @@ var init_execution_receipts = __esm({
95469
95556
  return;
95470
95557
  }
95471
95558
  const sanitized = payload.kind === "prompt.completed" ? payload : { ...payload, message: "The local Agent could not complete the request" };
95472
- this.#save(payload.commandId, {
95473
- ...receipt,
95474
- outcome: JSON.stringify({ type: "lifecycle-metadata", payload: sanitized, recordedAt: event.recordedAt })
95475
- });
95559
+ const outcome = { type: "lifecycle-metadata", payload, recordedAt: event.recordedAt };
95560
+ this.#save(
95561
+ payload.commandId,
95562
+ { ...receipt, outcome: JSON.stringify({ ...outcome, payload: sanitized }) },
95563
+ JSON.stringify(outcome)
95564
+ );
95476
95565
  };
95477
95566
  recover = () => {
95478
95567
  const recovered = [];
@@ -95504,7 +95593,7 @@ var init_execution_receipts = __esm({
95504
95593
  return recovered;
95505
95594
  };
95506
95595
  claimExecution = (commandId, sessionId, commandJson) => {
95507
- const commandHash = createHash6("sha256").update(commandJson).digest("hex");
95596
+ const commandHash = createHash7("sha256").update(commandJson).digest("hex");
95508
95597
  let existing = this.#executions.get(commandId);
95509
95598
  const previous = this.outcome(commandId);
95510
95599
  if (existing?.sessionId === sessionId && !existing.started && previous?.type === "lifecycle-metadata" && previous.payload.kind === "prompt.failed-before-start" && previous.payload.code === "runtime_restarted") {
@@ -96091,7 +96180,8 @@ var init_workspace_directory = __esm({
96091
96180
  };
96092
96181
  describe = async (bindingId, id, signal) => {
96093
96182
  const path8 = await this.resolve(bindingId, id, signal);
96094
- return { path: path8, label: this.label(path8) };
96183
+ const parent = dirname11(path8);
96184
+ return { path: path8, label: this.label(path8), parentDirectoryId: parent === path8 ? "" : encodePath(parent) };
96095
96185
  };
96096
96186
  list = async (bindingId, id, signal) => {
96097
96187
  const target = await this.resolve(bindingId, id, signal);
@@ -96368,8 +96458,12 @@ var init_scratch_directory = __esm({
96368
96458
  });
96369
96459
 
96370
96460
  // src/engine/session/content/external-content-store.ts
96371
- import { createHash as createHash7 } from "node:crypto";
96372
- import { join as join28 } from "node:path";
96461
+ import { createHash as createHash8 } from "node:crypto";
96462
+ import { extname as extname3, join as join28 } from "node:path";
96463
+ function contentFileName(key, name2) {
96464
+ const extension = extname3(name2).toLowerCase();
96465
+ return /^\.[a-z0-9]{1,16}$/u.test(extension) ? `${key}${extension}` : key;
96466
+ }
96373
96467
  var contentRequest, CONTENT_LIFETIME_MILLISECONDS, metadataSchema, LocalExternalContentStore;
96374
96468
  var init_external_content_store = __esm({
96375
96469
  "src/engine/session/content/external-content-store.ts"() {
@@ -96425,7 +96519,7 @@ var init_external_content_store = __esm({
96425
96519
  const active = AbortSignal.any([signal, this.#lifetime.signal]);
96426
96520
  active.throwIfAborted();
96427
96521
  const metadata = metadataSchema.parse({ kind, mediaType, name: name2 });
96428
- const key = createHash7("sha256").update(bytes).digest("hex");
96522
+ const key = createHash8("sha256").update(bytes).digest("hex");
96429
96523
  const request = `mobius-content:${kind}:${key}`;
96430
96524
  const existing = this.#entries.get(request);
96431
96525
  if (existing !== void 0 && existing.expiresAt > Date.now()) {
@@ -96438,7 +96532,7 @@ var init_external_content_store = __esm({
96438
96532
  }
96439
96533
  await this.#expire();
96440
96534
  active.throwIfAborted();
96441
- const path8 = await this.#scratch.write(kind, key, bytes, active);
96535
+ const path8 = await this.#scratch.write(kind, contentFileName(key, metadata.name), bytes, active);
96442
96536
  active.throwIfAborted();
96443
96537
  const retained = this.#entries.get(request);
96444
96538
  this.#entries.set(request, {
@@ -96474,7 +96568,11 @@ var init_external_content_store = __esm({
96474
96568
  read = (sessionId, request, signal) => this.#track(async () => {
96475
96569
  const active = AbortSignal.any([signal, this.#lifetime.signal]);
96476
96570
  const resolved = await this.#resolve(sessionId, request, active);
96477
- return resolved === null ? null : this.#scratch.read(resolved.path, active);
96571
+ if (resolved === null) {
96572
+ return null;
96573
+ }
96574
+ const bytes = await this.#scratch.read(resolved.path, active);
96575
+ return bytes === null ? null : { ...resolved, bytes };
96478
96576
  });
96479
96577
  [Symbol.asyncDispose] = async () => {
96480
96578
  clearInterval(this.#expirationTimer);
@@ -97445,7 +97543,7 @@ var init_agent_settings_adapter = __esm({
97445
97543
  });
97446
97544
 
97447
97545
  // src/engine/session/settings/discover-agent-settings.ts
97448
- import { createHash as createHash8 } from "node:crypto";
97546
+ import { createHash as createHash9 } from "node:crypto";
97449
97547
  function agentSettingsFailureDetails(agentId, failure2) {
97450
97548
  const details = { agentId, code: operationErrorCode(failure2) };
97451
97549
  return failure2 instanceof AcpConfigurationValueUnavailableError ? {
@@ -97710,7 +97808,7 @@ function settingsRevision(agent, reportedAgentVersion, settings, modelEffort) {
97710
97808
  unsupportedModelIds: modelEffort.unsupportedModelIds,
97711
97809
  valuesByModel: {}
97712
97810
  };
97713
- return createHash8("sha256").update(
97811
+ return createHash9("sha256").update(
97714
97812
  JSON.stringify({
97715
97813
  adapterVersion: agent.adapterVersion,
97716
97814
  agentId: agent.id,
@@ -97893,7 +97991,7 @@ var init_agent_settings = __esm({
97893
97991
  });
97894
97992
 
97895
97993
  // src/engine/runtime/command/registry/content-write/index.ts
97896
- import { createHash as createHash9 } from "node:crypto";
97994
+ import { createHash as createHash10 } from "node:crypto";
97897
97995
  function createContentWriteCommands(context) {
97898
97996
  const pending = /* @__PURE__ */ new Map();
97899
97997
  const operations = /* @__PURE__ */ new Set();
@@ -97923,7 +98021,7 @@ function createContentWriteCommands(context) {
97923
98021
  pending.set(message.requestId, {
97924
98022
  bytes: new Uint8Array(message.byteLength),
97925
98023
  command: message,
97926
- hash: createHash9("sha256"),
98024
+ hash: createHash10("sha256"),
97927
98025
  receivedBytes: 0,
97928
98026
  sequence: 0
97929
98027
  });
@@ -98021,7 +98119,7 @@ var init_content_write = __esm({
98021
98119
  });
98022
98120
 
98023
98121
  // src/engine/session/content/session-files.ts
98024
- import { basename as basename9, extname as extname3, isAbsolute as isAbsolute16, join as join32, normalize as normalize3, resolve as resolve17 } from "node:path";
98122
+ import { basename as basename9, extname as extname4, isAbsolute as isAbsolute16, join as join32, normalize as normalize3, resolve as resolve17 } from "node:path";
98025
98123
  import { fileURLToPath as fileURLToPath2 } from "node:url";
98026
98124
  function requestedPath(value) {
98027
98125
  if (value.includes("\0")) {
@@ -98077,7 +98175,7 @@ async function streamLocalFile(command, send2, sendChunk, signal, workingDirecto
98077
98175
  send2({
98078
98176
  byteLength: before.size,
98079
98177
  kind: FILE_BEGIN_KIND,
98080
- mediaType: external?.mediaType ?? raster?.mimeType ?? (extname3(target).toLowerCase() === ".svg" ? "image/svg+xml" : "application/octet-stream"),
98178
+ mediaType: external?.mediaType ?? raster?.mimeType ?? (extname4(target).toLowerCase() === ".svg" ? "image/svg+xml" : "application/octet-stream"),
98081
98179
  modifiedAt: before.modifiedAt.toISOString(),
98082
98180
  name: external?.name ?? (basename9(target) || "file"),
98083
98181
  requestId: command.requestId,
@@ -98860,75 +98958,6 @@ var init_apply_session_configuration = __esm({
98860
98958
  }
98861
98959
  });
98862
98960
 
98863
- // src/engine/session/prompt/prompt-artifacts.ts
98864
- import { createHash as createHash10 } from "node:crypto";
98865
- function isTextMediaType(mediaType) {
98866
- return mediaType.startsWith("text/") || mediaType === "application/json" || mediaType.endsWith("+json") || mediaType === "application/xml" || mediaType.endsWith("+xml");
98867
- }
98868
- async function resolvePromptArtifacts(read, attachments, signal) {
98869
- const images = [];
98870
- const resources = [];
98871
- for (const attachment of attachments) {
98872
- signal.throwIfAborted();
98873
- const bytes = await read(attachment, signal);
98874
- if (bytes.byteLength !== attachment.byteLength || createHash10("sha256").update(bytes).digest("hex") !== attachment.contentKey) {
98875
- throw new PromptArtifactError(
98876
- "artifact_integrity_failed",
98877
- "The prompt attachment failed integrity validation"
98878
- );
98879
- }
98880
- if (attachment.kind === "image") {
98881
- if (bytes.byteLength > PROMPT_IMAGE_MAX_BYTES || images.length >= 8) {
98882
- continue;
98883
- }
98884
- images.push({
98885
- data: Buffer.from(bytes).toString("base64"),
98886
- mimeType: attachment.mimeType,
98887
- name: attachment.name
98888
- });
98889
- continue;
98890
- }
98891
- if (!isTextMediaType(attachment.mimeType)) {
98892
- continue;
98893
- }
98894
- if (bytes.byteLength > MAX_AGENT_RESOURCE_BYTE_LENGTH || resources.length >= 16) {
98895
- continue;
98896
- }
98897
- let text2;
98898
- try {
98899
- text2 = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
98900
- } catch {
98901
- signal.throwIfAborted();
98902
- continue;
98903
- }
98904
- resources.push({ mimeType: attachment.mimeType, text: text2, type: "embedded", uri: attachment.uri });
98905
- }
98906
- return new ResolvedPromptArtifacts(images, resources);
98907
- }
98908
- var MAX_AGENT_RESOURCE_BYTE_LENGTH, PromptArtifactError, ResolvedPromptArtifacts;
98909
- var init_prompt_artifacts = __esm({
98910
- "src/engine/session/prompt/prompt-artifacts.ts"() {
98911
- "use strict";
98912
- init_protocol();
98913
- init_operation_error();
98914
- MAX_AGENT_RESOURCE_BYTE_LENGTH = 1e6;
98915
- PromptArtifactError = class extends OperationError {
98916
- constructor(code, message, options = {}) {
98917
- super(code, message, options);
98918
- this.name = "PromptArtifactError";
98919
- }
98920
- };
98921
- ResolvedPromptArtifacts = class {
98922
- images;
98923
- resources;
98924
- constructor(images, resources) {
98925
- this.images = images;
98926
- this.resources = resources;
98927
- }
98928
- };
98929
- }
98930
- });
98931
-
98932
98961
  // src/engine/session/prompt/execute-prompt.ts
98933
98962
  async function executePrompt({
98934
98963
  operations,
@@ -99158,16 +99187,16 @@ var init_prompt2 = __esm({
99158
99187
  eventProjection: context.eventProjection,
99159
99188
  command: message,
99160
99189
  resolveAgent: context.resolveAgent,
99161
- readArtifact: async (artifact, signal) => {
99162
- const bytes = await context.externalContent.read(
99190
+ readArtifact: async (attachment, signal) => {
99191
+ const artifact = await context.externalContent.read(
99163
99192
  message.sessionId,
99164
- `mobius-content:${artifact.kind}:${artifact.contentKey}`,
99193
+ `mobius-content:${attachment.kind}:${attachment.contentKey}`,
99165
99194
  signal
99166
99195
  );
99167
- if (bytes === null) {
99196
+ if (artifact === null) {
99168
99197
  throw new Error("The prompt attachment is unavailable");
99169
99198
  }
99170
- return bytes;
99199
+ return { bytes: artifact.bytes, path: artifact.path };
99171
99200
  },
99172
99201
  reportFailure: context.diagnostics.daemonDiagnostic,
99173
99202
  directories: context.directories,
@@ -99292,7 +99321,12 @@ async function prepareSession(command, recovery, closed, config2, resolveAgent,
99292
99321
  }
99293
99322
  async function executeWorkspaceList(socket, command, directories, signal) {
99294
99323
  try {
99295
- const listing = await directories.list(command.bindingId, command.directoryId, signal);
99324
+ const listing = command.view === "metadata" ? await directories.describe(command.bindingId, command.directoryId, signal).then((directory) => ({
99325
+ directoryId: command.directoryId,
99326
+ directoryLabel: directory.label,
99327
+ entries: [],
99328
+ parentDirectoryId: directory.parentDirectoryId
99329
+ })) : await directories.list(command.bindingId, command.directoryId, signal);
99296
99330
  send(socket, {
99297
99331
  bindingId: command.bindingId,
99298
99332
  directoryId: listing.directoryId,
@@ -100296,13 +100330,23 @@ var init_session_event_publisher = __esm({
100296
100330
  return;
100297
100331
  }
100298
100332
  if (batch === void 0 || newBatch) {
100299
- batch = { events: [], bytes: EMPTY_ENVELOPE_BYTES };
100333
+ batch = { events: [], firstAnswers: [], bytes: EMPTY_ENVELOPE_BYTES };
100300
100334
  this.#pending.push(batch);
100301
100335
  }
100302
100336
  batch.events.push(event);
100303
100337
  batch.bytes += bytes;
100304
100338
  this.#pendingBytes += additionalBytes;
100339
+ const awaiting = this.#awaitingFirstAnswer.get(event.sessionId);
100305
100340
  const firstAnswer = this.#consumeFirstAnswer(event);
100341
+ if (firstAnswer && awaiting !== void 0) {
100342
+ batch.firstAnswers.push({
100343
+ sessionId: event.sessionId,
100344
+ commandId: awaiting.commandId,
100345
+ eventId: event.eventId,
100346
+ observedAt: Date.now(),
100347
+ publishedAt: performance.now()
100348
+ });
100349
+ }
100306
100350
  const connection = this.#connection;
100307
100351
  if (connection.kind !== "connected" || connection.socket.readyState !== WebSocket9.OPEN) {
100308
100352
  return;
@@ -100357,6 +100401,19 @@ var init_session_event_publisher = __esm({
100357
100401
  this.#pendingBytes -= batch.bytes;
100358
100402
  try {
100359
100403
  socket.send(encoded);
100404
+ for (const answer of batch.firstAnswers) {
100405
+ console.info(
100406
+ JSON.stringify({
100407
+ event: "runtime-first-answer-handoff-timing",
100408
+ sessionId: answer.sessionId,
100409
+ commandId: answer.commandId,
100410
+ eventId: answer.eventId,
100411
+ observedAt: answer.observedAt,
100412
+ handedOffAt: Date.now(),
100413
+ publishToHandoffMs: performance.now() - answer.publishedAt
100414
+ })
100415
+ );
100416
+ }
100360
100417
  } catch {
100361
100418
  console.warn("Live Session output could not be sent", { code: "live_event_send_failed" });
100362
100419
  break;