@moxt-ai/mobius 0.0.20 → 0.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bots/bot-context-applicator.d.ts +14 -0
- package/dist/bots/bot-context-applicator.d.ts.map +1 -0
- package/dist/bots/bot-context-applicator.js +32 -0
- package/dist/bots/bot-context-applicator.js.map +1 -0
- package/dist/bots/bot-execution-context.d.ts +20 -0
- package/dist/bots/bot-execution-context.d.ts.map +1 -0
- package/dist/bots/bot-execution-context.js +82 -0
- package/dist/bots/bot-execution-context.js.map +1 -0
- package/dist/bots/bot-message-command.d.ts +6 -0
- package/dist/bots/bot-message-command.d.ts.map +1 -0
- package/dist/bots/bot-message-command.js +140 -0
- package/dist/bots/bot-message-command.js.map +1 -0
- package/dist/bots/bot-outbound-ipc.d.ts +12 -0
- package/dist/bots/bot-outbound-ipc.d.ts.map +1 -0
- package/dist/bots/bot-outbound-ipc.js +245 -0
- package/dist/bots/bot-outbound-ipc.js.map +1 -0
- package/dist/bots/local-bot-grant-store.d.ts +34 -0
- package/dist/bots/local-bot-grant-store.d.ts.map +1 -0
- package/dist/bots/local-bot-grant-store.js +263 -0
- package/dist/bots/local-bot-grant-store.js.map +1 -0
- package/dist/cli.js +1924 -209
- package/dist/cli.js.map +4 -4
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1970 -264
- package/dist/index.js.map +4 -4
- package/dist/prompt-artifact-resolver.d.ts +8 -2
- package/dist/prompt-artifact-resolver.d.ts.map +1 -1
- package/dist/prompt-artifact-resolver.js.map +1 -1
- package/dist/relay-connection/session-event-outbox.d.ts +2 -1
- package/dist/relay-connection/session-event-outbox.d.ts.map +1 -1
- package/dist/relay-connection/session-event-outbox.js +39 -0
- package/dist/relay-connection/session-event-outbox.js.map +1 -1
- package/dist/run-daemon.d.ts.map +1 -1
- package/dist/run-daemon.js +246 -8
- package/dist/run-daemon.js.map +1 -1
- package/package.json +1 -1
package/dist/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._~-]+)*$/;
|
|
@@ -22464,13 +23103,18 @@ var decodeNativeSessionCancel = (encoded) => decode4(nativeSessionCancelSchema,
|
|
|
22464
23103
|
var SESSION_EVENT_KIND = "session.event";
|
|
22465
23104
|
var SESSION_EVENT_ACK_KIND = "session.event.ack";
|
|
22466
23105
|
var SESSION_EVENT_COMMITTED_KIND = "session.event.committed";
|
|
22467
|
-
var
|
|
23106
|
+
var SESSION_EVENT_REJECTED_KIND = "session.event.rejected";
|
|
23107
|
+
var SessionEventRejectionCode = {
|
|
23108
|
+
SessionDeleted: "session_deleted",
|
|
23109
|
+
SessionNotFound: "session_not_found"
|
|
23110
|
+
};
|
|
23111
|
+
var IDENTIFIER_PATTERN4 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
|
|
22468
23112
|
var CURSOR_PATTERN = /^[A-Za-z0-9_-]{1,512}$/;
|
|
22469
23113
|
var MAX_RECORDED_EVENT_LENGTH = 8 * 1024 * 1024;
|
|
22470
23114
|
var DECIMAL_SEQUENCE_PATTERN = /^(?:0|[1-9][0-9]*)$/;
|
|
22471
23115
|
var eventSourceSchema = external_exports.discriminatedUnion("kind", [
|
|
22472
23116
|
external_exports.strictObject({
|
|
22473
|
-
attemptId: external_exports.string().min(1).max(128).regex(
|
|
23117
|
+
attemptId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
|
|
22474
23118
|
kind: external_exports.literal("attempt"),
|
|
22475
23119
|
sourceSeq: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN)
|
|
22476
23120
|
}).readonly(),
|
|
@@ -22480,29 +23124,35 @@ var eventSourceSchema = external_exports.discriminatedUnion("kind", [
|
|
|
22480
23124
|
}).readonly()
|
|
22481
23125
|
]);
|
|
22482
23126
|
var eventEnvelopeSchema = external_exports.strictObject({
|
|
22483
|
-
eventId: external_exports.string().min(1).max(128).regex(
|
|
23127
|
+
eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
|
|
22484
23128
|
kind: external_exports.literal(SESSION_EVENT_KIND),
|
|
22485
23129
|
payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
|
|
22486
|
-
sessionId: external_exports.string().min(1).max(128).regex(
|
|
23130
|
+
sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
|
|
22487
23131
|
source: eventSourceSchema
|
|
22488
23132
|
}).readonly();
|
|
22489
23133
|
var committedEventSchema = external_exports.strictObject({
|
|
22490
23134
|
cursor: external_exports.string().min(1).max(512).regex(CURSOR_PATTERN),
|
|
22491
|
-
eventId: external_exports.string().min(1).max(128).regex(
|
|
23135
|
+
eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
|
|
22492
23136
|
kind: external_exports.literal(SESSION_EVENT_COMMITTED_KIND),
|
|
22493
23137
|
payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
|
|
22494
23138
|
recordedAt: external_exports.string().datetime({ offset: true }),
|
|
22495
23139
|
sequence: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN),
|
|
22496
|
-
sessionId: external_exports.string().min(1).max(128).regex(
|
|
23140
|
+
sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
|
|
22497
23141
|
source: eventSourceSchema
|
|
22498
23142
|
}).readonly();
|
|
22499
23143
|
var eventAcknowledgementSchema = external_exports.strictObject({
|
|
22500
23144
|
cursor: external_exports.string().min(1).max(512).regex(CURSOR_PATTERN),
|
|
22501
23145
|
duplicate: external_exports.boolean(),
|
|
22502
|
-
eventId: external_exports.string().min(1).max(128).regex(
|
|
23146
|
+
eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
|
|
22503
23147
|
kind: external_exports.literal(SESSION_EVENT_ACK_KIND),
|
|
22504
23148
|
sequence: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN),
|
|
22505
|
-
sessionId: external_exports.string().min(1).max(128).regex(
|
|
23149
|
+
sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4)
|
|
23150
|
+
}).readonly();
|
|
23151
|
+
var eventRejectionSchema = external_exports.strictObject({
|
|
23152
|
+
code: external_exports.enum(SessionEventRejectionCode),
|
|
23153
|
+
eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
|
|
23154
|
+
kind: external_exports.literal(SESSION_EVENT_REJECTED_KIND),
|
|
23155
|
+
sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4)
|
|
22506
23156
|
}).readonly();
|
|
22507
23157
|
function decode5(encoded, schema) {
|
|
22508
23158
|
let value;
|
|
@@ -22530,6 +23180,7 @@ var encode4 = (message, schema) => {
|
|
|
22530
23180
|
};
|
|
22531
23181
|
var encodeSessionEventEnvelope = (message) => encode4(message, eventEnvelopeSchema);
|
|
22532
23182
|
var decodeSessionEventAcknowledgement = (encoded) => decode5(encoded, eventAcknowledgementSchema);
|
|
23183
|
+
var decodeSessionEventRejection = (encoded) => decode5(encoded, eventRejectionSchema);
|
|
22533
23184
|
|
|
22534
23185
|
// src/config.ts
|
|
22535
23186
|
function loadDefaultWorkspace() {
|
|
@@ -22550,15 +23201,15 @@ function createDaemonConfig(connection, agents = [], installableAgents = []) {
|
|
|
22550
23201
|
}
|
|
22551
23202
|
|
|
22552
23203
|
// src/pairing/pair-local-machine.ts
|
|
22553
|
-
import { randomUUID } from "node:crypto";
|
|
23204
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
22554
23205
|
import { mkdir as mkdir3, open as open4, realpath as realpath6, rename as rename3, stat as stat5, writeFile as writeFile2 } from "node:fs/promises";
|
|
22555
23206
|
import { hostname as hostname3 } from "node:os";
|
|
22556
23207
|
import { basename, join as join14, resolve as resolve3 } from "node:path";
|
|
22557
23208
|
import { fetch as fetch2 } from "undici";
|
|
22558
23209
|
var PAIRING_TIMEOUT_MILLISECONDS = 2e4;
|
|
22559
23210
|
var PAIRING_CODE_PATTERN = /^[A-HJ-NP-Z2-9]{4}(?:-[A-HJ-NP-Z2-9]{4}){4}$/;
|
|
22560
|
-
var
|
|
22561
|
-
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}$/;
|
|
22562
23213
|
var MAX_CONNECTION_FILE_LENGTH = 16 * 1024;
|
|
22563
23214
|
var CLAIM_RESPONSE_KEYS = ["channelId", "daemonToken", "runtimeId"];
|
|
22564
23215
|
var SAVED_CONNECTION_KEYS = ["defaultWorkspace", "channelId", "daemonToken", "relayOrigin"];
|
|
@@ -22570,36 +23221,36 @@ var PairingClientError = class extends Error {
|
|
|
22570
23221
|
this.name = "PairingClientError";
|
|
22571
23222
|
}
|
|
22572
23223
|
};
|
|
22573
|
-
function
|
|
23224
|
+
function isRecord6(value) {
|
|
22574
23225
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22575
23226
|
}
|
|
22576
23227
|
function hasExactKeys(value, expectedKeys) {
|
|
22577
23228
|
const keys = Object.keys(value);
|
|
22578
23229
|
return keys.length === expectedKeys.length && expectedKeys.every((key) => Object.hasOwn(value, key));
|
|
22579
23230
|
}
|
|
22580
|
-
function readSingleOption(arguments_,
|
|
23231
|
+
function readSingleOption(arguments_, option2) {
|
|
22581
23232
|
const values = [];
|
|
22582
23233
|
for (let index = 0; index < arguments_.length; index += 1) {
|
|
22583
|
-
if (arguments_[index] !==
|
|
23234
|
+
if (arguments_[index] !== option2) {
|
|
22584
23235
|
continue;
|
|
22585
23236
|
}
|
|
22586
23237
|
const value = arguments_[index + 1];
|
|
22587
23238
|
if (value === void 0 || value.startsWith("--")) {
|
|
22588
|
-
throw new PairingClientError("invalid_arguments", `${
|
|
23239
|
+
throw new PairingClientError("invalid_arguments", `${option2} requires a value`);
|
|
22589
23240
|
}
|
|
22590
23241
|
values.push(value);
|
|
22591
23242
|
index += 1;
|
|
22592
23243
|
}
|
|
22593
23244
|
if (values.length !== 1) {
|
|
22594
|
-
throw new PairingClientError("invalid_arguments", `${
|
|
23245
|
+
throw new PairingClientError("invalid_arguments", `${option2} must be provided exactly once`);
|
|
22595
23246
|
}
|
|
22596
23247
|
return values[0] ?? "";
|
|
22597
23248
|
}
|
|
22598
23249
|
function assertKnownArguments(arguments_) {
|
|
22599
23250
|
for (let index = 0; index < arguments_.length; index += 2) {
|
|
22600
|
-
const
|
|
22601
|
-
if (
|
|
22602
|
-
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"}`);
|
|
22603
23254
|
}
|
|
22604
23255
|
}
|
|
22605
23256
|
}
|
|
@@ -22647,7 +23298,7 @@ function parseChannelArgument(arguments_) {
|
|
|
22647
23298
|
throw new PairingClientError("invalid_arguments", "Usage: mobius start --channel <channel-id>");
|
|
22648
23299
|
}
|
|
22649
23300
|
const channelId = arguments_[1] ?? "";
|
|
22650
|
-
if (!
|
|
23301
|
+
if (!IDENTIFIER_PATTERN5.test(channelId)) {
|
|
22651
23302
|
throw new PairingClientError("invalid_channel_id", "The saved channel ID is invalid");
|
|
22652
23303
|
}
|
|
22653
23304
|
return channelId;
|
|
@@ -22686,9 +23337,9 @@ async function readJsonResponse(response) {
|
|
|
22686
23337
|
}
|
|
22687
23338
|
}
|
|
22688
23339
|
function readRelayError(value) {
|
|
22689
|
-
if (
|
|
23340
|
+
if (isRecord6(value)) {
|
|
22690
23341
|
const error61 = value["error"];
|
|
22691
|
-
if (
|
|
23342
|
+
if (isRecord6(error61)) {
|
|
22692
23343
|
const code = error61["code"];
|
|
22693
23344
|
const message = error61["message"];
|
|
22694
23345
|
if (typeof code === "string" && typeof message === "string") {
|
|
@@ -22699,16 +23350,16 @@ function readRelayError(value) {
|
|
|
22699
23350
|
return new PairingClientError("pairing_failed", "The relay could not pair this machine");
|
|
22700
23351
|
}
|
|
22701
23352
|
function decodeClaimResponse(value) {
|
|
22702
|
-
if (!
|
|
23353
|
+
if (!isRecord6(value) || !hasExactKeys(value, CLAIM_RESPONSE_KEYS)) {
|
|
22703
23354
|
throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
|
|
22704
23355
|
}
|
|
22705
23356
|
const channelId = value["channelId"];
|
|
22706
|
-
const
|
|
23357
|
+
const daemonToken2 = value["daemonToken"];
|
|
22707
23358
|
const runtimeId = value["runtimeId"];
|
|
22708
|
-
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)) {
|
|
22709
23360
|
throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
|
|
22710
23361
|
}
|
|
22711
|
-
return { channelId, daemonToken, runtimeId };
|
|
23362
|
+
return { channelId, daemonToken: daemonToken2, runtimeId };
|
|
22712
23363
|
}
|
|
22713
23364
|
async function claimPairing(options, defaultWorkspace, localAgents, installableAgents, signal) {
|
|
22714
23365
|
const agents = localAgents.map((agent) => ({
|
|
@@ -22743,18 +23394,18 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
|
|
|
22743
23394
|
}
|
|
22744
23395
|
return decodeClaimResponse(value);
|
|
22745
23396
|
}
|
|
22746
|
-
async function persistConnection(channelId, relayOrigin,
|
|
23397
|
+
async function persistConnection(channelId, relayOrigin, daemonToken2, defaultWorkspace) {
|
|
22747
23398
|
const connectionsDirectory = join14(readStateDirectory(), "connections");
|
|
22748
23399
|
await mkdir3(connectionsDirectory, { mode: 448, recursive: true });
|
|
22749
23400
|
const connectionPath = join14(connectionsDirectory, `${channelId}.json`);
|
|
22750
|
-
const temporaryPath = join14(connectionsDirectory, `.${channelId}.${
|
|
23401
|
+
const temporaryPath = join14(connectionsDirectory, `.${channelId}.${randomUUID2()}.tmp`);
|
|
22751
23402
|
await writeFile2(
|
|
22752
23403
|
temporaryPath,
|
|
22753
23404
|
`${JSON.stringify(
|
|
22754
23405
|
{
|
|
22755
23406
|
defaultWorkspace,
|
|
22756
23407
|
channelId,
|
|
22757
|
-
daemonToken,
|
|
23408
|
+
daemonToken: daemonToken2,
|
|
22758
23409
|
relayOrigin: relayOrigin.toString()
|
|
22759
23410
|
},
|
|
22760
23411
|
null,
|
|
@@ -22767,20 +23418,20 @@ async function persistConnection(channelId, relayOrigin, daemonToken, defaultWor
|
|
|
22767
23418
|
return connectionPath;
|
|
22768
23419
|
}
|
|
22769
23420
|
function decodeSavedConnection(value, expectedChannelId) {
|
|
22770
|
-
if (!
|
|
23421
|
+
if (!isRecord6(value) || !hasExactKeys(value, SAVED_CONNECTION_KEYS)) {
|
|
22771
23422
|
throw new PairingClientError("invalid_connection", "The saved connection is invalid");
|
|
22772
23423
|
}
|
|
22773
23424
|
const defaultWorkspace = value["defaultWorkspace"];
|
|
22774
23425
|
const channelId = value["channelId"];
|
|
22775
|
-
const
|
|
23426
|
+
const daemonToken2 = value["daemonToken"];
|
|
22776
23427
|
const relayOrigin = value["relayOrigin"];
|
|
22777
|
-
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") {
|
|
22778
23429
|
throw new PairingClientError("invalid_connection", "The saved connection is invalid");
|
|
22779
23430
|
}
|
|
22780
23431
|
return {
|
|
22781
23432
|
defaultWorkspace,
|
|
22782
23433
|
channelId,
|
|
22783
|
-
daemonToken,
|
|
23434
|
+
daemonToken: daemonToken2,
|
|
22784
23435
|
relayOrigin: parseRelayOrigin(relayOrigin)
|
|
22785
23436
|
};
|
|
22786
23437
|
}
|
|
@@ -22881,9 +23532,10 @@ async function resumeLocalMachine(arguments_, signal = new AbortController().sig
|
|
|
22881
23532
|
}
|
|
22882
23533
|
|
|
22883
23534
|
// src/run-daemon.ts
|
|
22884
|
-
import {
|
|
23535
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
23536
|
+
import { basename as basename3, join as join16 } from "node:path";
|
|
22885
23537
|
import { styleText } from "node:util";
|
|
22886
|
-
import { fetch as
|
|
23538
|
+
import { fetch as fetch6, WebSocket as WebSocket2 } from "undici";
|
|
22887
23539
|
|
|
22888
23540
|
// src/acp/session-manager.ts
|
|
22889
23541
|
import { spawn as spawn3 } from "node:child_process";
|
|
@@ -22896,7 +23548,7 @@ import {
|
|
|
22896
23548
|
|
|
22897
23549
|
// src/acp/activity.ts
|
|
22898
23550
|
var TRUNCATION_MARKER = "\n\u2026 output truncated by Mobius";
|
|
22899
|
-
function
|
|
23551
|
+
function isRecord7(value) {
|
|
22900
23552
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22901
23553
|
}
|
|
22902
23554
|
var AcpActivity = class _AcpActivity {
|
|
@@ -23163,7 +23815,7 @@ function contentPhase(content) {
|
|
|
23163
23815
|
return "";
|
|
23164
23816
|
}
|
|
23165
23817
|
const codex = metadata["codex"];
|
|
23166
|
-
if (!
|
|
23818
|
+
if (!isRecord7(codex)) {
|
|
23167
23819
|
return "";
|
|
23168
23820
|
}
|
|
23169
23821
|
const phase = codex["phase"];
|
|
@@ -23401,7 +24053,7 @@ var SessionConfigProtocolError = class extends Error {
|
|
|
23401
24053
|
this.name = "SessionConfigProtocolError";
|
|
23402
24054
|
}
|
|
23403
24055
|
};
|
|
23404
|
-
function
|
|
24056
|
+
function isRecord8(value) {
|
|
23405
24057
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23406
24058
|
}
|
|
23407
24059
|
function readString2(value, fallback = "") {
|
|
@@ -23413,13 +24065,13 @@ function truncate2(value, maximum) {
|
|
|
23413
24065
|
function readBoolean(value, fallback = false) {
|
|
23414
24066
|
return typeof value === "boolean" ? value : fallback;
|
|
23415
24067
|
}
|
|
23416
|
-
function normalizeConfigValue(
|
|
24068
|
+
function normalizeConfigValue(option2, groupId = "", groupName = "") {
|
|
23417
24069
|
return {
|
|
23418
|
-
description: truncate2(readString2(
|
|
24070
|
+
description: truncate2(readString2(option2["description"]), 500),
|
|
23419
24071
|
groupId: truncate2(groupId, 128),
|
|
23420
24072
|
groupName: truncate2(groupName, 255),
|
|
23421
|
-
name: truncate2(readString2(
|
|
23422
|
-
value: truncate2(readString2(
|
|
24073
|
+
name: truncate2(readString2(option2["name"], readString2(option2["value"])), 255),
|
|
24074
|
+
value: truncate2(readString2(option2["value"]), 500)
|
|
23423
24075
|
};
|
|
23424
24076
|
}
|
|
23425
24077
|
function normalizeConfigValues(value) {
|
|
@@ -23428,7 +24080,7 @@ function normalizeConfigValues(value) {
|
|
|
23428
24080
|
}
|
|
23429
24081
|
const normalized = [];
|
|
23430
24082
|
for (const entry of value) {
|
|
23431
|
-
if (!
|
|
24083
|
+
if (!isRecord8(entry)) {
|
|
23432
24084
|
continue;
|
|
23433
24085
|
}
|
|
23434
24086
|
const groupedOptions = entry["options"];
|
|
@@ -23436,7 +24088,7 @@ function normalizeConfigValues(value) {
|
|
|
23436
24088
|
const groupId = readString2(entry["group"]);
|
|
23437
24089
|
const groupName = readString2(entry["name"]);
|
|
23438
24090
|
for (const groupedOption of groupedOptions) {
|
|
23439
|
-
if (
|
|
24091
|
+
if (isRecord8(groupedOption)) {
|
|
23440
24092
|
normalized.push(normalizeConfigValue(groupedOption, groupId, groupName));
|
|
23441
24093
|
}
|
|
23442
24094
|
}
|
|
@@ -23449,21 +24101,21 @@ function normalizeConfigValues(value) {
|
|
|
23449
24101
|
function normalizeConfigOptions(value, modes) {
|
|
23450
24102
|
const normalized = [];
|
|
23451
24103
|
if (Array.isArray(value)) {
|
|
23452
|
-
for (const
|
|
23453
|
-
if (!
|
|
24104
|
+
for (const option2 of value) {
|
|
24105
|
+
if (!isRecord8(option2)) {
|
|
23454
24106
|
continue;
|
|
23455
24107
|
}
|
|
23456
|
-
const id = truncate2(readString2(
|
|
23457
|
-
const name = truncate2(readString2(
|
|
24108
|
+
const id = truncate2(readString2(option2["id"]), 128);
|
|
24109
|
+
const name = truncate2(readString2(option2["name"], id), 255);
|
|
23458
24110
|
if (id.length === 0 || name.length === 0) {
|
|
23459
24111
|
continue;
|
|
23460
24112
|
}
|
|
23461
|
-
if (
|
|
24113
|
+
if (option2["type"] === "boolean") {
|
|
23462
24114
|
normalized.push({
|
|
23463
|
-
booleanValue: readBoolean(
|
|
23464
|
-
category: truncate2(readString2(
|
|
24115
|
+
booleanValue: readBoolean(option2["currentValue"]),
|
|
24116
|
+
category: truncate2(readString2(option2["category"]), 128),
|
|
23465
24117
|
currentValue: "",
|
|
23466
|
-
description: truncate2(readString2(
|
|
24118
|
+
description: truncate2(readString2(option2["description"]), 500),
|
|
23467
24119
|
id,
|
|
23468
24120
|
name,
|
|
23469
24121
|
type: "boolean",
|
|
@@ -23471,15 +24123,15 @@ function normalizeConfigOptions(value, modes) {
|
|
|
23471
24123
|
});
|
|
23472
24124
|
continue;
|
|
23473
24125
|
}
|
|
23474
|
-
if (
|
|
23475
|
-
const values = normalizeConfigValues(
|
|
23476
|
-
const currentValue = truncate2(readString2(
|
|
24126
|
+
if (option2["type"] === "select") {
|
|
24127
|
+
const values = normalizeConfigValues(option2["options"]);
|
|
24128
|
+
const currentValue = truncate2(readString2(option2["currentValue"]), 500);
|
|
23477
24129
|
if (currentValue.length > 0 && values.some((entry) => entry.value === currentValue)) {
|
|
23478
24130
|
normalized.push({
|
|
23479
24131
|
booleanValue: false,
|
|
23480
|
-
category: truncate2(readString2(
|
|
24132
|
+
category: truncate2(readString2(option2["category"]), 128),
|
|
23481
24133
|
currentValue,
|
|
23482
|
-
description: truncate2(readString2(
|
|
24134
|
+
description: truncate2(readString2(option2["description"]), 500),
|
|
23483
24135
|
id,
|
|
23484
24136
|
name,
|
|
23485
24137
|
type: "select",
|
|
@@ -23489,12 +24141,12 @@ function normalizeConfigOptions(value, modes) {
|
|
|
23489
24141
|
}
|
|
23490
24142
|
}
|
|
23491
24143
|
}
|
|
23492
|
-
if (
|
|
24144
|
+
if (isRecord8(modes)) {
|
|
23493
24145
|
const values = [];
|
|
23494
24146
|
const availableModes = modes["availableModes"];
|
|
23495
24147
|
if (Array.isArray(availableModes)) {
|
|
23496
24148
|
for (const mode of availableModes) {
|
|
23497
|
-
if (!
|
|
24149
|
+
if (!isRecord8(mode)) {
|
|
23498
24150
|
continue;
|
|
23499
24151
|
}
|
|
23500
24152
|
const id = truncate2(readString2(mode["id"]), 500);
|
|
@@ -23527,7 +24179,7 @@ function normalizeConfigOptions(value, modes) {
|
|
|
23527
24179
|
return normalized.slice(0, 100);
|
|
23528
24180
|
}
|
|
23529
24181
|
function ensureReasoningEffortOption(current) {
|
|
23530
|
-
if (current.some((
|
|
24182
|
+
if (current.some((option2) => option2.category === "thought_level")) {
|
|
23531
24183
|
return current;
|
|
23532
24184
|
}
|
|
23533
24185
|
const unavailable = {
|
|
@@ -23548,7 +24200,7 @@ function ensureReasoningEffortOption(current) {
|
|
|
23548
24200
|
}
|
|
23549
24201
|
]
|
|
23550
24202
|
};
|
|
23551
|
-
const modelIndex = current.findIndex((
|
|
24203
|
+
const modelIndex = current.findIndex((option2) => option2.category === "model");
|
|
23552
24204
|
if (current.length < MAXIMUM_CONFIG_OPTIONS) {
|
|
23553
24205
|
if (modelIndex < 0) {
|
|
23554
24206
|
return [...current, unavailable];
|
|
@@ -23572,20 +24224,20 @@ function ensureReasoningEffortOption(current) {
|
|
|
23572
24224
|
return [...current.slice(0, MAXIMUM_CONFIG_OPTIONS - 2), model, unavailable];
|
|
23573
24225
|
}
|
|
23574
24226
|
function normalizeStandardLifecycle(response) {
|
|
23575
|
-
const lifecycle =
|
|
24227
|
+
const lifecycle = isRecord8(response) ? response : {};
|
|
23576
24228
|
return ensureReasoningEffortOption(normalizeConfigOptions(lifecycle["configOptions"], lifecycle["modes"]));
|
|
23577
24229
|
}
|
|
23578
24230
|
function replaceStandardConfigOptions(current, value) {
|
|
23579
24231
|
const next = normalizeConfigOptions(value, void 0);
|
|
23580
|
-
const withMode = next.some((
|
|
24232
|
+
const withMode = next.some((option2) => option2.category === "mode") ? next : [...current.filter((option2) => option2.category === "mode"), ...next].slice(0, 100);
|
|
23581
24233
|
return ensureReasoningEffortOption(withMode);
|
|
23582
24234
|
}
|
|
23583
24235
|
function updateCurrentValue(current, configId, value) {
|
|
23584
|
-
return current.map((
|
|
24236
|
+
return current.map((option2) => option2.id === configId ? { ...option2, currentValue: value } : option2);
|
|
23585
24237
|
}
|
|
23586
24238
|
var StandardSessionConfigProtocol = class {
|
|
23587
24239
|
configure = async (current, change, nativeSessionId, transport) => {
|
|
23588
|
-
const existing = current.find((
|
|
24240
|
+
const existing = current.find((option2) => option2.id === change.configId);
|
|
23589
24241
|
if (existing === void 0) {
|
|
23590
24242
|
return current;
|
|
23591
24243
|
}
|
|
@@ -23614,7 +24266,7 @@ var StandardSessionConfigProtocol = class {
|
|
|
23614
24266
|
"ACP agent exited while changing session configuration",
|
|
23615
24267
|
change.signal
|
|
23616
24268
|
);
|
|
23617
|
-
if (!
|
|
24269
|
+
if (!isRecord8(response) || !Array.isArray(response["configOptions"])) {
|
|
23618
24270
|
throw new SessionConfigProtocolError("The Agent returned an invalid session configuration response");
|
|
23619
24271
|
}
|
|
23620
24272
|
return replaceStandardConfigOptions(current, response["configOptions"]);
|
|
@@ -23628,31 +24280,31 @@ var standardSessionConfigProtocol = new StandardSessionConfigProtocol();
|
|
|
23628
24280
|
var LEGACY_MODEL_CONFIG_ID = "grok_build_legacy_model";
|
|
23629
24281
|
var LEGACY_REASONING_EFFORT_CONFIG_ID = "grok_build_legacy_reasoning_effort";
|
|
23630
24282
|
function legacyOptions(response) {
|
|
23631
|
-
if (!
|
|
24283
|
+
if (!isRecord8(response)) {
|
|
23632
24284
|
return [];
|
|
23633
24285
|
}
|
|
23634
24286
|
const metadata = response["_meta"];
|
|
23635
|
-
if (!
|
|
24287
|
+
if (!isRecord8(metadata)) {
|
|
23636
24288
|
return [];
|
|
23637
24289
|
}
|
|
23638
24290
|
const sessionConfig = metadata["x.ai/sessionConfig"];
|
|
23639
|
-
if (!
|
|
24291
|
+
if (!isRecord8(sessionConfig) || !Array.isArray(sessionConfig["options"])) {
|
|
23640
24292
|
return [];
|
|
23641
24293
|
}
|
|
23642
|
-
return sessionConfig["options"].slice(0, 500).filter(
|
|
24294
|
+
return sessionConfig["options"].slice(0, 500).filter(isRecord8);
|
|
23643
24295
|
}
|
|
23644
|
-
function legacyValue(
|
|
23645
|
-
const value = readString2(
|
|
24296
|
+
function legacyValue(option2) {
|
|
24297
|
+
const value = readString2(option2["id"]);
|
|
23646
24298
|
return {
|
|
23647
|
-
description: readString2(
|
|
24299
|
+
description: readString2(option2["description"]).slice(0, 500),
|
|
23648
24300
|
groupId: "",
|
|
23649
24301
|
groupName: "",
|
|
23650
|
-
name: readString2(
|
|
24302
|
+
name: readString2(option2["label"], value).slice(0, 255),
|
|
23651
24303
|
value: value.slice(0, 500)
|
|
23652
24304
|
};
|
|
23653
24305
|
}
|
|
23654
24306
|
function modelsRecord(response) {
|
|
23655
|
-
if (!
|
|
24307
|
+
if (!isRecord8(response) || !isRecord8(response["models"])) {
|
|
23656
24308
|
return {};
|
|
23657
24309
|
}
|
|
23658
24310
|
return response["models"];
|
|
@@ -23661,9 +24313,9 @@ function legacyModelOptions(response) {
|
|
|
23661
24313
|
const options = legacyOptions(response);
|
|
23662
24314
|
const models = modelsRecord(response);
|
|
23663
24315
|
const values = [];
|
|
23664
|
-
for (const
|
|
23665
|
-
if (
|
|
23666
|
-
const value = legacyValue(
|
|
24316
|
+
for (const option2 of options) {
|
|
24317
|
+
if (option2["category"] === "model") {
|
|
24318
|
+
const value = legacyValue(option2);
|
|
23667
24319
|
if (value.value.length > 0 && !values.some((existing) => existing.value === value.value)) {
|
|
23668
24320
|
values.push(value);
|
|
23669
24321
|
}
|
|
@@ -23671,7 +24323,7 @@ function legacyModelOptions(response) {
|
|
|
23671
24323
|
}
|
|
23672
24324
|
if (values.length === 0 && Array.isArray(models["availableModels"])) {
|
|
23673
24325
|
for (const model of models["availableModels"]) {
|
|
23674
|
-
if (!
|
|
24326
|
+
if (!isRecord8(model)) {
|
|
23675
24327
|
continue;
|
|
23676
24328
|
}
|
|
23677
24329
|
const value = readString2(model["modelId"]).slice(0, 500);
|
|
@@ -23689,7 +24341,7 @@ function legacyModelOptions(response) {
|
|
|
23689
24341
|
}
|
|
23690
24342
|
}
|
|
23691
24343
|
}
|
|
23692
|
-
const selected = options.find((
|
|
24344
|
+
const selected = options.find((option2) => option2["category"] === "model" && option2["selected"] === true);
|
|
23693
24345
|
const currentValue = readString2(
|
|
23694
24346
|
models["currentModelId"],
|
|
23695
24347
|
selected === void 0 ? "" : readString2(selected["id"])
|
|
@@ -23712,11 +24364,11 @@ function legacyModelOptions(response) {
|
|
|
23712
24364
|
function legacyReasoningEffortOptions(response) {
|
|
23713
24365
|
const options = legacyOptions(response);
|
|
23714
24366
|
const values = [];
|
|
23715
|
-
for (const
|
|
23716
|
-
if (
|
|
24367
|
+
for (const option2 of options) {
|
|
24368
|
+
if (option2["category"] !== "mode") {
|
|
23717
24369
|
continue;
|
|
23718
24370
|
}
|
|
23719
|
-
const value = legacyValue(
|
|
24371
|
+
const value = legacyValue(option2);
|
|
23720
24372
|
if (value.value.length > 0 && !values.some((existing) => existing.value === value.value)) {
|
|
23721
24373
|
values.push(value);
|
|
23722
24374
|
}
|
|
@@ -23724,7 +24376,7 @@ function legacyReasoningEffortOptions(response) {
|
|
|
23724
24376
|
if (values.length === 0) {
|
|
23725
24377
|
return [];
|
|
23726
24378
|
}
|
|
23727
|
-
const selected = options.find((
|
|
24379
|
+
const selected = options.find((option2) => option2["category"] === "mode" && option2["selected"] === true);
|
|
23728
24380
|
if (selected === void 0) {
|
|
23729
24381
|
values.unshift({
|
|
23730
24382
|
description: "Use the selected model's default reasoning effort",
|
|
@@ -23751,41 +24403,41 @@ function legacyReasoningEffortOptions(response) {
|
|
|
23751
24403
|
return [result];
|
|
23752
24404
|
}
|
|
23753
24405
|
function normalizeGrokLifecycle(response) {
|
|
23754
|
-
const lifecycle =
|
|
24406
|
+
const lifecycle = isRecord8(response) ? response : {};
|
|
23755
24407
|
const standard = normalizeConfigOptions(lifecycle["configOptions"], lifecycle["modes"]);
|
|
23756
24408
|
const normalized = [...standard];
|
|
23757
|
-
if (!normalized.some((
|
|
24409
|
+
if (!normalized.some((option2) => option2.category === "model")) {
|
|
23758
24410
|
normalized.push(...legacyModelOptions(response));
|
|
23759
24411
|
}
|
|
23760
|
-
if (!normalized.some((
|
|
24412
|
+
if (!normalized.some((option2) => option2.category === "thought_level")) {
|
|
23761
24413
|
const efforts = legacyReasoningEffortOptions(response);
|
|
23762
24414
|
if (efforts.length > 0) {
|
|
23763
|
-
const modelIndex = normalized.findIndex((
|
|
24415
|
+
const modelIndex = normalized.findIndex((option2) => option2.category === "model");
|
|
23764
24416
|
normalized.splice(modelIndex < 0 ? normalized.length : modelIndex + 1, 0, ...efforts);
|
|
23765
24417
|
}
|
|
23766
24418
|
}
|
|
23767
24419
|
return ensureReasoningEffortOption(normalized.slice(0, 100));
|
|
23768
24420
|
}
|
|
23769
24421
|
function updateCurrentValue2(current, category, value) {
|
|
23770
|
-
return current.map((
|
|
24422
|
+
return current.map((option2) => option2.category === category ? { ...option2, currentValue: value } : option2);
|
|
23771
24423
|
}
|
|
23772
24424
|
function validateGrokResponse(response, modelId) {
|
|
23773
|
-
if (!
|
|
24425
|
+
if (!isRecord8(response) || !isRecord8(response["_meta"])) {
|
|
23774
24426
|
throw new SessionConfigProtocolError("Grok Build returned an invalid session configuration response");
|
|
23775
24427
|
}
|
|
23776
24428
|
const model = response["_meta"]["model"];
|
|
23777
|
-
const appliedModel =
|
|
24429
|
+
const appliedModel = isRecord8(model) ? model["Ok"] : model;
|
|
23778
24430
|
if (appliedModel !== modelId) {
|
|
23779
24431
|
throw new SessionConfigProtocolError("Grok Build returned an invalid session configuration response");
|
|
23780
24432
|
}
|
|
23781
24433
|
}
|
|
23782
24434
|
var GrokBuildSessionConfigProtocol = class {
|
|
23783
24435
|
configure = async (current, change, nativeSessionId, transport) => {
|
|
23784
|
-
const existing = current.find((
|
|
24436
|
+
const existing = current.find((option2) => option2.id === change.configId);
|
|
23785
24437
|
if (existing === void 0 || existing.id !== LEGACY_MODEL_CONFIG_ID && existing.id !== LEGACY_REASONING_EFFORT_CONFIG_ID) {
|
|
23786
24438
|
return await standardSessionConfigProtocol.configure(current, change, nativeSessionId, transport);
|
|
23787
24439
|
}
|
|
23788
|
-
const model = current.find((
|
|
24440
|
+
const model = current.find((option2) => option2.category === "model");
|
|
23789
24441
|
if (model === void 0) {
|
|
23790
24442
|
return current;
|
|
23791
24443
|
}
|
|
@@ -23811,10 +24463,10 @@ var GrokBuildSessionConfigProtocol = class {
|
|
|
23811
24463
|
validateGrokResponse(response, modelId);
|
|
23812
24464
|
const updated = updateCurrentValue2(current, existing.category, change.value);
|
|
23813
24465
|
return existing.category === "thought_level" ? updated.map(
|
|
23814
|
-
(
|
|
23815
|
-
...
|
|
23816
|
-
values:
|
|
23817
|
-
} :
|
|
24466
|
+
(option2) => option2.category === "thought_level" ? {
|
|
24467
|
+
...option2,
|
|
24468
|
+
values: option2.values.filter((value) => value.value !== AGENT_DEFAULT_REASONING_EFFORT)
|
|
24469
|
+
} : option2
|
|
23818
24470
|
) : updated;
|
|
23819
24471
|
};
|
|
23820
24472
|
normalizeLifecycle = (response) => normalizeGrokLifecycle(response);
|
|
@@ -24217,7 +24869,7 @@ function createWritableAcpStream(output2) {
|
|
|
24217
24869
|
function truncate3(value, maximumLength) {
|
|
24218
24870
|
return value.length <= maximumLength ? value : `${value.slice(0, Math.max(0, maximumLength - 1))}\u2026`;
|
|
24219
24871
|
}
|
|
24220
|
-
function
|
|
24872
|
+
function isRecord9(value) {
|
|
24221
24873
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24222
24874
|
}
|
|
24223
24875
|
function readString4(value, fallback = "") {
|
|
@@ -24245,12 +24897,12 @@ function normalizeElicitationOptions(schema) {
|
|
|
24245
24897
|
const normalized = [];
|
|
24246
24898
|
const oneOf = schema["oneOf"];
|
|
24247
24899
|
if (Array.isArray(oneOf)) {
|
|
24248
|
-
for (const
|
|
24249
|
-
if (
|
|
24900
|
+
for (const option2 of oneOf) {
|
|
24901
|
+
if (isRecord9(option2) && typeof option2["const"] === "string") {
|
|
24250
24902
|
normalized.push({
|
|
24251
|
-
description: truncate3(readString4(
|
|
24252
|
-
label: truncate3(readString4(
|
|
24253
|
-
value: truncate3(
|
|
24903
|
+
description: truncate3(readString4(option2["description"]), 500),
|
|
24904
|
+
label: truncate3(readString4(option2["title"], option2["const"]), 255),
|
|
24905
|
+
value: truncate3(option2["const"], 500)
|
|
24254
24906
|
});
|
|
24255
24907
|
}
|
|
24256
24908
|
}
|
|
@@ -24266,7 +24918,7 @@ function normalizeElicitationOptions(schema) {
|
|
|
24266
24918
|
return normalized.slice(0, 200);
|
|
24267
24919
|
}
|
|
24268
24920
|
const items = schema["items"];
|
|
24269
|
-
if (!
|
|
24921
|
+
if (!isRecord9(items)) {
|
|
24270
24922
|
return normalized;
|
|
24271
24923
|
}
|
|
24272
24924
|
const anyOf = items["anyOf"];
|
|
@@ -24279,7 +24931,7 @@ function numericString(value) {
|
|
|
24279
24931
|
return typeof value === "number" && Number.isFinite(value) ? value.toString() : "";
|
|
24280
24932
|
}
|
|
24281
24933
|
function normalizeElicitationFields(requestedSchema) {
|
|
24282
|
-
if (!
|
|
24934
|
+
if (!isRecord9(requestedSchema) || !isRecord9(requestedSchema["properties"])) {
|
|
24283
24935
|
return [];
|
|
24284
24936
|
}
|
|
24285
24937
|
const properties = requestedSchema["properties"];
|
|
@@ -24289,7 +24941,7 @@ function normalizeElicitationFields(requestedSchema) {
|
|
|
24289
24941
|
);
|
|
24290
24942
|
const normalized = [];
|
|
24291
24943
|
for (const [name, property] of Object.entries(properties)) {
|
|
24292
|
-
if (!
|
|
24944
|
+
if (!isRecord9(property)) {
|
|
24293
24945
|
continue;
|
|
24294
24946
|
}
|
|
24295
24947
|
const type = elicitationFieldType(property["type"]);
|
|
@@ -24380,7 +25032,7 @@ function validateElicitationContent(encoded, requestedSchema) {
|
|
|
24380
25032
|
"invalid_elicitation_response"
|
|
24381
25033
|
);
|
|
24382
25034
|
}
|
|
24383
|
-
if (!
|
|
25035
|
+
if (!isRecord9(decoded) || !isRecord9(requestedSchema) || !isRecord9(requestedSchema["properties"])) {
|
|
24384
25036
|
throw new AcpExecutionError(
|
|
24385
25037
|
"Elicitation response does not match the requested form",
|
|
24386
25038
|
{},
|
|
@@ -24400,7 +25052,7 @@ function validateElicitationContent(encoded, requestedSchema) {
|
|
|
24400
25052
|
const validated = {};
|
|
24401
25053
|
for (const [name, value] of Object.entries(decoded)) {
|
|
24402
25054
|
const property = properties[name];
|
|
24403
|
-
if (!
|
|
25055
|
+
if (!isRecord9(property)) {
|
|
24404
25056
|
throw new AcpExecutionError(
|
|
24405
25057
|
`Elicitation field ${name} was not requested`,
|
|
24406
25058
|
{},
|
|
@@ -24437,7 +25089,7 @@ function validateElicitationContent(encoded, requestedSchema) {
|
|
|
24437
25089
|
);
|
|
24438
25090
|
}
|
|
24439
25091
|
const allowed = normalizeElicitationOptions(property);
|
|
24440
|
-
if (allowed.length > 0 && value.some((entry) => !allowed.some((
|
|
25092
|
+
if (allowed.length > 0 && value.some((entry) => !allowed.some((option2) => option2.value === entry))) {
|
|
24441
25093
|
throw new AcpExecutionError(
|
|
24442
25094
|
`Elicitation field ${name} contains an invalid selection`,
|
|
24443
25095
|
{},
|
|
@@ -24934,7 +25586,7 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
24934
25586
|
};
|
|
24935
25587
|
nativeSessionId = () => this.#nativeSessionId;
|
|
24936
25588
|
configure = async (options) => {
|
|
24937
|
-
const existing = this.#configOptions.find((
|
|
25589
|
+
const existing = this.#configOptions.find((option2) => option2.id === options.configId);
|
|
24938
25590
|
if (existing === void 0 || existing.type !== options.valueType) {
|
|
24939
25591
|
throw new AcpExecutionError(
|
|
24940
25592
|
"The requested ACP configuration option is unavailable",
|
|
@@ -25184,10 +25836,10 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
25184
25836
|
onPermission = async (request, signal) => {
|
|
25185
25837
|
this.assertNativeSession(request.sessionId);
|
|
25186
25838
|
const interactionId = `permission-${crypto.randomUUID()}`;
|
|
25187
|
-
const options = request.options.slice(0, 20).map((
|
|
25188
|
-
kind:
|
|
25189
|
-
name: truncate3(
|
|
25190
|
-
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)
|
|
25191
25843
|
}));
|
|
25192
25844
|
if (options.length === 0) {
|
|
25193
25845
|
throw new AcpExecutionError(
|
|
@@ -25196,7 +25848,7 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
25196
25848
|
"invalid_agent_permission_request"
|
|
25197
25849
|
);
|
|
25198
25850
|
}
|
|
25199
|
-
const pending = new PendingPermission(interactionId, new Set(options.map((
|
|
25851
|
+
const pending = new PendingPermission(interactionId, new Set(options.map((option2) => option2.optionId)));
|
|
25200
25852
|
this.#pendingPermissions.set(interactionId, pending);
|
|
25201
25853
|
const abort = () => {
|
|
25202
25854
|
void this.cancelPermission(interactionId);
|
|
@@ -25406,7 +26058,7 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
25406
26058
|
}
|
|
25407
26059
|
if (update.sessionUpdate === "current_mode_update") {
|
|
25408
26060
|
this.#configOptions = this.#configOptions.map(
|
|
25409
|
-
(
|
|
26061
|
+
(option2) => option2.category === "mode" ? { ...option2, currentValue: update.currentModeId } : option2
|
|
25410
26062
|
);
|
|
25411
26063
|
this.#configRevision += 1;
|
|
25412
26064
|
await this.emitConfigUpdate();
|
|
@@ -26638,45 +27290,755 @@ var WorkspaceDirectoryService = class {
|
|
|
26638
27290
|
};
|
|
26639
27291
|
};
|
|
26640
27292
|
|
|
26641
|
-
// src/
|
|
26642
|
-
import { randomUUID as
|
|
26643
|
-
|
|
26644
|
-
|
|
26645
|
-
|
|
26646
|
-
var
|
|
26647
|
-
|
|
26648
|
-
|
|
26649
|
-
|
|
26650
|
-
|
|
26651
|
-
|
|
26652
|
-
|
|
26653
|
-
|
|
26654
|
-
var
|
|
26655
|
-
|
|
26656
|
-
|
|
26657
|
-
|
|
26658
|
-
|
|
26659
|
-
|
|
26660
|
-
|
|
26661
|
-
|
|
26662
|
-
|
|
26663
|
-
|
|
26664
|
-
|
|
26665
|
-
|
|
26666
|
-
|
|
26667
|
-
|
|
26668
|
-
|
|
26669
|
-
|
|
26670
|
-
|
|
26671
|
-
|
|
26672
|
-
|
|
26673
|
-
|
|
26674
|
-
|
|
26675
|
-
|
|
26676
|
-
|
|
26677
|
-
|
|
26678
|
-
|
|
26679
|
-
|
|
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);
|
|
26680
28042
|
let message;
|
|
26681
28043
|
if (type === "userMessage") {
|
|
26682
28044
|
const { content } = userMessageSchema.parse(item);
|
|
@@ -26955,7 +28317,7 @@ var NativeSessionService = class {
|
|
|
26955
28317
|
if (authorized === null) {
|
|
26956
28318
|
continue;
|
|
26957
28319
|
}
|
|
26958
|
-
const entryId =
|
|
28320
|
+
const entryId = randomUUID4();
|
|
26959
28321
|
if (this.#entries.size >= 5e3) {
|
|
26960
28322
|
this.#entries.clear();
|
|
26961
28323
|
}
|
|
@@ -26983,7 +28345,7 @@ var NativeSessionService = class {
|
|
|
26983
28345
|
"invalid_native_session_response"
|
|
26984
28346
|
);
|
|
26985
28347
|
}
|
|
26986
|
-
nextCursor =
|
|
28348
|
+
nextCursor = randomUUID4();
|
|
26987
28349
|
if (this.#cursors.size >= 500) {
|
|
26988
28350
|
this.#cursors.clear();
|
|
26989
28351
|
}
|
|
@@ -27201,13 +28563,13 @@ var NativeSessionService = class {
|
|
|
27201
28563
|
};
|
|
27202
28564
|
|
|
27203
28565
|
// src/prompt-artifact-resolver.ts
|
|
27204
|
-
import { createHash as
|
|
27205
|
-
import { fetch as
|
|
28566
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
28567
|
+
import { fetch as fetch5 } from "undici";
|
|
27206
28568
|
var ARTIFACT_SCHEME = "mobius-artifact:";
|
|
27207
28569
|
var ARTIFACT_DOWNLOAD_TIMEOUT_MILLISECONDS = 2e4;
|
|
27208
28570
|
var MAX_AGENT_IMAGE_BASE64_LENGTH = 4e6;
|
|
27209
28571
|
var MAX_AGENT_RESOURCE_BYTE_LENGTH = 1e6;
|
|
27210
|
-
var
|
|
28572
|
+
var IDENTIFIER_PATTERN7 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
|
|
27211
28573
|
var PromptArtifactError = class extends Error {
|
|
27212
28574
|
code;
|
|
27213
28575
|
constructor(code, message, options = {}) {
|
|
@@ -27250,7 +28612,7 @@ function parseReference(resource) {
|
|
|
27250
28612
|
const encodedByteLength2 = url2.searchParams.get("byteLength") ?? "";
|
|
27251
28613
|
const sha256 = url2.searchParams.get("sha256") ?? "";
|
|
27252
28614
|
const byteLength = Number(encodedByteLength2);
|
|
27253
|
-
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)) {
|
|
27254
28616
|
throw new PromptArtifactError("artifact_reference_invalid", "The prompt artifact reference is invalid");
|
|
27255
28617
|
}
|
|
27256
28618
|
return new PromptArtifactReference(artifactId, byteLength, sha256, resource);
|
|
@@ -27311,7 +28673,7 @@ async function download(config2, command, reference, signal) {
|
|
|
27311
28673
|
const requestSignal = AbortSignal.any([signal, timeoutSignal]);
|
|
27312
28674
|
let response;
|
|
27313
28675
|
try {
|
|
27314
|
-
response = await
|
|
28676
|
+
response = await fetch5(downloadUrl(config2, command, reference), {
|
|
27315
28677
|
dispatcher: environmentProxyDispatcher,
|
|
27316
28678
|
headers: { accept: reference.resource.mimeType },
|
|
27317
28679
|
signal: requestSignal
|
|
@@ -27331,7 +28693,7 @@ async function download(config2, command, reference, signal) {
|
|
|
27331
28693
|
);
|
|
27332
28694
|
}
|
|
27333
28695
|
const bytes = await responseBytes(response, reference.byteLength, requestSignal);
|
|
27334
|
-
if (
|
|
28696
|
+
if (createHash3("sha256").update(bytes).digest("hex") !== reference.sha256) {
|
|
27335
28697
|
throw new PromptArtifactError(
|
|
27336
28698
|
"artifact_integrity_failed",
|
|
27337
28699
|
"The prompt artifact failed integrity validation"
|
|
@@ -27476,7 +28838,7 @@ function connectRelay(url2, signal) {
|
|
|
27476
28838
|
}
|
|
27477
28839
|
|
|
27478
28840
|
// src/relay-connection/liveness.ts
|
|
27479
|
-
import { randomUUID as
|
|
28841
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
27480
28842
|
var HEARTBEAT_ACK_TIMEOUT_MILLISECONDS = 1e4;
|
|
27481
28843
|
var HEARTBEAT_INTERVAL_MILLISECONDS = 2e4;
|
|
27482
28844
|
var RelayLivenessState = class {
|
|
@@ -27564,7 +28926,7 @@ var RelayConnectionLiveness = class {
|
|
|
27564
28926
|
}
|
|
27565
28927
|
throw new Error("Heartbeat was scheduled in an invalid state");
|
|
27566
28928
|
}
|
|
27567
|
-
const heartbeatId =
|
|
28929
|
+
const heartbeatId = randomUUID5();
|
|
27568
28930
|
this.#state = new AwaitingHeartbeatAckState(
|
|
27569
28931
|
heartbeatId,
|
|
27570
28932
|
this.#timer.schedule(this.#handleTimeout, HEARTBEAT_ACK_TIMEOUT_MILLISECONDS)
|
|
@@ -27580,8 +28942,8 @@ var RelayConnectionLiveness = class {
|
|
|
27580
28942
|
|
|
27581
28943
|
// src/relay-connection/session-event-outbox.ts
|
|
27582
28944
|
import { mkdirSync as mkdirSync3 } from "node:fs";
|
|
27583
|
-
import { dirname as
|
|
27584
|
-
import { DatabaseSync as
|
|
28945
|
+
import { dirname as dirname7 } from "node:path";
|
|
28946
|
+
import { DatabaseSync as DatabaseSync4 } from "node:sqlite";
|
|
27585
28947
|
function readPendingEnvelope(row) {
|
|
27586
28948
|
if (typeof row !== "object" || row === null || Array.isArray(row)) {
|
|
27587
28949
|
throw new Error("SQLite returned an invalid session event outbox row");
|
|
@@ -27595,8 +28957,8 @@ function readPendingEnvelope(row) {
|
|
|
27595
28957
|
var SessionEventOutbox = class {
|
|
27596
28958
|
#database;
|
|
27597
28959
|
constructor(path2) {
|
|
27598
|
-
mkdirSync3(
|
|
27599
|
-
this.#database = new
|
|
28960
|
+
mkdirSync3(dirname7(path2), { recursive: true });
|
|
28961
|
+
this.#database = new DatabaseSync4(path2);
|
|
27600
28962
|
this.#database.exec(`
|
|
27601
28963
|
CREATE TABLE IF NOT EXISTS relay_session_event_outbox (
|
|
27602
28964
|
ordinal INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -27606,6 +28968,15 @@ var SessionEventOutbox = class {
|
|
|
27606
28968
|
) STRICT;
|
|
27607
28969
|
CREATE INDEX IF NOT EXISTS relay_session_event_outbox_order
|
|
27608
28970
|
ON relay_session_event_outbox(ordinal);
|
|
28971
|
+
CREATE TABLE IF NOT EXISTS relay_session_event_dead_letters (
|
|
28972
|
+
ordinal INTEGER PRIMARY KEY,
|
|
28973
|
+
event_id TEXT NOT NULL UNIQUE,
|
|
28974
|
+
session_id TEXT NOT NULL,
|
|
28975
|
+
envelope_json TEXT NOT NULL,
|
|
28976
|
+
rejection_code TEXT NOT NULL CHECK (
|
|
28977
|
+
rejection_code IN ('session_deleted', 'session_not_found')
|
|
28978
|
+
)
|
|
28979
|
+
) STRICT;
|
|
27609
28980
|
CREATE TABLE IF NOT EXISTS relay_session_event_sources (
|
|
27610
28981
|
source_key TEXT PRIMARY KEY,
|
|
27611
28982
|
next_source_seq INTEGER NOT NULL
|
|
@@ -27678,6 +29049,35 @@ var SessionEventOutbox = class {
|
|
|
27678
29049
|
WHERE event_id = ? AND session_id = ?`
|
|
27679
29050
|
).run(acknowledgement.eventId, acknowledgement.sessionId);
|
|
27680
29051
|
};
|
|
29052
|
+
quarantine = (rejection) => {
|
|
29053
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
29054
|
+
try {
|
|
29055
|
+
const insertion = this.#database.prepare(
|
|
29056
|
+
`INSERT INTO relay_session_event_dead_letters (
|
|
29057
|
+
ordinal, event_id, session_id, envelope_json, rejection_code
|
|
29058
|
+
)
|
|
29059
|
+
SELECT ordinal, event_id, session_id, envelope_json, ?
|
|
29060
|
+
FROM relay_session_event_outbox
|
|
29061
|
+
WHERE event_id = ? AND session_id = ?`
|
|
29062
|
+
).run(rejection.code, rejection.eventId, rejection.sessionId);
|
|
29063
|
+
if (insertion.changes !== 1) {
|
|
29064
|
+
this.#database.exec("COMMIT");
|
|
29065
|
+
return false;
|
|
29066
|
+
}
|
|
29067
|
+
const deletion = this.#database.prepare(
|
|
29068
|
+
`DELETE FROM relay_session_event_outbox
|
|
29069
|
+
WHERE event_id = ? AND session_id = ?`
|
|
29070
|
+
).run(rejection.eventId, rejection.sessionId);
|
|
29071
|
+
if (deletion.changes !== 1) {
|
|
29072
|
+
throw new Error("The rejected session event could not be removed from the durable outbox");
|
|
29073
|
+
}
|
|
29074
|
+
this.#database.exec("COMMIT");
|
|
29075
|
+
return true;
|
|
29076
|
+
} catch (error61) {
|
|
29077
|
+
this.#database.exec("ROLLBACK");
|
|
29078
|
+
throw error61;
|
|
29079
|
+
}
|
|
29080
|
+
};
|
|
27681
29081
|
close = () => {
|
|
27682
29082
|
this.#database.close();
|
|
27683
29083
|
};
|
|
@@ -27749,6 +29149,12 @@ var RELAY_RECONNECT_DELAY_MILLISECONDS = 500;
|
|
|
27749
29149
|
var RELAY_CONNECTION_REFRESH_MILLISECONDS = 20 * 60 * 1e3;
|
|
27750
29150
|
var ACTIVE_TURN_RECONCILIATION_TIMEOUT_MILLISECONDS = 2e4;
|
|
27751
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
|
+
}
|
|
27752
29158
|
var RelayConnectionRefreshState = class {
|
|
27753
29159
|
};
|
|
27754
29160
|
var ScheduledRelayConnectionRefreshState = class extends RelayConnectionRefreshState {
|
|
@@ -28006,7 +29412,7 @@ async function reconcileActiveTurn(config2, turn, signal) {
|
|
|
28006
29412
|
const requestSignal = AbortSignal.any([signal, timeoutSignal]);
|
|
28007
29413
|
let response;
|
|
28008
29414
|
try {
|
|
28009
|
-
response = await
|
|
29415
|
+
response = await fetch6(activeTurnReconciliationEndpoint(config2, turn), {
|
|
28010
29416
|
body: JSON.stringify({ outcome: { kind: "running" } }),
|
|
28011
29417
|
dispatcher: environmentProxyDispatcher,
|
|
28012
29418
|
headers: { "content-type": "application/json" },
|
|
@@ -28109,13 +29515,13 @@ function reportFailure(publisher, command, code, message, attemptId) {
|
|
|
28109
29515
|
);
|
|
28110
29516
|
}
|
|
28111
29517
|
function operationErrorCode(error61) {
|
|
28112
|
-
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) {
|
|
28113
29519
|
return error61.code;
|
|
28114
29520
|
}
|
|
28115
29521
|
return "session_operation_failed";
|
|
28116
29522
|
}
|
|
28117
29523
|
function operationErrorMessage(error61) {
|
|
28118
|
-
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) {
|
|
28119
29525
|
return error61.message;
|
|
28120
29526
|
}
|
|
28121
29527
|
return "The local agent operation could not be completed";
|
|
@@ -28380,6 +29786,175 @@ async function executePrompt(outbox, publisher, command, config2, directories, a
|
|
|
28380
29786
|
console.error("Mobius daemon command failed", error61);
|
|
28381
29787
|
}
|
|
28382
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
|
+
}
|
|
28383
29958
|
function waitForRelayRetry(signal, timer) {
|
|
28384
29959
|
if (signal.aborted) {
|
|
28385
29960
|
return Promise.resolve();
|
|
@@ -28416,7 +29991,7 @@ async function publishAgentCatalogUntilAvailable(config2, signal, timer) {
|
|
|
28416
29991
|
}
|
|
28417
29992
|
}
|
|
28418
29993
|
}
|
|
28419
|
-
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) {
|
|
28420
29995
|
const relayUrl = new URL(config2.relayUrl);
|
|
28421
29996
|
relayUrl.searchParams.set("liveness", "1");
|
|
28422
29997
|
const socket = await connectRelay(relayUrl, signal);
|
|
@@ -28499,6 +30074,76 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
28499
30074
|
outbox.acknowledge(decodeSessionEventAcknowledgement(encoded));
|
|
28500
30075
|
return;
|
|
28501
30076
|
}
|
|
30077
|
+
if (kind === SESSION_EVENT_REJECTED_KIND) {
|
|
30078
|
+
const rejection = decodeSessionEventRejection(encoded);
|
|
30079
|
+
if (outbox.quarantine(rejection)) {
|
|
30080
|
+
audit.record({
|
|
30081
|
+
commandId: rejection.eventId,
|
|
30082
|
+
details: { code: rejection.code },
|
|
30083
|
+
event: "session_event_rejected",
|
|
30084
|
+
sessionId: rejection.sessionId
|
|
30085
|
+
});
|
|
30086
|
+
} else {
|
|
30087
|
+
console.warn("Mobius daemon ignored a rejection for an unknown session event");
|
|
30088
|
+
}
|
|
30089
|
+
return;
|
|
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
|
+
}
|
|
28502
30147
|
if (kind === NATIVE_SESSION_CANCEL_KIND) {
|
|
28503
30148
|
const command2 = decodeNativeSessionCancel(encoded);
|
|
28504
30149
|
const pending = nativeRequests.get(command2.requestId);
|
|
@@ -28697,6 +30342,44 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
28697
30342
|
});
|
|
28698
30343
|
return;
|
|
28699
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
|
+
}
|
|
28700
30383
|
if (kind !== SESSION_PROMPT_KIND) {
|
|
28701
30384
|
throw new Error("Unsupported protocol message");
|
|
28702
30385
|
}
|
|
@@ -28787,6 +30470,10 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
|
|
|
28787
30470
|
const sessionStore = new SqliteAcpSessionStore(config2.auditDatabasePath);
|
|
28788
30471
|
const outbox = new SessionEventOutbox(config2.auditDatabasePath);
|
|
28789
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);
|
|
28790
30477
|
const activeTurns = /* @__PURE__ */ new Map();
|
|
28791
30478
|
const activeAttemptIds = /* @__PURE__ */ new Map();
|
|
28792
30479
|
const recordSessionEvent = (sessionId, payload) => {
|
|
@@ -28825,6 +30512,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
|
|
|
28825
30512
|
};
|
|
28826
30513
|
const catalogPublication = publishAgentCatalogUntilAvailable(config2, signal, timer);
|
|
28827
30514
|
try {
|
|
30515
|
+
await ipc.listen(signal);
|
|
28828
30516
|
while (!signal.aborted) {
|
|
28829
30517
|
try {
|
|
28830
30518
|
await runRelayConnection(
|
|
@@ -28837,6 +30525,10 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
|
|
|
28837
30525
|
nativeSessions,
|
|
28838
30526
|
outbox,
|
|
28839
30527
|
publisher,
|
|
30528
|
+
grants,
|
|
30529
|
+
contexts,
|
|
30530
|
+
applicator,
|
|
30531
|
+
ipc,
|
|
28840
30532
|
activeTurns,
|
|
28841
30533
|
activeAttemptIds,
|
|
28842
30534
|
announceConnection,
|
|
@@ -28868,12 +30560,20 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
|
|
|
28868
30560
|
await installations.close();
|
|
28869
30561
|
} finally {
|
|
28870
30562
|
try {
|
|
28871
|
-
await
|
|
30563
|
+
await ipc.close();
|
|
28872
30564
|
} finally {
|
|
28873
30565
|
try {
|
|
28874
|
-
|
|
30566
|
+
await sessions.close();
|
|
28875
30567
|
} finally {
|
|
28876
|
-
|
|
30568
|
+
try {
|
|
30569
|
+
sessionStore.close();
|
|
30570
|
+
} finally {
|
|
30571
|
+
try {
|
|
30572
|
+
grants.close();
|
|
30573
|
+
} finally {
|
|
30574
|
+
outbox.close();
|
|
30575
|
+
}
|
|
30576
|
+
}
|
|
28877
30577
|
}
|
|
28878
30578
|
}
|
|
28879
30579
|
}
|
|
@@ -28891,11 +30591,13 @@ Usage:
|
|
|
28891
30591
|
mobius pair --url <relay-url> --code <pairing-code> [--workspace <directory>]
|
|
28892
30592
|
mobius start --channel <channel-id>
|
|
28893
30593
|
mobius agents [--json]
|
|
30594
|
+
mobius bot message send --target <current|alias> --text <message>
|
|
28894
30595
|
|
|
28895
30596
|
Commands:
|
|
28896
30597
|
pair Pair this machine and start its local daemon
|
|
28897
30598
|
start Start the local daemon for a saved channel
|
|
28898
30599
|
agents Show detected, missing, and integration-ready Agents
|
|
30600
|
+
bot Invoke Bot-scoped actions from an active local execution
|
|
28899
30601
|
|
|
28900
30602
|
Pairing grants this browser access to the machine with your user account's permissions.
|
|
28901
30603
|
New conversations default to ~/.mobius/workspace; choose other directories in the browser.
|
|
@@ -28911,7 +30613,7 @@ async function main() {
|
|
|
28911
30613
|
if (arguments_.length > 1 || arguments_.length === 1 && arguments_[0] !== "--json") {
|
|
28912
30614
|
throw new Error("Usage: mobius agents [--json]");
|
|
28913
30615
|
}
|
|
28914
|
-
await
|
|
30616
|
+
await mkdir5(loadDefaultWorkspace(), { recursive: true, mode: 448 });
|
|
28915
30617
|
const inventory = await discoverLocalAgentInventory({
|
|
28916
30618
|
defaultWorkspace: loadDefaultWorkspace(),
|
|
28917
30619
|
environment: process.env,
|
|
@@ -28920,6 +30622,18 @@ async function main() {
|
|
|
28920
30622
|
process.stdout.write(formatAgentDiagnostics(inventory, arguments_[0] === "--json"));
|
|
28921
30623
|
return;
|
|
28922
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
|
+
}
|
|
28923
30637
|
let config2;
|
|
28924
30638
|
if (command === "pair") {
|
|
28925
30639
|
process.stdout.write(`mobius version: ${package_default.version}
|
|
@@ -28959,7 +30673,8 @@ try {
|
|
|
28959
30673
|
} catch (error61) {
|
|
28960
30674
|
if (!shutdown.signal.aborted) {
|
|
28961
30675
|
const message = error61 instanceof Error ? error61.message : "Unknown failure";
|
|
28962
|
-
|
|
30676
|
+
const code = error61 instanceof BotMessageCommandError ? `${error61.code}: ` : "";
|
|
30677
|
+
process.stderr.write(`Mobius daemon failed: ${code}${message}
|
|
28963
30678
|
`);
|
|
28964
30679
|
process.exitCode = 1;
|
|
28965
30680
|
}
|