@wrongstack/core 0.300.0 → 0.302.0
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/chronicle/index.d.ts +2 -0
- package/dist/chronicle/index.js +297 -10
- package/dist/chronicle/project-server.js +253 -15
- package/dist/chronicle/sqlite-compaction.d.ts +20 -0
- package/dist/chronicle/sqlite-journal.d.ts +57 -0
- package/dist/coordination/agents/capability-manifest.d.ts +7 -0
- package/dist/coordination/agents/index.d.ts +3 -2
- package/dist/coordination/agents/index.js +818 -570
- package/dist/coordination/agents/project-agent-identity.d.ts +6 -6
- package/dist/coordination/agents/role-skills.d.ts +1 -1
- package/dist/coordination/agents/types.d.ts +6 -0
- package/dist/coordination/director.d.ts +2 -2
- package/dist/coordination/index.js +6787 -6447
- package/dist/coordination/mail-tools.d.ts +3 -3
- package/dist/coordination/mailbox-project-server.js +3 -4
- package/dist/coordination/mailbox-types.d.ts +6 -0
- package/dist/core/agent-response.d.ts +5 -1
- package/dist/core/agent-tools.d.ts +3 -0
- package/dist/core/context.d.ts +20 -0
- package/dist/core/index.d.ts +8 -7
- package/dist/core/index.js +893 -284
- package/dist/core/instruction-template.d.ts +6 -3
- package/dist/core/next-steps-slot.d.ts +88 -0
- package/dist/core/system-prompt-builder.d.ts +5 -3
- package/dist/core/system-prompt-memory-skills.d.ts +1 -0
- package/dist/core/system-prompt-skill-bodies.d.ts +3 -3
- package/dist/defaults/index.js +9797 -8898
- package/dist/design/index.js +11 -3
- package/dist/execution/auto-compaction-middleware.d.ts +17 -0
- package/dist/execution/autonomy-brain.d.ts +8 -2
- package/dist/execution/brain-runtime.d.ts +3 -1
- package/dist/execution/compaction-core.d.ts +41 -2
- package/dist/execution/council-brain.d.ts +37 -2
- package/dist/execution/council-orchestrator.d.ts +2 -2
- package/dist/execution/index.d.ts +11 -10
- package/dist/execution/index.js +5179 -4078
- package/dist/execution/tool-executor.d.ts +4 -1
- package/dist/execution/topic-shift-advisor.d.ts +53 -0
- package/dist/extension/index.js +8 -2
- package/dist/extension/registry.d.ts +8 -1
- package/dist/goal/index.js +11 -3
- package/dist/hooks/index.js +42 -9
- package/dist/hooks/runner.d.ts +12 -1
- package/dist/hq/index.js +41 -17
- package/dist/hq/publisher.d.ts +21 -3
- package/dist/index.d.ts +21 -20
- package/dist/index.js +10901 -8067
- package/dist/infrastructure/index.js +108 -21
- package/dist/kernel/events/session-events.d.ts +13 -0
- package/dist/kernel/events/tool-events.d.ts +3 -3
- package/dist/models/index.d.ts +1 -0
- package/dist/models/index.js +17 -0
- package/dist/models/provider-credentials.d.ts +54 -0
- package/dist/plugin/index.d.ts +1 -0
- package/dist/plugin/index.js +2024 -502
- package/dist/plugins/auto-review-plugin.d.ts +3 -0
- package/dist/plugins/cloud-config-sync-plugin.d.ts +22 -0
- package/dist/plugins/review-claim-registry.d.ts +23 -8
- package/dist/plugins/review-types.d.ts +2 -0
- package/dist/registry/index.js +109 -74
- package/dist/registry/tool-registry.d.ts +15 -0
- package/dist/security/capabilities.d.ts +2 -0
- package/dist/security/index.d.ts +1 -1
- package/dist/security/index.js +9 -2
- package/dist/security/readonly-permission-policy.d.ts +20 -0
- package/dist/session-registry-atomic-file.d.ts +32 -5
- package/dist/session-registry-types.d.ts +17 -0
- package/dist/session-registry.d.ts +1 -1
- package/dist/skills/frontmatter.d.ts +6 -0
- package/dist/skills/index.js +22 -5
- package/dist/storage/cloud-config-sync/sanitize.d.ts +54 -0
- package/dist/storage/cloud-config-sync.d.ts +87 -0
- package/dist/storage/index.d.ts +2 -1
- package/dist/storage/index.js +854 -66
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.js +511 -234
- package/dist/tools/one-shot-llm-tool.d.ts +1 -0
- package/dist/tools/plugin-manager.d.ts +27 -0
- package/dist/types/config/mcp-features.d.ts +18 -11
- package/dist/types/config/root.d.ts +8 -1
- package/dist/types/config/runtime.d.ts +20 -6
- package/dist/types/config/skills-fleet-brain.d.ts +12 -4
- package/dist/types/config/tools.d.ts +16 -0
- package/dist/types/context-window.d.ts +1 -0
- package/dist/types/hooks.d.ts +14 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.js +1 -0
- package/dist/types/multi-agent.d.ts +2 -0
- package/dist/types/one-shot-llm.d.ts +16 -0
- package/dist/types/provider.d.ts +16 -0
- package/dist/types/runtime-capability-manifest.d.ts +168 -0
- package/dist/types/skill.d.ts +5 -0
- package/dist/types/system-prompt.d.ts +3 -1
- package/dist/types/tool-executor.d.ts +8 -1
- package/dist/utils/context-breakdown.d.ts +8 -2
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +141 -31
- package/dist/utils/regex-guard.d.ts +16 -2
- package/dist/utils/sage-output-block.d.ts +7 -10
- package/dist/utils/wstack-paths.d.ts +11 -3
- package/instructions/agents/browser.md +1 -4
- package/instructions/agents/e2e.md +17 -15
- package/instructions/agents/ios.md +3 -3
- package/instructions/agents/search.md +1 -1
- package/instructions/autonomy/goal-preamble.md +4 -4
- package/instructions/coordination/director-preamble.md +2 -3
- package/instructions/coordination/subagent-baseline.md +3 -1
- package/instructions/leader-after-task.md +12 -0
- package/instructions/llm/chimera-review.md +1 -1
- package/instructions/modes/audit-lite.md +1 -1
- package/instructions/sections/tool/common-patterns.md +18 -2
- package/instructions/sections/tool/mailbox-compact.md +1 -1
- package/instructions/sections/tool/mailbox-full.md +1 -1
- package/instructions/system-lite.md +10 -0
- package/instructions/system-pro.md +23 -14
- package/instructions/system.md +22 -13
- package/package.json +3 -3
- package/skills/api-design/SKILL.md +3 -0
- package/skills/audit-log/SKILL.md +2 -0
- package/skills/auto-review/SKILL.md +6 -1
- package/skills/bug-hunter/SKILL.md +4 -1
- package/skills/chimera/SKILL.md +3 -0
- package/skills/data-governance/SKILL.md +3 -0
- package/skills/design-system/SKILL.md +5 -2
- package/skills/docker-deploy/SKILL.md +2 -0
- package/skills/git-flow/SKILL.md +2 -0
- package/skills/mailbox-bridge/SKILL.md +3 -0
- package/skills/mnemosyne/SKILL.md +2 -0
- package/skills/multi-agent/SKILL.md +4 -1
- package/skills/node-modern/SKILL.md +4 -1
- package/skills/observability/SKILL.md +3 -0
- package/skills/output-standards/SKILL.md +2 -0
- package/skills/plugin-author/SKILL.md +4 -1
- package/skills/prompt-engineering/SKILL.md +3 -1
- package/skills/react-modern/SKILL.md +6 -3
- package/skills/refactor-planner/SKILL.md +2 -0
- package/skills/research-web/SKILL.md +3 -0
- package/skills/sdd/SKILL.md +3 -1
- package/skills/security-scanner/SKILL.md +3 -0
- package/skills/skill-creator/SKILL.md +2 -0
- package/skills/tech-stack/SKILL.md +3 -0
- package/skills/testing/SKILL.md +4 -1
- package/skills/typescript-strict/SKILL.md +4 -1
- package/skills/wrongstack-kanban/SKILL.md +6 -3
- package/skills/wrongstack-mailbox/SKILL.md +4 -1
- package/skills/wrongstack-mailbox-mcp/SKILL.md +10 -8
|
@@ -35,27 +35,81 @@ var init_pid = __esm({
|
|
|
35
35
|
// src/session-registry-atomic-file.ts
|
|
36
36
|
import { randomUUID } from "node:crypto";
|
|
37
37
|
import * as fs6 from "node:fs/promises";
|
|
38
|
+
import { hostname } from "node:os";
|
|
38
39
|
import * as path8 from "node:path";
|
|
40
|
+
function lockOwnerStamp() {
|
|
41
|
+
return `${HOST_NAME}:${process.pid}`;
|
|
42
|
+
}
|
|
43
|
+
async function maybeUnlinkOwnedLock(lockPath) {
|
|
44
|
+
const owner = await fs6.readFile(lockPath, "utf8").catch(() => null);
|
|
45
|
+
if (owner === null || owner.trim() !== lockOwnerStamp()) return;
|
|
46
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
47
|
+
try {
|
|
48
|
+
await fs6.unlink(lockPath);
|
|
49
|
+
return;
|
|
50
|
+
} catch {
|
|
51
|
+
if (attempt < 2) await new Promise((resolve5) => setTimeout(resolve5, 5));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
39
55
|
async function breakStaleLock(lockPath) {
|
|
40
56
|
try {
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return
|
|
57
|
+
const content = await fs6.readFile(lockPath, "utf8").catch(() => "");
|
|
58
|
+
const trimmed = content.trim();
|
|
59
|
+
const colonIdx = trimmed.indexOf(":");
|
|
60
|
+
if (colonIdx === -1) {
|
|
61
|
+
const barePid = Number.parseInt(trimmed, 10);
|
|
62
|
+
if (Number.isInteger(barePid) && barePid > 0 && !isPidAlive(barePid)) {
|
|
63
|
+
return await breakStaleLockVerified(lockPath, async () => {
|
|
64
|
+
const reread = await fs6.readFile(lockPath, "utf8").catch(() => "");
|
|
65
|
+
return reread.trim() === trimmed;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return await breakStaleLockVerified(lockPath, async () => {
|
|
69
|
+
const st = await fs6.stat(lockPath);
|
|
70
|
+
return Date.now() - st.mtimeMs > STALE_LOCK_MS;
|
|
71
|
+
});
|
|
53
72
|
}
|
|
54
|
-
|
|
73
|
+
const ownerHost = trimmed.slice(0, colonIdx);
|
|
74
|
+
const ownerPid = Number.parseInt(trimmed.slice(colonIdx + 1), 10);
|
|
75
|
+
if (ownerHost === HOST_NAME && Number.isInteger(ownerPid) && ownerPid > 0) {
|
|
76
|
+
if (isPidAlive(ownerPid)) {
|
|
77
|
+
const stat5 = await fs6.stat(lockPath);
|
|
78
|
+
if (Date.now() - stat5.mtimeMs > SAME_HOST_STALE_MS) {
|
|
79
|
+
return await breakStaleLockVerified(lockPath, async () => {
|
|
80
|
+
const st = await fs6.stat(lockPath);
|
|
81
|
+
return Date.now() - st.mtimeMs > SAME_HOST_STALE_MS;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
return await breakStaleLockVerified(lockPath, async () => {
|
|
87
|
+
const reread = await fs6.readFile(lockPath, "utf8").catch(() => "");
|
|
88
|
+
return reread.trim() === trimmed;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return await breakStaleLockVerified(lockPath, async () => {
|
|
92
|
+
const st = await fs6.stat(lockPath);
|
|
93
|
+
return Date.now() - st.mtimeMs > STALE_LOCK_MS;
|
|
94
|
+
});
|
|
55
95
|
} catch {
|
|
56
96
|
return true;
|
|
57
97
|
}
|
|
58
98
|
}
|
|
99
|
+
async function breakStaleLockVerified(lockPath, verify) {
|
|
100
|
+
if (!await verify()) return false;
|
|
101
|
+
return await breakLockAtomically(lockPath) === true;
|
|
102
|
+
}
|
|
103
|
+
async function breakLockAtomically(lockPath) {
|
|
104
|
+
const tombstone = `${lockPath}.stale-${randomUUID()}.tmp`;
|
|
105
|
+
try {
|
|
106
|
+
await fs6.rename(lockPath, tombstone);
|
|
107
|
+
} catch {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
void fs6.unlink(tombstone).catch(() => void 0);
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
59
113
|
async function writeAtomicFile(filePath, registry) {
|
|
60
114
|
const tmp = path8.join(
|
|
61
115
|
path8.dirname(filePath),
|
|
@@ -120,14 +174,16 @@ async function pruneStaleTempFiles(filePath) {
|
|
|
120
174
|
} catch {
|
|
121
175
|
}
|
|
122
176
|
}
|
|
123
|
-
var STALE_LOCK_MS, STALE_TMP_MS, MAX_STALE_TMP_FILES;
|
|
177
|
+
var STALE_LOCK_MS, SAME_HOST_STALE_MS, STALE_TMP_MS, MAX_STALE_TMP_FILES, HOST_NAME;
|
|
124
178
|
var init_session_registry_atomic_file = __esm({
|
|
125
179
|
"src/session-registry-atomic-file.ts"() {
|
|
126
180
|
"use strict";
|
|
127
181
|
init_pid();
|
|
128
182
|
STALE_LOCK_MS = 1e4;
|
|
183
|
+
SAME_HOST_STALE_MS = 2 * STALE_LOCK_MS;
|
|
129
184
|
STALE_TMP_MS = 6e4;
|
|
130
185
|
MAX_STALE_TMP_FILES = 20;
|
|
186
|
+
HOST_NAME = hostname();
|
|
131
187
|
}
|
|
132
188
|
});
|
|
133
189
|
|
|
@@ -552,16 +608,33 @@ var init_session_registry = __esm({
|
|
|
552
608
|
continue;
|
|
553
609
|
}
|
|
554
610
|
}
|
|
611
|
+
let stampFailed = false;
|
|
555
612
|
try {
|
|
556
|
-
|
|
613
|
+
let stamped = false;
|
|
614
|
+
for (let stampAttempt = 0; stampAttempt < 3 && !stamped; stampAttempt++) {
|
|
615
|
+
try {
|
|
616
|
+
await lockHandle.writeFile(lockOwnerStamp());
|
|
617
|
+
stamped = true;
|
|
618
|
+
} catch {
|
|
619
|
+
if (stampAttempt < 2) await new Promise((resolve5) => setTimeout(resolve5, 5));
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
if (!stamped) {
|
|
623
|
+
stampFailed = true;
|
|
624
|
+
throw new Error("failed to stamp session-registry lock owner");
|
|
625
|
+
}
|
|
557
626
|
const raw = await fs7.readFile(this.filePath, "utf8").catch(() => "{}");
|
|
558
627
|
const registry = parseRegistry(raw);
|
|
559
628
|
fn(registry);
|
|
560
629
|
await this.writeAtomicWithRetry(registry);
|
|
561
630
|
return;
|
|
562
631
|
} finally {
|
|
563
|
-
await lockHandle.close();
|
|
564
|
-
|
|
632
|
+
await lockHandle.close().catch(() => void 0);
|
|
633
|
+
if (stampFailed) {
|
|
634
|
+
await fs7.unlink(lockPath).catch(() => void 0);
|
|
635
|
+
} else {
|
|
636
|
+
await maybeUnlinkOwnedLock(lockPath);
|
|
637
|
+
}
|
|
565
638
|
}
|
|
566
639
|
} catch (err) {
|
|
567
640
|
if (err instanceof SessionOwnershipConflictError) throw err;
|
|
@@ -2911,6 +2984,9 @@ function canonicalProjectRoot(absRoot) {
|
|
|
2911
2984
|
const commonDirFile = path5.join(gitDir, "commondir");
|
|
2912
2985
|
if (!fs4.statSync(commonDirFile).isFile()) return checkoutRoot;
|
|
2913
2986
|
const commonDir = path5.resolve(gitDir, fs4.readFileSync(commonDirFile, "utf8").trim());
|
|
2987
|
+
const worktreesDir = path5.dirname(gitDir);
|
|
2988
|
+
if (path5.basename(worktreesDir).toLowerCase() !== "worktrees") return checkoutRoot;
|
|
2989
|
+
if (path5.resolve(worktreesDir, "..") !== commonDir) return checkoutRoot;
|
|
2914
2990
|
if (path5.basename(commonDir).toLowerCase() !== ".git") return checkoutRoot;
|
|
2915
2991
|
return path5.dirname(commonDir);
|
|
2916
2992
|
} catch {
|
|
@@ -2933,7 +3009,7 @@ function safeProfileName(name) {
|
|
|
2933
3009
|
const safe = (name ?? "").replace(/[/\\:]/g, "_").replace(/\.\./g, "_").trim();
|
|
2934
3010
|
return safe || "default";
|
|
2935
3011
|
}
|
|
2936
|
-
function
|
|
3012
|
+
function bootstrapProfileName(globalRoot) {
|
|
2937
3013
|
try {
|
|
2938
3014
|
const parsed = JSON.parse(fs4.readFileSync(path5.join(globalRoot, "config.json"), "utf8"));
|
|
2939
3015
|
return safeProfileName(
|
|
@@ -2951,7 +3027,7 @@ function wstackGlobalRoot() {
|
|
|
2951
3027
|
function resolveWstackPaths(opts) {
|
|
2952
3028
|
const globalRoot = opts.globalRoot ?? (opts.userHome ? path5.join(opts.userHome, ".wrongstack") : wstackGlobalRoot());
|
|
2953
3029
|
const homeDir = opts.userHome ?? os2.homedir();
|
|
2954
|
-
const profileName = safeProfileName(opts.profileName ??
|
|
3030
|
+
const profileName = safeProfileName(opts.profileName ?? bootstrapProfileName(globalRoot));
|
|
2955
3031
|
const profileDir = path5.join(globalRoot, "profiles", profileName);
|
|
2956
3032
|
const hash = projectHash(opts.projectRoot);
|
|
2957
3033
|
const slug = projectSlug(opts.projectRoot);
|
|
@@ -3021,7 +3097,12 @@ function resolveWstackPaths(opts) {
|
|
|
3021
3097
|
projectRequirementIntakes: path5.join(projectDir, "requirement-intakes"),
|
|
3022
3098
|
syncConfig: path5.join(profileDir, "sync.json"),
|
|
3023
3099
|
configHistoryDir: path5.join(globalRoot, "config-history"),
|
|
3024
|
-
projectStatus: (
|
|
3100
|
+
projectStatus: (statusProjectSlug) => {
|
|
3101
|
+
if (!/^[a-z0-9](?:[a-z0-9-]{0,39})-[a-f0-9]{6}$/.test(statusProjectSlug)) {
|
|
3102
|
+
throw new Error(`Invalid project slug: ${statusProjectSlug}`);
|
|
3103
|
+
}
|
|
3104
|
+
return path5.join(globalRoot, "projects", statusProjectSlug, "status.json");
|
|
3105
|
+
}
|
|
3025
3106
|
};
|
|
3026
3107
|
}
|
|
3027
3108
|
|
|
@@ -3035,6 +3116,7 @@ function isBootstrapOnly(config) {
|
|
|
3035
3116
|
function normalizeTokenSavingTier(val) {
|
|
3036
3117
|
if (val === void 0) return "off";
|
|
3037
3118
|
if (typeof val === "boolean") return val ? "medium" : "off";
|
|
3119
|
+
if (val === "auto") return "medium";
|
|
3038
3120
|
const validTiers = /* @__PURE__ */ new Set([
|
|
3039
3121
|
"off",
|
|
3040
3122
|
"minimal",
|
|
@@ -3176,7 +3258,7 @@ var CONFIG_BEHAVIOR_DEFAULTS = {
|
|
|
3176
3258
|
enabled: false
|
|
3177
3259
|
}
|
|
3178
3260
|
},
|
|
3179
|
-
skills: { readClaudeSkills: true },
|
|
3261
|
+
skills: { readClaudeSkills: true, mode: "progressive" },
|
|
3180
3262
|
mcpServers: {},
|
|
3181
3263
|
fallbackAuto: true,
|
|
3182
3264
|
maxConcurrent: 4,
|
|
@@ -3378,6 +3460,10 @@ var KNOWN_DENIED_IN_PROJECT = [
|
|
|
3378
3460
|
reason: "Controls which plugin boot states the LLM may mutate; user-owned trust policy."
|
|
3379
3461
|
},
|
|
3380
3462
|
{ key: "sync", reason: "Carries githubToken credential and target repo." },
|
|
3463
|
+
{
|
|
3464
|
+
key: "cloudSync",
|
|
3465
|
+
reason: "Carries the my.wrongstack.com machine token credential and endpoint URL."
|
|
3466
|
+
},
|
|
3381
3467
|
{ key: "yolo", reason: "Disables all permission confirmation prompts." },
|
|
3382
3468
|
{ key: "extensions", reason: "Per-plugin config can carry command/credential fields." },
|
|
3383
3469
|
{ key: "hq", reason: "Carries HQ client token credential and endpoint URL." },
|
|
@@ -3440,6 +3526,7 @@ var KNOWN_CONFIG_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
|
|
|
3440
3526
|
"modelRuntime",
|
|
3441
3527
|
"hq",
|
|
3442
3528
|
"sync",
|
|
3529
|
+
"cloudSync",
|
|
3443
3530
|
"extensions",
|
|
3444
3531
|
"acp",
|
|
3445
3532
|
"fleet",
|
|
@@ -11,6 +11,13 @@ export interface SessionEventMap {
|
|
|
11
11
|
id: string;
|
|
12
12
|
sessionId?: string | undefined;
|
|
13
13
|
usage: Usage;
|
|
14
|
+
/**
|
|
15
|
+
* Register asynchronous session-end producer work during the synchronous
|
|
16
|
+
* `session.ended` callback. Cleanup waits for every registered promise to
|
|
17
|
+
* settle (fulfilled or rejected) before draining review work and closing.
|
|
18
|
+
* Calls made after the callback returns are outside the join contract.
|
|
19
|
+
*/
|
|
20
|
+
waitUntil?: ((work: Promise<void>) => void) | undefined;
|
|
14
21
|
};
|
|
15
22
|
'session.damaged': {
|
|
16
23
|
sessionId: string;
|
|
@@ -72,6 +79,12 @@ export interface SessionEventMap {
|
|
|
72
79
|
providerId: string;
|
|
73
80
|
modelId: string;
|
|
74
81
|
maxContext: number;
|
|
82
|
+
/** Previous positive limit when this event represents a live change. */
|
|
83
|
+
previousMaxContext?: number | undefined;
|
|
84
|
+
/** Whether the value came from static resolution or a live provider probe. */
|
|
85
|
+
source?: 'configured' | 'provider' | 'provider_overflow' | undefined;
|
|
86
|
+
/** True when the positive limit decreased and UI should surface a warning. */
|
|
87
|
+
decreased?: boolean | undefined;
|
|
75
88
|
};
|
|
76
89
|
'context.repaired': {
|
|
77
90
|
sessionId?: string | undefined;
|
|
@@ -202,9 +202,9 @@ export interface ToolEventMap {
|
|
|
202
202
|
input?: unknown | undefined;
|
|
203
203
|
output?: string | undefined;
|
|
204
204
|
/**
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
205
|
+
* Legacy inline `--- SAGE: … (Memory Injector) ---` content split off
|
|
206
|
+
* `output` before the preview cap. Current retrievals travel through
|
|
207
|
+
* `memory.injector_run` and provider memory-evidence blocks instead.
|
|
208
208
|
*
|
|
209
209
|
* Surfaces render it as a memory card, never as tool output: sharing the
|
|
210
210
|
* `output` budget used to cut a memory line mid-fence on short tool
|
package/dist/models/index.d.ts
CHANGED
|
@@ -8,4 +8,5 @@ export { ALIBABA_TOKEN_PLAN_MODELS, alibabaTokenPlanModelMeta, type AlibabaToken
|
|
|
8
8
|
export { MODELS_DEV_MODALITY_VALUES, modelsDevCostSchema, modelsDevLimitSchema, modelsDevModalitiesSchema, modelsDevModelSchema, modelsDevPayloadSchema, modelsDevProviderSchema, type ModelsDevModelParsed, type ModelsDevPayloadParsed, type ModelsDevProviderParsed, type ModelsDevSchemaSyncProof, } from './models-dev-schema.js';
|
|
9
9
|
export { MODEL_PROFILES, TASK_TO_ROLE, inferTaskType, findModelProfile, scoreModelForTask, type ModelProfile, type TaskType, } from './model-intelligence.js';
|
|
10
10
|
export { ModelRouter, type RouterConfig, type ModelPick, type RouterCosts, type ModelIntelligenceEntry, } from './model-router.js';
|
|
11
|
+
export { hasProviderCredential, hasProviderKeyInConfig, hasProviderKeyInEnv, type ProviderCredentialConfig, type ProviderCredentialSubject, } from './provider-credentials.js';
|
|
11
12
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/models/index.js
CHANGED
|
@@ -2391,6 +2391,20 @@ var ModelRouter = class {
|
|
|
2391
2391
|
return matrix;
|
|
2392
2392
|
}
|
|
2393
2393
|
};
|
|
2394
|
+
|
|
2395
|
+
// src/models/provider-credentials.ts
|
|
2396
|
+
function hasProviderKeyInEnv(provider, env = process.env) {
|
|
2397
|
+
return (provider.envVars ?? []).some((name) => !!env[name]);
|
|
2398
|
+
}
|
|
2399
|
+
function hasProviderKeyInConfig(providerId, config) {
|
|
2400
|
+
const entry = config?.providers?.[providerId];
|
|
2401
|
+
if (!entry) return false;
|
|
2402
|
+
if (typeof entry.apiKey === "string" && entry.apiKey.length > 0) return true;
|
|
2403
|
+
return Array.isArray(entry.apiKeys) && entry.apiKeys.some((k) => !!k?.apiKey);
|
|
2404
|
+
}
|
|
2405
|
+
function hasProviderCredential(provider, config, env = process.env) {
|
|
2406
|
+
return hasProviderKeyInEnv(provider, env) || hasProviderKeyInConfig(provider.id, config);
|
|
2407
|
+
}
|
|
2394
2408
|
export {
|
|
2395
2409
|
ALIBABA_TOKEN_PLAN_MODELS,
|
|
2396
2410
|
CODEX_MODELS,
|
|
@@ -2406,6 +2420,9 @@ export {
|
|
|
2406
2420
|
codexModelMeta,
|
|
2407
2421
|
describeCatalogModel,
|
|
2408
2422
|
findModelProfile,
|
|
2423
|
+
hasProviderCredential,
|
|
2424
|
+
hasProviderKeyInConfig,
|
|
2425
|
+
hasProviderKeyInEnv,
|
|
2409
2426
|
inferTaskType,
|
|
2410
2427
|
loadProjectModes,
|
|
2411
2428
|
loadUserModes,
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Does this provider have a usable credential?" — one answer.
|
|
3
|
+
*
|
|
4
|
+
* There were three, and they disagreed:
|
|
5
|
+
*
|
|
6
|
+
* - `cli/src/provider-helpers.ts` — env var OR `config.providers[id].apiKey`
|
|
7
|
+
* OR any entry in `apiKeys[]`. The complete rule.
|
|
8
|
+
* - `cli/src/slash-commands/modelcaps.ts` — config only. `/modelcaps` printed
|
|
9
|
+
* a hollow `○` next to every provider keyed purely through
|
|
10
|
+
* `ANTHROPIC_API_KEY`, which is the most common way to key one.
|
|
11
|
+
* - `webui-server/src/server/provider-handlers.ts` — `savedIds.has(id) || env`.
|
|
12
|
+
* `savedIds` means "appears in the saved config at all", so a provider saved
|
|
13
|
+
* with a `baseUrl` and no key reported `hasApiKey: true` and the WebUI
|
|
14
|
+
* offered it as ready to use.
|
|
15
|
+
*
|
|
16
|
+
* The rule itself is small; that it lives in three places is the defect. This
|
|
17
|
+
* module is in core because the CLI and the WebUI server both need it and
|
|
18
|
+
* neither may import the other.
|
|
19
|
+
*/
|
|
20
|
+
/** The provider fields the check reads. Both call sites can supply these. */
|
|
21
|
+
export interface ProviderCredentialSubject {
|
|
22
|
+
readonly id: string;
|
|
23
|
+
/** Environment variables that carry this provider's key, if any. */
|
|
24
|
+
readonly envVars?: readonly string[] | undefined;
|
|
25
|
+
}
|
|
26
|
+
/** The saved-config shape the check reads. */
|
|
27
|
+
export interface ProviderCredentialConfig {
|
|
28
|
+
readonly providers?: Readonly<Record<string, {
|
|
29
|
+
readonly apiKey?: string | undefined;
|
|
30
|
+
readonly apiKeys?: readonly ({
|
|
31
|
+
readonly apiKey?: string | undefined;
|
|
32
|
+
} | undefined)[] | undefined;
|
|
33
|
+
} | undefined>> | undefined;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Is a key present in the environment for this provider?
|
|
37
|
+
*
|
|
38
|
+
* Split out because the WebUI reports the two sources separately in places, and
|
|
39
|
+
* because a caller with no config still has a meaningful answer.
|
|
40
|
+
*/
|
|
41
|
+
export declare function hasProviderKeyInEnv(provider: ProviderCredentialSubject, env?: Readonly<Record<string, string | undefined>>): boolean;
|
|
42
|
+
/** Is a non-empty key stored in the saved config for this provider? */
|
|
43
|
+
export declare function hasProviderKeyInConfig(providerId: string, config: ProviderCredentialConfig | undefined): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Can the user call this provider right now?
|
|
46
|
+
*
|
|
47
|
+
* Deliberately does NOT cover keyless local gateways (loopback servers that
|
|
48
|
+
* declare no env vars). They need no credential at all, which is a different
|
|
49
|
+
* question with a different answer — see `isKeylessLocalProvider`. Folding the
|
|
50
|
+
* two together here would make "has a key" mean "is usable" and quietly lose
|
|
51
|
+
* the distinction the picker needs.
|
|
52
|
+
*/
|
|
53
|
+
export declare function hasProviderCredential(provider: ProviderCredentialSubject, config: ProviderCredentialConfig | undefined, env?: Readonly<Record<string, string | undefined>>): boolean;
|
|
54
|
+
//# sourceMappingURL=provider-credentials.d.ts.map
|
package/dist/plugin/index.d.ts
CHANGED
|
@@ -12,4 +12,5 @@ export { persistReviewReport, type ReportIntegrationResult, } from '../plugins/r
|
|
|
12
12
|
export { maybeCompactReviewStores, type ReviewStoreMaintenanceResult, } from '../plugins/review-store-maintenance.js';
|
|
13
13
|
export { createSkillsPlugin } from '../plugins/skills-plugin.js';
|
|
14
14
|
export { createSyncPlugin } from '../plugins/sync-plugin.js';
|
|
15
|
+
export { createCloudConfigSyncPlugin } from '../plugins/cloud-config-sync-plugin.js';
|
|
15
16
|
//# sourceMappingURL=index.d.ts.map
|