@wrongstack/cli 1.0.1 → 1.0.4
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/data/providers.json +21 -21
- package/dist/{acp-3LARESEO.js → acp-AB54FWM2.js} +122 -39
- package/dist/acp-agent-list.d.ts +14 -0
- package/dist/acp-hq-telemetry.d.ts +9 -2
- package/dist/acp-mcp-servers.d.ts +49 -0
- package/dist/acp-server-agent.d.ts +18 -6
- package/dist/{auth-ZUMCDNE5.js → auth-WDMSNZ3S.js} +79 -55
- package/dist/auth-menu/index.d.ts +1 -0
- package/dist/auth-menu/oauth-menu.d.ts +3 -1
- package/dist/auth-menu/panel-service.d.ts +2 -0
- package/dist/auth-menu/provider-auth-login.d.ts +12 -0
- package/dist/auth-menu/types.d.ts +3 -0
- package/dist/auto-discover-providers-DXR25GTG.js +7 -0
- package/dist/boot/dispatch-webui.d.ts +1 -0
- package/dist/boot/short-circuit-hq.d.ts +2 -0
- package/dist/boot/system-prompt-builder.d.ts +7 -0
- package/dist/boot/system-prompt.d.ts +2 -1
- package/dist/boot/tool-registry.d.ts +18 -1
- package/dist/chimera-reviewer-policy.d.ts +1 -1
- package/dist/{chunk-C2E24IXZ.js → chunk-3I5ZJXM5.js} +147 -241
- package/dist/{chunk-JHPXJRRI.js → chunk-4XCBEUBX.js} +13 -3
- package/dist/{chunk-FPIWTJ2G.js → chunk-6WRKAACA.js} +4 -4
- package/dist/chunk-AUQDGU5D.js +32 -0
- package/dist/{chunk-D2VCUN7M.js → chunk-BIWE22O5.js} +17 -17
- package/dist/{chunk-VOTTENR5.js → chunk-CDY4D5QK.js} +2 -2
- package/dist/chunk-D5GB5MHA.js +87 -0
- package/dist/chunk-DAKVBMD4.js +36 -0
- package/dist/{chunk-E6RFXHWD.js → chunk-EK2P53GL.js} +3 -2
- package/dist/chunk-I7V2OYVH.js +242 -0
- package/dist/{chunk-MXEJEYT7.js → chunk-JX6KL7OF.js} +15 -5
- package/dist/{chunk-ZSZ3EYWH.js → chunk-KEPABQYT.js} +109 -6
- package/dist/{chunk-IMWXXF4J.js → chunk-KNMIBKLV.js} +79 -1
- package/dist/{chunk-MNQQ4ZNF.js → chunk-ONOT5OJ2.js} +290 -687
- package/dist/chunk-Q7E3BPDU.js +62 -0
- package/dist/chunk-SIGUWXAA.js +43 -0
- package/dist/{chunk-TEBMCYZN.js → chunk-SIS37L3W.js} +58 -2
- package/dist/{chunk-KHWDTNBZ.js → chunk-U6PGWDMZ.js} +5 -5
- package/dist/{chunk-5IA5337I.js → chunk-XJ7K67PP.js} +8 -2
- package/dist/{cli-context-7X3M6U73.js → cli-context-WFC3BNGM.js} +131 -25
- package/dist/{cli-main-53KG6HAV.js → cli-main-GU3YZLMO.js} +3986 -2827
- package/dist/{diag-doctor-7LYUYU35.js → diag-doctor-PCER6KHH.js} +2 -2
- package/dist/execute-deps.d.ts +1 -0
- package/dist/{execution-MIBWBYB6.js → execution-RAZDDQFC.js} +115 -16
- package/dist/execution-specialist-trigger.d.ts +28 -0
- package/dist/fleet/acp-live-progress.d.ts +19 -0
- package/dist/fleet/host-acp-runner-cache.d.ts +3 -1
- package/dist/fleet/host-acp.d.ts +14 -2
- package/dist/fleet/host.d.ts +1 -0
- package/dist/{hq-IG3YRGCO.js → hq-5XHEIIH6.js} +127 -8
- package/dist/hq-command-controller.d.ts +31 -2
- package/dist/hq-server/client-address.d.ts +2 -0
- package/dist/hq-server/ip-allowlist.d.ts +16 -0
- package/dist/hq-server/preflight.d.ts +1 -0
- package/dist/hq-server/routes/auth/password-routes.d.ts +1 -1
- package/dist/hq-server/routes.d.ts +5 -4
- package/dist/hq-server/secret-input.d.ts +7 -0
- package/dist/hq-server/types.d.ts +3 -2
- package/dist/hq-server/upgrade-handler.d.ts +2 -0
- package/dist/hq-server/utils.d.ts +6 -0
- package/dist/{hq-server-OILU3NPI.js → hq-server-CNUTBWTK.js} +4 -3
- package/dist/hq-server.d.ts +4 -0
- package/dist/hq-service-L5INQFM4.js +507 -0
- package/dist/hq-service.d.ts +22 -0
- package/dist/index.js +4 -4
- package/dist/ip-allowlist-NHXO6AKJ.js +9 -0
- package/dist/live-settings-input.d.ts +4 -0
- package/dist/{mailbox-serve-VUCWZ2SJ.js → mailbox-serve-X3CR6VFW.js} +4 -3
- package/dist/{modeldiag-FMJT37SN.js → modeldiag-46CMWUNM.js} +31 -24
- package/dist/{per-subcommand-help-BWBHYVJO.js → per-subcommand-help-DHTYU524.js} +2 -2
- package/dist/{plugin-usage-HFBI3TFT.js → plugin-usage-M6KET4OZ.js} +2 -2
- package/dist/{plugins-PZ2VZL7V.js → plugins-WJLW6ULV.js} +3 -3
- package/dist/projects-LMNAGGEU.js +36 -0
- package/dist/{providers-models-YVMVYWRS.js → providers-models-6MOGAOVK.js} +2 -2
- package/dist/{proxy-wiring-MGRSKZZB.js → proxy-wiring-K2DORFFL.js} +3 -3
- package/dist/short-circuit-flags-YDMLAQ5R.js +10 -0
- package/dist/slash-commands/acp.d.ts +3 -0
- package/dist/slash-commands/codebase-map.d.ts +11 -0
- package/dist/slash-commands/command-context.d.ts +29 -0
- package/dist/slash-commands/context.d.ts +10 -0
- package/dist/slash-commands/ensemble.d.ts +1 -1
- package/dist/slash-commands/openai-quota.d.ts +31 -0
- package/dist/slash-commands/profile.d.ts +7 -0
- package/dist/subcommands/handlers/hq.d.ts +1 -0
- package/dist/subcommands/handlers/projects.d.ts +14 -0
- package/dist/{subcommands-WJLBHVKC.js → subcommands-7N4RIK6H.js} +2 -2
- package/dist/{version-help-MYKF724O.js → version-help-WXI42PZ3.js} +2 -2
- package/dist/{webui-server-5R35BHWZ.js → webui-server-OBV5JYJV.js} +27 -4
- package/dist/webui-server-options.d.ts +1 -0
- package/dist/wiring/atlas-prompt-contributor.d.ts +54 -0
- package/dist/wiring/cli-execute-builder.d.ts +1 -0
- package/dist/wiring/cli-slash-commands-setup.d.ts +7 -0
- package/dist/wiring/codebase-embeddings.d.ts +31 -0
- package/dist/wiring/command-host-state.d.ts +9 -0
- package/dist/wiring/concept-summarizer.d.ts +32 -0
- package/dist/wiring/external-plugins.d.ts +1 -0
- package/dist/wiring/lifecycle-plugins.d.ts +2 -1
- package/dist/wiring/pipeline.d.ts +2 -0
- package/dist/wiring/plugins.d.ts +2 -1
- package/dist/wiring/provider-runtime-setup.d.ts +1 -1
- package/dist/wiring/provider.d.ts +2 -1
- package/dist/wiring/session-command-handlers.d.ts +2 -1
- package/dist/wiring/slash-commands.d.ts +1 -0
- package/package.json +29 -29
- package/dist/auto-discover-providers-VQU3IZMR.js +0 -7
- package/dist/chunk-52C7PD2H.js +0 -61
- package/dist/chunk-Q5GTM25S.js +0 -17
- package/dist/chunk-TNK6237M.js +0 -262
- package/dist/projects-L6C6XLDY.js +0 -37
- package/dist/short-circuit-flags-UREFSYBL.js +0 -10
|
@@ -129,11 +129,21 @@ function scheduleImmediateProbe(runner) {
|
|
|
129
129
|
void runner.poke();
|
|
130
130
|
}
|
|
131
131
|
function buildHealthUrl(rawBase) {
|
|
132
|
-
const trimmed = rawBase.trim()
|
|
133
|
-
|
|
132
|
+
const trimmed = rawBase.trim();
|
|
133
|
+
try {
|
|
134
|
+
const base = new URL(trimmed);
|
|
135
|
+
base.search = "";
|
|
136
|
+
base.hash = "";
|
|
137
|
+
base.pathname = `${base.pathname.replace(/\/+$/, "")}${HEALTH_PATH}`;
|
|
138
|
+
return base.toString();
|
|
139
|
+
} catch {
|
|
140
|
+
const boundary = trimmed.search(/[?#]/);
|
|
141
|
+
const pathBase = boundary === -1 ? trimmed : trimmed.slice(0, boundary);
|
|
142
|
+
return `${pathBase.replace(/\/+$/, "")}${HEALTH_PATH}`;
|
|
143
|
+
}
|
|
134
144
|
}
|
|
135
145
|
|
|
136
146
|
export {
|
|
137
147
|
startProxyProbe
|
|
138
148
|
};
|
|
139
|
-
//# sourceMappingURL=chunk-
|
|
149
|
+
//# sourceMappingURL=chunk-4XCBEUBX.js.map
|
|
@@ -67,12 +67,12 @@ var helpCmd = async (_args, deps) => {
|
|
|
67
67
|
color.bold("Common flags"),
|
|
68
68
|
" --yolo / --no-yolo Force auto-approval on or off at startup",
|
|
69
69
|
" --confirm-destructive Deprecated \u2014 YOLO no longer prompts by destructiveness",
|
|
70
|
-
" --yolo-destructive
|
|
70
|
+
" --yolo-destructive Let YOLO run every destructive kind it is allowed to (see /yolo confirm)",
|
|
71
71
|
" --tui / --no-tui Force or disable TUI mode",
|
|
72
72
|
" --mouse Full mouse mode in the TUI (in-app scroll + clickable UI)",
|
|
73
73
|
" --desktop Open WrongStack Desktop (requires @wrongstack/desktop)",
|
|
74
|
-
" --hq [--host <h>] [--port <n>] [--password <secret>] [--tunnel] [--open]",
|
|
75
|
-
" Start HQ;
|
|
74
|
+
" --hq [--host <h>] [--port <n>] [--password <secret>] [--hq-allowlist <ip,cidr,...>] [--tunnel] [--hq-public-url <https-origin>] [--open]",
|
|
75
|
+
" Start HQ; publish through a temporary tunnel or persistent TLS proxy",
|
|
76
76
|
" --webui [--host <h>] [--port <n>] [--webui-token <t>] [--open]",
|
|
77
77
|
" [--webui-public-url <url>] [--webui-public-ws-url <url>] [--webui-require-token]",
|
|
78
78
|
" Serve the browser UI + WS bridge (prints a token URL,",
|
|
@@ -93,4 +93,4 @@ export {
|
|
|
93
93
|
versionCmd,
|
|
94
94
|
helpCmd
|
|
95
95
|
};
|
|
96
|
-
//# sourceMappingURL=chunk-
|
|
96
|
+
//# sourceMappingURL=chunk-6WRKAACA.js.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
// src/hq-server/secret-input.ts
|
|
3
|
+
import * as fs from "node:fs/promises";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
var MAX_PASSWORD_FILE_BYTES = 4096;
|
|
6
|
+
async function resolveHqPasswordInput(options = {}) {
|
|
7
|
+
const environment = options.environment ?? process.env;
|
|
8
|
+
const direct = options.explicitPassword ?? environment.WRONGSTACK_HQ_PASSWORD;
|
|
9
|
+
const file = environment.WRONGSTACK_HQ_PASSWORD_FILE;
|
|
10
|
+
if (direct !== void 0 && file !== void 0) {
|
|
11
|
+
throw new Error(
|
|
12
|
+
"Set only one of --password/WRONGSTACK_HQ_PASSWORD or WRONGSTACK_HQ_PASSWORD_FILE."
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
if (file === void 0) return direct;
|
|
16
|
+
if (!path.isAbsolute(file)) {
|
|
17
|
+
throw new Error("WRONGSTACK_HQ_PASSWORD_FILE must be an absolute path.");
|
|
18
|
+
}
|
|
19
|
+
const stat2 = await fs.stat(file);
|
|
20
|
+
if (!stat2.isFile()) throw new Error("WRONGSTACK_HQ_PASSWORD_FILE must point to a regular file.");
|
|
21
|
+
if (stat2.size > MAX_PASSWORD_FILE_BYTES) {
|
|
22
|
+
throw new Error(`WRONGSTACK_HQ_PASSWORD_FILE exceeds ${MAX_PASSWORD_FILE_BYTES} bytes.`);
|
|
23
|
+
}
|
|
24
|
+
const raw = await fs.readFile(file, "utf8");
|
|
25
|
+
if (raw.includes("\0")) throw new Error("WRONGSTACK_HQ_PASSWORD_FILE contains a NUL byte.");
|
|
26
|
+
return raw.replace(/\r?\n$/, "");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export {
|
|
30
|
+
resolveHqPasswordInput
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=chunk-AUQDGU5D.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
2
|
// src/subcommands/index.ts
|
|
3
3
|
var loaders = {
|
|
4
|
-
acp: async () => (await import("./acp-
|
|
4
|
+
acp: async () => (await import("./acp-AB54FWM2.js")).acpCmd,
|
|
5
5
|
init: async () => (await import("./init-DRMMFG2G.js")).initCmd,
|
|
6
|
-
auth: async () => (await import("./auth-
|
|
6
|
+
auth: async () => (await import("./auth-WDMSNZ3S.js")).authCmd,
|
|
7
7
|
update: async () => (await import("./update-5DPB4YD4.js")).updateCmd,
|
|
8
8
|
sessions: async () => (await import("./sessions-config-UL45XKX7.js")).sessionsCmd,
|
|
9
9
|
config: async () => (await import("./sessions-config-UL45XKX7.js")).configCmd,
|
|
@@ -14,25 +14,25 @@ var loaders = {
|
|
|
14
14
|
audit: async () => (await import("./audit-46YK5DSC.js")).auditCmd,
|
|
15
15
|
tools: async () => (await import("./tools-skills-GH24UCBY.js")).toolsCmd,
|
|
16
16
|
skills: async () => (await import("./tools-skills-GH24UCBY.js")).skillsCmd,
|
|
17
|
-
providers: async () => (await import("./providers-models-
|
|
18
|
-
models: async () => (await import("./providers-models-
|
|
17
|
+
providers: async () => (await import("./providers-models-6MOGAOVK.js")).providersCmd,
|
|
18
|
+
models: async () => (await import("./providers-models-6MOGAOVK.js")).modelsCmd,
|
|
19
19
|
mcp: async () => (await import("./mcp-HOMLC4WE.js")).mcpCmd,
|
|
20
|
-
plugin: async () => (await import("./plugin-usage-
|
|
21
|
-
plugins: async () => (await import("./plugin-usage-
|
|
22
|
-
diag: async () => (await import("./diag-doctor-
|
|
23
|
-
doctor: async () => (await import("./diag-doctor-
|
|
24
|
-
"proxy-status": async () => (await import("./diag-doctor-
|
|
20
|
+
plugin: async () => (await import("./plugin-usage-M6KET4OZ.js")).pluginCmd,
|
|
21
|
+
plugins: async () => (await import("./plugin-usage-M6KET4OZ.js")).pluginCmd,
|
|
22
|
+
diag: async () => (await import("./diag-doctor-PCER6KHH.js")).diagCmd,
|
|
23
|
+
doctor: async () => (await import("./diag-doctor-PCER6KHH.js")).doctorCmd,
|
|
24
|
+
"proxy-status": async () => (await import("./diag-doctor-PCER6KHH.js")).proxyCmd,
|
|
25
25
|
export: async () => (await import("./export-VVRIOWFV.js")).exportCmd,
|
|
26
|
-
usage: async () => (await import("./plugin-usage-
|
|
27
|
-
version: async () => (await import("./version-help-
|
|
28
|
-
help: async () => (await import("./version-help-
|
|
29
|
-
projects: async () => (await import("./projects-
|
|
30
|
-
modeldiag: async () => (await import("./modeldiag-
|
|
26
|
+
usage: async () => (await import("./plugin-usage-M6KET4OZ.js")).usageCmd,
|
|
27
|
+
version: async () => (await import("./version-help-WXI42PZ3.js")).versionCmd,
|
|
28
|
+
help: async () => (await import("./version-help-WXI42PZ3.js")).helpCmd,
|
|
29
|
+
projects: async () => (await import("./projects-LMNAGGEU.js")).projectsCmd,
|
|
30
|
+
modeldiag: async () => (await import("./modeldiag-46CMWUNM.js")).modeldiagCmd,
|
|
31
31
|
quick: async () => (await import("./quick-CNB4Z3HS.js")).quickCmd,
|
|
32
32
|
bench: async () => (await import("./bench-YBU6BVQP.js")).benchCmd,
|
|
33
33
|
chronicle: async () => (await import("./chronicle-UTFETHP6.js")).chronicleCmd,
|
|
34
|
-
hq: async () => (await import("./hq-
|
|
35
|
-
mailbox: async () => (await import("./mailbox-serve-
|
|
34
|
+
hq: async () => (await import("./hq-5XHEIIH6.js")).hqCmd,
|
|
35
|
+
mailbox: async () => (await import("./mailbox-serve-X3CR6VFW.js")).mailboxServeCmd,
|
|
36
36
|
permissions: async () => (await import("./permissions-CFDLXETM.js")).permissionsCmd,
|
|
37
37
|
project: async () => (await import("./project-AOQI5XTK.js")).projectCmd,
|
|
38
38
|
governance: async () => (await import("./governance-RYSHV675.js")).governanceCmd
|
|
@@ -51,4 +51,4 @@ export {
|
|
|
51
51
|
subcommands,
|
|
52
52
|
subcommandNames
|
|
53
53
|
};
|
|
54
|
-
//# sourceMappingURL=chunk-
|
|
54
|
+
//# sourceMappingURL=chunk-BIWE22O5.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
startProxyProbe
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4XCBEUBX.js";
|
|
4
4
|
|
|
5
5
|
// src/wiring/proxy-wiring.ts
|
|
6
6
|
import { applyProxyConfig } from "@wrongstack/core/wiring/proxy-rewrite";
|
|
@@ -53,4 +53,4 @@ export {
|
|
|
53
53
|
bootstrapWrongProxy,
|
|
54
54
|
shutdownWrongProxy
|
|
55
55
|
};
|
|
56
|
-
//# sourceMappingURL=chunk-
|
|
56
|
+
//# sourceMappingURL=chunk-CDY4D5QK.js.map
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
|
|
2
|
+
// src/boot/auto-discover-providers.ts
|
|
3
|
+
import * as fs from "node:fs/promises";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { discoverOpenAICompatibleModels, resolveDiscoveryTargets } from "@wrongstack/providers";
|
|
6
|
+
async function readCache(file) {
|
|
7
|
+
try {
|
|
8
|
+
return JSON.parse(await fs.readFile(file, "utf8"));
|
|
9
|
+
} catch {
|
|
10
|
+
return {};
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
async function discoverAndMergeProviders(opts) {
|
|
14
|
+
const targets = resolveDiscoveryTargets(opts.config);
|
|
15
|
+
if (targets.length === 0) return;
|
|
16
|
+
const cacheFile = path.join(opts.cacheDir, "discovered-models-cache.json");
|
|
17
|
+
const cache = await readCache(cacheFile);
|
|
18
|
+
let cacheDirty = false;
|
|
19
|
+
await Promise.all(
|
|
20
|
+
targets.map(
|
|
21
|
+
async ({
|
|
22
|
+
id,
|
|
23
|
+
cfg,
|
|
24
|
+
baseUrl,
|
|
25
|
+
apiKey,
|
|
26
|
+
cacheKey,
|
|
27
|
+
modelDiscoveryPath,
|
|
28
|
+
modelDiscoveryAuthoritative
|
|
29
|
+
}) => {
|
|
30
|
+
const provider = await discoverOpenAICompatibleModels(id, {
|
|
31
|
+
baseUrl,
|
|
32
|
+
apiKey,
|
|
33
|
+
headers: cfg.headers,
|
|
34
|
+
providerName: id,
|
|
35
|
+
modelDiscoveryPath,
|
|
36
|
+
fetchImpl: opts.fetchImpl
|
|
37
|
+
});
|
|
38
|
+
if (provider) {
|
|
39
|
+
const fetchedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
40
|
+
cache[cacheKey] = { fetchedAt, provider };
|
|
41
|
+
cacheDirty = true;
|
|
42
|
+
if (modelDiscoveryAuthoritative) {
|
|
43
|
+
opts.registry.mergeOverlay(
|
|
44
|
+
{ [id]: provider },
|
|
45
|
+
{ observedAt: fetchedAt, authoritativeProviderIds: [id] }
|
|
46
|
+
);
|
|
47
|
+
} else {
|
|
48
|
+
opts.registry.mergeOverlay({ [id]: provider });
|
|
49
|
+
}
|
|
50
|
+
opts.logger?.info(
|
|
51
|
+
`auto-discovered ${Object.keys(provider.models).length} models for "${id}" from ${baseUrl}`
|
|
52
|
+
);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const cached = cache[cacheKey];
|
|
56
|
+
if (cached) {
|
|
57
|
+
if (modelDiscoveryAuthoritative) {
|
|
58
|
+
opts.registry.mergeOverlay(
|
|
59
|
+
{ [id]: cached.provider },
|
|
60
|
+
{ observedAt: cached.fetchedAt, authoritativeProviderIds: [id] }
|
|
61
|
+
);
|
|
62
|
+
} else {
|
|
63
|
+
opts.registry.mergeOverlay({ [id]: cached.provider });
|
|
64
|
+
}
|
|
65
|
+
opts.logger?.warn(
|
|
66
|
+
`auto-discovery for "${id}" failed; using ${Object.keys(cached.provider.models).length} cached models from ${cached.fetchedAt}`
|
|
67
|
+
);
|
|
68
|
+
} else {
|
|
69
|
+
opts.logger?.warn(
|
|
70
|
+
`auto-discovery for "${id}" failed and no cache available (server at ${baseUrl} unreachable?)`
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
)
|
|
75
|
+
);
|
|
76
|
+
if (cacheDirty) {
|
|
77
|
+
try {
|
|
78
|
+
await fs.writeFile(cacheFile, JSON.stringify(cache), "utf8");
|
|
79
|
+
} catch {
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export {
|
|
85
|
+
discoverAndMergeProviders
|
|
86
|
+
};
|
|
87
|
+
//# sourceMappingURL=chunk-D5GB5MHA.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
// src/auth-menu/loopback-server.ts
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
import {
|
|
5
|
+
startLoopbackServer as startSharedLoopbackServer
|
|
6
|
+
} from "@wrongstack/providers/oauth";
|
|
7
|
+
import { callbackHtml } from "@wrongstack/providers/oauth";
|
|
8
|
+
var URL_METACHAR_REGEX = /[&|;<>(){}^"'`%\n\r\0]/;
|
|
9
|
+
function isSafeBrowserUrl(url) {
|
|
10
|
+
if (URL_METACHAR_REGEX.test(url)) return false;
|
|
11
|
+
try {
|
|
12
|
+
const parsed = new URL(url);
|
|
13
|
+
return parsed.protocol === "http:" || parsed.protocol === "https:";
|
|
14
|
+
} catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function openBrowser(url) {
|
|
19
|
+
if (!isSafeBrowserUrl(url)) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
const platform = process.platform;
|
|
24
|
+
const { command, args } = platform === "win32" ? { command: "cmd", args: ["/c", "start", "", url] } : platform === "darwin" ? { command: "open", args: [url] } : { command: "xdg-open", args: [url] };
|
|
25
|
+
const child = spawn(command, args, { stdio: "ignore", windowsHide: true });
|
|
26
|
+
child.on("error", () => {
|
|
27
|
+
});
|
|
28
|
+
child.unref();
|
|
29
|
+
} catch {
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
openBrowser
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=chunk-DAKVBMD4.js.map
|
|
@@ -12,7 +12,6 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
12
12
|
"version",
|
|
13
13
|
"yes",
|
|
14
14
|
"no-banner",
|
|
15
|
-
"no-features",
|
|
16
15
|
"tui",
|
|
17
16
|
"no-tui",
|
|
18
17
|
// Recovery switches. `--recover` reopens the most recent session with no
|
|
@@ -64,6 +63,8 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
64
63
|
"pnpm",
|
|
65
64
|
"yarn",
|
|
66
65
|
"bun",
|
|
66
|
+
// `wstack hq service install` toggles.
|
|
67
|
+
"no-auto-update",
|
|
67
68
|
// `wstack acp` booleans. Without these, parseArgs treats the value after
|
|
68
69
|
// `--fs`/`--echo` as the flag's value and eats a following positional
|
|
69
70
|
// (e.g. the agent list in `acp bench --fs gemini-cli,codex-cli`).
|
|
@@ -237,4 +238,4 @@ export {
|
|
|
237
238
|
parseAuthFlags,
|
|
238
239
|
parseSpawnFlags
|
|
239
240
|
};
|
|
240
|
-
//# sourceMappingURL=chunk-
|
|
241
|
+
//# sourceMappingURL=chunk-EK2P53GL.js.map
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
|
|
2
|
+
// src/hq-server/audit-actor.ts
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
function resolveAuditActor() {
|
|
5
|
+
const user = (process.env.USERNAME ?? process.env.USER ?? "").toString();
|
|
6
|
+
try {
|
|
7
|
+
const host = os.hostname();
|
|
8
|
+
return user ? `${user}@${host}` : `cli@${host}`;
|
|
9
|
+
} catch {
|
|
10
|
+
return user ? `${user}@unknown` : "cli";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// src/hq-server/utils.ts
|
|
15
|
+
import * as fs from "node:fs/promises";
|
|
16
|
+
import * as os2 from "node:os";
|
|
17
|
+
import * as path from "node:path";
|
|
18
|
+
import { resolveHqDataDir } from "@wrongstack/core/hq";
|
|
19
|
+
import { sanitizeApiError, scrubErrorDetail } from "@wrongstack/core/security";
|
|
20
|
+
var TRANSCRIPT_RING_MAX = 4e3;
|
|
21
|
+
var MAX_TRANSCRIPT_SESSIONS = 400;
|
|
22
|
+
var MAX_AGENT_RINGS = 800;
|
|
23
|
+
function evictOldest(map, max) {
|
|
24
|
+
while (map.size > max) {
|
|
25
|
+
const oldest = map.keys().next().value;
|
|
26
|
+
if (oldest === void 0) break;
|
|
27
|
+
map.delete(oldest);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function agentRingKey(sessionId, subId) {
|
|
31
|
+
return sessionId ? `${sessionId}::${subId}` : subId;
|
|
32
|
+
}
|
|
33
|
+
function agentMessageToEntry(p) {
|
|
34
|
+
const kind = typeof p["kind"] === "string" ? p["kind"] : "text";
|
|
35
|
+
const role = kind === "thinking" ? "thinking" : kind === "tool_use" || kind === "tool_result" ? "tool" : kind === "error" ? "error" : kind === "status" || kind === "system" ? "system" : "assistant";
|
|
36
|
+
return {
|
|
37
|
+
ts: typeof p["ts"] === "string" ? p["ts"] : (/* @__PURE__ */ new Date()).toISOString(),
|
|
38
|
+
role,
|
|
39
|
+
text: typeof p["content"] === "string" ? p["content"] : "",
|
|
40
|
+
...typeof p["toolName"] === "string" ? { tool: p["toolName"] } : {},
|
|
41
|
+
...kind === "error" ? { isError: true } : {}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
async function readLocalSubagentTranscript(sessionId, subagentId) {
|
|
45
|
+
try {
|
|
46
|
+
const { getSessionRegistry } = await import("@wrongstack/core/storage");
|
|
47
|
+
const { resolveWstackPaths, sessionScopedPath } = await import("@wrongstack/core/utils");
|
|
48
|
+
const globalRoot = path.dirname(resolveHqDataDir());
|
|
49
|
+
const registry = getSessionRegistry(globalRoot);
|
|
50
|
+
const entry = await registry.get(sessionId).catch(() => null);
|
|
51
|
+
if (!entry) return null;
|
|
52
|
+
const paths = resolveWstackPaths({ projectRoot: entry.projectRoot, globalRoot });
|
|
53
|
+
const sessionDir = sessionScopedPath(paths.projectSessions, sessionId, "");
|
|
54
|
+
if (!isSafePathSegment(subagentId)) return null;
|
|
55
|
+
const transcriptsRoot = path.resolve(sessionDir, "subagents", "transcripts");
|
|
56
|
+
const file = path.resolve(transcriptsRoot, subagentId, "transcript.jsonl");
|
|
57
|
+
if (!file.startsWith(transcriptsRoot + path.sep)) return null;
|
|
58
|
+
const raw = await fs.readFile(file, "utf8").catch(() => null);
|
|
59
|
+
if (raw === null) return null;
|
|
60
|
+
const out = [];
|
|
61
|
+
for (const line of raw.split("\n")) {
|
|
62
|
+
const trimmed = line.trim();
|
|
63
|
+
if (trimmed.length === 0) continue;
|
|
64
|
+
try {
|
|
65
|
+
out.push(agentMessageToEntry(JSON.parse(trimmed)));
|
|
66
|
+
} catch {
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return out;
|
|
70
|
+
} catch {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function decodePathSegment(value) {
|
|
75
|
+
let decoded;
|
|
76
|
+
try {
|
|
77
|
+
decoded = decodeURIComponent(value);
|
|
78
|
+
} catch {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
return isSafePathSegment(decoded) ? decoded : null;
|
|
82
|
+
}
|
|
83
|
+
function decodeSessionId(value) {
|
|
84
|
+
let decoded;
|
|
85
|
+
try {
|
|
86
|
+
decoded = decodeURIComponent(value);
|
|
87
|
+
} catch {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
return isSafeSessionId(decoded) ? decoded : null;
|
|
91
|
+
}
|
|
92
|
+
var MAX_PATH_SEGMENT_LENGTH = 256;
|
|
93
|
+
function isSafePathSegment(value) {
|
|
94
|
+
if (value.length === 0 || value.length > MAX_PATH_SEGMENT_LENGTH) return false;
|
|
95
|
+
if (value === "." || value === "..") return false;
|
|
96
|
+
if (value.includes("/") || value.includes("\\")) return false;
|
|
97
|
+
if (value.includes("\0")) return false;
|
|
98
|
+
if (value.includes(":")) return false;
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
function isSafeSessionId(value) {
|
|
102
|
+
if (value.length === 0 || value.length > MAX_PATH_SEGMENT_LENGTH) return false;
|
|
103
|
+
if (value.includes("\\") || value.includes("\0") || value.includes(":")) return false;
|
|
104
|
+
const parts = value.split("/");
|
|
105
|
+
if (parts.length > 2) return false;
|
|
106
|
+
return parts.every((p) => p.length > 0 && p !== "." && p !== "..");
|
|
107
|
+
}
|
|
108
|
+
function displayHost(host) {
|
|
109
|
+
return host === "0.0.0.0" ? "127.0.0.1" : host;
|
|
110
|
+
}
|
|
111
|
+
var RequestBodyTooLargeError = class extends Error {
|
|
112
|
+
};
|
|
113
|
+
function readRequestBody(req, maxBytes = 1e6) {
|
|
114
|
+
return new Promise((resolve2, reject) => {
|
|
115
|
+
const chunks = [];
|
|
116
|
+
let size = 0;
|
|
117
|
+
let settled = false;
|
|
118
|
+
req.on("data", (chunk) => {
|
|
119
|
+
if (settled) return;
|
|
120
|
+
size += chunk.length;
|
|
121
|
+
if (size > maxBytes) {
|
|
122
|
+
settled = true;
|
|
123
|
+
chunks.length = 0;
|
|
124
|
+
reject(new RequestBodyTooLargeError("request body too large"));
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
chunks.push(chunk);
|
|
128
|
+
});
|
|
129
|
+
req.on("end", () => {
|
|
130
|
+
if (!settled) resolve2(Buffer.concat(chunks).toString("utf8"));
|
|
131
|
+
});
|
|
132
|
+
req.on("error", (error) => {
|
|
133
|
+
if (!settled) reject(error);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
function writeInvalidBody(res, error) {
|
|
138
|
+
const tooLarge = error instanceof RequestBodyTooLargeError;
|
|
139
|
+
res.writeHead(tooLarge ? 413 : 400, { "Content-Type": "application/json" });
|
|
140
|
+
res.end(JSON.stringify({ error: tooLarge ? "request body too large" : "invalid json body" }));
|
|
141
|
+
}
|
|
142
|
+
function buildHttpUrl(host, port, token) {
|
|
143
|
+
const url = new URL(`http://${displayHost(host)}:${port}/`);
|
|
144
|
+
if (token) url.searchParams.set("token", token);
|
|
145
|
+
return url.toString();
|
|
146
|
+
}
|
|
147
|
+
function buildBootstrapHttpUrl(host, port, bootstrapCode) {
|
|
148
|
+
const url = new URL(`http://${displayHost(host)}:${port}/`);
|
|
149
|
+
url.hash = `bootstrap=${bootstrapCode}`;
|
|
150
|
+
return url.toString();
|
|
151
|
+
}
|
|
152
|
+
function buildClientWsUrl(host, port, token) {
|
|
153
|
+
const url = new URL(`ws://${displayHost(host)}:${port}/ws/client`);
|
|
154
|
+
if (token) url.searchParams.set("token", token);
|
|
155
|
+
return url.toString();
|
|
156
|
+
}
|
|
157
|
+
function normalizeHqPublicOrigin(value) {
|
|
158
|
+
const parsed = new URL(value.trim());
|
|
159
|
+
if (parsed.protocol !== "https:" || parsed.username !== "" || parsed.password !== "" || parsed.pathname !== "" && parsed.pathname !== "/" || parsed.search !== "" || parsed.hash !== "") {
|
|
160
|
+
throw new TypeError(
|
|
161
|
+
"HQ public URL must be an exact HTTPS origin without a path or credentials."
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
return parsed.origin;
|
|
165
|
+
}
|
|
166
|
+
function hqRuntimeMarkerPath(dataDir) {
|
|
167
|
+
return path.join(dataDir, "runtime.json");
|
|
168
|
+
}
|
|
169
|
+
function lanIPv4Addresses() {
|
|
170
|
+
const out = [];
|
|
171
|
+
try {
|
|
172
|
+
const ifaces = os2.networkInterfaces();
|
|
173
|
+
for (const name of Object.keys(ifaces)) {
|
|
174
|
+
for (const ni of ifaces[name] ?? []) {
|
|
175
|
+
if (ni.family === "IPv4" && !ni.internal) out.push(ni.address);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
} catch {
|
|
179
|
+
}
|
|
180
|
+
return out;
|
|
181
|
+
}
|
|
182
|
+
function truncateHqSummary(value, maxLength) {
|
|
183
|
+
if (typeof value !== "string" || value.length === 0) return void 0;
|
|
184
|
+
if (value.length <= maxLength) return value;
|
|
185
|
+
const suffix = `\u2026[truncated:${value.length - maxLength}]`;
|
|
186
|
+
if (maxLength <= suffix.length) return "\u2026";
|
|
187
|
+
const prefixLen = maxLength - suffix.length;
|
|
188
|
+
return `${value.slice(0, prefixLen)}${suffix}`;
|
|
189
|
+
}
|
|
190
|
+
function hqMachineKey(hostname2, machineId) {
|
|
191
|
+
const hn = hostname2?.trim();
|
|
192
|
+
return hn ? `host:${hn.toLowerCase()}` : `mid:${machineId || "local"}`;
|
|
193
|
+
}
|
|
194
|
+
function recordTimeseriesSignal(persistence, event) {
|
|
195
|
+
try {
|
|
196
|
+
if (event.type === "session.usage") {
|
|
197
|
+
const p = event.payload;
|
|
198
|
+
persistence.timeseries.record({
|
|
199
|
+
ts: Date.parse(event.timestamp) || Date.now(),
|
|
200
|
+
...typeof p.costUsd === "number" ? { costUsd: p.costUsd } : {},
|
|
201
|
+
...typeof p.inputTokens === "number" ? { inputTokens: p.inputTokens } : {},
|
|
202
|
+
...typeof p.outputTokens === "number" ? { outputTokens: p.outputTokens } : {},
|
|
203
|
+
...typeof p.model === "string" && p.model.length > 0 ? { model: p.model } : {},
|
|
204
|
+
...typeof p.provider === "string" && p.provider.length > 0 ? { provider: p.provider } : {},
|
|
205
|
+
...typeof p.cacheRead === "number" ? { cacheRead: p.cacheRead } : {},
|
|
206
|
+
...typeof p.cacheWrite === "number" ? { cacheWrite: p.cacheWrite } : {}
|
|
207
|
+
});
|
|
208
|
+
} else if (event.type === "tool.completed") {
|
|
209
|
+
persistence.timeseries.record({
|
|
210
|
+
ts: Date.parse(event.timestamp) || Date.now(),
|
|
211
|
+
toolCalls: 1
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
} catch {
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export {
|
|
219
|
+
resolveAuditActor,
|
|
220
|
+
TRANSCRIPT_RING_MAX,
|
|
221
|
+
MAX_TRANSCRIPT_SESSIONS,
|
|
222
|
+
MAX_AGENT_RINGS,
|
|
223
|
+
evictOldest,
|
|
224
|
+
agentRingKey,
|
|
225
|
+
agentMessageToEntry,
|
|
226
|
+
readLocalSubagentTranscript,
|
|
227
|
+
decodePathSegment,
|
|
228
|
+
decodeSessionId,
|
|
229
|
+
readRequestBody,
|
|
230
|
+
writeInvalidBody,
|
|
231
|
+
buildHttpUrl,
|
|
232
|
+
buildBootstrapHttpUrl,
|
|
233
|
+
buildClientWsUrl,
|
|
234
|
+
normalizeHqPublicOrigin,
|
|
235
|
+
hqRuntimeMarkerPath,
|
|
236
|
+
lanIPv4Addresses,
|
|
237
|
+
truncateHqSummary,
|
|
238
|
+
hqMachineKey,
|
|
239
|
+
recordTimeseriesSignal,
|
|
240
|
+
sanitizeApiError
|
|
241
|
+
};
|
|
242
|
+
//# sourceMappingURL=chunk-I7V2OYVH.js.map
|
|
@@ -1043,9 +1043,9 @@ var helpTable = {
|
|
|
1043
1043
|
// -- HQ (dashboard server) ──────────────────────────────────────────
|
|
1044
1044
|
hq: {
|
|
1045
1045
|
name: "hq",
|
|
1046
|
-
title: "wstack hq \u2014
|
|
1047
|
-
description: "Start the HQ server \u2014 a web dashboard for monitoring sessions, fleet status, and agent activity across projects
|
|
1048
|
-
usage: "wstack hq [serve] [
|
|
1046
|
+
title: "wstack hq \u2014 serve HQ, manage authentication, or install its system service",
|
|
1047
|
+
description: "Start the HQ server \u2014 a web dashboard for monitoring sessions, fleet status, and agent activity across projects; manage browser/client authentication, or install the persistent Ubuntu systemd service.",
|
|
1048
|
+
usage: "wstack hq [serve] [...] | wstack hq token [create|list|revoke] | wstack hq service [install|status|update|uninstall]",
|
|
1049
1049
|
subcommands: [
|
|
1050
1050
|
{ name: "serve", description: "Start the HQ dashboard server (default)." },
|
|
1051
1051
|
{
|
|
@@ -1053,7 +1053,17 @@ var helpTable = {
|
|
|
1053
1053
|
description: "Mint a browser or client authentication token."
|
|
1054
1054
|
},
|
|
1055
1055
|
{ name: "token list", description: "List active HQ authentication tokens." },
|
|
1056
|
-
{ name: "token revoke <id>", description: "Revoke an issued HQ authentication token." }
|
|
1056
|
+
{ name: "token revoke <id>", description: "Revoke an issued HQ authentication token." },
|
|
1057
|
+
{
|
|
1058
|
+
name: "service install",
|
|
1059
|
+
description: "Install an always-on systemd service and guarded automatic updater."
|
|
1060
|
+
},
|
|
1061
|
+
{ name: "service status", description: "Inspect the HQ service and update timer." },
|
|
1062
|
+
{ name: "service update", description: "Run the guarded update job immediately." },
|
|
1063
|
+
{
|
|
1064
|
+
name: "service uninstall",
|
|
1065
|
+
description: "Remove systemd units while preserving HQ data and secrets."
|
|
1066
|
+
}
|
|
1057
1067
|
],
|
|
1058
1068
|
seeAlso: "wstack sessions fleet (CLI equivalent for fleet status)"
|
|
1059
1069
|
},
|
|
@@ -1202,4 +1212,4 @@ export {
|
|
|
1202
1212
|
subcommandsWithFocusedHelp,
|
|
1203
1213
|
renderGenericHelp
|
|
1204
1214
|
};
|
|
1205
|
-
//# sourceMappingURL=chunk-
|
|
1215
|
+
//# sourceMappingURL=chunk-JX6KL7OF.js.map
|