@moxt-ai/mobius 0.0.20 → 0.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +1924 -209
- 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 +1970 -264
- 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/relay-connection/session-event-outbox.d.ts +2 -1
- package/dist/relay-connection/session-event-outbox.d.ts.map +1 -1
- package/dist/relay-connection/session-event-outbox.js +39 -0
- package/dist/relay-connection/session-event-outbox.js.map +1 -1
- package/dist/run-daemon.d.ts.map +1 -1
- package/dist/run-daemon.js +246 -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._~-]+)*$/;
|
|
@@ -19885,13 +20366,18 @@ var decodeNativeSessionCancel = (encoded) => decode4(nativeSessionCancelSchema,
|
|
|
19885
20366
|
var SESSION_EVENT_KIND = "session.event";
|
|
19886
20367
|
var SESSION_EVENT_ACK_KIND = "session.event.ack";
|
|
19887
20368
|
var SESSION_EVENT_COMMITTED_KIND = "session.event.committed";
|
|
19888
|
-
var
|
|
20369
|
+
var SESSION_EVENT_REJECTED_KIND = "session.event.rejected";
|
|
20370
|
+
var SessionEventRejectionCode = {
|
|
20371
|
+
SessionDeleted: "session_deleted",
|
|
20372
|
+
SessionNotFound: "session_not_found"
|
|
20373
|
+
};
|
|
20374
|
+
var IDENTIFIER_PATTERN4 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
|
|
19889
20375
|
var CURSOR_PATTERN = /^[A-Za-z0-9_-]{1,512}$/;
|
|
19890
20376
|
var MAX_RECORDED_EVENT_LENGTH = 8 * 1024 * 1024;
|
|
19891
20377
|
var DECIMAL_SEQUENCE_PATTERN = /^(?:0|[1-9][0-9]*)$/;
|
|
19892
20378
|
var eventSourceSchema = external_exports.discriminatedUnion("kind", [
|
|
19893
20379
|
external_exports.strictObject({
|
|
19894
|
-
attemptId: external_exports.string().min(1).max(128).regex(
|
|
20380
|
+
attemptId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
|
|
19895
20381
|
kind: external_exports.literal("attempt"),
|
|
19896
20382
|
sourceSeq: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN)
|
|
19897
20383
|
}).readonly(),
|
|
@@ -19901,29 +20387,35 @@ var eventSourceSchema = external_exports.discriminatedUnion("kind", [
|
|
|
19901
20387
|
}).readonly()
|
|
19902
20388
|
]);
|
|
19903
20389
|
var eventEnvelopeSchema = external_exports.strictObject({
|
|
19904
|
-
eventId: external_exports.string().min(1).max(128).regex(
|
|
20390
|
+
eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
|
|
19905
20391
|
kind: external_exports.literal(SESSION_EVENT_KIND),
|
|
19906
20392
|
payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
|
|
19907
|
-
sessionId: external_exports.string().min(1).max(128).regex(
|
|
20393
|
+
sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
|
|
19908
20394
|
source: eventSourceSchema
|
|
19909
20395
|
}).readonly();
|
|
19910
20396
|
var committedEventSchema = external_exports.strictObject({
|
|
19911
20397
|
cursor: external_exports.string().min(1).max(512).regex(CURSOR_PATTERN),
|
|
19912
|
-
eventId: external_exports.string().min(1).max(128).regex(
|
|
20398
|
+
eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
|
|
19913
20399
|
kind: external_exports.literal(SESSION_EVENT_COMMITTED_KIND),
|
|
19914
20400
|
payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
|
|
19915
20401
|
recordedAt: external_exports.string().datetime({ offset: true }),
|
|
19916
20402
|
sequence: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN),
|
|
19917
|
-
sessionId: external_exports.string().min(1).max(128).regex(
|
|
20403
|
+
sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
|
|
19918
20404
|
source: eventSourceSchema
|
|
19919
20405
|
}).readonly();
|
|
19920
20406
|
var eventAcknowledgementSchema = external_exports.strictObject({
|
|
19921
20407
|
cursor: external_exports.string().min(1).max(512).regex(CURSOR_PATTERN),
|
|
19922
20408
|
duplicate: external_exports.boolean(),
|
|
19923
|
-
eventId: external_exports.string().min(1).max(128).regex(
|
|
20409
|
+
eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
|
|
19924
20410
|
kind: external_exports.literal(SESSION_EVENT_ACK_KIND),
|
|
19925
20411
|
sequence: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN),
|
|
19926
|
-
sessionId: external_exports.string().min(1).max(128).regex(
|
|
20412
|
+
sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4)
|
|
20413
|
+
}).readonly();
|
|
20414
|
+
var eventRejectionSchema = external_exports.strictObject({
|
|
20415
|
+
code: external_exports.enum(SessionEventRejectionCode),
|
|
20416
|
+
eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
|
|
20417
|
+
kind: external_exports.literal(SESSION_EVENT_REJECTED_KIND),
|
|
20418
|
+
sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4)
|
|
19927
20419
|
}).readonly();
|
|
19928
20420
|
function decode5(encoded, schema) {
|
|
19929
20421
|
let value;
|
|
@@ -19951,6 +20443,7 @@ var encode4 = (message, schema) => {
|
|
|
19951
20443
|
};
|
|
19952
20444
|
var encodeSessionEventEnvelope = (message) => encode4(message, eventEnvelopeSchema);
|
|
19953
20445
|
var decodeSessionEventAcknowledgement = (encoded) => decode5(encoded, eventAcknowledgementSchema);
|
|
20446
|
+
var decodeSessionEventRejection = (encoded) => decode5(encoded, eventRejectionSchema);
|
|
19954
20447
|
|
|
19955
20448
|
// src/agent-catalog/local-agent.ts
|
|
19956
20449
|
import { realpathSync, statSync } from "node:fs";
|
|
@@ -20599,7 +21092,7 @@ import {
|
|
|
20599
21092
|
|
|
20600
21093
|
// src/acp/activity.ts
|
|
20601
21094
|
var TRUNCATION_MARKER = "\n\u2026 output truncated by Mobius";
|
|
20602
|
-
function
|
|
21095
|
+
function isRecord3(value) {
|
|
20603
21096
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20604
21097
|
}
|
|
20605
21098
|
var AcpActivity = class _AcpActivity {
|
|
@@ -20866,7 +21359,7 @@ function contentPhase(content) {
|
|
|
20866
21359
|
return "";
|
|
20867
21360
|
}
|
|
20868
21361
|
const codex = metadata["codex"];
|
|
20869
|
-
if (!
|
|
21362
|
+
if (!isRecord3(codex)) {
|
|
20870
21363
|
return "";
|
|
20871
21364
|
}
|
|
20872
21365
|
const phase = codex["phase"];
|
|
@@ -21104,7 +21597,7 @@ var SessionConfigProtocolError = class extends Error {
|
|
|
21104
21597
|
this.name = "SessionConfigProtocolError";
|
|
21105
21598
|
}
|
|
21106
21599
|
};
|
|
21107
|
-
function
|
|
21600
|
+
function isRecord4(value) {
|
|
21108
21601
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21109
21602
|
}
|
|
21110
21603
|
function readString2(value, fallback = "") {
|
|
@@ -21116,13 +21609,13 @@ function truncate2(value, maximum) {
|
|
|
21116
21609
|
function readBoolean(value, fallback = false) {
|
|
21117
21610
|
return typeof value === "boolean" ? value : fallback;
|
|
21118
21611
|
}
|
|
21119
|
-
function normalizeConfigValue(
|
|
21612
|
+
function normalizeConfigValue(option2, groupId = "", groupName = "") {
|
|
21120
21613
|
return {
|
|
21121
|
-
description: truncate2(readString2(
|
|
21614
|
+
description: truncate2(readString2(option2["description"]), 500),
|
|
21122
21615
|
groupId: truncate2(groupId, 128),
|
|
21123
21616
|
groupName: truncate2(groupName, 255),
|
|
21124
|
-
name: truncate2(readString2(
|
|
21125
|
-
value: truncate2(readString2(
|
|
21617
|
+
name: truncate2(readString2(option2["name"], readString2(option2["value"])), 255),
|
|
21618
|
+
value: truncate2(readString2(option2["value"]), 500)
|
|
21126
21619
|
};
|
|
21127
21620
|
}
|
|
21128
21621
|
function normalizeConfigValues(value) {
|
|
@@ -21131,7 +21624,7 @@ function normalizeConfigValues(value) {
|
|
|
21131
21624
|
}
|
|
21132
21625
|
const normalized = [];
|
|
21133
21626
|
for (const entry of value) {
|
|
21134
|
-
if (!
|
|
21627
|
+
if (!isRecord4(entry)) {
|
|
21135
21628
|
continue;
|
|
21136
21629
|
}
|
|
21137
21630
|
const groupedOptions = entry["options"];
|
|
@@ -21139,7 +21632,7 @@ function normalizeConfigValues(value) {
|
|
|
21139
21632
|
const groupId = readString2(entry["group"]);
|
|
21140
21633
|
const groupName = readString2(entry["name"]);
|
|
21141
21634
|
for (const groupedOption of groupedOptions) {
|
|
21142
|
-
if (
|
|
21635
|
+
if (isRecord4(groupedOption)) {
|
|
21143
21636
|
normalized.push(normalizeConfigValue(groupedOption, groupId, groupName));
|
|
21144
21637
|
}
|
|
21145
21638
|
}
|
|
@@ -21152,21 +21645,21 @@ function normalizeConfigValues(value) {
|
|
|
21152
21645
|
function normalizeConfigOptions(value, modes) {
|
|
21153
21646
|
const normalized = [];
|
|
21154
21647
|
if (Array.isArray(value)) {
|
|
21155
|
-
for (const
|
|
21156
|
-
if (!
|
|
21648
|
+
for (const option2 of value) {
|
|
21649
|
+
if (!isRecord4(option2)) {
|
|
21157
21650
|
continue;
|
|
21158
21651
|
}
|
|
21159
|
-
const id = truncate2(readString2(
|
|
21160
|
-
const name = truncate2(readString2(
|
|
21652
|
+
const id = truncate2(readString2(option2["id"]), 128);
|
|
21653
|
+
const name = truncate2(readString2(option2["name"], id), 255);
|
|
21161
21654
|
if (id.length === 0 || name.length === 0) {
|
|
21162
21655
|
continue;
|
|
21163
21656
|
}
|
|
21164
|
-
if (
|
|
21657
|
+
if (option2["type"] === "boolean") {
|
|
21165
21658
|
normalized.push({
|
|
21166
|
-
booleanValue: readBoolean(
|
|
21167
|
-
category: truncate2(readString2(
|
|
21659
|
+
booleanValue: readBoolean(option2["currentValue"]),
|
|
21660
|
+
category: truncate2(readString2(option2["category"]), 128),
|
|
21168
21661
|
currentValue: "",
|
|
21169
|
-
description: truncate2(readString2(
|
|
21662
|
+
description: truncate2(readString2(option2["description"]), 500),
|
|
21170
21663
|
id,
|
|
21171
21664
|
name,
|
|
21172
21665
|
type: "boolean",
|
|
@@ -21174,15 +21667,15 @@ function normalizeConfigOptions(value, modes) {
|
|
|
21174
21667
|
});
|
|
21175
21668
|
continue;
|
|
21176
21669
|
}
|
|
21177
|
-
if (
|
|
21178
|
-
const values = normalizeConfigValues(
|
|
21179
|
-
const currentValue = truncate2(readString2(
|
|
21670
|
+
if (option2["type"] === "select") {
|
|
21671
|
+
const values = normalizeConfigValues(option2["options"]);
|
|
21672
|
+
const currentValue = truncate2(readString2(option2["currentValue"]), 500);
|
|
21180
21673
|
if (currentValue.length > 0 && values.some((entry) => entry.value === currentValue)) {
|
|
21181
21674
|
normalized.push({
|
|
21182
21675
|
booleanValue: false,
|
|
21183
|
-
category: truncate2(readString2(
|
|
21676
|
+
category: truncate2(readString2(option2["category"]), 128),
|
|
21184
21677
|
currentValue,
|
|
21185
|
-
description: truncate2(readString2(
|
|
21678
|
+
description: truncate2(readString2(option2["description"]), 500),
|
|
21186
21679
|
id,
|
|
21187
21680
|
name,
|
|
21188
21681
|
type: "select",
|
|
@@ -21192,12 +21685,12 @@ function normalizeConfigOptions(value, modes) {
|
|
|
21192
21685
|
}
|
|
21193
21686
|
}
|
|
21194
21687
|
}
|
|
21195
|
-
if (
|
|
21688
|
+
if (isRecord4(modes)) {
|
|
21196
21689
|
const values = [];
|
|
21197
21690
|
const availableModes = modes["availableModes"];
|
|
21198
21691
|
if (Array.isArray(availableModes)) {
|
|
21199
21692
|
for (const mode of availableModes) {
|
|
21200
|
-
if (!
|
|
21693
|
+
if (!isRecord4(mode)) {
|
|
21201
21694
|
continue;
|
|
21202
21695
|
}
|
|
21203
21696
|
const id = truncate2(readString2(mode["id"]), 500);
|
|
@@ -21230,7 +21723,7 @@ function normalizeConfigOptions(value, modes) {
|
|
|
21230
21723
|
return normalized.slice(0, 100);
|
|
21231
21724
|
}
|
|
21232
21725
|
function ensureReasoningEffortOption(current) {
|
|
21233
|
-
if (current.some((
|
|
21726
|
+
if (current.some((option2) => option2.category === "thought_level")) {
|
|
21234
21727
|
return current;
|
|
21235
21728
|
}
|
|
21236
21729
|
const unavailable = {
|
|
@@ -21251,7 +21744,7 @@ function ensureReasoningEffortOption(current) {
|
|
|
21251
21744
|
}
|
|
21252
21745
|
]
|
|
21253
21746
|
};
|
|
21254
|
-
const modelIndex = current.findIndex((
|
|
21747
|
+
const modelIndex = current.findIndex((option2) => option2.category === "model");
|
|
21255
21748
|
if (current.length < MAXIMUM_CONFIG_OPTIONS) {
|
|
21256
21749
|
if (modelIndex < 0) {
|
|
21257
21750
|
return [...current, unavailable];
|
|
@@ -21275,20 +21768,20 @@ function ensureReasoningEffortOption(current) {
|
|
|
21275
21768
|
return [...current.slice(0, MAXIMUM_CONFIG_OPTIONS - 2), model, unavailable];
|
|
21276
21769
|
}
|
|
21277
21770
|
function normalizeStandardLifecycle(response) {
|
|
21278
|
-
const lifecycle =
|
|
21771
|
+
const lifecycle = isRecord4(response) ? response : {};
|
|
21279
21772
|
return ensureReasoningEffortOption(normalizeConfigOptions(lifecycle["configOptions"], lifecycle["modes"]));
|
|
21280
21773
|
}
|
|
21281
21774
|
function replaceStandardConfigOptions(current, value) {
|
|
21282
21775
|
const next = normalizeConfigOptions(value, void 0);
|
|
21283
|
-
const withMode = next.some((
|
|
21776
|
+
const withMode = next.some((option2) => option2.category === "mode") ? next : [...current.filter((option2) => option2.category === "mode"), ...next].slice(0, 100);
|
|
21284
21777
|
return ensureReasoningEffortOption(withMode);
|
|
21285
21778
|
}
|
|
21286
21779
|
function updateCurrentValue(current, configId, value) {
|
|
21287
|
-
return current.map((
|
|
21780
|
+
return current.map((option2) => option2.id === configId ? { ...option2, currentValue: value } : option2);
|
|
21288
21781
|
}
|
|
21289
21782
|
var StandardSessionConfigProtocol = class {
|
|
21290
21783
|
configure = async (current, change, nativeSessionId, transport) => {
|
|
21291
|
-
const existing = current.find((
|
|
21784
|
+
const existing = current.find((option2) => option2.id === change.configId);
|
|
21292
21785
|
if (existing === void 0) {
|
|
21293
21786
|
return current;
|
|
21294
21787
|
}
|
|
@@ -21317,7 +21810,7 @@ var StandardSessionConfigProtocol = class {
|
|
|
21317
21810
|
"ACP agent exited while changing session configuration",
|
|
21318
21811
|
change.signal
|
|
21319
21812
|
);
|
|
21320
|
-
if (!
|
|
21813
|
+
if (!isRecord4(response) || !Array.isArray(response["configOptions"])) {
|
|
21321
21814
|
throw new SessionConfigProtocolError("The Agent returned an invalid session configuration response");
|
|
21322
21815
|
}
|
|
21323
21816
|
return replaceStandardConfigOptions(current, response["configOptions"]);
|
|
@@ -21331,31 +21824,31 @@ var standardSessionConfigProtocol = new StandardSessionConfigProtocol();
|
|
|
21331
21824
|
var LEGACY_MODEL_CONFIG_ID = "grok_build_legacy_model";
|
|
21332
21825
|
var LEGACY_REASONING_EFFORT_CONFIG_ID = "grok_build_legacy_reasoning_effort";
|
|
21333
21826
|
function legacyOptions(response) {
|
|
21334
|
-
if (!
|
|
21827
|
+
if (!isRecord4(response)) {
|
|
21335
21828
|
return [];
|
|
21336
21829
|
}
|
|
21337
21830
|
const metadata = response["_meta"];
|
|
21338
|
-
if (!
|
|
21831
|
+
if (!isRecord4(metadata)) {
|
|
21339
21832
|
return [];
|
|
21340
21833
|
}
|
|
21341
21834
|
const sessionConfig = metadata["x.ai/sessionConfig"];
|
|
21342
|
-
if (!
|
|
21835
|
+
if (!isRecord4(sessionConfig) || !Array.isArray(sessionConfig["options"])) {
|
|
21343
21836
|
return [];
|
|
21344
21837
|
}
|
|
21345
|
-
return sessionConfig["options"].slice(0, 500).filter(
|
|
21838
|
+
return sessionConfig["options"].slice(0, 500).filter(isRecord4);
|
|
21346
21839
|
}
|
|
21347
|
-
function legacyValue(
|
|
21348
|
-
const value = readString2(
|
|
21840
|
+
function legacyValue(option2) {
|
|
21841
|
+
const value = readString2(option2["id"]);
|
|
21349
21842
|
return {
|
|
21350
|
-
description: readString2(
|
|
21843
|
+
description: readString2(option2["description"]).slice(0, 500),
|
|
21351
21844
|
groupId: "",
|
|
21352
21845
|
groupName: "",
|
|
21353
|
-
name: readString2(
|
|
21846
|
+
name: readString2(option2["label"], value).slice(0, 255),
|
|
21354
21847
|
value: value.slice(0, 500)
|
|
21355
21848
|
};
|
|
21356
21849
|
}
|
|
21357
21850
|
function modelsRecord(response) {
|
|
21358
|
-
if (!
|
|
21851
|
+
if (!isRecord4(response) || !isRecord4(response["models"])) {
|
|
21359
21852
|
return {};
|
|
21360
21853
|
}
|
|
21361
21854
|
return response["models"];
|
|
@@ -21364,9 +21857,9 @@ function legacyModelOptions(response) {
|
|
|
21364
21857
|
const options = legacyOptions(response);
|
|
21365
21858
|
const models = modelsRecord(response);
|
|
21366
21859
|
const values = [];
|
|
21367
|
-
for (const
|
|
21368
|
-
if (
|
|
21369
|
-
const value = legacyValue(
|
|
21860
|
+
for (const option2 of options) {
|
|
21861
|
+
if (option2["category"] === "model") {
|
|
21862
|
+
const value = legacyValue(option2);
|
|
21370
21863
|
if (value.value.length > 0 && !values.some((existing) => existing.value === value.value)) {
|
|
21371
21864
|
values.push(value);
|
|
21372
21865
|
}
|
|
@@ -21374,7 +21867,7 @@ function legacyModelOptions(response) {
|
|
|
21374
21867
|
}
|
|
21375
21868
|
if (values.length === 0 && Array.isArray(models["availableModels"])) {
|
|
21376
21869
|
for (const model of models["availableModels"]) {
|
|
21377
|
-
if (!
|
|
21870
|
+
if (!isRecord4(model)) {
|
|
21378
21871
|
continue;
|
|
21379
21872
|
}
|
|
21380
21873
|
const value = readString2(model["modelId"]).slice(0, 500);
|
|
@@ -21392,7 +21885,7 @@ function legacyModelOptions(response) {
|
|
|
21392
21885
|
}
|
|
21393
21886
|
}
|
|
21394
21887
|
}
|
|
21395
|
-
const selected = options.find((
|
|
21888
|
+
const selected = options.find((option2) => option2["category"] === "model" && option2["selected"] === true);
|
|
21396
21889
|
const currentValue = readString2(
|
|
21397
21890
|
models["currentModelId"],
|
|
21398
21891
|
selected === void 0 ? "" : readString2(selected["id"])
|
|
@@ -21415,11 +21908,11 @@ function legacyModelOptions(response) {
|
|
|
21415
21908
|
function legacyReasoningEffortOptions(response) {
|
|
21416
21909
|
const options = legacyOptions(response);
|
|
21417
21910
|
const values = [];
|
|
21418
|
-
for (const
|
|
21419
|
-
if (
|
|
21911
|
+
for (const option2 of options) {
|
|
21912
|
+
if (option2["category"] !== "mode") {
|
|
21420
21913
|
continue;
|
|
21421
21914
|
}
|
|
21422
|
-
const value = legacyValue(
|
|
21915
|
+
const value = legacyValue(option2);
|
|
21423
21916
|
if (value.value.length > 0 && !values.some((existing) => existing.value === value.value)) {
|
|
21424
21917
|
values.push(value);
|
|
21425
21918
|
}
|
|
@@ -21427,7 +21920,7 @@ function legacyReasoningEffortOptions(response) {
|
|
|
21427
21920
|
if (values.length === 0) {
|
|
21428
21921
|
return [];
|
|
21429
21922
|
}
|
|
21430
|
-
const selected = options.find((
|
|
21923
|
+
const selected = options.find((option2) => option2["category"] === "mode" && option2["selected"] === true);
|
|
21431
21924
|
if (selected === void 0) {
|
|
21432
21925
|
values.unshift({
|
|
21433
21926
|
description: "Use the selected model's default reasoning effort",
|
|
@@ -21454,41 +21947,41 @@ function legacyReasoningEffortOptions(response) {
|
|
|
21454
21947
|
return [result];
|
|
21455
21948
|
}
|
|
21456
21949
|
function normalizeGrokLifecycle(response) {
|
|
21457
|
-
const lifecycle =
|
|
21950
|
+
const lifecycle = isRecord4(response) ? response : {};
|
|
21458
21951
|
const standard = normalizeConfigOptions(lifecycle["configOptions"], lifecycle["modes"]);
|
|
21459
21952
|
const normalized = [...standard];
|
|
21460
|
-
if (!normalized.some((
|
|
21953
|
+
if (!normalized.some((option2) => option2.category === "model")) {
|
|
21461
21954
|
normalized.push(...legacyModelOptions(response));
|
|
21462
21955
|
}
|
|
21463
|
-
if (!normalized.some((
|
|
21956
|
+
if (!normalized.some((option2) => option2.category === "thought_level")) {
|
|
21464
21957
|
const efforts = legacyReasoningEffortOptions(response);
|
|
21465
21958
|
if (efforts.length > 0) {
|
|
21466
|
-
const modelIndex = normalized.findIndex((
|
|
21959
|
+
const modelIndex = normalized.findIndex((option2) => option2.category === "model");
|
|
21467
21960
|
normalized.splice(modelIndex < 0 ? normalized.length : modelIndex + 1, 0, ...efforts);
|
|
21468
21961
|
}
|
|
21469
21962
|
}
|
|
21470
21963
|
return ensureReasoningEffortOption(normalized.slice(0, 100));
|
|
21471
21964
|
}
|
|
21472
21965
|
function updateCurrentValue2(current, category, value) {
|
|
21473
|
-
return current.map((
|
|
21966
|
+
return current.map((option2) => option2.category === category ? { ...option2, currentValue: value } : option2);
|
|
21474
21967
|
}
|
|
21475
21968
|
function validateGrokResponse(response, modelId) {
|
|
21476
|
-
if (!
|
|
21969
|
+
if (!isRecord4(response) || !isRecord4(response["_meta"])) {
|
|
21477
21970
|
throw new SessionConfigProtocolError("Grok Build returned an invalid session configuration response");
|
|
21478
21971
|
}
|
|
21479
21972
|
const model = response["_meta"]["model"];
|
|
21480
|
-
const appliedModel =
|
|
21973
|
+
const appliedModel = isRecord4(model) ? model["Ok"] : model;
|
|
21481
21974
|
if (appliedModel !== modelId) {
|
|
21482
21975
|
throw new SessionConfigProtocolError("Grok Build returned an invalid session configuration response");
|
|
21483
21976
|
}
|
|
21484
21977
|
}
|
|
21485
21978
|
var GrokBuildSessionConfigProtocol = class {
|
|
21486
21979
|
configure = async (current, change, nativeSessionId, transport) => {
|
|
21487
|
-
const existing = current.find((
|
|
21980
|
+
const existing = current.find((option2) => option2.id === change.configId);
|
|
21488
21981
|
if (existing === void 0 || existing.id !== LEGACY_MODEL_CONFIG_ID && existing.id !== LEGACY_REASONING_EFFORT_CONFIG_ID) {
|
|
21489
21982
|
return await standardSessionConfigProtocol.configure(current, change, nativeSessionId, transport);
|
|
21490
21983
|
}
|
|
21491
|
-
const model = current.find((
|
|
21984
|
+
const model = current.find((option2) => option2.category === "model");
|
|
21492
21985
|
if (model === void 0) {
|
|
21493
21986
|
return current;
|
|
21494
21987
|
}
|
|
@@ -21514,10 +22007,10 @@ var GrokBuildSessionConfigProtocol = class {
|
|
|
21514
22007
|
validateGrokResponse(response, modelId);
|
|
21515
22008
|
const updated = updateCurrentValue2(current, existing.category, change.value);
|
|
21516
22009
|
return existing.category === "thought_level" ? updated.map(
|
|
21517
|
-
(
|
|
21518
|
-
...
|
|
21519
|
-
values:
|
|
21520
|
-
} :
|
|
22010
|
+
(option2) => option2.category === "thought_level" ? {
|
|
22011
|
+
...option2,
|
|
22012
|
+
values: option2.values.filter((value) => value.value !== AGENT_DEFAULT_REASONING_EFFORT)
|
|
22013
|
+
} : option2
|
|
21521
22014
|
) : updated;
|
|
21522
22015
|
};
|
|
21523
22016
|
normalizeLifecycle = (response) => normalizeGrokLifecycle(response);
|
|
@@ -21920,7 +22413,7 @@ function createWritableAcpStream(output2) {
|
|
|
21920
22413
|
function truncate3(value, maximumLength) {
|
|
21921
22414
|
return value.length <= maximumLength ? value : `${value.slice(0, Math.max(0, maximumLength - 1))}\u2026`;
|
|
21922
22415
|
}
|
|
21923
|
-
function
|
|
22416
|
+
function isRecord5(value) {
|
|
21924
22417
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21925
22418
|
}
|
|
21926
22419
|
function readString4(value, fallback = "") {
|
|
@@ -21948,12 +22441,12 @@ function normalizeElicitationOptions(schema) {
|
|
|
21948
22441
|
const normalized = [];
|
|
21949
22442
|
const oneOf = schema["oneOf"];
|
|
21950
22443
|
if (Array.isArray(oneOf)) {
|
|
21951
|
-
for (const
|
|
21952
|
-
if (
|
|
22444
|
+
for (const option2 of oneOf) {
|
|
22445
|
+
if (isRecord5(option2) && typeof option2["const"] === "string") {
|
|
21953
22446
|
normalized.push({
|
|
21954
|
-
description: truncate3(readString4(
|
|
21955
|
-
label: truncate3(readString4(
|
|
21956
|
-
value: truncate3(
|
|
22447
|
+
description: truncate3(readString4(option2["description"]), 500),
|
|
22448
|
+
label: truncate3(readString4(option2["title"], option2["const"]), 255),
|
|
22449
|
+
value: truncate3(option2["const"], 500)
|
|
21957
22450
|
});
|
|
21958
22451
|
}
|
|
21959
22452
|
}
|
|
@@ -21969,7 +22462,7 @@ function normalizeElicitationOptions(schema) {
|
|
|
21969
22462
|
return normalized.slice(0, 200);
|
|
21970
22463
|
}
|
|
21971
22464
|
const items = schema["items"];
|
|
21972
|
-
if (!
|
|
22465
|
+
if (!isRecord5(items)) {
|
|
21973
22466
|
return normalized;
|
|
21974
22467
|
}
|
|
21975
22468
|
const anyOf = items["anyOf"];
|
|
@@ -21982,7 +22475,7 @@ function numericString(value) {
|
|
|
21982
22475
|
return typeof value === "number" && Number.isFinite(value) ? value.toString() : "";
|
|
21983
22476
|
}
|
|
21984
22477
|
function normalizeElicitationFields(requestedSchema) {
|
|
21985
|
-
if (!
|
|
22478
|
+
if (!isRecord5(requestedSchema) || !isRecord5(requestedSchema["properties"])) {
|
|
21986
22479
|
return [];
|
|
21987
22480
|
}
|
|
21988
22481
|
const properties = requestedSchema["properties"];
|
|
@@ -21992,7 +22485,7 @@ function normalizeElicitationFields(requestedSchema) {
|
|
|
21992
22485
|
);
|
|
21993
22486
|
const normalized = [];
|
|
21994
22487
|
for (const [name, property] of Object.entries(properties)) {
|
|
21995
|
-
if (!
|
|
22488
|
+
if (!isRecord5(property)) {
|
|
21996
22489
|
continue;
|
|
21997
22490
|
}
|
|
21998
22491
|
const type = elicitationFieldType(property["type"]);
|
|
@@ -22083,7 +22576,7 @@ function validateElicitationContent(encoded, requestedSchema) {
|
|
|
22083
22576
|
"invalid_elicitation_response"
|
|
22084
22577
|
);
|
|
22085
22578
|
}
|
|
22086
|
-
if (!
|
|
22579
|
+
if (!isRecord5(decoded) || !isRecord5(requestedSchema) || !isRecord5(requestedSchema["properties"])) {
|
|
22087
22580
|
throw new AcpExecutionError(
|
|
22088
22581
|
"Elicitation response does not match the requested form",
|
|
22089
22582
|
{},
|
|
@@ -22103,7 +22596,7 @@ function validateElicitationContent(encoded, requestedSchema) {
|
|
|
22103
22596
|
const validated = {};
|
|
22104
22597
|
for (const [name, value] of Object.entries(decoded)) {
|
|
22105
22598
|
const property = properties[name];
|
|
22106
|
-
if (!
|
|
22599
|
+
if (!isRecord5(property)) {
|
|
22107
22600
|
throw new AcpExecutionError(
|
|
22108
22601
|
`Elicitation field ${name} was not requested`,
|
|
22109
22602
|
{},
|
|
@@ -22140,7 +22633,7 @@ function validateElicitationContent(encoded, requestedSchema) {
|
|
|
22140
22633
|
);
|
|
22141
22634
|
}
|
|
22142
22635
|
const allowed = normalizeElicitationOptions(property);
|
|
22143
|
-
if (allowed.length > 0 && value.some((entry) => !allowed.some((
|
|
22636
|
+
if (allowed.length > 0 && value.some((entry) => !allowed.some((option2) => option2.value === entry))) {
|
|
22144
22637
|
throw new AcpExecutionError(
|
|
22145
22638
|
`Elicitation field ${name} contains an invalid selection`,
|
|
22146
22639
|
{},
|
|
@@ -22637,7 +23130,7 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
22637
23130
|
};
|
|
22638
23131
|
nativeSessionId = () => this.#nativeSessionId;
|
|
22639
23132
|
configure = async (options) => {
|
|
22640
|
-
const existing = this.#configOptions.find((
|
|
23133
|
+
const existing = this.#configOptions.find((option2) => option2.id === options.configId);
|
|
22641
23134
|
if (existing === void 0 || existing.type !== options.valueType) {
|
|
22642
23135
|
throw new AcpExecutionError(
|
|
22643
23136
|
"The requested ACP configuration option is unavailable",
|
|
@@ -22887,10 +23380,10 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
22887
23380
|
onPermission = async (request, signal) => {
|
|
22888
23381
|
this.assertNativeSession(request.sessionId);
|
|
22889
23382
|
const interactionId = `permission-${crypto.randomUUID()}`;
|
|
22890
|
-
const options = request.options.slice(0, 20).map((
|
|
22891
|
-
kind:
|
|
22892
|
-
name: truncate3(
|
|
22893
|
-
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)
|
|
22894
23387
|
}));
|
|
22895
23388
|
if (options.length === 0) {
|
|
22896
23389
|
throw new AcpExecutionError(
|
|
@@ -22899,7 +23392,7 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
22899
23392
|
"invalid_agent_permission_request"
|
|
22900
23393
|
);
|
|
22901
23394
|
}
|
|
22902
|
-
const pending = new PendingPermission(interactionId, new Set(options.map((
|
|
23395
|
+
const pending = new PendingPermission(interactionId, new Set(options.map((option2) => option2.optionId)));
|
|
22903
23396
|
this.#pendingPermissions.set(interactionId, pending);
|
|
22904
23397
|
const abort = () => {
|
|
22905
23398
|
void this.cancelPermission(interactionId);
|
|
@@ -23109,7 +23602,7 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
23109
23602
|
}
|
|
23110
23603
|
if (update.sessionUpdate === "current_mode_update") {
|
|
23111
23604
|
this.#configOptions = this.#configOptions.map(
|
|
23112
|
-
(
|
|
23605
|
+
(option2) => option2.category === "mode" ? { ...option2, currentValue: update.currentModeId } : option2
|
|
23113
23606
|
);
|
|
23114
23607
|
this.#configRevision += 1;
|
|
23115
23608
|
await this.emitConfigUpdate();
|
|
@@ -23681,71 +24174,905 @@ async function runAcpPrompt(options) {
|
|
|
23681
24174
|
} finally {
|
|
23682
24175
|
await sessions.close();
|
|
23683
24176
|
}
|
|
23684
|
-
}
|
|
23685
|
-
|
|
23686
|
-
// src/audit/audit-store.ts
|
|
23687
|
-
import { mkdirSync as mkdirSync2 } from "node:fs";
|
|
23688
|
-
import { dirname as dirname2 } from "node:path";
|
|
23689
|
-
import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
|
|
23690
|
-
var AuditStore = class {
|
|
23691
|
-
database;
|
|
23692
|
-
constructor(path2) {
|
|
23693
|
-
mkdirSync2(dirname2(path2), { recursive: true });
|
|
23694
|
-
this.database = new DatabaseSync2(path2);
|
|
23695
|
-
this.database.exec(`
|
|
23696
|
-
CREATE TABLE IF NOT EXISTS audit_events (
|
|
23697
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23698
|
-
recorded_at TEXT NOT NULL,
|
|
23699
|
-
event TEXT NOT NULL,
|
|
23700
|
-
command_id TEXT NOT NULL,
|
|
23701
|
-
session_id TEXT NOT NULL,
|
|
23702
|
-
details_json TEXT NOT NULL DEFAULT '{}'
|
|
23703
|
-
) STRICT
|
|
23704
|
-
`);
|
|
23705
|
-
const columns = this.database.prepare("PRAGMA table_info(audit_events)").all();
|
|
23706
|
-
if (!columns.some((column) => Reflect.get(column, "name") === "details_json")) {
|
|
23707
|
-
this.database.exec("ALTER TABLE audit_events ADD COLUMN details_json TEXT NOT NULL DEFAULT '{}'");
|
|
23708
|
-
}
|
|
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
|
|
24911
|
+
});
|
|
24912
|
+
}
|
|
24913
|
+
if (response.status === 202 && isRecord7(value) && typeof value["outboundMessageId"] === "string") {
|
|
24914
|
+
return value["outboundMessageId"];
|
|
23709
24915
|
}
|
|
23710
|
-
|
|
23711
|
-
|
|
23712
|
-
|
|
23713
|
-
|
|
23714
|
-
|
|
23715
|
-
event,
|
|
23716
|
-
command_id,
|
|
23717
|
-
session_id,
|
|
23718
|
-
details_json
|
|
23719
|
-
) VALUES (?, ?, ?, ?, ?)
|
|
23720
|
-
`
|
|
23721
|
-
).run(
|
|
23722
|
-
(/* @__PURE__ */ new Date()).toISOString(),
|
|
23723
|
-
record2.event,
|
|
23724
|
-
record2.commandId,
|
|
23725
|
-
record2.sessionId,
|
|
23726
|
-
JSON.stringify(record2.details ?? {})
|
|
23727
|
-
);
|
|
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
|
+
}
|
|
23728
24921
|
}
|
|
23729
|
-
|
|
23730
|
-
|
|
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;
|
|
23731
24940
|
}
|
|
23732
|
-
|
|
23733
|
-
|
|
23734
|
-
// src/authorization/local-authorization-error.ts
|
|
23735
|
-
var LocalAuthorizationError = class extends Error {
|
|
23736
|
-
code = "local_authorization_failed";
|
|
23737
|
-
constructor(message, options = {}) {
|
|
23738
|
-
super(message, options);
|
|
23739
|
-
this.name = "LocalAuthorizationError";
|
|
24941
|
+
get socketPath() {
|
|
24942
|
+
return this.#socketPath;
|
|
23740
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
|
+
};
|
|
23741
25068
|
};
|
|
23742
25069
|
|
|
23743
25070
|
// src/pairing/pair-local-machine.ts
|
|
23744
|
-
import { randomUUID } from "node:crypto";
|
|
23745
|
-
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";
|
|
23746
25073
|
import { hostname as hostname3 } from "node:os";
|
|
23747
25074
|
import { basename, join as join14, resolve as resolve3 } from "node:path";
|
|
23748
|
-
import { fetch as
|
|
25075
|
+
import { fetch as fetch3 } from "undici";
|
|
23749
25076
|
|
|
23750
25077
|
// src/agent-catalog/agent-discovery.ts
|
|
23751
25078
|
var AgentDiscovery = class {
|
|
@@ -23853,8 +25180,8 @@ var LocalAgentInventory = class {
|
|
|
23853
25180
|
};
|
|
23854
25181
|
|
|
23855
25182
|
// src/agent-installation/managed-npm-package.ts
|
|
23856
|
-
import { mkdir, mkdtemp, open as open2, realpath as realpath2, rename, rm, stat as
|
|
23857
|
-
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";
|
|
23858
25185
|
var INSTALL_TIMEOUT_MILLISECONDS = 5 * 60 * 1e3;
|
|
23859
25186
|
var PACKAGE_METADATA_LIMIT_BYTES = 64 * 1024;
|
|
23860
25187
|
var PACKAGE_LOCK_LIMIT_BYTES = 8 * 1024 * 1024;
|
|
@@ -23901,7 +25228,7 @@ var ManagedNpmPackageError = class extends Error {
|
|
|
23901
25228
|
this.name = "ManagedNpmPackageError";
|
|
23902
25229
|
}
|
|
23903
25230
|
};
|
|
23904
|
-
function
|
|
25231
|
+
function isRecord8(value) {
|
|
23905
25232
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23906
25233
|
}
|
|
23907
25234
|
function packagePath(root, packageName) {
|
|
@@ -23909,7 +25236,7 @@ function packagePath(root, packageName) {
|
|
|
23909
25236
|
}
|
|
23910
25237
|
function isContainedPath(root, candidate) {
|
|
23911
25238
|
const difference = relative(root, candidate);
|
|
23912
|
-
return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep}`) && !
|
|
25239
|
+
return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep}`) && !isAbsolute2(difference);
|
|
23913
25240
|
}
|
|
23914
25241
|
async function readJsonRecord(path2, maximumBytes) {
|
|
23915
25242
|
try {
|
|
@@ -23923,7 +25250,7 @@ async function readJsonRecord(path2, maximumBytes) {
|
|
|
23923
25250
|
);
|
|
23924
25251
|
}
|
|
23925
25252
|
const value = JSON.parse(await handle.readFile({ encoding: "utf8" }));
|
|
23926
|
-
if (!
|
|
25253
|
+
if (!isRecord8(value)) {
|
|
23927
25254
|
throw new ManagedNpmPackageError(
|
|
23928
25255
|
"managed_package_verification_failed",
|
|
23929
25256
|
"The managed npm package metadata is invalid"
|
|
@@ -23949,7 +25276,7 @@ function readBinPath(packageMetadata, executableName) {
|
|
|
23949
25276
|
if (typeof bin === "string") {
|
|
23950
25277
|
return bin;
|
|
23951
25278
|
}
|
|
23952
|
-
if (
|
|
25279
|
+
if (isRecord8(bin) && typeof bin[executableName] === "string") {
|
|
23953
25280
|
return bin[executableName];
|
|
23954
25281
|
}
|
|
23955
25282
|
throw new ManagedNpmPackageError(
|
|
@@ -23965,7 +25292,7 @@ function verifyPackageLockEntry(lock, definition, verifyDependencyClosure) {
|
|
|
23965
25292
|
);
|
|
23966
25293
|
}
|
|
23967
25294
|
const packages = lock["packages"];
|
|
23968
|
-
if (!
|
|
25295
|
+
if (!isRecord8(packages)) {
|
|
23969
25296
|
throw new ManagedNpmPackageError(
|
|
23970
25297
|
"managed_package_verification_failed",
|
|
23971
25298
|
"The managed npm package lockfile is invalid"
|
|
@@ -23979,7 +25306,7 @@ function verifyPackageLockEntry(lock, definition, verifyDependencyClosure) {
|
|
|
23979
25306
|
if (verifyDependencyClosure && normalizedKey.length > 0) {
|
|
23980
25307
|
let resolved;
|
|
23981
25308
|
try {
|
|
23982
|
-
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") {
|
|
23983
25310
|
throw new Error("Invalid locked dependency");
|
|
23984
25311
|
}
|
|
23985
25312
|
resolved = new URL(candidate["resolved"]);
|
|
@@ -24002,7 +25329,7 @@ function verifyPackageLockEntry(lock, definition, verifyDependencyClosure) {
|
|
|
24002
25329
|
matches += 1;
|
|
24003
25330
|
}
|
|
24004
25331
|
}
|
|
24005
|
-
if (matches !== 1 || !
|
|
25332
|
+
if (matches !== 1 || !isRecord8(entry) || entry["integrity"] !== definition.integrity || entry["resolved"] !== definition.tarballUrl || entry["version"] !== definition.version) {
|
|
24006
25333
|
throw new ManagedNpmPackageError(
|
|
24007
25334
|
"managed_package_verification_failed",
|
|
24008
25335
|
"The managed npm package lockfile does not match the pinned artifact"
|
|
@@ -24075,7 +25402,7 @@ var ManagedNpmPackageInstaller = class {
|
|
|
24075
25402
|
install = async (root, definition, environment, signal) => {
|
|
24076
25403
|
signal.throwIfAborted();
|
|
24077
25404
|
try {
|
|
24078
|
-
const metadata = await
|
|
25405
|
+
const metadata = await stat3(root);
|
|
24079
25406
|
if (metadata.isDirectory()) {
|
|
24080
25407
|
return await validateManagedNpmPackage(root, definition);
|
|
24081
25408
|
}
|
|
@@ -24084,8 +25411,8 @@ var ManagedNpmPackageInstaller = class {
|
|
|
24084
25411
|
throw error61;
|
|
24085
25412
|
}
|
|
24086
25413
|
}
|
|
24087
|
-
const parent =
|
|
24088
|
-
await
|
|
25414
|
+
const parent = dirname4(root);
|
|
25415
|
+
await mkdir2(parent, { mode: 448, recursive: true });
|
|
24089
25416
|
const staging = await mkdtemp(join4(parent, `.${definition.version}.staging-`));
|
|
24090
25417
|
try {
|
|
24091
25418
|
const npm = await findExecutableOnPath(process.platform === "win32" ? "npm.cmd" : "npm", environment);
|
|
@@ -24119,7 +25446,7 @@ var ManagedNpmPackageInstaller = class {
|
|
|
24119
25446
|
NPM_CONFIG_IGNORE_SCRIPTS: "true",
|
|
24120
25447
|
NPM_CONFIG_PACKAGE_LOCK: "true",
|
|
24121
25448
|
NPM_CONFIG_REGISTRY: "https://registry.npmjs.org/",
|
|
24122
|
-
PATH: `${
|
|
25449
|
+
PATH: `${dirname4(process.execPath)}${delimiter}/usr/bin${delimiter}/bin`
|
|
24123
25450
|
};
|
|
24124
25451
|
if (definition.includeOptionalDependencies) {
|
|
24125
25452
|
installEnvironment["NPM_CONFIG_INCLUDE"] = "optional";
|
|
@@ -24342,8 +25669,8 @@ var CursorCliAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
24342
25669
|
};
|
|
24343
25670
|
|
|
24344
25671
|
// src/agent-catalog/agents/deepseek-harness-agent.ts
|
|
24345
|
-
import { realpath as realpath3, stat as
|
|
24346
|
-
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";
|
|
24347
25674
|
|
|
24348
25675
|
// src/agent-installation/deepseek-managed-package.ts
|
|
24349
25676
|
var DeepSeekHarnessManagedPackage = class extends SriManagedNpmPackageDefinition {
|
|
@@ -24361,12 +25688,12 @@ var DEEPSEEK_HARNESS_PACKAGE = new DeepSeekHarnessManagedPackage(
|
|
|
24361
25688
|
|
|
24362
25689
|
// src/agent-catalog/agents/deepseek-harness-agent.ts
|
|
24363
25690
|
async function validateAgentHome(path2) {
|
|
24364
|
-
if (!
|
|
25691
|
+
if (!isAbsolute3(path2) || normalize(path2) !== path2) {
|
|
24365
25692
|
throw new AgentProbeError("agent_environment_invalid", "The configured Agent home is invalid");
|
|
24366
25693
|
}
|
|
24367
25694
|
try {
|
|
24368
25695
|
const resolved = await realpath3(path2);
|
|
24369
|
-
const metadata = await
|
|
25696
|
+
const metadata = await stat4(resolved);
|
|
24370
25697
|
if (!metadata.isDirectory() || typeof process.getuid === "function" && metadata.uid !== process.getuid()) {
|
|
24371
25698
|
throw new Error("Agent home is not a user-owned directory");
|
|
24372
25699
|
}
|
|
@@ -24449,7 +25776,7 @@ var DeepSeekHarnessAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
24449
25776
|
|
|
24450
25777
|
// src/agent-catalog/agents/grok-build-agent.ts
|
|
24451
25778
|
import { realpath as realpath4 } from "node:fs/promises";
|
|
24452
|
-
import { isAbsolute as
|
|
25779
|
+
import { isAbsolute as isAbsolute4, join as join7, relative as relative2, sep as sep2 } from "node:path";
|
|
24453
25780
|
|
|
24454
25781
|
// src/agent-installation/grok-managed-package.ts
|
|
24455
25782
|
var GROK_BUILD_MANAGED_VERSION = "1.0.21";
|
|
@@ -24512,7 +25839,7 @@ function grokBuildManagedPackage(platform, architecture) {
|
|
|
24512
25839
|
// src/agent-catalog/agents/grok-build-agent.ts
|
|
24513
25840
|
function isContainedPath2(root, candidate) {
|
|
24514
25841
|
const difference = relative2(root, candidate);
|
|
24515
|
-
return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep2}`) && !
|
|
25842
|
+
return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep2}`) && !isAbsolute4(difference);
|
|
24516
25843
|
}
|
|
24517
25844
|
var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
24518
25845
|
adapterVersion = GROK_BUILD_MANAGED_VERSION;
|
|
@@ -24574,13 +25901,13 @@ var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
24574
25901
|
import { join as join9 } from "node:path";
|
|
24575
25902
|
|
|
24576
25903
|
// src/agent-installation/managed-agent-archive.ts
|
|
24577
|
-
import { createHash } from "node:crypto";
|
|
25904
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
24578
25905
|
import { createReadStream } from "node:fs";
|
|
24579
|
-
import { chmod, copyFile, mkdir as
|
|
24580
|
-
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";
|
|
24581
25908
|
|
|
24582
25909
|
// src/agent-installation/verified-download.ts
|
|
24583
|
-
import { fetch } from "undici";
|
|
25910
|
+
import { fetch as fetch2 } from "undici";
|
|
24584
25911
|
|
|
24585
25912
|
// src/network/environment-proxy.ts
|
|
24586
25913
|
import { EnvHttpProxyAgent } from "undici";
|
|
@@ -24632,16 +25959,16 @@ var ManagedAgentArchiveError = class extends Error {
|
|
|
24632
25959
|
this.name = "ManagedAgentArchiveError";
|
|
24633
25960
|
}
|
|
24634
25961
|
};
|
|
24635
|
-
function
|
|
25962
|
+
function isRecord9(value) {
|
|
24636
25963
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24637
25964
|
}
|
|
24638
25965
|
function isContainedPath3(root, candidate) {
|
|
24639
25966
|
const difference = relative3(root, candidate);
|
|
24640
|
-
return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep3}`) && !
|
|
25967
|
+
return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep3}`) && !isAbsolute5(difference);
|
|
24641
25968
|
}
|
|
24642
25969
|
async function hashFile(path2, signal) {
|
|
24643
25970
|
signal.throwIfAborted();
|
|
24644
|
-
const
|
|
25971
|
+
const digest2 = createHash2("sha256");
|
|
24645
25972
|
const stream = createReadStream(path2, { signal });
|
|
24646
25973
|
try {
|
|
24647
25974
|
for await (const chunk of stream) {
|
|
@@ -24652,9 +25979,9 @@ async function hashFile(path2, signal) {
|
|
|
24652
25979
|
"The managed Agent archive produced invalid bytes"
|
|
24653
25980
|
);
|
|
24654
25981
|
}
|
|
24655
|
-
|
|
25982
|
+
digest2.update(chunk);
|
|
24656
25983
|
}
|
|
24657
|
-
return
|
|
25984
|
+
return digest2.digest("hex");
|
|
24658
25985
|
} catch (error61) {
|
|
24659
25986
|
if (signal.aborted) {
|
|
24660
25987
|
signal.throwIfAborted();
|
|
@@ -24689,7 +26016,7 @@ async function readManifest(path2) {
|
|
|
24689
26016
|
);
|
|
24690
26017
|
}
|
|
24691
26018
|
const parsed = JSON.parse(await handle.readFile({ encoding: "utf8" }));
|
|
24692
|
-
if (!
|
|
26019
|
+
if (!isRecord9(parsed)) {
|
|
24693
26020
|
throw new ManagedAgentArchiveError(
|
|
24694
26021
|
"managed_archive_verification_failed",
|
|
24695
26022
|
"The managed Agent archive manifest is invalid"
|
|
@@ -24712,7 +26039,7 @@ async function readManifest(path2) {
|
|
|
24712
26039
|
async function validateManagedAgentArchive(root, definition, signal) {
|
|
24713
26040
|
try {
|
|
24714
26041
|
const rootPath = await realpath5(root);
|
|
24715
|
-
const rootMetadata = await
|
|
26042
|
+
const rootMetadata = await stat5(rootPath);
|
|
24716
26043
|
if (!rootMetadata.isDirectory() || typeof process.getuid === "function" && rootMetadata.uid !== process.getuid()) {
|
|
24717
26044
|
throw new Error("Managed Agent root is not user-owned");
|
|
24718
26045
|
}
|
|
@@ -24927,7 +26254,7 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
|
|
|
24927
26254
|
};
|
|
24928
26255
|
|
|
24929
26256
|
// src/agent-catalog/agents/workbuddy-agent.ts
|
|
24930
|
-
import { isAbsolute as
|
|
26257
|
+
import { isAbsolute as isAbsolute6, join as join11 } from "node:path";
|
|
24931
26258
|
|
|
24932
26259
|
// src/agent-installation/workbuddy-managed-package.ts
|
|
24933
26260
|
var WORKBUDDY_MANAGED_VERSION = "2.146.0";
|
|
@@ -24993,7 +26320,7 @@ var WorkBuddyAgentSpecification = class extends DirectAcpAgentDefinition {
|
|
|
24993
26320
|
}
|
|
24994
26321
|
const requestedPaths = [join11("/Applications", ...WORKBUDDY_MACOS_EXECUTABLE_PATH)];
|
|
24995
26322
|
const homeDirectory = context.environment["HOME"];
|
|
24996
|
-
if (homeDirectory !== void 0 &&
|
|
26323
|
+
if (homeDirectory !== void 0 && isAbsolute6(homeDirectory)) {
|
|
24997
26324
|
requestedPaths.unshift(join11(homeDirectory, "Applications", ...WORKBUDDY_MACOS_EXECUTABLE_PATH));
|
|
24998
26325
|
}
|
|
24999
26326
|
const executables = [];
|
|
@@ -25039,7 +26366,7 @@ import {
|
|
|
25039
26366
|
} from "@agentclientprotocol/sdk";
|
|
25040
26367
|
|
|
25041
26368
|
// src/agent-catalog/executable-discovery.ts
|
|
25042
|
-
import { isAbsolute as
|
|
26369
|
+
import { isAbsolute as isAbsolute7, join as join13 } from "node:path";
|
|
25043
26370
|
|
|
25044
26371
|
// src/agent-installation/managed-adapter-installer.ts
|
|
25045
26372
|
import { join as join12 } from "node:path";
|
|
@@ -25144,7 +26471,7 @@ async function resolveManagedAdapterExecutable(specification, context) {
|
|
|
25144
26471
|
async function resolveSpecificationExecutables(executableName, overrideVariable, resolveInstalled, resolveManaged, context) {
|
|
25145
26472
|
const override = context.environment[overrideVariable];
|
|
25146
26473
|
if (override !== void 0) {
|
|
25147
|
-
if (override.length === 0 || !
|
|
26474
|
+
if (override.length === 0 || !isAbsolute7(override)) {
|
|
25148
26475
|
return [];
|
|
25149
26476
|
}
|
|
25150
26477
|
const executable = await resolveExecutablePath(override, context.platform);
|
|
@@ -25564,8 +26891,8 @@ async function discoverLocalAgentInventory(options) {
|
|
|
25564
26891
|
// src/pairing/pair-local-machine.ts
|
|
25565
26892
|
var PAIRING_TIMEOUT_MILLISECONDS = 2e4;
|
|
25566
26893
|
var PAIRING_CODE_PATTERN = /^[A-HJ-NP-Z2-9]{4}(?:-[A-HJ-NP-Z2-9]{4}){4}$/;
|
|
25567
|
-
var
|
|
25568
|
-
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}$/;
|
|
25569
26896
|
var MAX_CONNECTION_FILE_LENGTH = 16 * 1024;
|
|
25570
26897
|
var CLAIM_RESPONSE_KEYS = ["channelId", "daemonToken", "runtimeId"];
|
|
25571
26898
|
var SAVED_CONNECTION_KEYS = ["defaultWorkspace", "channelId", "daemonToken", "relayOrigin"];
|
|
@@ -25577,36 +26904,36 @@ var PairingClientError = class extends Error {
|
|
|
25577
26904
|
this.name = "PairingClientError";
|
|
25578
26905
|
}
|
|
25579
26906
|
};
|
|
25580
|
-
function
|
|
26907
|
+
function isRecord10(value) {
|
|
25581
26908
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25582
26909
|
}
|
|
25583
26910
|
function hasExactKeys(value, expectedKeys) {
|
|
25584
26911
|
const keys = Object.keys(value);
|
|
25585
26912
|
return keys.length === expectedKeys.length && expectedKeys.every((key) => Object.hasOwn(value, key));
|
|
25586
26913
|
}
|
|
25587
|
-
function readSingleOption(arguments_,
|
|
26914
|
+
function readSingleOption(arguments_, option2) {
|
|
25588
26915
|
const values = [];
|
|
25589
26916
|
for (let index = 0; index < arguments_.length; index += 1) {
|
|
25590
|
-
if (arguments_[index] !==
|
|
26917
|
+
if (arguments_[index] !== option2) {
|
|
25591
26918
|
continue;
|
|
25592
26919
|
}
|
|
25593
26920
|
const value = arguments_[index + 1];
|
|
25594
26921
|
if (value === void 0 || value.startsWith("--")) {
|
|
25595
|
-
throw new PairingClientError("invalid_arguments", `${
|
|
26922
|
+
throw new PairingClientError("invalid_arguments", `${option2} requires a value`);
|
|
25596
26923
|
}
|
|
25597
26924
|
values.push(value);
|
|
25598
26925
|
index += 1;
|
|
25599
26926
|
}
|
|
25600
26927
|
if (values.length !== 1) {
|
|
25601
|
-
throw new PairingClientError("invalid_arguments", `${
|
|
26928
|
+
throw new PairingClientError("invalid_arguments", `${option2} must be provided exactly once`);
|
|
25602
26929
|
}
|
|
25603
26930
|
return values[0] ?? "";
|
|
25604
26931
|
}
|
|
25605
26932
|
function assertKnownArguments(arguments_) {
|
|
25606
26933
|
for (let index = 0; index < arguments_.length; index += 2) {
|
|
25607
|
-
const
|
|
25608
|
-
if (
|
|
25609
|
-
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"}`);
|
|
25610
26937
|
}
|
|
25611
26938
|
}
|
|
25612
26939
|
}
|
|
@@ -25654,7 +26981,7 @@ function parseChannelArgument(arguments_) {
|
|
|
25654
26981
|
throw new PairingClientError("invalid_arguments", "Usage: mobius start --channel <channel-id>");
|
|
25655
26982
|
}
|
|
25656
26983
|
const channelId = arguments_[1] ?? "";
|
|
25657
|
-
if (!
|
|
26984
|
+
if (!IDENTIFIER_PATTERN6.test(channelId)) {
|
|
25658
26985
|
throw new PairingClientError("invalid_channel_id", "The saved channel ID is invalid");
|
|
25659
26986
|
}
|
|
25660
26987
|
return channelId;
|
|
@@ -25662,9 +26989,9 @@ function parseChannelArgument(arguments_) {
|
|
|
25662
26989
|
async function resolveDefaultWorkspace(path2) {
|
|
25663
26990
|
const requestedWorkspace = resolve3(path2);
|
|
25664
26991
|
try {
|
|
25665
|
-
await
|
|
26992
|
+
await mkdir4(requestedWorkspace, { recursive: true, mode: 448 });
|
|
25666
26993
|
const defaultWorkspace = await realpath6(requestedWorkspace);
|
|
25667
|
-
const metadata = await
|
|
26994
|
+
const metadata = await stat6(defaultWorkspace);
|
|
25668
26995
|
if (!metadata.isDirectory()) {
|
|
25669
26996
|
throw new PairingClientError("invalid_workspace", "The default workspace is not a directory");
|
|
25670
26997
|
}
|
|
@@ -25693,9 +27020,9 @@ async function readJsonResponse(response) {
|
|
|
25693
27020
|
}
|
|
25694
27021
|
}
|
|
25695
27022
|
function readRelayError(value) {
|
|
25696
|
-
if (
|
|
27023
|
+
if (isRecord10(value)) {
|
|
25697
27024
|
const error61 = value["error"];
|
|
25698
|
-
if (
|
|
27025
|
+
if (isRecord10(error61)) {
|
|
25699
27026
|
const code = error61["code"];
|
|
25700
27027
|
const message = error61["message"];
|
|
25701
27028
|
if (typeof code === "string" && typeof message === "string") {
|
|
@@ -25706,16 +27033,16 @@ function readRelayError(value) {
|
|
|
25706
27033
|
return new PairingClientError("pairing_failed", "The relay could not pair this machine");
|
|
25707
27034
|
}
|
|
25708
27035
|
function decodeClaimResponse(value) {
|
|
25709
|
-
if (!
|
|
27036
|
+
if (!isRecord10(value) || !hasExactKeys(value, CLAIM_RESPONSE_KEYS)) {
|
|
25710
27037
|
throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
|
|
25711
27038
|
}
|
|
25712
27039
|
const channelId = value["channelId"];
|
|
25713
|
-
const
|
|
27040
|
+
const daemonToken2 = value["daemonToken"];
|
|
25714
27041
|
const runtimeId = value["runtimeId"];
|
|
25715
|
-
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)) {
|
|
25716
27043
|
throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
|
|
25717
27044
|
}
|
|
25718
|
-
return { channelId, daemonToken, runtimeId };
|
|
27045
|
+
return { channelId, daemonToken: daemonToken2, runtimeId };
|
|
25719
27046
|
}
|
|
25720
27047
|
async function claimPairing(options, defaultWorkspace, localAgents, installableAgents, signal) {
|
|
25721
27048
|
const agents = localAgents.map((agent) => ({
|
|
@@ -25728,7 +27055,7 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
|
|
|
25728
27055
|
const endpoint = mobiusApiUrl(options.relayOrigin, "/pairings/claim");
|
|
25729
27056
|
let response;
|
|
25730
27057
|
try {
|
|
25731
|
-
response = await
|
|
27058
|
+
response = await fetch3(endpoint, {
|
|
25732
27059
|
body: JSON.stringify({
|
|
25733
27060
|
agents,
|
|
25734
27061
|
installableAgents,
|
|
@@ -25750,18 +27077,18 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
|
|
|
25750
27077
|
}
|
|
25751
27078
|
return decodeClaimResponse(value);
|
|
25752
27079
|
}
|
|
25753
|
-
async function persistConnection(channelId, relayOrigin,
|
|
27080
|
+
async function persistConnection(channelId, relayOrigin, daemonToken2, defaultWorkspace) {
|
|
25754
27081
|
const connectionsDirectory = join14(readStateDirectory(), "connections");
|
|
25755
|
-
await
|
|
27082
|
+
await mkdir4(connectionsDirectory, { mode: 448, recursive: true });
|
|
25756
27083
|
const connectionPath = join14(connectionsDirectory, `${channelId}.json`);
|
|
25757
|
-
const temporaryPath = join14(connectionsDirectory, `.${channelId}.${
|
|
27084
|
+
const temporaryPath = join14(connectionsDirectory, `.${channelId}.${randomUUID3()}.tmp`);
|
|
25758
27085
|
await writeFile2(
|
|
25759
27086
|
temporaryPath,
|
|
25760
27087
|
`${JSON.stringify(
|
|
25761
27088
|
{
|
|
25762
27089
|
defaultWorkspace,
|
|
25763
27090
|
channelId,
|
|
25764
|
-
daemonToken,
|
|
27091
|
+
daemonToken: daemonToken2,
|
|
25765
27092
|
relayOrigin: relayOrigin.toString()
|
|
25766
27093
|
},
|
|
25767
27094
|
null,
|
|
@@ -25774,20 +27101,20 @@ async function persistConnection(channelId, relayOrigin, daemonToken, defaultWor
|
|
|
25774
27101
|
return connectionPath;
|
|
25775
27102
|
}
|
|
25776
27103
|
function decodeSavedConnection(value, expectedChannelId) {
|
|
25777
|
-
if (!
|
|
27104
|
+
if (!isRecord10(value) || !hasExactKeys(value, SAVED_CONNECTION_KEYS)) {
|
|
25778
27105
|
throw new PairingClientError("invalid_connection", "The saved connection is invalid");
|
|
25779
27106
|
}
|
|
25780
27107
|
const defaultWorkspace = value["defaultWorkspace"];
|
|
25781
27108
|
const channelId = value["channelId"];
|
|
25782
|
-
const
|
|
27109
|
+
const daemonToken2 = value["daemonToken"];
|
|
25783
27110
|
const relayOrigin = value["relayOrigin"];
|
|
25784
|
-
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") {
|
|
25785
27112
|
throw new PairingClientError("invalid_connection", "The saved connection is invalid");
|
|
25786
27113
|
}
|
|
25787
27114
|
return {
|
|
25788
27115
|
defaultWorkspace,
|
|
25789
27116
|
channelId,
|
|
25790
|
-
daemonToken,
|
|
27117
|
+
daemonToken: daemonToken2,
|
|
25791
27118
|
relayOrigin: parseRelayOrigin(relayOrigin)
|
|
25792
27119
|
};
|
|
25793
27120
|
}
|
|
@@ -25888,12 +27215,13 @@ async function resumeLocalMachine(arguments_, signal = new AbortController().sig
|
|
|
25888
27215
|
}
|
|
25889
27216
|
|
|
25890
27217
|
// src/run-daemon.ts
|
|
25891
|
-
import {
|
|
27218
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
27219
|
+
import { basename as basename3, join as join16 } from "node:path";
|
|
25892
27220
|
import { styleText } from "node:util";
|
|
25893
|
-
import { fetch as
|
|
27221
|
+
import { fetch as fetch6, WebSocket as WebSocket2 } from "undici";
|
|
25894
27222
|
|
|
25895
27223
|
// src/agent-catalog/publish-agent-catalog.ts
|
|
25896
|
-
import { fetch as
|
|
27224
|
+
import { fetch as fetch4 } from "undici";
|
|
25897
27225
|
var CATALOG_UPDATE_TIMEOUT_MILLISECONDS = 2e4;
|
|
25898
27226
|
var AgentCatalogPublishError = class extends Error {
|
|
25899
27227
|
code = "agent_catalog_update_failed";
|
|
@@ -25918,7 +27246,7 @@ async function publishAgentCatalog(config2, signal) {
|
|
|
25918
27246
|
let response;
|
|
25919
27247
|
const catalog = config2.catalog.read();
|
|
25920
27248
|
try {
|
|
25921
|
-
response = await
|
|
27249
|
+
response = await fetch4(catalogEndpoint(config2.relayUrl), {
|
|
25922
27250
|
body: JSON.stringify({
|
|
25923
27251
|
agents: catalog.agents.map((agent) => ({
|
|
25924
27252
|
agentPath: agent.agentIdentity.requestedPath,
|
|
@@ -26413,9 +27741,9 @@ var FixedInstallationExecutor = class {
|
|
|
26413
27741
|
};
|
|
26414
27742
|
|
|
26415
27743
|
// src/authorization/workspace-directory.ts
|
|
26416
|
-
import { readdir, realpath as realpath7, stat as
|
|
27744
|
+
import { readdir, realpath as realpath7, stat as stat7 } from "node:fs/promises";
|
|
26417
27745
|
import { homedir as homedir2 } from "node:os";
|
|
26418
|
-
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";
|
|
26419
27747
|
var WorkspaceDirectoryListing = class {
|
|
26420
27748
|
directoryId;
|
|
26421
27749
|
directoryLabel;
|
|
@@ -26467,7 +27795,7 @@ var WorkspaceDirectoryService = class {
|
|
|
26467
27795
|
}
|
|
26468
27796
|
if (id.startsWith("path-")) {
|
|
26469
27797
|
const path2 = decodePath(id, "path-");
|
|
26470
|
-
if (
|
|
27798
|
+
if (isAbsolute8(path2)) {
|
|
26471
27799
|
return path2;
|
|
26472
27800
|
}
|
|
26473
27801
|
}
|
|
@@ -26475,15 +27803,15 @@ var WorkspaceDirectoryService = class {
|
|
|
26475
27803
|
};
|
|
26476
27804
|
resolvePath = async (requested, signal) => {
|
|
26477
27805
|
signal.throwIfAborted();
|
|
26478
|
-
if (!
|
|
27806
|
+
if (!isAbsolute8(requested) || requested.includes("\0") || normalize2(requested) !== requested) {
|
|
26479
27807
|
throw new LocalAuthorizationError("The local directory path is invalid");
|
|
26480
27808
|
}
|
|
26481
27809
|
try {
|
|
26482
27810
|
const target = await realpath7(requested);
|
|
26483
27811
|
signal.throwIfAborted();
|
|
26484
|
-
const metadata = await
|
|
27812
|
+
const metadata = await stat7(target);
|
|
26485
27813
|
signal.throwIfAborted();
|
|
26486
|
-
if (!
|
|
27814
|
+
if (!isAbsolute8(target) || normalize2(target) !== target || !metadata.isDirectory()) {
|
|
26487
27815
|
throw new LocalAuthorizationError("The selected location is not a directory");
|
|
26488
27816
|
}
|
|
26489
27817
|
return target;
|
|
@@ -26499,7 +27827,7 @@ var WorkspaceDirectoryService = class {
|
|
|
26499
27827
|
};
|
|
26500
27828
|
label = (path2) => {
|
|
26501
27829
|
const suffix = relative4(homedir2(), path2);
|
|
26502
|
-
return suffix === "" ? "~" : !
|
|
27830
|
+
return suffix === "" ? "~" : !isAbsolute8(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
|
|
26503
27831
|
};
|
|
26504
27832
|
identify = async (bindingId, requestedPath, signal) => {
|
|
26505
27833
|
this.authorizeMachine(bindingId);
|
|
@@ -26539,7 +27867,7 @@ var WorkspaceDirectoryService = class {
|
|
|
26539
27867
|
}
|
|
26540
27868
|
}
|
|
26541
27869
|
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
26542
|
-
const parent =
|
|
27870
|
+
const parent = dirname6(target);
|
|
26543
27871
|
return new WorkspaceDirectoryListing(
|
|
26544
27872
|
id,
|
|
26545
27873
|
this.label(target),
|
|
@@ -26563,8 +27891,44 @@ var WorkspaceDirectoryService = class {
|
|
|
26563
27891
|
};
|
|
26564
27892
|
};
|
|
26565
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
|
+
|
|
26566
27930
|
// src/native-sessions/service.ts
|
|
26567
|
-
import { randomUUID as
|
|
27931
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
26568
27932
|
|
|
26569
27933
|
// src/native-sessions/codex-history.ts
|
|
26570
27934
|
import { spawn as spawn4 } from "node:child_process";
|
|
@@ -26880,7 +28244,7 @@ var NativeSessionService = class {
|
|
|
26880
28244
|
if (authorized === null) {
|
|
26881
28245
|
continue;
|
|
26882
28246
|
}
|
|
26883
|
-
const entryId =
|
|
28247
|
+
const entryId = randomUUID4();
|
|
26884
28248
|
if (this.#entries.size >= 5e3) {
|
|
26885
28249
|
this.#entries.clear();
|
|
26886
28250
|
}
|
|
@@ -26908,7 +28272,7 @@ var NativeSessionService = class {
|
|
|
26908
28272
|
"invalid_native_session_response"
|
|
26909
28273
|
);
|
|
26910
28274
|
}
|
|
26911
|
-
nextCursor =
|
|
28275
|
+
nextCursor = randomUUID4();
|
|
26912
28276
|
if (this.#cursors.size >= 500) {
|
|
26913
28277
|
this.#cursors.clear();
|
|
26914
28278
|
}
|
|
@@ -27126,13 +28490,13 @@ var NativeSessionService = class {
|
|
|
27126
28490
|
};
|
|
27127
28491
|
|
|
27128
28492
|
// src/prompt-artifact-resolver.ts
|
|
27129
|
-
import { createHash as
|
|
27130
|
-
import { fetch as
|
|
28493
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
28494
|
+
import { fetch as fetch5 } from "undici";
|
|
27131
28495
|
var ARTIFACT_SCHEME = "mobius-artifact:";
|
|
27132
28496
|
var ARTIFACT_DOWNLOAD_TIMEOUT_MILLISECONDS = 2e4;
|
|
27133
28497
|
var MAX_AGENT_IMAGE_BASE64_LENGTH = 4e6;
|
|
27134
28498
|
var MAX_AGENT_RESOURCE_BYTE_LENGTH = 1e6;
|
|
27135
|
-
var
|
|
28499
|
+
var IDENTIFIER_PATTERN7 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
|
|
27136
28500
|
var PromptArtifactError = class extends Error {
|
|
27137
28501
|
code;
|
|
27138
28502
|
constructor(code, message, options = {}) {
|
|
@@ -27175,7 +28539,7 @@ function parseReference(resource) {
|
|
|
27175
28539
|
const encodedByteLength2 = url2.searchParams.get("byteLength") ?? "";
|
|
27176
28540
|
const sha256 = url2.searchParams.get("sha256") ?? "";
|
|
27177
28541
|
const byteLength = Number(encodedByteLength2);
|
|
27178
|
-
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)) {
|
|
27179
28543
|
throw new PromptArtifactError("artifact_reference_invalid", "The prompt artifact reference is invalid");
|
|
27180
28544
|
}
|
|
27181
28545
|
return new PromptArtifactReference(artifactId, byteLength, sha256, resource);
|
|
@@ -27236,7 +28600,7 @@ async function download(config2, command, reference, signal) {
|
|
|
27236
28600
|
const requestSignal = AbortSignal.any([signal, timeoutSignal]);
|
|
27237
28601
|
let response;
|
|
27238
28602
|
try {
|
|
27239
|
-
response = await
|
|
28603
|
+
response = await fetch5(downloadUrl(config2, command, reference), {
|
|
27240
28604
|
dispatcher: environmentProxyDispatcher,
|
|
27241
28605
|
headers: { accept: reference.resource.mimeType },
|
|
27242
28606
|
signal: requestSignal
|
|
@@ -27256,7 +28620,7 @@ async function download(config2, command, reference, signal) {
|
|
|
27256
28620
|
);
|
|
27257
28621
|
}
|
|
27258
28622
|
const bytes = await responseBytes(response, reference.byteLength, requestSignal);
|
|
27259
|
-
if (
|
|
28623
|
+
if (createHash3("sha256").update(bytes).digest("hex") !== reference.sha256) {
|
|
27260
28624
|
throw new PromptArtifactError(
|
|
27261
28625
|
"artifact_integrity_failed",
|
|
27262
28626
|
"The prompt artifact failed integrity validation"
|
|
@@ -27401,7 +28765,7 @@ function connectRelay(url2, signal) {
|
|
|
27401
28765
|
}
|
|
27402
28766
|
|
|
27403
28767
|
// src/relay-connection/liveness.ts
|
|
27404
|
-
import { randomUUID as
|
|
28768
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
27405
28769
|
var HEARTBEAT_ACK_TIMEOUT_MILLISECONDS = 1e4;
|
|
27406
28770
|
var HEARTBEAT_INTERVAL_MILLISECONDS = 2e4;
|
|
27407
28771
|
var RelayLivenessState = class {
|
|
@@ -27489,7 +28853,7 @@ var RelayConnectionLiveness = class {
|
|
|
27489
28853
|
}
|
|
27490
28854
|
throw new Error("Heartbeat was scheduled in an invalid state");
|
|
27491
28855
|
}
|
|
27492
|
-
const heartbeatId =
|
|
28856
|
+
const heartbeatId = randomUUID5();
|
|
27493
28857
|
this.#state = new AwaitingHeartbeatAckState(
|
|
27494
28858
|
heartbeatId,
|
|
27495
28859
|
this.#timer.schedule(this.#handleTimeout, HEARTBEAT_ACK_TIMEOUT_MILLISECONDS)
|
|
@@ -27505,8 +28869,8 @@ var RelayConnectionLiveness = class {
|
|
|
27505
28869
|
|
|
27506
28870
|
// src/relay-connection/session-event-outbox.ts
|
|
27507
28871
|
import { mkdirSync as mkdirSync3 } from "node:fs";
|
|
27508
|
-
import { dirname as
|
|
27509
|
-
import { DatabaseSync as
|
|
28872
|
+
import { dirname as dirname7 } from "node:path";
|
|
28873
|
+
import { DatabaseSync as DatabaseSync4 } from "node:sqlite";
|
|
27510
28874
|
function readPendingEnvelope(row) {
|
|
27511
28875
|
if (typeof row !== "object" || row === null || Array.isArray(row)) {
|
|
27512
28876
|
throw new Error("SQLite returned an invalid session event outbox row");
|
|
@@ -27520,8 +28884,8 @@ function readPendingEnvelope(row) {
|
|
|
27520
28884
|
var SessionEventOutbox = class {
|
|
27521
28885
|
#database;
|
|
27522
28886
|
constructor(path2) {
|
|
27523
|
-
mkdirSync3(
|
|
27524
|
-
this.#database = new
|
|
28887
|
+
mkdirSync3(dirname7(path2), { recursive: true });
|
|
28888
|
+
this.#database = new DatabaseSync4(path2);
|
|
27525
28889
|
this.#database.exec(`
|
|
27526
28890
|
CREATE TABLE IF NOT EXISTS relay_session_event_outbox (
|
|
27527
28891
|
ordinal INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -27531,6 +28895,15 @@ var SessionEventOutbox = class {
|
|
|
27531
28895
|
) STRICT;
|
|
27532
28896
|
CREATE INDEX IF NOT EXISTS relay_session_event_outbox_order
|
|
27533
28897
|
ON relay_session_event_outbox(ordinal);
|
|
28898
|
+
CREATE TABLE IF NOT EXISTS relay_session_event_dead_letters (
|
|
28899
|
+
ordinal INTEGER PRIMARY KEY,
|
|
28900
|
+
event_id TEXT NOT NULL UNIQUE,
|
|
28901
|
+
session_id TEXT NOT NULL,
|
|
28902
|
+
envelope_json TEXT NOT NULL,
|
|
28903
|
+
rejection_code TEXT NOT NULL CHECK (
|
|
28904
|
+
rejection_code IN ('session_deleted', 'session_not_found')
|
|
28905
|
+
)
|
|
28906
|
+
) STRICT;
|
|
27534
28907
|
CREATE TABLE IF NOT EXISTS relay_session_event_sources (
|
|
27535
28908
|
source_key TEXT PRIMARY KEY,
|
|
27536
28909
|
next_source_seq INTEGER NOT NULL
|
|
@@ -27603,6 +28976,35 @@ var SessionEventOutbox = class {
|
|
|
27603
28976
|
WHERE event_id = ? AND session_id = ?`
|
|
27604
28977
|
).run(acknowledgement.eventId, acknowledgement.sessionId);
|
|
27605
28978
|
};
|
|
28979
|
+
quarantine = (rejection) => {
|
|
28980
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
28981
|
+
try {
|
|
28982
|
+
const insertion = this.#database.prepare(
|
|
28983
|
+
`INSERT INTO relay_session_event_dead_letters (
|
|
28984
|
+
ordinal, event_id, session_id, envelope_json, rejection_code
|
|
28985
|
+
)
|
|
28986
|
+
SELECT ordinal, event_id, session_id, envelope_json, ?
|
|
28987
|
+
FROM relay_session_event_outbox
|
|
28988
|
+
WHERE event_id = ? AND session_id = ?`
|
|
28989
|
+
).run(rejection.code, rejection.eventId, rejection.sessionId);
|
|
28990
|
+
if (insertion.changes !== 1) {
|
|
28991
|
+
this.#database.exec("COMMIT");
|
|
28992
|
+
return false;
|
|
28993
|
+
}
|
|
28994
|
+
const deletion = this.#database.prepare(
|
|
28995
|
+
`DELETE FROM relay_session_event_outbox
|
|
28996
|
+
WHERE event_id = ? AND session_id = ?`
|
|
28997
|
+
).run(rejection.eventId, rejection.sessionId);
|
|
28998
|
+
if (deletion.changes !== 1) {
|
|
28999
|
+
throw new Error("The rejected session event could not be removed from the durable outbox");
|
|
29000
|
+
}
|
|
29001
|
+
this.#database.exec("COMMIT");
|
|
29002
|
+
return true;
|
|
29003
|
+
} catch (error61) {
|
|
29004
|
+
this.#database.exec("ROLLBACK");
|
|
29005
|
+
throw error61;
|
|
29006
|
+
}
|
|
29007
|
+
};
|
|
27606
29008
|
close = () => {
|
|
27607
29009
|
this.#database.close();
|
|
27608
29010
|
};
|
|
@@ -27674,6 +29076,12 @@ var RELAY_RECONNECT_DELAY_MILLISECONDS = 500;
|
|
|
27674
29076
|
var RELAY_CONNECTION_REFRESH_MILLISECONDS = 20 * 60 * 1e3;
|
|
27675
29077
|
var ACTIVE_TURN_RECONCILIATION_TIMEOUT_MILLISECONDS = 2e4;
|
|
27676
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
|
+
}
|
|
27677
29085
|
var RelayConnectionRefreshState = class {
|
|
27678
29086
|
};
|
|
27679
29087
|
var ScheduledRelayConnectionRefreshState = class extends RelayConnectionRefreshState {
|
|
@@ -27931,7 +29339,7 @@ async function reconcileActiveTurn(config2, turn, signal) {
|
|
|
27931
29339
|
const requestSignal = AbortSignal.any([signal, timeoutSignal]);
|
|
27932
29340
|
let response;
|
|
27933
29341
|
try {
|
|
27934
|
-
response = await
|
|
29342
|
+
response = await fetch6(activeTurnReconciliationEndpoint(config2, turn), {
|
|
27935
29343
|
body: JSON.stringify({ outcome: { kind: "running" } }),
|
|
27936
29344
|
dispatcher: environmentProxyDispatcher,
|
|
27937
29345
|
headers: { "content-type": "application/json" },
|
|
@@ -28034,13 +29442,13 @@ function reportFailure(publisher, command, code, message, attemptId) {
|
|
|
28034
29442
|
);
|
|
28035
29443
|
}
|
|
28036
29444
|
function operationErrorCode(error61) {
|
|
28037
|
-
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) {
|
|
28038
29446
|
return error61.code;
|
|
28039
29447
|
}
|
|
28040
29448
|
return "session_operation_failed";
|
|
28041
29449
|
}
|
|
28042
29450
|
function operationErrorMessage(error61) {
|
|
28043
|
-
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) {
|
|
28044
29452
|
return error61.message;
|
|
28045
29453
|
}
|
|
28046
29454
|
return "The local agent operation could not be completed";
|
|
@@ -28305,6 +29713,175 @@ async function executePrompt(outbox, publisher, command, config2, directories, a
|
|
|
28305
29713
|
console.error("Mobius daemon command failed", error61);
|
|
28306
29714
|
}
|
|
28307
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
|
+
}
|
|
28308
29885
|
function waitForRelayRetry(signal, timer) {
|
|
28309
29886
|
if (signal.aborted) {
|
|
28310
29887
|
return Promise.resolve();
|
|
@@ -28341,7 +29918,7 @@ async function publishAgentCatalogUntilAvailable(config2, signal, timer) {
|
|
|
28341
29918
|
}
|
|
28342
29919
|
}
|
|
28343
29920
|
}
|
|
28344
|
-
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) {
|
|
28345
29922
|
const relayUrl = new URL(config2.relayUrl);
|
|
28346
29923
|
relayUrl.searchParams.set("liveness", "1");
|
|
28347
29924
|
const socket = await connectRelay(relayUrl, signal);
|
|
@@ -28424,6 +30001,76 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
28424
30001
|
outbox.acknowledge(decodeSessionEventAcknowledgement(encoded));
|
|
28425
30002
|
return;
|
|
28426
30003
|
}
|
|
30004
|
+
if (kind === SESSION_EVENT_REJECTED_KIND) {
|
|
30005
|
+
const rejection = decodeSessionEventRejection(encoded);
|
|
30006
|
+
if (outbox.quarantine(rejection)) {
|
|
30007
|
+
audit.record({
|
|
30008
|
+
commandId: rejection.eventId,
|
|
30009
|
+
details: { code: rejection.code },
|
|
30010
|
+
event: "session_event_rejected",
|
|
30011
|
+
sessionId: rejection.sessionId
|
|
30012
|
+
});
|
|
30013
|
+
} else {
|
|
30014
|
+
console.warn("Mobius daemon ignored a rejection for an unknown session event");
|
|
30015
|
+
}
|
|
30016
|
+
return;
|
|
30017
|
+
}
|
|
30018
|
+
if (kind === BOT_BINDING_APPROVAL_REQUEST_KIND) {
|
|
30019
|
+
const request = decodeBotExecutionBindingApprovalRequest(encoded);
|
|
30020
|
+
void grants.approve(
|
|
30021
|
+
request,
|
|
30022
|
+
config2.catalog,
|
|
30023
|
+
directories,
|
|
30024
|
+
config2.bindingId,
|
|
30025
|
+
Date.now(),
|
|
30026
|
+
connectionController.signal
|
|
30027
|
+
).then((approved) => {
|
|
30028
|
+
audit.record({
|
|
30029
|
+
commandId: request.requestId,
|
|
30030
|
+
details: {
|
|
30031
|
+
behaviorRevisionId: request.behaviorRevisionId,
|
|
30032
|
+
bindingId: request.bindingId,
|
|
30033
|
+
botId: request.botId,
|
|
30034
|
+
localGrantId: approved.localGrantId
|
|
30035
|
+
},
|
|
30036
|
+
event: "bot_binding_approved",
|
|
30037
|
+
sessionId: `bot-binding:${request.bindingId}`
|
|
30038
|
+
});
|
|
30039
|
+
if (socket.readyState === WebSocket2.OPEN) {
|
|
30040
|
+
send(socket, encodeBotExecutionBindingApprovedEvent(approved));
|
|
30041
|
+
}
|
|
30042
|
+
}).catch((error61) => {
|
|
30043
|
+
if (connectionController.signal.aborted) {
|
|
30044
|
+
return;
|
|
30045
|
+
}
|
|
30046
|
+
const code = error61 instanceof LocalBotAuthorizationError ? error61.code : "binding_incompatible";
|
|
30047
|
+
const message = error61 instanceof LocalBotAuthorizationError ? error61.message : "The local execution target is incompatible";
|
|
30048
|
+
grants.recordUnavailable(request, code, message, Date.now());
|
|
30049
|
+
audit.record({
|
|
30050
|
+
commandId: request.requestId,
|
|
30051
|
+
details: { bindingId: request.bindingId, botId: request.botId, code },
|
|
30052
|
+
event: "bot_binding_unavailable",
|
|
30053
|
+
sessionId: `bot-binding:${request.bindingId}`
|
|
30054
|
+
});
|
|
30055
|
+
if (socket.readyState === WebSocket2.OPEN) {
|
|
30056
|
+
send(
|
|
30057
|
+
socket,
|
|
30058
|
+
encodeBotExecutionBindingUnavailableEvent(
|
|
30059
|
+
new BotExecutionBindingUnavailableEvent(
|
|
30060
|
+
request.requestId,
|
|
30061
|
+
request.botId,
|
|
30062
|
+
request.behaviorRevisionId,
|
|
30063
|
+
request.bindingId,
|
|
30064
|
+
request.bindingRevision,
|
|
30065
|
+
code,
|
|
30066
|
+
message
|
|
30067
|
+
)
|
|
30068
|
+
)
|
|
30069
|
+
);
|
|
30070
|
+
}
|
|
30071
|
+
});
|
|
30072
|
+
return;
|
|
30073
|
+
}
|
|
28427
30074
|
if (kind === NATIVE_SESSION_CANCEL_KIND) {
|
|
28428
30075
|
const command2 = decodeNativeSessionCancel(encoded);
|
|
28429
30076
|
const pending = nativeRequests.get(command2.requestId);
|
|
@@ -28622,6 +30269,44 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
28622
30269
|
});
|
|
28623
30270
|
return;
|
|
28624
30271
|
}
|
|
30272
|
+
if (kind === BOT_SESSION_PROMPT_KIND) {
|
|
30273
|
+
const command2 = decodeBotSessionPromptCommand(encoded);
|
|
30274
|
+
if (activeTurns.has(command2.commandId)) {
|
|
30275
|
+
return;
|
|
30276
|
+
}
|
|
30277
|
+
const receipt2 = outbox.claimExecution(command2.commandId, command2.sessionId, encoded);
|
|
30278
|
+
if (receipt2.kind === "duplicate") {
|
|
30279
|
+
return;
|
|
30280
|
+
}
|
|
30281
|
+
const turn2 = new ActiveDaemonTurn(command2, receipt2.attemptId);
|
|
30282
|
+
activeTurns.set(command2.commandId, turn2);
|
|
30283
|
+
activeAttemptIds.set(command2.sessionId, receipt2.attemptId);
|
|
30284
|
+
void executeBotPrompt(
|
|
30285
|
+
outbox,
|
|
30286
|
+
publisher,
|
|
30287
|
+
command2,
|
|
30288
|
+
config2,
|
|
30289
|
+
directories,
|
|
30290
|
+
audit,
|
|
30291
|
+
sessions,
|
|
30292
|
+
grants,
|
|
30293
|
+
contexts,
|
|
30294
|
+
applicator,
|
|
30295
|
+
ipc,
|
|
30296
|
+
receipt2.attemptId,
|
|
30297
|
+
turn2.signal
|
|
30298
|
+
).catch((error61) => {
|
|
30299
|
+
console.error("Mobius daemon Bot turn failed", error61);
|
|
30300
|
+
}).finally(() => {
|
|
30301
|
+
activeTurns.delete(command2.commandId);
|
|
30302
|
+
if (activeAttemptIds.get(command2.sessionId) === receipt2.attemptId) {
|
|
30303
|
+
activeAttemptIds.delete(command2.sessionId);
|
|
30304
|
+
}
|
|
30305
|
+
turn2.finish();
|
|
30306
|
+
connectionRefresh.afterTurnFinished();
|
|
30307
|
+
});
|
|
30308
|
+
return;
|
|
30309
|
+
}
|
|
28625
30310
|
if (kind !== SESSION_PROMPT_KIND) {
|
|
28626
30311
|
throw new Error("Unsupported protocol message");
|
|
28627
30312
|
}
|
|
@@ -28712,6 +30397,10 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
|
|
|
28712
30397
|
const sessionStore = new SqliteAcpSessionStore(config2.auditDatabasePath);
|
|
28713
30398
|
const outbox = new SessionEventOutbox(config2.auditDatabasePath);
|
|
28714
30399
|
const publisher = new DaemonSessionEventPublisher(outbox);
|
|
30400
|
+
const grants = new LocalBotGrantStore(config2.auditDatabasePath);
|
|
30401
|
+
const contexts = new BotExecutionContextRegistry();
|
|
30402
|
+
const applicator = new EmbeddedBotContextApplicator();
|
|
30403
|
+
const ipc = new BotOutboundIpcServer(botIpcSocketPath(), config2.relayUrl, contexts);
|
|
28715
30404
|
const activeTurns = /* @__PURE__ */ new Map();
|
|
28716
30405
|
const activeAttemptIds = /* @__PURE__ */ new Map();
|
|
28717
30406
|
const recordSessionEvent = (sessionId, payload) => {
|
|
@@ -28750,6 +30439,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
|
|
|
28750
30439
|
};
|
|
28751
30440
|
const catalogPublication = publishAgentCatalogUntilAvailable(config2, signal, timer);
|
|
28752
30441
|
try {
|
|
30442
|
+
await ipc.listen(signal);
|
|
28753
30443
|
while (!signal.aborted) {
|
|
28754
30444
|
try {
|
|
28755
30445
|
await runRelayConnection(
|
|
@@ -28762,6 +30452,10 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
|
|
|
28762
30452
|
nativeSessions,
|
|
28763
30453
|
outbox,
|
|
28764
30454
|
publisher,
|
|
30455
|
+
grants,
|
|
30456
|
+
contexts,
|
|
30457
|
+
applicator,
|
|
30458
|
+
ipc,
|
|
28765
30459
|
activeTurns,
|
|
28766
30460
|
activeAttemptIds,
|
|
28767
30461
|
announceConnection,
|
|
@@ -28793,12 +30487,20 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
|
|
|
28793
30487
|
await installations.close();
|
|
28794
30488
|
} finally {
|
|
28795
30489
|
try {
|
|
28796
|
-
await
|
|
30490
|
+
await ipc.close();
|
|
28797
30491
|
} finally {
|
|
28798
30492
|
try {
|
|
28799
|
-
|
|
30493
|
+
await sessions.close();
|
|
28800
30494
|
} finally {
|
|
28801
|
-
|
|
30495
|
+
try {
|
|
30496
|
+
sessionStore.close();
|
|
30497
|
+
} finally {
|
|
30498
|
+
try {
|
|
30499
|
+
grants.close();
|
|
30500
|
+
} finally {
|
|
30501
|
+
outbox.close();
|
|
30502
|
+
}
|
|
30503
|
+
}
|
|
28802
30504
|
}
|
|
28803
30505
|
}
|
|
28804
30506
|
}
|
|
@@ -28808,9 +30510,13 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
|
|
|
28808
30510
|
export {
|
|
28809
30511
|
AcpExecutionError,
|
|
28810
30512
|
AuditStore,
|
|
30513
|
+
BotExecutionContextRegistry,
|
|
30514
|
+
BotMessageCommandError,
|
|
30515
|
+
BotOutboundIpcServer,
|
|
28811
30516
|
LocalAuthorizationError,
|
|
28812
30517
|
PairingClientError,
|
|
28813
30518
|
createAcpClient,
|
|
30519
|
+
executeBotMessageCommand,
|
|
28814
30520
|
loadDaemonConfig,
|
|
28815
30521
|
pairLocalMachine,
|
|
28816
30522
|
resumeLocalMachine,
|