@wrongstack/cli 1.1.5 → 1.1.7
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/{acp-NKUEYJDZ.js → acp-DJWUTU5J.js} +6 -6
- package/dist/acp-leader/acp-leader-host.d.ts +7 -0
- package/dist/acp-leader/acp-leader-provider.d.ts +10 -0
- package/dist/acp-leader/acp-leader-skills.d.ts +5 -0
- package/dist/acp-leader/acp-leader-stream.d.ts +8 -0
- package/dist/{auth-2ZG5DBHS.js → auth-XOJIPFFX.js} +2 -2
- package/dist/{chunk-UROB7MK5.js → chunk-BQ5OMSZG.js} +3 -2
- package/dist/{chunk-M7PSENGF.js → chunk-CL3BU45P.js} +5 -4
- package/dist/{chunk-M7FNHCE3.js → chunk-EAATL6FL.js} +110 -30
- package/dist/{chunk-JFYQGMMM.js → chunk-FWUIKCCO.js} +54 -49
- package/dist/{chunk-MEBXWI7U.js → chunk-OCB4I4GQ.js} +4 -4
- package/dist/{chunk-VEESMPTX.js → chunk-PGC44T7N.js} +2 -1
- package/dist/{chunk-5SGMUDP5.js → chunk-QRWXHGLB.js} +2 -2
- package/dist/{chunk-7BM4LGKQ.js → chunk-V3AKAH25.js} +6 -6
- package/dist/{chunk-LUEO5HLZ.js → chunk-X4DEQLAZ.js} +1 -1
- package/dist/{cli-context-CQYGIWOU.js → cli-context-F3B5TRZX.js} +40 -15
- package/dist/{cli-main-VRUJNUBX.js → cli-main-BPYX7AC6.js} +45 -12
- package/dist/{execution-IV72RUSM.js → execution-W3OWWXY7.js} +23 -9
- package/dist/{hq-54PQYR5O.js → hq-V2M4IYCI.js} +13 -3
- package/dist/hq-server/login-attempt-store.d.ts +2 -0
- package/dist/{hq-server-YK7FBLL6.js → hq-server-QM7EIVGJ.js} +2 -2
- package/dist/index.js +6 -6
- package/dist/live-settings-input.d.ts +1 -0
- package/dist/short-circuit-flags-6LWKP4KP.js +11 -0
- package/dist/{subcommands-OCJNO57E.js → subcommands-SR4K73WA.js} +2 -2
- package/dist/{version-help-X6CC4CFY.js → version-help-MITOB3YK.js} +2 -2
- package/dist/vibeui-dist-OEPU6BOM.js +27 -0
- package/dist/vibeui-dist.d.ts +6 -0
- package/dist/webui-server/host-settings.d.ts +1 -1
- package/dist/webui-server/http-bridge.d.ts +1 -1
- package/dist/webui-server/instance-registration.d.ts +1 -1
- package/dist/{webui-server-V2R5WQUK.js → webui-server-KREX7GYA.js} +11 -9
- package/dist/webui-server-options.d.ts +1 -1
- package/dist/wrongforge-leader/wrongforge-leader-provider.d.ts +8 -1
- package/package.json +35 -34
- package/dist/short-circuit-flags-AGHURHMQ.js +0 -11
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
loadCachedAcpRegistry,
|
|
5
5
|
refreshAcpRegistry,
|
|
6
6
|
setupProvider
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-EAATL6FL.js";
|
|
8
8
|
import {
|
|
9
9
|
createHqCommandDispatcher,
|
|
10
10
|
wrongstackBridgeSetup
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-QRWXHGLB.js";
|
|
12
12
|
import "./chunk-3LEIFO5D.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-PGC44T7N.js";
|
|
14
14
|
import {
|
|
15
15
|
startCliHqConnection
|
|
16
16
|
} from "./chunk-76JE54WD.js";
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
WebSocketServer
|
|
19
19
|
} from "./chunk-OZCYZYN2.js";
|
|
20
20
|
import "./chunk-UFRVTBV6.js";
|
|
21
|
-
import "./chunk-
|
|
21
|
+
import "./chunk-X4DEQLAZ.js";
|
|
22
22
|
import "./chunk-HKMOIIPQ.js";
|
|
23
23
|
import "./chunk-W23PY4IJ.js";
|
|
24
24
|
|
|
@@ -1124,7 +1124,7 @@ var acpCmd = async (args, deps) => {
|
|
|
1124
1124
|
const sub = args[0];
|
|
1125
1125
|
const loginIndex = sub === "auth" ? 0 : (sub === "server" || sub === "serve") && args[1] === "auth" ? 1 : -1;
|
|
1126
1126
|
if (loginIndex >= 0) {
|
|
1127
|
-
const { authCmd } = await import("./auth-
|
|
1127
|
+
const { authCmd } = await import("./auth-XOJIPFFX.js");
|
|
1128
1128
|
return authCmd(args.slice(loginIndex + 1), deps);
|
|
1129
1129
|
}
|
|
1130
1130
|
if (!sub || sub === "server" || sub === "serve") {
|
|
@@ -1205,4 +1205,4 @@ parallel:
|
|
|
1205
1205
|
export {
|
|
1206
1206
|
acpCmd
|
|
1207
1207
|
};
|
|
1208
|
-
//# sourceMappingURL=acp-
|
|
1208
|
+
//# sourceMappingURL=acp-DJWUTU5J.js.map
|
|
@@ -40,6 +40,13 @@ export interface AcpLeaderHost {
|
|
|
40
40
|
runTool(name: string, input: Record<string, unknown>, run?: {
|
|
41
41
|
sessionId?: string | undefined;
|
|
42
42
|
approve?: ((tool: Tool, input: Record<string, unknown>) => Promise<boolean>) | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Settle the call's tool card here: no tool_result reaches the
|
|
45
|
+
* conversation, and the caller's own stream does not draw one (the
|
|
46
|
+
* WrongForge leader's `wstack_*` calls). An ACP agent reports its fleet
|
|
47
|
+
* calls itself, so its cards come from its stream instead.
|
|
48
|
+
*/
|
|
49
|
+
announce?: boolean | undefined;
|
|
43
50
|
}): Promise<{
|
|
44
51
|
content: string;
|
|
45
52
|
isError: boolean;
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import type { AgentContextUsage, Capabilities, Config, Provider, ProviderFactory, Request, Response, StreamEvent } from '@wrongstack/core/types';
|
|
2
2
|
import { ACP_LEADER_PROVIDER_ID } from './acp-leader-host.js';
|
|
3
3
|
export { ACP_LEADER_PROVIDER_ID };
|
|
4
|
+
/**
|
|
5
|
+
* The side model the user set for an agent leader (`acp.leader.sideModel`),
|
|
6
|
+
* without falling back to the fallback chain: a leader that can answer side
|
|
7
|
+
* requests itself (WrongForge) must not hand them to `fallbackModels[0]`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function explicitLeaderSideModel(config: Config): {
|
|
10
|
+
provider: string;
|
|
11
|
+
model: string;
|
|
12
|
+
} | undefined;
|
|
4
13
|
export declare function leaderSideModel(config: Config): {
|
|
5
14
|
provider: string;
|
|
6
15
|
model: string;
|
|
@@ -58,6 +67,7 @@ export declare class AcpLeaderProvider implements Provider {
|
|
|
58
67
|
private observeContext;
|
|
59
68
|
private publishContext;
|
|
60
69
|
private loadAcp;
|
|
70
|
+
private dropFleetGrants;
|
|
61
71
|
private drop;
|
|
62
72
|
/** The persistent agent session for this conversation, started on first use. */
|
|
63
73
|
private sessionFor;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** The WrongStack `skill` tool as an agent sees it on this route, if offered. */
|
|
2
|
+
export declare function externalSkillLoader(offered: readonly string[] | undefined, prefix: string): string | undefined;
|
|
3
|
+
/** `text` with its required-skills marker rewritten for an agent leader. */
|
|
4
|
+
export declare function externalSkillDirective(text: string, loader: string | undefined): string;
|
|
5
|
+
//# sourceMappingURL=acp-leader-skills.d.ts.map
|
|
@@ -34,6 +34,13 @@ export declare class TextBlocks {
|
|
|
34
34
|
text(chunk: string): void;
|
|
35
35
|
close(): void;
|
|
36
36
|
}
|
|
37
|
+
interface CardOutput {
|
|
38
|
+
output: string;
|
|
39
|
+
fullOutput?: string | undefined;
|
|
40
|
+
outputBytes: number;
|
|
41
|
+
}
|
|
42
|
+
/** A card's output fields for a result text that no tool_result will carry. */
|
|
43
|
+
export declare function cardOutputForText(text: string): CardOutput;
|
|
37
44
|
/**
|
|
38
45
|
* The agent's own tool calls as the host's tool cards: `tool.started` once a
|
|
39
46
|
* call is announced, `tool.executed` once it settles. Named by the agent's
|
|
@@ -80,4 +87,5 @@ export declare function agentTurnError(err: unknown, agentId: string, classify:
|
|
|
80
87
|
error: ProviderError;
|
|
81
88
|
dead: boolean;
|
|
82
89
|
};
|
|
90
|
+
export {};
|
|
83
91
|
//# sourceMappingURL=acp-leader-stream.d.ts.map
|
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
import "./chunk-BCKVNORU.js";
|
|
45
45
|
import {
|
|
46
46
|
parseAuthFlags
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-CL3BU45P.js";
|
|
48
48
|
import "./chunk-W23PY4IJ.js";
|
|
49
49
|
|
|
50
50
|
// src/subcommands/handlers/auth.ts
|
|
@@ -745,4 +745,4 @@ async function runAuthRemove(deps, providerId) {
|
|
|
745
745
|
export {
|
|
746
746
|
authCmd
|
|
747
747
|
};
|
|
748
|
-
//# sourceMappingURL=auth-
|
|
748
|
+
//# sourceMappingURL=auth-XOJIPFFX.js.map
|
|
@@ -33,7 +33,7 @@ var helpCmd = async (_args, deps) => {
|
|
|
33
33
|
["wstack", "Interactive session (REPL or TUI, picked at launch)"],
|
|
34
34
|
['wstack "<task>"', 'Run one task and exit (also: --prompt "<task>")'],
|
|
35
35
|
["wstack quick", "Straight into the TUI with saved defaults"],
|
|
36
|
-
["wstack webui | simpleui", "Browser UI / minimal chat
|
|
36
|
+
["wstack webui | simpleui | vibeui", "Browser UI / minimal chat / focused coding workspace"],
|
|
37
37
|
["wstack desktop", "WrongStack Desktop (requires @wrongstack/desktop)"],
|
|
38
38
|
["wstack hq", "HQ command center across projects and machines"],
|
|
39
39
|
["wstack remote <user@host:/path>", "Run on a remote machine over SSH; WebUI tunneled here"],
|
|
@@ -129,6 +129,7 @@ var helpCmd = async (_args, deps) => {
|
|
|
129
129
|
"--simpleui [same flags] [--full-auto]",
|
|
130
130
|
"Minimal chat UI; --full-auto = YOLO + autonomy for this run only"
|
|
131
131
|
],
|
|
132
|
+
["--vibeui [same browser flags]", "Focused coding workspace (default port 3476)"],
|
|
132
133
|
[
|
|
133
134
|
"--hq [--host <h>] [--port <n>] [--password <p>] [--tunnel] [--open]",
|
|
134
135
|
"HQ server (+ --hq-allowlist, --hq-public-url)"
|
|
@@ -158,4 +159,4 @@ export {
|
|
|
158
159
|
versionCmd,
|
|
159
160
|
helpCmd
|
|
160
161
|
};
|
|
161
|
-
//# sourceMappingURL=chunk-
|
|
162
|
+
//# sourceMappingURL=chunk-BQ5OMSZG.js.map
|
|
@@ -54,6 +54,7 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
54
54
|
"webui",
|
|
55
55
|
"webui-session-child",
|
|
56
56
|
"simpleui",
|
|
57
|
+
"vibeui",
|
|
57
58
|
"full-auto",
|
|
58
59
|
"desktop",
|
|
59
60
|
"open",
|
|
@@ -205,11 +206,11 @@ function parseArgs(argv) {
|
|
|
205
206
|
return { flags, positional };
|
|
206
207
|
}
|
|
207
208
|
function normalizeSurfaceAliases(flags, positional) {
|
|
208
|
-
if (flags["simpleui"]) flags["webui"] = true;
|
|
209
|
+
if (flags["simpleui"] || flags["vibeui"]) flags["webui"] = true;
|
|
209
210
|
if (flags["webui-session-child"]) flags["webui"] = true;
|
|
210
211
|
const first = positional[0];
|
|
211
|
-
if (first === "simpleui") {
|
|
212
|
-
flags[
|
|
212
|
+
if (first === "simpleui" || first === "vibeui") {
|
|
213
|
+
flags[first] = true;
|
|
213
214
|
flags["webui"] = true;
|
|
214
215
|
positional.splice(0, 1);
|
|
215
216
|
return;
|
|
@@ -313,4 +314,4 @@ export {
|
|
|
313
314
|
parseAuthFlags,
|
|
314
315
|
parseSpawnFlags
|
|
315
316
|
};
|
|
316
|
-
//# sourceMappingURL=chunk-
|
|
317
|
+
//# sourceMappingURL=chunk-CL3BU45P.js.map
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
reportWrongForgeQuota,
|
|
4
4
|
writeWrongForgeInfoCache,
|
|
5
5
|
wrongstackBridgeSetup
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QRWXHGLB.js";
|
|
7
7
|
import {
|
|
8
8
|
isRestrictedMode
|
|
9
9
|
} from "./chunk-3LEIFO5D.js";
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
toProgress,
|
|
22
22
|
wfTokens,
|
|
23
23
|
wrongForgeCall
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-PGC44T7N.js";
|
|
25
25
|
import {
|
|
26
26
|
buildProviderForId,
|
|
27
27
|
resolveProviderCfgWithProxy
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
ACP_LEADER_PROVIDER_ID,
|
|
31
31
|
acpLeaderHost,
|
|
32
32
|
trackAcpLeader
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-X4DEQLAZ.js";
|
|
34
34
|
|
|
35
35
|
// src/acp-agent-list.ts
|
|
36
36
|
import { REGISTRY_ID_ALIASES } from "@wrongstack/acp";
|
|
@@ -569,6 +569,7 @@ function publishLeaderContext(events, sessionId, reading, fallbackMaxContext) {
|
|
|
569
569
|
|
|
570
570
|
// src/acp-leader/acp-leader-fleet.ts
|
|
571
571
|
import { randomBytes } from "node:crypto";
|
|
572
|
+
import { toErrorMessage as toErrorMessage2 } from "@wrongstack/core/utils";
|
|
572
573
|
import { MCPServer, serveHttp } from "@wrongstack/mcp";
|
|
573
574
|
var FLEET_SERVER_NAME = "wrongstack-fleet";
|
|
574
575
|
var FLEET_TOOLS = [
|
|
@@ -579,7 +580,10 @@ var FLEET_TOOLS = [
|
|
|
579
580
|
"roll_up",
|
|
580
581
|
"fleet_status",
|
|
581
582
|
"session_note",
|
|
582
|
-
"terminate_subagent"
|
|
583
|
+
"terminate_subagent",
|
|
584
|
+
// Not a fleet tool, but it too must run in this process: WrongStack's
|
|
585
|
+
// skills (a /bughunt playbook) reach the agent only through it.
|
|
586
|
+
"skill"
|
|
583
587
|
];
|
|
584
588
|
var MCP_PREFIX = `mcp__${FLEET_SERVER_NAME}__`;
|
|
585
589
|
function fleetToolName(mcpName) {
|
|
@@ -605,7 +609,11 @@ async function startFleetEndpoint(host, run) {
|
|
|
605
609
|
if (!offered.has(name)) {
|
|
606
610
|
return { content: `Tool "${name}" is not offered here`, isError: true };
|
|
607
611
|
}
|
|
608
|
-
|
|
612
|
+
try {
|
|
613
|
+
return await (run ? host.runTool(name, args, run) : host.runTool(name, args));
|
|
614
|
+
} catch (err) {
|
|
615
|
+
return { content: `Failed to execute ${name}: ${toErrorMessage2(err)}`, isError: true };
|
|
616
|
+
}
|
|
609
617
|
}
|
|
610
618
|
}
|
|
611
619
|
});
|
|
@@ -631,7 +639,11 @@ function fleetNote(tools) {
|
|
|
631
639
|
...has("fleet_status") ? ["- fleet_status: what is running and its progress."] : [],
|
|
632
640
|
...has("roll_up") ? ["- roll_up: the full result of finished tasks."] : [],
|
|
633
641
|
...has("session_note") ? ["- session_note: steer a running worker."] : [],
|
|
634
|
-
...has("terminate_subagent") ? ["- terminate_subagent: stop a worker."] : []
|
|
642
|
+
...has("terminate_subagent") ? ["- terminate_subagent: stop a worker."] : [],
|
|
643
|
+
...has("skill") ? [
|
|
644
|
+
"- skill: load one of WrongStack's skills by name (follow nextOffset to the last page);",
|
|
645
|
+
" a task that names WrongStack skills means these."
|
|
646
|
+
] : []
|
|
635
647
|
].join("\n");
|
|
636
648
|
}
|
|
637
649
|
|
|
@@ -674,9 +686,28 @@ function writeLeaderSession(stateDir, sessionId, record) {
|
|
|
674
686
|
return writing.catch(() => void 0);
|
|
675
687
|
}
|
|
676
688
|
|
|
689
|
+
// src/acp-leader/acp-leader-skills.ts
|
|
690
|
+
import { parseRequiredSkillsMarker } from "@wrongstack/core/skills";
|
|
691
|
+
var MARKERS = /<!--\s*wrongstack:required-skills\s+[\s\S]*?-->/g;
|
|
692
|
+
function externalSkillLoader(offered, prefix) {
|
|
693
|
+
return offered?.includes("skill") ? `${prefix}skill` : void 0;
|
|
694
|
+
}
|
|
695
|
+
function externalSkillDirective(text, loader) {
|
|
696
|
+
const skills = parseRequiredSkillsMarker(text);
|
|
697
|
+
if (!skills) return text;
|
|
698
|
+
const list = skills.join(", ");
|
|
699
|
+
const line = loader ? `[WrongStack] This task's playbook skills: ${list}. They are WrongStack skills: load each with the \`${loader}\` tool, following nextOffset to the last page, before changing code. Where the text below names the \`skill\` tool or a $name, it means that tool and these skills.` : `[WrongStack] This task's playbook skills: ${list}. This route offers no WrongStack skill tool: load them with your own skill tool if you have them, otherwise follow the protocol below without them.`;
|
|
700
|
+
let first = true;
|
|
701
|
+
return text.replace(MARKERS, () => {
|
|
702
|
+
if (!first) return "";
|
|
703
|
+
first = false;
|
|
704
|
+
return line;
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
|
|
677
708
|
// src/acp-leader/acp-leader-stream.ts
|
|
678
709
|
import { ProviderError } from "@wrongstack/core/types";
|
|
679
|
-
import { toErrorMessage as
|
|
710
|
+
import { toErrorMessage as toErrorMessage3 } from "@wrongstack/core/utils";
|
|
680
711
|
var StreamQueue = class {
|
|
681
712
|
items = [];
|
|
682
713
|
wake;
|
|
@@ -742,10 +773,7 @@ function clip(text, max) {
|
|
|
742
773
|
if (last >= 55296 && last <= 56319) end -= 1;
|
|
743
774
|
return `${text.slice(0, end)}\u2026`;
|
|
744
775
|
}
|
|
745
|
-
function
|
|
746
|
-
const raw = call.rawOutput;
|
|
747
|
-
const text = call.output ?? (raw ? typeof raw.output === "string" ? raw.output : JSON.stringify(raw) : void 0);
|
|
748
|
-
if (text === void 0) return void 0;
|
|
776
|
+
function cardOutputForText(text) {
|
|
749
777
|
const output = clip(text, OUTPUT_PREVIEW_CHARS);
|
|
750
778
|
return {
|
|
751
779
|
output,
|
|
@@ -754,6 +782,12 @@ function cardOutput(call) {
|
|
|
754
782
|
outputBytes: Buffer.byteLength(text)
|
|
755
783
|
};
|
|
756
784
|
}
|
|
785
|
+
function cardOutput(call) {
|
|
786
|
+
const raw = call.rawOutput;
|
|
787
|
+
const text = call.output ?? (raw ? typeof raw.output === "string" ? raw.output : JSON.stringify(raw) : void 0);
|
|
788
|
+
if (text === void 0) return void 0;
|
|
789
|
+
return cardOutputForText(text);
|
|
790
|
+
}
|
|
757
791
|
var ToolCardRelay = class {
|
|
758
792
|
constructor(events, meta) {
|
|
759
793
|
this.events = events;
|
|
@@ -886,7 +920,7 @@ function agentTurnError(err, agentId, classify) {
|
|
|
886
920
|
};
|
|
887
921
|
}
|
|
888
922
|
const kind = err?.kind;
|
|
889
|
-
const message = `${agentId}: ${
|
|
923
|
+
const message = `${agentId}: ${toErrorMessage3(err)}`;
|
|
890
924
|
if (kind === "stalled") {
|
|
891
925
|
return {
|
|
892
926
|
error: new ProviderError(message, 408, false, "acp", { kind: "timeout", cause: err }),
|
|
@@ -941,8 +975,11 @@ function parseSideModel(ref) {
|
|
|
941
975
|
if (provider === ACP_LEADER_PROVIDER_ID) return void 0;
|
|
942
976
|
return { provider, model: ref.slice(slash + 1) };
|
|
943
977
|
}
|
|
978
|
+
function explicitLeaderSideModel(config) {
|
|
979
|
+
return parseSideModel(config.acp?.leader?.sideModel);
|
|
980
|
+
}
|
|
944
981
|
function leaderSideModel(config) {
|
|
945
|
-
return
|
|
982
|
+
return explicitLeaderSideModel(config) ?? parseSideModel(config.fallbackBridge) ?? parseSideModel(config.fallbackModels?.[0]);
|
|
946
983
|
}
|
|
947
984
|
function isLeaderTurn(req) {
|
|
948
985
|
const { sessionId, threadId } = req.cache ?? {};
|
|
@@ -1060,7 +1097,10 @@ var AcpLeaderProvider = class {
|
|
|
1060
1097
|
}
|
|
1061
1098
|
/** The turn's prompt; an agent joining a conversation under way gets the turns before it. */
|
|
1062
1099
|
promptText(leader, req) {
|
|
1063
|
-
const latest =
|
|
1100
|
+
const latest = externalSkillDirective(
|
|
1101
|
+
latestUserText(req.messages),
|
|
1102
|
+
externalSkillLoader(leader.fleet?.tools, `mcp__${FLEET_SERVER_NAME}__`)
|
|
1103
|
+
);
|
|
1064
1104
|
const earlier = leader.joined ? void 0 : earlierConversation(req.messages);
|
|
1065
1105
|
leader.joined = true;
|
|
1066
1106
|
const prompt = earlier ? `${earlier}
|
|
@@ -1136,8 +1176,20 @@ ${withNotes}` : withNotes;
|
|
|
1136
1176
|
this.acp ??= await import("@wrongstack/acp");
|
|
1137
1177
|
return this.acp;
|
|
1138
1178
|
}
|
|
1179
|
+
dropFleetGrants(sessionId) {
|
|
1180
|
+
for (const grantKey of this.fleetGrants.keys()) {
|
|
1181
|
+
try {
|
|
1182
|
+
const parsed = JSON.parse(grantKey);
|
|
1183
|
+
if (Array.isArray(parsed) && parsed[0] === sessionId) {
|
|
1184
|
+
this.fleetGrants.delete(grantKey);
|
|
1185
|
+
}
|
|
1186
|
+
} catch {
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1139
1190
|
drop(key, leader) {
|
|
1140
1191
|
this.sessions.delete(key);
|
|
1192
|
+
this.dropFleetGrants(key);
|
|
1141
1193
|
void leader.session.close().catch(() => {
|
|
1142
1194
|
});
|
|
1143
1195
|
void leader.fleet?.close().catch(() => {
|
|
@@ -1312,6 +1364,7 @@ ${fleetNote(fleet.tools)}` : "")
|
|
|
1312
1364
|
async closeAll() {
|
|
1313
1365
|
const all = [...this.sessions.values()];
|
|
1314
1366
|
this.sessions.clear();
|
|
1367
|
+
this.fleetGrants.clear();
|
|
1315
1368
|
await Promise.all(
|
|
1316
1369
|
all.map(
|
|
1317
1370
|
(p) => p.then((leader) => {
|
|
@@ -1371,7 +1424,7 @@ import { registerBuiltinProviderAuthStrategies } from "@wrongstack/providers/oau
|
|
|
1371
1424
|
// src/wrongforge-leader/wrongforge-leader-provider.ts
|
|
1372
1425
|
import { consumeBtwNotes as consumeBtwNotes3 } from "@wrongstack/core/agent";
|
|
1373
1426
|
import { ProviderError as ProviderError3 } from "@wrongstack/core/types";
|
|
1374
|
-
import { toErrorMessage as
|
|
1427
|
+
import { toErrorMessage as toErrorMessage5 } from "@wrongstack/core/utils";
|
|
1375
1428
|
|
|
1376
1429
|
// src/wrongforge-leader/wrongforge-leader-gateway.ts
|
|
1377
1430
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
@@ -1379,7 +1432,7 @@ import http from "node:http";
|
|
|
1379
1432
|
import {
|
|
1380
1433
|
compactToolDefinitionForWire,
|
|
1381
1434
|
subjectForToolInput as subjectForToolInput2,
|
|
1382
|
-
toErrorMessage as
|
|
1435
|
+
toErrorMessage as toErrorMessage4
|
|
1383
1436
|
} from "@wrongstack/core/utils";
|
|
1384
1437
|
import { timingSafeTokenEqual } from "@wrongstack/primitives";
|
|
1385
1438
|
var NOT_OFFERED = /* @__PURE__ */ new Set([
|
|
@@ -1475,14 +1528,17 @@ async function startLeaderGateway(host, sessionId) {
|
|
|
1475
1528
|
}
|
|
1476
1529
|
host.runTool(name, input, {
|
|
1477
1530
|
sessionId,
|
|
1478
|
-
approve: (t, i) => askUser(host, sessionId, t, i)
|
|
1531
|
+
approve: (t, i) => askUser(host, sessionId, t, i),
|
|
1532
|
+
// The provider draws no card for a `wstack_*` call (its events are
|
|
1533
|
+
// marked external), so the session's card is settled here.
|
|
1534
|
+
announce: true
|
|
1479
1535
|
}).then(
|
|
1480
1536
|
(r) => send(res, 200, { ok: !r.isError, tool: name, content: r.content }),
|
|
1481
1537
|
(err) => send(res, 200, {
|
|
1482
1538
|
ok: false,
|
|
1483
1539
|
tool: name,
|
|
1484
1540
|
error: "tool_failed",
|
|
1485
|
-
message:
|
|
1541
|
+
message: toErrorMessage4(err)
|
|
1486
1542
|
})
|
|
1487
1543
|
);
|
|
1488
1544
|
});
|
|
@@ -1582,7 +1638,7 @@ function providerError(err, id) {
|
|
|
1582
1638
|
if (err.status >= 500) return make(err.message, err.status, true, "server");
|
|
1583
1639
|
return make(`${err.code}: ${err.message}`, err.status, false, "invalid_request");
|
|
1584
1640
|
}
|
|
1585
|
-
return make(
|
|
1641
|
+
return make(toErrorMessage5(err), 0, false, "unknown");
|
|
1586
1642
|
}
|
|
1587
1643
|
function taskError(record, id) {
|
|
1588
1644
|
const make = (message, status, retryable, kind) => new ProviderError3(`WrongForge: ${message}`, status, retryable, id, { kind });
|
|
@@ -1657,19 +1713,27 @@ var WrongForgeLeaderProvider = class {
|
|
|
1657
1713
|
}
|
|
1658
1714
|
return choice.id;
|
|
1659
1715
|
}
|
|
1660
|
-
/**
|
|
1661
|
-
|
|
1662
|
-
|
|
1716
|
+
/**
|
|
1717
|
+
* A side model for a turn WrongForge does not lead. `explicitOnly` (a side
|
|
1718
|
+
* request through `complete()`) takes only the model the user named in
|
|
1719
|
+
* `acp.leader.sideModel`: WrongForge answers those itself (`oneShot`), and
|
|
1720
|
+
* handing them to `fallbackModels[0]` let that model take over the session.
|
|
1721
|
+
* A worker's turn may still fall back to the fallback chain, since `oneShot`
|
|
1722
|
+
* would leave it without tools.
|
|
1723
|
+
*/
|
|
1724
|
+
sideProvider(explicitOnly = false) {
|
|
1725
|
+
const config = this.config();
|
|
1726
|
+
const ref = explicitOnly ? explicitLeaderSideModel(config) : leaderSideModel(config);
|
|
1663
1727
|
if (!ref || ref.provider === this.id) return void 0;
|
|
1664
1728
|
let provider = this.sideProviders.get(ref.provider);
|
|
1665
1729
|
if (!provider) {
|
|
1666
|
-
provider = this.opts.buildProvider(ref.provider,
|
|
1730
|
+
provider = this.opts.buildProvider(ref.provider, config);
|
|
1667
1731
|
if (provider) this.sideProviders.set(ref.provider, provider);
|
|
1668
1732
|
}
|
|
1669
1733
|
return provider ? { provider, model: ref.model } : void 0;
|
|
1670
1734
|
}
|
|
1671
1735
|
async complete(req, opts) {
|
|
1672
|
-
const side = this.sideProvider();
|
|
1736
|
+
const side = this.sideProvider(true);
|
|
1673
1737
|
if (side) return side.provider.complete({ ...req, model: side.model }, opts);
|
|
1674
1738
|
return this.oneShot(req, opts.signal);
|
|
1675
1739
|
}
|
|
@@ -1739,8 +1803,16 @@ var WrongForgeLeaderProvider = class {
|
|
|
1739
1803
|
try {
|
|
1740
1804
|
info = await this.info(call, opts.signal);
|
|
1741
1805
|
model = this.model(req.model, info);
|
|
1742
|
-
if (host
|
|
1806
|
+
if (host && !leader.gateway) {
|
|
1807
|
+
leader.gateway = startLeaderGateway(host, key).catch(() => {
|
|
1808
|
+
leader.gateway = void 0;
|
|
1809
|
+
return void 0;
|
|
1810
|
+
});
|
|
1811
|
+
}
|
|
1743
1812
|
gateway = await leader.gateway;
|
|
1813
|
+
if (!gateway) {
|
|
1814
|
+
leader.gateway = void 0;
|
|
1815
|
+
}
|
|
1744
1816
|
joinedBefore = leader.joined ?? await this.wfSessionExists(call, leader, opts.signal);
|
|
1745
1817
|
} catch (err) {
|
|
1746
1818
|
throw providerError(err, this.id);
|
|
@@ -1764,7 +1836,7 @@ var WrongForgeLeaderProvider = class {
|
|
|
1764
1836
|
"POST",
|
|
1765
1837
|
"/v1/tasks",
|
|
1766
1838
|
{
|
|
1767
|
-
prompt: this.promptText(req, joinedBefore),
|
|
1839
|
+
prompt: this.promptText(req, joinedBefore, gateway),
|
|
1768
1840
|
session_id: leader.wfSessionId,
|
|
1769
1841
|
workdir: host?.projectRoot ?? process.cwd(),
|
|
1770
1842
|
...model ? { model } : {},
|
|
@@ -1780,6 +1852,10 @@ var WrongForgeLeaderProvider = class {
|
|
|
1780
1852
|
);
|
|
1781
1853
|
taskId = task.id;
|
|
1782
1854
|
leader.joined = true;
|
|
1855
|
+
if (opts.signal.aborted) {
|
|
1856
|
+
cancelTask(call, taskId, "interrupted in WrongStack");
|
|
1857
|
+
throw new WfAborted();
|
|
1858
|
+
}
|
|
1783
1859
|
for await (const ev of followTask(call, task.id, opts.signal)) {
|
|
1784
1860
|
if (ev.type === "task.heartbeat" || ev.type === "step.finished") {
|
|
1785
1861
|
void reportWrongForgeQuota({ providerId: this.id, fetchImpl: this.opts.fetchImpl });
|
|
@@ -1831,8 +1907,11 @@ var WrongForgeLeaderProvider = class {
|
|
|
1831
1907
|
}
|
|
1832
1908
|
}
|
|
1833
1909
|
/** The turn's prompt; WrongForge joining a conversation under way gets the turns before it. */
|
|
1834
|
-
promptText(req, joined) {
|
|
1835
|
-
const latest =
|
|
1910
|
+
promptText(req, joined, gateway) {
|
|
1911
|
+
const latest = externalSkillDirective(
|
|
1912
|
+
latestUserText(req.messages),
|
|
1913
|
+
gateway ? externalSkillLoader(gateway.tools, gateway.spec.name_prefix ?? "") : void 0
|
|
1914
|
+
);
|
|
1836
1915
|
const earlier = joined ? void 0 : earlierConversation(req.messages);
|
|
1837
1916
|
const prompt = earlier ? `${earlier}
|
|
1838
1917
|
|
|
@@ -2043,7 +2122,7 @@ Try \`wstack models refresh\` once you have network access.`,
|
|
|
2043
2122
|
cause: err
|
|
2044
2123
|
});
|
|
2045
2124
|
}
|
|
2046
|
-
if (config.features.modelsRegistry && !acpLeader) {
|
|
2125
|
+
if (config.features.modelsRegistry && !acpLeader && !wrongForgeLeader) {
|
|
2047
2126
|
provider = await withCatalogCapabilities(
|
|
2048
2127
|
modelsRegistry,
|
|
2049
2128
|
config.provider,
|
|
@@ -2062,9 +2141,10 @@ export {
|
|
|
2062
2141
|
wrongstackAcpPermissionPolicy,
|
|
2063
2142
|
recordAcpRateLimit,
|
|
2064
2143
|
startAcpTurnReminders,
|
|
2144
|
+
cardOutputForText,
|
|
2065
2145
|
WRONGFORGE_REASONING,
|
|
2066
2146
|
wrongForgeRuntime,
|
|
2067
2147
|
setupProvider,
|
|
2068
2148
|
createGracefulShutdown
|
|
2069
2149
|
};
|
|
2070
|
-
//# sourceMappingURL=chunk-
|
|
2150
|
+
//# sourceMappingURL=chunk-EAATL6FL.js.map
|
|
@@ -201,6 +201,7 @@ var LoginAttemptStore = class _LoginAttemptStore {
|
|
|
201
201
|
store = /* @__PURE__ */ new Map();
|
|
202
202
|
writeTimer;
|
|
203
203
|
dirty = false;
|
|
204
|
+
writeTail = Promise.resolve();
|
|
204
205
|
filePath;
|
|
205
206
|
debounceMs;
|
|
206
207
|
retentionMs;
|
|
@@ -339,9 +340,7 @@ var LoginAttemptStore = class _LoginAttemptStore {
|
|
|
339
340
|
clearTimeout(this.writeTimer);
|
|
340
341
|
this.writeTimer = void 0;
|
|
341
342
|
}
|
|
342
|
-
|
|
343
|
-
await this.writeToDisk();
|
|
344
|
-
}
|
|
343
|
+
await this.writeToDisk();
|
|
345
344
|
}
|
|
346
345
|
scheduleWrite() {
|
|
347
346
|
this.dirty = true;
|
|
@@ -352,7 +351,14 @@ var LoginAttemptStore = class _LoginAttemptStore {
|
|
|
352
351
|
}, this.debounceMs);
|
|
353
352
|
this.writeTimer.unref?.();
|
|
354
353
|
}
|
|
355
|
-
|
|
354
|
+
writeToDisk() {
|
|
355
|
+
const pending = this.writeTail.then(() => {
|
|
356
|
+
return this.dirty ? this.writeSnapshotToDisk() : void 0;
|
|
357
|
+
});
|
|
358
|
+
this.writeTail = pending.catch(() => void 0);
|
|
359
|
+
return pending;
|
|
360
|
+
}
|
|
361
|
+
async writeSnapshotToDisk() {
|
|
356
362
|
this.dirty = false;
|
|
357
363
|
const now = Date.now();
|
|
358
364
|
const cutoff = now - this.retentionMs;
|
|
@@ -3733,52 +3739,51 @@ ${terminalText("Reachable from other machines on your network:", "blue", { bold:
|
|
|
3733
3739
|
|
|
3734
3740
|
// src/hq-server/server-lifecycle.ts
|
|
3735
3741
|
function createHqServerShutdown(params) {
|
|
3736
|
-
let
|
|
3737
|
-
return () =>
|
|
3738
|
-
if (
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
ws.terminate();
|
|
3756
|
-
} catch {
|
|
3742
|
+
let closing;
|
|
3743
|
+
return () => {
|
|
3744
|
+
if (closing) return closing;
|
|
3745
|
+
closing = new Promise((res) => {
|
|
3746
|
+
clearInterval(params.cleanupTimer);
|
|
3747
|
+
clearInterval(params.browserHeartbeatTimer);
|
|
3748
|
+
clearInterval(params.timeseriesFlushTimer);
|
|
3749
|
+
clearInterval(params.sessionCleanupTimer);
|
|
3750
|
+
params.stopAlertEngine();
|
|
3751
|
+
params.authWatcher.close();
|
|
3752
|
+
params.snapshotBroadcaster.close();
|
|
3753
|
+
params.bootstrapStore.clear();
|
|
3754
|
+
params.persistence.timeseries.flush();
|
|
3755
|
+
for (const ws of [...params.browsers, ...params.clients.keys()]) {
|
|
3756
|
+
try {
|
|
3757
|
+
ws.close(1001, "HQ shutting down");
|
|
3758
|
+
ws.terminate();
|
|
3759
|
+
} catch {
|
|
3760
|
+
}
|
|
3757
3761
|
}
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
params.
|
|
3779
|
-
|
|
3762
|
+
params.wss.close();
|
|
3763
|
+
params.mailboxManager.close();
|
|
3764
|
+
params.httpServer.close(() => {
|
|
3765
|
+
const mailboxCloses = [...params.mailboxManager.mailboxGateways.values()].map(
|
|
3766
|
+
({ mailbox }) => mailbox.close().catch(() => void 0)
|
|
3767
|
+
);
|
|
3768
|
+
params.mailboxManager.mailboxGateways.clear();
|
|
3769
|
+
params.mailboxManager.mailboxGatewayLastUsed.clear();
|
|
3770
|
+
void Promise.allSettled([
|
|
3771
|
+
...mailboxCloses,
|
|
3772
|
+
// Chimera/race: flush the login-attempt store INSIDE the awaited
|
|
3773
|
+
// shutdown set — the old fire-and-forget `void flush()` let close()
|
|
3774
|
+
// resolve before the debounced write landed, so persistence tests
|
|
3775
|
+
// had to sleep past it (and restarts could miss lockout state).
|
|
3776
|
+
params.loginAttempts.flush(),
|
|
3777
|
+
params.persistence.eventLog.drain(),
|
|
3778
|
+
params.persistence.snapshotStore.drain(),
|
|
3779
|
+
params.persistence.timeseries.drain(),
|
|
3780
|
+
params.persistence.kanban.drain(),
|
|
3781
|
+
params.persistence.sage?.drain()
|
|
3782
|
+
]).then(() => clearHqRuntimeMarker(params.dataDir, params.hqUrl)).catch(() => void 0).finally(() => res());
|
|
3783
|
+
});
|
|
3780
3784
|
});
|
|
3781
|
-
|
|
3785
|
+
return closing;
|
|
3786
|
+
};
|
|
3782
3787
|
}
|
|
3783
3788
|
|
|
3784
3789
|
// src/hq-server/socket-credentials.ts
|
|
@@ -5385,4 +5390,4 @@ export {
|
|
|
5385
5390
|
startHqServer,
|
|
5386
5391
|
HqInsecureExposureError2 as HqInsecureExposureError
|
|
5387
5392
|
};
|
|
5388
|
-
//# sourceMappingURL=chunk-
|
|
5393
|
+
//# sourceMappingURL=chunk-FWUIKCCO.js.map
|