@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.
- package/dist/bots/bot-context-applicator.d.ts +14 -0
- package/dist/bots/bot-context-applicator.d.ts.map +1 -0
- package/dist/bots/bot-context-applicator.js +32 -0
- package/dist/bots/bot-context-applicator.js.map +1 -0
- package/dist/bots/bot-execution-context.d.ts +20 -0
- package/dist/bots/bot-execution-context.d.ts.map +1 -0
- package/dist/bots/bot-execution-context.js +82 -0
- package/dist/bots/bot-execution-context.js.map +1 -0
- package/dist/bots/bot-message-command.d.ts +6 -0
- package/dist/bots/bot-message-command.d.ts.map +1 -0
- package/dist/bots/bot-message-command.js +140 -0
- package/dist/bots/bot-message-command.js.map +1 -0
- package/dist/bots/bot-outbound-ipc.d.ts +12 -0
- package/dist/bots/bot-outbound-ipc.d.ts.map +1 -0
- package/dist/bots/bot-outbound-ipc.js +245 -0
- package/dist/bots/bot-outbound-ipc.js.map +1 -0
- package/dist/bots/local-bot-grant-store.d.ts +34 -0
- package/dist/bots/local-bot-grant-store.d.ts.map +1 -0
- package/dist/bots/local-bot-grant-store.js +263 -0
- package/dist/bots/local-bot-grant-store.js.map +1 -0
- package/dist/cli.js +1872 -213
- package/dist/cli.js.map +4 -4
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1930 -280
- package/dist/index.js.map +4 -4
- package/dist/prompt-artifact-resolver.d.ts +8 -2
- package/dist/prompt-artifact-resolver.d.ts.map +1 -1
- package/dist/prompt-artifact-resolver.js.map +1 -1
- package/dist/run-daemon.d.ts.map +1 -1
- package/dist/run-daemon.js +241 -8
- package/dist/run-daemon.js.map +1 -1
- 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((
|
|
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
|
|
3730
|
-
const result =
|
|
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
|
|
3790
|
-
const result =
|
|
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
|
|
3815
|
-
for (const v of
|
|
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,
|
|
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
|
|
3830
|
-
const pv =
|
|
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(
|
|
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((
|
|
3845
|
-
const propShape = propShapes.get(
|
|
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
|
|
13777
|
-
const values =
|
|
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,
|
|
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
|
|
15342
|
-
if (!
|
|
15341
|
+
for (const option2 of options) {
|
|
15342
|
+
if (!option2 || typeof option2 !== "object")
|
|
15343
15343
|
return;
|
|
15344
|
-
compactTypeUnion(
|
|
15345
|
-
const keys = Object.keys(
|
|
15344
|
+
compactTypeUnion(option2);
|
|
15345
|
+
const keys = Object.keys(option2);
|
|
15346
15346
|
if (keys.length !== 1 || keys[0] !== "type")
|
|
15347
15347
|
return;
|
|
15348
|
-
const 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
|
|
15639
|
-
if (isTransforming(
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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 (!
|
|
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
|
|
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(
|
|
21612
|
+
function normalizeConfigValue(option2, groupId = "", groupName = "") {
|
|
21132
21613
|
return {
|
|
21133
|
-
description: truncate2(readString2(
|
|
21614
|
+
description: truncate2(readString2(option2["description"]), 500),
|
|
21134
21615
|
groupId: truncate2(groupId, 128),
|
|
21135
21616
|
groupName: truncate2(groupName, 255),
|
|
21136
|
-
name: truncate2(readString2(
|
|
21137
|
-
value: truncate2(readString2(
|
|
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 (!
|
|
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 (
|
|
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
|
|
21168
|
-
if (!
|
|
21648
|
+
for (const option2 of value) {
|
|
21649
|
+
if (!isRecord4(option2)) {
|
|
21169
21650
|
continue;
|
|
21170
21651
|
}
|
|
21171
|
-
const id = truncate2(readString2(
|
|
21172
|
-
const name = truncate2(readString2(
|
|
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 (
|
|
21657
|
+
if (option2["type"] === "boolean") {
|
|
21177
21658
|
normalized.push({
|
|
21178
|
-
booleanValue: readBoolean(
|
|
21179
|
-
category: truncate2(readString2(
|
|
21659
|
+
booleanValue: readBoolean(option2["currentValue"]),
|
|
21660
|
+
category: truncate2(readString2(option2["category"]), 128),
|
|
21180
21661
|
currentValue: "",
|
|
21181
|
-
description: truncate2(readString2(
|
|
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 (
|
|
21190
|
-
const values = normalizeConfigValues(
|
|
21191
|
-
const currentValue = truncate2(readString2(
|
|
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(
|
|
21676
|
+
category: truncate2(readString2(option2["category"]), 128),
|
|
21196
21677
|
currentValue,
|
|
21197
|
-
description: truncate2(readString2(
|
|
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 (
|
|
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 (!
|
|
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((
|
|
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((
|
|
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 =
|
|
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((
|
|
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((
|
|
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((
|
|
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 (!
|
|
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 (!
|
|
21827
|
+
if (!isRecord4(response)) {
|
|
21347
21828
|
return [];
|
|
21348
21829
|
}
|
|
21349
21830
|
const metadata = response["_meta"];
|
|
21350
|
-
if (!
|
|
21831
|
+
if (!isRecord4(metadata)) {
|
|
21351
21832
|
return [];
|
|
21352
21833
|
}
|
|
21353
21834
|
const sessionConfig = metadata["x.ai/sessionConfig"];
|
|
21354
|
-
if (!
|
|
21835
|
+
if (!isRecord4(sessionConfig) || !Array.isArray(sessionConfig["options"])) {
|
|
21355
21836
|
return [];
|
|
21356
21837
|
}
|
|
21357
|
-
return sessionConfig["options"].slice(0, 500).filter(
|
|
21838
|
+
return sessionConfig["options"].slice(0, 500).filter(isRecord4);
|
|
21358
21839
|
}
|
|
21359
|
-
function legacyValue(
|
|
21360
|
-
const value = readString2(
|
|
21840
|
+
function legacyValue(option2) {
|
|
21841
|
+
const value = readString2(option2["id"]);
|
|
21361
21842
|
return {
|
|
21362
|
-
description: readString2(
|
|
21843
|
+
description: readString2(option2["description"]).slice(0, 500),
|
|
21363
21844
|
groupId: "",
|
|
21364
21845
|
groupName: "",
|
|
21365
|
-
name: readString2(
|
|
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 (!
|
|
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
|
|
21380
|
-
if (
|
|
21381
|
-
const value = legacyValue(
|
|
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 (!
|
|
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((
|
|
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
|
|
21431
|
-
if (
|
|
21911
|
+
for (const option2 of options) {
|
|
21912
|
+
if (option2["category"] !== "mode") {
|
|
21432
21913
|
continue;
|
|
21433
21914
|
}
|
|
21434
|
-
const value = legacyValue(
|
|
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((
|
|
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 =
|
|
21950
|
+
const lifecycle = isRecord4(response) ? response : {};
|
|
21470
21951
|
const standard = normalizeConfigOptions(lifecycle["configOptions"], lifecycle["modes"]);
|
|
21471
21952
|
const normalized = [...standard];
|
|
21472
|
-
if (!normalized.some((
|
|
21953
|
+
if (!normalized.some((option2) => option2.category === "model")) {
|
|
21473
21954
|
normalized.push(...legacyModelOptions(response));
|
|
21474
21955
|
}
|
|
21475
|
-
if (!normalized.some((
|
|
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((
|
|
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((
|
|
21966
|
+
return current.map((option2) => option2.category === category ? { ...option2, currentValue: value } : option2);
|
|
21486
21967
|
}
|
|
21487
21968
|
function validateGrokResponse(response, modelId) {
|
|
21488
|
-
if (!
|
|
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 =
|
|
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((
|
|
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((
|
|
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
|
-
(
|
|
21530
|
-
...
|
|
21531
|
-
values:
|
|
21532
|
-
} :
|
|
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
|
|
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
|
|
21964
|
-
if (
|
|
22444
|
+
for (const option2 of oneOf) {
|
|
22445
|
+
if (isRecord5(option2) && typeof option2["const"] === "string") {
|
|
21965
22446
|
normalized.push({
|
|
21966
|
-
description: truncate3(readString4(
|
|
21967
|
-
label: truncate3(readString4(
|
|
21968
|
-
value: truncate3(
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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((
|
|
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((
|
|
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((
|
|
22903
|
-
kind:
|
|
22904
|
-
name: truncate3(
|
|
22905
|
-
optionId: truncate3(
|
|
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((
|
|
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
|
-
(
|
|
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
|
-
|
|
23723
|
-
|
|
23724
|
-
|
|
23725
|
-
|
|
23726
|
-
|
|
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
|
-
|
|
23742
|
-
|
|
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
|
|
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
|
|
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
|
|
23869
|
-
import { delimiter, dirname as
|
|
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
|
|
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}`) && !
|
|
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 (!
|
|
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 (
|
|
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 (!
|
|
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") || !
|
|
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 || !
|
|
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
|
|
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 =
|
|
24100
|
-
await
|
|
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: `${
|
|
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
|
|
24358
|
-
import { isAbsolute as
|
|
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 (!
|
|
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
|
|
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
|
|
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}`) && !
|
|
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
|
|
24592
|
-
import { dirname as
|
|
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
|
|
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}`) && !
|
|
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
|
|
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
|
-
|
|
25982
|
+
digest2.update(chunk);
|
|
24668
25983
|
}
|
|
24669
|
-
return
|
|
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 (!
|
|
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
|
|
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
|
|
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 &&
|
|
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
|
|
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 || !
|
|
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
|
|
25580
|
-
var
|
|
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
|
|
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_,
|
|
26914
|
+
function readSingleOption(arguments_, option2) {
|
|
25600
26915
|
const values = [];
|
|
25601
26916
|
for (let index = 0; index < arguments_.length; index += 1) {
|
|
25602
|
-
if (arguments_[index] !==
|
|
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", `${
|
|
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", `${
|
|
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
|
|
25620
|
-
if (
|
|
25621
|
-
throw new PairingClientError("invalid_arguments", `Unknown pairing 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 (!
|
|
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
|
|
26992
|
+
await mkdir4(requestedWorkspace, { recursive: true, mode: 448 });
|
|
25678
26993
|
const defaultWorkspace = await realpath6(requestedWorkspace);
|
|
25679
|
-
const metadata = await
|
|
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 (
|
|
27023
|
+
if (isRecord10(value)) {
|
|
25709
27024
|
const error61 = value["error"];
|
|
25710
|
-
if (
|
|
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 (!
|
|
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
|
|
27040
|
+
const daemonToken2 = value["daemonToken"];
|
|
25726
27041
|
const runtimeId = value["runtimeId"];
|
|
25727
|
-
if (typeof channelId !== "string" || !
|
|
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
|
|
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,
|
|
27080
|
+
async function persistConnection(channelId, relayOrigin, daemonToken2, defaultWorkspace) {
|
|
25766
27081
|
const connectionsDirectory = join14(readStateDirectory(), "connections");
|
|
25767
|
-
await
|
|
27082
|
+
await mkdir4(connectionsDirectory, { mode: 448, recursive: true });
|
|
25768
27083
|
const connectionPath = join14(connectionsDirectory, `${channelId}.json`);
|
|
25769
|
-
const temporaryPath = join14(connectionsDirectory, `.${channelId}.${
|
|
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 (!
|
|
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
|
|
27109
|
+
const daemonToken2 = value["daemonToken"];
|
|
25795
27110
|
const relayOrigin = value["relayOrigin"];
|
|
25796
|
-
if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 (
|
|
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 (!
|
|
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
|
|
27812
|
+
const metadata = await stat7(target);
|
|
26497
27813
|
signal.throwIfAborted();
|
|
26498
|
-
if (!
|
|
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 === "" ? "~" : !
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
27142
|
-
import { fetch as
|
|
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
|
|
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 || !
|
|
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
|
|
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 (
|
|
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
|
|
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 =
|
|
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
|
|
27521
|
-
import { DatabaseSync as
|
|
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(
|
|
27536
|
-
this.#database = new
|
|
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
|
|
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
|
|
30498
|
+
await ipc.close();
|
|
28861
30499
|
} finally {
|
|
28862
30500
|
try {
|
|
28863
|
-
|
|
30501
|
+
await sessions.close();
|
|
28864
30502
|
} finally {
|
|
28865
|
-
|
|
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,
|