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