@moxt-ai/mobius 0.0.21 → 0.0.23

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 +1872 -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 +1930 -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 +241 -8
  32. package/dist/run-daemon.js.map +1 -1
  33. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3708,7 +3708,7 @@ var $ZodUnion = /* @__PURE__ */ $constructor("$ZodUnion", (inst, def) => {
3708
3708
  defineLazyInternal(inst, "optout", (zod) => zod.def.options.some((o) => o._zod.optout === "optional") ? "optional" : void 0);
3709
3709
  defineLazyInternal(inst, "values", (zod) => {
3710
3710
  if (zod.def.options.every((o) => o._zod.values)) {
3711
- return new Set(zod.def.options.flatMap((option) => Array.from(option._zod.values)));
3711
+ return new Set(zod.def.options.flatMap((option2) => Array.from(option2._zod.values)));
3712
3712
  }
3713
3713
  return void 0;
3714
3714
  });
@@ -3726,8 +3726,8 @@ var $ZodUnion = /* @__PURE__ */ $constructor("$ZodUnion", (inst, def) => {
3726
3726
  }
3727
3727
  let async = false;
3728
3728
  const results = [];
3729
- for (const option of def.options) {
3730
- const result = option._zod.run({
3729
+ for (const option2 of def.options) {
3730
+ const result = option2._zod.run({
3731
3731
  value: payload.value,
3732
3732
  issues: []
3733
3733
  }, ctx);
@@ -3786,8 +3786,8 @@ var $ZodXor = /* @__PURE__ */ $constructor("$ZodXor", (inst, def) => {
3786
3786
  }
3787
3787
  let async = false;
3788
3788
  const results = [];
3789
- for (const option of def.options) {
3790
- const result = option._zod.run({
3789
+ for (const option2 of def.options) {
3790
+ const result = option2._zod.run({
3791
3791
  value: payload.value,
3792
3792
  issues: []
3793
3793
  }, ctx);
@@ -3811,10 +3811,10 @@ function getDiscriminatedOption(union2, value) {
3811
3811
  if (!map2) {
3812
3812
  map2 = /* @__PURE__ */ new Map();
3813
3813
  const { options, discriminator } = internals.def;
3814
- for (const option of options) {
3815
- for (const v of option._zod.propValues?.[discriminator] ?? [])
3814
+ for (const option2 of options) {
3815
+ for (const v of option2._zod.propValues?.[discriminator] ?? [])
3816
3816
  if (!map2.has(v))
3817
- map2.set(v, option);
3817
+ map2.set(v, option2);
3818
3818
  }
3819
3819
  internals.bag.optionsMap = map2;
3820
3820
  }
@@ -3826,10 +3826,10 @@ var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnio
3826
3826
  const _super = inst._zod.parse;
3827
3827
  defineLazyInternal(inst, "propValues", (zod) => {
3828
3828
  const propValues = {};
3829
- for (const option of zod.def.options) {
3830
- const pv = option._zod.propValues;
3829
+ for (const option2 of zod.def.options) {
3830
+ const pv = option2._zod.propValues;
3831
3831
  if (!pv || Object.keys(pv).length === 0)
3832
- throw new Error(`Invalid discriminated union option at index "${zod.def.options.indexOf(option)}"`);
3832
+ throw new Error(`Invalid discriminated union option at index "${zod.def.options.indexOf(option2)}"`);
3833
3833
  for (const [k, v] of Object.entries(pv)) {
3834
3834
  if (!Object.prototype.hasOwnProperty.call(propValues, k)) {
3835
3835
  assignProp(propValues, k, /* @__PURE__ */ new Set());
@@ -3841,8 +3841,8 @@ var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnio
3841
3841
  }
3842
3842
  return propValues;
3843
3843
  });
3844
- def.options.forEach((option, i) => {
3845
- const propShape = propShapes.get(option._zod.def);
3844
+ def.options.forEach((option2, i) => {
3845
+ const propShape = propShapes.get(option2._zod.def);
3846
3846
  if (propShape && !Object.prototype.hasOwnProperty.call(propShape, def.discriminator)) {
3847
3847
  throw new Error(`Invalid discriminated union option at index "${i}"`);
3848
3848
  }
@@ -13773,8 +13773,8 @@ function generateDiscriminatedUnionCheck(doc, ctx, def, accessor) {
13773
13773
  doc.write(`let ${outputVar};`);
13774
13774
  let firstBranch = true;
13775
13775
  const claimed = /* @__PURE__ */ new Set();
13776
- for (const option of def.options) {
13777
- const values = option._zod.propValues?.[def.discriminator];
13776
+ for (const option2 of def.options) {
13777
+ const values = option2._zod.propValues?.[def.discriminator];
13778
13778
  if (!values || values.size === 0) {
13779
13779
  throw new ZodCompileUnsupportedError("discriminated union option without static discriminator values");
13780
13780
  }
@@ -13788,7 +13788,7 @@ function generateDiscriminatedUnionCheck(doc, ctx, def, accessor) {
13788
13788
  const prefix = firstBranch ? "if" : "else if";
13789
13789
  doc.write(`${prefix} (${conditions.join(" || ")}) {`);
13790
13790
  doc.indented((d) => {
13791
- const branchOutput = generateCheck(d, ctx, option, accessor);
13791
+ const branchOutput = generateCheck(d, ctx, option2, accessor);
13792
13792
  d.write(`${outputVar} = ${branchOutput};`);
13793
13793
  });
13794
13794
  doc.write(`}`);
@@ -15338,14 +15338,14 @@ function compactTypeUnion(schema) {
15338
15338
  if (!Array.isArray(options) || options.length === 0 || schema.type !== void 0)
15339
15339
  return;
15340
15340
  const types = [];
15341
- for (const option of options) {
15342
- if (!option || typeof option !== "object")
15341
+ for (const option2 of options) {
15342
+ if (!option2 || typeof option2 !== "object")
15343
15343
  return;
15344
- compactTypeUnion(option);
15345
- const keys = Object.keys(option);
15344
+ compactTypeUnion(option2);
15345
+ const keys = Object.keys(option2);
15346
15346
  if (keys.length !== 1 || keys[0] !== "type")
15347
15347
  return;
15348
- const type = option.type;
15348
+ const type = option2.type;
15349
15349
  for (const member of Array.isArray(type) ? type : [type]) {
15350
15350
  if (typeof member !== "string")
15351
15351
  return;
@@ -15635,8 +15635,8 @@ function isTransforming(_schema, _ctx) {
15635
15635
  return false;
15636
15636
  }
15637
15637
  if (def.type === "union") {
15638
- for (const option of def.options) {
15639
- if (isTransforming(option, ctx))
15638
+ for (const option2 of def.options) {
15639
+ if (isTransforming(option2, ctx))
15640
15640
  return true;
15641
15641
  }
15642
15642
  return false;
@@ -19712,6 +19712,487 @@ function encodeSessionFailedEvent(message) {
19712
19712
  return JSON.stringify(decodeSessionFailedEvent(JSON.stringify(message)));
19713
19713
  }
19714
19714
 
19715
+ // ../protocol/src/bot.ts
19716
+ var BOT_BINDING_APPROVAL_REQUEST_KIND = "bot.binding.approval.request";
19717
+ var BOT_BINDING_APPROVED_KIND = "bot.binding.approved";
19718
+ var BOT_BINDING_UNAVAILABLE_KIND = "bot.binding.unavailable";
19719
+ var BOT_SESSION_PROMPT_KIND = "bot.session.prompt";
19720
+ var IDENTIFIER_PATTERN3 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
19721
+ var DIRECTORY_IDENTIFIER_PATTERN3 = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,2047}$/;
19722
+ var TOKEN_PATTERN = /^[a-zA-Z0-9_-]{32,256}$/;
19723
+ var SHA256_PATTERN = /^[a-f0-9]{64}$/;
19724
+ var MAX_INSTRUCTIONS_LENGTH = 1e5;
19725
+ var BotDeliveryTargetReference = class {
19726
+ alias;
19727
+ deliveryTargetId;
19728
+ constructor(alias, deliveryTargetId) {
19729
+ this.alias = alias;
19730
+ this.deliveryTargetId = deliveryTargetId;
19731
+ }
19732
+ };
19733
+ var BotCompletionDeliveryPolicy = class {
19734
+ };
19735
+ var NoBotCompletionDeliveryPolicy = class extends BotCompletionDeliveryPolicy {
19736
+ kind = "none";
19737
+ };
19738
+ var RequiredBotCompletionDeliveryPolicy = class extends BotCompletionDeliveryPolicy {
19739
+ deliveryTargetId;
19740
+ kind = "required";
19741
+ messageTemplate;
19742
+ constructor(deliveryTargetId, messageTemplate) {
19743
+ super();
19744
+ this.deliveryTargetId = deliveryTargetId;
19745
+ this.messageTemplate = messageTemplate;
19746
+ }
19747
+ };
19748
+ var BotReplyRoute = class {
19749
+ };
19750
+ var OwnerBotReplyRoute = class extends BotReplyRoute {
19751
+ kind = "owner";
19752
+ };
19753
+ var BotConnectionReplyRoute = class extends BotReplyRoute {
19754
+ connectionId;
19755
+ deliveryTargetId;
19756
+ kind = "connection";
19757
+ constructor(connectionId, deliveryTargetId) {
19758
+ super();
19759
+ this.connectionId = connectionId;
19760
+ this.deliveryTargetId = deliveryTargetId;
19761
+ }
19762
+ };
19763
+ var BotExecutionBindingApprovalRequest = class {
19764
+ agentConfigRevision;
19765
+ agentRef;
19766
+ allowedDeliveryTargets;
19767
+ behaviorDigest;
19768
+ behaviorInstructions;
19769
+ behaviorRevisionId;
19770
+ bindingId;
19771
+ bindingRevision;
19772
+ botId;
19773
+ completionPolicy;
19774
+ kind = BOT_BINDING_APPROVAL_REQUEST_KIND;
19775
+ requestId;
19776
+ requiredCapabilities;
19777
+ runtimeId;
19778
+ workspaceRef;
19779
+ constructor(requestId, botId, behaviorRevisionId, bindingId, bindingRevision, runtimeId, agentRef, workspaceRef, agentConfigRevision, behaviorInstructions, behaviorDigest, requiredCapabilities, allowedDeliveryTargets, completionPolicy) {
19780
+ this.requestId = requestId;
19781
+ this.botId = botId;
19782
+ this.behaviorRevisionId = behaviorRevisionId;
19783
+ this.bindingId = bindingId;
19784
+ this.bindingRevision = bindingRevision;
19785
+ this.runtimeId = runtimeId;
19786
+ this.agentRef = agentRef;
19787
+ this.workspaceRef = workspaceRef;
19788
+ this.agentConfigRevision = agentConfigRevision;
19789
+ this.behaviorInstructions = behaviorInstructions;
19790
+ this.behaviorDigest = behaviorDigest;
19791
+ this.requiredCapabilities = Object.freeze([...requiredCapabilities]);
19792
+ this.allowedDeliveryTargets = Object.freeze(
19793
+ allowedDeliveryTargets.map(
19794
+ (target) => new BotDeliveryTargetReference(target.alias, target.deliveryTargetId)
19795
+ )
19796
+ );
19797
+ this.completionPolicy = completionPolicy;
19798
+ }
19799
+ };
19800
+ var BotExecutionBindingApprovedEvent = class {
19801
+ agentIdentityDigest;
19802
+ behaviorRevisionId;
19803
+ bindingId;
19804
+ bindingRevision;
19805
+ botId;
19806
+ kind = BOT_BINDING_APPROVED_KIND;
19807
+ localGrantId;
19808
+ requestId;
19809
+ workspaceIdentityDigest;
19810
+ constructor(requestId, botId, behaviorRevisionId, bindingId, bindingRevision, localGrantId, agentIdentityDigest, workspaceIdentityDigest) {
19811
+ this.requestId = requestId;
19812
+ this.botId = botId;
19813
+ this.behaviorRevisionId = behaviorRevisionId;
19814
+ this.bindingId = bindingId;
19815
+ this.bindingRevision = bindingRevision;
19816
+ this.localGrantId = localGrantId;
19817
+ this.agentIdentityDigest = agentIdentityDigest;
19818
+ this.workspaceIdentityDigest = workspaceIdentityDigest;
19819
+ }
19820
+ };
19821
+ var BotExecutionBindingUnavailableEvent = class {
19822
+ behaviorRevisionId;
19823
+ bindingId;
19824
+ bindingRevision;
19825
+ botId;
19826
+ code;
19827
+ kind = BOT_BINDING_UNAVAILABLE_KIND;
19828
+ message;
19829
+ requestId;
19830
+ constructor(requestId, botId, behaviorRevisionId, bindingId, bindingRevision, code, message) {
19831
+ this.requestId = requestId;
19832
+ this.botId = botId;
19833
+ this.behaviorRevisionId = behaviorRevisionId;
19834
+ this.bindingId = bindingId;
19835
+ this.bindingRevision = bindingRevision;
19836
+ this.code = code;
19837
+ this.message = message;
19838
+ }
19839
+ };
19840
+ var BotSessionPromptCommand = class {
19841
+ additionalDirectoryIds;
19842
+ agentId;
19843
+ allowedDeliveryTargets;
19844
+ behaviorDigest;
19845
+ behaviorInstructions;
19846
+ behaviorRevisionId;
19847
+ bindingId;
19848
+ bindingRevision;
19849
+ botId;
19850
+ commandId;
19851
+ conversationId;
19852
+ directoryId;
19853
+ executionCapabilityId;
19854
+ executionCapabilitySecret;
19855
+ executionDeadlineAt;
19856
+ executionId;
19857
+ images;
19858
+ kind = BOT_SESSION_PROMPT_KIND;
19859
+ localGrantId;
19860
+ prompt;
19861
+ replyRoute;
19862
+ resources;
19863
+ sessionId;
19864
+ turnId;
19865
+ constructor(sessionId, commandId, agentId, bindingId, directoryId2, additionalDirectoryIds, images, resources, prompt, executionId, executionCapabilityId, executionCapabilitySecret, executionDeadlineAt, botId, conversationId, turnId, behaviorRevisionId, bindingRevision, localGrantId, behaviorInstructions, behaviorDigest, allowedDeliveryTargets, replyRoute) {
19866
+ this.sessionId = sessionId;
19867
+ this.commandId = commandId;
19868
+ this.agentId = agentId;
19869
+ this.bindingId = bindingId;
19870
+ this.directoryId = directoryId2;
19871
+ this.additionalDirectoryIds = Object.freeze([...additionalDirectoryIds]);
19872
+ this.images = Object.freeze([...images]);
19873
+ this.resources = Object.freeze([...resources]);
19874
+ this.prompt = prompt;
19875
+ this.executionId = executionId;
19876
+ this.executionCapabilityId = executionCapabilityId;
19877
+ this.executionCapabilitySecret = executionCapabilitySecret;
19878
+ this.executionDeadlineAt = executionDeadlineAt;
19879
+ this.botId = botId;
19880
+ this.conversationId = conversationId;
19881
+ this.turnId = turnId;
19882
+ this.behaviorRevisionId = behaviorRevisionId;
19883
+ this.bindingRevision = bindingRevision;
19884
+ this.localGrantId = localGrantId;
19885
+ this.behaviorInstructions = behaviorInstructions;
19886
+ this.behaviorDigest = behaviorDigest;
19887
+ this.allowedDeliveryTargets = Object.freeze(
19888
+ allowedDeliveryTargets.map(
19889
+ (target) => new BotDeliveryTargetReference(target.alias, target.deliveryTargetId)
19890
+ )
19891
+ );
19892
+ this.replyRoute = replyRoute;
19893
+ }
19894
+ };
19895
+ function isRecord2(value) {
19896
+ return typeof value === "object" && value !== null && !Array.isArray(value);
19897
+ }
19898
+ function parseJson3(encoded) {
19899
+ let value;
19900
+ try {
19901
+ value = JSON.parse(encoded);
19902
+ } catch (cause) {
19903
+ throw new ProtocolMessageError("Message is not valid JSON", { cause });
19904
+ }
19905
+ if (!isRecord2(value)) {
19906
+ throw new ProtocolMessageError("Message must be a JSON object");
19907
+ }
19908
+ return value;
19909
+ }
19910
+ function assertExactKeys2(value, expected) {
19911
+ const keys = Object.keys(value);
19912
+ if (keys.length !== expected.length || keys.some((key) => !expected.includes(key))) {
19913
+ throw new ProtocolMessageError("Message fields do not match the Bot protocol");
19914
+ }
19915
+ }
19916
+ function readText2(value, key, maximumLength, allowEmpty) {
19917
+ const field = value[key];
19918
+ if (typeof field !== "string" || field.length > maximumLength || !allowEmpty && field.length === 0) {
19919
+ throw new ProtocolMessageError(`Invalid Bot protocol field: ${key}`);
19920
+ }
19921
+ return field;
19922
+ }
19923
+ function readIdentifier2(value, key) {
19924
+ const field = readText2(value, key, 128, false);
19925
+ if (!IDENTIFIER_PATTERN3.test(field)) {
19926
+ throw new ProtocolMessageError(`Invalid Bot identifier field: ${key}`);
19927
+ }
19928
+ return field;
19929
+ }
19930
+ function readDirectoryIdentifier2(value, key) {
19931
+ const field = readText2(value, key, 2048, false);
19932
+ if (!DIRECTORY_IDENTIFIER_PATTERN3.test(field)) {
19933
+ throw new ProtocolMessageError(`Invalid Bot directory field: ${key}`);
19934
+ }
19935
+ return field;
19936
+ }
19937
+ function readInteger(value, key) {
19938
+ const field = value[key];
19939
+ if (typeof field !== "number" || !Number.isSafeInteger(field) || field < 1) {
19940
+ throw new ProtocolMessageError(`Invalid Bot integer field: ${key}`);
19941
+ }
19942
+ return field;
19943
+ }
19944
+ function readTimestamp(value, key) {
19945
+ const field = readText2(value, key, 64, false);
19946
+ if (Number.isNaN(Date.parse(field))) {
19947
+ throw new ProtocolMessageError(`Invalid Bot timestamp field: ${key}`);
19948
+ }
19949
+ return field;
19950
+ }
19951
+ function readDigest(value, key) {
19952
+ const field = readText2(value, key, 64, false);
19953
+ if (!SHA256_PATTERN.test(field)) {
19954
+ throw new ProtocolMessageError(`Invalid Bot digest field: ${key}`);
19955
+ }
19956
+ return field;
19957
+ }
19958
+ function readToken(value, key) {
19959
+ const field = readText2(value, key, 256, false);
19960
+ if (!TOKEN_PATTERN.test(field)) {
19961
+ throw new ProtocolMessageError(`Invalid Bot token field: ${key}`);
19962
+ }
19963
+ return field;
19964
+ }
19965
+ function readIdentifiers(value, key, maximumCount) {
19966
+ const field = value[key];
19967
+ if (!Array.isArray(field) || field.length > maximumCount) {
19968
+ throw new ProtocolMessageError(`Invalid Bot identifier list: ${key}`);
19969
+ }
19970
+ const identifiers = [];
19971
+ const unique = /* @__PURE__ */ new Set();
19972
+ for (const candidate of field) {
19973
+ if (typeof candidate !== "string" || !IDENTIFIER_PATTERN3.test(candidate) || unique.has(candidate)) {
19974
+ throw new ProtocolMessageError(`Invalid Bot identifier list: ${key}`);
19975
+ }
19976
+ unique.add(candidate);
19977
+ identifiers.push(candidate);
19978
+ }
19979
+ return Object.freeze(identifiers);
19980
+ }
19981
+ function readTargets(value, key) {
19982
+ const field = value[key];
19983
+ if (!Array.isArray(field) || field.length > 64) {
19984
+ throw new ProtocolMessageError(`Invalid Bot delivery targets: ${key}`);
19985
+ }
19986
+ const targets = [];
19987
+ const identifiers = /* @__PURE__ */ new Set();
19988
+ const aliases = /* @__PURE__ */ new Set();
19989
+ for (const candidate of field) {
19990
+ if (!isRecord2(candidate)) {
19991
+ throw new ProtocolMessageError(`Invalid Bot delivery targets: ${key}`);
19992
+ }
19993
+ assertExactKeys2(candidate, ["alias", "deliveryTargetId"]);
19994
+ const alias = readIdentifier2(candidate, "alias");
19995
+ const deliveryTargetId = readIdentifier2(candidate, "deliveryTargetId");
19996
+ if (aliases.has(alias) || identifiers.has(deliveryTargetId)) {
19997
+ throw new ProtocolMessageError(`Duplicate Bot delivery target: ${key}`);
19998
+ }
19999
+ aliases.add(alias);
20000
+ identifiers.add(deliveryTargetId);
20001
+ targets.push(new BotDeliveryTargetReference(alias, deliveryTargetId));
20002
+ }
20003
+ return Object.freeze(targets);
20004
+ }
20005
+ function readCompletionPolicy(value) {
20006
+ if (!isRecord2(value)) {
20007
+ throw new ProtocolMessageError("Invalid Bot completion policy");
20008
+ }
20009
+ const kind = readText2(value, "kind", 32, false);
20010
+ if (kind === "none") {
20011
+ assertExactKeys2(value, ["kind"]);
20012
+ return new NoBotCompletionDeliveryPolicy();
20013
+ }
20014
+ if (kind === "required") {
20015
+ assertExactKeys2(value, ["deliveryTargetId", "kind", "messageTemplate"]);
20016
+ return new RequiredBotCompletionDeliveryPolicy(
20017
+ readIdentifier2(value, "deliveryTargetId"),
20018
+ readText2(value, "messageTemplate", 1e4, false)
20019
+ );
20020
+ }
20021
+ throw new ProtocolMessageError("Invalid Bot completion policy");
20022
+ }
20023
+ function readReplyRoute(value) {
20024
+ if (!isRecord2(value)) {
20025
+ throw new ProtocolMessageError("Invalid Bot reply route");
20026
+ }
20027
+ const kind = readText2(value, "kind", 32, false);
20028
+ if (kind === "owner") {
20029
+ assertExactKeys2(value, ["kind"]);
20030
+ return new OwnerBotReplyRoute();
20031
+ }
20032
+ if (kind === "connection") {
20033
+ assertExactKeys2(value, ["connectionId", "deliveryTargetId", "kind"]);
20034
+ return new BotConnectionReplyRoute(
20035
+ readIdentifier2(value, "connectionId"),
20036
+ readIdentifier2(value, "deliveryTargetId")
20037
+ );
20038
+ }
20039
+ throw new ProtocolMessageError("Invalid Bot reply route");
20040
+ }
20041
+ function decodeBotExecutionBindingApprovalRequest(encoded) {
20042
+ const value = parseJson3(encoded);
20043
+ assertExactKeys2(value, [
20044
+ "agentConfigRevision",
20045
+ "agentRef",
20046
+ "allowedDeliveryTargets",
20047
+ "behaviorDigest",
20048
+ "behaviorInstructions",
20049
+ "behaviorRevisionId",
20050
+ "bindingId",
20051
+ "bindingRevision",
20052
+ "botId",
20053
+ "completionPolicy",
20054
+ "kind",
20055
+ "requestId",
20056
+ "requiredCapabilities",
20057
+ "runtimeId",
20058
+ "workspaceRef"
20059
+ ]);
20060
+ if (value["kind"] !== BOT_BINDING_APPROVAL_REQUEST_KIND) {
20061
+ throw new ProtocolMessageError("Invalid Bot binding approval request kind");
20062
+ }
20063
+ return new BotExecutionBindingApprovalRequest(
20064
+ readIdentifier2(value, "requestId"),
20065
+ readIdentifier2(value, "botId"),
20066
+ readIdentifier2(value, "behaviorRevisionId"),
20067
+ readIdentifier2(value, "bindingId"),
20068
+ readInteger(value, "bindingRevision"),
20069
+ readIdentifier2(value, "runtimeId"),
20070
+ readIdentifier2(value, "agentRef"),
20071
+ readDirectoryIdentifier2(value, "workspaceRef"),
20072
+ readInteger(value, "agentConfigRevision"),
20073
+ readText2(value, "behaviorInstructions", MAX_INSTRUCTIONS_LENGTH, true),
20074
+ readDigest(value, "behaviorDigest"),
20075
+ readIdentifiers(value, "requiredCapabilities", 32),
20076
+ readTargets(value, "allowedDeliveryTargets"),
20077
+ readCompletionPolicy(value["completionPolicy"])
20078
+ );
20079
+ }
20080
+ function decodeBotExecutionBindingApprovedEvent(encoded) {
20081
+ const value = parseJson3(encoded);
20082
+ assertExactKeys2(value, [
20083
+ "agentIdentityDigest",
20084
+ "behaviorRevisionId",
20085
+ "bindingId",
20086
+ "bindingRevision",
20087
+ "botId",
20088
+ "kind",
20089
+ "localGrantId",
20090
+ "requestId",
20091
+ "workspaceIdentityDigest"
20092
+ ]);
20093
+ if (value["kind"] !== BOT_BINDING_APPROVED_KIND) {
20094
+ throw new ProtocolMessageError("Invalid Bot binding approval event kind");
20095
+ }
20096
+ return new BotExecutionBindingApprovedEvent(
20097
+ readIdentifier2(value, "requestId"),
20098
+ readIdentifier2(value, "botId"),
20099
+ readIdentifier2(value, "behaviorRevisionId"),
20100
+ readIdentifier2(value, "bindingId"),
20101
+ readInteger(value, "bindingRevision"),
20102
+ readIdentifier2(value, "localGrantId"),
20103
+ readDigest(value, "agentIdentityDigest"),
20104
+ readDigest(value, "workspaceIdentityDigest")
20105
+ );
20106
+ }
20107
+ function encodeBotExecutionBindingApprovedEvent(event) {
20108
+ return JSON.stringify(decodeBotExecutionBindingApprovedEvent(JSON.stringify(event)));
20109
+ }
20110
+ function decodeBotExecutionBindingUnavailableEvent(encoded) {
20111
+ const value = parseJson3(encoded);
20112
+ assertExactKeys2(value, [
20113
+ "behaviorRevisionId",
20114
+ "bindingId",
20115
+ "bindingRevision",
20116
+ "botId",
20117
+ "code",
20118
+ "kind",
20119
+ "message",
20120
+ "requestId"
20121
+ ]);
20122
+ if (value["kind"] !== BOT_BINDING_UNAVAILABLE_KIND) {
20123
+ throw new ProtocolMessageError("Invalid Bot binding unavailable event kind");
20124
+ }
20125
+ return new BotExecutionBindingUnavailableEvent(
20126
+ readIdentifier2(value, "requestId"),
20127
+ readIdentifier2(value, "botId"),
20128
+ readIdentifier2(value, "behaviorRevisionId"),
20129
+ readIdentifier2(value, "bindingId"),
20130
+ readInteger(value, "bindingRevision"),
20131
+ readIdentifier2(value, "code"),
20132
+ readText2(value, "message", 500, false)
20133
+ );
20134
+ }
20135
+ function encodeBotExecutionBindingUnavailableEvent(event) {
20136
+ return JSON.stringify(decodeBotExecutionBindingUnavailableEvent(JSON.stringify(event)));
20137
+ }
20138
+ function decodeBotSessionPromptCommand(encoded) {
20139
+ const value = parseJson3(encoded);
20140
+ assertExactKeys2(value, [
20141
+ "additionalDirectoryIds",
20142
+ "agentId",
20143
+ "allowedDeliveryTargets",
20144
+ "behaviorDigest",
20145
+ "behaviorInstructions",
20146
+ "behaviorRevisionId",
20147
+ "bindingId",
20148
+ "bindingRevision",
20149
+ "botId",
20150
+ "commandId",
20151
+ "conversationId",
20152
+ "directoryId",
20153
+ "executionCapabilityId",
20154
+ "executionCapabilitySecret",
20155
+ "executionDeadlineAt",
20156
+ "executionId",
20157
+ "images",
20158
+ "kind",
20159
+ "localGrantId",
20160
+ "prompt",
20161
+ "replyRoute",
20162
+ "resources",
20163
+ "sessionId",
20164
+ "turnId"
20165
+ ]);
20166
+ if (value["kind"] !== BOT_SESSION_PROMPT_KIND) {
20167
+ throw new ProtocolMessageError("Invalid Bot Session prompt kind");
20168
+ }
20169
+ return new BotSessionPromptCommand(
20170
+ readIdentifier2(value, "sessionId"),
20171
+ readIdentifier2(value, "commandId"),
20172
+ readIdentifier2(value, "agentId"),
20173
+ readIdentifier2(value, "bindingId"),
20174
+ readDirectoryIdentifier2(value, "directoryId"),
20175
+ readIdentifiers(value, "additionalDirectoryIds", 16),
20176
+ decodePromptImagesValue(value["images"]),
20177
+ decodePromptResourcesValue(value["resources"]),
20178
+ readText2(value, "prompt", 1e4, false),
20179
+ readIdentifier2(value, "executionId"),
20180
+ readIdentifier2(value, "executionCapabilityId"),
20181
+ readToken(value, "executionCapabilitySecret"),
20182
+ readTimestamp(value, "executionDeadlineAt"),
20183
+ readIdentifier2(value, "botId"),
20184
+ readIdentifier2(value, "conversationId"),
20185
+ readIdentifier2(value, "turnId"),
20186
+ readIdentifier2(value, "behaviorRevisionId"),
20187
+ readInteger(value, "bindingRevision"),
20188
+ readIdentifier2(value, "localGrantId"),
20189
+ readText2(value, "behaviorInstructions", MAX_INSTRUCTIONS_LENGTH, true),
20190
+ readDigest(value, "behaviorDigest"),
20191
+ readTargets(value, "allowedDeliveryTargets"),
20192
+ readReplyRoute(value["replyRoute"])
20193
+ );
20194
+ }
20195
+
19715
20196
  // ../protocol/src/mobius-api.ts
19716
20197
  var MOBIUS_API_PREFIX = "/mobius/api";
19717
20198
  var API_PREFIX_PATTERN = /^\/[a-zA-Z0-9._~-]+(?:\/[a-zA-Z0-9._~-]+)*$/;
@@ -19890,13 +20371,13 @@ var SessionEventRejectionCode = {
19890
20371
  SessionDeleted: "session_deleted",
19891
20372
  SessionNotFound: "session_not_found"
19892
20373
  };
19893
- var IDENTIFIER_PATTERN3 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
20374
+ var IDENTIFIER_PATTERN4 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
19894
20375
  var CURSOR_PATTERN = /^[A-Za-z0-9_-]{1,512}$/;
19895
20376
  var MAX_RECORDED_EVENT_LENGTH = 8 * 1024 * 1024;
19896
20377
  var DECIMAL_SEQUENCE_PATTERN = /^(?:0|[1-9][0-9]*)$/;
19897
20378
  var eventSourceSchema = external_exports.discriminatedUnion("kind", [
19898
20379
  external_exports.strictObject({
19899
- attemptId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3),
20380
+ attemptId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
19900
20381
  kind: external_exports.literal("attempt"),
19901
20382
  sourceSeq: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN)
19902
20383
  }).readonly(),
@@ -19906,35 +20387,35 @@ var eventSourceSchema = external_exports.discriminatedUnion("kind", [
19906
20387
  }).readonly()
19907
20388
  ]);
19908
20389
  var eventEnvelopeSchema = external_exports.strictObject({
19909
- eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3),
20390
+ eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
19910
20391
  kind: external_exports.literal(SESSION_EVENT_KIND),
19911
20392
  payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
19912
- sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3),
20393
+ sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
19913
20394
  source: eventSourceSchema
19914
20395
  }).readonly();
19915
20396
  var committedEventSchema = external_exports.strictObject({
19916
20397
  cursor: external_exports.string().min(1).max(512).regex(CURSOR_PATTERN),
19917
- eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3),
20398
+ eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
19918
20399
  kind: external_exports.literal(SESSION_EVENT_COMMITTED_KIND),
19919
20400
  payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
19920
20401
  recordedAt: external_exports.string().datetime({ offset: true }),
19921
20402
  sequence: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN),
19922
- sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3),
20403
+ sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
19923
20404
  source: eventSourceSchema
19924
20405
  }).readonly();
19925
20406
  var eventAcknowledgementSchema = external_exports.strictObject({
19926
20407
  cursor: external_exports.string().min(1).max(512).regex(CURSOR_PATTERN),
19927
20408
  duplicate: external_exports.boolean(),
19928
- eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3),
20409
+ eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
19929
20410
  kind: external_exports.literal(SESSION_EVENT_ACK_KIND),
19930
20411
  sequence: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN),
19931
- sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3)
20412
+ sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4)
19932
20413
  }).readonly();
19933
20414
  var eventRejectionSchema = external_exports.strictObject({
19934
20415
  code: external_exports.enum(SessionEventRejectionCode),
19935
- eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3),
20416
+ eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
19936
20417
  kind: external_exports.literal(SESSION_EVENT_REJECTED_KIND),
19937
- sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3)
20418
+ sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4)
19938
20419
  }).readonly();
19939
20420
  function decode5(encoded, schema) {
19940
20421
  let value;
@@ -20611,7 +21092,7 @@ import {
20611
21092
 
20612
21093
  // src/acp/activity.ts
20613
21094
  var TRUNCATION_MARKER = "\n\u2026 output truncated by Mobius";
20614
- function isRecord2(value) {
21095
+ function isRecord3(value) {
20615
21096
  return typeof value === "object" && value !== null && !Array.isArray(value);
20616
21097
  }
20617
21098
  var AcpActivity = class _AcpActivity {
@@ -20878,7 +21359,7 @@ function contentPhase(content) {
20878
21359
  return "";
20879
21360
  }
20880
21361
  const codex = metadata["codex"];
20881
- if (!isRecord2(codex)) {
21362
+ if (!isRecord3(codex)) {
20882
21363
  return "";
20883
21364
  }
20884
21365
  const phase = codex["phase"];
@@ -21116,7 +21597,7 @@ var SessionConfigProtocolError = class extends Error {
21116
21597
  this.name = "SessionConfigProtocolError";
21117
21598
  }
21118
21599
  };
21119
- function isRecord3(value) {
21600
+ function isRecord4(value) {
21120
21601
  return typeof value === "object" && value !== null && !Array.isArray(value);
21121
21602
  }
21122
21603
  function readString2(value, fallback = "") {
@@ -21128,13 +21609,13 @@ function truncate2(value, maximum) {
21128
21609
  function readBoolean(value, fallback = false) {
21129
21610
  return typeof value === "boolean" ? value : fallback;
21130
21611
  }
21131
- function normalizeConfigValue(option, groupId = "", groupName = "") {
21612
+ function normalizeConfigValue(option2, groupId = "", groupName = "") {
21132
21613
  return {
21133
- description: truncate2(readString2(option["description"]), 500),
21614
+ description: truncate2(readString2(option2["description"]), 500),
21134
21615
  groupId: truncate2(groupId, 128),
21135
21616
  groupName: truncate2(groupName, 255),
21136
- name: truncate2(readString2(option["name"], readString2(option["value"])), 255),
21137
- value: truncate2(readString2(option["value"]), 500)
21617
+ name: truncate2(readString2(option2["name"], readString2(option2["value"])), 255),
21618
+ value: truncate2(readString2(option2["value"]), 500)
21138
21619
  };
21139
21620
  }
21140
21621
  function normalizeConfigValues(value) {
@@ -21143,7 +21624,7 @@ function normalizeConfigValues(value) {
21143
21624
  }
21144
21625
  const normalized = [];
21145
21626
  for (const entry of value) {
21146
- if (!isRecord3(entry)) {
21627
+ if (!isRecord4(entry)) {
21147
21628
  continue;
21148
21629
  }
21149
21630
  const groupedOptions = entry["options"];
@@ -21151,7 +21632,7 @@ function normalizeConfigValues(value) {
21151
21632
  const groupId = readString2(entry["group"]);
21152
21633
  const groupName = readString2(entry["name"]);
21153
21634
  for (const groupedOption of groupedOptions) {
21154
- if (isRecord3(groupedOption)) {
21635
+ if (isRecord4(groupedOption)) {
21155
21636
  normalized.push(normalizeConfigValue(groupedOption, groupId, groupName));
21156
21637
  }
21157
21638
  }
@@ -21164,21 +21645,21 @@ function normalizeConfigValues(value) {
21164
21645
  function normalizeConfigOptions(value, modes) {
21165
21646
  const normalized = [];
21166
21647
  if (Array.isArray(value)) {
21167
- for (const option of value) {
21168
- if (!isRecord3(option)) {
21648
+ for (const option2 of value) {
21649
+ if (!isRecord4(option2)) {
21169
21650
  continue;
21170
21651
  }
21171
- const id = truncate2(readString2(option["id"]), 128);
21172
- const name = truncate2(readString2(option["name"], id), 255);
21652
+ const id = truncate2(readString2(option2["id"]), 128);
21653
+ const name = truncate2(readString2(option2["name"], id), 255);
21173
21654
  if (id.length === 0 || name.length === 0) {
21174
21655
  continue;
21175
21656
  }
21176
- if (option["type"] === "boolean") {
21657
+ if (option2["type"] === "boolean") {
21177
21658
  normalized.push({
21178
- booleanValue: readBoolean(option["currentValue"]),
21179
- category: truncate2(readString2(option["category"]), 128),
21659
+ booleanValue: readBoolean(option2["currentValue"]),
21660
+ category: truncate2(readString2(option2["category"]), 128),
21180
21661
  currentValue: "",
21181
- description: truncate2(readString2(option["description"]), 500),
21662
+ description: truncate2(readString2(option2["description"]), 500),
21182
21663
  id,
21183
21664
  name,
21184
21665
  type: "boolean",
@@ -21186,15 +21667,15 @@ function normalizeConfigOptions(value, modes) {
21186
21667
  });
21187
21668
  continue;
21188
21669
  }
21189
- if (option["type"] === "select") {
21190
- const values = normalizeConfigValues(option["options"]);
21191
- const currentValue = truncate2(readString2(option["currentValue"]), 500);
21670
+ if (option2["type"] === "select") {
21671
+ const values = normalizeConfigValues(option2["options"]);
21672
+ const currentValue = truncate2(readString2(option2["currentValue"]), 500);
21192
21673
  if (currentValue.length > 0 && values.some((entry) => entry.value === currentValue)) {
21193
21674
  normalized.push({
21194
21675
  booleanValue: false,
21195
- category: truncate2(readString2(option["category"]), 128),
21676
+ category: truncate2(readString2(option2["category"]), 128),
21196
21677
  currentValue,
21197
- description: truncate2(readString2(option["description"]), 500),
21678
+ description: truncate2(readString2(option2["description"]), 500),
21198
21679
  id,
21199
21680
  name,
21200
21681
  type: "select",
@@ -21204,12 +21685,12 @@ function normalizeConfigOptions(value, modes) {
21204
21685
  }
21205
21686
  }
21206
21687
  }
21207
- if (isRecord3(modes)) {
21688
+ if (isRecord4(modes)) {
21208
21689
  const values = [];
21209
21690
  const availableModes = modes["availableModes"];
21210
21691
  if (Array.isArray(availableModes)) {
21211
21692
  for (const mode of availableModes) {
21212
- if (!isRecord3(mode)) {
21693
+ if (!isRecord4(mode)) {
21213
21694
  continue;
21214
21695
  }
21215
21696
  const id = truncate2(readString2(mode["id"]), 500);
@@ -21242,7 +21723,7 @@ function normalizeConfigOptions(value, modes) {
21242
21723
  return normalized.slice(0, 100);
21243
21724
  }
21244
21725
  function ensureReasoningEffortOption(current) {
21245
- if (current.some((option) => option.category === "thought_level")) {
21726
+ if (current.some((option2) => option2.category === "thought_level")) {
21246
21727
  return current;
21247
21728
  }
21248
21729
  const unavailable = {
@@ -21263,7 +21744,7 @@ function ensureReasoningEffortOption(current) {
21263
21744
  }
21264
21745
  ]
21265
21746
  };
21266
- const modelIndex = current.findIndex((option) => option.category === "model");
21747
+ const modelIndex = current.findIndex((option2) => option2.category === "model");
21267
21748
  if (current.length < MAXIMUM_CONFIG_OPTIONS) {
21268
21749
  if (modelIndex < 0) {
21269
21750
  return [...current, unavailable];
@@ -21287,20 +21768,20 @@ function ensureReasoningEffortOption(current) {
21287
21768
  return [...current.slice(0, MAXIMUM_CONFIG_OPTIONS - 2), model, unavailable];
21288
21769
  }
21289
21770
  function normalizeStandardLifecycle(response) {
21290
- const lifecycle = isRecord3(response) ? response : {};
21771
+ const lifecycle = isRecord4(response) ? response : {};
21291
21772
  return ensureReasoningEffortOption(normalizeConfigOptions(lifecycle["configOptions"], lifecycle["modes"]));
21292
21773
  }
21293
21774
  function replaceStandardConfigOptions(current, value) {
21294
21775
  const next = normalizeConfigOptions(value, void 0);
21295
- const withMode = next.some((option) => option.category === "mode") ? next : [...current.filter((option) => option.category === "mode"), ...next].slice(0, 100);
21776
+ const withMode = next.some((option2) => option2.category === "mode") ? next : [...current.filter((option2) => option2.category === "mode"), ...next].slice(0, 100);
21296
21777
  return ensureReasoningEffortOption(withMode);
21297
21778
  }
21298
21779
  function updateCurrentValue(current, configId, value) {
21299
- return current.map((option) => option.id === configId ? { ...option, currentValue: value } : option);
21780
+ return current.map((option2) => option2.id === configId ? { ...option2, currentValue: value } : option2);
21300
21781
  }
21301
21782
  var StandardSessionConfigProtocol = class {
21302
21783
  configure = async (current, change, nativeSessionId, transport) => {
21303
- const existing = current.find((option) => option.id === change.configId);
21784
+ const existing = current.find((option2) => option2.id === change.configId);
21304
21785
  if (existing === void 0) {
21305
21786
  return current;
21306
21787
  }
@@ -21329,7 +21810,7 @@ var StandardSessionConfigProtocol = class {
21329
21810
  "ACP agent exited while changing session configuration",
21330
21811
  change.signal
21331
21812
  );
21332
- if (!isRecord3(response) || !Array.isArray(response["configOptions"])) {
21813
+ if (!isRecord4(response) || !Array.isArray(response["configOptions"])) {
21333
21814
  throw new SessionConfigProtocolError("The Agent returned an invalid session configuration response");
21334
21815
  }
21335
21816
  return replaceStandardConfigOptions(current, response["configOptions"]);
@@ -21343,31 +21824,31 @@ var standardSessionConfigProtocol = new StandardSessionConfigProtocol();
21343
21824
  var LEGACY_MODEL_CONFIG_ID = "grok_build_legacy_model";
21344
21825
  var LEGACY_REASONING_EFFORT_CONFIG_ID = "grok_build_legacy_reasoning_effort";
21345
21826
  function legacyOptions(response) {
21346
- if (!isRecord3(response)) {
21827
+ if (!isRecord4(response)) {
21347
21828
  return [];
21348
21829
  }
21349
21830
  const metadata = response["_meta"];
21350
- if (!isRecord3(metadata)) {
21831
+ if (!isRecord4(metadata)) {
21351
21832
  return [];
21352
21833
  }
21353
21834
  const sessionConfig = metadata["x.ai/sessionConfig"];
21354
- if (!isRecord3(sessionConfig) || !Array.isArray(sessionConfig["options"])) {
21835
+ if (!isRecord4(sessionConfig) || !Array.isArray(sessionConfig["options"])) {
21355
21836
  return [];
21356
21837
  }
21357
- return sessionConfig["options"].slice(0, 500).filter(isRecord3);
21838
+ return sessionConfig["options"].slice(0, 500).filter(isRecord4);
21358
21839
  }
21359
- function legacyValue(option) {
21360
- const value = readString2(option["id"]);
21840
+ function legacyValue(option2) {
21841
+ const value = readString2(option2["id"]);
21361
21842
  return {
21362
- description: readString2(option["description"]).slice(0, 500),
21843
+ description: readString2(option2["description"]).slice(0, 500),
21363
21844
  groupId: "",
21364
21845
  groupName: "",
21365
- name: readString2(option["label"], value).slice(0, 255),
21846
+ name: readString2(option2["label"], value).slice(0, 255),
21366
21847
  value: value.slice(0, 500)
21367
21848
  };
21368
21849
  }
21369
21850
  function modelsRecord(response) {
21370
- if (!isRecord3(response) || !isRecord3(response["models"])) {
21851
+ if (!isRecord4(response) || !isRecord4(response["models"])) {
21371
21852
  return {};
21372
21853
  }
21373
21854
  return response["models"];
@@ -21376,9 +21857,9 @@ function legacyModelOptions(response) {
21376
21857
  const options = legacyOptions(response);
21377
21858
  const models = modelsRecord(response);
21378
21859
  const values = [];
21379
- for (const option of options) {
21380
- if (option["category"] === "model") {
21381
- const value = legacyValue(option);
21860
+ for (const option2 of options) {
21861
+ if (option2["category"] === "model") {
21862
+ const value = legacyValue(option2);
21382
21863
  if (value.value.length > 0 && !values.some((existing) => existing.value === value.value)) {
21383
21864
  values.push(value);
21384
21865
  }
@@ -21386,7 +21867,7 @@ function legacyModelOptions(response) {
21386
21867
  }
21387
21868
  if (values.length === 0 && Array.isArray(models["availableModels"])) {
21388
21869
  for (const model of models["availableModels"]) {
21389
- if (!isRecord3(model)) {
21870
+ if (!isRecord4(model)) {
21390
21871
  continue;
21391
21872
  }
21392
21873
  const value = readString2(model["modelId"]).slice(0, 500);
@@ -21404,7 +21885,7 @@ function legacyModelOptions(response) {
21404
21885
  }
21405
21886
  }
21406
21887
  }
21407
- const selected = options.find((option) => option["category"] === "model" && option["selected"] === true);
21888
+ const selected = options.find((option2) => option2["category"] === "model" && option2["selected"] === true);
21408
21889
  const currentValue = readString2(
21409
21890
  models["currentModelId"],
21410
21891
  selected === void 0 ? "" : readString2(selected["id"])
@@ -21427,11 +21908,11 @@ function legacyModelOptions(response) {
21427
21908
  function legacyReasoningEffortOptions(response) {
21428
21909
  const options = legacyOptions(response);
21429
21910
  const values = [];
21430
- for (const option of options) {
21431
- if (option["category"] !== "mode") {
21911
+ for (const option2 of options) {
21912
+ if (option2["category"] !== "mode") {
21432
21913
  continue;
21433
21914
  }
21434
- const value = legacyValue(option);
21915
+ const value = legacyValue(option2);
21435
21916
  if (value.value.length > 0 && !values.some((existing) => existing.value === value.value)) {
21436
21917
  values.push(value);
21437
21918
  }
@@ -21439,7 +21920,7 @@ function legacyReasoningEffortOptions(response) {
21439
21920
  if (values.length === 0) {
21440
21921
  return [];
21441
21922
  }
21442
- const selected = options.find((option) => option["category"] === "mode" && option["selected"] === true);
21923
+ const selected = options.find((option2) => option2["category"] === "mode" && option2["selected"] === true);
21443
21924
  if (selected === void 0) {
21444
21925
  values.unshift({
21445
21926
  description: "Use the selected model's default reasoning effort",
@@ -21466,41 +21947,41 @@ function legacyReasoningEffortOptions(response) {
21466
21947
  return [result];
21467
21948
  }
21468
21949
  function normalizeGrokLifecycle(response) {
21469
- const lifecycle = isRecord3(response) ? response : {};
21950
+ const lifecycle = isRecord4(response) ? response : {};
21470
21951
  const standard = normalizeConfigOptions(lifecycle["configOptions"], lifecycle["modes"]);
21471
21952
  const normalized = [...standard];
21472
- if (!normalized.some((option) => option.category === "model")) {
21953
+ if (!normalized.some((option2) => option2.category === "model")) {
21473
21954
  normalized.push(...legacyModelOptions(response));
21474
21955
  }
21475
- if (!normalized.some((option) => option.category === "thought_level")) {
21956
+ if (!normalized.some((option2) => option2.category === "thought_level")) {
21476
21957
  const efforts = legacyReasoningEffortOptions(response);
21477
21958
  if (efforts.length > 0) {
21478
- const modelIndex = normalized.findIndex((option) => option.category === "model");
21959
+ const modelIndex = normalized.findIndex((option2) => option2.category === "model");
21479
21960
  normalized.splice(modelIndex < 0 ? normalized.length : modelIndex + 1, 0, ...efforts);
21480
21961
  }
21481
21962
  }
21482
21963
  return ensureReasoningEffortOption(normalized.slice(0, 100));
21483
21964
  }
21484
21965
  function updateCurrentValue2(current, category, value) {
21485
- return current.map((option) => option.category === category ? { ...option, currentValue: value } : option);
21966
+ return current.map((option2) => option2.category === category ? { ...option2, currentValue: value } : option2);
21486
21967
  }
21487
21968
  function validateGrokResponse(response, modelId) {
21488
- if (!isRecord3(response) || !isRecord3(response["_meta"])) {
21969
+ if (!isRecord4(response) || !isRecord4(response["_meta"])) {
21489
21970
  throw new SessionConfigProtocolError("Grok Build returned an invalid session configuration response");
21490
21971
  }
21491
21972
  const model = response["_meta"]["model"];
21492
- const appliedModel = isRecord3(model) ? model["Ok"] : model;
21973
+ const appliedModel = isRecord4(model) ? model["Ok"] : model;
21493
21974
  if (appliedModel !== modelId) {
21494
21975
  throw new SessionConfigProtocolError("Grok Build returned an invalid session configuration response");
21495
21976
  }
21496
21977
  }
21497
21978
  var GrokBuildSessionConfigProtocol = class {
21498
21979
  configure = async (current, change, nativeSessionId, transport) => {
21499
- const existing = current.find((option) => option.id === change.configId);
21980
+ const existing = current.find((option2) => option2.id === change.configId);
21500
21981
  if (existing === void 0 || existing.id !== LEGACY_MODEL_CONFIG_ID && existing.id !== LEGACY_REASONING_EFFORT_CONFIG_ID) {
21501
21982
  return await standardSessionConfigProtocol.configure(current, change, nativeSessionId, transport);
21502
21983
  }
21503
- const model = current.find((option) => option.category === "model");
21984
+ const model = current.find((option2) => option2.category === "model");
21504
21985
  if (model === void 0) {
21505
21986
  return current;
21506
21987
  }
@@ -21526,10 +22007,10 @@ var GrokBuildSessionConfigProtocol = class {
21526
22007
  validateGrokResponse(response, modelId);
21527
22008
  const updated = updateCurrentValue2(current, existing.category, change.value);
21528
22009
  return existing.category === "thought_level" ? updated.map(
21529
- (option) => option.category === "thought_level" ? {
21530
- ...option,
21531
- values: option.values.filter((value) => value.value !== AGENT_DEFAULT_REASONING_EFFORT)
21532
- } : option
22010
+ (option2) => option2.category === "thought_level" ? {
22011
+ ...option2,
22012
+ values: option2.values.filter((value) => value.value !== AGENT_DEFAULT_REASONING_EFFORT)
22013
+ } : option2
21533
22014
  ) : updated;
21534
22015
  };
21535
22016
  normalizeLifecycle = (response) => normalizeGrokLifecycle(response);
@@ -21932,7 +22413,7 @@ function createWritableAcpStream(output2) {
21932
22413
  function truncate3(value, maximumLength) {
21933
22414
  return value.length <= maximumLength ? value : `${value.slice(0, Math.max(0, maximumLength - 1))}\u2026`;
21934
22415
  }
21935
- function isRecord4(value) {
22416
+ function isRecord5(value) {
21936
22417
  return typeof value === "object" && value !== null && !Array.isArray(value);
21937
22418
  }
21938
22419
  function readString4(value, fallback = "") {
@@ -21960,12 +22441,12 @@ function normalizeElicitationOptions(schema) {
21960
22441
  const normalized = [];
21961
22442
  const oneOf = schema["oneOf"];
21962
22443
  if (Array.isArray(oneOf)) {
21963
- for (const option of oneOf) {
21964
- if (isRecord4(option) && typeof option["const"] === "string") {
22444
+ for (const option2 of oneOf) {
22445
+ if (isRecord5(option2) && typeof option2["const"] === "string") {
21965
22446
  normalized.push({
21966
- description: truncate3(readString4(option["description"]), 500),
21967
- label: truncate3(readString4(option["title"], option["const"]), 255),
21968
- value: truncate3(option["const"], 500)
22447
+ description: truncate3(readString4(option2["description"]), 500),
22448
+ label: truncate3(readString4(option2["title"], option2["const"]), 255),
22449
+ value: truncate3(option2["const"], 500)
21969
22450
  });
21970
22451
  }
21971
22452
  }
@@ -21981,7 +22462,7 @@ function normalizeElicitationOptions(schema) {
21981
22462
  return normalized.slice(0, 200);
21982
22463
  }
21983
22464
  const items = schema["items"];
21984
- if (!isRecord4(items)) {
22465
+ if (!isRecord5(items)) {
21985
22466
  return normalized;
21986
22467
  }
21987
22468
  const anyOf = items["anyOf"];
@@ -21994,7 +22475,7 @@ function numericString(value) {
21994
22475
  return typeof value === "number" && Number.isFinite(value) ? value.toString() : "";
21995
22476
  }
21996
22477
  function normalizeElicitationFields(requestedSchema) {
21997
- if (!isRecord4(requestedSchema) || !isRecord4(requestedSchema["properties"])) {
22478
+ if (!isRecord5(requestedSchema) || !isRecord5(requestedSchema["properties"])) {
21998
22479
  return [];
21999
22480
  }
22000
22481
  const properties = requestedSchema["properties"];
@@ -22004,7 +22485,7 @@ function normalizeElicitationFields(requestedSchema) {
22004
22485
  );
22005
22486
  const normalized = [];
22006
22487
  for (const [name, property] of Object.entries(properties)) {
22007
- if (!isRecord4(property)) {
22488
+ if (!isRecord5(property)) {
22008
22489
  continue;
22009
22490
  }
22010
22491
  const type = elicitationFieldType(property["type"]);
@@ -22095,7 +22576,7 @@ function validateElicitationContent(encoded, requestedSchema) {
22095
22576
  "invalid_elicitation_response"
22096
22577
  );
22097
22578
  }
22098
- if (!isRecord4(decoded) || !isRecord4(requestedSchema) || !isRecord4(requestedSchema["properties"])) {
22579
+ if (!isRecord5(decoded) || !isRecord5(requestedSchema) || !isRecord5(requestedSchema["properties"])) {
22099
22580
  throw new AcpExecutionError(
22100
22581
  "Elicitation response does not match the requested form",
22101
22582
  {},
@@ -22115,7 +22596,7 @@ function validateElicitationContent(encoded, requestedSchema) {
22115
22596
  const validated = {};
22116
22597
  for (const [name, value] of Object.entries(decoded)) {
22117
22598
  const property = properties[name];
22118
- if (!isRecord4(property)) {
22599
+ if (!isRecord5(property)) {
22119
22600
  throw new AcpExecutionError(
22120
22601
  `Elicitation field ${name} was not requested`,
22121
22602
  {},
@@ -22152,7 +22633,7 @@ function validateElicitationContent(encoded, requestedSchema) {
22152
22633
  );
22153
22634
  }
22154
22635
  const allowed = normalizeElicitationOptions(property);
22155
- if (allowed.length > 0 && value.some((entry) => !allowed.some((option) => option.value === entry))) {
22636
+ if (allowed.length > 0 && value.some((entry) => !allowed.some((option2) => option2.value === entry))) {
22156
22637
  throw new AcpExecutionError(
22157
22638
  `Elicitation field ${name} contains an invalid selection`,
22158
22639
  {},
@@ -22649,7 +23130,7 @@ var AcpProcessSession = class _AcpProcessSession {
22649
23130
  };
22650
23131
  nativeSessionId = () => this.#nativeSessionId;
22651
23132
  configure = async (options) => {
22652
- const existing = this.#configOptions.find((option) => option.id === options.configId);
23133
+ const existing = this.#configOptions.find((option2) => option2.id === options.configId);
22653
23134
  if (existing === void 0 || existing.type !== options.valueType) {
22654
23135
  throw new AcpExecutionError(
22655
23136
  "The requested ACP configuration option is unavailable",
@@ -22899,10 +23380,10 @@ var AcpProcessSession = class _AcpProcessSession {
22899
23380
  onPermission = async (request, signal) => {
22900
23381
  this.assertNativeSession(request.sessionId);
22901
23382
  const interactionId = `permission-${crypto.randomUUID()}`;
22902
- const options = request.options.slice(0, 20).map((option) => ({
22903
- kind: option.kind,
22904
- name: truncate3(option.name, 255),
22905
- optionId: truncate3(option.optionId, 255)
23383
+ const options = request.options.slice(0, 20).map((option2) => ({
23384
+ kind: option2.kind,
23385
+ name: truncate3(option2.name, 255),
23386
+ optionId: truncate3(option2.optionId, 255)
22906
23387
  }));
22907
23388
  if (options.length === 0) {
22908
23389
  throw new AcpExecutionError(
@@ -22911,7 +23392,7 @@ var AcpProcessSession = class _AcpProcessSession {
22911
23392
  "invalid_agent_permission_request"
22912
23393
  );
22913
23394
  }
22914
- const pending = new PendingPermission(interactionId, new Set(options.map((option) => option.optionId)));
23395
+ const pending = new PendingPermission(interactionId, new Set(options.map((option2) => option2.optionId)));
22915
23396
  this.#pendingPermissions.set(interactionId, pending);
22916
23397
  const abort = () => {
22917
23398
  void this.cancelPermission(interactionId);
@@ -23121,7 +23602,7 @@ var AcpProcessSession = class _AcpProcessSession {
23121
23602
  }
23122
23603
  if (update.sessionUpdate === "current_mode_update") {
23123
23604
  this.#configOptions = this.#configOptions.map(
23124
- (option) => option.category === "mode" ? { ...option, currentValue: update.currentModeId } : option
23605
+ (option2) => option2.category === "mode" ? { ...option2, currentValue: update.currentModeId } : option2
23125
23606
  );
23126
23607
  this.#configRevision += 1;
23127
23608
  await this.emitConfigUpdate();
@@ -23677,87 +24158,921 @@ var AcpSessionManager = class {
23677
24158
  async function runAcpPrompt(options) {
23678
24159
  const sessions = new AcpSessionManager();
23679
24160
  try {
23680
- return await sessions.runPrompt({
23681
- additionalDirectories: [],
23682
- agent: new LocalAgentDefinition("test-agent", "Test agent", options.agentCommand, options.agentArguments),
23683
- cwd: options.cwd,
23684
- commandId: crypto.randomUUID(),
23685
- images: [],
23686
- onActivity: options.onActivity,
23687
- onText: options.onText,
23688
- prompt: options.prompt,
23689
- resources: [],
23690
- sessionId: crypto.randomUUID(),
23691
- signal: options.signal
24161
+ return await sessions.runPrompt({
24162
+ additionalDirectories: [],
24163
+ agent: new LocalAgentDefinition("test-agent", "Test agent", options.agentCommand, options.agentArguments),
24164
+ cwd: options.cwd,
24165
+ commandId: crypto.randomUUID(),
24166
+ images: [],
24167
+ onActivity: options.onActivity,
24168
+ onText: options.onText,
24169
+ prompt: options.prompt,
24170
+ resources: [],
24171
+ sessionId: crypto.randomUUID(),
24172
+ signal: options.signal
24173
+ });
24174
+ } finally {
24175
+ await sessions.close();
24176
+ }
24177
+ }
24178
+
24179
+ // src/audit/audit-store.ts
24180
+ import { mkdirSync as mkdirSync2 } from "node:fs";
24181
+ import { dirname as dirname2 } from "node:path";
24182
+ import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
24183
+ var AuditStore = class {
24184
+ database;
24185
+ constructor(path2) {
24186
+ mkdirSync2(dirname2(path2), { recursive: true });
24187
+ this.database = new DatabaseSync2(path2);
24188
+ this.database.exec(`
24189
+ CREATE TABLE IF NOT EXISTS audit_events (
24190
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
24191
+ recorded_at TEXT NOT NULL,
24192
+ event TEXT NOT NULL,
24193
+ command_id TEXT NOT NULL,
24194
+ session_id TEXT NOT NULL,
24195
+ details_json TEXT NOT NULL DEFAULT '{}'
24196
+ ) STRICT
24197
+ `);
24198
+ const columns = this.database.prepare("PRAGMA table_info(audit_events)").all();
24199
+ if (!columns.some((column) => Reflect.get(column, "name") === "details_json")) {
24200
+ this.database.exec("ALTER TABLE audit_events ADD COLUMN details_json TEXT NOT NULL DEFAULT '{}'");
24201
+ }
24202
+ }
24203
+ record(record2) {
24204
+ this.database.prepare(
24205
+ `
24206
+ INSERT INTO audit_events (
24207
+ recorded_at,
24208
+ event,
24209
+ command_id,
24210
+ session_id,
24211
+ details_json
24212
+ ) VALUES (?, ?, ?, ?, ?)
24213
+ `
24214
+ ).run(
24215
+ (/* @__PURE__ */ new Date()).toISOString(),
24216
+ record2.event,
24217
+ record2.commandId,
24218
+ record2.sessionId,
24219
+ JSON.stringify(record2.details ?? {})
24220
+ );
24221
+ }
24222
+ close() {
24223
+ this.database.close();
24224
+ }
24225
+ };
24226
+
24227
+ // src/authorization/local-authorization-error.ts
24228
+ var LocalAuthorizationError = class extends Error {
24229
+ code = "local_authorization_failed";
24230
+ constructor(message, options = {}) {
24231
+ super(message, options);
24232
+ this.name = "LocalAuthorizationError";
24233
+ }
24234
+ };
24235
+
24236
+ // src/bots/bot-execution-context.ts
24237
+ import { randomBytes } from "node:crypto";
24238
+
24239
+ // src/bots/local-bot-grant-store.ts
24240
+ import { createHash, randomUUID } from "node:crypto";
24241
+ import { stat as stat2 } from "node:fs/promises";
24242
+ import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
24243
+ var LOCAL_BOT_GRANT_LIFETIME_MILLISECONDS = 90 * 24 * 60 * 60 * 1e3;
24244
+ var LocalBotAuthorizationError = class extends Error {
24245
+ code;
24246
+ constructor(code, message, options = {}) {
24247
+ super(message, options);
24248
+ this.code = code;
24249
+ this.name = "LocalBotAuthorizationError";
24250
+ }
24251
+ };
24252
+ var LocalBotGrant = class {
24253
+ agent;
24254
+ agentIdentityDigest;
24255
+ allowedDeliveryTargetIds;
24256
+ behaviorDigest;
24257
+ behaviorRevisionId;
24258
+ bindingId;
24259
+ bindingRevision;
24260
+ botId;
24261
+ expiresAt;
24262
+ localGrantId;
24263
+ revocationEpoch;
24264
+ workspaceIdentityDigest;
24265
+ workspacePath;
24266
+ constructor(localGrantId, botId, behaviorRevisionId, behaviorDigest, bindingId, bindingRevision, agent, agentIdentityDigest, workspacePath, workspaceIdentityDigest, allowedDeliveryTargetIds, expiresAt, revocationEpoch) {
24267
+ this.localGrantId = localGrantId;
24268
+ this.botId = botId;
24269
+ this.behaviorRevisionId = behaviorRevisionId;
24270
+ this.behaviorDigest = behaviorDigest;
24271
+ this.bindingId = bindingId;
24272
+ this.bindingRevision = bindingRevision;
24273
+ this.agent = agent;
24274
+ this.agentIdentityDigest = agentIdentityDigest;
24275
+ this.workspacePath = workspacePath;
24276
+ this.workspaceIdentityDigest = workspaceIdentityDigest;
24277
+ this.allowedDeliveryTargetIds = Object.freeze([...allowedDeliveryTargetIds]);
24278
+ this.expiresAt = expiresAt;
24279
+ this.revocationEpoch = revocationEpoch;
24280
+ }
24281
+ };
24282
+ function digest(value) {
24283
+ return createHash("sha256").update(value, "utf8").digest("hex");
24284
+ }
24285
+ function agentDigest(agent) {
24286
+ return digest(
24287
+ JSON.stringify({
24288
+ adapter: agent.adapterIdentity,
24289
+ agent: agent.agentIdentity,
24290
+ agentVersion: agent.agentVersion,
24291
+ arguments: agent.arguments,
24292
+ id: agent.id
24293
+ })
24294
+ );
24295
+ }
24296
+ async function workspaceDigest(path2) {
24297
+ const metadata = await stat2(path2);
24298
+ if (!metadata.isDirectory()) {
24299
+ throw new LocalBotAuthorizationError("binding_incompatible", "The Bot workspace is not a directory");
24300
+ }
24301
+ return digest(
24302
+ JSON.stringify({
24303
+ changedAtMilliseconds: metadata.ctimeMs,
24304
+ device: metadata.dev,
24305
+ inode: metadata.ino,
24306
+ path: path2
24307
+ })
24308
+ );
24309
+ }
24310
+ function exactTargets(left, right) {
24311
+ if (left.length !== right.length) {
24312
+ return false;
24313
+ }
24314
+ const expected = [...left].sort();
24315
+ const actual = [...right].sort();
24316
+ return expected.every((target, index) => target === actual[index]);
24317
+ }
24318
+ function rowString(row, key) {
24319
+ const value = Reflect.get(row, key);
24320
+ if (typeof value !== "string") {
24321
+ throw new LocalBotAuthorizationError("local_grant_invalid", "The local Bot grant is invalid");
24322
+ }
24323
+ return value;
24324
+ }
24325
+ function rowInteger(row, key) {
24326
+ const value = Reflect.get(row, key);
24327
+ if (typeof value !== "number" || !Number.isSafeInteger(value)) {
24328
+ throw new LocalBotAuthorizationError("local_grant_invalid", "The local Bot grant is invalid");
24329
+ }
24330
+ return value;
24331
+ }
24332
+ function parseTargets(encoded) {
24333
+ let value;
24334
+ try {
24335
+ value = JSON.parse(encoded);
24336
+ } catch (cause) {
24337
+ throw new LocalBotAuthorizationError("local_grant_invalid", "The local Bot grant is invalid", { cause });
24338
+ }
24339
+ if (!Array.isArray(value) || value.some((target) => typeof target !== "string")) {
24340
+ throw new LocalBotAuthorizationError("local_grant_invalid", "The local Bot grant is invalid");
24341
+ }
24342
+ return value.filter((target) => typeof target === "string");
24343
+ }
24344
+ var LocalBotGrantStore = class {
24345
+ #database;
24346
+ constructor(path2) {
24347
+ this.#database = new DatabaseSync3(path2);
24348
+ this.#database.exec(`
24349
+ CREATE TABLE IF NOT EXISTS local_bot_grants (
24350
+ local_grant_id TEXT PRIMARY KEY,
24351
+ bot_id TEXT NOT NULL,
24352
+ behavior_revision_id TEXT NOT NULL,
24353
+ behavior_digest TEXT NOT NULL,
24354
+ binding_id TEXT NOT NULL UNIQUE,
24355
+ binding_revision INTEGER NOT NULL,
24356
+ agent_ref TEXT NOT NULL,
24357
+ agent_identity_digest TEXT NOT NULL,
24358
+ workspace_ref TEXT NOT NULL,
24359
+ workspace_path TEXT NOT NULL,
24360
+ workspace_identity_digest TEXT NOT NULL,
24361
+ allowed_delivery_target_ids_json TEXT NOT NULL,
24362
+ unattended_policy_json TEXT NOT NULL,
24363
+ created_at INTEGER NOT NULL,
24364
+ expires_at INTEGER NOT NULL,
24365
+ revocation_epoch INTEGER NOT NULL DEFAULT 0,
24366
+ revoked_at INTEGER
24367
+ ) STRICT;
24368
+ CREATE TABLE IF NOT EXISTS local_bot_binding_resolutions (
24369
+ request_id TEXT PRIMARY KEY,
24370
+ binding_id TEXT NOT NULL,
24371
+ local_grant_id TEXT NOT NULL,
24372
+ resolved_at INTEGER NOT NULL,
24373
+ result TEXT NOT NULL CHECK (result IN ('approved', 'unavailable')),
24374
+ error_code TEXT,
24375
+ error_message TEXT
24376
+ ) STRICT;
24377
+ `);
24378
+ }
24379
+ approve = async (request, catalog, directories, bindingAuthorityId, now, signal) => {
24380
+ signal.throwIfAborted();
24381
+ const existing = this.#database.prepare(
24382
+ `SELECT grants.* FROM local_bot_binding_resolutions AS resolutions
24383
+ INNER JOIN local_bot_grants AS grants
24384
+ ON grants.local_grant_id = resolutions.local_grant_id
24385
+ WHERE resolutions.request_id = ? AND resolutions.binding_id = ?
24386
+ AND resolutions.result = 'approved'`
24387
+ ).get(request.requestId, request.bindingId);
24388
+ if (existing !== void 0) {
24389
+ return new BotExecutionBindingApprovedEvent(
24390
+ request.requestId,
24391
+ request.botId,
24392
+ request.behaviorRevisionId,
24393
+ request.bindingId,
24394
+ request.bindingRevision,
24395
+ rowString(existing, "local_grant_id"),
24396
+ rowString(existing, "agent_identity_digest"),
24397
+ rowString(existing, "workspace_identity_digest")
24398
+ );
24399
+ }
24400
+ const resolved = await this.resolveProposal(request, catalog, directories, bindingAuthorityId, signal);
24401
+ const localGrantId = `lbg_${randomUUID()}`;
24402
+ const expiresAt = now + LOCAL_BOT_GRANT_LIFETIME_MILLISECONDS;
24403
+ this.#database.exec("BEGIN IMMEDIATE");
24404
+ try {
24405
+ this.#database.prepare(
24406
+ `INSERT INTO local_bot_grants (
24407
+ local_grant_id, bot_id, behavior_revision_id, behavior_digest,
24408
+ binding_id, binding_revision, agent_ref,
24409
+ agent_identity_digest, workspace_ref, workspace_path,
24410
+ workspace_identity_digest, allowed_delivery_target_ids_json,
24411
+ unattended_policy_json, created_at, expires_at
24412
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
24413
+ ).run(
24414
+ localGrantId,
24415
+ request.botId,
24416
+ request.behaviorRevisionId,
24417
+ request.behaviorDigest,
24418
+ request.bindingId,
24419
+ request.bindingRevision,
24420
+ request.agentRef,
24421
+ resolved.agentIdentityDigest,
24422
+ request.workspaceRef,
24423
+ resolved.workspacePath,
24424
+ resolved.workspaceIdentityDigest,
24425
+ JSON.stringify(request.allowedDeliveryTargets.map((target) => target.deliveryTargetId)),
24426
+ JSON.stringify({ localSideEffects: "owner-approval-required" }),
24427
+ now,
24428
+ expiresAt
24429
+ );
24430
+ this.#database.prepare(
24431
+ `INSERT INTO local_bot_binding_resolutions (
24432
+ request_id, binding_id, local_grant_id, resolved_at, result
24433
+ ) VALUES (?, ?, ?, ?, 'approved')`
24434
+ ).run(request.requestId, request.bindingId, localGrantId, now);
24435
+ this.#database.exec("COMMIT");
24436
+ } catch (cause) {
24437
+ this.#database.exec("ROLLBACK");
24438
+ throw cause;
24439
+ }
24440
+ signal.throwIfAborted();
24441
+ return new BotExecutionBindingApprovedEvent(
24442
+ request.requestId,
24443
+ request.botId,
24444
+ request.behaviorRevisionId,
24445
+ request.bindingId,
24446
+ request.bindingRevision,
24447
+ localGrantId,
24448
+ resolved.agentIdentityDigest,
24449
+ resolved.workspaceIdentityDigest
24450
+ );
24451
+ };
24452
+ resolveExecution = async (command, catalog, directories, bindingAuthorityId, now, signal) => {
24453
+ signal.throwIfAborted();
24454
+ const row = this.#database.prepare(
24455
+ `SELECT * FROM local_bot_grants
24456
+ WHERE local_grant_id = ? AND bot_id = ?
24457
+ AND behavior_revision_id = ? AND behavior_digest = ?
24458
+ AND binding_id = ? AND binding_revision = ?
24459
+ AND agent_ref = ? AND workspace_ref = ?
24460
+ AND revoked_at IS NULL AND expires_at > ?`
24461
+ ).get(
24462
+ command.localGrantId,
24463
+ command.botId,
24464
+ command.behaviorRevisionId,
24465
+ command.behaviorDigest,
24466
+ command.bindingId,
24467
+ command.bindingRevision,
24468
+ command.agentId,
24469
+ command.directoryId,
24470
+ now
24471
+ );
24472
+ if (row === void 0) {
24473
+ throw new LocalBotAuthorizationError(
24474
+ "binding_not_approved",
24475
+ "The Bot execution binding is not locally approved"
24476
+ );
24477
+ }
24478
+ const approvedTargets = parseTargets(rowString(row, "allowed_delivery_target_ids_json"));
24479
+ const requestedTargets = command.allowedDeliveryTargets.map((target) => target.deliveryTargetId);
24480
+ if (!exactTargets(approvedTargets, requestedTargets)) {
24481
+ throw new LocalBotAuthorizationError(
24482
+ "binding_not_approved",
24483
+ "The Bot execution target policy changed after local approval"
24484
+ );
24485
+ }
24486
+ const agent = catalog.find(command.agentId);
24487
+ const [adapterUnchanged, agentUnchanged] = await Promise.all([
24488
+ revalidateExecutable(agent.adapterIdentity),
24489
+ revalidateExecutable(agent.agentIdentity)
24490
+ ]);
24491
+ signal.throwIfAborted();
24492
+ const workspacePath = await directories.resolve(bindingAuthorityId, command.directoryId, signal);
24493
+ const currentAgentDigest = agentDigest(agent);
24494
+ const currentWorkspaceDigest = await workspaceDigest(workspacePath);
24495
+ signal.throwIfAborted();
24496
+ if (!adapterUnchanged || !agentUnchanged || currentAgentDigest !== rowString(row, "agent_identity_digest") || currentWorkspaceDigest !== rowString(row, "workspace_identity_digest") || workspacePath !== rowString(row, "workspace_path")) {
24497
+ this.revoke(rowString(row, "local_grant_id"), now);
24498
+ throw new LocalBotAuthorizationError(
24499
+ "binding_not_approved",
24500
+ "The Bot execution target changed and requires local approval"
24501
+ );
24502
+ }
24503
+ if (command.behaviorInstructions.length > 0 && !agent.capabilities.embeddedContextPrompt) {
24504
+ throw new LocalBotAuthorizationError(
24505
+ "binding_incompatible",
24506
+ "The local Agent cannot apply the approved Bot behavior"
24507
+ );
24508
+ }
24509
+ return new LocalBotGrant(
24510
+ rowString(row, "local_grant_id"),
24511
+ command.botId,
24512
+ command.behaviorRevisionId,
24513
+ command.behaviorDigest,
24514
+ command.bindingId,
24515
+ command.bindingRevision,
24516
+ agent,
24517
+ currentAgentDigest,
24518
+ workspacePath,
24519
+ currentWorkspaceDigest,
24520
+ approvedTargets,
24521
+ rowInteger(row, "expires_at"),
24522
+ rowInteger(row, "revocation_epoch")
24523
+ );
24524
+ };
24525
+ recordUnavailable = (request, code, message, now) => {
24526
+ this.#database.prepare(
24527
+ `INSERT OR IGNORE INTO local_bot_binding_resolutions (
24528
+ request_id, binding_id, local_grant_id, resolved_at,
24529
+ result, error_code, error_message
24530
+ ) VALUES (?, ?, '', ?, 'unavailable', ?, ?)`
24531
+ ).run(request.requestId, request.bindingId, now, code, message);
24532
+ };
24533
+ close = () => {
24534
+ this.#database.close();
24535
+ };
24536
+ resolveProposal = async (request, catalog, directories, bindingAuthorityId, signal) => {
24537
+ const agent = catalog.find(request.agentRef);
24538
+ if (request.requiredCapabilities.includes("embedded-context") && !agent.capabilities.embeddedContextPrompt) {
24539
+ throw new LocalBotAuthorizationError(
24540
+ "binding_incompatible",
24541
+ "The local Agent cannot apply embedded Bot context"
24542
+ );
24543
+ }
24544
+ if (request.requiredCapabilities.some((capability) => capability !== "embedded-context")) {
24545
+ throw new LocalBotAuthorizationError(
24546
+ "binding_incompatible",
24547
+ "The Bot requires an unsupported local Agent capability"
24548
+ );
24549
+ }
24550
+ const [adapterUnchanged, agentUnchanged] = await Promise.all([
24551
+ revalidateExecutable(agent.adapterIdentity),
24552
+ revalidateExecutable(agent.agentIdentity)
24553
+ ]);
24554
+ signal.throwIfAborted();
24555
+ if (!adapterUnchanged || !agentUnchanged) {
24556
+ throw new LocalBotAuthorizationError(
24557
+ "binding_incompatible",
24558
+ "The local Agent executable changed before approval"
24559
+ );
24560
+ }
24561
+ const workspacePath = await directories.resolve(bindingAuthorityId, request.workspaceRef, signal);
24562
+ return {
24563
+ agent,
24564
+ agentIdentityDigest: agentDigest(agent),
24565
+ workspaceIdentityDigest: await workspaceDigest(workspacePath),
24566
+ workspacePath
24567
+ };
24568
+ };
24569
+ revoke = (localGrantId, now) => {
24570
+ this.#database.prepare(
24571
+ `UPDATE local_bot_grants
24572
+ SET revoked_at = COALESCE(revoked_at, ?), revocation_epoch = revocation_epoch + 1
24573
+ WHERE local_grant_id = ? AND revoked_at IS NULL`
24574
+ ).run(now, localGrantId);
24575
+ };
24576
+ };
24577
+
24578
+ // src/bots/bot-execution-context.ts
24579
+ var ActiveBotExecutionContext = class {
24580
+ command;
24581
+ contextHandle;
24582
+ constructor(contextHandle, command) {
24583
+ this.contextHandle = contextHandle;
24584
+ this.command = command;
24585
+ }
24586
+ resolveTarget = (target) => {
24587
+ if (target === "current") {
24588
+ if (!(this.command.replyRoute instanceof BotConnectionReplyRoute)) {
24589
+ throw new LocalBotAuthorizationError(
24590
+ "delivery_target_not_allowed",
24591
+ "This Bot conversation has no external reply target"
24592
+ );
24593
+ }
24594
+ return this.command.replyRoute.deliveryTargetId;
24595
+ }
24596
+ const resolved = this.command.allowedDeliveryTargets.find((candidate) => candidate.alias === target);
24597
+ if (resolved === void 0) {
24598
+ throw new LocalBotAuthorizationError(
24599
+ "delivery_target_not_allowed",
24600
+ "The named Bot delivery target is not approved"
24601
+ );
24602
+ }
24603
+ return resolved.deliveryTargetId;
24604
+ };
24605
+ };
24606
+ var BotExecutionContextLease = class {
24607
+ context;
24608
+ #release;
24609
+ #released = false;
24610
+ constructor(context, release) {
24611
+ this.context = context;
24612
+ this.#release = release;
24613
+ }
24614
+ release = () => {
24615
+ if (this.#released) {
24616
+ return;
24617
+ }
24618
+ this.#released = true;
24619
+ this.#release();
24620
+ };
24621
+ };
24622
+ var BotExecutionContextRegistry = class {
24623
+ #activeByHandle = /* @__PURE__ */ new Map();
24624
+ #handlesBySession = /* @__PURE__ */ new Map();
24625
+ #inactiveHandles = /* @__PURE__ */ new Set();
24626
+ #now;
24627
+ constructor(now = Date.now) {
24628
+ this.#now = now;
24629
+ }
24630
+ activate = (command) => {
24631
+ let handle = this.#handlesBySession.get(command.sessionId);
24632
+ if (handle === void 0) {
24633
+ handle = `ctx_${randomBytes(32).toString("base64url")}`;
24634
+ this.#handlesBySession.set(command.sessionId, handle);
24635
+ }
24636
+ if (this.#activeByHandle.has(handle)) {
24637
+ throw new LocalBotAuthorizationError("session_busy", "The Bot execution context is already active");
24638
+ }
24639
+ const context = new ActiveBotExecutionContext(handle, command);
24640
+ this.#inactiveHandles.delete(handle);
24641
+ this.#activeByHandle.set(handle, context);
24642
+ return new BotExecutionContextLease(context, () => {
24643
+ if (this.#activeByHandle.get(handle) === context) {
24644
+ this.#activeByHandle.delete(handle);
24645
+ this.#inactiveHandles.add(handle);
24646
+ }
24647
+ });
24648
+ };
24649
+ read = (handle) => {
24650
+ const context = this.#activeByHandle.get(handle);
24651
+ if (context === void 0) {
24652
+ if (this.#inactiveHandles.has(handle)) {
24653
+ throw new LocalBotAuthorizationError(
24654
+ "execution_capability_expired",
24655
+ "The Bot execution capability has expired"
24656
+ );
24657
+ }
24658
+ throw new LocalBotAuthorizationError(
24659
+ "execution_context_required",
24660
+ "An active Bot execution context is required"
24661
+ );
24662
+ }
24663
+ if (Date.parse(context.command.executionDeadlineAt) <= this.#now()) {
24664
+ throw new LocalBotAuthorizationError(
24665
+ "execution_capability_expired",
24666
+ "The Bot execution capability has expired"
24667
+ );
24668
+ }
24669
+ return context;
24670
+ };
24671
+ };
24672
+
24673
+ // src/bots/bot-message-command.ts
24674
+ import { randomUUID as randomUUID2 } from "node:crypto";
24675
+ import { createConnection } from "node:net";
24676
+ var BOT_IPC_RESPONSE_LIMIT = 64 * 1024;
24677
+ var BOT_IPC_TIMEOUT_MILLISECONDS = 2e4;
24678
+ var BotMessageCommandError = class extends Error {
24679
+ code;
24680
+ constructor(code, message, options = {}) {
24681
+ super(message, options);
24682
+ this.code = code;
24683
+ this.name = "BotMessageCommandError";
24684
+ }
24685
+ };
24686
+ function isRecord6(value) {
24687
+ return typeof value === "object" && value !== null && !Array.isArray(value);
24688
+ }
24689
+ function requiredEnvironment(environment, name) {
24690
+ const value = environment[name]?.trim();
24691
+ if (value === void 0 || value.length === 0) {
24692
+ throw new BotMessageCommandError(
24693
+ "execution_context_required",
24694
+ "This command is available only inside an active Mobius Bot execution"
24695
+ );
24696
+ }
24697
+ return value;
24698
+ }
24699
+ function option(arguments_, name) {
24700
+ const index = arguments_.indexOf(name);
24701
+ if (index < 0 || index + 1 >= arguments_.length || arguments_[index + 1]?.startsWith("--") === true) {
24702
+ throw new BotMessageCommandError(
24703
+ "invalid_request",
24704
+ "Usage: mobius bot message send --target <current|alias> --text <message>"
24705
+ );
24706
+ }
24707
+ const value = arguments_[index + 1];
24708
+ if (value === void 0) {
24709
+ throw new BotMessageCommandError("invalid_request", "The Bot message option is missing");
24710
+ }
24711
+ return value;
24712
+ }
24713
+ function validateArguments(arguments_) {
24714
+ if (arguments_.length !== 4) {
24715
+ throw new BotMessageCommandError(
24716
+ "invalid_request",
24717
+ "Usage: mobius bot message send --target <current|alias> --text <message>"
24718
+ );
24719
+ }
24720
+ const names = [arguments_[0], arguments_[2]];
24721
+ if (!names.includes("--target") || !names.includes("--text") || names[0] === names[1]) {
24722
+ throw new BotMessageCommandError(
24723
+ "invalid_request",
24724
+ "Usage: mobius bot message send --target <current|alias> --text <message>"
24725
+ );
24726
+ }
24727
+ }
24728
+ function decodeResponse(encoded) {
24729
+ let value;
24730
+ try {
24731
+ value = JSON.parse(encoded);
24732
+ } catch (cause) {
24733
+ throw new BotMessageCommandError("bot_service_unavailable", "The local Bot service returned invalid data", {
24734
+ cause
24735
+ });
24736
+ }
24737
+ if (!isRecord6(value) || typeof value["ok"] !== "boolean") {
24738
+ throw new BotMessageCommandError("bot_service_unavailable", "The local Bot service returned invalid data");
24739
+ }
24740
+ if (value["ok"] === true && typeof value["outboundMessageId"] === "string") {
24741
+ return value["outboundMessageId"];
24742
+ }
24743
+ const error61 = value["error"];
24744
+ if (value["ok"] === false && isRecord6(error61) && typeof error61["code"] === "string" && typeof error61["message"] === "string") {
24745
+ throw new BotMessageCommandError(error61["code"], error61["message"]);
24746
+ }
24747
+ throw new BotMessageCommandError("bot_service_unavailable", "The local Bot service returned invalid data");
24748
+ }
24749
+ async function requestLocalBotService(socketPath, payload, signal) {
24750
+ signal.throwIfAborted();
24751
+ return await new Promise((resolve5, reject) => {
24752
+ const socket = createConnection(socketPath);
24753
+ const chunks = [];
24754
+ let length = 0;
24755
+ let finished = false;
24756
+ const finish = () => {
24757
+ socket.removeAllListeners();
24758
+ socket.destroy();
24759
+ };
24760
+ const fail = (error61) => {
24761
+ if (finished) {
24762
+ return;
24763
+ }
24764
+ finished = true;
24765
+ finish();
24766
+ if (error61 instanceof BotMessageCommandError) {
24767
+ reject(error61);
24768
+ return;
24769
+ }
24770
+ reject(
24771
+ new BotMessageCommandError(
24772
+ "execution_context_required",
24773
+ "The active Mobius Bot execution is unavailable",
24774
+ { cause: error61 }
24775
+ )
24776
+ );
24777
+ };
24778
+ const abort = () => fail(signal.reason);
24779
+ socket.setTimeout(BOT_IPC_TIMEOUT_MILLISECONDS, () => {
24780
+ fail(new BotMessageCommandError("bot_service_unavailable", "The local Bot service timed out"));
24781
+ });
24782
+ socket.once("error", fail);
24783
+ socket.once("connect", () => socket.end(`${payload}
24784
+ `));
24785
+ socket.on("data", (chunk) => {
24786
+ length += chunk.byteLength;
24787
+ if (length > BOT_IPC_RESPONSE_LIMIT) {
24788
+ fail(new BotMessageCommandError("bot_service_unavailable", "The local Bot response is too large"));
24789
+ return;
24790
+ }
24791
+ chunks.push(chunk);
24792
+ });
24793
+ socket.once("end", () => {
24794
+ if (finished) {
24795
+ return;
24796
+ }
24797
+ finished = true;
24798
+ signal.removeEventListener("abort", abort);
24799
+ try {
24800
+ resolve5(decodeResponse(Buffer.concat(chunks).toString("utf8")));
24801
+ } catch (error61) {
24802
+ reject(error61);
24803
+ } finally {
24804
+ finish();
24805
+ }
24806
+ });
24807
+ signal.addEventListener("abort", abort, { once: true });
24808
+ });
24809
+ }
24810
+ async function executeBotMessageCommand(arguments_, environment, signal) {
24811
+ validateArguments(arguments_);
24812
+ const contextHandle = requiredEnvironment(environment, "MOBIUS_BOT_CONTEXT");
24813
+ const socketPath = requiredEnvironment(environment, "MOBIUS_BOT_SOCKET");
24814
+ const target = option(arguments_, "--target");
24815
+ const text = option(arguments_, "--text");
24816
+ if (!/^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/.test(target) || text.trim().length === 0 || text.length > 1e4) {
24817
+ throw new BotMessageCommandError("invalid_request", "The Bot outbound message is invalid");
24818
+ }
24819
+ return await requestLocalBotService(
24820
+ socketPath,
24821
+ JSON.stringify({
24822
+ contextHandle,
24823
+ idempotencyKey: `cli_${randomUUID2()}`,
24824
+ target,
24825
+ text
24826
+ }),
24827
+ signal
24828
+ );
24829
+ }
24830
+
24831
+ // src/bots/bot-outbound-ipc.ts
24832
+ import { chmod, mkdir, unlink } from "node:fs/promises";
24833
+ import { createServer } from "node:net";
24834
+ import { dirname as dirname3, isAbsolute } from "node:path";
24835
+ import { fetch } from "undici";
24836
+ var BOT_IPC_REQUEST_LIMIT = 32 * 1024;
24837
+ var BOT_IPC_TIMEOUT_MILLISECONDS2 = 2e4;
24838
+ var BOT_RELAY_TIMEOUT_MILLISECONDS = 2e4;
24839
+ var IDENTIFIER_PATTERN5 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
24840
+ var WINDOWS_NAMED_PIPE_PREFIX = "\\\\.\\pipe\\";
24841
+ var BotOutboundIpcRequest = class {
24842
+ contextHandle;
24843
+ idempotencyKey;
24844
+ target;
24845
+ text;
24846
+ constructor(contextHandle, idempotencyKey, target, text) {
24847
+ this.contextHandle = contextHandle;
24848
+ this.idempotencyKey = idempotencyKey;
24849
+ this.target = target;
24850
+ this.text = text;
24851
+ }
24852
+ };
24853
+ function isRecord7(value) {
24854
+ return typeof value === "object" && value !== null && !Array.isArray(value);
24855
+ }
24856
+ function decodeRequest(encoded) {
24857
+ let value;
24858
+ try {
24859
+ value = JSON.parse(encoded);
24860
+ } catch (cause) {
24861
+ throw new LocalBotAuthorizationError("invalid_request", "The local Bot request is invalid", { cause });
24862
+ }
24863
+ if (!isRecord7(value)) {
24864
+ throw new LocalBotAuthorizationError("invalid_request", "The local Bot request is invalid");
24865
+ }
24866
+ const keys = Object.keys(value);
24867
+ if (keys.length !== 4 || !keys.every((key) => ["contextHandle", "idempotencyKey", "target", "text"].includes(key))) {
24868
+ throw new LocalBotAuthorizationError("invalid_request", "The local Bot request fields are invalid");
24869
+ }
24870
+ const contextHandle = value["contextHandle"];
24871
+ const idempotencyKey = value["idempotencyKey"];
24872
+ const target = value["target"];
24873
+ const text = value["text"];
24874
+ if (typeof contextHandle !== "string" || !/^ctx_[a-zA-Z0-9_-]{43}$/.test(contextHandle) || typeof idempotencyKey !== "string" || !IDENTIFIER_PATTERN5.test(idempotencyKey) || typeof target !== "string" || !IDENTIFIER_PATTERN5.test(target) || typeof text !== "string" || text.trim().length === 0 || text.length > 1e4) {
24875
+ throw new LocalBotAuthorizationError("invalid_request", "The local Bot request is invalid");
24876
+ }
24877
+ return new BotOutboundIpcRequest(contextHandle, idempotencyKey, target, text);
24878
+ }
24879
+ function relayEndpoint(relayUrl, context, target) {
24880
+ const endpoint = new URL(relayUrl);
24881
+ if (endpoint.protocol !== "ws:" && endpoint.protocol !== "wss:") {
24882
+ throw new LocalBotAuthorizationError("bot_service_unavailable", "The Mobius Relay URL is invalid");
24883
+ }
24884
+ endpoint.protocol = endpoint.protocol === "wss:" ? "https:" : "http:";
24885
+ endpoint.search = "";
24886
+ const execution = encodeURIComponent(context.command.executionId);
24887
+ if (target === "current") {
24888
+ context.resolveTarget(target);
24889
+ endpoint.pathname = `${MOBIUS_API_PREFIX}/v1/bot-executions/${execution}/reply-messages`;
24890
+ return endpoint;
24891
+ }
24892
+ const deliveryTargetId = context.resolveTarget(target);
24893
+ endpoint.pathname = `${MOBIUS_API_PREFIX}/v1/bot-executions/${execution}/delivery-targets/${encodeURIComponent(deliveryTargetId)}/messages`;
24894
+ return endpoint;
24895
+ }
24896
+ function daemonToken(relayUrl) {
24897
+ const token = relayUrl.searchParams.get("token") ?? "";
24898
+ if (!/^[a-zA-Z0-9_-]{32,256}$/.test(token)) {
24899
+ throw new LocalBotAuthorizationError("bot_service_unavailable", "The Runtime credential is unavailable");
24900
+ }
24901
+ return token;
24902
+ }
24903
+ async function decodeRelayResponse(response) {
24904
+ const encoded = await response.text();
24905
+ let value;
24906
+ try {
24907
+ value = JSON.parse(encoded);
24908
+ } catch (cause) {
24909
+ throw new LocalBotAuthorizationError("bot_service_unavailable", "The Mobius Relay returned invalid data", {
24910
+ cause
23692
24911
  });
23693
- } finally {
23694
- await sessions.close();
23695
24912
  }
23696
- }
23697
-
23698
- // src/audit/audit-store.ts
23699
- import { mkdirSync as mkdirSync2 } from "node:fs";
23700
- import { dirname as dirname2 } from "node:path";
23701
- import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
23702
- var AuditStore = class {
23703
- database;
23704
- constructor(path2) {
23705
- mkdirSync2(dirname2(path2), { recursive: true });
23706
- this.database = new DatabaseSync2(path2);
23707
- this.database.exec(`
23708
- CREATE TABLE IF NOT EXISTS audit_events (
23709
- id INTEGER PRIMARY KEY AUTOINCREMENT,
23710
- recorded_at TEXT NOT NULL,
23711
- event TEXT NOT NULL,
23712
- command_id TEXT NOT NULL,
23713
- session_id TEXT NOT NULL,
23714
- details_json TEXT NOT NULL DEFAULT '{}'
23715
- ) STRICT
23716
- `);
23717
- const columns = this.database.prepare("PRAGMA table_info(audit_events)").all();
23718
- if (!columns.some((column) => Reflect.get(column, "name") === "details_json")) {
23719
- this.database.exec("ALTER TABLE audit_events ADD COLUMN details_json TEXT NOT NULL DEFAULT '{}'");
23720
- }
24913
+ if (response.status === 202 && isRecord7(value) && typeof value["outboundMessageId"] === "string") {
24914
+ return value["outboundMessageId"];
23721
24915
  }
23722
- record(record2) {
23723
- this.database.prepare(
23724
- `
23725
- INSERT INTO audit_events (
23726
- recorded_at,
23727
- event,
23728
- command_id,
23729
- session_id,
23730
- details_json
23731
- ) VALUES (?, ?, ?, ?, ?)
23732
- `
23733
- ).run(
23734
- (/* @__PURE__ */ new Date()).toISOString(),
23735
- record2.event,
23736
- record2.commandId,
23737
- record2.sessionId,
23738
- JSON.stringify(record2.details ?? {})
23739
- );
24916
+ if (isRecord7(value) && isRecord7(value["error"])) {
24917
+ const error61 = value["error"];
24918
+ if (typeof error61["code"] === "string" && typeof error61["message"] === "string") {
24919
+ throw new LocalBotAuthorizationError(error61["code"], error61["message"]);
24920
+ }
23740
24921
  }
23741
- close() {
23742
- this.database.close();
24922
+ throw new LocalBotAuthorizationError("bot_service_unavailable", "The Mobius Relay rejected the Bot action");
24923
+ }
24924
+ var BotOutboundIpcServer = class {
24925
+ #registry;
24926
+ #relayUrl;
24927
+ #server;
24928
+ #socketPath;
24929
+ #usesFilesystemSocket;
24930
+ constructor(socketPath, relayUrl, registry2) {
24931
+ const usesFilesystemSocket = !socketPath.startsWith(WINDOWS_NAMED_PIPE_PREFIX);
24932
+ if (usesFilesystemSocket && !isAbsolute(socketPath)) {
24933
+ throw new Error("The Bot IPC path must be absolute");
24934
+ }
24935
+ this.#registry = registry2;
24936
+ this.#relayUrl = new URL(relayUrl);
24937
+ this.#server = createServer({ allowHalfOpen: true }, (socket) => this.accept(socket));
24938
+ this.#socketPath = socketPath;
24939
+ this.#usesFilesystemSocket = usesFilesystemSocket;
23743
24940
  }
23744
- };
23745
-
23746
- // src/authorization/local-authorization-error.ts
23747
- var LocalAuthorizationError = class extends Error {
23748
- code = "local_authorization_failed";
23749
- constructor(message, options = {}) {
23750
- super(message, options);
23751
- this.name = "LocalAuthorizationError";
24941
+ get socketPath() {
24942
+ return this.#socketPath;
23752
24943
  }
24944
+ listen = async (signal) => {
24945
+ signal.throwIfAborted();
24946
+ if (this.#usesFilesystemSocket) {
24947
+ await mkdir(dirname3(this.#socketPath), { mode: 448, recursive: true });
24948
+ await unlink(this.#socketPath).catch((error61) => {
24949
+ if (!isRecord7(error61) || error61["code"] !== "ENOENT") {
24950
+ throw error61;
24951
+ }
24952
+ });
24953
+ }
24954
+ await new Promise((resolve5, reject) => {
24955
+ const fail = (error61) => reject(error61);
24956
+ this.#server.once("error", fail);
24957
+ this.#server.listen(this.#socketPath, () => {
24958
+ this.#server.removeListener("error", fail);
24959
+ resolve5();
24960
+ });
24961
+ });
24962
+ if (this.#usesFilesystemSocket) {
24963
+ await chmod(this.#socketPath, 384);
24964
+ }
24965
+ signal.addEventListener("abort", this.abort, { once: true });
24966
+ if (signal.aborted) {
24967
+ this.abort();
24968
+ }
24969
+ };
24970
+ close = async () => {
24971
+ if (this.#server.listening) {
24972
+ await new Promise((resolve5, reject) => {
24973
+ this.#server.close((error61) => {
24974
+ if (error61 === void 0) {
24975
+ resolve5();
24976
+ return;
24977
+ }
24978
+ reject(error61);
24979
+ });
24980
+ });
24981
+ }
24982
+ if (this.#usesFilesystemSocket) {
24983
+ await unlink(this.#socketPath).catch((error61) => {
24984
+ if (!isRecord7(error61) || error61["code"] !== "ENOENT") {
24985
+ throw error61;
24986
+ }
24987
+ });
24988
+ }
24989
+ };
24990
+ #abort = () => {
24991
+ this.#server.close();
24992
+ };
24993
+ abort = () => this.#abort();
24994
+ accept = (socket) => {
24995
+ const chunks = [];
24996
+ let length = 0;
24997
+ let rejected = false;
24998
+ const controller = new AbortController();
24999
+ socket.setTimeout(BOT_IPC_TIMEOUT_MILLISECONDS2, () => {
25000
+ controller.abort(new Error("Bot IPC request timed out"));
25001
+ socket.destroy();
25002
+ });
25003
+ socket.on("data", (chunk) => {
25004
+ length += chunk.byteLength;
25005
+ if (length > BOT_IPC_REQUEST_LIMIT) {
25006
+ rejected = true;
25007
+ controller.abort(new Error("Bot IPC request is too large"));
25008
+ socket.end(
25009
+ JSON.stringify({
25010
+ error: { code: "invalid_request", message: "The local Bot request is too large" },
25011
+ ok: false
25012
+ })
25013
+ );
25014
+ return;
25015
+ }
25016
+ chunks.push(chunk);
25017
+ });
25018
+ socket.once("error", () => controller.abort());
25019
+ socket.once("close", () => controller.abort());
25020
+ socket.once("end", () => {
25021
+ if (rejected) {
25022
+ return;
25023
+ }
25024
+ void this.handle(Buffer.concat(chunks).toString("utf8").trim(), controller.signal).then(
25025
+ (outboundMessageId) => {
25026
+ if (!socket.destroyed) {
25027
+ socket.end(JSON.stringify({ ok: true, outboundMessageId }));
25028
+ }
25029
+ },
25030
+ (error61) => {
25031
+ if (socket.destroyed) {
25032
+ return;
25033
+ }
25034
+ const code = error61 instanceof LocalBotAuthorizationError ? error61.code : "bot_service_unavailable";
25035
+ const message = error61 instanceof LocalBotAuthorizationError ? error61.message : "The local Bot action could not be completed";
25036
+ socket.end(JSON.stringify({ error: { code, message }, ok: false }));
25037
+ }
25038
+ );
25039
+ });
25040
+ };
25041
+ handle = async (encoded, signal) => {
25042
+ const request = decodeRequest(encoded);
25043
+ const context = this.#registry.read(request.contextHandle);
25044
+ const timeout = AbortSignal.timeout(BOT_RELAY_TIMEOUT_MILLISECONDS);
25045
+ const requestSignal = AbortSignal.any([signal, timeout]);
25046
+ let response;
25047
+ try {
25048
+ response = await fetch(relayEndpoint(this.#relayUrl, context, request.target), {
25049
+ body: JSON.stringify({ idempotencyKey: request.idempotencyKey, text: request.text }),
25050
+ headers: {
25051
+ authorization: `Bearer ${daemonToken(this.#relayUrl)}`,
25052
+ "content-type": "application/json",
25053
+ "x-mobius-bot-execution-capability": context.command.executionCapabilitySecret
25054
+ },
25055
+ method: "POST",
25056
+ signal: requestSignal
25057
+ });
25058
+ } catch (cause) {
25059
+ signal.throwIfAborted();
25060
+ throw new LocalBotAuthorizationError(
25061
+ timeout.aborted ? "bot_service_timeout" : "bot_service_unavailable",
25062
+ timeout.aborted ? "The Mobius Bot action timed out" : "The Mobius Relay is unavailable",
25063
+ { cause }
25064
+ );
25065
+ }
25066
+ return await decodeRelayResponse(response);
25067
+ };
23753
25068
  };
23754
25069
 
23755
25070
  // src/pairing/pair-local-machine.ts
23756
- import { randomUUID } from "node:crypto";
23757
- import { mkdir as mkdir3, open as open4, realpath as realpath6, rename as rename3, stat as stat5, writeFile as writeFile2 } from "node:fs/promises";
25071
+ import { randomUUID as randomUUID3 } from "node:crypto";
25072
+ import { mkdir as mkdir4, open as open4, realpath as realpath6, rename as rename3, stat as stat6, writeFile as writeFile2 } from "node:fs/promises";
23758
25073
  import { hostname as hostname3 } from "node:os";
23759
25074
  import { basename, join as join14, resolve as resolve3 } from "node:path";
23760
- import { fetch as fetch2 } from "undici";
25075
+ import { fetch as fetch3 } from "undici";
23761
25076
 
23762
25077
  // src/agent-catalog/agent-discovery.ts
23763
25078
  var AgentDiscovery = class {
@@ -23865,8 +25180,8 @@ var LocalAgentInventory = class {
23865
25180
  };
23866
25181
 
23867
25182
  // src/agent-installation/managed-npm-package.ts
23868
- import { mkdir, mkdtemp, open as open2, realpath as realpath2, rename, rm, stat as stat2 } from "node:fs/promises";
23869
- import { delimiter, dirname as dirname3, isAbsolute, join as join4, relative, sep } from "node:path";
25183
+ import { mkdir as mkdir2, mkdtemp, open as open2, realpath as realpath2, rename, rm, stat as stat3 } from "node:fs/promises";
25184
+ import { delimiter, dirname as dirname4, isAbsolute as isAbsolute2, join as join4, relative, sep } from "node:path";
23870
25185
  var INSTALL_TIMEOUT_MILLISECONDS = 5 * 60 * 1e3;
23871
25186
  var PACKAGE_METADATA_LIMIT_BYTES = 64 * 1024;
23872
25187
  var PACKAGE_LOCK_LIMIT_BYTES = 8 * 1024 * 1024;
@@ -23913,7 +25228,7 @@ var ManagedNpmPackageError = class extends Error {
23913
25228
  this.name = "ManagedNpmPackageError";
23914
25229
  }
23915
25230
  };
23916
- function isRecord5(value) {
25231
+ function isRecord8(value) {
23917
25232
  return typeof value === "object" && value !== null && !Array.isArray(value);
23918
25233
  }
23919
25234
  function packagePath(root, packageName) {
@@ -23921,7 +25236,7 @@ function packagePath(root, packageName) {
23921
25236
  }
23922
25237
  function isContainedPath(root, candidate) {
23923
25238
  const difference = relative(root, candidate);
23924
- return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep}`) && !isAbsolute(difference);
25239
+ return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep}`) && !isAbsolute2(difference);
23925
25240
  }
23926
25241
  async function readJsonRecord(path2, maximumBytes) {
23927
25242
  try {
@@ -23935,7 +25250,7 @@ async function readJsonRecord(path2, maximumBytes) {
23935
25250
  );
23936
25251
  }
23937
25252
  const value = JSON.parse(await handle.readFile({ encoding: "utf8" }));
23938
- if (!isRecord5(value)) {
25253
+ if (!isRecord8(value)) {
23939
25254
  throw new ManagedNpmPackageError(
23940
25255
  "managed_package_verification_failed",
23941
25256
  "The managed npm package metadata is invalid"
@@ -23961,7 +25276,7 @@ function readBinPath(packageMetadata, executableName) {
23961
25276
  if (typeof bin === "string") {
23962
25277
  return bin;
23963
25278
  }
23964
- if (isRecord5(bin) && typeof bin[executableName] === "string") {
25279
+ if (isRecord8(bin) && typeof bin[executableName] === "string") {
23965
25280
  return bin[executableName];
23966
25281
  }
23967
25282
  throw new ManagedNpmPackageError(
@@ -23977,7 +25292,7 @@ function verifyPackageLockEntry(lock, definition, verifyDependencyClosure) {
23977
25292
  );
23978
25293
  }
23979
25294
  const packages = lock["packages"];
23980
- if (!isRecord5(packages)) {
25295
+ if (!isRecord8(packages)) {
23981
25296
  throw new ManagedNpmPackageError(
23982
25297
  "managed_package_verification_failed",
23983
25298
  "The managed npm package lockfile is invalid"
@@ -23991,7 +25306,7 @@ function verifyPackageLockEntry(lock, definition, verifyDependencyClosure) {
23991
25306
  if (verifyDependencyClosure && normalizedKey.length > 0) {
23992
25307
  let resolved;
23993
25308
  try {
23994
- if (!normalizedKey.split("/").includes("node_modules") || !isRecord5(candidate) || typeof candidate["version"] !== "string" || candidate["version"].length === 0 || typeof candidate["integrity"] !== "string" || !/^sha512-[A-Za-z0-9+/]{86}==$/.test(candidate["integrity"]) || typeof candidate["resolved"] !== "string") {
25309
+ if (!normalizedKey.split("/").includes("node_modules") || !isRecord8(candidate) || typeof candidate["version"] !== "string" || candidate["version"].length === 0 || typeof candidate["integrity"] !== "string" || !/^sha512-[A-Za-z0-9+/]{86}==$/.test(candidate["integrity"]) || typeof candidate["resolved"] !== "string") {
23995
25310
  throw new Error("Invalid locked dependency");
23996
25311
  }
23997
25312
  resolved = new URL(candidate["resolved"]);
@@ -24014,7 +25329,7 @@ function verifyPackageLockEntry(lock, definition, verifyDependencyClosure) {
24014
25329
  matches += 1;
24015
25330
  }
24016
25331
  }
24017
- if (matches !== 1 || !isRecord5(entry) || entry["integrity"] !== definition.integrity || entry["resolved"] !== definition.tarballUrl || entry["version"] !== definition.version) {
25332
+ if (matches !== 1 || !isRecord8(entry) || entry["integrity"] !== definition.integrity || entry["resolved"] !== definition.tarballUrl || entry["version"] !== definition.version) {
24018
25333
  throw new ManagedNpmPackageError(
24019
25334
  "managed_package_verification_failed",
24020
25335
  "The managed npm package lockfile does not match the pinned artifact"
@@ -24087,7 +25402,7 @@ var ManagedNpmPackageInstaller = class {
24087
25402
  install = async (root, definition, environment, signal) => {
24088
25403
  signal.throwIfAborted();
24089
25404
  try {
24090
- const metadata = await stat2(root);
25405
+ const metadata = await stat3(root);
24091
25406
  if (metadata.isDirectory()) {
24092
25407
  return await validateManagedNpmPackage(root, definition);
24093
25408
  }
@@ -24096,8 +25411,8 @@ var ManagedNpmPackageInstaller = class {
24096
25411
  throw error61;
24097
25412
  }
24098
25413
  }
24099
- const parent = dirname3(root);
24100
- await mkdir(parent, { mode: 448, recursive: true });
25414
+ const parent = dirname4(root);
25415
+ await mkdir2(parent, { mode: 448, recursive: true });
24101
25416
  const staging = await mkdtemp(join4(parent, `.${definition.version}.staging-`));
24102
25417
  try {
24103
25418
  const npm = await findExecutableOnPath(process.platform === "win32" ? "npm.cmd" : "npm", environment);
@@ -24131,7 +25446,7 @@ var ManagedNpmPackageInstaller = class {
24131
25446
  NPM_CONFIG_IGNORE_SCRIPTS: "true",
24132
25447
  NPM_CONFIG_PACKAGE_LOCK: "true",
24133
25448
  NPM_CONFIG_REGISTRY: "https://registry.npmjs.org/",
24134
- PATH: `${dirname3(process.execPath)}${delimiter}/usr/bin${delimiter}/bin`
25449
+ PATH: `${dirname4(process.execPath)}${delimiter}/usr/bin${delimiter}/bin`
24135
25450
  };
24136
25451
  if (definition.includeOptionalDependencies) {
24137
25452
  installEnvironment["NPM_CONFIG_INCLUDE"] = "optional";
@@ -24354,8 +25669,8 @@ var CursorCliAgentSpecification = class extends DirectAcpAgentDefinition {
24354
25669
  };
24355
25670
 
24356
25671
  // src/agent-catalog/agents/deepseek-harness-agent.ts
24357
- import { realpath as realpath3, stat as stat3 } from "node:fs/promises";
24358
- import { isAbsolute as isAbsolute2, join as join6, normalize } from "node:path";
25672
+ import { realpath as realpath3, stat as stat4 } from "node:fs/promises";
25673
+ import { isAbsolute as isAbsolute3, join as join6, normalize } from "node:path";
24359
25674
 
24360
25675
  // src/agent-installation/deepseek-managed-package.ts
24361
25676
  var DeepSeekHarnessManagedPackage = class extends SriManagedNpmPackageDefinition {
@@ -24373,12 +25688,12 @@ var DEEPSEEK_HARNESS_PACKAGE = new DeepSeekHarnessManagedPackage(
24373
25688
 
24374
25689
  // src/agent-catalog/agents/deepseek-harness-agent.ts
24375
25690
  async function validateAgentHome(path2) {
24376
- if (!isAbsolute2(path2) || normalize(path2) !== path2) {
25691
+ if (!isAbsolute3(path2) || normalize(path2) !== path2) {
24377
25692
  throw new AgentProbeError("agent_environment_invalid", "The configured Agent home is invalid");
24378
25693
  }
24379
25694
  try {
24380
25695
  const resolved = await realpath3(path2);
24381
- const metadata = await stat3(resolved);
25696
+ const metadata = await stat4(resolved);
24382
25697
  if (!metadata.isDirectory() || typeof process.getuid === "function" && metadata.uid !== process.getuid()) {
24383
25698
  throw new Error("Agent home is not a user-owned directory");
24384
25699
  }
@@ -24461,7 +25776,7 @@ var DeepSeekHarnessAgentSpecification = class extends DirectAcpAgentDefinition {
24461
25776
 
24462
25777
  // src/agent-catalog/agents/grok-build-agent.ts
24463
25778
  import { realpath as realpath4 } from "node:fs/promises";
24464
- import { isAbsolute as isAbsolute3, join as join7, relative as relative2, sep as sep2 } from "node:path";
25779
+ import { isAbsolute as isAbsolute4, join as join7, relative as relative2, sep as sep2 } from "node:path";
24465
25780
 
24466
25781
  // src/agent-installation/grok-managed-package.ts
24467
25782
  var GROK_BUILD_MANAGED_VERSION = "1.0.21";
@@ -24524,7 +25839,7 @@ function grokBuildManagedPackage(platform, architecture) {
24524
25839
  // src/agent-catalog/agents/grok-build-agent.ts
24525
25840
  function isContainedPath2(root, candidate) {
24526
25841
  const difference = relative2(root, candidate);
24527
- return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep2}`) && !isAbsolute3(difference);
25842
+ return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep2}`) && !isAbsolute4(difference);
24528
25843
  }
24529
25844
  var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
24530
25845
  adapterVersion = GROK_BUILD_MANAGED_VERSION;
@@ -24586,13 +25901,13 @@ var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
24586
25901
  import { join as join9 } from "node:path";
24587
25902
 
24588
25903
  // src/agent-installation/managed-agent-archive.ts
24589
- import { createHash } from "node:crypto";
25904
+ import { createHash as createHash2 } from "node:crypto";
24590
25905
  import { createReadStream } from "node:fs";
24591
- import { chmod, copyFile, mkdir as mkdir2, mkdtemp as mkdtemp2, open as open3, realpath as realpath5, rename as rename2, rm as rm2, stat as stat4, writeFile } from "node:fs/promises";
24592
- import { dirname as dirname4, isAbsolute as isAbsolute4, join as join8, relative as relative3, sep as sep3 } from "node:path";
25906
+ import { chmod as chmod2, copyFile, mkdir as mkdir3, mkdtemp as mkdtemp2, open as open3, realpath as realpath5, rename as rename2, rm as rm2, stat as stat5, writeFile } from "node:fs/promises";
25907
+ import { dirname as dirname5, isAbsolute as isAbsolute5, join as join8, relative as relative3, sep as sep3 } from "node:path";
24593
25908
 
24594
25909
  // src/agent-installation/verified-download.ts
24595
- import { fetch } from "undici";
25910
+ import { fetch as fetch2 } from "undici";
24596
25911
 
24597
25912
  // src/network/environment-proxy.ts
24598
25913
  import { EnvHttpProxyAgent } from "undici";
@@ -24644,16 +25959,16 @@ var ManagedAgentArchiveError = class extends Error {
24644
25959
  this.name = "ManagedAgentArchiveError";
24645
25960
  }
24646
25961
  };
24647
- function isRecord6(value) {
25962
+ function isRecord9(value) {
24648
25963
  return typeof value === "object" && value !== null && !Array.isArray(value);
24649
25964
  }
24650
25965
  function isContainedPath3(root, candidate) {
24651
25966
  const difference = relative3(root, candidate);
24652
- return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep3}`) && !isAbsolute4(difference);
25967
+ return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep3}`) && !isAbsolute5(difference);
24653
25968
  }
24654
25969
  async function hashFile(path2, signal) {
24655
25970
  signal.throwIfAborted();
24656
- const digest = createHash("sha256");
25971
+ const digest2 = createHash2("sha256");
24657
25972
  const stream = createReadStream(path2, { signal });
24658
25973
  try {
24659
25974
  for await (const chunk of stream) {
@@ -24664,9 +25979,9 @@ async function hashFile(path2, signal) {
24664
25979
  "The managed Agent archive produced invalid bytes"
24665
25980
  );
24666
25981
  }
24667
- digest.update(chunk);
25982
+ digest2.update(chunk);
24668
25983
  }
24669
- return digest.digest("hex");
25984
+ return digest2.digest("hex");
24670
25985
  } catch (error61) {
24671
25986
  if (signal.aborted) {
24672
25987
  signal.throwIfAborted();
@@ -24701,7 +26016,7 @@ async function readManifest(path2) {
24701
26016
  );
24702
26017
  }
24703
26018
  const parsed = JSON.parse(await handle.readFile({ encoding: "utf8" }));
24704
- if (!isRecord6(parsed)) {
26019
+ if (!isRecord9(parsed)) {
24705
26020
  throw new ManagedAgentArchiveError(
24706
26021
  "managed_archive_verification_failed",
24707
26022
  "The managed Agent archive manifest is invalid"
@@ -24724,7 +26039,7 @@ async function readManifest(path2) {
24724
26039
  async function validateManagedAgentArchive(root, definition, signal) {
24725
26040
  try {
24726
26041
  const rootPath = await realpath5(root);
24727
- const rootMetadata = await stat4(rootPath);
26042
+ const rootMetadata = await stat5(rootPath);
24728
26043
  if (!rootMetadata.isDirectory() || typeof process.getuid === "function" && rootMetadata.uid !== process.getuid()) {
24729
26044
  throw new Error("Managed Agent root is not user-owned");
24730
26045
  }
@@ -24939,7 +26254,7 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
24939
26254
  };
24940
26255
 
24941
26256
  // src/agent-catalog/agents/workbuddy-agent.ts
24942
- import { isAbsolute as isAbsolute5, join as join11 } from "node:path";
26257
+ import { isAbsolute as isAbsolute6, join as join11 } from "node:path";
24943
26258
 
24944
26259
  // src/agent-installation/workbuddy-managed-package.ts
24945
26260
  var WORKBUDDY_MANAGED_VERSION = "2.146.0";
@@ -25005,7 +26320,7 @@ var WorkBuddyAgentSpecification = class extends DirectAcpAgentDefinition {
25005
26320
  }
25006
26321
  const requestedPaths = [join11("/Applications", ...WORKBUDDY_MACOS_EXECUTABLE_PATH)];
25007
26322
  const homeDirectory = context.environment["HOME"];
25008
- if (homeDirectory !== void 0 && isAbsolute5(homeDirectory)) {
26323
+ if (homeDirectory !== void 0 && isAbsolute6(homeDirectory)) {
25009
26324
  requestedPaths.unshift(join11(homeDirectory, "Applications", ...WORKBUDDY_MACOS_EXECUTABLE_PATH));
25010
26325
  }
25011
26326
  const executables = [];
@@ -25051,7 +26366,7 @@ import {
25051
26366
  } from "@agentclientprotocol/sdk";
25052
26367
 
25053
26368
  // src/agent-catalog/executable-discovery.ts
25054
- import { isAbsolute as isAbsolute6, join as join13 } from "node:path";
26369
+ import { isAbsolute as isAbsolute7, join as join13 } from "node:path";
25055
26370
 
25056
26371
  // src/agent-installation/managed-adapter-installer.ts
25057
26372
  import { join as join12 } from "node:path";
@@ -25156,7 +26471,7 @@ async function resolveManagedAdapterExecutable(specification, context) {
25156
26471
  async function resolveSpecificationExecutables(executableName, overrideVariable, resolveInstalled, resolveManaged, context) {
25157
26472
  const override = context.environment[overrideVariable];
25158
26473
  if (override !== void 0) {
25159
- if (override.length === 0 || !isAbsolute6(override)) {
26474
+ if (override.length === 0 || !isAbsolute7(override)) {
25160
26475
  return [];
25161
26476
  }
25162
26477
  const executable = await resolveExecutablePath(override, context.platform);
@@ -25576,8 +26891,8 @@ async function discoverLocalAgentInventory(options) {
25576
26891
  // src/pairing/pair-local-machine.ts
25577
26892
  var PAIRING_TIMEOUT_MILLISECONDS = 2e4;
25578
26893
  var PAIRING_CODE_PATTERN = /^[A-HJ-NP-Z2-9]{4}(?:-[A-HJ-NP-Z2-9]{4}){4}$/;
25579
- var IDENTIFIER_PATTERN4 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
25580
- var TOKEN_PATTERN = /^[a-zA-Z0-9_-]{32,256}$/;
26894
+ var IDENTIFIER_PATTERN6 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
26895
+ var TOKEN_PATTERN2 = /^[a-zA-Z0-9_-]{32,256}$/;
25581
26896
  var MAX_CONNECTION_FILE_LENGTH = 16 * 1024;
25582
26897
  var CLAIM_RESPONSE_KEYS = ["channelId", "daemonToken", "runtimeId"];
25583
26898
  var SAVED_CONNECTION_KEYS = ["defaultWorkspace", "channelId", "daemonToken", "relayOrigin"];
@@ -25589,36 +26904,36 @@ var PairingClientError = class extends Error {
25589
26904
  this.name = "PairingClientError";
25590
26905
  }
25591
26906
  };
25592
- function isRecord7(value) {
26907
+ function isRecord10(value) {
25593
26908
  return typeof value === "object" && value !== null && !Array.isArray(value);
25594
26909
  }
25595
26910
  function hasExactKeys(value, expectedKeys) {
25596
26911
  const keys = Object.keys(value);
25597
26912
  return keys.length === expectedKeys.length && expectedKeys.every((key) => Object.hasOwn(value, key));
25598
26913
  }
25599
- function readSingleOption(arguments_, option) {
26914
+ function readSingleOption(arguments_, option2) {
25600
26915
  const values = [];
25601
26916
  for (let index = 0; index < arguments_.length; index += 1) {
25602
- if (arguments_[index] !== option) {
26917
+ if (arguments_[index] !== option2) {
25603
26918
  continue;
25604
26919
  }
25605
26920
  const value = arguments_[index + 1];
25606
26921
  if (value === void 0 || value.startsWith("--")) {
25607
- throw new PairingClientError("invalid_arguments", `${option} requires a value`);
26922
+ throw new PairingClientError("invalid_arguments", `${option2} requires a value`);
25608
26923
  }
25609
26924
  values.push(value);
25610
26925
  index += 1;
25611
26926
  }
25612
26927
  if (values.length !== 1) {
25613
- throw new PairingClientError("invalid_arguments", `${option} must be provided exactly once`);
26928
+ throw new PairingClientError("invalid_arguments", `${option2} must be provided exactly once`);
25614
26929
  }
25615
26930
  return values[0] ?? "";
25616
26931
  }
25617
26932
  function assertKnownArguments(arguments_) {
25618
26933
  for (let index = 0; index < arguments_.length; index += 2) {
25619
- const option = arguments_[index];
25620
- if (option !== "--url" && option !== "--code" && option !== "--workspace") {
25621
- throw new PairingClientError("invalid_arguments", `Unknown pairing option: ${option ?? "missing option"}`);
26934
+ const option2 = arguments_[index];
26935
+ if (option2 !== "--url" && option2 !== "--code" && option2 !== "--workspace") {
26936
+ throw new PairingClientError("invalid_arguments", `Unknown pairing option: ${option2 ?? "missing option"}`);
25622
26937
  }
25623
26938
  }
25624
26939
  }
@@ -25666,7 +26981,7 @@ function parseChannelArgument(arguments_) {
25666
26981
  throw new PairingClientError("invalid_arguments", "Usage: mobius start --channel <channel-id>");
25667
26982
  }
25668
26983
  const channelId = arguments_[1] ?? "";
25669
- if (!IDENTIFIER_PATTERN4.test(channelId)) {
26984
+ if (!IDENTIFIER_PATTERN6.test(channelId)) {
25670
26985
  throw new PairingClientError("invalid_channel_id", "The saved channel ID is invalid");
25671
26986
  }
25672
26987
  return channelId;
@@ -25674,9 +26989,9 @@ function parseChannelArgument(arguments_) {
25674
26989
  async function resolveDefaultWorkspace(path2) {
25675
26990
  const requestedWorkspace = resolve3(path2);
25676
26991
  try {
25677
- await mkdir3(requestedWorkspace, { recursive: true, mode: 448 });
26992
+ await mkdir4(requestedWorkspace, { recursive: true, mode: 448 });
25678
26993
  const defaultWorkspace = await realpath6(requestedWorkspace);
25679
- const metadata = await stat5(defaultWorkspace);
26994
+ const metadata = await stat6(defaultWorkspace);
25680
26995
  if (!metadata.isDirectory()) {
25681
26996
  throw new PairingClientError("invalid_workspace", "The default workspace is not a directory");
25682
26997
  }
@@ -25705,9 +27020,9 @@ async function readJsonResponse(response) {
25705
27020
  }
25706
27021
  }
25707
27022
  function readRelayError(value) {
25708
- if (isRecord7(value)) {
27023
+ if (isRecord10(value)) {
25709
27024
  const error61 = value["error"];
25710
- if (isRecord7(error61)) {
27025
+ if (isRecord10(error61)) {
25711
27026
  const code = error61["code"];
25712
27027
  const message = error61["message"];
25713
27028
  if (typeof code === "string" && typeof message === "string") {
@@ -25718,16 +27033,16 @@ function readRelayError(value) {
25718
27033
  return new PairingClientError("pairing_failed", "The relay could not pair this machine");
25719
27034
  }
25720
27035
  function decodeClaimResponse(value) {
25721
- if (!isRecord7(value) || !hasExactKeys(value, CLAIM_RESPONSE_KEYS)) {
27036
+ if (!isRecord10(value) || !hasExactKeys(value, CLAIM_RESPONSE_KEYS)) {
25722
27037
  throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
25723
27038
  }
25724
27039
  const channelId = value["channelId"];
25725
- const daemonToken = value["daemonToken"];
27040
+ const daemonToken2 = value["daemonToken"];
25726
27041
  const runtimeId = value["runtimeId"];
25727
- if (typeof channelId !== "string" || !IDENTIFIER_PATTERN4.test(channelId) || typeof daemonToken !== "string" || !TOKEN_PATTERN.test(daemonToken) || typeof runtimeId !== "string" || !IDENTIFIER_PATTERN4.test(runtimeId)) {
27042
+ if (typeof channelId !== "string" || !IDENTIFIER_PATTERN6.test(channelId) || typeof daemonToken2 !== "string" || !TOKEN_PATTERN2.test(daemonToken2) || typeof runtimeId !== "string" || !IDENTIFIER_PATTERN6.test(runtimeId)) {
25728
27043
  throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
25729
27044
  }
25730
- return { channelId, daemonToken, runtimeId };
27045
+ return { channelId, daemonToken: daemonToken2, runtimeId };
25731
27046
  }
25732
27047
  async function claimPairing(options, defaultWorkspace, localAgents, installableAgents, signal) {
25733
27048
  const agents = localAgents.map((agent) => ({
@@ -25740,7 +27055,7 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
25740
27055
  const endpoint = mobiusApiUrl(options.relayOrigin, "/pairings/claim");
25741
27056
  let response;
25742
27057
  try {
25743
- response = await fetch2(endpoint, {
27058
+ response = await fetch3(endpoint, {
25744
27059
  body: JSON.stringify({
25745
27060
  agents,
25746
27061
  installableAgents,
@@ -25762,18 +27077,18 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
25762
27077
  }
25763
27078
  return decodeClaimResponse(value);
25764
27079
  }
25765
- async function persistConnection(channelId, relayOrigin, daemonToken, defaultWorkspace) {
27080
+ async function persistConnection(channelId, relayOrigin, daemonToken2, defaultWorkspace) {
25766
27081
  const connectionsDirectory = join14(readStateDirectory(), "connections");
25767
- await mkdir3(connectionsDirectory, { mode: 448, recursive: true });
27082
+ await mkdir4(connectionsDirectory, { mode: 448, recursive: true });
25768
27083
  const connectionPath = join14(connectionsDirectory, `${channelId}.json`);
25769
- const temporaryPath = join14(connectionsDirectory, `.${channelId}.${randomUUID()}.tmp`);
27084
+ const temporaryPath = join14(connectionsDirectory, `.${channelId}.${randomUUID3()}.tmp`);
25770
27085
  await writeFile2(
25771
27086
  temporaryPath,
25772
27087
  `${JSON.stringify(
25773
27088
  {
25774
27089
  defaultWorkspace,
25775
27090
  channelId,
25776
- daemonToken,
27091
+ daemonToken: daemonToken2,
25777
27092
  relayOrigin: relayOrigin.toString()
25778
27093
  },
25779
27094
  null,
@@ -25786,20 +27101,20 @@ async function persistConnection(channelId, relayOrigin, daemonToken, defaultWor
25786
27101
  return connectionPath;
25787
27102
  }
25788
27103
  function decodeSavedConnection(value, expectedChannelId) {
25789
- if (!isRecord7(value) || !hasExactKeys(value, SAVED_CONNECTION_KEYS)) {
27104
+ if (!isRecord10(value) || !hasExactKeys(value, SAVED_CONNECTION_KEYS)) {
25790
27105
  throw new PairingClientError("invalid_connection", "The saved connection is invalid");
25791
27106
  }
25792
27107
  const defaultWorkspace = value["defaultWorkspace"];
25793
27108
  const channelId = value["channelId"];
25794
- const daemonToken = value["daemonToken"];
27109
+ const daemonToken2 = value["daemonToken"];
25795
27110
  const relayOrigin = value["relayOrigin"];
25796
- if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !IDENTIFIER_PATTERN4.test(channelId) || typeof daemonToken !== "string" || !TOKEN_PATTERN.test(daemonToken) || typeof relayOrigin !== "string") {
27111
+ if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !IDENTIFIER_PATTERN6.test(channelId) || typeof daemonToken2 !== "string" || !TOKEN_PATTERN2.test(daemonToken2) || typeof relayOrigin !== "string") {
25797
27112
  throw new PairingClientError("invalid_connection", "The saved connection is invalid");
25798
27113
  }
25799
27114
  return {
25800
27115
  defaultWorkspace,
25801
27116
  channelId,
25802
- daemonToken,
27117
+ daemonToken: daemonToken2,
25803
27118
  relayOrigin: parseRelayOrigin(relayOrigin)
25804
27119
  };
25805
27120
  }
@@ -25900,12 +27215,13 @@ async function resumeLocalMachine(arguments_, signal = new AbortController().sig
25900
27215
  }
25901
27216
 
25902
27217
  // src/run-daemon.ts
25903
- import { basename as basename3 } from "node:path";
27218
+ import { randomUUID as randomUUID6 } from "node:crypto";
27219
+ import { basename as basename3, join as join16 } from "node:path";
25904
27220
  import { styleText } from "node:util";
25905
- import { fetch as fetch5, WebSocket as WebSocket2 } from "undici";
27221
+ import { fetch as fetch6, WebSocket as WebSocket2 } from "undici";
25906
27222
 
25907
27223
  // src/agent-catalog/publish-agent-catalog.ts
25908
- import { fetch as fetch3 } from "undici";
27224
+ import { fetch as fetch4 } from "undici";
25909
27225
  var CATALOG_UPDATE_TIMEOUT_MILLISECONDS = 2e4;
25910
27226
  var AgentCatalogPublishError = class extends Error {
25911
27227
  code = "agent_catalog_update_failed";
@@ -25930,7 +27246,7 @@ async function publishAgentCatalog(config2, signal) {
25930
27246
  let response;
25931
27247
  const catalog = config2.catalog.read();
25932
27248
  try {
25933
- response = await fetch3(catalogEndpoint(config2.relayUrl), {
27249
+ response = await fetch4(catalogEndpoint(config2.relayUrl), {
25934
27250
  body: JSON.stringify({
25935
27251
  agents: catalog.agents.map((agent) => ({
25936
27252
  agentPath: agent.agentIdentity.requestedPath,
@@ -26425,9 +27741,9 @@ var FixedInstallationExecutor = class {
26425
27741
  };
26426
27742
 
26427
27743
  // src/authorization/workspace-directory.ts
26428
- import { readdir, realpath as realpath7, stat as stat6 } from "node:fs/promises";
27744
+ import { readdir, realpath as realpath7, stat as stat7 } from "node:fs/promises";
26429
27745
  import { homedir as homedir2 } from "node:os";
26430
- import { basename as basename2, dirname as dirname5, isAbsolute as isAbsolute7, join as join15, normalize as normalize2, relative as relative4 } from "node:path";
27746
+ import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute8, join as join15, normalize as normalize2, relative as relative4 } from "node:path";
26431
27747
  var WorkspaceDirectoryListing = class {
26432
27748
  directoryId;
26433
27749
  directoryLabel;
@@ -26479,7 +27795,7 @@ var WorkspaceDirectoryService = class {
26479
27795
  }
26480
27796
  if (id.startsWith("path-")) {
26481
27797
  const path2 = decodePath(id, "path-");
26482
- if (isAbsolute7(path2)) {
27798
+ if (isAbsolute8(path2)) {
26483
27799
  return path2;
26484
27800
  }
26485
27801
  }
@@ -26487,15 +27803,15 @@ var WorkspaceDirectoryService = class {
26487
27803
  };
26488
27804
  resolvePath = async (requested, signal) => {
26489
27805
  signal.throwIfAborted();
26490
- if (!isAbsolute7(requested) || requested.includes("\0") || normalize2(requested) !== requested) {
27806
+ if (!isAbsolute8(requested) || requested.includes("\0") || normalize2(requested) !== requested) {
26491
27807
  throw new LocalAuthorizationError("The local directory path is invalid");
26492
27808
  }
26493
27809
  try {
26494
27810
  const target = await realpath7(requested);
26495
27811
  signal.throwIfAborted();
26496
- const metadata = await stat6(target);
27812
+ const metadata = await stat7(target);
26497
27813
  signal.throwIfAborted();
26498
- if (!isAbsolute7(target) || normalize2(target) !== target || !metadata.isDirectory()) {
27814
+ if (!isAbsolute8(target) || normalize2(target) !== target || !metadata.isDirectory()) {
26499
27815
  throw new LocalAuthorizationError("The selected location is not a directory");
26500
27816
  }
26501
27817
  return target;
@@ -26511,7 +27827,7 @@ var WorkspaceDirectoryService = class {
26511
27827
  };
26512
27828
  label = (path2) => {
26513
27829
  const suffix = relative4(homedir2(), path2);
26514
- return suffix === "" ? "~" : !isAbsolute7(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
27830
+ return suffix === "" ? "~" : !isAbsolute8(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
26515
27831
  };
26516
27832
  identify = async (bindingId, requestedPath, signal) => {
26517
27833
  this.authorizeMachine(bindingId);
@@ -26551,7 +27867,7 @@ var WorkspaceDirectoryService = class {
26551
27867
  }
26552
27868
  }
26553
27869
  entries.sort((a, b) => a.name.localeCompare(b.name));
26554
- const parent = dirname5(target);
27870
+ const parent = dirname6(target);
26555
27871
  return new WorkspaceDirectoryListing(
26556
27872
  id,
26557
27873
  this.label(target),
@@ -26575,8 +27891,44 @@ var WorkspaceDirectoryService = class {
26575
27891
  };
26576
27892
  };
26577
27893
 
27894
+ // src/bots/bot-context-applicator.ts
27895
+ var AppliedBotContext = class {
27896
+ resources;
27897
+ constructor(resources) {
27898
+ this.resources = Object.freeze([...resources]);
27899
+ }
27900
+ };
27901
+ var EmbeddedBotContextApplicator = class {
27902
+ apply = async (command, grant, resources, signal) => {
27903
+ signal.throwIfAborted();
27904
+ if (grant.botId !== command.botId || grant.behaviorRevisionId !== command.behaviorRevisionId || grant.behaviorDigest !== command.behaviorDigest) {
27905
+ throw new LocalBotAuthorizationError(
27906
+ "binding_not_approved",
27907
+ "The Bot behavior does not match its local authorization"
27908
+ );
27909
+ }
27910
+ if (command.behaviorInstructions.length === 0) {
27911
+ return new AppliedBotContext(resources);
27912
+ }
27913
+ if (!grant.agent.capabilities.embeddedContextPrompt) {
27914
+ throw new LocalBotAuthorizationError(
27915
+ "binding_incompatible",
27916
+ "The local Agent cannot enforce the Bot behavior context"
27917
+ );
27918
+ }
27919
+ const trustedContext = {
27920
+ mimeType: "text/markdown",
27921
+ name: "Mobius Bot behavior",
27922
+ text: command.behaviorInstructions,
27923
+ type: "embedded",
27924
+ uri: `mobius://bots/${encodeURIComponent(command.botId)}/behavior-revisions/${encodeURIComponent(command.behaviorRevisionId)}?sha256=${command.behaviorDigest}`
27925
+ };
27926
+ return new AppliedBotContext([trustedContext, ...resources]);
27927
+ };
27928
+ };
27929
+
26578
27930
  // src/native-sessions/service.ts
26579
- import { randomUUID as randomUUID2 } from "node:crypto";
27931
+ import { randomUUID as randomUUID4 } from "node:crypto";
26580
27932
 
26581
27933
  // src/native-sessions/codex-history.ts
26582
27934
  import { spawn as spawn4 } from "node:child_process";
@@ -26892,7 +28244,7 @@ var NativeSessionService = class {
26892
28244
  if (authorized === null) {
26893
28245
  continue;
26894
28246
  }
26895
- const entryId = randomUUID2();
28247
+ const entryId = randomUUID4();
26896
28248
  if (this.#entries.size >= 5e3) {
26897
28249
  this.#entries.clear();
26898
28250
  }
@@ -26920,7 +28272,7 @@ var NativeSessionService = class {
26920
28272
  "invalid_native_session_response"
26921
28273
  );
26922
28274
  }
26923
- nextCursor = randomUUID2();
28275
+ nextCursor = randomUUID4();
26924
28276
  if (this.#cursors.size >= 500) {
26925
28277
  this.#cursors.clear();
26926
28278
  }
@@ -27138,13 +28490,13 @@ var NativeSessionService = class {
27138
28490
  };
27139
28491
 
27140
28492
  // src/prompt-artifact-resolver.ts
27141
- import { createHash as createHash2 } from "node:crypto";
27142
- import { fetch as fetch4 } from "undici";
28493
+ import { createHash as createHash3 } from "node:crypto";
28494
+ import { fetch as fetch5 } from "undici";
27143
28495
  var ARTIFACT_SCHEME = "mobius-artifact:";
27144
28496
  var ARTIFACT_DOWNLOAD_TIMEOUT_MILLISECONDS = 2e4;
27145
28497
  var MAX_AGENT_IMAGE_BASE64_LENGTH = 4e6;
27146
28498
  var MAX_AGENT_RESOURCE_BYTE_LENGTH = 1e6;
27147
- var IDENTIFIER_PATTERN5 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
28499
+ var IDENTIFIER_PATTERN7 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
27148
28500
  var PromptArtifactError = class extends Error {
27149
28501
  code;
27150
28502
  constructor(code, message, options = {}) {
@@ -27187,7 +28539,7 @@ function parseReference(resource) {
27187
28539
  const encodedByteLength2 = url2.searchParams.get("byteLength") ?? "";
27188
28540
  const sha256 = url2.searchParams.get("sha256") ?? "";
27189
28541
  const byteLength = Number(encodedByteLength2);
27190
- 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)) {
28542
+ 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)) {
27191
28543
  throw new PromptArtifactError("artifact_reference_invalid", "The prompt artifact reference is invalid");
27192
28544
  }
27193
28545
  return new PromptArtifactReference(artifactId, byteLength, sha256, resource);
@@ -27248,7 +28600,7 @@ async function download(config2, command, reference, signal) {
27248
28600
  const requestSignal = AbortSignal.any([signal, timeoutSignal]);
27249
28601
  let response;
27250
28602
  try {
27251
- response = await fetch4(downloadUrl(config2, command, reference), {
28603
+ response = await fetch5(downloadUrl(config2, command, reference), {
27252
28604
  dispatcher: environmentProxyDispatcher,
27253
28605
  headers: { accept: reference.resource.mimeType },
27254
28606
  signal: requestSignal
@@ -27268,7 +28620,7 @@ async function download(config2, command, reference, signal) {
27268
28620
  );
27269
28621
  }
27270
28622
  const bytes = await responseBytes(response, reference.byteLength, requestSignal);
27271
- if (createHash2("sha256").update(bytes).digest("hex") !== reference.sha256) {
28623
+ if (createHash3("sha256").update(bytes).digest("hex") !== reference.sha256) {
27272
28624
  throw new PromptArtifactError(
27273
28625
  "artifact_integrity_failed",
27274
28626
  "The prompt artifact failed integrity validation"
@@ -27413,7 +28765,7 @@ function connectRelay(url2, signal) {
27413
28765
  }
27414
28766
 
27415
28767
  // src/relay-connection/liveness.ts
27416
- import { randomUUID as randomUUID3 } from "node:crypto";
28768
+ import { randomUUID as randomUUID5 } from "node:crypto";
27417
28769
  var HEARTBEAT_ACK_TIMEOUT_MILLISECONDS = 1e4;
27418
28770
  var HEARTBEAT_INTERVAL_MILLISECONDS = 2e4;
27419
28771
  var RelayLivenessState = class {
@@ -27501,7 +28853,7 @@ var RelayConnectionLiveness = class {
27501
28853
  }
27502
28854
  throw new Error("Heartbeat was scheduled in an invalid state");
27503
28855
  }
27504
- const heartbeatId = randomUUID3();
28856
+ const heartbeatId = randomUUID5();
27505
28857
  this.#state = new AwaitingHeartbeatAckState(
27506
28858
  heartbeatId,
27507
28859
  this.#timer.schedule(this.#handleTimeout, HEARTBEAT_ACK_TIMEOUT_MILLISECONDS)
@@ -27517,8 +28869,8 @@ var RelayConnectionLiveness = class {
27517
28869
 
27518
28870
  // src/relay-connection/session-event-outbox.ts
27519
28871
  import { mkdirSync as mkdirSync3 } from "node:fs";
27520
- import { dirname as dirname6 } from "node:path";
27521
- import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
28872
+ import { dirname as dirname7 } from "node:path";
28873
+ import { DatabaseSync as DatabaseSync4 } from "node:sqlite";
27522
28874
  function readPendingEnvelope(row) {
27523
28875
  if (typeof row !== "object" || row === null || Array.isArray(row)) {
27524
28876
  throw new Error("SQLite returned an invalid session event outbox row");
@@ -27532,8 +28884,8 @@ function readPendingEnvelope(row) {
27532
28884
  var SessionEventOutbox = class {
27533
28885
  #database;
27534
28886
  constructor(path2) {
27535
- mkdirSync3(dirname6(path2), { recursive: true });
27536
- this.#database = new DatabaseSync3(path2);
28887
+ mkdirSync3(dirname7(path2), { recursive: true });
28888
+ this.#database = new DatabaseSync4(path2);
27537
28889
  this.#database.exec(`
27538
28890
  CREATE TABLE IF NOT EXISTS relay_session_event_outbox (
27539
28891
  ordinal INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -27724,6 +29076,12 @@ var RELAY_RECONNECT_DELAY_MILLISECONDS = 500;
27724
29076
  var RELAY_CONNECTION_REFRESH_MILLISECONDS = 20 * 60 * 1e3;
27725
29077
  var ACTIVE_TURN_RECONCILIATION_TIMEOUT_MILLISECONDS = 2e4;
27726
29078
  var ACTIVE_TURN_RECONCILIATION_CLOSE_CODE = 4009;
29079
+ function botIpcSocketPath() {
29080
+ if (process.platform === "win32") {
29081
+ return `\\\\.\\pipe\\mobius-bot-${randomUUID6()}`;
29082
+ }
29083
+ return join16("/tmp", `mobius-bot-${randomUUID6()}.sock`);
29084
+ }
27727
29085
  var RelayConnectionRefreshState = class {
27728
29086
  };
27729
29087
  var ScheduledRelayConnectionRefreshState = class extends RelayConnectionRefreshState {
@@ -27981,7 +29339,7 @@ async function reconcileActiveTurn(config2, turn, signal) {
27981
29339
  const requestSignal = AbortSignal.any([signal, timeoutSignal]);
27982
29340
  let response;
27983
29341
  try {
27984
- response = await fetch5(activeTurnReconciliationEndpoint(config2, turn), {
29342
+ response = await fetch6(activeTurnReconciliationEndpoint(config2, turn), {
27985
29343
  body: JSON.stringify({ outcome: { kind: "running" } }),
27986
29344
  dispatcher: environmentProxyDispatcher,
27987
29345
  headers: { "content-type": "application/json" },
@@ -28084,13 +29442,13 @@ function reportFailure(publisher, command, code, message, attemptId) {
28084
29442
  );
28085
29443
  }
28086
29444
  function operationErrorCode(error61) {
28087
- if (error61 instanceof AcpExecutionError || error61 instanceof LocalAuthorizationError || error61 instanceof LocalAgentCatalogError || error61 instanceof PromptArtifactError) {
29445
+ if (error61 instanceof AcpExecutionError || error61 instanceof LocalAuthorizationError || error61 instanceof LocalAgentCatalogError || error61 instanceof LocalBotAuthorizationError || error61 instanceof PromptArtifactError) {
28088
29446
  return error61.code;
28089
29447
  }
28090
29448
  return "session_operation_failed";
28091
29449
  }
28092
29450
  function operationErrorMessage(error61) {
28093
- if (error61 instanceof AcpExecutionError || error61 instanceof LocalAuthorizationError || error61 instanceof LocalAgentCatalogError || error61 instanceof PromptArtifactError) {
29451
+ if (error61 instanceof AcpExecutionError || error61 instanceof LocalAuthorizationError || error61 instanceof LocalAgentCatalogError || error61 instanceof LocalBotAuthorizationError || error61 instanceof PromptArtifactError) {
28094
29452
  return error61.message;
28095
29453
  }
28096
29454
  return "The local agent operation could not be completed";
@@ -28355,6 +29713,175 @@ async function executePrompt(outbox, publisher, command, config2, directories, a
28355
29713
  console.error("Mobius daemon command failed", error61);
28356
29714
  }
28357
29715
  }
29716
+ function botExecutionAgent(agent, contextHandle, socketPath) {
29717
+ return new LocalAgentDefinition(
29718
+ agent.id,
29719
+ agent.label,
29720
+ agent.command,
29721
+ agent.arguments,
29722
+ {
29723
+ ...agent.environment,
29724
+ MOBIUS_BOT_CONTEXT: contextHandle,
29725
+ MOBIUS_BOT_SOCKET: socketPath,
29726
+ MOBIUS_RELAY_TOKEN: "",
29727
+ MOBIUS_RELAY_URL: ""
29728
+ },
29729
+ agent.adapterVersion,
29730
+ agent.agentVersion,
29731
+ agent.adapterIdentity,
29732
+ agent.agentIdentity,
29733
+ agent.promptTimeoutMilliseconds,
29734
+ agent.capabilities
29735
+ );
29736
+ }
29737
+ async function executeBotPrompt(outbox, publisher, command, config2, directories, audit, sessions, grants, contexts, applicator, ipc, attemptId, signal) {
29738
+ try {
29739
+ if (command.additionalDirectoryIds.length > 0) {
29740
+ throw new LocalBotAuthorizationError(
29741
+ "binding_not_approved",
29742
+ "The Bot execution requested unapproved additional directories"
29743
+ );
29744
+ }
29745
+ const deadline = Date.parse(command.executionDeadlineAt);
29746
+ const remaining = deadline - Date.now();
29747
+ if (!Number.isSafeInteger(deadline) || remaining <= 0) {
29748
+ throw new LocalBotAuthorizationError("turn_expired", "The Bot execution deadline has expired");
29749
+ }
29750
+ const grant = await grants.resolveExecution(
29751
+ command,
29752
+ config2.catalog,
29753
+ directories,
29754
+ config2.bindingId,
29755
+ Date.now(),
29756
+ signal
29757
+ );
29758
+ const attachments = await resolvePromptArtifacts(config2, command, signal);
29759
+ const applied = await applicator.apply(command, grant, attachments.resources, signal);
29760
+ const lease = contexts.activate(command);
29761
+ try {
29762
+ const deadlineSignal = AbortSignal.timeout(remaining);
29763
+ const executionSignal = AbortSignal.any([signal, deadlineSignal]);
29764
+ const agent = botExecutionAgent(grant.agent, lease.context.contextHandle, ipc.socketPath);
29765
+ audit.record({
29766
+ commandId: command.commandId,
29767
+ details: {
29768
+ behaviorRevisionId: command.behaviorRevisionId,
29769
+ bindingId: command.bindingId,
29770
+ botId: command.botId,
29771
+ executionId: command.executionId,
29772
+ localGrantId: command.localGrantId
29773
+ },
29774
+ event: "bot_session_authorized",
29775
+ sessionId: command.sessionId
29776
+ });
29777
+ outbox.transitionExecution(command.commandId, "running");
29778
+ publisher.recordAttempt(
29779
+ command.sessionId,
29780
+ encodeSessionStartedEvent({
29781
+ attemptId,
29782
+ commandId: command.commandId,
29783
+ kind: SESSION_STARTED_KIND,
29784
+ sessionId: command.sessionId
29785
+ }),
29786
+ attemptId
29787
+ );
29788
+ const result = await sessions.runPrompt({
29789
+ additionalDirectories: [],
29790
+ agent,
29791
+ commandId: command.commandId,
29792
+ cwd: grant.workspacePath,
29793
+ images: attachments.images,
29794
+ onActivity: (activity) => {
29795
+ publisher.recordAttempt(
29796
+ command.sessionId,
29797
+ encodeAgentActivityEvent({
29798
+ activityId: activity.activityId,
29799
+ activityType: activity.activityType,
29800
+ commandId: command.commandId,
29801
+ content: activity.content,
29802
+ detail: activity.detail,
29803
+ input: activity.input,
29804
+ kind: AGENT_ACTIVITY_KIND,
29805
+ locations: activity.locations,
29806
+ name: activity.name,
29807
+ output: activity.output,
29808
+ sequence: activity.sequence,
29809
+ sessionId: command.sessionId,
29810
+ status: activity.status,
29811
+ title: activity.title,
29812
+ toolKind: activity.toolKind
29813
+ }),
29814
+ attemptId
29815
+ );
29816
+ return Promise.resolve();
29817
+ },
29818
+ onText: (text) => {
29819
+ publisher.recordAttempt(
29820
+ command.sessionId,
29821
+ encodeAgentMessageDeltaEvent({
29822
+ commandId: command.commandId,
29823
+ kind: AGENT_MESSAGE_DELTA_KIND,
29824
+ sessionId: command.sessionId,
29825
+ text
29826
+ }),
29827
+ attemptId
29828
+ );
29829
+ return Promise.resolve();
29830
+ },
29831
+ prompt: command.prompt,
29832
+ resources: applied.resources,
29833
+ sessionId: command.sessionId,
29834
+ signal: executionSignal
29835
+ });
29836
+ publisher.recordAttempt(
29837
+ command.sessionId,
29838
+ encodeSessionCompletedEvent({
29839
+ commandId: command.commandId,
29840
+ kind: SESSION_COMPLETED_KIND,
29841
+ sessionId: command.sessionId,
29842
+ stopReason: result.stopReason
29843
+ }),
29844
+ attemptId
29845
+ );
29846
+ outbox.transitionExecution(
29847
+ command.commandId,
29848
+ result.stopReason === "cancelled" ? "cancelled" : "succeeded"
29849
+ );
29850
+ audit.record({
29851
+ commandId: command.commandId,
29852
+ details: { botId: command.botId, executionId: command.executionId },
29853
+ event: result.stopReason === "cancelled" ? "bot_session_cancelled" : "bot_session_completed",
29854
+ sessionId: command.sessionId
29855
+ });
29856
+ } finally {
29857
+ lease.release();
29858
+ }
29859
+ } catch (error61) {
29860
+ const failure = Date.parse(command.executionDeadlineAt) <= Date.now() ? new LocalBotAuthorizationError("turn_expired", "The Bot execution deadline has expired", {
29861
+ cause: error61
29862
+ }) : error61;
29863
+ audit.record({
29864
+ commandId: command.commandId,
29865
+ details: {
29866
+ botId: command.botId,
29867
+ code: operationErrorCode(failure),
29868
+ executionId: command.executionId
29869
+ },
29870
+ event: "bot_session_failed",
29871
+ sessionId: command.sessionId
29872
+ });
29873
+ const code = operationErrorCode(failure);
29874
+ reportFailure(
29875
+ publisher,
29876
+ command,
29877
+ code === "session_operation_failed" ? "agent_execution_failed" : code,
29878
+ code === "session_operation_failed" ? "The local agent could not complete the Bot request" : operationErrorMessage(failure),
29879
+ attemptId
29880
+ );
29881
+ outbox.transitionExecution(command.commandId, "failed");
29882
+ console.error("Mobius daemon Bot command failed", failure);
29883
+ }
29884
+ }
28358
29885
  function waitForRelayRetry(signal, timer) {
28359
29886
  if (signal.aborted) {
28360
29887
  return Promise.resolve();
@@ -28391,7 +29918,7 @@ async function publishAgentCatalogUntilAvailable(config2, signal, timer) {
28391
29918
  }
28392
29919
  }
28393
29920
  }
28394
- async function runRelayConnection(config2, directories, audit, sessions, installations, installationObserver, nativeSessions, outbox, publisher, activeTurns, activeAttemptIds, onConnected, signal, timer) {
29921
+ async function runRelayConnection(config2, directories, audit, sessions, installations, installationObserver, nativeSessions, outbox, publisher, grants, contexts, applicator, ipc, activeTurns, activeAttemptIds, onConnected, signal, timer) {
28395
29922
  const relayUrl = new URL(config2.relayUrl);
28396
29923
  relayUrl.searchParams.set("liveness", "1");
28397
29924
  const socket = await connectRelay(relayUrl, signal);
@@ -28488,6 +30015,70 @@ async function runRelayConnection(config2, directories, audit, sessions, install
28488
30015
  }
28489
30016
  return;
28490
30017
  }
30018
+ if (kind === BOT_BINDING_APPROVED_KIND) {
30019
+ decodeBotExecutionBindingApprovedEvent(encoded);
30020
+ return;
30021
+ }
30022
+ if (kind === BOT_BINDING_UNAVAILABLE_KIND) {
30023
+ decodeBotExecutionBindingUnavailableEvent(encoded);
30024
+ return;
30025
+ }
30026
+ if (kind === BOT_BINDING_APPROVAL_REQUEST_KIND) {
30027
+ const request = decodeBotExecutionBindingApprovalRequest(encoded);
30028
+ void grants.approve(
30029
+ request,
30030
+ config2.catalog,
30031
+ directories,
30032
+ config2.bindingId,
30033
+ Date.now(),
30034
+ connectionController.signal
30035
+ ).then((approved) => {
30036
+ audit.record({
30037
+ commandId: request.requestId,
30038
+ details: {
30039
+ behaviorRevisionId: request.behaviorRevisionId,
30040
+ bindingId: request.bindingId,
30041
+ botId: request.botId,
30042
+ localGrantId: approved.localGrantId
30043
+ },
30044
+ event: "bot_binding_approved",
30045
+ sessionId: `bot-binding:${request.bindingId}`
30046
+ });
30047
+ if (socket.readyState === WebSocket2.OPEN) {
30048
+ send(socket, encodeBotExecutionBindingApprovedEvent(approved));
30049
+ }
30050
+ }).catch((error61) => {
30051
+ if (connectionController.signal.aborted) {
30052
+ return;
30053
+ }
30054
+ const code = error61 instanceof LocalBotAuthorizationError ? error61.code : "binding_incompatible";
30055
+ const message = error61 instanceof LocalBotAuthorizationError ? error61.message : "The local execution target is incompatible";
30056
+ grants.recordUnavailable(request, code, message, Date.now());
30057
+ audit.record({
30058
+ commandId: request.requestId,
30059
+ details: { bindingId: request.bindingId, botId: request.botId, code },
30060
+ event: "bot_binding_unavailable",
30061
+ sessionId: `bot-binding:${request.bindingId}`
30062
+ });
30063
+ if (socket.readyState === WebSocket2.OPEN) {
30064
+ send(
30065
+ socket,
30066
+ encodeBotExecutionBindingUnavailableEvent(
30067
+ new BotExecutionBindingUnavailableEvent(
30068
+ request.requestId,
30069
+ request.botId,
30070
+ request.behaviorRevisionId,
30071
+ request.bindingId,
30072
+ request.bindingRevision,
30073
+ code,
30074
+ message
30075
+ )
30076
+ )
30077
+ );
30078
+ }
30079
+ });
30080
+ return;
30081
+ }
28491
30082
  if (kind === NATIVE_SESSION_CANCEL_KIND) {
28492
30083
  const command2 = decodeNativeSessionCancel(encoded);
28493
30084
  const pending = nativeRequests.get(command2.requestId);
@@ -28686,6 +30277,44 @@ async function runRelayConnection(config2, directories, audit, sessions, install
28686
30277
  });
28687
30278
  return;
28688
30279
  }
30280
+ if (kind === BOT_SESSION_PROMPT_KIND) {
30281
+ const command2 = decodeBotSessionPromptCommand(encoded);
30282
+ if (activeTurns.has(command2.commandId)) {
30283
+ return;
30284
+ }
30285
+ const receipt2 = outbox.claimExecution(command2.commandId, command2.sessionId, encoded);
30286
+ if (receipt2.kind === "duplicate") {
30287
+ return;
30288
+ }
30289
+ const turn2 = new ActiveDaemonTurn(command2, receipt2.attemptId);
30290
+ activeTurns.set(command2.commandId, turn2);
30291
+ activeAttemptIds.set(command2.sessionId, receipt2.attemptId);
30292
+ void executeBotPrompt(
30293
+ outbox,
30294
+ publisher,
30295
+ command2,
30296
+ config2,
30297
+ directories,
30298
+ audit,
30299
+ sessions,
30300
+ grants,
30301
+ contexts,
30302
+ applicator,
30303
+ ipc,
30304
+ receipt2.attemptId,
30305
+ turn2.signal
30306
+ ).catch((error61) => {
30307
+ console.error("Mobius daemon Bot turn failed", error61);
30308
+ }).finally(() => {
30309
+ activeTurns.delete(command2.commandId);
30310
+ if (activeAttemptIds.get(command2.sessionId) === receipt2.attemptId) {
30311
+ activeAttemptIds.delete(command2.sessionId);
30312
+ }
30313
+ turn2.finish();
30314
+ connectionRefresh.afterTurnFinished();
30315
+ });
30316
+ return;
30317
+ }
28689
30318
  if (kind !== SESSION_PROMPT_KIND) {
28690
30319
  throw new Error("Unsupported protocol message");
28691
30320
  }
@@ -28776,6 +30405,10 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
28776
30405
  const sessionStore = new SqliteAcpSessionStore(config2.auditDatabasePath);
28777
30406
  const outbox = new SessionEventOutbox(config2.auditDatabasePath);
28778
30407
  const publisher = new DaemonSessionEventPublisher(outbox);
30408
+ const grants = new LocalBotGrantStore(config2.auditDatabasePath);
30409
+ const contexts = new BotExecutionContextRegistry();
30410
+ const applicator = new EmbeddedBotContextApplicator();
30411
+ const ipc = new BotOutboundIpcServer(botIpcSocketPath(), config2.relayUrl, contexts);
28779
30412
  const activeTurns = /* @__PURE__ */ new Map();
28780
30413
  const activeAttemptIds = /* @__PURE__ */ new Map();
28781
30414
  const recordSessionEvent = (sessionId, payload) => {
@@ -28814,6 +30447,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
28814
30447
  };
28815
30448
  const catalogPublication = publishAgentCatalogUntilAvailable(config2, signal, timer);
28816
30449
  try {
30450
+ await ipc.listen(signal);
28817
30451
  while (!signal.aborted) {
28818
30452
  try {
28819
30453
  await runRelayConnection(
@@ -28826,6 +30460,10 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
28826
30460
  nativeSessions,
28827
30461
  outbox,
28828
30462
  publisher,
30463
+ grants,
30464
+ contexts,
30465
+ applicator,
30466
+ ipc,
28829
30467
  activeTurns,
28830
30468
  activeAttemptIds,
28831
30469
  announceConnection,
@@ -28857,12 +30495,20 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
28857
30495
  await installations.close();
28858
30496
  } finally {
28859
30497
  try {
28860
- await sessions.close();
30498
+ await ipc.close();
28861
30499
  } finally {
28862
30500
  try {
28863
- sessionStore.close();
30501
+ await sessions.close();
28864
30502
  } finally {
28865
- outbox.close();
30503
+ try {
30504
+ sessionStore.close();
30505
+ } finally {
30506
+ try {
30507
+ grants.close();
30508
+ } finally {
30509
+ outbox.close();
30510
+ }
30511
+ }
28866
30512
  }
28867
30513
  }
28868
30514
  }
@@ -28872,9 +30518,13 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
28872
30518
  export {
28873
30519
  AcpExecutionError,
28874
30520
  AuditStore,
30521
+ BotExecutionContextRegistry,
30522
+ BotMessageCommandError,
30523
+ BotOutboundIpcServer,
28875
30524
  LocalAuthorizationError,
28876
30525
  PairingClientError,
28877
30526
  createAcpClient,
30527
+ executeBotMessageCommand,
28878
30528
  loadDaemonConfig,
28879
30529
  pairLocalMachine,
28880
30530
  resumeLocalMachine,