@wrongstack/core 0.306.3 → 0.306.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/coordination/index.js +136 -40
- package/dist/coordination/mail-tools.d.ts +1 -1
- package/dist/core/conversation-state.d.ts +1 -2
- package/dist/core/fallback-model.d.ts +19 -1
- package/dist/core/fallback-profile-manager.d.ts +21 -3
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +152 -46
- package/dist/defaults/index.js +295 -91
- package/dist/execution/auto-compaction-middleware.d.ts +64 -0
- package/dist/execution/compaction-core.d.ts +4 -0
- package/dist/execution/index.d.ts +1 -1
- package/dist/execution/index.js +230 -89
- package/dist/execution/retry-policy.d.ts +27 -0
- package/dist/hq/index.js +50 -15
- package/dist/index.d.ts +1 -1
- package/dist/index.js +588 -134
- package/dist/infrastructure/index.js +21 -0
- package/dist/plugin/index.js +195 -19
- package/dist/security/index.js +50 -15
- package/dist/session-catalog/index.js +50 -15
- package/dist/session-catalog/project-server.js +50 -15
- package/dist/storage/cloud-config-sync/sanitize.d.ts +18 -0
- package/dist/storage/cloud-config-sync.d.ts +1 -1
- package/dist/storage/index.js +276 -23
- package/dist/storage/provider-config-watcher.d.ts +9 -0
- package/dist/storage/session-store/strict-empty-check.d.ts +7 -0
- package/dist/storage/session-store.d.ts +1 -0
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.js +83 -22
- package/dist/types/config/root.d.ts +14 -0
- package/dist/types/session.d.ts +7 -0
- package/package.json +3 -3
|
@@ -8328,6 +8328,24 @@ import { dirname as dirname5 } from "node:path";
|
|
|
8328
8328
|
import { homedir as homedir2 } from "node:os";
|
|
8329
8329
|
|
|
8330
8330
|
// src/security/secret-scrubber.ts
|
|
8331
|
+
var JSON_CREDENTIAL_KEY_ANCHORS = [
|
|
8332
|
+
'Key"',
|
|
8333
|
+
'key"',
|
|
8334
|
+
'KEY"',
|
|
8335
|
+
'token"',
|
|
8336
|
+
'Token"',
|
|
8337
|
+
'TOKEN"',
|
|
8338
|
+
'secret"',
|
|
8339
|
+
'Secret"',
|
|
8340
|
+
'SECRET"',
|
|
8341
|
+
'password"',
|
|
8342
|
+
'Password"',
|
|
8343
|
+
'PASSWORD"',
|
|
8344
|
+
'authorization"',
|
|
8345
|
+
'Authorization"',
|
|
8346
|
+
'bearer"',
|
|
8347
|
+
'Bearer"'
|
|
8348
|
+
];
|
|
8331
8349
|
var PATTERNS = [
|
|
8332
8350
|
// Anchored at the start where possible so partial matches inside larger
|
|
8333
8351
|
// strings don't trigger false positives.
|
|
@@ -8430,6 +8448,30 @@ var PATTERNS = [
|
|
|
8430
8448
|
regex: /(^|\s)([A-Z_]{4,}(?:KEY|TOKEN|SECRET|PASSWORD|PWD))\s*[:=]\s*['"]?([A-Za-z0-9_/+=-]{20,512})['"]?(?=\s|$)/g,
|
|
8431
8449
|
anchor: ["KEY", "TOKEN", "SECRET", "PASSWORD", "PWD"]
|
|
8432
8450
|
},
|
|
8451
|
+
{
|
|
8452
|
+
type: "json_credential_key",
|
|
8453
|
+
// The JSON counterpart to `high_entropy_env`, and the pattern that the
|
|
8454
|
+
// now-deleted `JSON_KEY_ANCHORS` list was written for. Without it those
|
|
8455
|
+
// anchors only widened the cheap pre-scan — `hasCredentialAnchors` said
|
|
8456
|
+
// "this text may hold a secret", every pattern then declined to match, and
|
|
8457
|
+
// the value went out verbatim. `high_entropy_env` cannot cover these: it
|
|
8458
|
+
// requires an UPPERCASE unquoted key (`API_KEY=…`), so `{"apiKey":"…"}`
|
|
8459
|
+
// never matched.
|
|
8460
|
+
//
|
|
8461
|
+
// Tool results are routinely serialised as JSON, and a credential with no
|
|
8462
|
+
// recognisable prefix (Azure, self-hosted gateways, Anthropic/Codex OAuth)
|
|
8463
|
+
// has no other pattern that can catch it — this is the only thing standing
|
|
8464
|
+
// between such a value and the session JSONL, chronicle, HQ broadcast and
|
|
8465
|
+
// the model's own context.
|
|
8466
|
+
//
|
|
8467
|
+
// The key may carry a prefix (`"anthropicApiKey"`), but the credential word
|
|
8468
|
+
// must END the key: `"tokenCount"` and `"maxTokens"` do not match, because
|
|
8469
|
+
// the closing quote has to follow the word immediately.
|
|
8470
|
+
// Value floor of 8 chars keeps enum-ish values (`"authorization":"none"`)
|
|
8471
|
+
// out. Capture groups: 1=key + punctuation, 2=value, 3=closing quote.
|
|
8472
|
+
regex: /("[A-Za-z0-9_]*(?:apiKey|api_key|token|secret|password|authorization|bearer|private_key|access_token|refresh_token|client_secret)"\s*:\s*")([^"\\]{8,512})(")/gi,
|
|
8473
|
+
anchor: JSON_CREDENTIAL_KEY_ANCHORS
|
|
8474
|
+
},
|
|
8433
8475
|
// ── Ported from packages/plugins credential-patterns.ts (WS-034) ─────────
|
|
8434
8476
|
// The plugin runtime carried 37 patterns while this scrubber — the one that
|
|
8435
8477
|
// guards session JSONL, chronicle, HQ broadcast, WebUI events and the auth
|
|
@@ -8512,9 +8554,12 @@ var PATTERNS = [
|
|
|
8512
8554
|
anchor: "GOCSPX-"
|
|
8513
8555
|
}
|
|
8514
8556
|
];
|
|
8515
|
-
var SIMPLE_PATTERNS = PATTERNS.filter(
|
|
8557
|
+
var SIMPLE_PATTERNS = PATTERNS.filter(
|
|
8558
|
+
(p) => p.type !== "high_entropy_env" && p.type !== "json_credential_key"
|
|
8559
|
+
);
|
|
8516
8560
|
var COMBINED_REGEX = new RegExp(SIMPLE_PATTERNS.map((p) => `(${p.regex.source})`).join("|"), "g");
|
|
8517
8561
|
var HIGH_ENTROPY_REGEX = PATTERNS.find((p) => p.type === "high_entropy_env").regex;
|
|
8562
|
+
var JSON_CREDENTIAL_REGEX = PATTERNS.find((p) => p.type === "json_credential_key").regex;
|
|
8518
8563
|
var COMBINED_REPLACEMENTS = SIMPLE_PATTERNS.map((p) => `[REDACTED:${p.type}]`);
|
|
8519
8564
|
var SCRUB_CHUNK_BYTES = 64 * 1024;
|
|
8520
8565
|
var SCRUB_OVERLAP_BYTES = 1024;
|
|
@@ -8525,20 +8570,7 @@ var PATTERN_ANCHORS = [
|
|
|
8525
8570
|
)
|
|
8526
8571
|
)
|
|
8527
8572
|
];
|
|
8528
|
-
var
|
|
8529
|
-
'"apiKey"',
|
|
8530
|
-
'"api_key"',
|
|
8531
|
-
'"token"',
|
|
8532
|
-
'"secret"',
|
|
8533
|
-
'"password"',
|
|
8534
|
-
'"authorization"',
|
|
8535
|
-
'"bearer"',
|
|
8536
|
-
'"private_key"',
|
|
8537
|
-
'"access_token"',
|
|
8538
|
-
'"refresh_token"',
|
|
8539
|
-
'"client_secret"'
|
|
8540
|
-
];
|
|
8541
|
-
var ALL_ANCHORS = [...PATTERN_ANCHORS, ...JSON_KEY_ANCHORS];
|
|
8573
|
+
var ALL_ANCHORS = PATTERN_ANCHORS;
|
|
8542
8574
|
function hasCredentialAnchors(text) {
|
|
8543
8575
|
for (const anchor of ALL_ANCHORS) {
|
|
8544
8576
|
if (text.includes(anchor)) return true;
|
|
@@ -8587,6 +8619,9 @@ var DefaultSecretScrubber = class {
|
|
|
8587
8619
|
out = out.replace(HIGH_ENTROPY_REGEX, (_match, lead, key, _value) => {
|
|
8588
8620
|
return `${lead}${key}=[REDACTED:high_entropy_env]`;
|
|
8589
8621
|
});
|
|
8622
|
+
out = out.replace(JSON_CREDENTIAL_REGEX, (_match, keyPrefix, _value, closingQuote) => {
|
|
8623
|
+
return `${keyPrefix}[REDACTED:json_credential_key]${closingQuote}`;
|
|
8624
|
+
});
|
|
8590
8625
|
return out;
|
|
8591
8626
|
}
|
|
8592
8627
|
/**
|
|
@@ -17102,9 +17137,40 @@ async function readOrBuildShardManifestEntry(opts) {
|
|
|
17102
17137
|
return entry;
|
|
17103
17138
|
}
|
|
17104
17139
|
|
|
17105
|
-
// src/storage/session-store/
|
|
17140
|
+
// src/storage/session-store/strict-empty-check.ts
|
|
17106
17141
|
import { createReadStream as createReadStream4 } from "node:fs";
|
|
17107
17142
|
import { createInterface as createInterface4 } from "node:readline";
|
|
17143
|
+
var EMPTY_SESSION_EVENT_TYPES = /* @__PURE__ */ new Set(["session_start", "session_resumed", "session_end"]);
|
|
17144
|
+
async function isStrictlyEmptySessionFile(file) {
|
|
17145
|
+
const input = createReadStream4(file, { encoding: "utf8" });
|
|
17146
|
+
const lines = createInterface4({ input, crlfDelay: Infinity });
|
|
17147
|
+
let sawSessionStart = false;
|
|
17148
|
+
try {
|
|
17149
|
+
for await (const line of lines) {
|
|
17150
|
+
if (!line.trim()) continue;
|
|
17151
|
+
let event;
|
|
17152
|
+
try {
|
|
17153
|
+
event = JSON.parse(line);
|
|
17154
|
+
} catch {
|
|
17155
|
+
return false;
|
|
17156
|
+
}
|
|
17157
|
+
if (event === null || typeof event !== "object" || Array.isArray(event)) return false;
|
|
17158
|
+
const type = event.type;
|
|
17159
|
+
if (typeof type !== "string" || !EMPTY_SESSION_EVENT_TYPES.has(type)) return false;
|
|
17160
|
+
if (type === "session_start") sawSessionStart = true;
|
|
17161
|
+
}
|
|
17162
|
+
} catch {
|
|
17163
|
+
return false;
|
|
17164
|
+
} finally {
|
|
17165
|
+
lines.close();
|
|
17166
|
+
input.destroy();
|
|
17167
|
+
}
|
|
17168
|
+
return sawSessionStart;
|
|
17169
|
+
}
|
|
17170
|
+
|
|
17171
|
+
// src/storage/session-store/summary-builder.ts
|
|
17172
|
+
import { createReadStream as createReadStream5 } from "node:fs";
|
|
17173
|
+
import { createInterface as createInterface5 } from "node:readline";
|
|
17108
17174
|
async function summarizeSessionFile(opts) {
|
|
17109
17175
|
return summarizeSessionEventSequence({
|
|
17110
17176
|
id: opts.id,
|
|
@@ -17221,8 +17287,8 @@ async function summarizeSessionEventSequence(opts) {
|
|
|
17221
17287
|
}
|
|
17222
17288
|
}
|
|
17223
17289
|
async function* iterateSessionEvents(file, secretScrubber) {
|
|
17224
|
-
const stream =
|
|
17225
|
-
const lines =
|
|
17290
|
+
const stream = createReadStream5(file, { encoding: "utf8" });
|
|
17291
|
+
const lines = createInterface5({ input: stream, crlfDelay: Infinity });
|
|
17226
17292
|
try {
|
|
17227
17293
|
for await (const line of lines) {
|
|
17228
17294
|
if (!line.trim()) continue;
|
|
@@ -18118,6 +18184,10 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
18118
18184
|
await deleteSessionArtifacts({ rootDir: this.dir, id, jsonlPath });
|
|
18119
18185
|
await this.writeTombstone(id);
|
|
18120
18186
|
}
|
|
18187
|
+
async isEmpty(id) {
|
|
18188
|
+
const canonicalId = await this.resolveId(id);
|
|
18189
|
+
return isStrictlyEmptySessionFile(this.sessionPath(canonicalId, ".jsonl"));
|
|
18190
|
+
}
|
|
18121
18191
|
async delete(id) {
|
|
18122
18192
|
if (this.catalogClient) {
|
|
18123
18193
|
const canonical = await this.resolveId(id);
|
|
@@ -18681,6 +18751,12 @@ function parseModelRef(ref) {
|
|
|
18681
18751
|
function hasText(value) {
|
|
18682
18752
|
return typeof value === "string" && value.trim().length > 0;
|
|
18683
18753
|
}
|
|
18754
|
+
function asRefList(value) {
|
|
18755
|
+
return Array.isArray(value) ? value : void 0;
|
|
18756
|
+
}
|
|
18757
|
+
function asProfileName(value) {
|
|
18758
|
+
return hasText(value) ? value : void 0;
|
|
18759
|
+
}
|
|
18684
18760
|
function providerHasKey(entry) {
|
|
18685
18761
|
if (!entry) return false;
|
|
18686
18762
|
if (hasText(entry.apiKey)) return true;
|
|
@@ -18691,7 +18767,7 @@ function providerHasKey(entry) {
|
|
|
18691
18767
|
}
|
|
18692
18768
|
function visibleProviderModels(config, providerId, providerModels) {
|
|
18693
18769
|
const entry = config.providers?.[providerId];
|
|
18694
|
-
return entry?.models
|
|
18770
|
+
return Array.isArray(entry?.models) ? [...entry.models] : providerModels;
|
|
18695
18771
|
}
|
|
18696
18772
|
function buildProfiles(config) {
|
|
18697
18773
|
const entries = /* @__PURE__ */ new Map();
|
|
@@ -18728,13 +18804,34 @@ var FallbackProfileManager = class {
|
|
|
18728
18804
|
listProfiles() {
|
|
18729
18805
|
return Object.freeze([...this.profiles.keys()]);
|
|
18730
18806
|
}
|
|
18807
|
+
/**
|
|
18808
|
+
* The profile the session has selected (`config.fallbackProfile`, set by
|
|
18809
|
+
* `/fallback profile use <name>`), or undefined when none is selected or the
|
|
18810
|
+
* name no longer resolves to a defined profile.
|
|
18811
|
+
*
|
|
18812
|
+
* Consulted by every resolution entry point when the caller does not name a
|
|
18813
|
+
* profile itself. Without this the leader — which passes no profile — could
|
|
18814
|
+
* never use a named profile at all: `config.fallbackProfiles` was reachable
|
|
18815
|
+
* only by copying a chain into `fallbackModels`.
|
|
18816
|
+
*/
|
|
18817
|
+
activeProfileName() {
|
|
18818
|
+
const name = asProfileName(this.config.fallbackProfile);
|
|
18819
|
+
return name && this.profiles.has(name) ? name : void 0;
|
|
18820
|
+
}
|
|
18731
18821
|
// ── Resolution ─────────────────────────────────────────────────────────
|
|
18732
18822
|
/**
|
|
18733
18823
|
* Resolve a named fallback profile to a validated, provider-filtered chain.
|
|
18734
18824
|
*
|
|
18735
|
-
* Returns an empty chain when
|
|
18736
|
-
*
|
|
18737
|
-
*
|
|
18825
|
+
* Returns an empty chain when the profile doesn't exist, or when every entry
|
|
18826
|
+
* is excluded, quarantined, or blacked out.
|
|
18827
|
+
*
|
|
18828
|
+
* Filtering is intentionally identical to {@link resolveRefs} (the explicit
|
|
18829
|
+
* `fallbackModels` path): the self-exclusion, the runtime status tracker,
|
|
18830
|
+
* and the availability calendar — nothing else. Anything a named profile
|
|
18831
|
+
* drops, an explicit chain drops too, and vice versa. Profiles used to apply
|
|
18832
|
+
* two extra filters (provider "usability" and the `providers[].models`
|
|
18833
|
+
* snapshot) that the explicit path did not, which silently rerouted roles
|
|
18834
|
+
* pinned to a profile onto a different model than the one configured.
|
|
18738
18835
|
*
|
|
18739
18836
|
* @param name - Profile name from config.fallbackProfiles.
|
|
18740
18837
|
* @param defaultProvider - Used when an entry has no explicit provider.
|
|
@@ -18755,13 +18852,9 @@ var FallbackProfileManager = class {
|
|
|
18755
18852
|
if (seen.has(key)) continue;
|
|
18756
18853
|
seen.add(key);
|
|
18757
18854
|
if (excludeKey && key === excludeKey) continue;
|
|
18758
|
-
const health = this.checkProvider(providerId);
|
|
18759
|
-
if (!health.usable) continue;
|
|
18760
18855
|
if (this.statusTracker && !this.statusTracker.isAvailable(providerId, parsed.model)) continue;
|
|
18761
18856
|
if (!evaluateModelCalendar(this.config.modelAvailabilitySchedule, providerId, parsed.model).allowed)
|
|
18762
18857
|
continue;
|
|
18763
|
-
const allowedModels = this.config.providers?.[providerId]?.models;
|
|
18764
|
-
if (allowedModels && !allowedModels.includes(parsed.model)) continue;
|
|
18765
18858
|
resolved.push({
|
|
18766
18859
|
providerId,
|
|
18767
18860
|
model: parsed.model,
|
|
@@ -18779,12 +18872,14 @@ var FallbackProfileManager = class {
|
|
|
18779
18872
|
resolveEffective(opts = {}) {
|
|
18780
18873
|
const bridge = this.resolveBridge(opts.exclude);
|
|
18781
18874
|
let selected = FREEZER_EMPTY;
|
|
18782
|
-
|
|
18783
|
-
|
|
18875
|
+
const explicitRefs = asRefList(opts.fallbackModels);
|
|
18876
|
+
const profileName = asProfileName(opts.fallbackProfile) ?? this.activeProfileName();
|
|
18877
|
+
if (explicitRefs && explicitRefs.length > 0) {
|
|
18878
|
+
const resolved = this.resolveRefs(explicitRefs, opts.exclude);
|
|
18784
18879
|
if (resolved.length > 0) selected = resolved;
|
|
18785
18880
|
}
|
|
18786
|
-
if (selected.length === 0 &&
|
|
18787
|
-
const resolved = this.resolve(
|
|
18881
|
+
if (selected.length === 0 && profileName) {
|
|
18882
|
+
const resolved = this.resolve(profileName, { exclude: opts.exclude });
|
|
18788
18883
|
if (resolved.length > 0) selected = resolved;
|
|
18789
18884
|
}
|
|
18790
18885
|
if (selected.length === 0 && opts.fallbackAuto !== false) {
|
|
@@ -18860,13 +18955,14 @@ var FallbackProfileManager = class {
|
|
|
18860
18955
|
};
|
|
18861
18956
|
const configFallbackAuto = this.config.fallbackAuto;
|
|
18862
18957
|
const effectiveFallbackAuto = configFallbackAuto !== void 0 && configFallbackAuto !== null ? configFallbackAuto : !opts.closedWorld;
|
|
18863
|
-
const explicitRefs = opts.fallbackModels ?? this.config.fallbackModels;
|
|
18958
|
+
const explicitRefs = asRefList(opts.fallbackModels) ?? asRefList(this.config.fallbackModels);
|
|
18959
|
+
const profileName = asProfileName(opts.fallbackProfile) ?? this.activeProfileName();
|
|
18864
18960
|
const explicitUsable = explicitRefs !== void 0 && explicitRefs.length > 0 && this.resolveRefs(explicitRefs, current).length > 0;
|
|
18865
|
-
const profileUsable =
|
|
18961
|
+
const profileUsable = profileName !== void 0 && this.hasProfile(profileName) && this.resolve(profileName, { exclude: current }).length > 0;
|
|
18866
18962
|
const fromExplicitSource = explicitUsable || profileUsable;
|
|
18867
|
-
const selectedChain = opts.closedWorld ? explicitRefs && explicitRefs.length > 0 ? this.resolveRefs(explicitRefs, current) :
|
|
18963
|
+
const selectedChain = opts.closedWorld ? explicitRefs && explicitRefs.length > 0 ? this.resolveRefs(explicitRefs, current) : profileName ? this.resolve(profileName, { exclude: current }) : FREEZER_EMPTY : this.resolveEffective({
|
|
18868
18964
|
fallbackModels: explicitRefs,
|
|
18869
|
-
fallbackProfile:
|
|
18965
|
+
fallbackProfile: profileName,
|
|
18870
18966
|
fallbackAuto: effectiveFallbackAuto,
|
|
18871
18967
|
exclude: current
|
|
18872
18968
|
});
|
|
@@ -18883,7 +18979,7 @@ var FallbackProfileManager = class {
|
|
|
18883
18979
|
});
|
|
18884
18980
|
}
|
|
18885
18981
|
candidates.push(...selectedChain);
|
|
18886
|
-
if (!fromExplicitSource && effectiveFallbackAuto &&
|
|
18982
|
+
if (!fromExplicitSource && effectiveFallbackAuto && profileName !== "default") {
|
|
18887
18983
|
candidates.push(...this.resolve("default", { exclude: current }));
|
|
18888
18984
|
}
|
|
18889
18985
|
if (!fromExplicitSource && effectiveFallbackAuto) {
|
|
@@ -18961,7 +19057,7 @@ var FallbackProfileManager = class {
|
|
|
18961
19057
|
const leaderModel = this.config.model;
|
|
18962
19058
|
const providers = this.config.providers ?? {};
|
|
18963
19059
|
const favoriteSet = new Set(
|
|
18964
|
-
(this.config.favoriteModels ?? []).map((ref) => {
|
|
19060
|
+
(asRefList(this.config.favoriteModels) ?? []).map((ref) => {
|
|
18965
19061
|
const p = parseModelRef(ref);
|
|
18966
19062
|
return `${p.provider ?? leaderProvider}/${p.model}`;
|
|
18967
19063
|
})
|
|
@@ -27720,10 +27816,10 @@ var AdaptiveConcurrencyController = class {
|
|
|
27720
27816
|
};
|
|
27721
27817
|
|
|
27722
27818
|
// src/coordination/agent-monitor.ts
|
|
27723
|
-
import { createReadStream as
|
|
27819
|
+
import { createReadStream as createReadStream6 } from "node:fs";
|
|
27724
27820
|
import * as fs6 from "node:fs/promises";
|
|
27725
27821
|
import * as path38 from "node:path";
|
|
27726
|
-
import { createInterface as
|
|
27822
|
+
import { createInterface as createInterface6 } from "node:readline";
|
|
27727
27823
|
var AgentMonitorService = class _AgentMonitorService {
|
|
27728
27824
|
_fleetBus;
|
|
27729
27825
|
_events;
|
|
@@ -27830,8 +27926,8 @@ var AgentMonitorService = class _AgentMonitorService {
|
|
|
27830
27926
|
const accessible = await fs6.access(file).then(() => true).catch(() => false);
|
|
27831
27927
|
if (!accessible) return [];
|
|
27832
27928
|
const out = [];
|
|
27833
|
-
const input =
|
|
27834
|
-
const lines =
|
|
27929
|
+
const input = createReadStream6(file, { encoding: "utf8" });
|
|
27930
|
+
const lines = createInterface6({ input, crlfDelay: Number.POSITIVE_INFINITY });
|
|
27835
27931
|
try {
|
|
27836
27932
|
for await (const line of lines) {
|
|
27837
27933
|
const trimmed = line.trim();
|
|
@@ -75,12 +75,12 @@ export declare function makeMailSendTool(opts?: MailToolsOptions): {
|
|
|
75
75
|
required: string[];
|
|
76
76
|
};
|
|
77
77
|
execute(input: unknown, ctx: Context): Promise<{
|
|
78
|
+
summary?: never;
|
|
78
79
|
ok: boolean;
|
|
79
80
|
error: string;
|
|
80
81
|
messageId?: never;
|
|
81
82
|
from?: never;
|
|
82
83
|
to?: never;
|
|
83
|
-
summary?: never;
|
|
84
84
|
} | {
|
|
85
85
|
error?: never;
|
|
86
86
|
ok: boolean;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { ContentBlock } from '../types/blocks.js';
|
|
2
2
|
import type { Message } from '../types/messages.js';
|
|
3
|
-
import type { TodoItem } from './context.js';
|
|
4
|
-
import { Context } from './context.js';
|
|
3
|
+
import type { Context, TodoItem } from './context.js';
|
|
5
4
|
/**
|
|
6
5
|
* Observable wrapper for mutable conversation state. Production code should
|
|
7
6
|
* mutate messages, todos, and meta through this API so subscribers see a
|
|
@@ -143,9 +143,27 @@ export declare function fallbackProfileChain(config: Config, profileName: string
|
|
|
143
143
|
export declare function smartDefaultFallbackChain(config: Config): string[];
|
|
144
144
|
/**
|
|
145
145
|
* The effective fallback chain for a turn: the explicit `fallbackModels` list
|
|
146
|
-
* when non-empty, otherwise the
|
|
146
|
+
* when non-empty, otherwise the selected profile, otherwise the smart default
|
|
147
|
+
* (unless `fallbackAuto` is off).
|
|
148
|
+
*
|
|
149
|
+
* NOTE: this is the SELECTED chain, not the full runtime order — it omits the
|
|
150
|
+
* bridge, the primary re-insertion, the extra `default`-profile depth and the
|
|
151
|
+
* last-resort sweep that {@link runtimeFallbackChain} adds. Use
|
|
152
|
+
* `runtimeFallbackChain` for anything shown to a user as "what will be tried".
|
|
147
153
|
*/
|
|
148
154
|
export declare function effectiveFallbackChain(config: Config): string[];
|
|
155
|
+
/**
|
|
156
|
+
* The chain the agent loop will ACTUALLY rotate through, in order, if the
|
|
157
|
+
* current primary fails right now — the same `resolveCandidates` call the
|
|
158
|
+
* fallback extension makes, including bridge, primary re-insertion, the
|
|
159
|
+
* `default`-profile depth and the last-resort sweep.
|
|
160
|
+
*
|
|
161
|
+
* `/fallback` used to render `effectiveFallbackChain` instead, so the
|
|
162
|
+
* displayed chain could be four entries while the runtime rotated through
|
|
163
|
+
* seventeen — the view was structurally unable to match the behavior it
|
|
164
|
+
* claimed to describe.
|
|
165
|
+
*/
|
|
166
|
+
export declare function runtimeFallbackChain(config: Config): string[];
|
|
149
167
|
/**
|
|
150
168
|
* Build the cross-provider fallback extension. Always returns an extension —
|
|
151
169
|
* the effective chain (`effectiveFallbackChain`) is recomputed every turn from
|
|
@@ -59,12 +59,30 @@ export declare class FallbackProfileManager {
|
|
|
59
59
|
setStatusTracker(tracker: ProviderModelStatusTracker | undefined): void;
|
|
60
60
|
hasProfile(name: string): boolean;
|
|
61
61
|
listProfiles(): readonly string[];
|
|
62
|
+
/**
|
|
63
|
+
* The profile the session has selected (`config.fallbackProfile`, set by
|
|
64
|
+
* `/fallback profile use <name>`), or undefined when none is selected or the
|
|
65
|
+
* name no longer resolves to a defined profile.
|
|
66
|
+
*
|
|
67
|
+
* Consulted by every resolution entry point when the caller does not name a
|
|
68
|
+
* profile itself. Without this the leader — which passes no profile — could
|
|
69
|
+
* never use a named profile at all: `config.fallbackProfiles` was reachable
|
|
70
|
+
* only by copying a chain into `fallbackModels`.
|
|
71
|
+
*/
|
|
72
|
+
activeProfileName(): string | undefined;
|
|
62
73
|
/**
|
|
63
74
|
* Resolve a named fallback profile to a validated, provider-filtered chain.
|
|
64
75
|
*
|
|
65
|
-
* Returns an empty chain when
|
|
66
|
-
*
|
|
67
|
-
*
|
|
76
|
+
* Returns an empty chain when the profile doesn't exist, or when every entry
|
|
77
|
+
* is excluded, quarantined, or blacked out.
|
|
78
|
+
*
|
|
79
|
+
* Filtering is intentionally identical to {@link resolveRefs} (the explicit
|
|
80
|
+
* `fallbackModels` path): the self-exclusion, the runtime status tracker,
|
|
81
|
+
* and the availability calendar — nothing else. Anything a named profile
|
|
82
|
+
* drops, an explicit chain drops too, and vice versa. Profiles used to apply
|
|
83
|
+
* two extra filters (provider "usability" and the `providers[].models`
|
|
84
|
+
* snapshot) that the explicit path did not, which silently rerouted roles
|
|
85
|
+
* pinned to a profile onto a different model than the one configured.
|
|
68
86
|
*
|
|
69
87
|
* @param name - Profile name from config.fallbackProfiles.
|
|
70
88
|
* @param defaultProvider - Used when an entry has no explicit provider.
|
package/dist/core/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export { buildBtwBlock, consumeBtwNotes, pendingBtwCount, setBtwNote, } from './
|
|
|
4
4
|
export { Context, type ContextInit, type ProviderMemoryEvidence, type RunOptions, type TodoItem, } from './context.js';
|
|
5
5
|
export { type ContinuationInput, type ContinuationSource, detectContinueIntent, type ResolvedContinuation, resolveContinuation, } from './continue-intent.js';
|
|
6
6
|
export { ConversationState, type ReadonlyConversationState, type StateChange, type StateChangeHandler, wrapAsState, } from './conversation-state.js';
|
|
7
|
-
export { createFallbackModelExtension, effectiveFallbackChain, type FallbackGateFn, type FallbackModelDeps, fallbackProfileChain, smartDefaultFallbackChain, } from './fallback-model.js';
|
|
7
|
+
export { createFallbackModelExtension, effectiveFallbackChain, type FallbackGateFn, type FallbackModelDeps, fallbackProfileChain, runtimeFallbackChain, smartDefaultFallbackChain, } from './fallback-model.js';
|
|
8
8
|
export { FallbackProfileManager } from './fallback-profile-manager.js';
|
|
9
9
|
export { InputBuilder, type InputBuilderEvent, type InputBuilderOptions, } from './input-builder.js';
|
|
10
10
|
export { type InstructionBundle, type InstructionBundlePaths, loadInstructionBundle, type SystemInstructionVariant, } from './instruction-bundle.js';
|