@moxt-ai/mobius 0.0.21 → 0.0.22

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/bots/bot-context-applicator.d.ts +14 -0
  2. package/dist/bots/bot-context-applicator.d.ts.map +1 -0
  3. package/dist/bots/bot-context-applicator.js +32 -0
  4. package/dist/bots/bot-context-applicator.js.map +1 -0
  5. package/dist/bots/bot-execution-context.d.ts +20 -0
  6. package/dist/bots/bot-execution-context.d.ts.map +1 -0
  7. package/dist/bots/bot-execution-context.js +82 -0
  8. package/dist/bots/bot-execution-context.js.map +1 -0
  9. package/dist/bots/bot-message-command.d.ts +6 -0
  10. package/dist/bots/bot-message-command.d.ts.map +1 -0
  11. package/dist/bots/bot-message-command.js +140 -0
  12. package/dist/bots/bot-message-command.js.map +1 -0
  13. package/dist/bots/bot-outbound-ipc.d.ts +12 -0
  14. package/dist/bots/bot-outbound-ipc.d.ts.map +1 -0
  15. package/dist/bots/bot-outbound-ipc.js +245 -0
  16. package/dist/bots/bot-outbound-ipc.js.map +1 -0
  17. package/dist/bots/local-bot-grant-store.d.ts +34 -0
  18. package/dist/bots/local-bot-grant-store.d.ts.map +1 -0
  19. package/dist/bots/local-bot-grant-store.js +263 -0
  20. package/dist/bots/local-bot-grant-store.js.map +1 -0
  21. package/dist/cli.js +1864 -213
  22. package/dist/cli.js.map +4 -4
  23. package/dist/index.d.ts +3 -0
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +1922 -280
  26. package/dist/index.js.map +4 -4
  27. package/dist/prompt-artifact-resolver.d.ts +8 -2
  28. package/dist/prompt-artifact-resolver.d.ts.map +1 -1
  29. package/dist/prompt-artifact-resolver.js.map +1 -1
  30. package/dist/run-daemon.d.ts.map +1 -1
  31. package/dist/run-daemon.js +231 -8
  32. package/dist/run-daemon.js.map +1 -1
  33. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -6,12 +6,12 @@ var __export = (target, all) => {
6
6
  };
7
7
 
8
8
  // src/cli.ts
9
- import { mkdir as mkdir4 } from "node:fs/promises";
9
+ import { mkdir as mkdir5 } from "node:fs/promises";
10
10
 
11
11
  // package.json
12
12
  var package_default = {
13
13
  name: "@moxt-ai/mobius",
14
- version: "0.0.21",
14
+ version: "0.0.22",
15
15
  description: "Mobius CLI for pairing and running local AI agent services.",
16
16
  type: "module",
17
17
  bin: {
@@ -1616,7 +1616,7 @@ function isContainedPath3(root, candidate) {
1616
1616
  }
1617
1617
  async function hashFile(path2, signal) {
1618
1618
  signal.throwIfAborted();
1619
- const digest = createHash("sha256");
1619
+ const digest2 = createHash("sha256");
1620
1620
  const stream = createReadStream(path2, { signal });
1621
1621
  try {
1622
1622
  for await (const chunk of stream) {
@@ -1627,9 +1627,9 @@ async function hashFile(path2, signal) {
1627
1627
  "The managed Agent archive produced invalid bytes"
1628
1628
  );
1629
1629
  }
1630
- digest.update(chunk);
1630
+ digest2.update(chunk);
1631
1631
  }
1632
- return digest.digest("hex");
1632
+ return digest2.digest("hex");
1633
1633
  } catch (error61) {
1634
1634
  if (signal.aborted) {
1635
1635
  signal.throwIfAborted();
@@ -2611,6 +2611,164 @@ var AuditStore = class {
2611
2611
  }
2612
2612
  };
2613
2613
 
2614
+ // src/bots/bot-message-command.ts
2615
+ import { randomUUID } from "node:crypto";
2616
+ import { createConnection } from "node:net";
2617
+ var BOT_IPC_RESPONSE_LIMIT = 64 * 1024;
2618
+ var BOT_IPC_TIMEOUT_MILLISECONDS = 2e4;
2619
+ var BotMessageCommandError = class extends Error {
2620
+ code;
2621
+ constructor(code, message, options = {}) {
2622
+ super(message, options);
2623
+ this.code = code;
2624
+ this.name = "BotMessageCommandError";
2625
+ }
2626
+ };
2627
+ function isRecord3(value) {
2628
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2629
+ }
2630
+ function requiredEnvironment(environment, name) {
2631
+ const value = environment[name]?.trim();
2632
+ if (value === void 0 || value.length === 0) {
2633
+ throw new BotMessageCommandError(
2634
+ "execution_context_required",
2635
+ "This command is available only inside an active Mobius Bot execution"
2636
+ );
2637
+ }
2638
+ return value;
2639
+ }
2640
+ function option(arguments_, name) {
2641
+ const index = arguments_.indexOf(name);
2642
+ if (index < 0 || index + 1 >= arguments_.length || arguments_[index + 1]?.startsWith("--") === true) {
2643
+ throw new BotMessageCommandError(
2644
+ "invalid_request",
2645
+ "Usage: mobius bot message send --target <current|alias> --text <message>"
2646
+ );
2647
+ }
2648
+ const value = arguments_[index + 1];
2649
+ if (value === void 0) {
2650
+ throw new BotMessageCommandError("invalid_request", "The Bot message option is missing");
2651
+ }
2652
+ return value;
2653
+ }
2654
+ function validateArguments(arguments_) {
2655
+ if (arguments_.length !== 4) {
2656
+ throw new BotMessageCommandError(
2657
+ "invalid_request",
2658
+ "Usage: mobius bot message send --target <current|alias> --text <message>"
2659
+ );
2660
+ }
2661
+ const names = [arguments_[0], arguments_[2]];
2662
+ if (!names.includes("--target") || !names.includes("--text") || names[0] === names[1]) {
2663
+ throw new BotMessageCommandError(
2664
+ "invalid_request",
2665
+ "Usage: mobius bot message send --target <current|alias> --text <message>"
2666
+ );
2667
+ }
2668
+ }
2669
+ function decodeResponse(encoded) {
2670
+ let value;
2671
+ try {
2672
+ value = JSON.parse(encoded);
2673
+ } catch (cause) {
2674
+ throw new BotMessageCommandError("bot_service_unavailable", "The local Bot service returned invalid data", {
2675
+ cause
2676
+ });
2677
+ }
2678
+ if (!isRecord3(value) || typeof value["ok"] !== "boolean") {
2679
+ throw new BotMessageCommandError("bot_service_unavailable", "The local Bot service returned invalid data");
2680
+ }
2681
+ if (value["ok"] === true && typeof value["outboundMessageId"] === "string") {
2682
+ return value["outboundMessageId"];
2683
+ }
2684
+ const error61 = value["error"];
2685
+ if (value["ok"] === false && isRecord3(error61) && typeof error61["code"] === "string" && typeof error61["message"] === "string") {
2686
+ throw new BotMessageCommandError(error61["code"], error61["message"]);
2687
+ }
2688
+ throw new BotMessageCommandError("bot_service_unavailable", "The local Bot service returned invalid data");
2689
+ }
2690
+ async function requestLocalBotService(socketPath, payload, signal) {
2691
+ signal.throwIfAborted();
2692
+ return await new Promise((resolve5, reject) => {
2693
+ const socket = createConnection(socketPath);
2694
+ const chunks = [];
2695
+ let length = 0;
2696
+ let finished = false;
2697
+ const finish = () => {
2698
+ socket.removeAllListeners();
2699
+ socket.destroy();
2700
+ };
2701
+ const fail = (error61) => {
2702
+ if (finished) {
2703
+ return;
2704
+ }
2705
+ finished = true;
2706
+ finish();
2707
+ if (error61 instanceof BotMessageCommandError) {
2708
+ reject(error61);
2709
+ return;
2710
+ }
2711
+ reject(
2712
+ new BotMessageCommandError(
2713
+ "execution_context_required",
2714
+ "The active Mobius Bot execution is unavailable",
2715
+ { cause: error61 }
2716
+ )
2717
+ );
2718
+ };
2719
+ const abort = () => fail(signal.reason);
2720
+ socket.setTimeout(BOT_IPC_TIMEOUT_MILLISECONDS, () => {
2721
+ fail(new BotMessageCommandError("bot_service_unavailable", "The local Bot service timed out"));
2722
+ });
2723
+ socket.once("error", fail);
2724
+ socket.once("connect", () => socket.end(`${payload}
2725
+ `));
2726
+ socket.on("data", (chunk) => {
2727
+ length += chunk.byteLength;
2728
+ if (length > BOT_IPC_RESPONSE_LIMIT) {
2729
+ fail(new BotMessageCommandError("bot_service_unavailable", "The local Bot response is too large"));
2730
+ return;
2731
+ }
2732
+ chunks.push(chunk);
2733
+ });
2734
+ socket.once("end", () => {
2735
+ if (finished) {
2736
+ return;
2737
+ }
2738
+ finished = true;
2739
+ signal.removeEventListener("abort", abort);
2740
+ try {
2741
+ resolve5(decodeResponse(Buffer.concat(chunks).toString("utf8")));
2742
+ } catch (error61) {
2743
+ reject(error61);
2744
+ } finally {
2745
+ finish();
2746
+ }
2747
+ });
2748
+ signal.addEventListener("abort", abort, { once: true });
2749
+ });
2750
+ }
2751
+ async function executeBotMessageCommand(arguments_, environment, signal) {
2752
+ validateArguments(arguments_);
2753
+ const contextHandle = requiredEnvironment(environment, "MOBIUS_BOT_CONTEXT");
2754
+ const socketPath = requiredEnvironment(environment, "MOBIUS_BOT_SOCKET");
2755
+ const target = option(arguments_, "--target");
2756
+ const text = option(arguments_, "--text");
2757
+ if (!/^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/.test(target) || text.trim().length === 0 || text.length > 1e4) {
2758
+ throw new BotMessageCommandError("invalid_request", "The Bot outbound message is invalid");
2759
+ }
2760
+ return await requestLocalBotService(
2761
+ socketPath,
2762
+ JSON.stringify({
2763
+ contextHandle,
2764
+ idempotencyKey: `cli_${randomUUID()}`,
2765
+ target,
2766
+ text
2767
+ }),
2768
+ signal
2769
+ );
2770
+ }
2771
+
2614
2772
  // src/config.ts
2615
2773
  import { join as join13 } from "node:path";
2616
2774
 
@@ -6287,7 +6445,7 @@ var $ZodUnion = /* @__PURE__ */ $constructor("$ZodUnion", (inst, def) => {
6287
6445
  defineLazyInternal(inst, "optout", (zod) => zod.def.options.some((o) => o._zod.optout === "optional") ? "optional" : void 0);
6288
6446
  defineLazyInternal(inst, "values", (zod) => {
6289
6447
  if (zod.def.options.every((o) => o._zod.values)) {
6290
- return new Set(zod.def.options.flatMap((option) => Array.from(option._zod.values)));
6448
+ return new Set(zod.def.options.flatMap((option2) => Array.from(option2._zod.values)));
6291
6449
  }
6292
6450
  return void 0;
6293
6451
  });
@@ -6305,8 +6463,8 @@ var $ZodUnion = /* @__PURE__ */ $constructor("$ZodUnion", (inst, def) => {
6305
6463
  }
6306
6464
  let async = false;
6307
6465
  const results = [];
6308
- for (const option of def.options) {
6309
- const result = option._zod.run({
6466
+ for (const option2 of def.options) {
6467
+ const result = option2._zod.run({
6310
6468
  value: payload.value,
6311
6469
  issues: []
6312
6470
  }, ctx);
@@ -6365,8 +6523,8 @@ var $ZodXor = /* @__PURE__ */ $constructor("$ZodXor", (inst, def) => {
6365
6523
  }
6366
6524
  let async = false;
6367
6525
  const results = [];
6368
- for (const option of def.options) {
6369
- const result = option._zod.run({
6526
+ for (const option2 of def.options) {
6527
+ const result = option2._zod.run({
6370
6528
  value: payload.value,
6371
6529
  issues: []
6372
6530
  }, ctx);
@@ -6390,10 +6548,10 @@ function getDiscriminatedOption(union2, value) {
6390
6548
  if (!map2) {
6391
6549
  map2 = /* @__PURE__ */ new Map();
6392
6550
  const { options, discriminator } = internals.def;
6393
- for (const option of options) {
6394
- for (const v of option._zod.propValues?.[discriminator] ?? [])
6551
+ for (const option2 of options) {
6552
+ for (const v of option2._zod.propValues?.[discriminator] ?? [])
6395
6553
  if (!map2.has(v))
6396
- map2.set(v, option);
6554
+ map2.set(v, option2);
6397
6555
  }
6398
6556
  internals.bag.optionsMap = map2;
6399
6557
  }
@@ -6405,10 +6563,10 @@ var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnio
6405
6563
  const _super = inst._zod.parse;
6406
6564
  defineLazyInternal(inst, "propValues", (zod) => {
6407
6565
  const propValues = {};
6408
- for (const option of zod.def.options) {
6409
- const pv = option._zod.propValues;
6566
+ for (const option2 of zod.def.options) {
6567
+ const pv = option2._zod.propValues;
6410
6568
  if (!pv || Object.keys(pv).length === 0)
6411
- throw new Error(`Invalid discriminated union option at index "${zod.def.options.indexOf(option)}"`);
6569
+ throw new Error(`Invalid discriminated union option at index "${zod.def.options.indexOf(option2)}"`);
6412
6570
  for (const [k, v] of Object.entries(pv)) {
6413
6571
  if (!Object.prototype.hasOwnProperty.call(propValues, k)) {
6414
6572
  assignProp(propValues, k, /* @__PURE__ */ new Set());
@@ -6420,8 +6578,8 @@ var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnio
6420
6578
  }
6421
6579
  return propValues;
6422
6580
  });
6423
- def.options.forEach((option, i) => {
6424
- const propShape = propShapes.get(option._zod.def);
6581
+ def.options.forEach((option2, i) => {
6582
+ const propShape = propShapes.get(option2._zod.def);
6425
6583
  if (propShape && !Object.prototype.hasOwnProperty.call(propShape, def.discriminator)) {
6426
6584
  throw new Error(`Invalid discriminated union option at index "${i}"`);
6427
6585
  }
@@ -16352,8 +16510,8 @@ function generateDiscriminatedUnionCheck(doc, ctx, def, accessor) {
16352
16510
  doc.write(`let ${outputVar};`);
16353
16511
  let firstBranch = true;
16354
16512
  const claimed = /* @__PURE__ */ new Set();
16355
- for (const option of def.options) {
16356
- const values = option._zod.propValues?.[def.discriminator];
16513
+ for (const option2 of def.options) {
16514
+ const values = option2._zod.propValues?.[def.discriminator];
16357
16515
  if (!values || values.size === 0) {
16358
16516
  throw new ZodCompileUnsupportedError("discriminated union option without static discriminator values");
16359
16517
  }
@@ -16367,7 +16525,7 @@ function generateDiscriminatedUnionCheck(doc, ctx, def, accessor) {
16367
16525
  const prefix = firstBranch ? "if" : "else if";
16368
16526
  doc.write(`${prefix} (${conditions.join(" || ")}) {`);
16369
16527
  doc.indented((d) => {
16370
- const branchOutput = generateCheck(d, ctx, option, accessor);
16528
+ const branchOutput = generateCheck(d, ctx, option2, accessor);
16371
16529
  d.write(`${outputVar} = ${branchOutput};`);
16372
16530
  });
16373
16531
  doc.write(`}`);
@@ -17917,14 +18075,14 @@ function compactTypeUnion(schema) {
17917
18075
  if (!Array.isArray(options) || options.length === 0 || schema.type !== void 0)
17918
18076
  return;
17919
18077
  const types = [];
17920
- for (const option of options) {
17921
- if (!option || typeof option !== "object")
18078
+ for (const option2 of options) {
18079
+ if (!option2 || typeof option2 !== "object")
17922
18080
  return;
17923
- compactTypeUnion(option);
17924
- const keys = Object.keys(option);
18081
+ compactTypeUnion(option2);
18082
+ const keys = Object.keys(option2);
17925
18083
  if (keys.length !== 1 || keys[0] !== "type")
17926
18084
  return;
17927
- const type = option.type;
18085
+ const type = option2.type;
17928
18086
  for (const member of Array.isArray(type) ? type : [type]) {
17929
18087
  if (typeof member !== "string")
17930
18088
  return;
@@ -18214,8 +18372,8 @@ function isTransforming(_schema, _ctx) {
18214
18372
  return false;
18215
18373
  }
18216
18374
  if (def.type === "union") {
18217
- for (const option of def.options) {
18218
- if (isTransforming(option, ctx))
18375
+ for (const option2 of def.options) {
18376
+ if (isTransforming(option2, ctx))
18219
18377
  return true;
18220
18378
  }
18221
18379
  return false;
@@ -21956,7 +22114,7 @@ var ProtocolMessageError = class extends Error {
21956
22114
  this.name = "ProtocolMessageError";
21957
22115
  }
21958
22116
  };
21959
- function isRecord3(value) {
22117
+ function isRecord4(value) {
21960
22118
  return typeof value === "object" && value !== null && !Array.isArray(value);
21961
22119
  }
21962
22120
  function parseJson2(encoded) {
@@ -21968,7 +22126,7 @@ function parseJson2(encoded) {
21968
22126
  cause: error61
21969
22127
  });
21970
22128
  }
21971
- if (!isRecord3(value)) {
22129
+ if (!isRecord4(value)) {
21972
22130
  throw new ProtocolMessageError("Message must be a JSON object");
21973
22131
  }
21974
22132
  return value;
@@ -22052,7 +22210,7 @@ function readActivityContent(value) {
22052
22210
  }
22053
22211
  function readActivityDetail(value) {
22054
22212
  const field = value["detail"];
22055
- if (!isRecord3(field)) {
22213
+ if (!isRecord4(field)) {
22056
22214
  throw new ProtocolMessageError("Invalid activity detail field");
22057
22215
  }
22058
22216
  const kind = readString(field, "kind", 32);
@@ -22291,6 +22449,487 @@ function encodeSessionFailedEvent(message) {
22291
22449
  return JSON.stringify(decodeSessionFailedEvent(JSON.stringify(message)));
22292
22450
  }
22293
22451
 
22452
+ // ../protocol/src/bot.ts
22453
+ var BOT_BINDING_APPROVAL_REQUEST_KIND = "bot.binding.approval.request";
22454
+ var BOT_BINDING_APPROVED_KIND = "bot.binding.approved";
22455
+ var BOT_BINDING_UNAVAILABLE_KIND = "bot.binding.unavailable";
22456
+ var BOT_SESSION_PROMPT_KIND = "bot.session.prompt";
22457
+ var IDENTIFIER_PATTERN3 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
22458
+ var DIRECTORY_IDENTIFIER_PATTERN3 = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,2047}$/;
22459
+ var TOKEN_PATTERN = /^[a-zA-Z0-9_-]{32,256}$/;
22460
+ var SHA256_PATTERN = /^[a-f0-9]{64}$/;
22461
+ var MAX_INSTRUCTIONS_LENGTH = 1e5;
22462
+ var BotDeliveryTargetReference = class {
22463
+ alias;
22464
+ deliveryTargetId;
22465
+ constructor(alias, deliveryTargetId) {
22466
+ this.alias = alias;
22467
+ this.deliveryTargetId = deliveryTargetId;
22468
+ }
22469
+ };
22470
+ var BotCompletionDeliveryPolicy = class {
22471
+ };
22472
+ var NoBotCompletionDeliveryPolicy = class extends BotCompletionDeliveryPolicy {
22473
+ kind = "none";
22474
+ };
22475
+ var RequiredBotCompletionDeliveryPolicy = class extends BotCompletionDeliveryPolicy {
22476
+ deliveryTargetId;
22477
+ kind = "required";
22478
+ messageTemplate;
22479
+ constructor(deliveryTargetId, messageTemplate) {
22480
+ super();
22481
+ this.deliveryTargetId = deliveryTargetId;
22482
+ this.messageTemplate = messageTemplate;
22483
+ }
22484
+ };
22485
+ var BotReplyRoute = class {
22486
+ };
22487
+ var OwnerBotReplyRoute = class extends BotReplyRoute {
22488
+ kind = "owner";
22489
+ };
22490
+ var BotConnectionReplyRoute = class extends BotReplyRoute {
22491
+ connectionId;
22492
+ deliveryTargetId;
22493
+ kind = "connection";
22494
+ constructor(connectionId, deliveryTargetId) {
22495
+ super();
22496
+ this.connectionId = connectionId;
22497
+ this.deliveryTargetId = deliveryTargetId;
22498
+ }
22499
+ };
22500
+ var BotExecutionBindingApprovalRequest = class {
22501
+ agentConfigRevision;
22502
+ agentRef;
22503
+ allowedDeliveryTargets;
22504
+ behaviorDigest;
22505
+ behaviorInstructions;
22506
+ behaviorRevisionId;
22507
+ bindingId;
22508
+ bindingRevision;
22509
+ botId;
22510
+ completionPolicy;
22511
+ kind = BOT_BINDING_APPROVAL_REQUEST_KIND;
22512
+ requestId;
22513
+ requiredCapabilities;
22514
+ runtimeId;
22515
+ workspaceRef;
22516
+ constructor(requestId, botId, behaviorRevisionId, bindingId, bindingRevision, runtimeId, agentRef, workspaceRef, agentConfigRevision, behaviorInstructions, behaviorDigest, requiredCapabilities, allowedDeliveryTargets, completionPolicy) {
22517
+ this.requestId = requestId;
22518
+ this.botId = botId;
22519
+ this.behaviorRevisionId = behaviorRevisionId;
22520
+ this.bindingId = bindingId;
22521
+ this.bindingRevision = bindingRevision;
22522
+ this.runtimeId = runtimeId;
22523
+ this.agentRef = agentRef;
22524
+ this.workspaceRef = workspaceRef;
22525
+ this.agentConfigRevision = agentConfigRevision;
22526
+ this.behaviorInstructions = behaviorInstructions;
22527
+ this.behaviorDigest = behaviorDigest;
22528
+ this.requiredCapabilities = Object.freeze([...requiredCapabilities]);
22529
+ this.allowedDeliveryTargets = Object.freeze(
22530
+ allowedDeliveryTargets.map(
22531
+ (target) => new BotDeliveryTargetReference(target.alias, target.deliveryTargetId)
22532
+ )
22533
+ );
22534
+ this.completionPolicy = completionPolicy;
22535
+ }
22536
+ };
22537
+ var BotExecutionBindingApprovedEvent = class {
22538
+ agentIdentityDigest;
22539
+ behaviorRevisionId;
22540
+ bindingId;
22541
+ bindingRevision;
22542
+ botId;
22543
+ kind = BOT_BINDING_APPROVED_KIND;
22544
+ localGrantId;
22545
+ requestId;
22546
+ workspaceIdentityDigest;
22547
+ constructor(requestId, botId, behaviorRevisionId, bindingId, bindingRevision, localGrantId, agentIdentityDigest, workspaceIdentityDigest) {
22548
+ this.requestId = requestId;
22549
+ this.botId = botId;
22550
+ this.behaviorRevisionId = behaviorRevisionId;
22551
+ this.bindingId = bindingId;
22552
+ this.bindingRevision = bindingRevision;
22553
+ this.localGrantId = localGrantId;
22554
+ this.agentIdentityDigest = agentIdentityDigest;
22555
+ this.workspaceIdentityDigest = workspaceIdentityDigest;
22556
+ }
22557
+ };
22558
+ var BotExecutionBindingUnavailableEvent = class {
22559
+ behaviorRevisionId;
22560
+ bindingId;
22561
+ bindingRevision;
22562
+ botId;
22563
+ code;
22564
+ kind = BOT_BINDING_UNAVAILABLE_KIND;
22565
+ message;
22566
+ requestId;
22567
+ constructor(requestId, botId, behaviorRevisionId, bindingId, bindingRevision, code, message) {
22568
+ this.requestId = requestId;
22569
+ this.botId = botId;
22570
+ this.behaviorRevisionId = behaviorRevisionId;
22571
+ this.bindingId = bindingId;
22572
+ this.bindingRevision = bindingRevision;
22573
+ this.code = code;
22574
+ this.message = message;
22575
+ }
22576
+ };
22577
+ var BotSessionPromptCommand = class {
22578
+ additionalDirectoryIds;
22579
+ agentId;
22580
+ allowedDeliveryTargets;
22581
+ behaviorDigest;
22582
+ behaviorInstructions;
22583
+ behaviorRevisionId;
22584
+ bindingId;
22585
+ bindingRevision;
22586
+ botId;
22587
+ commandId;
22588
+ conversationId;
22589
+ directoryId;
22590
+ executionCapabilityId;
22591
+ executionCapabilitySecret;
22592
+ executionDeadlineAt;
22593
+ executionId;
22594
+ images;
22595
+ kind = BOT_SESSION_PROMPT_KIND;
22596
+ localGrantId;
22597
+ prompt;
22598
+ replyRoute;
22599
+ resources;
22600
+ sessionId;
22601
+ turnId;
22602
+ constructor(sessionId, commandId, agentId, bindingId, directoryId2, additionalDirectoryIds, images, resources, prompt, executionId, executionCapabilityId, executionCapabilitySecret, executionDeadlineAt, botId, conversationId, turnId, behaviorRevisionId, bindingRevision, localGrantId, behaviorInstructions, behaviorDigest, allowedDeliveryTargets, replyRoute) {
22603
+ this.sessionId = sessionId;
22604
+ this.commandId = commandId;
22605
+ this.agentId = agentId;
22606
+ this.bindingId = bindingId;
22607
+ this.directoryId = directoryId2;
22608
+ this.additionalDirectoryIds = Object.freeze([...additionalDirectoryIds]);
22609
+ this.images = Object.freeze([...images]);
22610
+ this.resources = Object.freeze([...resources]);
22611
+ this.prompt = prompt;
22612
+ this.executionId = executionId;
22613
+ this.executionCapabilityId = executionCapabilityId;
22614
+ this.executionCapabilitySecret = executionCapabilitySecret;
22615
+ this.executionDeadlineAt = executionDeadlineAt;
22616
+ this.botId = botId;
22617
+ this.conversationId = conversationId;
22618
+ this.turnId = turnId;
22619
+ this.behaviorRevisionId = behaviorRevisionId;
22620
+ this.bindingRevision = bindingRevision;
22621
+ this.localGrantId = localGrantId;
22622
+ this.behaviorInstructions = behaviorInstructions;
22623
+ this.behaviorDigest = behaviorDigest;
22624
+ this.allowedDeliveryTargets = Object.freeze(
22625
+ allowedDeliveryTargets.map(
22626
+ (target) => new BotDeliveryTargetReference(target.alias, target.deliveryTargetId)
22627
+ )
22628
+ );
22629
+ this.replyRoute = replyRoute;
22630
+ }
22631
+ };
22632
+ function isRecord5(value) {
22633
+ return typeof value === "object" && value !== null && !Array.isArray(value);
22634
+ }
22635
+ function parseJson3(encoded) {
22636
+ let value;
22637
+ try {
22638
+ value = JSON.parse(encoded);
22639
+ } catch (cause) {
22640
+ throw new ProtocolMessageError("Message is not valid JSON", { cause });
22641
+ }
22642
+ if (!isRecord5(value)) {
22643
+ throw new ProtocolMessageError("Message must be a JSON object");
22644
+ }
22645
+ return value;
22646
+ }
22647
+ function assertExactKeys2(value, expected) {
22648
+ const keys = Object.keys(value);
22649
+ if (keys.length !== expected.length || keys.some((key) => !expected.includes(key))) {
22650
+ throw new ProtocolMessageError("Message fields do not match the Bot protocol");
22651
+ }
22652
+ }
22653
+ function readText2(value, key, maximumLength, allowEmpty) {
22654
+ const field = value[key];
22655
+ if (typeof field !== "string" || field.length > maximumLength || !allowEmpty && field.length === 0) {
22656
+ throw new ProtocolMessageError(`Invalid Bot protocol field: ${key}`);
22657
+ }
22658
+ return field;
22659
+ }
22660
+ function readIdentifier2(value, key) {
22661
+ const field = readText2(value, key, 128, false);
22662
+ if (!IDENTIFIER_PATTERN3.test(field)) {
22663
+ throw new ProtocolMessageError(`Invalid Bot identifier field: ${key}`);
22664
+ }
22665
+ return field;
22666
+ }
22667
+ function readDirectoryIdentifier2(value, key) {
22668
+ const field = readText2(value, key, 2048, false);
22669
+ if (!DIRECTORY_IDENTIFIER_PATTERN3.test(field)) {
22670
+ throw new ProtocolMessageError(`Invalid Bot directory field: ${key}`);
22671
+ }
22672
+ return field;
22673
+ }
22674
+ function readInteger(value, key) {
22675
+ const field = value[key];
22676
+ if (typeof field !== "number" || !Number.isSafeInteger(field) || field < 1) {
22677
+ throw new ProtocolMessageError(`Invalid Bot integer field: ${key}`);
22678
+ }
22679
+ return field;
22680
+ }
22681
+ function readTimestamp(value, key) {
22682
+ const field = readText2(value, key, 64, false);
22683
+ if (Number.isNaN(Date.parse(field))) {
22684
+ throw new ProtocolMessageError(`Invalid Bot timestamp field: ${key}`);
22685
+ }
22686
+ return field;
22687
+ }
22688
+ function readDigest(value, key) {
22689
+ const field = readText2(value, key, 64, false);
22690
+ if (!SHA256_PATTERN.test(field)) {
22691
+ throw new ProtocolMessageError(`Invalid Bot digest field: ${key}`);
22692
+ }
22693
+ return field;
22694
+ }
22695
+ function readToken(value, key) {
22696
+ const field = readText2(value, key, 256, false);
22697
+ if (!TOKEN_PATTERN.test(field)) {
22698
+ throw new ProtocolMessageError(`Invalid Bot token field: ${key}`);
22699
+ }
22700
+ return field;
22701
+ }
22702
+ function readIdentifiers(value, key, maximumCount) {
22703
+ const field = value[key];
22704
+ if (!Array.isArray(field) || field.length > maximumCount) {
22705
+ throw new ProtocolMessageError(`Invalid Bot identifier list: ${key}`);
22706
+ }
22707
+ const identifiers = [];
22708
+ const unique = /* @__PURE__ */ new Set();
22709
+ for (const candidate of field) {
22710
+ if (typeof candidate !== "string" || !IDENTIFIER_PATTERN3.test(candidate) || unique.has(candidate)) {
22711
+ throw new ProtocolMessageError(`Invalid Bot identifier list: ${key}`);
22712
+ }
22713
+ unique.add(candidate);
22714
+ identifiers.push(candidate);
22715
+ }
22716
+ return Object.freeze(identifiers);
22717
+ }
22718
+ function readTargets(value, key) {
22719
+ const field = value[key];
22720
+ if (!Array.isArray(field) || field.length > 64) {
22721
+ throw new ProtocolMessageError(`Invalid Bot delivery targets: ${key}`);
22722
+ }
22723
+ const targets = [];
22724
+ const identifiers = /* @__PURE__ */ new Set();
22725
+ const aliases = /* @__PURE__ */ new Set();
22726
+ for (const candidate of field) {
22727
+ if (!isRecord5(candidate)) {
22728
+ throw new ProtocolMessageError(`Invalid Bot delivery targets: ${key}`);
22729
+ }
22730
+ assertExactKeys2(candidate, ["alias", "deliveryTargetId"]);
22731
+ const alias = readIdentifier2(candidate, "alias");
22732
+ const deliveryTargetId = readIdentifier2(candidate, "deliveryTargetId");
22733
+ if (aliases.has(alias) || identifiers.has(deliveryTargetId)) {
22734
+ throw new ProtocolMessageError(`Duplicate Bot delivery target: ${key}`);
22735
+ }
22736
+ aliases.add(alias);
22737
+ identifiers.add(deliveryTargetId);
22738
+ targets.push(new BotDeliveryTargetReference(alias, deliveryTargetId));
22739
+ }
22740
+ return Object.freeze(targets);
22741
+ }
22742
+ function readCompletionPolicy(value) {
22743
+ if (!isRecord5(value)) {
22744
+ throw new ProtocolMessageError("Invalid Bot completion policy");
22745
+ }
22746
+ const kind = readText2(value, "kind", 32, false);
22747
+ if (kind === "none") {
22748
+ assertExactKeys2(value, ["kind"]);
22749
+ return new NoBotCompletionDeliveryPolicy();
22750
+ }
22751
+ if (kind === "required") {
22752
+ assertExactKeys2(value, ["deliveryTargetId", "kind", "messageTemplate"]);
22753
+ return new RequiredBotCompletionDeliveryPolicy(
22754
+ readIdentifier2(value, "deliveryTargetId"),
22755
+ readText2(value, "messageTemplate", 1e4, false)
22756
+ );
22757
+ }
22758
+ throw new ProtocolMessageError("Invalid Bot completion policy");
22759
+ }
22760
+ function readReplyRoute(value) {
22761
+ if (!isRecord5(value)) {
22762
+ throw new ProtocolMessageError("Invalid Bot reply route");
22763
+ }
22764
+ const kind = readText2(value, "kind", 32, false);
22765
+ if (kind === "owner") {
22766
+ assertExactKeys2(value, ["kind"]);
22767
+ return new OwnerBotReplyRoute();
22768
+ }
22769
+ if (kind === "connection") {
22770
+ assertExactKeys2(value, ["connectionId", "deliveryTargetId", "kind"]);
22771
+ return new BotConnectionReplyRoute(
22772
+ readIdentifier2(value, "connectionId"),
22773
+ readIdentifier2(value, "deliveryTargetId")
22774
+ );
22775
+ }
22776
+ throw new ProtocolMessageError("Invalid Bot reply route");
22777
+ }
22778
+ function decodeBotExecutionBindingApprovalRequest(encoded) {
22779
+ const value = parseJson3(encoded);
22780
+ assertExactKeys2(value, [
22781
+ "agentConfigRevision",
22782
+ "agentRef",
22783
+ "allowedDeliveryTargets",
22784
+ "behaviorDigest",
22785
+ "behaviorInstructions",
22786
+ "behaviorRevisionId",
22787
+ "bindingId",
22788
+ "bindingRevision",
22789
+ "botId",
22790
+ "completionPolicy",
22791
+ "kind",
22792
+ "requestId",
22793
+ "requiredCapabilities",
22794
+ "runtimeId",
22795
+ "workspaceRef"
22796
+ ]);
22797
+ if (value["kind"] !== BOT_BINDING_APPROVAL_REQUEST_KIND) {
22798
+ throw new ProtocolMessageError("Invalid Bot binding approval request kind");
22799
+ }
22800
+ return new BotExecutionBindingApprovalRequest(
22801
+ readIdentifier2(value, "requestId"),
22802
+ readIdentifier2(value, "botId"),
22803
+ readIdentifier2(value, "behaviorRevisionId"),
22804
+ readIdentifier2(value, "bindingId"),
22805
+ readInteger(value, "bindingRevision"),
22806
+ readIdentifier2(value, "runtimeId"),
22807
+ readIdentifier2(value, "agentRef"),
22808
+ readDirectoryIdentifier2(value, "workspaceRef"),
22809
+ readInteger(value, "agentConfigRevision"),
22810
+ readText2(value, "behaviorInstructions", MAX_INSTRUCTIONS_LENGTH, true),
22811
+ readDigest(value, "behaviorDigest"),
22812
+ readIdentifiers(value, "requiredCapabilities", 32),
22813
+ readTargets(value, "allowedDeliveryTargets"),
22814
+ readCompletionPolicy(value["completionPolicy"])
22815
+ );
22816
+ }
22817
+ function decodeBotExecutionBindingApprovedEvent(encoded) {
22818
+ const value = parseJson3(encoded);
22819
+ assertExactKeys2(value, [
22820
+ "agentIdentityDigest",
22821
+ "behaviorRevisionId",
22822
+ "bindingId",
22823
+ "bindingRevision",
22824
+ "botId",
22825
+ "kind",
22826
+ "localGrantId",
22827
+ "requestId",
22828
+ "workspaceIdentityDigest"
22829
+ ]);
22830
+ if (value["kind"] !== BOT_BINDING_APPROVED_KIND) {
22831
+ throw new ProtocolMessageError("Invalid Bot binding approval event kind");
22832
+ }
22833
+ return new BotExecutionBindingApprovedEvent(
22834
+ readIdentifier2(value, "requestId"),
22835
+ readIdentifier2(value, "botId"),
22836
+ readIdentifier2(value, "behaviorRevisionId"),
22837
+ readIdentifier2(value, "bindingId"),
22838
+ readInteger(value, "bindingRevision"),
22839
+ readIdentifier2(value, "localGrantId"),
22840
+ readDigest(value, "agentIdentityDigest"),
22841
+ readDigest(value, "workspaceIdentityDigest")
22842
+ );
22843
+ }
22844
+ function encodeBotExecutionBindingApprovedEvent(event) {
22845
+ return JSON.stringify(decodeBotExecutionBindingApprovedEvent(JSON.stringify(event)));
22846
+ }
22847
+ function decodeBotExecutionBindingUnavailableEvent(encoded) {
22848
+ const value = parseJson3(encoded);
22849
+ assertExactKeys2(value, [
22850
+ "behaviorRevisionId",
22851
+ "bindingId",
22852
+ "bindingRevision",
22853
+ "botId",
22854
+ "code",
22855
+ "kind",
22856
+ "message",
22857
+ "requestId"
22858
+ ]);
22859
+ if (value["kind"] !== BOT_BINDING_UNAVAILABLE_KIND) {
22860
+ throw new ProtocolMessageError("Invalid Bot binding unavailable event kind");
22861
+ }
22862
+ return new BotExecutionBindingUnavailableEvent(
22863
+ readIdentifier2(value, "requestId"),
22864
+ readIdentifier2(value, "botId"),
22865
+ readIdentifier2(value, "behaviorRevisionId"),
22866
+ readIdentifier2(value, "bindingId"),
22867
+ readInteger(value, "bindingRevision"),
22868
+ readIdentifier2(value, "code"),
22869
+ readText2(value, "message", 500, false)
22870
+ );
22871
+ }
22872
+ function encodeBotExecutionBindingUnavailableEvent(event) {
22873
+ return JSON.stringify(decodeBotExecutionBindingUnavailableEvent(JSON.stringify(event)));
22874
+ }
22875
+ function decodeBotSessionPromptCommand(encoded) {
22876
+ const value = parseJson3(encoded);
22877
+ assertExactKeys2(value, [
22878
+ "additionalDirectoryIds",
22879
+ "agentId",
22880
+ "allowedDeliveryTargets",
22881
+ "behaviorDigest",
22882
+ "behaviorInstructions",
22883
+ "behaviorRevisionId",
22884
+ "bindingId",
22885
+ "bindingRevision",
22886
+ "botId",
22887
+ "commandId",
22888
+ "conversationId",
22889
+ "directoryId",
22890
+ "executionCapabilityId",
22891
+ "executionCapabilitySecret",
22892
+ "executionDeadlineAt",
22893
+ "executionId",
22894
+ "images",
22895
+ "kind",
22896
+ "localGrantId",
22897
+ "prompt",
22898
+ "replyRoute",
22899
+ "resources",
22900
+ "sessionId",
22901
+ "turnId"
22902
+ ]);
22903
+ if (value["kind"] !== BOT_SESSION_PROMPT_KIND) {
22904
+ throw new ProtocolMessageError("Invalid Bot Session prompt kind");
22905
+ }
22906
+ return new BotSessionPromptCommand(
22907
+ readIdentifier2(value, "sessionId"),
22908
+ readIdentifier2(value, "commandId"),
22909
+ readIdentifier2(value, "agentId"),
22910
+ readIdentifier2(value, "bindingId"),
22911
+ readDirectoryIdentifier2(value, "directoryId"),
22912
+ readIdentifiers(value, "additionalDirectoryIds", 16),
22913
+ decodePromptImagesValue(value["images"]),
22914
+ decodePromptResourcesValue(value["resources"]),
22915
+ readText2(value, "prompt", 1e4, false),
22916
+ readIdentifier2(value, "executionId"),
22917
+ readIdentifier2(value, "executionCapabilityId"),
22918
+ readToken(value, "executionCapabilitySecret"),
22919
+ readTimestamp(value, "executionDeadlineAt"),
22920
+ readIdentifier2(value, "botId"),
22921
+ readIdentifier2(value, "conversationId"),
22922
+ readIdentifier2(value, "turnId"),
22923
+ readIdentifier2(value, "behaviorRevisionId"),
22924
+ readInteger(value, "bindingRevision"),
22925
+ readIdentifier2(value, "localGrantId"),
22926
+ readText2(value, "behaviorInstructions", MAX_INSTRUCTIONS_LENGTH, true),
22927
+ readDigest(value, "behaviorDigest"),
22928
+ readTargets(value, "allowedDeliveryTargets"),
22929
+ readReplyRoute(value["replyRoute"])
22930
+ );
22931
+ }
22932
+
22294
22933
  // ../protocol/src/mobius-api.ts
22295
22934
  var MOBIUS_API_PREFIX = "/mobius/api";
22296
22935
  var API_PREFIX_PATTERN = /^\/[a-zA-Z0-9._~-]+(?:\/[a-zA-Z0-9._~-]+)*$/;
@@ -22469,13 +23108,13 @@ var SessionEventRejectionCode = {
22469
23108
  SessionDeleted: "session_deleted",
22470
23109
  SessionNotFound: "session_not_found"
22471
23110
  };
22472
- var IDENTIFIER_PATTERN3 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
23111
+ var IDENTIFIER_PATTERN4 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
22473
23112
  var CURSOR_PATTERN = /^[A-Za-z0-9_-]{1,512}$/;
22474
23113
  var MAX_RECORDED_EVENT_LENGTH = 8 * 1024 * 1024;
22475
23114
  var DECIMAL_SEQUENCE_PATTERN = /^(?:0|[1-9][0-9]*)$/;
22476
23115
  var eventSourceSchema = external_exports.discriminatedUnion("kind", [
22477
23116
  external_exports.strictObject({
22478
- attemptId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3),
23117
+ attemptId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
22479
23118
  kind: external_exports.literal("attempt"),
22480
23119
  sourceSeq: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN)
22481
23120
  }).readonly(),
@@ -22485,35 +23124,35 @@ var eventSourceSchema = external_exports.discriminatedUnion("kind", [
22485
23124
  }).readonly()
22486
23125
  ]);
22487
23126
  var eventEnvelopeSchema = external_exports.strictObject({
22488
- eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3),
23127
+ eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
22489
23128
  kind: external_exports.literal(SESSION_EVENT_KIND),
22490
23129
  payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
22491
- sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3),
23130
+ sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
22492
23131
  source: eventSourceSchema
22493
23132
  }).readonly();
22494
23133
  var committedEventSchema = external_exports.strictObject({
22495
23134
  cursor: external_exports.string().min(1).max(512).regex(CURSOR_PATTERN),
22496
- eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3),
23135
+ eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
22497
23136
  kind: external_exports.literal(SESSION_EVENT_COMMITTED_KIND),
22498
23137
  payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
22499
23138
  recordedAt: external_exports.string().datetime({ offset: true }),
22500
23139
  sequence: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN),
22501
- sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3),
23140
+ sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
22502
23141
  source: eventSourceSchema
22503
23142
  }).readonly();
22504
23143
  var eventAcknowledgementSchema = external_exports.strictObject({
22505
23144
  cursor: external_exports.string().min(1).max(512).regex(CURSOR_PATTERN),
22506
23145
  duplicate: external_exports.boolean(),
22507
- eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3),
23146
+ eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
22508
23147
  kind: external_exports.literal(SESSION_EVENT_ACK_KIND),
22509
23148
  sequence: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN),
22510
- sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3)
23149
+ sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4)
22511
23150
  }).readonly();
22512
23151
  var eventRejectionSchema = external_exports.strictObject({
22513
23152
  code: external_exports.enum(SessionEventRejectionCode),
22514
- eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3),
23153
+ eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
22515
23154
  kind: external_exports.literal(SESSION_EVENT_REJECTED_KIND),
22516
- sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3)
23155
+ sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4)
22517
23156
  }).readonly();
22518
23157
  function decode5(encoded, schema) {
22519
23158
  let value;
@@ -22562,15 +23201,15 @@ function createDaemonConfig(connection, agents = [], installableAgents = []) {
22562
23201
  }
22563
23202
 
22564
23203
  // src/pairing/pair-local-machine.ts
22565
- import { randomUUID } from "node:crypto";
23204
+ import { randomUUID as randomUUID2 } from "node:crypto";
22566
23205
  import { mkdir as mkdir3, open as open4, realpath as realpath6, rename as rename3, stat as stat5, writeFile as writeFile2 } from "node:fs/promises";
22567
23206
  import { hostname as hostname3 } from "node:os";
22568
23207
  import { basename, join as join14, resolve as resolve3 } from "node:path";
22569
23208
  import { fetch as fetch2 } from "undici";
22570
23209
  var PAIRING_TIMEOUT_MILLISECONDS = 2e4;
22571
23210
  var PAIRING_CODE_PATTERN = /^[A-HJ-NP-Z2-9]{4}(?:-[A-HJ-NP-Z2-9]{4}){4}$/;
22572
- var IDENTIFIER_PATTERN4 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
22573
- var TOKEN_PATTERN = /^[a-zA-Z0-9_-]{32,256}$/;
23211
+ var IDENTIFIER_PATTERN5 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
23212
+ var TOKEN_PATTERN2 = /^[a-zA-Z0-9_-]{32,256}$/;
22574
23213
  var MAX_CONNECTION_FILE_LENGTH = 16 * 1024;
22575
23214
  var CLAIM_RESPONSE_KEYS = ["channelId", "daemonToken", "runtimeId"];
22576
23215
  var SAVED_CONNECTION_KEYS = ["defaultWorkspace", "channelId", "daemonToken", "relayOrigin"];
@@ -22582,36 +23221,36 @@ var PairingClientError = class extends Error {
22582
23221
  this.name = "PairingClientError";
22583
23222
  }
22584
23223
  };
22585
- function isRecord4(value) {
23224
+ function isRecord6(value) {
22586
23225
  return typeof value === "object" && value !== null && !Array.isArray(value);
22587
23226
  }
22588
23227
  function hasExactKeys(value, expectedKeys) {
22589
23228
  const keys = Object.keys(value);
22590
23229
  return keys.length === expectedKeys.length && expectedKeys.every((key) => Object.hasOwn(value, key));
22591
23230
  }
22592
- function readSingleOption(arguments_, option) {
23231
+ function readSingleOption(arguments_, option2) {
22593
23232
  const values = [];
22594
23233
  for (let index = 0; index < arguments_.length; index += 1) {
22595
- if (arguments_[index] !== option) {
23234
+ if (arguments_[index] !== option2) {
22596
23235
  continue;
22597
23236
  }
22598
23237
  const value = arguments_[index + 1];
22599
23238
  if (value === void 0 || value.startsWith("--")) {
22600
- throw new PairingClientError("invalid_arguments", `${option} requires a value`);
23239
+ throw new PairingClientError("invalid_arguments", `${option2} requires a value`);
22601
23240
  }
22602
23241
  values.push(value);
22603
23242
  index += 1;
22604
23243
  }
22605
23244
  if (values.length !== 1) {
22606
- throw new PairingClientError("invalid_arguments", `${option} must be provided exactly once`);
23245
+ throw new PairingClientError("invalid_arguments", `${option2} must be provided exactly once`);
22607
23246
  }
22608
23247
  return values[0] ?? "";
22609
23248
  }
22610
23249
  function assertKnownArguments(arguments_) {
22611
23250
  for (let index = 0; index < arguments_.length; index += 2) {
22612
- const option = arguments_[index];
22613
- if (option !== "--url" && option !== "--code" && option !== "--workspace") {
22614
- throw new PairingClientError("invalid_arguments", `Unknown pairing option: ${option ?? "missing option"}`);
23251
+ const option2 = arguments_[index];
23252
+ if (option2 !== "--url" && option2 !== "--code" && option2 !== "--workspace") {
23253
+ throw new PairingClientError("invalid_arguments", `Unknown pairing option: ${option2 ?? "missing option"}`);
22615
23254
  }
22616
23255
  }
22617
23256
  }
@@ -22659,7 +23298,7 @@ function parseChannelArgument(arguments_) {
22659
23298
  throw new PairingClientError("invalid_arguments", "Usage: mobius start --channel <channel-id>");
22660
23299
  }
22661
23300
  const channelId = arguments_[1] ?? "";
22662
- if (!IDENTIFIER_PATTERN4.test(channelId)) {
23301
+ if (!IDENTIFIER_PATTERN5.test(channelId)) {
22663
23302
  throw new PairingClientError("invalid_channel_id", "The saved channel ID is invalid");
22664
23303
  }
22665
23304
  return channelId;
@@ -22698,9 +23337,9 @@ async function readJsonResponse(response) {
22698
23337
  }
22699
23338
  }
22700
23339
  function readRelayError(value) {
22701
- if (isRecord4(value)) {
23340
+ if (isRecord6(value)) {
22702
23341
  const error61 = value["error"];
22703
- if (isRecord4(error61)) {
23342
+ if (isRecord6(error61)) {
22704
23343
  const code = error61["code"];
22705
23344
  const message = error61["message"];
22706
23345
  if (typeof code === "string" && typeof message === "string") {
@@ -22711,16 +23350,16 @@ function readRelayError(value) {
22711
23350
  return new PairingClientError("pairing_failed", "The relay could not pair this machine");
22712
23351
  }
22713
23352
  function decodeClaimResponse(value) {
22714
- if (!isRecord4(value) || !hasExactKeys(value, CLAIM_RESPONSE_KEYS)) {
23353
+ if (!isRecord6(value) || !hasExactKeys(value, CLAIM_RESPONSE_KEYS)) {
22715
23354
  throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
22716
23355
  }
22717
23356
  const channelId = value["channelId"];
22718
- const daemonToken = value["daemonToken"];
23357
+ const daemonToken2 = value["daemonToken"];
22719
23358
  const runtimeId = value["runtimeId"];
22720
- if (typeof channelId !== "string" || !IDENTIFIER_PATTERN4.test(channelId) || typeof daemonToken !== "string" || !TOKEN_PATTERN.test(daemonToken) || typeof runtimeId !== "string" || !IDENTIFIER_PATTERN4.test(runtimeId)) {
23359
+ if (typeof channelId !== "string" || !IDENTIFIER_PATTERN5.test(channelId) || typeof daemonToken2 !== "string" || !TOKEN_PATTERN2.test(daemonToken2) || typeof runtimeId !== "string" || !IDENTIFIER_PATTERN5.test(runtimeId)) {
22721
23360
  throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
22722
23361
  }
22723
- return { channelId, daemonToken, runtimeId };
23362
+ return { channelId, daemonToken: daemonToken2, runtimeId };
22724
23363
  }
22725
23364
  async function claimPairing(options, defaultWorkspace, localAgents, installableAgents, signal) {
22726
23365
  const agents = localAgents.map((agent) => ({
@@ -22755,18 +23394,18 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
22755
23394
  }
22756
23395
  return decodeClaimResponse(value);
22757
23396
  }
22758
- async function persistConnection(channelId, relayOrigin, daemonToken, defaultWorkspace) {
23397
+ async function persistConnection(channelId, relayOrigin, daemonToken2, defaultWorkspace) {
22759
23398
  const connectionsDirectory = join14(readStateDirectory(), "connections");
22760
23399
  await mkdir3(connectionsDirectory, { mode: 448, recursive: true });
22761
23400
  const connectionPath = join14(connectionsDirectory, `${channelId}.json`);
22762
- const temporaryPath = join14(connectionsDirectory, `.${channelId}.${randomUUID()}.tmp`);
23401
+ const temporaryPath = join14(connectionsDirectory, `.${channelId}.${randomUUID2()}.tmp`);
22763
23402
  await writeFile2(
22764
23403
  temporaryPath,
22765
23404
  `${JSON.stringify(
22766
23405
  {
22767
23406
  defaultWorkspace,
22768
23407
  channelId,
22769
- daemonToken,
23408
+ daemonToken: daemonToken2,
22770
23409
  relayOrigin: relayOrigin.toString()
22771
23410
  },
22772
23411
  null,
@@ -22779,20 +23418,20 @@ async function persistConnection(channelId, relayOrigin, daemonToken, defaultWor
22779
23418
  return connectionPath;
22780
23419
  }
22781
23420
  function decodeSavedConnection(value, expectedChannelId) {
22782
- if (!isRecord4(value) || !hasExactKeys(value, SAVED_CONNECTION_KEYS)) {
23421
+ if (!isRecord6(value) || !hasExactKeys(value, SAVED_CONNECTION_KEYS)) {
22783
23422
  throw new PairingClientError("invalid_connection", "The saved connection is invalid");
22784
23423
  }
22785
23424
  const defaultWorkspace = value["defaultWorkspace"];
22786
23425
  const channelId = value["channelId"];
22787
- const daemonToken = value["daemonToken"];
23426
+ const daemonToken2 = value["daemonToken"];
22788
23427
  const relayOrigin = value["relayOrigin"];
22789
- if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !IDENTIFIER_PATTERN4.test(channelId) || typeof daemonToken !== "string" || !TOKEN_PATTERN.test(daemonToken) || typeof relayOrigin !== "string") {
23428
+ if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !IDENTIFIER_PATTERN5.test(channelId) || typeof daemonToken2 !== "string" || !TOKEN_PATTERN2.test(daemonToken2) || typeof relayOrigin !== "string") {
22790
23429
  throw new PairingClientError("invalid_connection", "The saved connection is invalid");
22791
23430
  }
22792
23431
  return {
22793
23432
  defaultWorkspace,
22794
23433
  channelId,
22795
- daemonToken,
23434
+ daemonToken: daemonToken2,
22796
23435
  relayOrigin: parseRelayOrigin(relayOrigin)
22797
23436
  };
22798
23437
  }
@@ -22893,9 +23532,10 @@ async function resumeLocalMachine(arguments_, signal = new AbortController().sig
22893
23532
  }
22894
23533
 
22895
23534
  // src/run-daemon.ts
22896
- import { basename as basename3 } from "node:path";
23535
+ import { randomUUID as randomUUID6 } from "node:crypto";
23536
+ import { basename as basename3, join as join16 } from "node:path";
22897
23537
  import { styleText } from "node:util";
22898
- import { fetch as fetch5, WebSocket as WebSocket2 } from "undici";
23538
+ import { fetch as fetch6, WebSocket as WebSocket2 } from "undici";
22899
23539
 
22900
23540
  // src/acp/session-manager.ts
22901
23541
  import { spawn as spawn3 } from "node:child_process";
@@ -22908,7 +23548,7 @@ import {
22908
23548
 
22909
23549
  // src/acp/activity.ts
22910
23550
  var TRUNCATION_MARKER = "\n\u2026 output truncated by Mobius";
22911
- function isRecord5(value) {
23551
+ function isRecord7(value) {
22912
23552
  return typeof value === "object" && value !== null && !Array.isArray(value);
22913
23553
  }
22914
23554
  var AcpActivity = class _AcpActivity {
@@ -23175,7 +23815,7 @@ function contentPhase(content) {
23175
23815
  return "";
23176
23816
  }
23177
23817
  const codex = metadata["codex"];
23178
- if (!isRecord5(codex)) {
23818
+ if (!isRecord7(codex)) {
23179
23819
  return "";
23180
23820
  }
23181
23821
  const phase = codex["phase"];
@@ -23413,7 +24053,7 @@ var SessionConfigProtocolError = class extends Error {
23413
24053
  this.name = "SessionConfigProtocolError";
23414
24054
  }
23415
24055
  };
23416
- function isRecord6(value) {
24056
+ function isRecord8(value) {
23417
24057
  return typeof value === "object" && value !== null && !Array.isArray(value);
23418
24058
  }
23419
24059
  function readString2(value, fallback = "") {
@@ -23425,13 +24065,13 @@ function truncate2(value, maximum) {
23425
24065
  function readBoolean(value, fallback = false) {
23426
24066
  return typeof value === "boolean" ? value : fallback;
23427
24067
  }
23428
- function normalizeConfigValue(option, groupId = "", groupName = "") {
24068
+ function normalizeConfigValue(option2, groupId = "", groupName = "") {
23429
24069
  return {
23430
- description: truncate2(readString2(option["description"]), 500),
24070
+ description: truncate2(readString2(option2["description"]), 500),
23431
24071
  groupId: truncate2(groupId, 128),
23432
24072
  groupName: truncate2(groupName, 255),
23433
- name: truncate2(readString2(option["name"], readString2(option["value"])), 255),
23434
- value: truncate2(readString2(option["value"]), 500)
24073
+ name: truncate2(readString2(option2["name"], readString2(option2["value"])), 255),
24074
+ value: truncate2(readString2(option2["value"]), 500)
23435
24075
  };
23436
24076
  }
23437
24077
  function normalizeConfigValues(value) {
@@ -23440,7 +24080,7 @@ function normalizeConfigValues(value) {
23440
24080
  }
23441
24081
  const normalized = [];
23442
24082
  for (const entry of value) {
23443
- if (!isRecord6(entry)) {
24083
+ if (!isRecord8(entry)) {
23444
24084
  continue;
23445
24085
  }
23446
24086
  const groupedOptions = entry["options"];
@@ -23448,7 +24088,7 @@ function normalizeConfigValues(value) {
23448
24088
  const groupId = readString2(entry["group"]);
23449
24089
  const groupName = readString2(entry["name"]);
23450
24090
  for (const groupedOption of groupedOptions) {
23451
- if (isRecord6(groupedOption)) {
24091
+ if (isRecord8(groupedOption)) {
23452
24092
  normalized.push(normalizeConfigValue(groupedOption, groupId, groupName));
23453
24093
  }
23454
24094
  }
@@ -23461,21 +24101,21 @@ function normalizeConfigValues(value) {
23461
24101
  function normalizeConfigOptions(value, modes) {
23462
24102
  const normalized = [];
23463
24103
  if (Array.isArray(value)) {
23464
- for (const option of value) {
23465
- if (!isRecord6(option)) {
24104
+ for (const option2 of value) {
24105
+ if (!isRecord8(option2)) {
23466
24106
  continue;
23467
24107
  }
23468
- const id = truncate2(readString2(option["id"]), 128);
23469
- const name = truncate2(readString2(option["name"], id), 255);
24108
+ const id = truncate2(readString2(option2["id"]), 128);
24109
+ const name = truncate2(readString2(option2["name"], id), 255);
23470
24110
  if (id.length === 0 || name.length === 0) {
23471
24111
  continue;
23472
24112
  }
23473
- if (option["type"] === "boolean") {
24113
+ if (option2["type"] === "boolean") {
23474
24114
  normalized.push({
23475
- booleanValue: readBoolean(option["currentValue"]),
23476
- category: truncate2(readString2(option["category"]), 128),
24115
+ booleanValue: readBoolean(option2["currentValue"]),
24116
+ category: truncate2(readString2(option2["category"]), 128),
23477
24117
  currentValue: "",
23478
- description: truncate2(readString2(option["description"]), 500),
24118
+ description: truncate2(readString2(option2["description"]), 500),
23479
24119
  id,
23480
24120
  name,
23481
24121
  type: "boolean",
@@ -23483,15 +24123,15 @@ function normalizeConfigOptions(value, modes) {
23483
24123
  });
23484
24124
  continue;
23485
24125
  }
23486
- if (option["type"] === "select") {
23487
- const values = normalizeConfigValues(option["options"]);
23488
- const currentValue = truncate2(readString2(option["currentValue"]), 500);
24126
+ if (option2["type"] === "select") {
24127
+ const values = normalizeConfigValues(option2["options"]);
24128
+ const currentValue = truncate2(readString2(option2["currentValue"]), 500);
23489
24129
  if (currentValue.length > 0 && values.some((entry) => entry.value === currentValue)) {
23490
24130
  normalized.push({
23491
24131
  booleanValue: false,
23492
- category: truncate2(readString2(option["category"]), 128),
24132
+ category: truncate2(readString2(option2["category"]), 128),
23493
24133
  currentValue,
23494
- description: truncate2(readString2(option["description"]), 500),
24134
+ description: truncate2(readString2(option2["description"]), 500),
23495
24135
  id,
23496
24136
  name,
23497
24137
  type: "select",
@@ -23501,12 +24141,12 @@ function normalizeConfigOptions(value, modes) {
23501
24141
  }
23502
24142
  }
23503
24143
  }
23504
- if (isRecord6(modes)) {
24144
+ if (isRecord8(modes)) {
23505
24145
  const values = [];
23506
24146
  const availableModes = modes["availableModes"];
23507
24147
  if (Array.isArray(availableModes)) {
23508
24148
  for (const mode of availableModes) {
23509
- if (!isRecord6(mode)) {
24149
+ if (!isRecord8(mode)) {
23510
24150
  continue;
23511
24151
  }
23512
24152
  const id = truncate2(readString2(mode["id"]), 500);
@@ -23539,7 +24179,7 @@ function normalizeConfigOptions(value, modes) {
23539
24179
  return normalized.slice(0, 100);
23540
24180
  }
23541
24181
  function ensureReasoningEffortOption(current) {
23542
- if (current.some((option) => option.category === "thought_level")) {
24182
+ if (current.some((option2) => option2.category === "thought_level")) {
23543
24183
  return current;
23544
24184
  }
23545
24185
  const unavailable = {
@@ -23560,7 +24200,7 @@ function ensureReasoningEffortOption(current) {
23560
24200
  }
23561
24201
  ]
23562
24202
  };
23563
- const modelIndex = current.findIndex((option) => option.category === "model");
24203
+ const modelIndex = current.findIndex((option2) => option2.category === "model");
23564
24204
  if (current.length < MAXIMUM_CONFIG_OPTIONS) {
23565
24205
  if (modelIndex < 0) {
23566
24206
  return [...current, unavailable];
@@ -23584,20 +24224,20 @@ function ensureReasoningEffortOption(current) {
23584
24224
  return [...current.slice(0, MAXIMUM_CONFIG_OPTIONS - 2), model, unavailable];
23585
24225
  }
23586
24226
  function normalizeStandardLifecycle(response) {
23587
- const lifecycle = isRecord6(response) ? response : {};
24227
+ const lifecycle = isRecord8(response) ? response : {};
23588
24228
  return ensureReasoningEffortOption(normalizeConfigOptions(lifecycle["configOptions"], lifecycle["modes"]));
23589
24229
  }
23590
24230
  function replaceStandardConfigOptions(current, value) {
23591
24231
  const next = normalizeConfigOptions(value, void 0);
23592
- const withMode = next.some((option) => option.category === "mode") ? next : [...current.filter((option) => option.category === "mode"), ...next].slice(0, 100);
24232
+ const withMode = next.some((option2) => option2.category === "mode") ? next : [...current.filter((option2) => option2.category === "mode"), ...next].slice(0, 100);
23593
24233
  return ensureReasoningEffortOption(withMode);
23594
24234
  }
23595
24235
  function updateCurrentValue(current, configId, value) {
23596
- return current.map((option) => option.id === configId ? { ...option, currentValue: value } : option);
24236
+ return current.map((option2) => option2.id === configId ? { ...option2, currentValue: value } : option2);
23597
24237
  }
23598
24238
  var StandardSessionConfigProtocol = class {
23599
24239
  configure = async (current, change, nativeSessionId, transport) => {
23600
- const existing = current.find((option) => option.id === change.configId);
24240
+ const existing = current.find((option2) => option2.id === change.configId);
23601
24241
  if (existing === void 0) {
23602
24242
  return current;
23603
24243
  }
@@ -23626,7 +24266,7 @@ var StandardSessionConfigProtocol = class {
23626
24266
  "ACP agent exited while changing session configuration",
23627
24267
  change.signal
23628
24268
  );
23629
- if (!isRecord6(response) || !Array.isArray(response["configOptions"])) {
24269
+ if (!isRecord8(response) || !Array.isArray(response["configOptions"])) {
23630
24270
  throw new SessionConfigProtocolError("The Agent returned an invalid session configuration response");
23631
24271
  }
23632
24272
  return replaceStandardConfigOptions(current, response["configOptions"]);
@@ -23640,31 +24280,31 @@ var standardSessionConfigProtocol = new StandardSessionConfigProtocol();
23640
24280
  var LEGACY_MODEL_CONFIG_ID = "grok_build_legacy_model";
23641
24281
  var LEGACY_REASONING_EFFORT_CONFIG_ID = "grok_build_legacy_reasoning_effort";
23642
24282
  function legacyOptions(response) {
23643
- if (!isRecord6(response)) {
24283
+ if (!isRecord8(response)) {
23644
24284
  return [];
23645
24285
  }
23646
24286
  const metadata = response["_meta"];
23647
- if (!isRecord6(metadata)) {
24287
+ if (!isRecord8(metadata)) {
23648
24288
  return [];
23649
24289
  }
23650
24290
  const sessionConfig = metadata["x.ai/sessionConfig"];
23651
- if (!isRecord6(sessionConfig) || !Array.isArray(sessionConfig["options"])) {
24291
+ if (!isRecord8(sessionConfig) || !Array.isArray(sessionConfig["options"])) {
23652
24292
  return [];
23653
24293
  }
23654
- return sessionConfig["options"].slice(0, 500).filter(isRecord6);
24294
+ return sessionConfig["options"].slice(0, 500).filter(isRecord8);
23655
24295
  }
23656
- function legacyValue(option) {
23657
- const value = readString2(option["id"]);
24296
+ function legacyValue(option2) {
24297
+ const value = readString2(option2["id"]);
23658
24298
  return {
23659
- description: readString2(option["description"]).slice(0, 500),
24299
+ description: readString2(option2["description"]).slice(0, 500),
23660
24300
  groupId: "",
23661
24301
  groupName: "",
23662
- name: readString2(option["label"], value).slice(0, 255),
24302
+ name: readString2(option2["label"], value).slice(0, 255),
23663
24303
  value: value.slice(0, 500)
23664
24304
  };
23665
24305
  }
23666
24306
  function modelsRecord(response) {
23667
- if (!isRecord6(response) || !isRecord6(response["models"])) {
24307
+ if (!isRecord8(response) || !isRecord8(response["models"])) {
23668
24308
  return {};
23669
24309
  }
23670
24310
  return response["models"];
@@ -23673,9 +24313,9 @@ function legacyModelOptions(response) {
23673
24313
  const options = legacyOptions(response);
23674
24314
  const models = modelsRecord(response);
23675
24315
  const values = [];
23676
- for (const option of options) {
23677
- if (option["category"] === "model") {
23678
- const value = legacyValue(option);
24316
+ for (const option2 of options) {
24317
+ if (option2["category"] === "model") {
24318
+ const value = legacyValue(option2);
23679
24319
  if (value.value.length > 0 && !values.some((existing) => existing.value === value.value)) {
23680
24320
  values.push(value);
23681
24321
  }
@@ -23683,7 +24323,7 @@ function legacyModelOptions(response) {
23683
24323
  }
23684
24324
  if (values.length === 0 && Array.isArray(models["availableModels"])) {
23685
24325
  for (const model of models["availableModels"]) {
23686
- if (!isRecord6(model)) {
24326
+ if (!isRecord8(model)) {
23687
24327
  continue;
23688
24328
  }
23689
24329
  const value = readString2(model["modelId"]).slice(0, 500);
@@ -23701,7 +24341,7 @@ function legacyModelOptions(response) {
23701
24341
  }
23702
24342
  }
23703
24343
  }
23704
- const selected = options.find((option) => option["category"] === "model" && option["selected"] === true);
24344
+ const selected = options.find((option2) => option2["category"] === "model" && option2["selected"] === true);
23705
24345
  const currentValue = readString2(
23706
24346
  models["currentModelId"],
23707
24347
  selected === void 0 ? "" : readString2(selected["id"])
@@ -23724,11 +24364,11 @@ function legacyModelOptions(response) {
23724
24364
  function legacyReasoningEffortOptions(response) {
23725
24365
  const options = legacyOptions(response);
23726
24366
  const values = [];
23727
- for (const option of options) {
23728
- if (option["category"] !== "mode") {
24367
+ for (const option2 of options) {
24368
+ if (option2["category"] !== "mode") {
23729
24369
  continue;
23730
24370
  }
23731
- const value = legacyValue(option);
24371
+ const value = legacyValue(option2);
23732
24372
  if (value.value.length > 0 && !values.some((existing) => existing.value === value.value)) {
23733
24373
  values.push(value);
23734
24374
  }
@@ -23736,7 +24376,7 @@ function legacyReasoningEffortOptions(response) {
23736
24376
  if (values.length === 0) {
23737
24377
  return [];
23738
24378
  }
23739
- const selected = options.find((option) => option["category"] === "mode" && option["selected"] === true);
24379
+ const selected = options.find((option2) => option2["category"] === "mode" && option2["selected"] === true);
23740
24380
  if (selected === void 0) {
23741
24381
  values.unshift({
23742
24382
  description: "Use the selected model's default reasoning effort",
@@ -23763,41 +24403,41 @@ function legacyReasoningEffortOptions(response) {
23763
24403
  return [result];
23764
24404
  }
23765
24405
  function normalizeGrokLifecycle(response) {
23766
- const lifecycle = isRecord6(response) ? response : {};
24406
+ const lifecycle = isRecord8(response) ? response : {};
23767
24407
  const standard = normalizeConfigOptions(lifecycle["configOptions"], lifecycle["modes"]);
23768
24408
  const normalized = [...standard];
23769
- if (!normalized.some((option) => option.category === "model")) {
24409
+ if (!normalized.some((option2) => option2.category === "model")) {
23770
24410
  normalized.push(...legacyModelOptions(response));
23771
24411
  }
23772
- if (!normalized.some((option) => option.category === "thought_level")) {
24412
+ if (!normalized.some((option2) => option2.category === "thought_level")) {
23773
24413
  const efforts = legacyReasoningEffortOptions(response);
23774
24414
  if (efforts.length > 0) {
23775
- const modelIndex = normalized.findIndex((option) => option.category === "model");
24415
+ const modelIndex = normalized.findIndex((option2) => option2.category === "model");
23776
24416
  normalized.splice(modelIndex < 0 ? normalized.length : modelIndex + 1, 0, ...efforts);
23777
24417
  }
23778
24418
  }
23779
24419
  return ensureReasoningEffortOption(normalized.slice(0, 100));
23780
24420
  }
23781
24421
  function updateCurrentValue2(current, category, value) {
23782
- return current.map((option) => option.category === category ? { ...option, currentValue: value } : option);
24422
+ return current.map((option2) => option2.category === category ? { ...option2, currentValue: value } : option2);
23783
24423
  }
23784
24424
  function validateGrokResponse(response, modelId) {
23785
- if (!isRecord6(response) || !isRecord6(response["_meta"])) {
24425
+ if (!isRecord8(response) || !isRecord8(response["_meta"])) {
23786
24426
  throw new SessionConfigProtocolError("Grok Build returned an invalid session configuration response");
23787
24427
  }
23788
24428
  const model = response["_meta"]["model"];
23789
- const appliedModel = isRecord6(model) ? model["Ok"] : model;
24429
+ const appliedModel = isRecord8(model) ? model["Ok"] : model;
23790
24430
  if (appliedModel !== modelId) {
23791
24431
  throw new SessionConfigProtocolError("Grok Build returned an invalid session configuration response");
23792
24432
  }
23793
24433
  }
23794
24434
  var GrokBuildSessionConfigProtocol = class {
23795
24435
  configure = async (current, change, nativeSessionId, transport) => {
23796
- const existing = current.find((option) => option.id === change.configId);
24436
+ const existing = current.find((option2) => option2.id === change.configId);
23797
24437
  if (existing === void 0 || existing.id !== LEGACY_MODEL_CONFIG_ID && existing.id !== LEGACY_REASONING_EFFORT_CONFIG_ID) {
23798
24438
  return await standardSessionConfigProtocol.configure(current, change, nativeSessionId, transport);
23799
24439
  }
23800
- const model = current.find((option) => option.category === "model");
24440
+ const model = current.find((option2) => option2.category === "model");
23801
24441
  if (model === void 0) {
23802
24442
  return current;
23803
24443
  }
@@ -23823,10 +24463,10 @@ var GrokBuildSessionConfigProtocol = class {
23823
24463
  validateGrokResponse(response, modelId);
23824
24464
  const updated = updateCurrentValue2(current, existing.category, change.value);
23825
24465
  return existing.category === "thought_level" ? updated.map(
23826
- (option) => option.category === "thought_level" ? {
23827
- ...option,
23828
- values: option.values.filter((value) => value.value !== AGENT_DEFAULT_REASONING_EFFORT)
23829
- } : option
24466
+ (option2) => option2.category === "thought_level" ? {
24467
+ ...option2,
24468
+ values: option2.values.filter((value) => value.value !== AGENT_DEFAULT_REASONING_EFFORT)
24469
+ } : option2
23830
24470
  ) : updated;
23831
24471
  };
23832
24472
  normalizeLifecycle = (response) => normalizeGrokLifecycle(response);
@@ -24229,7 +24869,7 @@ function createWritableAcpStream(output2) {
24229
24869
  function truncate3(value, maximumLength) {
24230
24870
  return value.length <= maximumLength ? value : `${value.slice(0, Math.max(0, maximumLength - 1))}\u2026`;
24231
24871
  }
24232
- function isRecord7(value) {
24872
+ function isRecord9(value) {
24233
24873
  return typeof value === "object" && value !== null && !Array.isArray(value);
24234
24874
  }
24235
24875
  function readString4(value, fallback = "") {
@@ -24257,12 +24897,12 @@ function normalizeElicitationOptions(schema) {
24257
24897
  const normalized = [];
24258
24898
  const oneOf = schema["oneOf"];
24259
24899
  if (Array.isArray(oneOf)) {
24260
- for (const option of oneOf) {
24261
- if (isRecord7(option) && typeof option["const"] === "string") {
24900
+ for (const option2 of oneOf) {
24901
+ if (isRecord9(option2) && typeof option2["const"] === "string") {
24262
24902
  normalized.push({
24263
- description: truncate3(readString4(option["description"]), 500),
24264
- label: truncate3(readString4(option["title"], option["const"]), 255),
24265
- value: truncate3(option["const"], 500)
24903
+ description: truncate3(readString4(option2["description"]), 500),
24904
+ label: truncate3(readString4(option2["title"], option2["const"]), 255),
24905
+ value: truncate3(option2["const"], 500)
24266
24906
  });
24267
24907
  }
24268
24908
  }
@@ -24278,7 +24918,7 @@ function normalizeElicitationOptions(schema) {
24278
24918
  return normalized.slice(0, 200);
24279
24919
  }
24280
24920
  const items = schema["items"];
24281
- if (!isRecord7(items)) {
24921
+ if (!isRecord9(items)) {
24282
24922
  return normalized;
24283
24923
  }
24284
24924
  const anyOf = items["anyOf"];
@@ -24291,7 +24931,7 @@ function numericString(value) {
24291
24931
  return typeof value === "number" && Number.isFinite(value) ? value.toString() : "";
24292
24932
  }
24293
24933
  function normalizeElicitationFields(requestedSchema) {
24294
- if (!isRecord7(requestedSchema) || !isRecord7(requestedSchema["properties"])) {
24934
+ if (!isRecord9(requestedSchema) || !isRecord9(requestedSchema["properties"])) {
24295
24935
  return [];
24296
24936
  }
24297
24937
  const properties = requestedSchema["properties"];
@@ -24301,7 +24941,7 @@ function normalizeElicitationFields(requestedSchema) {
24301
24941
  );
24302
24942
  const normalized = [];
24303
24943
  for (const [name, property] of Object.entries(properties)) {
24304
- if (!isRecord7(property)) {
24944
+ if (!isRecord9(property)) {
24305
24945
  continue;
24306
24946
  }
24307
24947
  const type = elicitationFieldType(property["type"]);
@@ -24392,7 +25032,7 @@ function validateElicitationContent(encoded, requestedSchema) {
24392
25032
  "invalid_elicitation_response"
24393
25033
  );
24394
25034
  }
24395
- if (!isRecord7(decoded) || !isRecord7(requestedSchema) || !isRecord7(requestedSchema["properties"])) {
25035
+ if (!isRecord9(decoded) || !isRecord9(requestedSchema) || !isRecord9(requestedSchema["properties"])) {
24396
25036
  throw new AcpExecutionError(
24397
25037
  "Elicitation response does not match the requested form",
24398
25038
  {},
@@ -24412,7 +25052,7 @@ function validateElicitationContent(encoded, requestedSchema) {
24412
25052
  const validated = {};
24413
25053
  for (const [name, value] of Object.entries(decoded)) {
24414
25054
  const property = properties[name];
24415
- if (!isRecord7(property)) {
25055
+ if (!isRecord9(property)) {
24416
25056
  throw new AcpExecutionError(
24417
25057
  `Elicitation field ${name} was not requested`,
24418
25058
  {},
@@ -24449,7 +25089,7 @@ function validateElicitationContent(encoded, requestedSchema) {
24449
25089
  );
24450
25090
  }
24451
25091
  const allowed = normalizeElicitationOptions(property);
24452
- if (allowed.length > 0 && value.some((entry) => !allowed.some((option) => option.value === entry))) {
25092
+ if (allowed.length > 0 && value.some((entry) => !allowed.some((option2) => option2.value === entry))) {
24453
25093
  throw new AcpExecutionError(
24454
25094
  `Elicitation field ${name} contains an invalid selection`,
24455
25095
  {},
@@ -24946,7 +25586,7 @@ var AcpProcessSession = class _AcpProcessSession {
24946
25586
  };
24947
25587
  nativeSessionId = () => this.#nativeSessionId;
24948
25588
  configure = async (options) => {
24949
- const existing = this.#configOptions.find((option) => option.id === options.configId);
25589
+ const existing = this.#configOptions.find((option2) => option2.id === options.configId);
24950
25590
  if (existing === void 0 || existing.type !== options.valueType) {
24951
25591
  throw new AcpExecutionError(
24952
25592
  "The requested ACP configuration option is unavailable",
@@ -25196,10 +25836,10 @@ var AcpProcessSession = class _AcpProcessSession {
25196
25836
  onPermission = async (request, signal) => {
25197
25837
  this.assertNativeSession(request.sessionId);
25198
25838
  const interactionId = `permission-${crypto.randomUUID()}`;
25199
- const options = request.options.slice(0, 20).map((option) => ({
25200
- kind: option.kind,
25201
- name: truncate3(option.name, 255),
25202
- optionId: truncate3(option.optionId, 255)
25839
+ const options = request.options.slice(0, 20).map((option2) => ({
25840
+ kind: option2.kind,
25841
+ name: truncate3(option2.name, 255),
25842
+ optionId: truncate3(option2.optionId, 255)
25203
25843
  }));
25204
25844
  if (options.length === 0) {
25205
25845
  throw new AcpExecutionError(
@@ -25208,7 +25848,7 @@ var AcpProcessSession = class _AcpProcessSession {
25208
25848
  "invalid_agent_permission_request"
25209
25849
  );
25210
25850
  }
25211
- const pending = new PendingPermission(interactionId, new Set(options.map((option) => option.optionId)));
25851
+ const pending = new PendingPermission(interactionId, new Set(options.map((option2) => option2.optionId)));
25212
25852
  this.#pendingPermissions.set(interactionId, pending);
25213
25853
  const abort = () => {
25214
25854
  void this.cancelPermission(interactionId);
@@ -25418,7 +26058,7 @@ var AcpProcessSession = class _AcpProcessSession {
25418
26058
  }
25419
26059
  if (update.sessionUpdate === "current_mode_update") {
25420
26060
  this.#configOptions = this.#configOptions.map(
25421
- (option) => option.category === "mode" ? { ...option, currentValue: update.currentModeId } : option
26061
+ (option2) => option2.category === "mode" ? { ...option2, currentValue: update.currentModeId } : option2
25422
26062
  );
25423
26063
  this.#configRevision += 1;
25424
26064
  await this.emitConfigUpdate();
@@ -26650,47 +27290,757 @@ var WorkspaceDirectoryService = class {
26650
27290
  };
26651
27291
  };
26652
27292
 
26653
- // src/native-sessions/service.ts
26654
- import { randomUUID as randomUUID2 } from "node:crypto";
26655
-
26656
- // src/native-sessions/codex-history.ts
26657
- import { spawn as spawn4 } from "node:child_process";
26658
- var responseSchema = external_exports.union([
26659
- external_exports.object({
26660
- id: external_exports.number(),
26661
- error: external_exports.object({ code: external_exports.number(), message: external_exports.string() })
26662
- }),
26663
- external_exports.object({ id: external_exports.number(), result: external_exports.unknown() }),
26664
- external_exports.object({ method: external_exports.string() })
26665
- ]);
26666
- var threadSchema = external_exports.object({
26667
- thread: external_exports.object({
26668
- id: nativeSessionIdSchema,
26669
- cwd: external_exports.string().min(1).max(2048).refine((path2) => !path2.includes("\0"))
26670
- })
26671
- });
26672
- var turnsSchema = external_exports.object({
26673
- data: external_exports.array(external_exports.object({ items: external_exports.array(external_exports.unknown()).max(1e5) })).max(SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT),
26674
- nextCursor: external_exports.string().nullish()
26675
- });
26676
- var itemTypeSchema = external_exports.object({ type: external_exports.string().min(1).max(80) });
26677
- var userMessageSchema = external_exports.object({
26678
- content: external_exports.array(external_exports.unknown()).max(1e4)
26679
- });
26680
- var textSchema = external_exports.object({ text: external_exports.string() });
26681
- var imageSchema = external_exports.object({ url: external_exports.string() });
26682
- var agentMessageSchema = textSchema.extend({ phase: external_exports.string().nullish() });
26683
- function decodeHistory(thread, value) {
26684
- const page = turnsSchema.parse(value);
26685
- const messages = [];
26686
- let characters = 0;
26687
- let imageCharacters = 0;
26688
- let truncated = page.nextCursor != null;
26689
- for (const turn of page.data.toReversed()) {
26690
- for (const item of turn.items) {
26691
- const { type } = itemTypeSchema.parse(item);
26692
- let message;
26693
- if (type === "userMessage") {
27293
+ // src/bots/local-bot-grant-store.ts
27294
+ import { createHash as createHash2, randomUUID as randomUUID3 } from "node:crypto";
27295
+ import { stat as stat7 } from "node:fs/promises";
27296
+ import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
27297
+ var LOCAL_BOT_GRANT_LIFETIME_MILLISECONDS = 90 * 24 * 60 * 60 * 1e3;
27298
+ var LocalBotAuthorizationError = class extends Error {
27299
+ code;
27300
+ constructor(code, message, options = {}) {
27301
+ super(message, options);
27302
+ this.code = code;
27303
+ this.name = "LocalBotAuthorizationError";
27304
+ }
27305
+ };
27306
+ var LocalBotGrant = class {
27307
+ agent;
27308
+ agentIdentityDigest;
27309
+ allowedDeliveryTargetIds;
27310
+ behaviorDigest;
27311
+ behaviorRevisionId;
27312
+ bindingId;
27313
+ bindingRevision;
27314
+ botId;
27315
+ expiresAt;
27316
+ localGrantId;
27317
+ revocationEpoch;
27318
+ workspaceIdentityDigest;
27319
+ workspacePath;
27320
+ constructor(localGrantId, botId, behaviorRevisionId, behaviorDigest, bindingId, bindingRevision, agent, agentIdentityDigest, workspacePath, workspaceIdentityDigest, allowedDeliveryTargetIds, expiresAt, revocationEpoch) {
27321
+ this.localGrantId = localGrantId;
27322
+ this.botId = botId;
27323
+ this.behaviorRevisionId = behaviorRevisionId;
27324
+ this.behaviorDigest = behaviorDigest;
27325
+ this.bindingId = bindingId;
27326
+ this.bindingRevision = bindingRevision;
27327
+ this.agent = agent;
27328
+ this.agentIdentityDigest = agentIdentityDigest;
27329
+ this.workspacePath = workspacePath;
27330
+ this.workspaceIdentityDigest = workspaceIdentityDigest;
27331
+ this.allowedDeliveryTargetIds = Object.freeze([...allowedDeliveryTargetIds]);
27332
+ this.expiresAt = expiresAt;
27333
+ this.revocationEpoch = revocationEpoch;
27334
+ }
27335
+ };
27336
+ function digest(value) {
27337
+ return createHash2("sha256").update(value, "utf8").digest("hex");
27338
+ }
27339
+ function agentDigest(agent) {
27340
+ return digest(
27341
+ JSON.stringify({
27342
+ adapter: agent.adapterIdentity,
27343
+ agent: agent.agentIdentity,
27344
+ agentVersion: agent.agentVersion,
27345
+ arguments: agent.arguments,
27346
+ id: agent.id
27347
+ })
27348
+ );
27349
+ }
27350
+ async function workspaceDigest(path2) {
27351
+ const metadata = await stat7(path2);
27352
+ if (!metadata.isDirectory()) {
27353
+ throw new LocalBotAuthorizationError("binding_incompatible", "The Bot workspace is not a directory");
27354
+ }
27355
+ return digest(
27356
+ JSON.stringify({
27357
+ changedAtMilliseconds: metadata.ctimeMs,
27358
+ device: metadata.dev,
27359
+ inode: metadata.ino,
27360
+ path: path2
27361
+ })
27362
+ );
27363
+ }
27364
+ function exactTargets(left, right) {
27365
+ if (left.length !== right.length) {
27366
+ return false;
27367
+ }
27368
+ const expected = [...left].sort();
27369
+ const actual = [...right].sort();
27370
+ return expected.every((target, index) => target === actual[index]);
27371
+ }
27372
+ function rowString(row, key) {
27373
+ const value = Reflect.get(row, key);
27374
+ if (typeof value !== "string") {
27375
+ throw new LocalBotAuthorizationError("local_grant_invalid", "The local Bot grant is invalid");
27376
+ }
27377
+ return value;
27378
+ }
27379
+ function rowInteger(row, key) {
27380
+ const value = Reflect.get(row, key);
27381
+ if (typeof value !== "number" || !Number.isSafeInteger(value)) {
27382
+ throw new LocalBotAuthorizationError("local_grant_invalid", "The local Bot grant is invalid");
27383
+ }
27384
+ return value;
27385
+ }
27386
+ function parseTargets(encoded) {
27387
+ let value;
27388
+ try {
27389
+ value = JSON.parse(encoded);
27390
+ } catch (cause) {
27391
+ throw new LocalBotAuthorizationError("local_grant_invalid", "The local Bot grant is invalid", { cause });
27392
+ }
27393
+ if (!Array.isArray(value) || value.some((target) => typeof target !== "string")) {
27394
+ throw new LocalBotAuthorizationError("local_grant_invalid", "The local Bot grant is invalid");
27395
+ }
27396
+ return value.filter((target) => typeof target === "string");
27397
+ }
27398
+ var LocalBotGrantStore = class {
27399
+ #database;
27400
+ constructor(path2) {
27401
+ this.#database = new DatabaseSync3(path2);
27402
+ this.#database.exec(`
27403
+ CREATE TABLE IF NOT EXISTS local_bot_grants (
27404
+ local_grant_id TEXT PRIMARY KEY,
27405
+ bot_id TEXT NOT NULL,
27406
+ behavior_revision_id TEXT NOT NULL,
27407
+ behavior_digest TEXT NOT NULL,
27408
+ binding_id TEXT NOT NULL UNIQUE,
27409
+ binding_revision INTEGER NOT NULL,
27410
+ agent_ref TEXT NOT NULL,
27411
+ agent_identity_digest TEXT NOT NULL,
27412
+ workspace_ref TEXT NOT NULL,
27413
+ workspace_path TEXT NOT NULL,
27414
+ workspace_identity_digest TEXT NOT NULL,
27415
+ allowed_delivery_target_ids_json TEXT NOT NULL,
27416
+ unattended_policy_json TEXT NOT NULL,
27417
+ created_at INTEGER NOT NULL,
27418
+ expires_at INTEGER NOT NULL,
27419
+ revocation_epoch INTEGER NOT NULL DEFAULT 0,
27420
+ revoked_at INTEGER
27421
+ ) STRICT;
27422
+ CREATE TABLE IF NOT EXISTS local_bot_binding_resolutions (
27423
+ request_id TEXT PRIMARY KEY,
27424
+ binding_id TEXT NOT NULL,
27425
+ local_grant_id TEXT NOT NULL,
27426
+ resolved_at INTEGER NOT NULL,
27427
+ result TEXT NOT NULL CHECK (result IN ('approved', 'unavailable')),
27428
+ error_code TEXT,
27429
+ error_message TEXT
27430
+ ) STRICT;
27431
+ `);
27432
+ }
27433
+ approve = async (request, catalog, directories, bindingAuthorityId, now, signal) => {
27434
+ signal.throwIfAborted();
27435
+ const existing = this.#database.prepare(
27436
+ `SELECT grants.* FROM local_bot_binding_resolutions AS resolutions
27437
+ INNER JOIN local_bot_grants AS grants
27438
+ ON grants.local_grant_id = resolutions.local_grant_id
27439
+ WHERE resolutions.request_id = ? AND resolutions.binding_id = ?
27440
+ AND resolutions.result = 'approved'`
27441
+ ).get(request.requestId, request.bindingId);
27442
+ if (existing !== void 0) {
27443
+ return new BotExecutionBindingApprovedEvent(
27444
+ request.requestId,
27445
+ request.botId,
27446
+ request.behaviorRevisionId,
27447
+ request.bindingId,
27448
+ request.bindingRevision,
27449
+ rowString(existing, "local_grant_id"),
27450
+ rowString(existing, "agent_identity_digest"),
27451
+ rowString(existing, "workspace_identity_digest")
27452
+ );
27453
+ }
27454
+ const resolved = await this.resolveProposal(request, catalog, directories, bindingAuthorityId, signal);
27455
+ const localGrantId = `lbg_${randomUUID3()}`;
27456
+ const expiresAt = now + LOCAL_BOT_GRANT_LIFETIME_MILLISECONDS;
27457
+ this.#database.exec("BEGIN IMMEDIATE");
27458
+ try {
27459
+ this.#database.prepare(
27460
+ `INSERT INTO local_bot_grants (
27461
+ local_grant_id, bot_id, behavior_revision_id, behavior_digest,
27462
+ binding_id, binding_revision, agent_ref,
27463
+ agent_identity_digest, workspace_ref, workspace_path,
27464
+ workspace_identity_digest, allowed_delivery_target_ids_json,
27465
+ unattended_policy_json, created_at, expires_at
27466
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
27467
+ ).run(
27468
+ localGrantId,
27469
+ request.botId,
27470
+ request.behaviorRevisionId,
27471
+ request.behaviorDigest,
27472
+ request.bindingId,
27473
+ request.bindingRevision,
27474
+ request.agentRef,
27475
+ resolved.agentIdentityDigest,
27476
+ request.workspaceRef,
27477
+ resolved.workspacePath,
27478
+ resolved.workspaceIdentityDigest,
27479
+ JSON.stringify(request.allowedDeliveryTargets.map((target) => target.deliveryTargetId)),
27480
+ JSON.stringify({ localSideEffects: "owner-approval-required" }),
27481
+ now,
27482
+ expiresAt
27483
+ );
27484
+ this.#database.prepare(
27485
+ `INSERT INTO local_bot_binding_resolutions (
27486
+ request_id, binding_id, local_grant_id, resolved_at, result
27487
+ ) VALUES (?, ?, ?, ?, 'approved')`
27488
+ ).run(request.requestId, request.bindingId, localGrantId, now);
27489
+ this.#database.exec("COMMIT");
27490
+ } catch (cause) {
27491
+ this.#database.exec("ROLLBACK");
27492
+ throw cause;
27493
+ }
27494
+ signal.throwIfAborted();
27495
+ return new BotExecutionBindingApprovedEvent(
27496
+ request.requestId,
27497
+ request.botId,
27498
+ request.behaviorRevisionId,
27499
+ request.bindingId,
27500
+ request.bindingRevision,
27501
+ localGrantId,
27502
+ resolved.agentIdentityDigest,
27503
+ resolved.workspaceIdentityDigest
27504
+ );
27505
+ };
27506
+ resolveExecution = async (command, catalog, directories, bindingAuthorityId, now, signal) => {
27507
+ signal.throwIfAborted();
27508
+ const row = this.#database.prepare(
27509
+ `SELECT * FROM local_bot_grants
27510
+ WHERE local_grant_id = ? AND bot_id = ?
27511
+ AND behavior_revision_id = ? AND behavior_digest = ?
27512
+ AND binding_id = ? AND binding_revision = ?
27513
+ AND agent_ref = ? AND workspace_ref = ?
27514
+ AND revoked_at IS NULL AND expires_at > ?`
27515
+ ).get(
27516
+ command.localGrantId,
27517
+ command.botId,
27518
+ command.behaviorRevisionId,
27519
+ command.behaviorDigest,
27520
+ command.bindingId,
27521
+ command.bindingRevision,
27522
+ command.agentId,
27523
+ command.directoryId,
27524
+ now
27525
+ );
27526
+ if (row === void 0) {
27527
+ throw new LocalBotAuthorizationError(
27528
+ "binding_not_approved",
27529
+ "The Bot execution binding is not locally approved"
27530
+ );
27531
+ }
27532
+ const approvedTargets = parseTargets(rowString(row, "allowed_delivery_target_ids_json"));
27533
+ const requestedTargets = command.allowedDeliveryTargets.map((target) => target.deliveryTargetId);
27534
+ if (!exactTargets(approvedTargets, requestedTargets)) {
27535
+ throw new LocalBotAuthorizationError(
27536
+ "binding_not_approved",
27537
+ "The Bot execution target policy changed after local approval"
27538
+ );
27539
+ }
27540
+ const agent = catalog.find(command.agentId);
27541
+ const [adapterUnchanged, agentUnchanged] = await Promise.all([
27542
+ revalidateExecutable(agent.adapterIdentity),
27543
+ revalidateExecutable(agent.agentIdentity)
27544
+ ]);
27545
+ signal.throwIfAborted();
27546
+ const workspacePath = await directories.resolve(bindingAuthorityId, command.directoryId, signal);
27547
+ const currentAgentDigest = agentDigest(agent);
27548
+ const currentWorkspaceDigest = await workspaceDigest(workspacePath);
27549
+ signal.throwIfAborted();
27550
+ if (!adapterUnchanged || !agentUnchanged || currentAgentDigest !== rowString(row, "agent_identity_digest") || currentWorkspaceDigest !== rowString(row, "workspace_identity_digest") || workspacePath !== rowString(row, "workspace_path")) {
27551
+ this.revoke(rowString(row, "local_grant_id"), now);
27552
+ throw new LocalBotAuthorizationError(
27553
+ "binding_not_approved",
27554
+ "The Bot execution target changed and requires local approval"
27555
+ );
27556
+ }
27557
+ if (command.behaviorInstructions.length > 0 && !agent.capabilities.embeddedContextPrompt) {
27558
+ throw new LocalBotAuthorizationError(
27559
+ "binding_incompatible",
27560
+ "The local Agent cannot apply the approved Bot behavior"
27561
+ );
27562
+ }
27563
+ return new LocalBotGrant(
27564
+ rowString(row, "local_grant_id"),
27565
+ command.botId,
27566
+ command.behaviorRevisionId,
27567
+ command.behaviorDigest,
27568
+ command.bindingId,
27569
+ command.bindingRevision,
27570
+ agent,
27571
+ currentAgentDigest,
27572
+ workspacePath,
27573
+ currentWorkspaceDigest,
27574
+ approvedTargets,
27575
+ rowInteger(row, "expires_at"),
27576
+ rowInteger(row, "revocation_epoch")
27577
+ );
27578
+ };
27579
+ recordUnavailable = (request, code, message, now) => {
27580
+ this.#database.prepare(
27581
+ `INSERT OR IGNORE INTO local_bot_binding_resolutions (
27582
+ request_id, binding_id, local_grant_id, resolved_at,
27583
+ result, error_code, error_message
27584
+ ) VALUES (?, ?, '', ?, 'unavailable', ?, ?)`
27585
+ ).run(request.requestId, request.bindingId, now, code, message);
27586
+ };
27587
+ close = () => {
27588
+ this.#database.close();
27589
+ };
27590
+ resolveProposal = async (request, catalog, directories, bindingAuthorityId, signal) => {
27591
+ const agent = catalog.find(request.agentRef);
27592
+ if (request.requiredCapabilities.includes("embedded-context") && !agent.capabilities.embeddedContextPrompt) {
27593
+ throw new LocalBotAuthorizationError(
27594
+ "binding_incompatible",
27595
+ "The local Agent cannot apply embedded Bot context"
27596
+ );
27597
+ }
27598
+ if (request.requiredCapabilities.some((capability) => capability !== "embedded-context")) {
27599
+ throw new LocalBotAuthorizationError(
27600
+ "binding_incompatible",
27601
+ "The Bot requires an unsupported local Agent capability"
27602
+ );
27603
+ }
27604
+ const [adapterUnchanged, agentUnchanged] = await Promise.all([
27605
+ revalidateExecutable(agent.adapterIdentity),
27606
+ revalidateExecutable(agent.agentIdentity)
27607
+ ]);
27608
+ signal.throwIfAborted();
27609
+ if (!adapterUnchanged || !agentUnchanged) {
27610
+ throw new LocalBotAuthorizationError(
27611
+ "binding_incompatible",
27612
+ "The local Agent executable changed before approval"
27613
+ );
27614
+ }
27615
+ const workspacePath = await directories.resolve(bindingAuthorityId, request.workspaceRef, signal);
27616
+ return {
27617
+ agent,
27618
+ agentIdentityDigest: agentDigest(agent),
27619
+ workspaceIdentityDigest: await workspaceDigest(workspacePath),
27620
+ workspacePath
27621
+ };
27622
+ };
27623
+ revoke = (localGrantId, now) => {
27624
+ this.#database.prepare(
27625
+ `UPDATE local_bot_grants
27626
+ SET revoked_at = COALESCE(revoked_at, ?), revocation_epoch = revocation_epoch + 1
27627
+ WHERE local_grant_id = ? AND revoked_at IS NULL`
27628
+ ).run(now, localGrantId);
27629
+ };
27630
+ };
27631
+
27632
+ // src/bots/bot-context-applicator.ts
27633
+ var AppliedBotContext = class {
27634
+ resources;
27635
+ constructor(resources) {
27636
+ this.resources = Object.freeze([...resources]);
27637
+ }
27638
+ };
27639
+ var EmbeddedBotContextApplicator = class {
27640
+ apply = async (command, grant, resources, signal) => {
27641
+ signal.throwIfAborted();
27642
+ if (grant.botId !== command.botId || grant.behaviorRevisionId !== command.behaviorRevisionId || grant.behaviorDigest !== command.behaviorDigest) {
27643
+ throw new LocalBotAuthorizationError(
27644
+ "binding_not_approved",
27645
+ "The Bot behavior does not match its local authorization"
27646
+ );
27647
+ }
27648
+ if (command.behaviorInstructions.length === 0) {
27649
+ return new AppliedBotContext(resources);
27650
+ }
27651
+ if (!grant.agent.capabilities.embeddedContextPrompt) {
27652
+ throw new LocalBotAuthorizationError(
27653
+ "binding_incompatible",
27654
+ "The local Agent cannot enforce the Bot behavior context"
27655
+ );
27656
+ }
27657
+ const trustedContext = {
27658
+ mimeType: "text/markdown",
27659
+ name: "Mobius Bot behavior",
27660
+ text: command.behaviorInstructions,
27661
+ type: "embedded",
27662
+ uri: `mobius://bots/${encodeURIComponent(command.botId)}/behavior-revisions/${encodeURIComponent(command.behaviorRevisionId)}?sha256=${command.behaviorDigest}`
27663
+ };
27664
+ return new AppliedBotContext([trustedContext, ...resources]);
27665
+ };
27666
+ };
27667
+
27668
+ // src/bots/bot-execution-context.ts
27669
+ import { randomBytes } from "node:crypto";
27670
+ var ActiveBotExecutionContext = class {
27671
+ command;
27672
+ contextHandle;
27673
+ constructor(contextHandle, command) {
27674
+ this.contextHandle = contextHandle;
27675
+ this.command = command;
27676
+ }
27677
+ resolveTarget = (target) => {
27678
+ if (target === "current") {
27679
+ if (!(this.command.replyRoute instanceof BotConnectionReplyRoute)) {
27680
+ throw new LocalBotAuthorizationError(
27681
+ "delivery_target_not_allowed",
27682
+ "This Bot conversation has no external reply target"
27683
+ );
27684
+ }
27685
+ return this.command.replyRoute.deliveryTargetId;
27686
+ }
27687
+ const resolved = this.command.allowedDeliveryTargets.find((candidate) => candidate.alias === target);
27688
+ if (resolved === void 0) {
27689
+ throw new LocalBotAuthorizationError(
27690
+ "delivery_target_not_allowed",
27691
+ "The named Bot delivery target is not approved"
27692
+ );
27693
+ }
27694
+ return resolved.deliveryTargetId;
27695
+ };
27696
+ };
27697
+ var BotExecutionContextLease = class {
27698
+ context;
27699
+ #release;
27700
+ #released = false;
27701
+ constructor(context, release) {
27702
+ this.context = context;
27703
+ this.#release = release;
27704
+ }
27705
+ release = () => {
27706
+ if (this.#released) {
27707
+ return;
27708
+ }
27709
+ this.#released = true;
27710
+ this.#release();
27711
+ };
27712
+ };
27713
+ var BotExecutionContextRegistry = class {
27714
+ #activeByHandle = /* @__PURE__ */ new Map();
27715
+ #handlesBySession = /* @__PURE__ */ new Map();
27716
+ #inactiveHandles = /* @__PURE__ */ new Set();
27717
+ #now;
27718
+ constructor(now = Date.now) {
27719
+ this.#now = now;
27720
+ }
27721
+ activate = (command) => {
27722
+ let handle = this.#handlesBySession.get(command.sessionId);
27723
+ if (handle === void 0) {
27724
+ handle = `ctx_${randomBytes(32).toString("base64url")}`;
27725
+ this.#handlesBySession.set(command.sessionId, handle);
27726
+ }
27727
+ if (this.#activeByHandle.has(handle)) {
27728
+ throw new LocalBotAuthorizationError("session_busy", "The Bot execution context is already active");
27729
+ }
27730
+ const context = new ActiveBotExecutionContext(handle, command);
27731
+ this.#inactiveHandles.delete(handle);
27732
+ this.#activeByHandle.set(handle, context);
27733
+ return new BotExecutionContextLease(context, () => {
27734
+ if (this.#activeByHandle.get(handle) === context) {
27735
+ this.#activeByHandle.delete(handle);
27736
+ this.#inactiveHandles.add(handle);
27737
+ }
27738
+ });
27739
+ };
27740
+ read = (handle) => {
27741
+ const context = this.#activeByHandle.get(handle);
27742
+ if (context === void 0) {
27743
+ if (this.#inactiveHandles.has(handle)) {
27744
+ throw new LocalBotAuthorizationError(
27745
+ "execution_capability_expired",
27746
+ "The Bot execution capability has expired"
27747
+ );
27748
+ }
27749
+ throw new LocalBotAuthorizationError(
27750
+ "execution_context_required",
27751
+ "An active Bot execution context is required"
27752
+ );
27753
+ }
27754
+ if (Date.parse(context.command.executionDeadlineAt) <= this.#now()) {
27755
+ throw new LocalBotAuthorizationError(
27756
+ "execution_capability_expired",
27757
+ "The Bot execution capability has expired"
27758
+ );
27759
+ }
27760
+ return context;
27761
+ };
27762
+ };
27763
+
27764
+ // src/bots/bot-outbound-ipc.ts
27765
+ import { chmod as chmod2, mkdir as mkdir4, unlink } from "node:fs/promises";
27766
+ import { createServer } from "node:net";
27767
+ import { dirname as dirname6, isAbsolute as isAbsolute8 } from "node:path";
27768
+ import { fetch as fetch4 } from "undici";
27769
+ var BOT_IPC_REQUEST_LIMIT = 32 * 1024;
27770
+ var BOT_IPC_TIMEOUT_MILLISECONDS2 = 2e4;
27771
+ var BOT_RELAY_TIMEOUT_MILLISECONDS = 2e4;
27772
+ var IDENTIFIER_PATTERN6 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
27773
+ var WINDOWS_NAMED_PIPE_PREFIX = "\\\\.\\pipe\\";
27774
+ var BotOutboundIpcRequest = class {
27775
+ contextHandle;
27776
+ idempotencyKey;
27777
+ target;
27778
+ text;
27779
+ constructor(contextHandle, idempotencyKey, target, text) {
27780
+ this.contextHandle = contextHandle;
27781
+ this.idempotencyKey = idempotencyKey;
27782
+ this.target = target;
27783
+ this.text = text;
27784
+ }
27785
+ };
27786
+ function isRecord10(value) {
27787
+ return typeof value === "object" && value !== null && !Array.isArray(value);
27788
+ }
27789
+ function decodeRequest(encoded) {
27790
+ let value;
27791
+ try {
27792
+ value = JSON.parse(encoded);
27793
+ } catch (cause) {
27794
+ throw new LocalBotAuthorizationError("invalid_request", "The local Bot request is invalid", { cause });
27795
+ }
27796
+ if (!isRecord10(value)) {
27797
+ throw new LocalBotAuthorizationError("invalid_request", "The local Bot request is invalid");
27798
+ }
27799
+ const keys = Object.keys(value);
27800
+ if (keys.length !== 4 || !keys.every((key) => ["contextHandle", "idempotencyKey", "target", "text"].includes(key))) {
27801
+ throw new LocalBotAuthorizationError("invalid_request", "The local Bot request fields are invalid");
27802
+ }
27803
+ const contextHandle = value["contextHandle"];
27804
+ const idempotencyKey = value["idempotencyKey"];
27805
+ const target = value["target"];
27806
+ const text = value["text"];
27807
+ if (typeof contextHandle !== "string" || !/^ctx_[a-zA-Z0-9_-]{43}$/.test(contextHandle) || typeof idempotencyKey !== "string" || !IDENTIFIER_PATTERN6.test(idempotencyKey) || typeof target !== "string" || !IDENTIFIER_PATTERN6.test(target) || typeof text !== "string" || text.trim().length === 0 || text.length > 1e4) {
27808
+ throw new LocalBotAuthorizationError("invalid_request", "The local Bot request is invalid");
27809
+ }
27810
+ return new BotOutboundIpcRequest(contextHandle, idempotencyKey, target, text);
27811
+ }
27812
+ function relayEndpoint(relayUrl, context, target) {
27813
+ const endpoint = new URL(relayUrl);
27814
+ if (endpoint.protocol !== "ws:" && endpoint.protocol !== "wss:") {
27815
+ throw new LocalBotAuthorizationError("bot_service_unavailable", "The Mobius Relay URL is invalid");
27816
+ }
27817
+ endpoint.protocol = endpoint.protocol === "wss:" ? "https:" : "http:";
27818
+ endpoint.search = "";
27819
+ const execution = encodeURIComponent(context.command.executionId);
27820
+ if (target === "current") {
27821
+ context.resolveTarget(target);
27822
+ endpoint.pathname = `${MOBIUS_API_PREFIX}/v1/bot-executions/${execution}/reply-messages`;
27823
+ return endpoint;
27824
+ }
27825
+ const deliveryTargetId = context.resolveTarget(target);
27826
+ endpoint.pathname = `${MOBIUS_API_PREFIX}/v1/bot-executions/${execution}/delivery-targets/${encodeURIComponent(deliveryTargetId)}/messages`;
27827
+ return endpoint;
27828
+ }
27829
+ function daemonToken(relayUrl) {
27830
+ const token = relayUrl.searchParams.get("token") ?? "";
27831
+ if (!/^[a-zA-Z0-9_-]{32,256}$/.test(token)) {
27832
+ throw new LocalBotAuthorizationError("bot_service_unavailable", "The Runtime credential is unavailable");
27833
+ }
27834
+ return token;
27835
+ }
27836
+ async function decodeRelayResponse(response) {
27837
+ const encoded = await response.text();
27838
+ let value;
27839
+ try {
27840
+ value = JSON.parse(encoded);
27841
+ } catch (cause) {
27842
+ throw new LocalBotAuthorizationError("bot_service_unavailable", "The Mobius Relay returned invalid data", {
27843
+ cause
27844
+ });
27845
+ }
27846
+ if (response.status === 202 && isRecord10(value) && typeof value["outboundMessageId"] === "string") {
27847
+ return value["outboundMessageId"];
27848
+ }
27849
+ if (isRecord10(value) && isRecord10(value["error"])) {
27850
+ const error61 = value["error"];
27851
+ if (typeof error61["code"] === "string" && typeof error61["message"] === "string") {
27852
+ throw new LocalBotAuthorizationError(error61["code"], error61["message"]);
27853
+ }
27854
+ }
27855
+ throw new LocalBotAuthorizationError("bot_service_unavailable", "The Mobius Relay rejected the Bot action");
27856
+ }
27857
+ var BotOutboundIpcServer = class {
27858
+ #registry;
27859
+ #relayUrl;
27860
+ #server;
27861
+ #socketPath;
27862
+ #usesFilesystemSocket;
27863
+ constructor(socketPath, relayUrl, registry2) {
27864
+ const usesFilesystemSocket = !socketPath.startsWith(WINDOWS_NAMED_PIPE_PREFIX);
27865
+ if (usesFilesystemSocket && !isAbsolute8(socketPath)) {
27866
+ throw new Error("The Bot IPC path must be absolute");
27867
+ }
27868
+ this.#registry = registry2;
27869
+ this.#relayUrl = new URL(relayUrl);
27870
+ this.#server = createServer({ allowHalfOpen: true }, (socket) => this.accept(socket));
27871
+ this.#socketPath = socketPath;
27872
+ this.#usesFilesystemSocket = usesFilesystemSocket;
27873
+ }
27874
+ get socketPath() {
27875
+ return this.#socketPath;
27876
+ }
27877
+ listen = async (signal) => {
27878
+ signal.throwIfAborted();
27879
+ if (this.#usesFilesystemSocket) {
27880
+ await mkdir4(dirname6(this.#socketPath), { mode: 448, recursive: true });
27881
+ await unlink(this.#socketPath).catch((error61) => {
27882
+ if (!isRecord10(error61) || error61["code"] !== "ENOENT") {
27883
+ throw error61;
27884
+ }
27885
+ });
27886
+ }
27887
+ await new Promise((resolve5, reject) => {
27888
+ const fail = (error61) => reject(error61);
27889
+ this.#server.once("error", fail);
27890
+ this.#server.listen(this.#socketPath, () => {
27891
+ this.#server.removeListener("error", fail);
27892
+ resolve5();
27893
+ });
27894
+ });
27895
+ if (this.#usesFilesystemSocket) {
27896
+ await chmod2(this.#socketPath, 384);
27897
+ }
27898
+ signal.addEventListener("abort", this.abort, { once: true });
27899
+ if (signal.aborted) {
27900
+ this.abort();
27901
+ }
27902
+ };
27903
+ close = async () => {
27904
+ if (this.#server.listening) {
27905
+ await new Promise((resolve5, reject) => {
27906
+ this.#server.close((error61) => {
27907
+ if (error61 === void 0) {
27908
+ resolve5();
27909
+ return;
27910
+ }
27911
+ reject(error61);
27912
+ });
27913
+ });
27914
+ }
27915
+ if (this.#usesFilesystemSocket) {
27916
+ await unlink(this.#socketPath).catch((error61) => {
27917
+ if (!isRecord10(error61) || error61["code"] !== "ENOENT") {
27918
+ throw error61;
27919
+ }
27920
+ });
27921
+ }
27922
+ };
27923
+ #abort = () => {
27924
+ this.#server.close();
27925
+ };
27926
+ abort = () => this.#abort();
27927
+ accept = (socket) => {
27928
+ const chunks = [];
27929
+ let length = 0;
27930
+ let rejected = false;
27931
+ const controller = new AbortController();
27932
+ socket.setTimeout(BOT_IPC_TIMEOUT_MILLISECONDS2, () => {
27933
+ controller.abort(new Error("Bot IPC request timed out"));
27934
+ socket.destroy();
27935
+ });
27936
+ socket.on("data", (chunk) => {
27937
+ length += chunk.byteLength;
27938
+ if (length > BOT_IPC_REQUEST_LIMIT) {
27939
+ rejected = true;
27940
+ controller.abort(new Error("Bot IPC request is too large"));
27941
+ socket.end(
27942
+ JSON.stringify({
27943
+ error: { code: "invalid_request", message: "The local Bot request is too large" },
27944
+ ok: false
27945
+ })
27946
+ );
27947
+ return;
27948
+ }
27949
+ chunks.push(chunk);
27950
+ });
27951
+ socket.once("error", () => controller.abort());
27952
+ socket.once("close", () => controller.abort());
27953
+ socket.once("end", () => {
27954
+ if (rejected) {
27955
+ return;
27956
+ }
27957
+ void this.handle(Buffer.concat(chunks).toString("utf8").trim(), controller.signal).then(
27958
+ (outboundMessageId) => {
27959
+ if (!socket.destroyed) {
27960
+ socket.end(JSON.stringify({ ok: true, outboundMessageId }));
27961
+ }
27962
+ },
27963
+ (error61) => {
27964
+ if (socket.destroyed) {
27965
+ return;
27966
+ }
27967
+ const code = error61 instanceof LocalBotAuthorizationError ? error61.code : "bot_service_unavailable";
27968
+ const message = error61 instanceof LocalBotAuthorizationError ? error61.message : "The local Bot action could not be completed";
27969
+ socket.end(JSON.stringify({ error: { code, message }, ok: false }));
27970
+ }
27971
+ );
27972
+ });
27973
+ };
27974
+ handle = async (encoded, signal) => {
27975
+ const request = decodeRequest(encoded);
27976
+ const context = this.#registry.read(request.contextHandle);
27977
+ const timeout = AbortSignal.timeout(BOT_RELAY_TIMEOUT_MILLISECONDS);
27978
+ const requestSignal = AbortSignal.any([signal, timeout]);
27979
+ let response;
27980
+ try {
27981
+ response = await fetch4(relayEndpoint(this.#relayUrl, context, request.target), {
27982
+ body: JSON.stringify({ idempotencyKey: request.idempotencyKey, text: request.text }),
27983
+ headers: {
27984
+ authorization: `Bearer ${daemonToken(this.#relayUrl)}`,
27985
+ "content-type": "application/json",
27986
+ "x-mobius-bot-execution-capability": context.command.executionCapabilitySecret
27987
+ },
27988
+ method: "POST",
27989
+ signal: requestSignal
27990
+ });
27991
+ } catch (cause) {
27992
+ signal.throwIfAborted();
27993
+ throw new LocalBotAuthorizationError(
27994
+ timeout.aborted ? "bot_service_timeout" : "bot_service_unavailable",
27995
+ timeout.aborted ? "The Mobius Bot action timed out" : "The Mobius Relay is unavailable",
27996
+ { cause }
27997
+ );
27998
+ }
27999
+ return await decodeRelayResponse(response);
28000
+ };
28001
+ };
28002
+
28003
+ // src/native-sessions/service.ts
28004
+ import { randomUUID as randomUUID4 } from "node:crypto";
28005
+
28006
+ // src/native-sessions/codex-history.ts
28007
+ import { spawn as spawn4 } from "node:child_process";
28008
+ var responseSchema = external_exports.union([
28009
+ external_exports.object({
28010
+ id: external_exports.number(),
28011
+ error: external_exports.object({ code: external_exports.number(), message: external_exports.string() })
28012
+ }),
28013
+ external_exports.object({ id: external_exports.number(), result: external_exports.unknown() }),
28014
+ external_exports.object({ method: external_exports.string() })
28015
+ ]);
28016
+ var threadSchema = external_exports.object({
28017
+ thread: external_exports.object({
28018
+ id: nativeSessionIdSchema,
28019
+ cwd: external_exports.string().min(1).max(2048).refine((path2) => !path2.includes("\0"))
28020
+ })
28021
+ });
28022
+ var turnsSchema = external_exports.object({
28023
+ data: external_exports.array(external_exports.object({ items: external_exports.array(external_exports.unknown()).max(1e5) })).max(SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT),
28024
+ nextCursor: external_exports.string().nullish()
28025
+ });
28026
+ var itemTypeSchema = external_exports.object({ type: external_exports.string().min(1).max(80) });
28027
+ var userMessageSchema = external_exports.object({
28028
+ content: external_exports.array(external_exports.unknown()).max(1e4)
28029
+ });
28030
+ var textSchema = external_exports.object({ text: external_exports.string() });
28031
+ var imageSchema = external_exports.object({ url: external_exports.string() });
28032
+ var agentMessageSchema = textSchema.extend({ phase: external_exports.string().nullish() });
28033
+ function decodeHistory(thread, value) {
28034
+ const page = turnsSchema.parse(value);
28035
+ const messages = [];
28036
+ let characters = 0;
28037
+ let imageCharacters = 0;
28038
+ let truncated = page.nextCursor != null;
28039
+ for (const turn of page.data.toReversed()) {
28040
+ for (const item of turn.items) {
28041
+ const { type } = itemTypeSchema.parse(item);
28042
+ let message;
28043
+ if (type === "userMessage") {
26694
28044
  const { content } = userMessageSchema.parse(item);
26695
28045
  const parsed = parseNativeHistoryText(
26696
28046
  content.map((block) => {
@@ -26967,7 +28317,7 @@ var NativeSessionService = class {
26967
28317
  if (authorized === null) {
26968
28318
  continue;
26969
28319
  }
26970
- const entryId = randomUUID2();
28320
+ const entryId = randomUUID4();
26971
28321
  if (this.#entries.size >= 5e3) {
26972
28322
  this.#entries.clear();
26973
28323
  }
@@ -26995,7 +28345,7 @@ var NativeSessionService = class {
26995
28345
  "invalid_native_session_response"
26996
28346
  );
26997
28347
  }
26998
- nextCursor = randomUUID2();
28348
+ nextCursor = randomUUID4();
26999
28349
  if (this.#cursors.size >= 500) {
27000
28350
  this.#cursors.clear();
27001
28351
  }
@@ -27213,13 +28563,13 @@ var NativeSessionService = class {
27213
28563
  };
27214
28564
 
27215
28565
  // src/prompt-artifact-resolver.ts
27216
- import { createHash as createHash2 } from "node:crypto";
27217
- import { fetch as fetch4 } from "undici";
28566
+ import { createHash as createHash3 } from "node:crypto";
28567
+ import { fetch as fetch5 } from "undici";
27218
28568
  var ARTIFACT_SCHEME = "mobius-artifact:";
27219
28569
  var ARTIFACT_DOWNLOAD_TIMEOUT_MILLISECONDS = 2e4;
27220
28570
  var MAX_AGENT_IMAGE_BASE64_LENGTH = 4e6;
27221
28571
  var MAX_AGENT_RESOURCE_BYTE_LENGTH = 1e6;
27222
- var IDENTIFIER_PATTERN5 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
28572
+ var IDENTIFIER_PATTERN7 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
27223
28573
  var PromptArtifactError = class extends Error {
27224
28574
  code;
27225
28575
  constructor(code, message, options = {}) {
@@ -27262,7 +28612,7 @@ function parseReference(resource) {
27262
28612
  const encodedByteLength2 = url2.searchParams.get("byteLength") ?? "";
27263
28613
  const sha256 = url2.searchParams.get("sha256") ?? "";
27264
28614
  const byteLength = Number(encodedByteLength2);
27265
- if (url2.protocol !== ARTIFACT_SCHEME || url2.hash.length > 0 || resource.type !== "link" || resource.text.length > 0 || !IDENTIFIER_PATTERN5.test(artifactId) || keys.length !== 2 || keys[0] !== "byteLength" || keys[1] !== "sha256" || !/^[1-9][0-9]*$/.test(encodedByteLength2) || !Number.isSafeInteger(byteLength) || !/^[a-f0-9]{64}$/.test(sha256)) {
28615
+ if (url2.protocol !== ARTIFACT_SCHEME || url2.hash.length > 0 || resource.type !== "link" || resource.text.length > 0 || !IDENTIFIER_PATTERN7.test(artifactId) || keys.length !== 2 || keys[0] !== "byteLength" || keys[1] !== "sha256" || !/^[1-9][0-9]*$/.test(encodedByteLength2) || !Number.isSafeInteger(byteLength) || !/^[a-f0-9]{64}$/.test(sha256)) {
27266
28616
  throw new PromptArtifactError("artifact_reference_invalid", "The prompt artifact reference is invalid");
27267
28617
  }
27268
28618
  return new PromptArtifactReference(artifactId, byteLength, sha256, resource);
@@ -27323,7 +28673,7 @@ async function download(config2, command, reference, signal) {
27323
28673
  const requestSignal = AbortSignal.any([signal, timeoutSignal]);
27324
28674
  let response;
27325
28675
  try {
27326
- response = await fetch4(downloadUrl(config2, command, reference), {
28676
+ response = await fetch5(downloadUrl(config2, command, reference), {
27327
28677
  dispatcher: environmentProxyDispatcher,
27328
28678
  headers: { accept: reference.resource.mimeType },
27329
28679
  signal: requestSignal
@@ -27343,7 +28693,7 @@ async function download(config2, command, reference, signal) {
27343
28693
  );
27344
28694
  }
27345
28695
  const bytes = await responseBytes(response, reference.byteLength, requestSignal);
27346
- if (createHash2("sha256").update(bytes).digest("hex") !== reference.sha256) {
28696
+ if (createHash3("sha256").update(bytes).digest("hex") !== reference.sha256) {
27347
28697
  throw new PromptArtifactError(
27348
28698
  "artifact_integrity_failed",
27349
28699
  "The prompt artifact failed integrity validation"
@@ -27488,7 +28838,7 @@ function connectRelay(url2, signal) {
27488
28838
  }
27489
28839
 
27490
28840
  // src/relay-connection/liveness.ts
27491
- import { randomUUID as randomUUID3 } from "node:crypto";
28841
+ import { randomUUID as randomUUID5 } from "node:crypto";
27492
28842
  var HEARTBEAT_ACK_TIMEOUT_MILLISECONDS = 1e4;
27493
28843
  var HEARTBEAT_INTERVAL_MILLISECONDS = 2e4;
27494
28844
  var RelayLivenessState = class {
@@ -27576,7 +28926,7 @@ var RelayConnectionLiveness = class {
27576
28926
  }
27577
28927
  throw new Error("Heartbeat was scheduled in an invalid state");
27578
28928
  }
27579
- const heartbeatId = randomUUID3();
28929
+ const heartbeatId = randomUUID5();
27580
28930
  this.#state = new AwaitingHeartbeatAckState(
27581
28931
  heartbeatId,
27582
28932
  this.#timer.schedule(this.#handleTimeout, HEARTBEAT_ACK_TIMEOUT_MILLISECONDS)
@@ -27592,8 +28942,8 @@ var RelayConnectionLiveness = class {
27592
28942
 
27593
28943
  // src/relay-connection/session-event-outbox.ts
27594
28944
  import { mkdirSync as mkdirSync3 } from "node:fs";
27595
- import { dirname as dirname6 } from "node:path";
27596
- import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
28945
+ import { dirname as dirname7 } from "node:path";
28946
+ import { DatabaseSync as DatabaseSync4 } from "node:sqlite";
27597
28947
  function readPendingEnvelope(row) {
27598
28948
  if (typeof row !== "object" || row === null || Array.isArray(row)) {
27599
28949
  throw new Error("SQLite returned an invalid session event outbox row");
@@ -27607,8 +28957,8 @@ function readPendingEnvelope(row) {
27607
28957
  var SessionEventOutbox = class {
27608
28958
  #database;
27609
28959
  constructor(path2) {
27610
- mkdirSync3(dirname6(path2), { recursive: true });
27611
- this.#database = new DatabaseSync3(path2);
28960
+ mkdirSync3(dirname7(path2), { recursive: true });
28961
+ this.#database = new DatabaseSync4(path2);
27612
28962
  this.#database.exec(`
27613
28963
  CREATE TABLE IF NOT EXISTS relay_session_event_outbox (
27614
28964
  ordinal INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -27799,6 +29149,12 @@ var RELAY_RECONNECT_DELAY_MILLISECONDS = 500;
27799
29149
  var RELAY_CONNECTION_REFRESH_MILLISECONDS = 20 * 60 * 1e3;
27800
29150
  var ACTIVE_TURN_RECONCILIATION_TIMEOUT_MILLISECONDS = 2e4;
27801
29151
  var ACTIVE_TURN_RECONCILIATION_CLOSE_CODE = 4009;
29152
+ function botIpcSocketPath() {
29153
+ if (process.platform === "win32") {
29154
+ return `\\\\.\\pipe\\mobius-bot-${randomUUID6()}`;
29155
+ }
29156
+ return join16("/tmp", `mobius-bot-${randomUUID6()}.sock`);
29157
+ }
27802
29158
  var RelayConnectionRefreshState = class {
27803
29159
  };
27804
29160
  var ScheduledRelayConnectionRefreshState = class extends RelayConnectionRefreshState {
@@ -28056,7 +29412,7 @@ async function reconcileActiveTurn(config2, turn, signal) {
28056
29412
  const requestSignal = AbortSignal.any([signal, timeoutSignal]);
28057
29413
  let response;
28058
29414
  try {
28059
- response = await fetch5(activeTurnReconciliationEndpoint(config2, turn), {
29415
+ response = await fetch6(activeTurnReconciliationEndpoint(config2, turn), {
28060
29416
  body: JSON.stringify({ outcome: { kind: "running" } }),
28061
29417
  dispatcher: environmentProxyDispatcher,
28062
29418
  headers: { "content-type": "application/json" },
@@ -28159,13 +29515,13 @@ function reportFailure(publisher, command, code, message, attemptId) {
28159
29515
  );
28160
29516
  }
28161
29517
  function operationErrorCode(error61) {
28162
- if (error61 instanceof AcpExecutionError || error61 instanceof LocalAuthorizationError || error61 instanceof LocalAgentCatalogError || error61 instanceof PromptArtifactError) {
29518
+ if (error61 instanceof AcpExecutionError || error61 instanceof LocalAuthorizationError || error61 instanceof LocalAgentCatalogError || error61 instanceof LocalBotAuthorizationError || error61 instanceof PromptArtifactError) {
28163
29519
  return error61.code;
28164
29520
  }
28165
29521
  return "session_operation_failed";
28166
29522
  }
28167
29523
  function operationErrorMessage(error61) {
28168
- if (error61 instanceof AcpExecutionError || error61 instanceof LocalAuthorizationError || error61 instanceof LocalAgentCatalogError || error61 instanceof PromptArtifactError) {
29524
+ if (error61 instanceof AcpExecutionError || error61 instanceof LocalAuthorizationError || error61 instanceof LocalAgentCatalogError || error61 instanceof LocalBotAuthorizationError || error61 instanceof PromptArtifactError) {
28169
29525
  return error61.message;
28170
29526
  }
28171
29527
  return "The local agent operation could not be completed";
@@ -28430,6 +29786,175 @@ async function executePrompt(outbox, publisher, command, config2, directories, a
28430
29786
  console.error("Mobius daemon command failed", error61);
28431
29787
  }
28432
29788
  }
29789
+ function botExecutionAgent(agent, contextHandle, socketPath) {
29790
+ return new LocalAgentDefinition(
29791
+ agent.id,
29792
+ agent.label,
29793
+ agent.command,
29794
+ agent.arguments,
29795
+ {
29796
+ ...agent.environment,
29797
+ MOBIUS_BOT_CONTEXT: contextHandle,
29798
+ MOBIUS_BOT_SOCKET: socketPath,
29799
+ MOBIUS_RELAY_TOKEN: "",
29800
+ MOBIUS_RELAY_URL: ""
29801
+ },
29802
+ agent.adapterVersion,
29803
+ agent.agentVersion,
29804
+ agent.adapterIdentity,
29805
+ agent.agentIdentity,
29806
+ agent.promptTimeoutMilliseconds,
29807
+ agent.capabilities
29808
+ );
29809
+ }
29810
+ async function executeBotPrompt(outbox, publisher, command, config2, directories, audit, sessions, grants, contexts, applicator, ipc, attemptId, signal) {
29811
+ try {
29812
+ if (command.additionalDirectoryIds.length > 0) {
29813
+ throw new LocalBotAuthorizationError(
29814
+ "binding_not_approved",
29815
+ "The Bot execution requested unapproved additional directories"
29816
+ );
29817
+ }
29818
+ const deadline = Date.parse(command.executionDeadlineAt);
29819
+ const remaining = deadline - Date.now();
29820
+ if (!Number.isSafeInteger(deadline) || remaining <= 0) {
29821
+ throw new LocalBotAuthorizationError("turn_expired", "The Bot execution deadline has expired");
29822
+ }
29823
+ const grant = await grants.resolveExecution(
29824
+ command,
29825
+ config2.catalog,
29826
+ directories,
29827
+ config2.bindingId,
29828
+ Date.now(),
29829
+ signal
29830
+ );
29831
+ const attachments = await resolvePromptArtifacts(config2, command, signal);
29832
+ const applied = await applicator.apply(command, grant, attachments.resources, signal);
29833
+ const lease = contexts.activate(command);
29834
+ try {
29835
+ const deadlineSignal = AbortSignal.timeout(remaining);
29836
+ const executionSignal = AbortSignal.any([signal, deadlineSignal]);
29837
+ const agent = botExecutionAgent(grant.agent, lease.context.contextHandle, ipc.socketPath);
29838
+ audit.record({
29839
+ commandId: command.commandId,
29840
+ details: {
29841
+ behaviorRevisionId: command.behaviorRevisionId,
29842
+ bindingId: command.bindingId,
29843
+ botId: command.botId,
29844
+ executionId: command.executionId,
29845
+ localGrantId: command.localGrantId
29846
+ },
29847
+ event: "bot_session_authorized",
29848
+ sessionId: command.sessionId
29849
+ });
29850
+ outbox.transitionExecution(command.commandId, "running");
29851
+ publisher.recordAttempt(
29852
+ command.sessionId,
29853
+ encodeSessionStartedEvent({
29854
+ attemptId,
29855
+ commandId: command.commandId,
29856
+ kind: SESSION_STARTED_KIND,
29857
+ sessionId: command.sessionId
29858
+ }),
29859
+ attemptId
29860
+ );
29861
+ const result = await sessions.runPrompt({
29862
+ additionalDirectories: [],
29863
+ agent,
29864
+ commandId: command.commandId,
29865
+ cwd: grant.workspacePath,
29866
+ images: attachments.images,
29867
+ onActivity: (activity) => {
29868
+ publisher.recordAttempt(
29869
+ command.sessionId,
29870
+ encodeAgentActivityEvent({
29871
+ activityId: activity.activityId,
29872
+ activityType: activity.activityType,
29873
+ commandId: command.commandId,
29874
+ content: activity.content,
29875
+ detail: activity.detail,
29876
+ input: activity.input,
29877
+ kind: AGENT_ACTIVITY_KIND,
29878
+ locations: activity.locations,
29879
+ name: activity.name,
29880
+ output: activity.output,
29881
+ sequence: activity.sequence,
29882
+ sessionId: command.sessionId,
29883
+ status: activity.status,
29884
+ title: activity.title,
29885
+ toolKind: activity.toolKind
29886
+ }),
29887
+ attemptId
29888
+ );
29889
+ return Promise.resolve();
29890
+ },
29891
+ onText: (text) => {
29892
+ publisher.recordAttempt(
29893
+ command.sessionId,
29894
+ encodeAgentMessageDeltaEvent({
29895
+ commandId: command.commandId,
29896
+ kind: AGENT_MESSAGE_DELTA_KIND,
29897
+ sessionId: command.sessionId,
29898
+ text
29899
+ }),
29900
+ attemptId
29901
+ );
29902
+ return Promise.resolve();
29903
+ },
29904
+ prompt: command.prompt,
29905
+ resources: applied.resources,
29906
+ sessionId: command.sessionId,
29907
+ signal: executionSignal
29908
+ });
29909
+ publisher.recordAttempt(
29910
+ command.sessionId,
29911
+ encodeSessionCompletedEvent({
29912
+ commandId: command.commandId,
29913
+ kind: SESSION_COMPLETED_KIND,
29914
+ sessionId: command.sessionId,
29915
+ stopReason: result.stopReason
29916
+ }),
29917
+ attemptId
29918
+ );
29919
+ outbox.transitionExecution(
29920
+ command.commandId,
29921
+ result.stopReason === "cancelled" ? "cancelled" : "succeeded"
29922
+ );
29923
+ audit.record({
29924
+ commandId: command.commandId,
29925
+ details: { botId: command.botId, executionId: command.executionId },
29926
+ event: result.stopReason === "cancelled" ? "bot_session_cancelled" : "bot_session_completed",
29927
+ sessionId: command.sessionId
29928
+ });
29929
+ } finally {
29930
+ lease.release();
29931
+ }
29932
+ } catch (error61) {
29933
+ const failure = Date.parse(command.executionDeadlineAt) <= Date.now() ? new LocalBotAuthorizationError("turn_expired", "The Bot execution deadline has expired", {
29934
+ cause: error61
29935
+ }) : error61;
29936
+ audit.record({
29937
+ commandId: command.commandId,
29938
+ details: {
29939
+ botId: command.botId,
29940
+ code: operationErrorCode(failure),
29941
+ executionId: command.executionId
29942
+ },
29943
+ event: "bot_session_failed",
29944
+ sessionId: command.sessionId
29945
+ });
29946
+ const code = operationErrorCode(failure);
29947
+ reportFailure(
29948
+ publisher,
29949
+ command,
29950
+ code === "session_operation_failed" ? "agent_execution_failed" : code,
29951
+ code === "session_operation_failed" ? "The local agent could not complete the Bot request" : operationErrorMessage(failure),
29952
+ attemptId
29953
+ );
29954
+ outbox.transitionExecution(command.commandId, "failed");
29955
+ console.error("Mobius daemon Bot command failed", failure);
29956
+ }
29957
+ }
28433
29958
  function waitForRelayRetry(signal, timer) {
28434
29959
  if (signal.aborted) {
28435
29960
  return Promise.resolve();
@@ -28466,7 +29991,7 @@ async function publishAgentCatalogUntilAvailable(config2, signal, timer) {
28466
29991
  }
28467
29992
  }
28468
29993
  }
28469
- async function runRelayConnection(config2, directories, audit, sessions, installations, installationObserver, nativeSessions, outbox, publisher, activeTurns, activeAttemptIds, onConnected, signal, timer) {
29994
+ async function runRelayConnection(config2, directories, audit, sessions, installations, installationObserver, nativeSessions, outbox, publisher, grants, contexts, applicator, ipc, activeTurns, activeAttemptIds, onConnected, signal, timer) {
28470
29995
  const relayUrl = new URL(config2.relayUrl);
28471
29996
  relayUrl.searchParams.set("liveness", "1");
28472
29997
  const socket = await connectRelay(relayUrl, signal);
@@ -28563,6 +30088,62 @@ async function runRelayConnection(config2, directories, audit, sessions, install
28563
30088
  }
28564
30089
  return;
28565
30090
  }
30091
+ if (kind === BOT_BINDING_APPROVAL_REQUEST_KIND) {
30092
+ const request = decodeBotExecutionBindingApprovalRequest(encoded);
30093
+ void grants.approve(
30094
+ request,
30095
+ config2.catalog,
30096
+ directories,
30097
+ config2.bindingId,
30098
+ Date.now(),
30099
+ connectionController.signal
30100
+ ).then((approved) => {
30101
+ audit.record({
30102
+ commandId: request.requestId,
30103
+ details: {
30104
+ behaviorRevisionId: request.behaviorRevisionId,
30105
+ bindingId: request.bindingId,
30106
+ botId: request.botId,
30107
+ localGrantId: approved.localGrantId
30108
+ },
30109
+ event: "bot_binding_approved",
30110
+ sessionId: `bot-binding:${request.bindingId}`
30111
+ });
30112
+ if (socket.readyState === WebSocket2.OPEN) {
30113
+ send(socket, encodeBotExecutionBindingApprovedEvent(approved));
30114
+ }
30115
+ }).catch((error61) => {
30116
+ if (connectionController.signal.aborted) {
30117
+ return;
30118
+ }
30119
+ const code = error61 instanceof LocalBotAuthorizationError ? error61.code : "binding_incompatible";
30120
+ const message = error61 instanceof LocalBotAuthorizationError ? error61.message : "The local execution target is incompatible";
30121
+ grants.recordUnavailable(request, code, message, Date.now());
30122
+ audit.record({
30123
+ commandId: request.requestId,
30124
+ details: { bindingId: request.bindingId, botId: request.botId, code },
30125
+ event: "bot_binding_unavailable",
30126
+ sessionId: `bot-binding:${request.bindingId}`
30127
+ });
30128
+ if (socket.readyState === WebSocket2.OPEN) {
30129
+ send(
30130
+ socket,
30131
+ encodeBotExecutionBindingUnavailableEvent(
30132
+ new BotExecutionBindingUnavailableEvent(
30133
+ request.requestId,
30134
+ request.botId,
30135
+ request.behaviorRevisionId,
30136
+ request.bindingId,
30137
+ request.bindingRevision,
30138
+ code,
30139
+ message
30140
+ )
30141
+ )
30142
+ );
30143
+ }
30144
+ });
30145
+ return;
30146
+ }
28566
30147
  if (kind === NATIVE_SESSION_CANCEL_KIND) {
28567
30148
  const command2 = decodeNativeSessionCancel(encoded);
28568
30149
  const pending = nativeRequests.get(command2.requestId);
@@ -28761,6 +30342,44 @@ async function runRelayConnection(config2, directories, audit, sessions, install
28761
30342
  });
28762
30343
  return;
28763
30344
  }
30345
+ if (kind === BOT_SESSION_PROMPT_KIND) {
30346
+ const command2 = decodeBotSessionPromptCommand(encoded);
30347
+ if (activeTurns.has(command2.commandId)) {
30348
+ return;
30349
+ }
30350
+ const receipt2 = outbox.claimExecution(command2.commandId, command2.sessionId, encoded);
30351
+ if (receipt2.kind === "duplicate") {
30352
+ return;
30353
+ }
30354
+ const turn2 = new ActiveDaemonTurn(command2, receipt2.attemptId);
30355
+ activeTurns.set(command2.commandId, turn2);
30356
+ activeAttemptIds.set(command2.sessionId, receipt2.attemptId);
30357
+ void executeBotPrompt(
30358
+ outbox,
30359
+ publisher,
30360
+ command2,
30361
+ config2,
30362
+ directories,
30363
+ audit,
30364
+ sessions,
30365
+ grants,
30366
+ contexts,
30367
+ applicator,
30368
+ ipc,
30369
+ receipt2.attemptId,
30370
+ turn2.signal
30371
+ ).catch((error61) => {
30372
+ console.error("Mobius daemon Bot turn failed", error61);
30373
+ }).finally(() => {
30374
+ activeTurns.delete(command2.commandId);
30375
+ if (activeAttemptIds.get(command2.sessionId) === receipt2.attemptId) {
30376
+ activeAttemptIds.delete(command2.sessionId);
30377
+ }
30378
+ turn2.finish();
30379
+ connectionRefresh.afterTurnFinished();
30380
+ });
30381
+ return;
30382
+ }
28764
30383
  if (kind !== SESSION_PROMPT_KIND) {
28765
30384
  throw new Error("Unsupported protocol message");
28766
30385
  }
@@ -28851,6 +30470,10 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
28851
30470
  const sessionStore = new SqliteAcpSessionStore(config2.auditDatabasePath);
28852
30471
  const outbox = new SessionEventOutbox(config2.auditDatabasePath);
28853
30472
  const publisher = new DaemonSessionEventPublisher(outbox);
30473
+ const grants = new LocalBotGrantStore(config2.auditDatabasePath);
30474
+ const contexts = new BotExecutionContextRegistry();
30475
+ const applicator = new EmbeddedBotContextApplicator();
30476
+ const ipc = new BotOutboundIpcServer(botIpcSocketPath(), config2.relayUrl, contexts);
28854
30477
  const activeTurns = /* @__PURE__ */ new Map();
28855
30478
  const activeAttemptIds = /* @__PURE__ */ new Map();
28856
30479
  const recordSessionEvent = (sessionId, payload) => {
@@ -28889,6 +30512,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
28889
30512
  };
28890
30513
  const catalogPublication = publishAgentCatalogUntilAvailable(config2, signal, timer);
28891
30514
  try {
30515
+ await ipc.listen(signal);
28892
30516
  while (!signal.aborted) {
28893
30517
  try {
28894
30518
  await runRelayConnection(
@@ -28901,6 +30525,10 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
28901
30525
  nativeSessions,
28902
30526
  outbox,
28903
30527
  publisher,
30528
+ grants,
30529
+ contexts,
30530
+ applicator,
30531
+ ipc,
28904
30532
  activeTurns,
28905
30533
  activeAttemptIds,
28906
30534
  announceConnection,
@@ -28932,12 +30560,20 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
28932
30560
  await installations.close();
28933
30561
  } finally {
28934
30562
  try {
28935
- await sessions.close();
30563
+ await ipc.close();
28936
30564
  } finally {
28937
30565
  try {
28938
- sessionStore.close();
30566
+ await sessions.close();
28939
30567
  } finally {
28940
- outbox.close();
30568
+ try {
30569
+ sessionStore.close();
30570
+ } finally {
30571
+ try {
30572
+ grants.close();
30573
+ } finally {
30574
+ outbox.close();
30575
+ }
30576
+ }
28941
30577
  }
28942
30578
  }
28943
30579
  }
@@ -28955,11 +30591,13 @@ Usage:
28955
30591
  mobius pair --url <relay-url> --code <pairing-code> [--workspace <directory>]
28956
30592
  mobius start --channel <channel-id>
28957
30593
  mobius agents [--json]
30594
+ mobius bot message send --target <current|alias> --text <message>
28958
30595
 
28959
30596
  Commands:
28960
30597
  pair Pair this machine and start its local daemon
28961
30598
  start Start the local daemon for a saved channel
28962
30599
  agents Show detected, missing, and integration-ready Agents
30600
+ bot Invoke Bot-scoped actions from an active local execution
28963
30601
 
28964
30602
  Pairing grants this browser access to the machine with your user account's permissions.
28965
30603
  New conversations default to ~/.mobius/workspace; choose other directories in the browser.
@@ -28975,7 +30613,7 @@ async function main() {
28975
30613
  if (arguments_.length > 1 || arguments_.length === 1 && arguments_[0] !== "--json") {
28976
30614
  throw new Error("Usage: mobius agents [--json]");
28977
30615
  }
28978
- await mkdir4(loadDefaultWorkspace(), { recursive: true, mode: 448 });
30616
+ await mkdir5(loadDefaultWorkspace(), { recursive: true, mode: 448 });
28979
30617
  const inventory = await discoverLocalAgentInventory({
28980
30618
  defaultWorkspace: loadDefaultWorkspace(),
28981
30619
  environment: process.env,
@@ -28984,6 +30622,18 @@ async function main() {
28984
30622
  process.stdout.write(formatAgentDiagnostics(inventory, arguments_[0] === "--json"));
28985
30623
  return;
28986
30624
  }
30625
+ if (command === "bot") {
30626
+ if (process.argv[3] !== "message" || process.argv[4] !== "send") {
30627
+ throw new BotMessageCommandError(
30628
+ "invalid_request",
30629
+ "Usage: mobius bot message send --target <current|alias> --text <message>"
30630
+ );
30631
+ }
30632
+ const outboundMessageId = await executeBotMessageCommand(process.argv.slice(5), process.env, shutdown.signal);
30633
+ process.stdout.write(`${JSON.stringify({ outboundMessageId })}
30634
+ `);
30635
+ return;
30636
+ }
28987
30637
  let config2;
28988
30638
  if (command === "pair") {
28989
30639
  process.stdout.write(`mobius version: ${package_default.version}
@@ -29023,7 +30673,8 @@ try {
29023
30673
  } catch (error61) {
29024
30674
  if (!shutdown.signal.aborted) {
29025
30675
  const message = error61 instanceof Error ? error61.message : "Unknown failure";
29026
- process.stderr.write(`Mobius daemon failed: ${message}
30676
+ const code = error61 instanceof BotMessageCommandError ? `${error61.code}: ` : "";
30677
+ process.stderr.write(`Mobius daemon failed: ${code}${message}
29027
30678
  `);
29028
30679
  process.exitCode = 1;
29029
30680
  }