@songsid/agend 2.1.5 → 2.1.6-beta.10
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/agent-endpoint.d.ts +18 -0
- package/dist/agent-endpoint.js +53 -2
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/apply-job.d.ts +114 -0
- package/dist/apply-job.js +214 -0
- package/dist/apply-job.js.map +1 -0
- package/dist/backend/claude-code.d.ts +25 -0
- package/dist/backend/claude-code.js +127 -0
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/codex.d.ts +57 -0
- package/dist/backend/codex.js +183 -0
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/credential-profile.d.ts +159 -0
- package/dist/backend/credential-profile.js +340 -0
- package/dist/backend/credential-profile.js.map +1 -0
- package/dist/backend/factory.js +4 -1
- package/dist/backend/factory.js.map +1 -1
- package/dist/backend/kiro-auth-store.d.ts +25 -0
- package/dist/backend/kiro-auth-store.js +61 -0
- package/dist/backend/kiro-auth-store.js.map +1 -0
- package/dist/backend/kiro.d.ts +8 -0
- package/dist/backend/kiro.js +31 -2
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/muse.d.ts +90 -0
- package/dist/backend/muse.js +437 -0
- package/dist/backend/muse.js.map +1 -0
- package/dist/backend/types.d.ts +54 -0
- package/dist/backend/types.js.map +1 -1
- package/dist/channel/access-manager.d.ts +20 -0
- package/dist/channel/access-manager.js +25 -0
- package/dist/channel/access-manager.js.map +1 -1
- package/dist/channel/adapters/discord.d.ts +17 -0
- package/dist/channel/adapters/discord.js +72 -11
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +6 -0
- package/dist/channel/adapters/telegram.js +36 -0
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/markdown-chunk.d.ts +8 -3
- package/dist/channel/markdown-chunk.js +12 -3
- package/dist/channel/markdown-chunk.js.map +1 -1
- package/dist/channel/mcp-server.js +9 -12
- package/dist/channel/mcp-server.js.map +1 -1
- package/dist/channel/mcp-tools.d.ts +6 -2
- package/dist/channel/mcp-tools.js +6 -36
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/tool-router.js +32 -3
- package/dist/channel/tool-router.js.map +1 -1
- package/dist/channel/types.d.ts +18 -0
- package/dist/cli.js +113 -0
- package/dist/cli.js.map +1 -1
- package/dist/config-validator.js +45 -5
- package/dist/config-validator.js.map +1 -1
- package/dist/connection-secrets.d.ts +96 -0
- package/dist/connection-secrets.js +25 -0
- package/dist/connection-secrets.js.map +1 -0
- package/dist/daemon.d.ts +76 -0
- package/dist/daemon.js +489 -103
- package/dist/daemon.js.map +1 -1
- package/dist/event-log.d.ts +9 -0
- package/dist/event-log.js +21 -0
- package/dist/event-log.js.map +1 -1
- package/dist/fleet-level-config.d.ts +42 -0
- package/dist/fleet-level-config.js +78 -0
- package/dist/fleet-level-config.js.map +1 -0
- package/dist/fleet-lock.d.ts +21 -0
- package/dist/fleet-lock.js +42 -8
- package/dist/fleet-lock.js.map +1 -1
- package/dist/fleet-manager.d.ts +425 -2
- package/dist/fleet-manager.js +2055 -182
- package/dist/fleet-manager.js.map +1 -1
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +145 -0
- package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +11 -1
- package/dist/instance-config-impact.d.ts +55 -0
- package/dist/instance-config-impact.js +152 -0
- package/dist/instance-config-impact.js.map +1 -0
- package/dist/instance-lifecycle.js +8 -4
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/locale.js +24 -0
- package/dist/locale.js.map +1 -1
- package/dist/logger.js +42 -25
- package/dist/logger.js.map +1 -1
- package/dist/muse-usage-relay.d.ts +72 -0
- package/dist/muse-usage-relay.js +419 -0
- package/dist/muse-usage-relay.js.map +1 -0
- package/dist/outbound-handlers.d.ts +5 -1
- package/dist/outbound-handlers.js +199 -1
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +7 -5
- package/dist/outbound-schemas.js +3 -2
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/provider-probe.d.ts +48 -0
- package/dist/provider-probe.js +121 -0
- package/dist/provider-probe.js.map +1 -0
- package/dist/provider-secret-registry.d.ts +98 -0
- package/dist/provider-secret-registry.js +334 -0
- package/dist/provider-secret-registry.js.map +1 -0
- package/dist/quickstart-api.d.ts +164 -0
- package/dist/quickstart-api.js +351 -0
- package/dist/quickstart-api.js.map +1 -0
- package/dist/quickstart.js +23 -50
- package/dist/quickstart.js.map +1 -1
- package/dist/scheduler/db.js +17 -5
- package/dist/scheduler/db.js.map +1 -1
- package/dist/scheduler/db.test.js +34 -1
- package/dist/scheduler/db.test.js.map +1 -1
- package/dist/scheduler/types.d.ts +4 -0
- package/dist/scheduler/types.js.map +1 -1
- package/dist/secret-store.d.ts +25 -0
- package/dist/secret-store.js +165 -0
- package/dist/secret-store.js.map +1 -0
- package/dist/self-restart-limit.d.ts +21 -0
- package/dist/self-restart-limit.js +129 -0
- package/dist/self-restart-limit.js.map +1 -0
- package/dist/settings-api.d.ts +116 -0
- package/dist/settings-api.js +530 -5
- package/dist/settings-api.js.map +1 -1
- package/dist/setup-auth.d.ts +113 -0
- package/dist/setup-auth.js +181 -0
- package/dist/setup-auth.js.map +1 -0
- package/dist/setup-form.d.ts +18 -0
- package/dist/setup-form.js +315 -0
- package/dist/setup-form.js.map +1 -0
- package/dist/setup-host.d.ts +162 -0
- package/dist/setup-host.js +496 -0
- package/dist/setup-host.js.map +1 -0
- package/dist/setup-marker.d.ts +8 -0
- package/dist/setup-marker.js +39 -0
- package/dist/setup-marker.js.map +1 -0
- package/dist/setup-tunnel-consent.d.ts +53 -0
- package/dist/setup-tunnel-consent.js +82 -0
- package/dist/setup-tunnel-consent.js.map +1 -0
- package/dist/setup-wizard.js +4 -0
- package/dist/setup-wizard.js.map +1 -1
- package/dist/steer-capability.js +4 -1
- package/dist/steer-capability.js.map +1 -1
- package/dist/tips.js +1 -1
- package/dist/tips.js.map +1 -1
- package/dist/tmux-manager.js +29 -4
- package/dist/tmux-manager.js.map +1 -1
- package/dist/tool-permissions-notice.d.ts +38 -0
- package/dist/tool-permissions-notice.js +92 -0
- package/dist/tool-permissions-notice.js.map +1 -0
- package/dist/tool-permissions.d.ts +120 -0
- package/dist/tool-permissions.js +277 -0
- package/dist/tool-permissions.js.map +1 -0
- package/dist/topic-commands.js +1 -0
- package/dist/topic-commands.js.map +1 -1
- package/dist/transcript-sources.d.ts +12 -1
- package/dist/transcript-sources.js +19 -3
- package/dist/transcript-sources.js.map +1 -1
- package/dist/tunnel/cloudflared.d.ts +71 -0
- package/dist/tunnel/cloudflared.js +447 -0
- package/dist/tunnel/cloudflared.js.map +1 -0
- package/dist/tunnel/lease.d.ts +75 -0
- package/dist/tunnel/lease.js +209 -0
- package/dist/tunnel/lease.js.map +1 -0
- package/dist/tunnel/manager.d.ts +56 -0
- package/dist/tunnel/manager.js +167 -0
- package/dist/tunnel/manager.js.map +1 -0
- package/dist/tunnel/types.d.ts +119 -0
- package/dist/tunnel/types.js +33 -0
- package/dist/tunnel/types.js.map +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/ui/dashboard.html +4 -3
- package/dist/ui/settings.html +808 -156
- package/dist/ui/view.html +2 -2
- package/dist/usage/i18n-keys.d.ts +1 -1
- package/dist/usage/i18n-keys.js +1 -1
- package/dist/usage/i18n-keys.js.map +1 -1
- package/dist/usage/providers.d.ts +23 -14
- package/dist/usage/providers.js +220 -58
- package/dist/usage/providers.js.map +1 -1
- package/dist/usage/usage-api.d.ts +13 -0
- package/dist/usage/usage-api.js +69 -1
- package/dist/usage/usage-api.js.map +1 -1
- package/dist/web-api.js +8 -5
- package/dist/web-api.js.map +1 -1
- package/dist/web-auth.d.ts +75 -0
- package/dist/web-auth.js +208 -2
- package/dist/web-auth.js.map +1 -1
- package/dist/web-terminal.d.ts +30 -1
- package/dist/web-terminal.js +86 -3
- package/dist/web-terminal.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { lookup as dnsLookup } from "node:dns/promises";
|
|
2
|
+
import { BlockList, isIP } from "node:net";
|
|
3
|
+
import { request as httpsRequest } from "node:https";
|
|
4
|
+
import { redactProviderError } from "./provider-probe.js";
|
|
5
|
+
function jsonObject(body) {
|
|
6
|
+
return !!body && typeof body === "object" && !Array.isArray(body);
|
|
7
|
+
}
|
|
8
|
+
const modelList = (status, body) => status >= 200 && status < 300 && jsonObject(body);
|
|
9
|
+
/** Initial registry. xAI stays out until its endpoint/auth contract is fixed. */
|
|
10
|
+
export const PROVIDER_SECRET_SPECS = Object.freeze([
|
|
11
|
+
{
|
|
12
|
+
id: "groq.api_key",
|
|
13
|
+
envKey: "GROQ_API_KEY",
|
|
14
|
+
displayName: "Groq API key",
|
|
15
|
+
kind: "api_key",
|
|
16
|
+
allowedHosts: ["https://api.groq.com"],
|
|
17
|
+
verifier: {
|
|
18
|
+
origin: "https://api.groq.com",
|
|
19
|
+
path: "/openai/v1/models",
|
|
20
|
+
auth: "bearer",
|
|
21
|
+
timeoutMs: 8_000,
|
|
22
|
+
maxResponseBytes: 256 * 1024,
|
|
23
|
+
expected: modelList,
|
|
24
|
+
},
|
|
25
|
+
activation: "reload_hook",
|
|
26
|
+
reloadHookId: "groq.voice",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: "openai.api_key",
|
|
30
|
+
envKey: "OPENAI_API_KEY",
|
|
31
|
+
displayName: "OpenAI API key",
|
|
32
|
+
kind: "api_key",
|
|
33
|
+
allowedHosts: ["https://api.openai.com"],
|
|
34
|
+
verifier: {
|
|
35
|
+
origin: "https://api.openai.com",
|
|
36
|
+
path: "/v1/models",
|
|
37
|
+
auth: "bearer",
|
|
38
|
+
timeoutMs: 8_000,
|
|
39
|
+
maxResponseBytes: 256 * 1024,
|
|
40
|
+
expected: modelList,
|
|
41
|
+
},
|
|
42
|
+
activation: "next_use",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: "anthropic.api_key",
|
|
46
|
+
envKey: "ANTHROPIC_API_KEY",
|
|
47
|
+
displayName: "Anthropic API key",
|
|
48
|
+
kind: "api_key",
|
|
49
|
+
allowedHosts: ["https://api.anthropic.com"],
|
|
50
|
+
verifier: {
|
|
51
|
+
origin: "https://api.anthropic.com",
|
|
52
|
+
path: "/v1/models",
|
|
53
|
+
auth: "anthropic",
|
|
54
|
+
timeoutMs: 8_000,
|
|
55
|
+
maxResponseBytes: 256 * 1024,
|
|
56
|
+
expected: modelList,
|
|
57
|
+
},
|
|
58
|
+
activation: "next_use",
|
|
59
|
+
},
|
|
60
|
+
].map(spec => Object.freeze({
|
|
61
|
+
...spec,
|
|
62
|
+
allowedHosts: Object.freeze([...spec.allowedHosts]),
|
|
63
|
+
verifier: spec.verifier ? Object.freeze({ ...spec.verifier }) : undefined,
|
|
64
|
+
})));
|
|
65
|
+
const RESERVED_ENV_KEYS = new Set(["PATH", "HOME", "PWD", "SHELL", "ENV", "BASH_ENV", "NODE_OPTIONS", "LD_PRELOAD"]);
|
|
66
|
+
const ENV_KEY = /^[A-Za-z_][A-Za-z0-9_]{0,127}$/;
|
|
67
|
+
export function providerSecretSpec(id) {
|
|
68
|
+
return PROVIDER_SECRET_SPECS.find(spec => spec.id === id);
|
|
69
|
+
}
|
|
70
|
+
/** Validate immutable registry data at module load and in focused tests. */
|
|
71
|
+
export function validateProviderSecretRegistry(specs = PROVIDER_SECRET_SPECS) {
|
|
72
|
+
const ids = new Set();
|
|
73
|
+
const keys = new Set();
|
|
74
|
+
for (const spec of specs) {
|
|
75
|
+
if (ids.has(spec.id))
|
|
76
|
+
throw new Error("provider secret registry contains duplicate id");
|
|
77
|
+
ids.add(spec.id);
|
|
78
|
+
if (!ENV_KEY.test(spec.envKey) || RESERVED_ENV_KEYS.has(spec.envKey))
|
|
79
|
+
throw new Error("provider secret registry contains unsafe env key");
|
|
80
|
+
if (keys.has(spec.envKey))
|
|
81
|
+
throw new Error("provider secret registry contains duplicate env key");
|
|
82
|
+
keys.add(spec.envKey);
|
|
83
|
+
for (const origin of spec.allowedHosts) {
|
|
84
|
+
const parsed = new URL(origin);
|
|
85
|
+
if (parsed.protocol !== "https:" || isIP(parsed.hostname) !== 0 || parsed.username || parsed.password || parsed.search || parsed.hash || parsed.pathname !== "/") {
|
|
86
|
+
throw new Error("provider secret registry contains unsafe origin");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (!spec.verifier)
|
|
90
|
+
continue;
|
|
91
|
+
const verifierOrigin = new URL(spec.verifier.origin);
|
|
92
|
+
if (verifierOrigin.protocol !== "https:" || isIP(verifierOrigin.hostname) !== 0 || verifierOrigin.username || verifierOrigin.password || verifierOrigin.search || verifierOrigin.hash || verifierOrigin.pathname !== "/") {
|
|
93
|
+
throw new Error("provider secret verifier contains unsafe origin");
|
|
94
|
+
}
|
|
95
|
+
if (!spec.allowedHosts.includes(spec.verifier.origin))
|
|
96
|
+
throw new Error("provider verifier origin is not allowlisted");
|
|
97
|
+
if (!spec.verifier.path.startsWith("/") || spec.verifier.path.includes("?") || spec.verifier.path.includes("#") || spec.verifier.path.includes("\\")) {
|
|
98
|
+
throw new Error("provider verifier contains unsafe path");
|
|
99
|
+
}
|
|
100
|
+
if (!Number.isFinite(spec.verifier.timeoutMs) || spec.verifier.timeoutMs <= 0 || !Number.isFinite(spec.verifier.maxResponseBytes) || spec.verifier.maxResponseBytes <= 0) {
|
|
101
|
+
throw new Error("provider verifier limits are invalid");
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
validateProviderSecretRegistry();
|
|
106
|
+
export function validateSecretHeaderValue(secret) {
|
|
107
|
+
if (!secret || secret.length > 4096 || /[\r\n\0]/.test(secret) || /[^\x20-\x7e]/.test(secret)) {
|
|
108
|
+
throw new Error("secret header value is invalid");
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const PRIVATE_IPV4 = new BlockList();
|
|
112
|
+
for (const [address, prefix] of [
|
|
113
|
+
["0.0.0.0", 8], ["10.0.0.0", 8], ["100.64.0.0", 10], ["127.0.0.0", 8],
|
|
114
|
+
["169.254.0.0", 16], ["172.16.0.0", 12], ["192.0.0.0", 24], ["192.0.2.0", 24],
|
|
115
|
+
["192.168.0.0", 16], ["198.18.0.0", 15], ["198.51.100.0", 24], ["203.0.113.0", 24],
|
|
116
|
+
["224.0.0.0", 4], ["240.0.0.0", 4],
|
|
117
|
+
])
|
|
118
|
+
PRIVATE_IPV4.addSubnet(address, prefix, "ipv4");
|
|
119
|
+
const PRIVATE_IPV6 = new BlockList();
|
|
120
|
+
for (const [address, prefix] of [
|
|
121
|
+
["::", 128], ["::1", 128], ["::ffff:0:0", 96], ["fc00::", 7], ["fe80::", 10], ["ff00::", 8],
|
|
122
|
+
])
|
|
123
|
+
PRIVATE_IPV6.addSubnet(address, prefix, "ipv6");
|
|
124
|
+
/**
|
|
125
|
+
* BlockList handles IPv4-mapped IPv6 spellings (including hex tails) without
|
|
126
|
+
* relying on string prefixes. Unknown address families fail closed.
|
|
127
|
+
*/
|
|
128
|
+
function isPrivateAddress(address) {
|
|
129
|
+
const family = isIP(address);
|
|
130
|
+
if (family === 4)
|
|
131
|
+
return PRIVATE_IPV4.check(address, "ipv4");
|
|
132
|
+
if (family === 6)
|
|
133
|
+
return PRIVATE_IPV6.check(address, "ipv6");
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
export function createProviderHttpClientForTests(options) {
|
|
137
|
+
if (process.env.NODE_ENV !== "test")
|
|
138
|
+
throw new Error("provider HTTP test transport is unavailable outside tests");
|
|
139
|
+
return FixedProviderHttpClient.createForTests(options);
|
|
140
|
+
}
|
|
141
|
+
function responseBodyText(response, maxBytes, timeoutMs) {
|
|
142
|
+
return new Promise((resolve, reject) => {
|
|
143
|
+
const chunks = [];
|
|
144
|
+
let size = 0;
|
|
145
|
+
let settled = false;
|
|
146
|
+
const timer = setTimeout(() => { if (!settled) {
|
|
147
|
+
settled = true;
|
|
148
|
+
response.destroy();
|
|
149
|
+
reject(new Error("provider response timeout"));
|
|
150
|
+
} }, timeoutMs);
|
|
151
|
+
timer.unref?.();
|
|
152
|
+
response.on("data", (chunk) => {
|
|
153
|
+
if (settled)
|
|
154
|
+
return;
|
|
155
|
+
size += chunk.length;
|
|
156
|
+
if (size > maxBytes) {
|
|
157
|
+
settled = true;
|
|
158
|
+
clearTimeout(timer);
|
|
159
|
+
response.destroy();
|
|
160
|
+
reject(new Error("provider response exceeded limit"));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
chunks.push(Buffer.from(chunk));
|
|
164
|
+
});
|
|
165
|
+
response.on("end", () => {
|
|
166
|
+
if (settled)
|
|
167
|
+
return;
|
|
168
|
+
settled = true;
|
|
169
|
+
clearTimeout(timer);
|
|
170
|
+
resolve(Buffer.concat(chunks).toString("utf8"));
|
|
171
|
+
});
|
|
172
|
+
response.on("error", err => {
|
|
173
|
+
if (settled)
|
|
174
|
+
return;
|
|
175
|
+
settled = true;
|
|
176
|
+
clearTimeout(timer);
|
|
177
|
+
reject(err);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Direct HTTPS client. It deliberately does not use fetch/undici's ambient
|
|
183
|
+
* proxy environment: the allowlisted provider is the only destination. DNS is
|
|
184
|
+
* resolved once and the resulting address is returned on every lookup call,
|
|
185
|
+
* preventing a check/connect TOCTOU window.
|
|
186
|
+
*/
|
|
187
|
+
export class FixedProviderHttpClient {
|
|
188
|
+
testOptions;
|
|
189
|
+
constructor(testOptions) {
|
|
190
|
+
this.testOptions = testOptions;
|
|
191
|
+
}
|
|
192
|
+
static create() {
|
|
193
|
+
return new FixedProviderHttpClient();
|
|
194
|
+
}
|
|
195
|
+
static createForTests(options) {
|
|
196
|
+
return new FixedProviderHttpClient(options);
|
|
197
|
+
}
|
|
198
|
+
async request(spec, secret) {
|
|
199
|
+
const verifier = spec.verifier;
|
|
200
|
+
if (!verifier)
|
|
201
|
+
throw new Error("unsupported verifier");
|
|
202
|
+
if (process.env.NODE_TLS_REJECT_UNAUTHORIZED === "0")
|
|
203
|
+
throw new Error("TLS verification is disabled");
|
|
204
|
+
validateSecretHeaderValue(secret);
|
|
205
|
+
const origin = new URL(verifier.origin);
|
|
206
|
+
if (!spec.allowedHosts.includes(origin.origin))
|
|
207
|
+
throw new Error("provider origin is not allowlisted");
|
|
208
|
+
const deadline = Date.now() + verifier.timeoutMs;
|
|
209
|
+
const resolved = await Promise.race([
|
|
210
|
+
(this.testOptions?.dnsLookup
|
|
211
|
+
? this.testOptions.dnsLookup(origin.hostname, { all: false, verbatim: true })
|
|
212
|
+
: dnsLookup(origin.hostname, { all: false, verbatim: true })),
|
|
213
|
+
new Promise((_, reject) => {
|
|
214
|
+
const timer = setTimeout(() => reject(new Error("provider DNS lookup timeout")), verifier.timeoutMs);
|
|
215
|
+
timer.unref?.();
|
|
216
|
+
}),
|
|
217
|
+
]);
|
|
218
|
+
const address = Array.isArray(resolved) ? resolved[0] : resolved;
|
|
219
|
+
if (!address?.address)
|
|
220
|
+
throw new Error("provider DNS returned no address");
|
|
221
|
+
if (this.testOptions?.allowPrivateAddress !== true && isPrivateAddress(address.address)) {
|
|
222
|
+
throw new Error("provider address is not public");
|
|
223
|
+
}
|
|
224
|
+
const headers = { Accept: "application/json" };
|
|
225
|
+
if (verifier.auth === "bearer")
|
|
226
|
+
headers.Authorization = `Bearer ${secret}`;
|
|
227
|
+
else if (verifier.auth === "x-api-key")
|
|
228
|
+
headers["x-api-key"] = secret;
|
|
229
|
+
else {
|
|
230
|
+
headers["x-api-key"] = secret;
|
|
231
|
+
headers["anthropic-version"] = "2023-06-01";
|
|
232
|
+
}
|
|
233
|
+
const requestOptions = {
|
|
234
|
+
protocol: "https:",
|
|
235
|
+
hostname: origin.hostname,
|
|
236
|
+
port: origin.port || 443,
|
|
237
|
+
path: verifier.path,
|
|
238
|
+
method: "GET",
|
|
239
|
+
headers,
|
|
240
|
+
rejectUnauthorized: true,
|
|
241
|
+
ca: this.testOptions?.ca,
|
|
242
|
+
servername: origin.hostname,
|
|
243
|
+
// Explicitly bypass any agent/proxy supplied by ambient config.
|
|
244
|
+
agent: false,
|
|
245
|
+
lookup: (_hostname, options, callback) => {
|
|
246
|
+
this.testOptions?.onConnectLookup?.(options);
|
|
247
|
+
if (options.all)
|
|
248
|
+
callback(null, [{ address: address.address, family: address.family }]);
|
|
249
|
+
else
|
|
250
|
+
callback(null, address.address, address.family);
|
|
251
|
+
},
|
|
252
|
+
};
|
|
253
|
+
// Node 20+ may request an all-address lookup when autoSelectFamily is
|
|
254
|
+
// enabled by the runtime. Keep this explicit in the transport so the
|
|
255
|
+
// callback below is exercised consistently across supported Node releases.
|
|
256
|
+
requestOptions.autoSelectFamily = true;
|
|
257
|
+
const raw = await new Promise((resolve, reject) => {
|
|
258
|
+
let settled = false;
|
|
259
|
+
const remaining = Math.max(1, deadline - Date.now());
|
|
260
|
+
const timer = setTimeout(() => {
|
|
261
|
+
if (settled)
|
|
262
|
+
return;
|
|
263
|
+
settled = true;
|
|
264
|
+
request.destroy(new Error("provider request timeout"));
|
|
265
|
+
reject(new Error("provider request timeout"));
|
|
266
|
+
}, remaining);
|
|
267
|
+
timer.unref?.();
|
|
268
|
+
this.testOptions?.onRequest?.(requestOptions);
|
|
269
|
+
const request = httpsRequest(requestOptions, response => {
|
|
270
|
+
responseBodyText(response, verifier.maxResponseBytes, Math.max(1, deadline - Date.now())).then(body => {
|
|
271
|
+
if (settled)
|
|
272
|
+
return;
|
|
273
|
+
settled = true;
|
|
274
|
+
clearTimeout(timer);
|
|
275
|
+
resolve({ response, body });
|
|
276
|
+
}, error => {
|
|
277
|
+
if (settled)
|
|
278
|
+
return;
|
|
279
|
+
settled = true;
|
|
280
|
+
clearTimeout(timer);
|
|
281
|
+
reject(error);
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
request.on("error", error => {
|
|
285
|
+
if (settled)
|
|
286
|
+
return;
|
|
287
|
+
settled = true;
|
|
288
|
+
clearTimeout(timer);
|
|
289
|
+
reject(error);
|
|
290
|
+
});
|
|
291
|
+
request.end();
|
|
292
|
+
});
|
|
293
|
+
let body = null;
|
|
294
|
+
try {
|
|
295
|
+
body = JSON.parse(raw.body);
|
|
296
|
+
}
|
|
297
|
+
catch {
|
|
298
|
+
body = raw.body;
|
|
299
|
+
}
|
|
300
|
+
// A redirect is never followed by this client. It is classified as
|
|
301
|
+
// unavailable by verifyProviderSecret, regardless of Location contents.
|
|
302
|
+
return { status: raw.response.statusCode ?? 0, body, detail: redactProviderError(raw.body, secret) };
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
export async function verifyProviderSecret(spec, secret, client = FixedProviderHttpClient.create()) {
|
|
306
|
+
if (!spec?.verifier)
|
|
307
|
+
return { ok: false, status: "unsupported_verifier" };
|
|
308
|
+
try {
|
|
309
|
+
const response = await client.request(spec, secret);
|
|
310
|
+
if (response.status >= 200 && response.status < 300 && spec.verifier.expected(response.status, response.body)) {
|
|
311
|
+
return { ok: true, status: "verified", provider_status: response.status };
|
|
312
|
+
}
|
|
313
|
+
if (response.status === 401 || response.status === 403)
|
|
314
|
+
return { ok: false, status: "provider_rejected" };
|
|
315
|
+
return { ok: false, status: "provider_unavailable", error: safeProviderDetail(response.detail, secret) };
|
|
316
|
+
}
|
|
317
|
+
catch (error) {
|
|
318
|
+
return { ok: false, status: "provider_unavailable", error: safeProviderDetail(redactProviderError(error, secret), secret) };
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
function safeProviderDetail(detail, secret) {
|
|
322
|
+
if (!detail)
|
|
323
|
+
return undefined;
|
|
324
|
+
return redactProviderError(detail, secret)
|
|
325
|
+
.replace(/(?:Bearer|x-api-key|api-key|authorization)\s*[:=]?\s*[^\s,;]+/gi, "$1: [redacted]")
|
|
326
|
+
.slice(0, 180);
|
|
327
|
+
}
|
|
328
|
+
export function providerRegistryEnvKeys() {
|
|
329
|
+
return new Set(PROVIDER_SECRET_SPECS.map(spec => spec.envKey));
|
|
330
|
+
}
|
|
331
|
+
export function isReservedProviderEnvKey(key) {
|
|
332
|
+
return RESERVED_ENV_KEYS.has(key);
|
|
333
|
+
}
|
|
334
|
+
//# sourceMappingURL=provider-secret-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-secret-registry.js","sourceRoot":"","sources":["../src/provider-secret-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Settings setup wizard's server side.
|
|
3
|
+
*
|
|
4
|
+
* Four steps, the same four `agend quickstart` walks: pick a backend and a
|
|
5
|
+
* working directory, pick a platform, prove the bot credentials, then write the
|
|
6
|
+
* files and start. The probes are the CLI's own (`provider-probe.ts`), so the
|
|
7
|
+
* wizard cannot drift into asking the providers different questions.
|
|
8
|
+
*
|
|
9
|
+
* What it deliberately does not do: apply. The last step writes the
|
|
10
|
+
* configuration and hands back, and the page then starts a normal apply job —
|
|
11
|
+
* the same one the panel uses everywhere else, with the same progress, the same
|
|
12
|
+
* idempotency key and the same disk-backed recovery across a restart.
|
|
13
|
+
*/
|
|
14
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
15
|
+
import type { SecretWriteResult } from "./secret-file.js";
|
|
16
|
+
import type { FleetConfig } from "./types.js";
|
|
17
|
+
import { type BotIdentity, type DiscordGuild } from "./provider-probe.js";
|
|
18
|
+
/** One slice of Telegram long polling, so the browser gets an answer. */
|
|
19
|
+
export declare const TELEGRAM_WAIT_SLICE_MS = 25000;
|
|
20
|
+
export declare const WIZARD_BACKENDS: readonly [{
|
|
21
|
+
readonly name: "claude-code";
|
|
22
|
+
readonly binary: "claude";
|
|
23
|
+
}, {
|
|
24
|
+
readonly name: "codex";
|
|
25
|
+
readonly binary: "codex";
|
|
26
|
+
}, {
|
|
27
|
+
readonly name: "opencode";
|
|
28
|
+
readonly binary: "opencode";
|
|
29
|
+
}, {
|
|
30
|
+
readonly name: "kiro-cli";
|
|
31
|
+
readonly binary: "kiro-cli";
|
|
32
|
+
}, {
|
|
33
|
+
readonly name: "antigravity";
|
|
34
|
+
readonly binary: "agy";
|
|
35
|
+
}, {
|
|
36
|
+
readonly name: "grok";
|
|
37
|
+
readonly binary: "grok";
|
|
38
|
+
}, {
|
|
39
|
+
readonly name: "muse";
|
|
40
|
+
readonly binary: "muse";
|
|
41
|
+
}];
|
|
42
|
+
export interface WizardEnvironment {
|
|
43
|
+
backends: string[];
|
|
44
|
+
/** Channels already configured, so the wizard can pre-fill and warn. */
|
|
45
|
+
channels: Array<{
|
|
46
|
+
id: string;
|
|
47
|
+
type: string;
|
|
48
|
+
token_env: string | null;
|
|
49
|
+
group_id: string | null;
|
|
50
|
+
/** Who can currently drive that connection, so a replacement can say who
|
|
51
|
+
* it is about to remove. */
|
|
52
|
+
allowed_users?: string[];
|
|
53
|
+
}>;
|
|
54
|
+
has_fleet: boolean;
|
|
55
|
+
}
|
|
56
|
+
export interface WizardPlanInput {
|
|
57
|
+
platform: "telegram" | "discord";
|
|
58
|
+
token_env: string;
|
|
59
|
+
backend: string;
|
|
60
|
+
working_directory: string;
|
|
61
|
+
instance_name: string;
|
|
62
|
+
group_id?: string;
|
|
63
|
+
guild_id?: string;
|
|
64
|
+
general_channel_id?: string;
|
|
65
|
+
admin_user_id?: string;
|
|
66
|
+
}
|
|
67
|
+
/** What the last step shows before anything is written. */
|
|
68
|
+
export interface WizardPlan {
|
|
69
|
+
/** The channel entry that will be merged into fleet.yaml. */
|
|
70
|
+
channel: Record<string, unknown>;
|
|
71
|
+
instance: {
|
|
72
|
+
name: string;
|
|
73
|
+
working_directory: string;
|
|
74
|
+
backend: string;
|
|
75
|
+
};
|
|
76
|
+
/** Env var names only — never the value. */
|
|
77
|
+
env_keys: string[];
|
|
78
|
+
warnings: string[];
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* A channel id that is free, or the id of the connection being replaced.
|
|
82
|
+
*
|
|
83
|
+
* The platform name is the obvious id and the first bot gets it. A second bot on
|
|
84
|
+
* the same platform cannot have it — `duplicate channel id` — so it is
|
|
85
|
+
* qualified by the variable that holds its token. Without this the wizard can
|
|
86
|
+
* never add a second Telegram bot at all.
|
|
87
|
+
*/
|
|
88
|
+
export declare function nextChannelId(platform: string, tokenEnv: string, existing: ReadonlyArray<{
|
|
89
|
+
id: string;
|
|
90
|
+
token_env: string | null;
|
|
91
|
+
}>): string;
|
|
92
|
+
export declare function planQuickstart(input: WizardPlanInput, env: WizardEnvironment): WizardPlan;
|
|
93
|
+
/** Upsert one `KEY=value` line, preserving everything else in the file. */
|
|
94
|
+
export declare function upsertEnvLine(existing: string, key: string, value: string): string;
|
|
95
|
+
export declare function writeQuickstartSecret(dataDir: string, key: string, value: string): SecretWriteResult;
|
|
96
|
+
export type ProbeRequest = {
|
|
97
|
+
action: "verify";
|
|
98
|
+
platform: "telegram" | "discord";
|
|
99
|
+
token: string;
|
|
100
|
+
} | {
|
|
101
|
+
action: "guilds";
|
|
102
|
+
token: string;
|
|
103
|
+
} | {
|
|
104
|
+
action: "await-telegram-start";
|
|
105
|
+
token: string;
|
|
106
|
+
offset?: number;
|
|
107
|
+
};
|
|
108
|
+
export type ProbeResult = {
|
|
109
|
+
ok: true;
|
|
110
|
+
identity: BotIdentity;
|
|
111
|
+
} | {
|
|
112
|
+
ok: true;
|
|
113
|
+
guilds: DiscordGuild[];
|
|
114
|
+
} | {
|
|
115
|
+
ok: true;
|
|
116
|
+
found: {
|
|
117
|
+
groupId: number;
|
|
118
|
+
userId: number;
|
|
119
|
+
} | null;
|
|
120
|
+
offset: number;
|
|
121
|
+
} | {
|
|
122
|
+
ok: false;
|
|
123
|
+
error: string;
|
|
124
|
+
conflict?: true;
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Run one probe.
|
|
128
|
+
*
|
|
129
|
+
* `isTokenInUse` exists for the Telegram wait: `getUpdates` has exactly one
|
|
130
|
+
* consumer, so polling a token the running fleet already polls makes the two
|
|
131
|
+
* take turns and both miss messages. Refusing is the only honest answer — the
|
|
132
|
+
* alternative silently breaks the live bot while the wizard waits.
|
|
133
|
+
*/
|
|
134
|
+
export declare function runProviderProbe(request: ProbeRequest, opts?: {
|
|
135
|
+
isTokenInUse?: (token: string) => boolean;
|
|
136
|
+
deadlineMs?: number;
|
|
137
|
+
}): Promise<ProbeResult>;
|
|
138
|
+
export declare function detectWizardBackends(): string[];
|
|
139
|
+
/**
|
|
140
|
+
* What the wizard's routes need from their host.
|
|
141
|
+
*
|
|
142
|
+
* Five fields, and none of them is a fleet: this is the whole "ConfigVerbs +
|
|
143
|
+
* ProviderProbeVerbs" surface. A running fleet supplies it from FleetManager; a
|
|
144
|
+
* pre-fleet setup host supplies it from a file. `tests/prefleet-host.test.ts`
|
|
145
|
+
* asserts this module's import graph reaches neither fleet-manager, daemon nor
|
|
146
|
+
* instance-lifecycle, so the host cannot grow a path to them by accident.
|
|
147
|
+
*/
|
|
148
|
+
export interface QuickstartApiContext {
|
|
149
|
+
fleetConfig: FleetConfig | null;
|
|
150
|
+
dataDir: string;
|
|
151
|
+
logger: {
|
|
152
|
+
info(obj: unknown, msg?: string): void;
|
|
153
|
+
warn(obj: unknown, msg?: string): void;
|
|
154
|
+
};
|
|
155
|
+
saveFleetConfig(): void;
|
|
156
|
+
/** Only a running fleet can answer this; without one, nothing is polling. */
|
|
157
|
+
isBotTokenInUse?(token: string): boolean;
|
|
158
|
+
}
|
|
159
|
+
/** The channels as the wizard sees them, from either config shape. */
|
|
160
|
+
export declare function wizardChannels(cfg: FleetConfig | null): WizardEnvironment["channels"];
|
|
161
|
+
/** Reject anything that would land in fleet.yaml or a shell env file unchecked. */
|
|
162
|
+
export declare function validateWizardInput(input: Partial<WizardPlanInput>): string | null;
|
|
163
|
+
/** Handle one wizard route. Returns false when the path is not one of ours. */
|
|
164
|
+
export declare function handleQuickstartRequest(req: IncomingMessage, res: ServerResponse, url: URL, ctx: QuickstartApiContext): boolean;
|