svamp-cli 0.2.332 → 0.2.333
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/{adminCommands-BNGSC5oD.mjs → adminCommands-BMzwjOct.mjs} +1 -1
- package/dist/{agentCommands-DD47Krr1.mjs → agentCommands-BVz1k2R2.mjs} +35 -6
- package/dist/{auth-CE3Cnkn6.mjs → auth-D0v5RwMJ.mjs} +1 -1
- package/dist/{cli-CdYVO7ce.mjs → cli-DmjtuskT.mjs} +77 -77
- package/dist/cli.mjs +2 -2
- package/dist/{commands-D7wwybeC.mjs → commands-BOGd7CmP.mjs} +8 -3
- package/dist/{commands-CHKSUX7x.mjs → commands-C3r_GhOb.mjs} +3 -3
- package/dist/{commands-09sPSIH-.mjs → commands-CPTWYXJD.mjs} +3 -3
- package/dist/{commands-14Tf0D6G.mjs → commands-CYgkxHsf.mjs} +3 -3
- package/dist/{commands-BIKekqQG.mjs → commands-CwoMu1mu.mjs} +1 -1
- package/dist/{commands-C2X-uElg.mjs → commands-DKouDroK.mjs} +1 -1
- package/dist/{commands-DXJlhBPk.mjs → commands-DcQMh7oz.mjs} +7 -9
- package/dist/{commands-BIx8s0JL.mjs → commands-DmPwUOqX.mjs} +11 -11
- package/dist/{fleet-bAe_gJfS.mjs → fleet-5foIrEnM.mjs} +3 -3
- package/dist/{headlessCli-Bwg5pf3s.mjs → headlessCli-BLZSVVlt.mjs} +2 -2
- package/dist/index.mjs +1 -1
- package/dist/{notifyCommands-Cc3wLAWW.mjs → notifyCommands-DADOx-j_.mjs} +1 -1
- package/dist/package-By6uMuic.mjs +64 -0
- package/dist/{pinnedClaudeCode-BO0Qs_kE.mjs → pinnedClaudeCode-C43KnZ-Q.mjs} +27 -6
- package/dist/{rpc-Bv6_c-xW.mjs → rpc-CoPRGZkJ.mjs} +2 -1
- package/dist/{rpc-DObWvEis.mjs → rpc-UomHF39a.mjs} +13 -1
- package/dist/{run-CyyWhgFI.mjs → run-CkEjIO1m.mjs} +1 -1
- package/dist/{run-DGhVoN3s.mjs → run-PXdghhjy.mjs} +425 -101
- package/dist/{scheduler-BvtNZ0pl.mjs → scheduler-gMWmsAgp.mjs} +1 -1
- package/dist/{serveCommands-CEM708Ls.mjs → serveCommands-Cklx2iuZ.mjs} +10 -10
- package/dist/{sideband--9vWYqKA.mjs → sideband-DXyAkIaB.mjs} +1 -1
- package/package.json +3 -3
- package/dist/package-CPQqs8ty.mjs +0 -64
|
@@ -7,8 +7,8 @@ import path__default, { join, delimiter, resolve as resolve$1, dirname as dirnam
|
|
|
7
7
|
import { fileURLToPath } from 'url';
|
|
8
8
|
import { execFile, execSync, spawn, exec as exec$1 } from 'child_process';
|
|
9
9
|
import * as crypto from 'crypto';
|
|
10
|
-
import { randomUUID, createHash } from 'crypto';
|
|
11
|
-
import { existsSync, readFileSync, mkdirSync as mkdirSync$1, writeFileSync as writeFileSync$1, chmodSync as chmodSync$1, rmSync as rmSync$1, cpSync, statSync, realpathSync, readdirSync, renameSync, appendFileSync, openSync, readSync, closeSync, unlinkSync as unlinkSync$1, writeSync } from 'node:fs';
|
|
10
|
+
import { randomUUID, createHash, randomBytes as randomBytes$1 } from 'crypto';
|
|
11
|
+
import { existsSync, readFileSync, mkdirSync as mkdirSync$1, writeFileSync as writeFileSync$1, chmodSync as chmodSync$1, rmSync as rmSync$1, cpSync, statSync, realpathSync, readdirSync, renameSync, appendFileSync, openSync, readSync, closeSync, unlinkSync as unlinkSync$1, fstatSync, writeSync } from 'node:fs';
|
|
12
12
|
import { join as join$1, extname, resolve, sep, basename, dirname } from 'node:path';
|
|
13
13
|
import { randomUUID as randomUUID$1, randomBytes, createHash as createHash$1, timingSafeEqual } from 'node:crypto';
|
|
14
14
|
import { exec, spawn as spawn$1, execSync as execSync$1, execFile as execFile$1, execFileSync } from 'node:child_process';
|
|
@@ -5446,10 +5446,11 @@ function cronMatches(expr, date) {
|
|
|
5446
5446
|
if (c.domRestricted && c.dowRestricted) return domOk || dowOk;
|
|
5447
5447
|
return domOk && dowOk;
|
|
5448
5448
|
}
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5449
|
+
const _zoneFormatters = /* @__PURE__ */ new Map();
|
|
5450
|
+
function zoneFormatter(tz) {
|
|
5451
|
+
let f = _zoneFormatters.get(tz);
|
|
5452
|
+
if (!f) {
|
|
5453
|
+
f = new Intl.DateTimeFormat("en-US", {
|
|
5453
5454
|
timeZone: tz,
|
|
5454
5455
|
hour12: false,
|
|
5455
5456
|
year: "numeric",
|
|
@@ -5457,7 +5458,15 @@ function inZone(date, tz) {
|
|
|
5457
5458
|
day: "2-digit",
|
|
5458
5459
|
hour: "2-digit",
|
|
5459
5460
|
minute: "2-digit"
|
|
5460
|
-
})
|
|
5461
|
+
});
|
|
5462
|
+
_zoneFormatters.set(tz, f);
|
|
5463
|
+
}
|
|
5464
|
+
return f;
|
|
5465
|
+
}
|
|
5466
|
+
function inZone(date, tz) {
|
|
5467
|
+
if (!tz) return date;
|
|
5468
|
+
try {
|
|
5469
|
+
const p = zoneFormatter(tz).formatToParts(date).reduce((o, x) => {
|
|
5461
5470
|
o[x.type] = x.value;
|
|
5462
5471
|
return o;
|
|
5463
5472
|
}, {});
|
|
@@ -5467,6 +5476,34 @@ function inZone(date, tz) {
|
|
|
5467
5476
|
return date;
|
|
5468
5477
|
}
|
|
5469
5478
|
}
|
|
5479
|
+
function nextFire(expr, from, tz) {
|
|
5480
|
+
const c = parseCron(expr);
|
|
5481
|
+
if (tz && scanForMatch(c, from, void 0) === null) return null;
|
|
5482
|
+
return scanForMatch(c, from, tz);
|
|
5483
|
+
}
|
|
5484
|
+
function scanForMatch(c, from, tz) {
|
|
5485
|
+
const d = new Date(from.getTime());
|
|
5486
|
+
d.setSeconds(0, 0);
|
|
5487
|
+
d.setMinutes(d.getMinutes() + 1);
|
|
5488
|
+
for (let i = 0; i < 366 * 24 * 60; i++) {
|
|
5489
|
+
if (cronMatches(c, tz ? inZone(d, tz) : d)) return new Date(d.getTime());
|
|
5490
|
+
d.setMinutes(d.getMinutes() + 1);
|
|
5491
|
+
}
|
|
5492
|
+
return null;
|
|
5493
|
+
}
|
|
5494
|
+
function describeNextFire(expr, tz, from = /* @__PURE__ */ new Date()) {
|
|
5495
|
+
let next;
|
|
5496
|
+
try {
|
|
5497
|
+
next = nextFire(expr, from, tz);
|
|
5498
|
+
} catch {
|
|
5499
|
+
return null;
|
|
5500
|
+
}
|
|
5501
|
+
if (!next) return "never fires";
|
|
5502
|
+
const shown = tz ? inZone(next, tz) : next;
|
|
5503
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
5504
|
+
const stamp = `${shown.getFullYear()}-${pad(shown.getMonth() + 1)}-${pad(shown.getDate())} ${pad(shown.getHours())}:${pad(shown.getMinutes())}`;
|
|
5505
|
+
return `next ${stamp} ${tz || "local"}`;
|
|
5506
|
+
}
|
|
5470
5507
|
function resolvePath(ctx, path) {
|
|
5471
5508
|
return path.split(".").reduce((o, k) => o == null ? void 0 : o[k], ctx);
|
|
5472
5509
|
}
|
|
@@ -7823,9 +7860,12 @@ async function registerMachineService(server, machineId, metadata, daemonState,
|
|
|
7823
7860
|
if (!tunnels) throw new Error("Tunnel management not available");
|
|
7824
7861
|
const client = tunnels.get(params.name);
|
|
7825
7862
|
if (!client) throw new Error(`Tunnel '${params.name}' not found`);
|
|
7863
|
+
const owner = handlers.listExposedTunnels?.().find((t) => t.name === params.name)?.sessionId;
|
|
7826
7864
|
client.destroy();
|
|
7827
7865
|
tunnels.delete(params.name);
|
|
7828
7866
|
handlers.forgetExposedTunnel?.(params.name);
|
|
7867
|
+
if (owner) handlers.dropTunnelSessionLink?.(owner, params.name);
|
|
7868
|
+
handlers.scheduleServiceLinkReconcile?.();
|
|
7829
7869
|
return { name: params.name, stopped: true };
|
|
7830
7870
|
},
|
|
7831
7871
|
/**
|
|
@@ -7868,6 +7908,7 @@ async function registerMachineService(server, machineId, metadata, daemonState,
|
|
|
7868
7908
|
sessionId: params.sessionId,
|
|
7869
7909
|
addedAt: Date.now()
|
|
7870
7910
|
});
|
|
7911
|
+
if (params.sessionId) handlers.scheduleServiceLinkReconcile?.();
|
|
7871
7912
|
const urls = {};
|
|
7872
7913
|
for (const [port, url] of tunnel.getUrls()) urls[port] = url;
|
|
7873
7914
|
return { ...tunnel.status, urls };
|
|
@@ -7879,9 +7920,12 @@ async function registerMachineService(server, machineId, metadata, daemonState,
|
|
|
7879
7920
|
if (!tunnels) throw new Error("Tunnel management not available");
|
|
7880
7921
|
const client = tunnels.get(params.name);
|
|
7881
7922
|
if (!client) throw new Error(`Tunnel '${params.name}' not found`);
|
|
7923
|
+
const owner = handlers.listExposedTunnels?.().find((t) => t.name === params.name)?.sessionId;
|
|
7882
7924
|
client.destroy();
|
|
7883
7925
|
tunnels.delete(params.name);
|
|
7884
7926
|
handlers.forgetExposedTunnel?.(params.name);
|
|
7927
|
+
if (owner) handlers.dropTunnelSessionLink?.(owner, params.name);
|
|
7928
|
+
handlers.scheduleServiceLinkReconcile?.();
|
|
7885
7929
|
return { name: params.name, stopped: true };
|
|
7886
7930
|
},
|
|
7887
7931
|
/**
|
|
@@ -7942,7 +7986,9 @@ async function registerMachineService(server, machineId, metadata, daemonState,
|
|
|
7942
7986
|
assertMayReplaceMount(sm, params.name, context);
|
|
7943
7987
|
const ownerEmail2 = resolveMountOwnerEmailFor(params.ownerEmail, context);
|
|
7944
7988
|
const access = params.access || "owner";
|
|
7945
|
-
|
|
7989
|
+
const result = sm.addMount(params.name, params.directory, params.sessionId, access, ownerEmail2);
|
|
7990
|
+
if (params.sessionId) handlers.scheduleServiceLinkReconcile?.();
|
|
7991
|
+
return result;
|
|
7946
7992
|
},
|
|
7947
7993
|
/**
|
|
7948
7994
|
* Apply a mount declaratively. Replaces existing mount with same name.
|
|
@@ -8332,7 +8378,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
|
|
|
8332
8378
|
}
|
|
8333
8379
|
const deps = buildSessionDeps(rpc, { cwd, ownerEmail: owner });
|
|
8334
8380
|
const sender = { name: context?.user?.email || context?.user?.id || "user", kind: "user", verified: true };
|
|
8335
|
-
const { toolsForRole } = await import('./sideband
|
|
8381
|
+
const { toolsForRole } = await import('./sideband-DXyAkIaB.mjs');
|
|
8336
8382
|
const r2 = await runWiseAgent({ message: params.message, sender, config: { tools: toolsForRole(role2) }, deps, transport, model: resolved.model });
|
|
8337
8383
|
return fmt(r2);
|
|
8338
8384
|
}
|
|
@@ -8464,7 +8510,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
|
|
|
8464
8510
|
return { ok: false, call_id: callId, status: "busy", error: "channel is busy (too many concurrent requests) \u2014 retry shortly" };
|
|
8465
8511
|
}
|
|
8466
8512
|
const rendered = renderMessage(c, { sender: r.sender, body: { message: kwargs.message }, callId });
|
|
8467
|
-
const { queryCore } = await import('./commands-
|
|
8513
|
+
const { queryCore } = await import('./commands-DKouDroK.mjs');
|
|
8468
8514
|
const timeout = c.reply?.timeout_sec || 120;
|
|
8469
8515
|
let result;
|
|
8470
8516
|
let thrownSessionId;
|
|
@@ -9278,10 +9324,15 @@ const OUTPOST_EXEC_TIMEOUT_MS = 12 * 6e4;
|
|
|
9278
9324
|
const OUTPOST_MAX_OUTPUT_BYTES = 1 << 20;
|
|
9279
9325
|
function capOutpostOutput(s) {
|
|
9280
9326
|
if (!s) return "";
|
|
9281
|
-
|
|
9282
|
-
|
|
9283
|
-
|
|
9284
|
-
|
|
9327
|
+
const bytes = Buffer.byteLength(s, "utf-8");
|
|
9328
|
+
if (bytes <= OUTPOST_MAX_OUTPUT_BYTES) return s;
|
|
9329
|
+
const buf = Buffer.from(s, "utf-8");
|
|
9330
|
+
let start = buf.length - OUTPOST_MAX_OUTPUT_BYTES;
|
|
9331
|
+
while (start < buf.length && (buf[start] & 192) === 128) start++;
|
|
9332
|
+
const tail = buf.subarray(start).toString("utf-8");
|
|
9333
|
+
const dropped = bytes - Buffer.byteLength(tail, "utf-8");
|
|
9334
|
+
return `[svamp-daemon] output truncated: ${dropped} earlier bytes dropped
|
|
9335
|
+
${tail}`;
|
|
9285
9336
|
}
|
|
9286
9337
|
class OutpostCoordinator {
|
|
9287
9338
|
conns = /* @__PURE__ */ new Map();
|
|
@@ -9399,9 +9450,14 @@ class OutpostCoordinator {
|
|
|
9399
9450
|
resolveTarget(target) {
|
|
9400
9451
|
const live = this.listConnections();
|
|
9401
9452
|
if (target) {
|
|
9402
|
-
const
|
|
9403
|
-
if (
|
|
9404
|
-
|
|
9453
|
+
const byId = live.find((c) => c.machine === target);
|
|
9454
|
+
if (byId) return { machine: byId.machine };
|
|
9455
|
+
const byLabel = live.filter((c) => c.label === target);
|
|
9456
|
+
if (byLabel.length === 1) return { machine: byLabel[0].machine };
|
|
9457
|
+
if (byLabel.length > 1) {
|
|
9458
|
+
return { error: `outpost label "${target}" is ambiguous \u2014 ${byLabel.length} connected outposts share it (${byLabel.map((c) => c.machine).join(", ")}); pass the machine id instead` };
|
|
9459
|
+
}
|
|
9460
|
+
return { error: `no connected outpost named "${target}" (connected: ${live.map((c) => c.machine).join(", ") || "none"})` };
|
|
9405
9461
|
}
|
|
9406
9462
|
if (live.length === 0) return { error: "no remote outpost is connected \u2014 run the install one-liner on the remote machine first" };
|
|
9407
9463
|
if (live.length > 1) return { error: `multiple outposts connected (${live.map((c) => c.machine).join(", ")}) \u2014 pass a target` };
|
|
@@ -10015,7 +10071,7 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
|
|
|
10015
10071
|
ensureParticipantsChannel(initialMetadata.sharing);
|
|
10016
10072
|
const forkClaudeOnce = async (prompt, claudeSessionId, cwd, maxTurns, timeoutMs) => {
|
|
10017
10073
|
const { spawn } = await import('child_process');
|
|
10018
|
-
const forkEnv = { ...process.env, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1" };
|
|
10074
|
+
const forkEnv = { ...process.env, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1", DISABLE_AUTOUPDATER: "1" };
|
|
10019
10075
|
applyClaudeProxyEnv(forkEnv);
|
|
10020
10076
|
return new Promise((resolve) => {
|
|
10021
10077
|
const child = spawn("claude", [
|
|
@@ -11609,6 +11665,53 @@ function buildSessionIdentityEnv(identity) {
|
|
|
11609
11665
|
return env;
|
|
11610
11666
|
}
|
|
11611
11667
|
|
|
11668
|
+
async function downloadSkillAtomically(targetDir, files, fetchFile) {
|
|
11669
|
+
const stagingDir = `${targetDir}.tmp-${process.pid}-${Date.now().toString(36)}`;
|
|
11670
|
+
try {
|
|
11671
|
+
mkdirSync$1(stagingDir, { recursive: true });
|
|
11672
|
+
for (const filePath of files) {
|
|
11673
|
+
if (!filePath) continue;
|
|
11674
|
+
const content = await fetchFile(filePath);
|
|
11675
|
+
const localPath = join$1(stagingDir, filePath);
|
|
11676
|
+
if (!localPath.startsWith(stagingDir + "/")) continue;
|
|
11677
|
+
mkdirSync$1(dirname(localPath), { recursive: true });
|
|
11678
|
+
writeFileSync$1(localPath, content, "utf-8");
|
|
11679
|
+
}
|
|
11680
|
+
} catch (err) {
|
|
11681
|
+
rmSync$1(stagingDir, { recursive: true, force: true });
|
|
11682
|
+
throw err;
|
|
11683
|
+
}
|
|
11684
|
+
const backupDir = `${targetDir}.old-${process.pid}-${Date.now().toString(36)}`;
|
|
11685
|
+
let backedUp = false;
|
|
11686
|
+
try {
|
|
11687
|
+
if (existsSync(targetDir)) {
|
|
11688
|
+
renameSync(targetDir, backupDir);
|
|
11689
|
+
backedUp = true;
|
|
11690
|
+
}
|
|
11691
|
+
renameSync(stagingDir, targetDir);
|
|
11692
|
+
} catch (err) {
|
|
11693
|
+
if (backedUp && !existsSync(targetDir)) {
|
|
11694
|
+
try {
|
|
11695
|
+
renameSync(backupDir, targetDir);
|
|
11696
|
+
backedUp = false;
|
|
11697
|
+
} catch {
|
|
11698
|
+
}
|
|
11699
|
+
}
|
|
11700
|
+
try {
|
|
11701
|
+
rmSync$1(stagingDir, { recursive: true, force: true });
|
|
11702
|
+
} catch {
|
|
11703
|
+
}
|
|
11704
|
+
if (backedUp) {
|
|
11705
|
+
try {
|
|
11706
|
+
rmSync$1(backupDir, { recursive: true, force: true });
|
|
11707
|
+
} catch {
|
|
11708
|
+
}
|
|
11709
|
+
}
|
|
11710
|
+
throw err;
|
|
11711
|
+
}
|
|
11712
|
+
if (backedUp) rmSync$1(backupDir, { recursive: true, force: true });
|
|
11713
|
+
}
|
|
11714
|
+
|
|
11612
11715
|
const HOTRELOAD_ENV = "SVAMP_DEV_HOTRELOAD";
|
|
11613
11716
|
function isHotReloadEnabled(env = process.env) {
|
|
11614
11717
|
const v = env[HOTRELOAD_ENV];
|
|
@@ -14219,7 +14322,7 @@ function codexCumulativeTokens(payload) {
|
|
|
14219
14322
|
return nonCachedInput + output + Math.round(cached * 0.1);
|
|
14220
14323
|
}
|
|
14221
14324
|
|
|
14222
|
-
const PINNED_CODEX_VERSION = "0.
|
|
14325
|
+
const PINNED_CODEX_VERSION = "0.149.0";
|
|
14223
14326
|
const MIN_CODEX_STEER_VERSION = { major: 0, minor: 129, patch: 0 };
|
|
14224
14327
|
function cmpVer(a, b) {
|
|
14225
14328
|
return a.major - b.major || a.minor - b.minor || a.patch - b.patch;
|
|
@@ -15250,6 +15353,15 @@ function kimiProviderConfigured(configTomlText, provider) {
|
|
|
15250
15353
|
const block = nextTable < 0 ? rest : rest.slice(0, nextTable);
|
|
15251
15354
|
return /(^|\n)\s*api_key\s*=/.test(block);
|
|
15252
15355
|
}
|
|
15356
|
+
function kimiHasGlobalDefaultModel(configTomlText) {
|
|
15357
|
+
if (!configTomlText) return false;
|
|
15358
|
+
const firstTable = configTomlText.search(/(^|\n)\s*\[/);
|
|
15359
|
+
const preamble = firstTable < 0 ? configTomlText : configTomlText.slice(0, firstTable);
|
|
15360
|
+
return /(^|\n)\s*default_model\s*=/.test(preamble);
|
|
15361
|
+
}
|
|
15362
|
+
function kimiConfigComplete(configTomlText, provider) {
|
|
15363
|
+
return kimiProviderConfigured(configTomlText, provider) && kimiHasGlobalDefaultModel(configTomlText);
|
|
15364
|
+
}
|
|
15253
15365
|
function kimiModelMenu(env = process.env) {
|
|
15254
15366
|
return (env.SVAMP_KIMI_MODELS || "").split(",").map((s) => s.trim()).filter(Boolean).filter((m, i, a) => a.indexOf(m) === i);
|
|
15255
15367
|
}
|
|
@@ -15271,8 +15383,10 @@ var kimiProvider = /*#__PURE__*/Object.freeze({
|
|
|
15271
15383
|
buildKimiCatalogAddArgs: buildKimiCatalogAddArgs,
|
|
15272
15384
|
hasKimiProvider: hasKimiProvider,
|
|
15273
15385
|
kimiClampModel: kimiClampModel,
|
|
15386
|
+
kimiConfigComplete: kimiConfigComplete,
|
|
15274
15387
|
kimiDefaultModel: kimiDefaultModel,
|
|
15275
15388
|
kimiDefaultModelId: kimiDefaultModelId,
|
|
15389
|
+
kimiHasGlobalDefaultModel: kimiHasGlobalDefaultModel,
|
|
15276
15390
|
kimiModelMenu: kimiModelMenu,
|
|
15277
15391
|
kimiProviderConfigured: kimiProviderConfigured,
|
|
15278
15392
|
kimiSpawnEnv: kimiSpawnEnv,
|
|
@@ -15291,7 +15405,7 @@ async function ensureKimiProviderConfigured(env = process.env, command = "kimi",
|
|
|
15291
15405
|
}) {
|
|
15292
15406
|
const cfg = resolveKimiProvider(env);
|
|
15293
15407
|
if (!hasKimiProvider(cfg)) return false;
|
|
15294
|
-
if (
|
|
15408
|
+
if (kimiConfigComplete(readKimiConfig(), cfg.provider)) return true;
|
|
15295
15409
|
const args = buildKimiCatalogAddArgs(cfg);
|
|
15296
15410
|
if (!args) return false;
|
|
15297
15411
|
try {
|
|
@@ -15309,7 +15423,11 @@ async function ensureKimiProviderConfigured(env = process.env, command = "kimi",
|
|
|
15309
15423
|
);
|
|
15310
15424
|
});
|
|
15311
15425
|
log(`[kimi] configured provider '${cfg.provider}' in ${KIMI_CONFIG_PATH}`);
|
|
15312
|
-
|
|
15426
|
+
const complete = kimiConfigComplete(readKimiConfig(), cfg.provider);
|
|
15427
|
+
if (!complete) {
|
|
15428
|
+
log(`[kimi] catalog add left ${KIMI_CONFIG_PATH} without a global default_model \u2014 \`kimi acp\` will refuse session/new ("no default model configured")`);
|
|
15429
|
+
}
|
|
15430
|
+
return complete;
|
|
15313
15431
|
} catch (err) {
|
|
15314
15432
|
log(`[kimi] provider auto-config failed (${err?.message || err}); session may need kimi-auth`);
|
|
15315
15433
|
return false;
|
|
@@ -16297,14 +16415,21 @@ class ProcessSupervisor {
|
|
|
16297
16415
|
if (entry.stopping) throw new Error(`Process '${entry.spec.name}' is being stopped, try again shortly`);
|
|
16298
16416
|
throw new Error(`Process '${entry.spec.name}' is already running`);
|
|
16299
16417
|
}
|
|
16300
|
-
entry
|
|
16301
|
-
|
|
16302
|
-
|
|
16303
|
-
|
|
16304
|
-
|
|
16305
|
-
|
|
16306
|
-
|
|
16307
|
-
|
|
16418
|
+
return this.runExclusive(entry, async () => {
|
|
16419
|
+
if (entry.deleted) throw new Error(`Process '${idOrName}' has been removed`);
|
|
16420
|
+
if (entry.child) {
|
|
16421
|
+
if (entry.stopping) throw new Error(`Process '${entry.spec.name}' is being stopped, try again shortly`);
|
|
16422
|
+
throw new Error(`Process '${entry.spec.name}' is already running`);
|
|
16423
|
+
}
|
|
16424
|
+
entry.stopping = false;
|
|
16425
|
+
this.clearTimers(entry);
|
|
16426
|
+
if (entry.spec.desiredStopped) {
|
|
16427
|
+
entry.spec.desiredStopped = false;
|
|
16428
|
+
await this.persistSpec(entry.spec);
|
|
16429
|
+
}
|
|
16430
|
+
this.resetFailureTracking(entry);
|
|
16431
|
+
await this.startEntry(entry, false);
|
|
16432
|
+
});
|
|
16308
16433
|
}
|
|
16309
16434
|
/**
|
|
16310
16435
|
* Stop a running process. Does NOT remove it from supervision.
|
|
@@ -16314,7 +16439,7 @@ class ProcessSupervisor {
|
|
|
16314
16439
|
*/
|
|
16315
16440
|
/**
|
|
16316
16441
|
* #0347: run `fn` in the entry's lifecycle critical section. Each call awaits the previous
|
|
16317
|
-
* lifecycle op's SETTLEMENT before running, so stop/restart/apply/update/remove are strictly
|
|
16442
|
+
* lifecycle op's SETTLEMENT before running, so start/stop/restart/apply/update/remove are strictly
|
|
16318
16443
|
* serialized per entry and can never interleave across an `await killChild` (which is what let
|
|
16319
16444
|
* two ops double-spawn an orphan, or resurrect a just-stopped process). The chain tail never
|
|
16320
16445
|
* rejects (a failed op must not wedge the queue); the caller still gets the real result/error.
|
|
@@ -16531,7 +16656,7 @@ class ProcessSupervisor {
|
|
|
16531
16656
|
}
|
|
16532
16657
|
async persistSpec(spec) {
|
|
16533
16658
|
const filePath = path__default.join(this.persistDir, `${spec.id}.json`);
|
|
16534
|
-
const tmpPath = filePath
|
|
16659
|
+
const tmpPath = `${filePath}.tmp-${process.pid}-${randomBytes$1(4).toString("hex")}`;
|
|
16535
16660
|
await writeFile$1(tmpPath, JSON.stringify(spec, null, 2), "utf-8");
|
|
16536
16661
|
await rename(tmpPath, filePath);
|
|
16537
16662
|
}
|
|
@@ -17110,7 +17235,7 @@ function searchIssues(projectRoot, query) {
|
|
|
17110
17235
|
const q = query.trim();
|
|
17111
17236
|
if (!q) return [];
|
|
17112
17237
|
try {
|
|
17113
|
-
const out = execFileSync("rg", ["-l", "-i", "--no-messages", q, issuesDir(projectRoot)], { encoding: "utf-8" });
|
|
17238
|
+
const out = execFileSync("rg", ["-l", "-i", "-F", "--no-messages", "-e", q, "--", issuesDir(projectRoot)], { encoding: "utf-8" });
|
|
17114
17239
|
const files = out.split("\n").filter(Boolean);
|
|
17115
17240
|
const issues = [];
|
|
17116
17241
|
for (const f of files) {
|
|
@@ -17121,9 +17246,24 @@ function searchIssues(projectRoot, query) {
|
|
|
17121
17246
|
}
|
|
17122
17247
|
}
|
|
17123
17248
|
return issues.sort((a, b) => Number(a.id) - Number(b.id));
|
|
17124
|
-
} catch {
|
|
17125
|
-
|
|
17126
|
-
return
|
|
17249
|
+
} catch (e) {
|
|
17250
|
+
if (e?.status === 1) return [];
|
|
17251
|
+
return searchIssuesInMemory(projectRoot, q);
|
|
17252
|
+
}
|
|
17253
|
+
}
|
|
17254
|
+
function searchIssuesInMemory(projectRoot, q) {
|
|
17255
|
+
const ql = q.toLowerCase();
|
|
17256
|
+
return listIssues(projectRoot, { includeArchived: true }).filter((i) => i.title.toLowerCase().includes(ql) || (i.body || "").toLowerCase().includes(ql) || i.labels.some((l) => l.toLowerCase().includes(ql)));
|
|
17257
|
+
}
|
|
17258
|
+
function checkVerifyCommand(projectRoot, issue) {
|
|
17259
|
+
const cmd = issue?.verify?.type === "command" ? (issue.verify.text || "").trim() : "";
|
|
17260
|
+
if (!cmd) return { ok: true };
|
|
17261
|
+
try {
|
|
17262
|
+
execSync$1(cmd, { cwd: projectRoot, stdio: "pipe", timeout: 6e5, maxBuffer: 64 * 1024 * 1024 });
|
|
17263
|
+
return { ok: true, cmd };
|
|
17264
|
+
} catch (e) {
|
|
17265
|
+
const output = (String(e?.stdout || "") + String(e?.stderr || "")).split("\n").slice(-15).join("\n").trim();
|
|
17266
|
+
return { ok: false, cmd, output };
|
|
17127
17267
|
}
|
|
17128
17268
|
}
|
|
17129
17269
|
function summarize(issues) {
|
|
@@ -17166,11 +17306,29 @@ function resolveLogPrunePolicy(env = process.env) {
|
|
|
17166
17306
|
maxBytes: num(env.SVAMP_LOG_MAX_BYTES, DEFAULT_LOG_PRUNE_POLICY.maxBytes)
|
|
17167
17307
|
};
|
|
17168
17308
|
}
|
|
17169
|
-
function
|
|
17170
|
-
|
|
17171
|
-
|
|
17172
|
-
|
|
17173
|
-
|
|
17309
|
+
function trimToLineStart(buf) {
|
|
17310
|
+
const nl = buf.indexOf(10);
|
|
17311
|
+
return nl >= 0 && nl + 1 < buf.length ? buf.subarray(nl + 1) : buf;
|
|
17312
|
+
}
|
|
17313
|
+
|
|
17314
|
+
function readLogTail(path, tailBytes) {
|
|
17315
|
+
const fd = openSync(path, "r");
|
|
17316
|
+
try {
|
|
17317
|
+
const size = fstatSync(fd).size;
|
|
17318
|
+
const want = Math.min(Math.max(0, Math.floor(tailBytes)), size);
|
|
17319
|
+
if (want === 0) return { data: Buffer.alloc(0), truncated: size > 0 };
|
|
17320
|
+
const buf = Buffer.allocUnsafe(want);
|
|
17321
|
+
const start = size - want;
|
|
17322
|
+
let read = 0;
|
|
17323
|
+
while (read < want) {
|
|
17324
|
+
const n = readSync(fd, buf, read, want - read, start + read);
|
|
17325
|
+
if (n <= 0) break;
|
|
17326
|
+
read += n;
|
|
17327
|
+
}
|
|
17328
|
+
return { data: read === want ? buf : buf.subarray(0, read), truncated: size > want };
|
|
17329
|
+
} finally {
|
|
17330
|
+
closeSync(fd);
|
|
17331
|
+
}
|
|
17174
17332
|
}
|
|
17175
17333
|
|
|
17176
17334
|
const CARRIER_FIELDS = ["message", "error", "detail", "reason", "description"];
|
|
@@ -17889,6 +18047,15 @@ function isCostCeiling(kind) {
|
|
|
17889
18047
|
function isHardBudgetStop(kind) {
|
|
17890
18048
|
return isCostCeiling(kind) || kind === "iteration";
|
|
17891
18049
|
}
|
|
18050
|
+
function rearmStartedAt(startedAt, completedAt, now) {
|
|
18051
|
+
const fin = (v) => typeof v === "number" && Number.isFinite(v) && v > 0;
|
|
18052
|
+
if (!fin(startedAt)) return startedAt;
|
|
18053
|
+
if (!fin(completedAt)) return startedAt;
|
|
18054
|
+
if (completedAt < startedAt) return startedAt;
|
|
18055
|
+
const dormantMs = now - completedAt;
|
|
18056
|
+
if (dormantMs <= 0) return startedAt;
|
|
18057
|
+
return startedAt + dormantMs;
|
|
18058
|
+
}
|
|
17892
18059
|
function checkLoopBudget(ledger, limits, now, startedAt) {
|
|
17893
18060
|
const L = limits || {};
|
|
17894
18061
|
const led = ledger || { turns: 0, tokens: 0, window: [] };
|
|
@@ -18368,6 +18535,47 @@ function isContextTooLongError(text) {
|
|
|
18368
18535
|
if (t.includes("context") && t.includes("exceed") && t.includes("limit") && !t.includes("subscription")) return true;
|
|
18369
18536
|
return false;
|
|
18370
18537
|
}
|
|
18538
|
+
function shouldEvaluateProactiveCompaction(state) {
|
|
18539
|
+
if (!state.enabled) return false;
|
|
18540
|
+
if (state.disabled) return false;
|
|
18541
|
+
if (state.turnErrored) return false;
|
|
18542
|
+
if (state.compactPending) return false;
|
|
18543
|
+
if (state.justCompacted) return false;
|
|
18544
|
+
return true;
|
|
18545
|
+
}
|
|
18546
|
+
function compactSupportedFromSlashCommands(slashCommands) {
|
|
18547
|
+
if (!Array.isArray(slashCommands) || slashCommands.length === 0) return void 0;
|
|
18548
|
+
return slashCommands.some(
|
|
18549
|
+
(c) => typeof c === "string" && c.trim().replace(/^\//, "").toLowerCase() === "compact"
|
|
18550
|
+
);
|
|
18551
|
+
}
|
|
18552
|
+
const DEFAULT_COMPACT_NO_BOUNDARY_STRIKES = 3;
|
|
18553
|
+
function decideCompactUnsupported(input) {
|
|
18554
|
+
const prior = Math.max(0, input.priorStrikes || 0);
|
|
18555
|
+
const limit = Math.max(1, input.maxStrikes);
|
|
18556
|
+
if (input.turnErrored) {
|
|
18557
|
+
return { disable: false, warnUnsupported: false, strikes: prior, reason: "errored-turn" };
|
|
18558
|
+
}
|
|
18559
|
+
if (!input.wasAutoInjected) {
|
|
18560
|
+
return {
|
|
18561
|
+
disable: false,
|
|
18562
|
+
warnUnsupported: input.compactSupported === false,
|
|
18563
|
+
strikes: prior,
|
|
18564
|
+
reason: "user-typed"
|
|
18565
|
+
};
|
|
18566
|
+
}
|
|
18567
|
+
if (input.compactSupported === false) {
|
|
18568
|
+
return { disable: true, warnUnsupported: true, strikes: prior + 1, reason: "unsupported" };
|
|
18569
|
+
}
|
|
18570
|
+
const strikes = prior + 1;
|
|
18571
|
+
if (strikes >= limit) {
|
|
18572
|
+
return { disable: true, warnUnsupported: false, strikes, reason: "strikes-exhausted" };
|
|
18573
|
+
}
|
|
18574
|
+
return { disable: false, warnUnsupported: false, strikes, reason: "strike" };
|
|
18575
|
+
}
|
|
18576
|
+
function describeNoBoundary(strikes, limit) {
|
|
18577
|
+
return `Automatic compaction ran but reported no compaction boundary (attempt ${strikes} of ${limit}) \u2014 usually because there was nothing left to compact. Keeping automatic compaction enabled.`;
|
|
18578
|
+
}
|
|
18371
18579
|
|
|
18372
18580
|
function fmtTokens(n) {
|
|
18373
18581
|
return Math.max(0, Math.round(n)).toLocaleString("en-US");
|
|
@@ -18941,23 +19149,27 @@ function compareVersions(a, b) {
|
|
|
18941
19149
|
return 0;
|
|
18942
19150
|
}
|
|
18943
19151
|
async function installSkillFromEndpoint(name, baseUrl) {
|
|
18944
|
-
const
|
|
18945
|
-
if (!resp.ok) throw new Error(`HTTP ${resp.status} from ${baseUrl}`);
|
|
18946
|
-
const index = await resp.json();
|
|
19152
|
+
const index = await fetchEndpointSkillIndex(baseUrl);
|
|
18947
19153
|
const files = index.files || [];
|
|
18948
19154
|
if (files.length === 0) throw new Error(`Skill index at ${baseUrl} has no files`);
|
|
18949
|
-
|
|
18950
|
-
|
|
18951
|
-
for (const filePath of files) {
|
|
18952
|
-
if (!filePath) continue;
|
|
18953
|
-
const url = `${baseUrl}${filePath}`;
|
|
18954
|
-
const fileResp = await fetch(url, { signal: AbortSignal.timeout(3e4) });
|
|
19155
|
+
await downloadSkillAtomically(join(CLAUDE_SKILLS_DIR, name), files, async (filePath) => {
|
|
19156
|
+
const fileResp = await fetch(`${baseUrl}${filePath}`, { signal: AbortSignal.timeout(3e4) });
|
|
18955
19157
|
if (!fileResp.ok) throw new Error(`Failed to download ${filePath}: HTTP ${fileResp.status}`);
|
|
18956
|
-
|
|
18957
|
-
|
|
18958
|
-
|
|
18959
|
-
|
|
18960
|
-
|
|
19158
|
+
return fileResp.text();
|
|
19159
|
+
});
|
|
19160
|
+
}
|
|
19161
|
+
async function fetchEndpointSkillIndex(baseUrl) {
|
|
19162
|
+
const resp = await fetch(baseUrl, { signal: AbortSignal.timeout(15e3) });
|
|
19163
|
+
if (!resp.ok) throw new Error(`HTTP ${resp.status} from ${baseUrl}`);
|
|
19164
|
+
return await resp.json();
|
|
19165
|
+
}
|
|
19166
|
+
async function fetchEndpointSkillVersion(baseUrl) {
|
|
19167
|
+
try {
|
|
19168
|
+
const index = await fetchEndpointSkillIndex(baseUrl);
|
|
19169
|
+
const v = index?.version;
|
|
19170
|
+
return typeof v === "string" && v.trim() ? v.trim() : null;
|
|
19171
|
+
} catch {
|
|
19172
|
+
return null;
|
|
18961
19173
|
}
|
|
18962
19174
|
}
|
|
18963
19175
|
async function installSkillFromMarketplace(name) {
|
|
@@ -18981,26 +19193,11 @@ async function installSkillFromMarketplace(name) {
|
|
|
18981
19193
|
}
|
|
18982
19194
|
const files = await collectFiles();
|
|
18983
19195
|
if (files.length === 0) throw new Error(`Skill ${name} has no files in marketplace`);
|
|
18984
|
-
|
|
18985
|
-
|
|
18986
|
-
|
|
18987
|
-
|
|
18988
|
-
|
|
18989
|
-
const url = `${BASE}/files/${filePath}`;
|
|
18990
|
-
const resp = await fetch(url, { signal: AbortSignal.timeout(3e4) });
|
|
18991
|
-
if (!resp.ok) throw new Error(`Failed to download ${filePath}: HTTP ${resp.status}`);
|
|
18992
|
-
const content = await resp.text();
|
|
18993
|
-
const localPath = join(stagingDir, filePath);
|
|
18994
|
-
if (!localPath.startsWith(stagingDir + "/")) continue;
|
|
18995
|
-
mkdirSync(dirname$1(localPath), { recursive: true });
|
|
18996
|
-
writeFileSync(localPath, content, "utf-8");
|
|
18997
|
-
}
|
|
18998
|
-
rmSync(targetDir, { recursive: true, force: true });
|
|
18999
|
-
renameSync$1(stagingDir, targetDir);
|
|
19000
|
-
} catch (err) {
|
|
19001
|
-
rmSync(stagingDir, { recursive: true, force: true });
|
|
19002
|
-
throw err;
|
|
19003
|
-
}
|
|
19196
|
+
await downloadSkillAtomically(join(CLAUDE_SKILLS_DIR, name), files, async (filePath) => {
|
|
19197
|
+
const resp = await fetch(`${BASE}/files/${filePath}`, { signal: AbortSignal.timeout(3e4) });
|
|
19198
|
+
if (!resp.ok) throw new Error(`Failed to download ${filePath}: HTTP ${resp.status}`);
|
|
19199
|
+
return resp.text();
|
|
19200
|
+
});
|
|
19004
19201
|
}
|
|
19005
19202
|
function getBundledSkillsDir() {
|
|
19006
19203
|
try {
|
|
@@ -19219,9 +19416,16 @@ async function ensureAutoInstalledSkills(logger) {
|
|
|
19219
19416
|
marketplaceVersion: () => fetchMarketplaceSkillVersion("svamp")
|
|
19220
19417
|
},
|
|
19221
19418
|
{
|
|
19419
|
+
// #1192: the agent-skills endpoint's index already carries a `version` (verified live:
|
|
19420
|
+
// `{"name":"hypha","version":"1.0.0","files":[...]}`), and installSkillFromEndpoint
|
|
19421
|
+
// fetches that exact document anyway — it just used to discard the field. Supplying the
|
|
19422
|
+
// probe moves `hypha` off the "install once, never refresh" branch, so a machine is no
|
|
19423
|
+
// longer pinned forever to whatever version it first installed. Safe now that #1191
|
|
19424
|
+
// gave this downloader atomic staging: a refresh that fails mid-download leaves the
|
|
19425
|
+
// previous skill intact instead of half-overwriting it.
|
|
19222
19426
|
name: "hypha",
|
|
19223
|
-
install: () => installSkillFromEndpoint("hypha", `${getSkillsServer()}/ws/agent-skills/`)
|
|
19224
|
-
|
|
19427
|
+
install: () => installSkillFromEndpoint("hypha", `${getSkillsServer()}/ws/agent-skills/`),
|
|
19428
|
+
marketplaceVersion: () => fetchEndpointSkillVersion(`${getSkillsServer()}/ws/agent-skills/`)
|
|
19225
19429
|
},
|
|
19226
19430
|
{
|
|
19227
19431
|
// `<artifact>` block rendering — see packages/svamp-app/.../Artifact.tsx.
|
|
@@ -19787,13 +19991,13 @@ function createSvampConfigChecker(directory, sessionId, getMetadata, setMetadata
|
|
|
19787
19991
|
};
|
|
19788
19992
|
let announcedLoopStart = (() => {
|
|
19789
19993
|
const s = readLoopState(directory, sessionId);
|
|
19790
|
-
return s && (s.phase === "done" || s.phase === "gave_up") ? s.started_at ?? "\u2205" : null;
|
|
19994
|
+
return s && (s.phase === "done" || s.phase === "gave_up") ? String(s.started_at ?? "\u2205") : null;
|
|
19791
19995
|
})();
|
|
19792
19996
|
const loopChecker = () => {
|
|
19793
19997
|
try {
|
|
19794
19998
|
const s = readLoopState(directory, sessionId);
|
|
19795
19999
|
if (!s || s.phase !== "done" && s.phase !== "gave_up") return;
|
|
19796
|
-
const key = s.started_at ?? "\u2205";
|
|
20000
|
+
const key = String(s.started_at ?? "\u2205");
|
|
19797
20001
|
if (key === announcedLoopStart) return;
|
|
19798
20002
|
announcedLoopStart = key;
|
|
19799
20003
|
const iter = s.ledger && typeof s.ledger.turns === "number" && s.ledger.turns > 0 ? s.ledger.turns : typeof s.iteration === "number" ? s.iteration : 0;
|
|
@@ -20185,7 +20389,9 @@ function pruneDaemonLogs(exclude = []) {
|
|
|
20185
20389
|
for (const { name } of plan.truncateFiles) {
|
|
20186
20390
|
try {
|
|
20187
20391
|
const p = join(LOGS_DIR, name);
|
|
20188
|
-
const
|
|
20392
|
+
const keepBytes = Math.floor(policy.maxBytes / 8);
|
|
20393
|
+
const tail = readLogTail(p, keepBytes);
|
|
20394
|
+
const kept = tail.truncated ? trimToLineStart(tail.data) : tail.data;
|
|
20189
20395
|
writeFileSync(p, kept);
|
|
20190
20396
|
} catch {
|
|
20191
20397
|
}
|
|
@@ -20498,7 +20704,7 @@ async function startDaemon(options) {
|
|
|
20498
20704
|
try {
|
|
20499
20705
|
const dir = loadSessionIndex()[sessionId]?.directory;
|
|
20500
20706
|
if (!dir) return;
|
|
20501
|
-
const { reconcileServiceLinks } = await import('./agentCommands-
|
|
20707
|
+
const { reconcileServiceLinks } = await import('./agentCommands-BVz1k2R2.mjs');
|
|
20502
20708
|
const configPath = getSvampConfigPath(dir, sessionId);
|
|
20503
20709
|
const config = readSvampConfig(configPath);
|
|
20504
20710
|
const entries = Array.from(urls.entries());
|
|
@@ -20520,7 +20726,7 @@ async function startDaemon(options) {
|
|
|
20520
20726
|
try {
|
|
20521
20727
|
const dir = loadSessionIndex()[sessionId]?.directory;
|
|
20522
20728
|
if (!dir) return;
|
|
20523
|
-
const { reconcileServiceLinks } = await import('./agentCommands-
|
|
20729
|
+
const { reconcileServiceLinks } = await import('./agentCommands-BVz1k2R2.mjs');
|
|
20524
20730
|
const configPath = getSvampConfigPath(dir, sessionId);
|
|
20525
20731
|
const config = readSvampConfig(configPath);
|
|
20526
20732
|
const incoming = [{
|
|
@@ -20541,7 +20747,7 @@ async function startDaemon(options) {
|
|
|
20541
20747
|
try {
|
|
20542
20748
|
const dir = loadSessionIndex()[sessionId]?.directory;
|
|
20543
20749
|
if (!dir) return;
|
|
20544
|
-
const { dropServiceLinks } = await import('./agentCommands-
|
|
20750
|
+
const { dropServiceLinks } = await import('./agentCommands-BVz1k2R2.mjs');
|
|
20545
20751
|
const configPath = getSvampConfigPath(dir, sessionId);
|
|
20546
20752
|
const config = readSvampConfig(configPath);
|
|
20547
20753
|
if (dropServiceLinks(config, "serve", mountName)) {
|
|
@@ -20552,6 +20758,73 @@ async function startDaemon(options) {
|
|
|
20552
20758
|
logger.log(`[serve] Link drop failed for mount ${mountName}: ${err?.message || err}`);
|
|
20553
20759
|
}
|
|
20554
20760
|
}
|
|
20761
|
+
async function dropTunnelSessionLink(sessionId, tunnelName) {
|
|
20762
|
+
if (!sessionId) return;
|
|
20763
|
+
try {
|
|
20764
|
+
const dir = loadSessionIndex()[sessionId]?.directory;
|
|
20765
|
+
if (!dir) return;
|
|
20766
|
+
const { dropServiceLinks } = await import('./agentCommands-BVz1k2R2.mjs');
|
|
20767
|
+
const configPath = getSvampConfigPath(dir, sessionId);
|
|
20768
|
+
const config = readSvampConfig(configPath);
|
|
20769
|
+
if (dropServiceLinks(config, "tunnel", tunnelName)) {
|
|
20770
|
+
writeSvampConfig(configPath, config);
|
|
20771
|
+
logger.log(`[exposed-tunnels] Dropped Launch Pad link for tunnel ${tunnelName} \u2190 session ${sessionId}`);
|
|
20772
|
+
}
|
|
20773
|
+
} catch (err) {
|
|
20774
|
+
logger.log(`[exposed-tunnels] Link drop failed for tunnel ${tunnelName}: ${err?.message || err}`);
|
|
20775
|
+
}
|
|
20776
|
+
}
|
|
20777
|
+
async function reconcileAllServiceLinks() {
|
|
20778
|
+
try {
|
|
20779
|
+
const { reconcileServiceLinksExact } = await import('./agentCommands-BVz1k2R2.mjs');
|
|
20780
|
+
const desiredBySession = /* @__PURE__ */ new Map();
|
|
20781
|
+
const push = (sessionId, entry) => {
|
|
20782
|
+
if (!sessionId || !entry.url) return;
|
|
20783
|
+
const list = desiredBySession.get(sessionId) ?? [];
|
|
20784
|
+
list.push(entry);
|
|
20785
|
+
desiredBySession.set(sessionId, list);
|
|
20786
|
+
};
|
|
20787
|
+
for (const m of serveManager$1.listMounts()) {
|
|
20788
|
+
if (m?.sessionId && m?.url) push(m.sessionId, { url: String(m.url), label: m.name, service: { kind: "serve", name: m.name } });
|
|
20789
|
+
}
|
|
20790
|
+
const specBySession = /* @__PURE__ */ new Map();
|
|
20791
|
+
for (const spec of loadExposedTunnels()) if (spec.sessionId) specBySession.set(spec.name, spec.sessionId);
|
|
20792
|
+
for (const [name, tunnel] of tunnels) {
|
|
20793
|
+
const sessionId = specBySession.get(name);
|
|
20794
|
+
if (!sessionId) continue;
|
|
20795
|
+
const urls = Array.from(tunnel.getUrls().entries());
|
|
20796
|
+
for (const [port, url] of urls) {
|
|
20797
|
+
push(sessionId, { url: String(url), label: urls.length > 1 ? `${name}:${port}` : name, service: { kind: "tunnel", name } });
|
|
20798
|
+
}
|
|
20799
|
+
}
|
|
20800
|
+
const sessionIds = /* @__PURE__ */ new Set([...Object.keys(loadSessionIndex()), ...desiredBySession.keys()]);
|
|
20801
|
+
for (const sessionId of sessionIds) {
|
|
20802
|
+
try {
|
|
20803
|
+
const dir = loadSessionIndex()[sessionId]?.directory;
|
|
20804
|
+
if (!dir) continue;
|
|
20805
|
+
const configPath = getSvampConfigPath(dir, sessionId);
|
|
20806
|
+
const config = readSvampConfig(configPath);
|
|
20807
|
+
const desired = desiredBySession.get(sessionId) ?? [];
|
|
20808
|
+
if (reconcileServiceLinksExact(config, ["serve", "tunnel"], desired)) {
|
|
20809
|
+
writeSvampConfig(configPath, config);
|
|
20810
|
+
logger.log(`[launchpad] Reconciled service links for session ${sessionId} (${desired.length} live)`);
|
|
20811
|
+
}
|
|
20812
|
+
} catch (err) {
|
|
20813
|
+
logger.log(`[launchpad] Reconcile failed for session ${sessionId}: ${err?.message || err}`);
|
|
20814
|
+
}
|
|
20815
|
+
}
|
|
20816
|
+
} catch (err) {
|
|
20817
|
+
logger.log(`[launchpad] Service-link sweep failed: ${err?.message || err}`);
|
|
20818
|
+
}
|
|
20819
|
+
}
|
|
20820
|
+
let serviceLinkReconcileTimer;
|
|
20821
|
+
function scheduleServiceLinkReconcile(delayMs = 1200) {
|
|
20822
|
+
if (serviceLinkReconcileTimer) clearTimeout(serviceLinkReconcileTimer);
|
|
20823
|
+
serviceLinkReconcileTimer = setTimeout(() => {
|
|
20824
|
+
serviceLinkReconcileTimer = void 0;
|
|
20825
|
+
void reconcileAllServiceLinks();
|
|
20826
|
+
}, delayMs);
|
|
20827
|
+
}
|
|
20555
20828
|
async function createExposedTunnel(spec) {
|
|
20556
20829
|
const { FrpcTunnel } = await Promise.resolve().then(function () { return frpc; });
|
|
20557
20830
|
const tunnel = new FrpcTunnel({
|
|
@@ -20584,8 +20857,18 @@ async function startDaemon(options) {
|
|
|
20584
20857
|
ensureAutoInstalledCommands(logger);
|
|
20585
20858
|
(async () => {
|
|
20586
20859
|
try {
|
|
20587
|
-
const { beginClaudeVersionReconcile } = await import('./pinnedClaudeCode-
|
|
20588
|
-
|
|
20860
|
+
const { beginClaudeVersionReconcile, CLAUDE_VERSION_RECHECK_MS } = await import('./pinnedClaudeCode-C43KnZ-Q.mjs');
|
|
20861
|
+
const onResult = (result) => {
|
|
20862
|
+
if (result?.kind === "install-failed" || result?.kind === "skipped" || result?.kind === "not-installed") {
|
|
20863
|
+
logger.log(`[claude-version] WARNING \u2014 machine is NOT on the pinned Claude Code (${result.kind}). Sessions are running an untested build.`);
|
|
20864
|
+
}
|
|
20865
|
+
};
|
|
20866
|
+
beginClaudeVersionReconcile((msg) => logger.log(msg), { onResult });
|
|
20867
|
+
const jitter = Math.floor(Math.random() * 5 * 6e4);
|
|
20868
|
+
const timer = setInterval(() => {
|
|
20869
|
+
beginClaudeVersionReconcile((msg) => logger.log(msg), { onResult });
|
|
20870
|
+
}, CLAUDE_VERSION_RECHECK_MS + jitter);
|
|
20871
|
+
timer.unref?.();
|
|
20589
20872
|
} catch (e) {
|
|
20590
20873
|
logger.log(`[claude-version] check failed: ${e?.message || e}`);
|
|
20591
20874
|
}
|
|
@@ -21078,7 +21361,7 @@ ${v.guidance ? v.guidance + "\n" : ""}Criteria: ${v.criteria || "(none)"}
|
|
|
21078
21361
|
const cwd = sessionMetadata.path || directory;
|
|
21079
21362
|
const model = process.env.SVAMP_TOPIC_MODEL;
|
|
21080
21363
|
try {
|
|
21081
|
-
const forkEnv = { ...process.env, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1" };
|
|
21364
|
+
const forkEnv = { ...process.env, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1", DISABLE_AUTOUPDATER: "1" };
|
|
21082
21365
|
applyClaudeProxyEnv(forkEnv);
|
|
21083
21366
|
const child = spawn("claude", [
|
|
21084
21367
|
"--print",
|
|
@@ -21517,6 +21800,9 @@ ${parts.join("\n")}`);
|
|
|
21517
21800
|
let autoCompactWasAutoInjected = false;
|
|
21518
21801
|
let autoCompactDisabled = false;
|
|
21519
21802
|
let autoCompactRecoveryTried = false;
|
|
21803
|
+
let justCompactedTurn = false;
|
|
21804
|
+
let compactNoBoundaryStrikes = 0;
|
|
21805
|
+
let compactSupported = void 0;
|
|
21520
21806
|
let noIsolationWarned = false;
|
|
21521
21807
|
const RATELIMIT_CFG = getRateLimitRetryConfig();
|
|
21522
21808
|
let currentTurnMessage;
|
|
@@ -21962,15 +22248,30 @@ ${parts.join("\n")}`);
|
|
|
21962
22248
|
pendingCompactTurn = false;
|
|
21963
22249
|
const wasAuto = autoCompactWasAutoInjected;
|
|
21964
22250
|
autoCompactWasAutoInjected = false;
|
|
21965
|
-
|
|
22251
|
+
const d = decideCompactUnsupported({
|
|
22252
|
+
wasAutoInjected: wasAuto,
|
|
22253
|
+
turnErrored: !!msg.is_error,
|
|
22254
|
+
compactSupported,
|
|
22255
|
+
priorStrikes: compactNoBoundaryStrikes,
|
|
22256
|
+
maxStrikes: DEFAULT_COMPACT_NO_BOUNDARY_STRIKES
|
|
22257
|
+
});
|
|
22258
|
+
compactNoBoundaryStrikes = d.strikes;
|
|
22259
|
+
if (d.disable) {
|
|
21966
22260
|
autoCompactDisabled = true;
|
|
21967
|
-
logger.log(`[Session ${sessionId}]
|
|
22261
|
+
logger.log(`[Session ${sessionId}] Disabling the auto-compaction backstop for this session (${d.reason})`);
|
|
22262
|
+
}
|
|
22263
|
+
logger.log(`[Session ${sessionId}] /compact produced no compaction boundary (reason=${d.reason}, strikes=${d.strikes}, supported=${String(compactSupported)}, errored=${!!msg.is_error})`);
|
|
22264
|
+
if (d.warnUnsupported) {
|
|
22265
|
+
sessionService.pushMessage(
|
|
22266
|
+
{ type: "message", message: compactUnsupportedWarning(), level: "warning" },
|
|
22267
|
+
"event"
|
|
22268
|
+
);
|
|
22269
|
+
} else if (wasAuto && d.reason !== "errored-turn") {
|
|
22270
|
+
sessionService.pushMessage(
|
|
22271
|
+
{ type: "message", message: describeNoBoundary(d.strikes, DEFAULT_COMPACT_NO_BOUNDARY_STRIKES), level: "warning" },
|
|
22272
|
+
"event"
|
|
22273
|
+
);
|
|
21968
22274
|
}
|
|
21969
|
-
logger.log(`[Session ${sessionId}] /compact produced no compaction boundary \u2014 Claude Code likely too old to handle it in stream-json mode`);
|
|
21970
|
-
sessionService.pushMessage(
|
|
21971
|
-
{ type: "message", message: compactUnsupportedWarning(), level: "warning" },
|
|
21972
|
-
"event"
|
|
21973
|
-
);
|
|
21974
22275
|
}
|
|
21975
22276
|
if (!msg.is_error) {
|
|
21976
22277
|
resetRateLimitStreak();
|
|
@@ -22061,7 +22362,15 @@ ${parts.join("\n")}`);
|
|
|
22061
22362
|
logger.log(`[Session ${sessionId}] ${taskInfo}`);
|
|
22062
22363
|
sessionService.pushMessage({ type: "session_event", message: taskInfo }, "session");
|
|
22063
22364
|
}
|
|
22064
|
-
|
|
22365
|
+
const mayEvaluateLayer1 = shouldEvaluateProactiveCompaction({
|
|
22366
|
+
justCompacted: justCompactedTurn,
|
|
22367
|
+
compactPending: pendingCompactTurn,
|
|
22368
|
+
turnErrored: !!msg.is_error,
|
|
22369
|
+
disabled: autoCompactDisabled,
|
|
22370
|
+
enabled: autoCompactEnabled
|
|
22371
|
+
});
|
|
22372
|
+
justCompactedTurn = false;
|
|
22373
|
+
if (mayEvaluateLayer1) {
|
|
22065
22374
|
try {
|
|
22066
22375
|
const observed = computeObservedContext(msg.usage);
|
|
22067
22376
|
const decision = decideProactiveCompaction({
|
|
@@ -22125,6 +22434,7 @@ ${parts.join("\n")}`);
|
|
|
22125
22434
|
userMessagePending = false;
|
|
22126
22435
|
if (msg.slash_commands && Array.isArray(msg.slash_commands)) {
|
|
22127
22436
|
sessionMetadata = { ...sessionMetadata, slashCommands: msg.slash_commands };
|
|
22437
|
+
compactSupported = compactSupportedFromSlashCommands(msg.slash_commands);
|
|
22128
22438
|
}
|
|
22129
22439
|
if (typeof msg.model === "string" && msg.model.length > 0) {
|
|
22130
22440
|
lastMainModel = msg.model;
|
|
@@ -22178,6 +22488,8 @@ ${parts.join("\n")}`);
|
|
|
22178
22488
|
pendingCompactTurn = false;
|
|
22179
22489
|
autoCompactWasAutoInjected = false;
|
|
22180
22490
|
autoCompactRecoveryTried = false;
|
|
22491
|
+
justCompactedTurn = true;
|
|
22492
|
+
compactNoBoundaryStrikes = 0;
|
|
22181
22493
|
const compactLine = describeCompaction(msg.compact_metadata);
|
|
22182
22494
|
logger.log(`[Session ${sessionId}] ${compactLine}`);
|
|
22183
22495
|
sessionService.pushMessage(
|
|
@@ -22994,11 +23306,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
22994
23306
|
});
|
|
22995
23307
|
},
|
|
22996
23308
|
onIssue: async (params) => {
|
|
22997
|
-
const { issueRpc } = await import('./rpc-
|
|
23309
|
+
const { issueRpc } = await import('./rpc-UomHF39a.mjs');
|
|
22998
23310
|
return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner, rekickLoopOwner });
|
|
22999
23311
|
},
|
|
23000
23312
|
onWorkflow: async (params) => {
|
|
23001
|
-
const { workflowRpc } = await import('./rpc-
|
|
23313
|
+
const { workflowRpc } = await import('./rpc-CoPRGZkJ.mjs');
|
|
23002
23314
|
return workflowRpc(params?.cwd || directory, params || {});
|
|
23003
23315
|
},
|
|
23004
23316
|
onRipgrep: async (args, cwd) => {
|
|
@@ -23218,6 +23530,8 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
23218
23530
|
active: true,
|
|
23219
23531
|
phase: "continue",
|
|
23220
23532
|
iteration: 0,
|
|
23533
|
+
started_at: rearmStartedAt(s.started_at, s.completed_at, Date.now()),
|
|
23534
|
+
// #1170
|
|
23221
23535
|
completed_at: void 0,
|
|
23222
23536
|
gave_up_reason: void 0,
|
|
23223
23537
|
verify_errors: 0,
|
|
@@ -23719,11 +24033,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
23719
24033
|
});
|
|
23720
24034
|
},
|
|
23721
24035
|
onIssue: async (params) => {
|
|
23722
|
-
const { issueRpc } = await import('./rpc-
|
|
24036
|
+
const { issueRpc } = await import('./rpc-UomHF39a.mjs');
|
|
23723
24037
|
return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner, rekickLoopOwner });
|
|
23724
24038
|
},
|
|
23725
24039
|
onWorkflow: async (params) => {
|
|
23726
|
-
const { workflowRpc } = await import('./rpc-
|
|
24040
|
+
const { workflowRpc } = await import('./rpc-CoPRGZkJ.mjs');
|
|
23727
24041
|
return workflowRpc(params?.cwd || directory, params || {});
|
|
23728
24042
|
},
|
|
23729
24043
|
onRipgrep: async (args, cwd) => {
|
|
@@ -24588,7 +24902,11 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
|
|
|
24588
24902
|
sharingNotificationSync,
|
|
24589
24903
|
persistExposedTunnel,
|
|
24590
24904
|
forgetExposedTunnel,
|
|
24591
|
-
listExposedTunnels: () => loadExposedTunnels().map((t) => ({ name: t.name, ports: t.ports, group: t.group, sessionId: t.sessionId, addedAt: t.addedAt }))
|
|
24905
|
+
listExposedTunnels: () => loadExposedTunnels().map((t) => ({ name: t.name, ports: t.ports, group: t.group, sessionId: t.sessionId, addedAt: t.addedAt })),
|
|
24906
|
+
dropTunnelSessionLink: (sessionId, tunnelName) => {
|
|
24907
|
+
void dropTunnelSessionLink(sessionId, tunnelName);
|
|
24908
|
+
},
|
|
24909
|
+
scheduleServiceLinkReconcile: () => scheduleServiceLinkReconcile()
|
|
24592
24910
|
});
|
|
24593
24911
|
const machineService = await registerMachineService(
|
|
24594
24912
|
server,
|
|
@@ -24720,6 +25038,7 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
|
|
|
24720
25038
|
} catch (err) {
|
|
24721
25039
|
logger.log(`[serve] mount link reconcile failed: ${err?.message || err}`);
|
|
24722
25040
|
}
|
|
25041
|
+
scheduleServiceLinkReconcile(3e3);
|
|
24723
25042
|
}).catch((err) => logger.error(`[serve] mount restore failed: ${err?.message || err}`));
|
|
24724
25043
|
const daemonOwnerEmail = parseJwtEmail(process.env.HYPHA_TOKEN || "") || null;
|
|
24725
25044
|
serveManager$1.setSessionResolver((sessionId) => {
|
|
@@ -24803,7 +25122,7 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
|
|
|
24803
25122
|
}
|
|
24804
25123
|
if (persistedSessions.length > 0) {
|
|
24805
25124
|
try {
|
|
24806
|
-
const { awaitClaudeVersionReady } = await import('./pinnedClaudeCode-
|
|
25125
|
+
const { awaitClaudeVersionReady } = await import('./pinnedClaudeCode-C43KnZ-Q.mjs');
|
|
24807
25126
|
await awaitClaudeVersionReady();
|
|
24808
25127
|
} catch {
|
|
24809
25128
|
}
|
|
@@ -25069,7 +25388,7 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
|
|
|
25069
25388
|
const PING_TIMEOUT_MS = 15e3;
|
|
25070
25389
|
const POST_RECONNECT_GRACE_MS = 2e4;
|
|
25071
25390
|
const RECONNECT_JITTER_MS = 2500;
|
|
25072
|
-
const { WorkflowScheduler } = await import('./scheduler-
|
|
25391
|
+
const { WorkflowScheduler } = await import('./scheduler-gMWmsAgp.mjs');
|
|
25073
25392
|
const workflowProjectRoots = () => {
|
|
25074
25393
|
const dirs = /* @__PURE__ */ new Set();
|
|
25075
25394
|
for (const s of pidToTrackedSession.values()) {
|
|
@@ -25108,6 +25427,9 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
|
|
|
25108
25427
|
};
|
|
25109
25428
|
runOAuthAccountRefresh();
|
|
25110
25429
|
const backendAccountRefreshInterval = setInterval(runOAuthAccountRefresh, 5 * 6e4);
|
|
25430
|
+
const serviceLinkSweepInterval = setInterval(() => {
|
|
25431
|
+
void reconcileAllServiceLinks();
|
|
25432
|
+
}, 6e4);
|
|
25111
25433
|
let heartbeatRunning = false;
|
|
25112
25434
|
let heartbeatCycle = 0;
|
|
25113
25435
|
const heartbeatInterval = setInterval(async () => {
|
|
@@ -25360,6 +25682,8 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
|
|
|
25360
25682
|
clearInterval(heartbeatInterval);
|
|
25361
25683
|
clearInterval(workflowSchedulerInterval);
|
|
25362
25684
|
clearInterval(backendAccountRefreshInterval);
|
|
25685
|
+
clearInterval(serviceLinkSweepInterval);
|
|
25686
|
+
if (serviceLinkReconcileTimer) clearTimeout(serviceLinkReconcileTimer);
|
|
25363
25687
|
if (proxyTokenRefreshInterval) clearInterval(proxyTokenRefreshInterval);
|
|
25364
25688
|
if (oauthRefreshInterval) clearInterval(oauthRefreshInterval);
|
|
25365
25689
|
if (unhandledRejectionResetTimer) clearTimeout(unhandledRejectionResetTimer);
|
|
@@ -25704,4 +26028,4 @@ var run = /*#__PURE__*/Object.freeze({
|
|
|
25704
26028
|
writeStopMarker: writeStopMarker
|
|
25705
26029
|
});
|
|
25706
26030
|
|
|
25707
|
-
export {
|
|
26031
|
+
export { SKILLS_DIR as $, validateCronExpr as A, validateWorkflowName as B, saveWorkflow as C, rawWorkflow as D, listWorkflows as E, isWorkflowEnabled as F, workflowSchedules as G, inZone as H, cronMatches as I, summarize as J, workflowSteps as K, describeNextFire as L, parseJwtEmail as M, computeCollectionConfigUpdate as N, SYSTEM_COLLECTION_CONFIG as O, loadMachineContext as P, buildMachineInstructions as Q, READ_ONLY_TOOLS as R, SharingNotificationSync as S, machineToolsForRole as T, buildMachineTools as U, parseFrontmatter as V, getSkillsServer as W, getSkillsWorkspaceName as X, getSkillsCollectionName as Y, fetchWithTimeout as Z, searchSkills as _, createSessionStore as a, getSkillInfo as a0, downloadSkillFile as a1, listSkillFiles as a2, resolveModel as a3, formatHandle as a4, normalizeAllowedUser as a5, loadSecurityContextConfig as a6, resolveSecurityContext as a7, buildSecurityContextFromFlags as a8, mergeSecurityContexts as a9, GeminiTransport$1 as aA, KimiTransport$1 as aB, kimiProvider as aC, kimiSetup as aD, api as aE, supervisorLock as aF, run as aG, buildSessionShareUrl as aa, computeOutboundHop as ab, registerAwaitingReply as ac, buildMachineShareUrl as ad, parseHandle as ae, handleMatchesMetadata as af, PINNED_CODEX_VERSION as ag, clearStopMarker as ah, stopMarkerExists as ai, withFileLock as aj, describeMisconfiguration as ak, buildMachineDeps as al, applyClaudeProxyEnv as am, composeSessionId as an, generateFriendlyName as ao, generateHookSettings as ap, instanceConfig as aq, frpc as ar, staticFileServer as as, claudeAuth as at, codexProvider as au, projectInfo as av, DefaultTransport$1 as aw, acpBackend as ax, acpAgentConfig as ay, codexAppServerBackend as az, stopDaemon as b, connectToHypha as c, daemonStatus as d, shortId as e, resolveProjectRoot as f, getHyphaServerUrl$1 as g, getIssue as h, checkVerifyCommand as i, resumeIssue as j, addComment as k, addIssue as l, listIssues as m, isPendingIssue as n, searchIssues as o, pauseIssue as p, isVisibleTo as q, registerMachineService as r, startDaemon as s, getRun as t, updateIssue as u, listRuns as v, getWorkflow as w, runWorkflow as x, setWorkflowEnabled as y, removeWorkflow as z };
|