@vicvic-im/agent-bot 0.1.1 → 0.1.3
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/README.md +9 -3
- package/dist/agents/acp.d.ts +2 -1
- package/dist/agents/acp.d.ts.map +1 -1
- package/dist/agents/types.d.ts +16 -0
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/bin-server.cjs +1422 -0
- package/dist/bin-server.cjs.map +1 -0
- package/dist/bin-server.d.ts +2 -0
- package/dist/bin-server.d.ts.map +1 -0
- package/dist/bin-server.js +19 -0
- package/dist/bin-server.js.map +1 -0
- package/dist/{chunk-QQ2NXJ3L.js → chunk-CDBYOHVL.js} +2 -2
- package/dist/{chunk-SCVC76UL.js → chunk-ELLWQDOY.js} +217 -105
- package/dist/chunk-ELLWQDOY.js.map +1 -0
- package/dist/cli.cjs +246 -119
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +32 -17
- package/dist/cli.js.map +1 -1
- package/dist/core/dispatcher.d.ts +3 -1
- package/dist/core/dispatcher.d.ts.map +1 -1
- package/dist/core/pm2.d.ts +7 -0
- package/dist/core/pm2.d.ts.map +1 -0
- package/dist/index.cjs +210 -98
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/server.cjs +210 -96
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +10 -10
- package/dist/chunk-SCVC76UL.js.map +0 -1
- /package/dist/{chunk-QQ2NXJ3L.js.map → chunk-CDBYOHVL.js.map} +0 -0
package/dist/server.cjs
CHANGED
|
@@ -34,7 +34,6 @@ __export(server_exports, {
|
|
|
34
34
|
startBot: () => startBot
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(server_exports);
|
|
37
|
-
var import_node_path4 = require("path");
|
|
38
37
|
|
|
39
38
|
// src/config.ts
|
|
40
39
|
var import_node_fs = require("fs");
|
|
@@ -137,11 +136,11 @@ function parseEnv(value) {
|
|
|
137
136
|
if (value === void 0 || value === null) return void 0;
|
|
138
137
|
const record = asRecord(value, "agent.env");
|
|
139
138
|
const env = {};
|
|
140
|
-
for (const [key,
|
|
141
|
-
if (typeof
|
|
139
|
+
for (const [key, entry] of Object.entries(record)) {
|
|
140
|
+
if (typeof entry !== "string") {
|
|
142
141
|
throw new ConfigError(`Invalid "agent.env.${key}": expected a string`);
|
|
143
142
|
}
|
|
144
|
-
env[key] =
|
|
143
|
+
env[key] = entry;
|
|
145
144
|
}
|
|
146
145
|
return env;
|
|
147
146
|
}
|
|
@@ -185,7 +184,7 @@ function parseAgent(root, configDir) {
|
|
|
185
184
|
return {
|
|
186
185
|
name: agentName,
|
|
187
186
|
command: optionalString(agentRaw.command, "agent.command"),
|
|
188
|
-
args: Array.isArray(argsRaw) ? argsRaw.map((
|
|
187
|
+
args: Array.isArray(argsRaw) ? argsRaw.map((entry) => String(entry)) : void 0,
|
|
189
188
|
cwd,
|
|
190
189
|
model: optionalString(agentRaw.model, "agent.model") ?? null,
|
|
191
190
|
env: parseEnv(agentRaw.env)
|
|
@@ -250,6 +249,9 @@ var acp = __toESM(require("@agentclientprotocol/sdk"), 1);
|
|
|
250
249
|
// src/agents/types.ts
|
|
251
250
|
var EMPTY_USAGE = { used: 0, size: 0, cost: null };
|
|
252
251
|
|
|
252
|
+
// src/version.ts
|
|
253
|
+
var VBOT_VERSION = "0.1.3";
|
|
254
|
+
|
|
253
255
|
// src/agents/acp.ts
|
|
254
256
|
var AgentAbortError = class extends Error {
|
|
255
257
|
constructor() {
|
|
@@ -266,6 +268,14 @@ var AgentStartError = class extends Error {
|
|
|
266
268
|
stderr;
|
|
267
269
|
};
|
|
268
270
|
var STDERR_LIMIT = 4e3;
|
|
271
|
+
function flattenSelectOptions(options) {
|
|
272
|
+
return options.flatMap(
|
|
273
|
+
(entry) => "group" in entry ? entry.options.map((option) => ({ value: option.value, label: option.name })) : [{ value: entry.value, label: entry.name }]
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
function isModelOption(option) {
|
|
277
|
+
return option.type === "select" && (option.category === "model" || option.id === "model");
|
|
278
|
+
}
|
|
269
279
|
var AcpAgent = class {
|
|
270
280
|
constructor(name, config) {
|
|
271
281
|
this.name = name;
|
|
@@ -295,6 +305,14 @@ var AcpAgent = class {
|
|
|
295
305
|
sessionId() {
|
|
296
306
|
return this.session;
|
|
297
307
|
}
|
|
308
|
+
currentModel() {
|
|
309
|
+
const option = this.configOptions.find(isModelOption);
|
|
310
|
+
if (!option || option.type !== "select") return null;
|
|
311
|
+
const value = String(option.currentValue);
|
|
312
|
+
const options = flattenSelectOptions(option.options);
|
|
313
|
+
const label = options.find((entry) => entry.value === value)?.label ?? value;
|
|
314
|
+
return { value, label, options };
|
|
315
|
+
}
|
|
298
316
|
resetSession() {
|
|
299
317
|
this.session = null;
|
|
300
318
|
}
|
|
@@ -362,7 +380,7 @@ var AcpAgent = class {
|
|
|
362
380
|
const init = await this.ctx.request(acp.methods.agent.initialize, {
|
|
363
381
|
protocolVersion: 1,
|
|
364
382
|
clientCapabilities: {},
|
|
365
|
-
clientInfo: { name: "vbot", version:
|
|
383
|
+
clientInfo: { name: "vbot", version: VBOT_VERSION }
|
|
366
384
|
});
|
|
367
385
|
this.initCaps = init.agentCapabilities;
|
|
368
386
|
} catch (error) {
|
|
@@ -449,7 +467,7 @@ var AcpAgent = class {
|
|
|
449
467
|
);
|
|
450
468
|
pending.catch(() => void 0);
|
|
451
469
|
const response = await Promise.race([pending, aborted]);
|
|
452
|
-
await new Promise((
|
|
470
|
+
await new Promise((resolve2) => setImmediate(resolve2));
|
|
453
471
|
if (response.stopReason === "cancelled" || request.signal.aborted) {
|
|
454
472
|
throw new AgentAbortError();
|
|
455
473
|
}
|
|
@@ -481,15 +499,14 @@ var AcpAgent = class {
|
|
|
481
499
|
this.pendingModel = model;
|
|
482
500
|
return true;
|
|
483
501
|
}
|
|
484
|
-
const option = this.configOptions.find(
|
|
485
|
-
(entry2) => entry2.type === "select" && (entry2.id === "model" || entry2.category === "model")
|
|
486
|
-
);
|
|
502
|
+
const option = this.configOptions.find(isModelOption);
|
|
487
503
|
if (!option) return false;
|
|
488
|
-
await this.ctx.request(acp.methods.agent.session.setConfigOption, {
|
|
504
|
+
const response = await this.ctx.request(acp.methods.agent.session.setConfigOption, {
|
|
489
505
|
sessionId: this.session,
|
|
490
506
|
configId: option.id,
|
|
491
507
|
value: model
|
|
492
508
|
});
|
|
509
|
+
if (response?.configOptions?.length) this.configOptions = response.configOptions;
|
|
493
510
|
this.pendingModel = null;
|
|
494
511
|
return true;
|
|
495
512
|
}
|
|
@@ -508,8 +525,8 @@ var AcpAgent = class {
|
|
|
508
525
|
} catch {
|
|
509
526
|
}
|
|
510
527
|
if (!child || child.exitCode !== null) return;
|
|
511
|
-
const exited = new Promise((
|
|
512
|
-
child.once("exit", () =>
|
|
528
|
+
const exited = new Promise((resolve2) => {
|
|
529
|
+
child.once("exit", () => resolve2());
|
|
513
530
|
});
|
|
514
531
|
child.kill("SIGTERM");
|
|
515
532
|
const timer = setTimeout(() => child.kill("SIGKILL"), 3e3);
|
|
@@ -625,21 +642,29 @@ var BotQueue = class {
|
|
|
625
642
|
}
|
|
626
643
|
};
|
|
627
644
|
|
|
628
|
-
// src/version.ts
|
|
629
|
-
var VBOT_VERSION = "0.1.1";
|
|
630
|
-
|
|
631
645
|
// src/core/dispatcher.ts
|
|
632
|
-
var
|
|
633
|
-
|
|
634
|
-
/
|
|
635
|
-
/
|
|
636
|
-
/
|
|
637
|
-
/
|
|
638
|
-
/
|
|
639
|
-
/
|
|
640
|
-
/
|
|
641
|
-
|
|
642
|
-
|
|
646
|
+
var import_node_os2 = require("os");
|
|
647
|
+
var HELP_ROWS = [
|
|
648
|
+
["/new", "Start a new session"],
|
|
649
|
+
["/stop", "Abort the current request"],
|
|
650
|
+
["/status", "Show agent, session and queue status"],
|
|
651
|
+
["/agent [name]", "Show or switch agent backend"],
|
|
652
|
+
["/model [name]", "Show or switch model"],
|
|
653
|
+
["/cost", "Show context usage and cost"],
|
|
654
|
+
["/version", "Show vbot version"],
|
|
655
|
+
["/help", "Show this help"]
|
|
656
|
+
];
|
|
657
|
+
var HELP_FOOTER = "Other /commands are sent to the agent as prompts.";
|
|
658
|
+
var NEW_BUSY_TEXT = "Cannot reset the session while a request is running. Use /stop first.";
|
|
659
|
+
var MODEL_BUSY_TEXT = "Cannot switch model while a request is running. Use /stop first.";
|
|
660
|
+
var HELP_TEXT = [
|
|
661
|
+
table(
|
|
662
|
+
["Command", "Description"],
|
|
663
|
+
HELP_ROWS.map(([command, description]) => [command, description])
|
|
664
|
+
),
|
|
665
|
+
"",
|
|
666
|
+
HELP_FOOTER
|
|
667
|
+
].join("\n");
|
|
643
668
|
function createDispatcher(runtime) {
|
|
644
669
|
return (text, reply) => {
|
|
645
670
|
const send = (message) => {
|
|
@@ -653,11 +678,57 @@ function createDispatcher(runtime) {
|
|
|
653
678
|
});
|
|
654
679
|
};
|
|
655
680
|
}
|
|
681
|
+
function escapeCell(value) {
|
|
682
|
+
return value.replace(/\|/g, "\\|").replace(/\r?\n/g, " ");
|
|
683
|
+
}
|
|
684
|
+
function table(headers, rows) {
|
|
685
|
+
const head = `| ${headers.map(escapeCell).join(" | ")} |`;
|
|
686
|
+
const separator = `| ${headers.map(() => "---").join(" | ")} |`;
|
|
687
|
+
const body = rows.map((row) => `| ${row.map(escapeCell).join(" | ")} |`);
|
|
688
|
+
return [head, separator, ...body].join("\n");
|
|
689
|
+
}
|
|
690
|
+
function formatNumber(value) {
|
|
691
|
+
if (!Number.isFinite(value)) return String(value);
|
|
692
|
+
const negative = value < 0;
|
|
693
|
+
const digits = Math.abs(Math.trunc(value)).toString();
|
|
694
|
+
let out = "";
|
|
695
|
+
for (let i = 0; i < digits.length; i += 1) {
|
|
696
|
+
if (i > 0 && (digits.length - i) % 3 === 0) out += ",";
|
|
697
|
+
out += digits[i];
|
|
698
|
+
}
|
|
699
|
+
return negative ? "-" + out : out;
|
|
700
|
+
}
|
|
701
|
+
function percentOf(used, size) {
|
|
702
|
+
if (size <= 0) return null;
|
|
703
|
+
return `${(used / size * 100).toFixed(1)}%`;
|
|
704
|
+
}
|
|
705
|
+
function usageText(runtime) {
|
|
706
|
+
const { used, size } = runtime.state().usage;
|
|
707
|
+
if (size <= 0) return "not reported";
|
|
708
|
+
const base = `${formatNumber(used)} / ${formatNumber(size)}`;
|
|
709
|
+
const percent = percentOf(used, size);
|
|
710
|
+
return percent ? `${base} (${percent})` : base;
|
|
711
|
+
}
|
|
712
|
+
function compactPath(path) {
|
|
713
|
+
const home = (0, import_node_os2.homedir)();
|
|
714
|
+
if (!home) return path;
|
|
715
|
+
if (path === home) return "~";
|
|
716
|
+
const prefix = home + "/";
|
|
717
|
+
if (path.startsWith(prefix)) return "~" + path.slice(home.length);
|
|
718
|
+
return path;
|
|
719
|
+
}
|
|
720
|
+
function modelText(runtime) {
|
|
721
|
+
const current = runtime.agent().currentModel();
|
|
722
|
+
if (current) return current.label;
|
|
723
|
+
const configured = runtime.config().agent.model;
|
|
724
|
+
if (configured) return `${configured} (configured, not applied yet)`;
|
|
725
|
+
return "unknown (session not started)";
|
|
726
|
+
}
|
|
656
727
|
function handleSlashCommand(runtime, text, send) {
|
|
657
728
|
const [rawCommand, ...args] = text.split(/\s+/);
|
|
658
729
|
switch (rawCommand.toLowerCase()) {
|
|
659
730
|
case "/new":
|
|
660
|
-
handleNew(runtime, send);
|
|
731
|
+
void handleNew(runtime, send);
|
|
661
732
|
return null;
|
|
662
733
|
case "/stop":
|
|
663
734
|
handleStop(runtime, send);
|
|
@@ -669,7 +740,7 @@ function handleSlashCommand(runtime, text, send) {
|
|
|
669
740
|
handleAgent(runtime, args, send);
|
|
670
741
|
return null;
|
|
671
742
|
case "/model":
|
|
672
|
-
handleModel(runtime, args, send);
|
|
743
|
+
void handleModel(runtime, args, send);
|
|
673
744
|
return null;
|
|
674
745
|
case "/cost":
|
|
675
746
|
send(costText(runtime));
|
|
@@ -684,12 +755,18 @@ function handleSlashCommand(runtime, text, send) {
|
|
|
684
755
|
return text.slice(1);
|
|
685
756
|
}
|
|
686
757
|
}
|
|
687
|
-
function handleNew(runtime, send) {
|
|
688
|
-
runtime.
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
runtime.
|
|
758
|
+
async function handleNew(runtime, send) {
|
|
759
|
+
if (runtime.queue().status().busy) {
|
|
760
|
+
send(NEW_BUSY_TEXT);
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
await runtime.serialize(async () => {
|
|
764
|
+
runtime.agent().resetSession();
|
|
765
|
+
const state = runtime.state();
|
|
766
|
+
state.acpSessionId = null;
|
|
767
|
+
state.usage = { used: 0, size: 0, cost: null };
|
|
768
|
+
runtime.saveState();
|
|
769
|
+
});
|
|
693
770
|
send("Session reset. Starting a new conversation.");
|
|
694
771
|
}
|
|
695
772
|
function handleStop(runtime, send) {
|
|
@@ -705,12 +782,18 @@ function handleStop(runtime, send) {
|
|
|
705
782
|
}
|
|
706
783
|
function handleAgent(runtime, args, send) {
|
|
707
784
|
const name = args.join(" ").trim();
|
|
785
|
+
const current = runtime.config().agent.name;
|
|
708
786
|
if (!name) {
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
787
|
+
send(
|
|
788
|
+
table(
|
|
789
|
+
["Agent", "Backend", ""],
|
|
790
|
+
AGENT_NAMES.map((entry) => [
|
|
791
|
+
entry,
|
|
792
|
+
AGENTS[entry].label,
|
|
793
|
+
entry === current ? "\u2190 current" : ""
|
|
794
|
+
])
|
|
795
|
+
)
|
|
796
|
+
);
|
|
714
797
|
return;
|
|
715
798
|
}
|
|
716
799
|
if (!isAgentName(name)) {
|
|
@@ -726,56 +809,95 @@ ${list}`);
|
|
|
726
809
|
(error) => send(`Error: ${error instanceof Error ? error.message : String(error)}`)
|
|
727
810
|
);
|
|
728
811
|
}
|
|
729
|
-
function handleModel(runtime, args, send) {
|
|
812
|
+
async function handleModel(runtime, args, send) {
|
|
730
813
|
const model = args.join(" ").trim();
|
|
731
814
|
if (!model) {
|
|
732
|
-
send(
|
|
815
|
+
send(modelReport(runtime));
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
if (runtime.queue().status().busy) {
|
|
819
|
+
send(MODEL_BUSY_TEXT);
|
|
733
820
|
return;
|
|
734
821
|
}
|
|
735
822
|
const config = runtime.config();
|
|
736
823
|
const hadSession = runtime.agent().sessionId() !== null;
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
}
|
|
824
|
+
const supported = await runtime.serialize(async () => {
|
|
825
|
+
const accepted = await runtime.agent().setModel(model);
|
|
826
|
+
config.agent.model = model;
|
|
827
|
+
runtime.saveConfig();
|
|
828
|
+
return accepted;
|
|
829
|
+
});
|
|
830
|
+
const applied = runtime.agent().currentModel()?.label ?? model;
|
|
831
|
+
if (!supported) {
|
|
746
832
|
send(
|
|
747
|
-
|
|
833
|
+
`Model saved: ${model}. This agent does not expose a runtime model option; it will be used on the next session if supported.`
|
|
748
834
|
);
|
|
749
|
-
|
|
750
|
-
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
send(
|
|
838
|
+
hadSession ? `Model switched to: ${applied}` : `Model set to: ${applied}. It will apply when the session starts.`
|
|
751
839
|
);
|
|
752
840
|
}
|
|
841
|
+
function modelReport(runtime) {
|
|
842
|
+
const current = runtime.agent().currentModel();
|
|
843
|
+
if (!current) {
|
|
844
|
+
const configured = runtime.config().agent.model;
|
|
845
|
+
const hint = configured ? `Configured: ${configured}
|
|
846
|
+
|
|
847
|
+
The agent has not reported a model yet; it becomes visible after the first message.` : "This agent does not expose a runtime model option, or the session has not started.";
|
|
848
|
+
return `Current: unknown
|
|
849
|
+
|
|
850
|
+
${hint}`;
|
|
851
|
+
}
|
|
852
|
+
const lines = [`Current: ${current.label}`];
|
|
853
|
+
if (current.options.length > 0) {
|
|
854
|
+
lines.push(
|
|
855
|
+
"",
|
|
856
|
+
table(
|
|
857
|
+
["Model", ""],
|
|
858
|
+
current.options.map((option) => [
|
|
859
|
+
option.label,
|
|
860
|
+
option.value === current.value ? "\u2190 current" : ""
|
|
861
|
+
])
|
|
862
|
+
)
|
|
863
|
+
);
|
|
864
|
+
}
|
|
865
|
+
lines.push("", "Switch: /model <name>");
|
|
866
|
+
return lines.join("\n");
|
|
867
|
+
}
|
|
753
868
|
function statusText(runtime) {
|
|
754
869
|
const config = runtime.config();
|
|
755
870
|
const agent = runtime.agent();
|
|
756
871
|
const state = runtime.state();
|
|
757
872
|
const queue = runtime.queue().status();
|
|
758
|
-
const
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
873
|
+
const { used, size } = state.usage;
|
|
874
|
+
const summary = [
|
|
875
|
+
`**${config.agent.name}**`,
|
|
876
|
+
queue.busy ? "busy" : "idle",
|
|
877
|
+
size > 0 ? `${formatNumber(used)} / ${formatNumber(size)}` : null
|
|
878
|
+
].filter(Boolean).join(" \xB7 ");
|
|
879
|
+
const rows = [
|
|
880
|
+
["Agent", `${config.agent.name} (${AGENTS[config.agent.name].label})`],
|
|
881
|
+
["Session", agent.sessionId() ?? "none"],
|
|
882
|
+
["Work dir", compactPath(config.agent.cwd)],
|
|
883
|
+
["Model", modelText(runtime)],
|
|
884
|
+
["Status", queue.busy ? "busy" : "idle"],
|
|
885
|
+
["Queue", String(queue.queued)],
|
|
886
|
+
["Usage", usageText(runtime)],
|
|
887
|
+
["Capabilities", capabilitiesText(agent.capabilities())]
|
|
767
888
|
];
|
|
768
|
-
return
|
|
889
|
+
return [summary, "", table(["Field", "Value"], rows)].join("\n");
|
|
769
890
|
}
|
|
770
891
|
function costText(runtime) {
|
|
771
892
|
const usage = runtime.state().usage;
|
|
772
|
-
const
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
893
|
+
const cost = usage.cost ? `${usage.cost.amount} ${usage.cost.currency}` : "not reported by this agent";
|
|
894
|
+
return table(
|
|
895
|
+
["Field", "Value"],
|
|
896
|
+
[
|
|
897
|
+
["Context", usageText(runtime)],
|
|
898
|
+
["Cost", cost]
|
|
899
|
+
]
|
|
900
|
+
);
|
|
779
901
|
}
|
|
780
902
|
function capabilitiesText(caps) {
|
|
781
903
|
const enabled = [
|
|
@@ -830,10 +952,10 @@ var import_node_path3 = require("path");
|
|
|
830
952
|
// src/core/state.ts
|
|
831
953
|
var import_node_crypto = require("crypto");
|
|
832
954
|
var import_node_fs2 = require("fs");
|
|
833
|
-
var
|
|
955
|
+
var import_node_os3 = require("os");
|
|
834
956
|
var import_node_path2 = require("path");
|
|
835
957
|
function vbotHome() {
|
|
836
|
-
return process.env.VBOT_HOME?.trim() || (0, import_node_path2.join)((0,
|
|
958
|
+
return process.env.VBOT_HOME?.trim() || (0, import_node_path2.join)((0, import_node_os3.homedir)(), ".vbot");
|
|
837
959
|
}
|
|
838
960
|
function stateDir() {
|
|
839
961
|
return (0, import_node_path2.join)(vbotHome(), "state");
|
|
@@ -991,10 +1113,10 @@ var VicvicWire = class {
|
|
|
991
1113
|
if (!socket || socket.readyState !== import_ws.default.OPEN) {
|
|
992
1114
|
throw new Error("Bot connection is not open");
|
|
993
1115
|
}
|
|
994
|
-
await new Promise((
|
|
1116
|
+
await new Promise((resolve2, reject) => {
|
|
995
1117
|
socket.send(JSON.stringify({ type: "reply", msgUid, text }), (error) => {
|
|
996
1118
|
if (error) reject(error);
|
|
997
|
-
else
|
|
1119
|
+
else resolve2();
|
|
998
1120
|
});
|
|
999
1121
|
});
|
|
1000
1122
|
}
|
|
@@ -1162,13 +1284,17 @@ async function startBot(configPath) {
|
|
|
1162
1284
|
saveConfig: () => saveConfig(config, configPath)
|
|
1163
1285
|
};
|
|
1164
1286
|
holder.queue = new BotQueue((item, signal) => gate(() => processPrompt(ctx, item, signal)));
|
|
1165
|
-
const runtime = createRuntime(
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
switching
|
|
1170
|
-
|
|
1171
|
-
|
|
1287
|
+
const runtime = createRuntime(
|
|
1288
|
+
ctx,
|
|
1289
|
+
(task) => gate(task),
|
|
1290
|
+
(name) => {
|
|
1291
|
+
if (switching) return Promise.reject(new Error("Agent switch already in progress."));
|
|
1292
|
+
switching = true;
|
|
1293
|
+
return gate(() => switchAgent(ctx, name)).finally(() => {
|
|
1294
|
+
switching = false;
|
|
1295
|
+
});
|
|
1296
|
+
}
|
|
1297
|
+
);
|
|
1172
1298
|
const dispatch = createDispatcher(runtime);
|
|
1173
1299
|
let notifySignal = () => void 0;
|
|
1174
1300
|
const wire = new VicvicWire({
|
|
@@ -1229,7 +1355,7 @@ async function runBot(configPath) {
|
|
|
1229
1355
|
const bot = await startBot(configPath);
|
|
1230
1356
|
await bot.finished;
|
|
1231
1357
|
}
|
|
1232
|
-
function createRuntime(ctx, switchAgent2) {
|
|
1358
|
+
function createRuntime(ctx, gate, switchAgent2) {
|
|
1233
1359
|
return {
|
|
1234
1360
|
config: () => ctx.config,
|
|
1235
1361
|
agent: () => ctx.getAgent(),
|
|
@@ -1237,6 +1363,7 @@ function createRuntime(ctx, switchAgent2) {
|
|
|
1237
1363
|
state: () => ctx.state,
|
|
1238
1364
|
saveState: () => ctx.saveState(),
|
|
1239
1365
|
saveConfig: () => ctx.saveConfig(),
|
|
1366
|
+
serialize: (task) => gate(task),
|
|
1240
1367
|
switchAgent: switchAgent2
|
|
1241
1368
|
};
|
|
1242
1369
|
}
|
|
@@ -1288,19 +1415,6 @@ ${error.stderr}`);
|
|
|
1288
1415
|
console.error("[server] agent run failed:", error);
|
|
1289
1416
|
replySafe(reply, `Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
1290
1417
|
}
|
|
1291
|
-
var entry = process.argv[1] ?? "";
|
|
1292
|
-
if (/(^|[\\/])server\.(js|cjs|ts)$/.test(entry)) {
|
|
1293
|
-
const configPath = process.argv[2];
|
|
1294
|
-
if (!configPath) {
|
|
1295
|
-
console.error("Usage: server.js <config-path>");
|
|
1296
|
-
process.exit(1);
|
|
1297
|
-
}
|
|
1298
|
-
runBot((0, import_node_path4.resolve)(configPath)).catch((error) => {
|
|
1299
|
-
console.error(error instanceof Error ? error.message : String(error));
|
|
1300
|
-
const expected = error instanceof ConfigError || error instanceof LockError;
|
|
1301
|
-
process.exit(expected ? 2 : 1);
|
|
1302
|
-
});
|
|
1303
|
-
}
|
|
1304
1418
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1305
1419
|
0 && (module.exports = {
|
|
1306
1420
|
runBot,
|