privateer-agent 0.15.4 → 0.15.6
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/README.md +11 -0
- package/bin/boot-bundle.d.mts +2 -0
- package/bin/boot-bundle.mjs +44 -0
- package/bin/fresh-supervisor.d.mts +5 -1
- package/bin/fresh-supervisor.mjs +47 -10
- package/bin/privateer-launch.mjs +27 -3
- package/bin/privateer-subagent.mjs +5 -2
- package/bin/privateer-verify.mjs +12 -0
- package/bin/session-recovery.d.mts +53 -0
- package/bin/session-recovery.mjs +240 -0
- package/bin/session-seal-preload.mjs +17 -0
- package/bin/session-seal.d.mts +25 -0
- package/bin/session-seal.mjs +242 -0
- package/dist-boot/boot.mjs +3 -0
- package/dist-boot/c-27JKSMWL.mjs +1460 -0
- package/dist-boot/c-2BMRFV24.mjs +269 -0
- package/dist-boot/c-2CTF6JA3.mjs +166 -0
- package/dist-boot/c-2G3BBHRJ.mjs +84 -0
- package/dist-boot/c-2IDLKXX6.mjs +250 -0
- package/dist-boot/c-2NJD5VYM.mjs +8 -0
- package/dist-boot/c-2S5EEQPW.mjs +1602 -0
- package/dist-boot/c-2WRDCUVI.mjs +25 -0
- package/dist-boot/c-2YN3M256.mjs +14 -0
- package/dist-boot/c-37GM3GMU.mjs +187 -0
- package/dist-boot/c-3STKRSVO.mjs +2480 -0
- package/dist-boot/c-3TPV6TQQ.mjs +2320 -0
- package/dist-boot/c-3UVHLQDJ.mjs +225 -0
- package/dist-boot/c-42PUUZYC.mjs +697 -0
- package/dist-boot/c-4D5UMWVW.mjs +683 -0
- package/dist-boot/c-4ETZRMTA.mjs +46 -0
- package/dist-boot/c-4QT25BD5.mjs +1482 -0
- package/dist-boot/c-4WVR32AP.mjs +2579 -0
- package/dist-boot/c-5EMM567G.mjs +152 -0
- package/dist-boot/c-5FA4CV63.mjs +145 -0
- package/dist-boot/c-5GV3X3RB.mjs +14 -0
- package/dist-boot/c-5JCEPRIY.mjs +52 -0
- package/dist-boot/c-5NDKIIWT.mjs +16 -0
- package/dist-boot/c-5QL3AR26.mjs +4665 -0
- package/dist-boot/c-5XY6MFKN.mjs +5142 -0
- package/dist-boot/c-65UZIZC7.mjs +2897 -0
- package/dist-boot/c-6FUXKHOK.mjs +1969 -0
- package/dist-boot/c-6JHWQE4V.mjs +18242 -0
- package/dist-boot/c-6LOBR4I6.mjs +5280 -0
- package/dist-boot/c-6QHOZXKQ.mjs +14394 -0
- package/dist-boot/c-6ZO2SADQ.mjs +178 -0
- package/dist-boot/c-6ZORVVZP.mjs +1449 -0
- package/dist-boot/c-76QH4UCP.mjs +2441 -0
- package/dist-boot/c-77GO5L5Y.mjs +20982 -0
- package/dist-boot/c-7M23XFTN.mjs +5052 -0
- package/dist-boot/c-7TC367E2.mjs +32 -0
- package/dist-boot/c-7UOG7POX.mjs +1524 -0
- package/dist-boot/c-7VHP3FLN.mjs +376 -0
- package/dist-boot/c-A73JHZP2.mjs +13207 -0
- package/dist-boot/c-ABXULAFL.mjs +71 -0
- package/dist-boot/c-ANDD2AQO.mjs +74 -0
- package/dist-boot/c-AOY77AZL.mjs +1430 -0
- package/dist-boot/c-AXEPZ22I.mjs +108 -0
- package/dist-boot/c-B2Y7VNHU.mjs +427 -0
- package/dist-boot/c-B7VJUH73.mjs +77 -0
- package/dist-boot/c-BFW6CDVL.mjs +24 -0
- package/dist-boot/c-BHNIF2AR.mjs +188 -0
- package/dist-boot/c-BKF2O6BL.mjs +23 -0
- package/dist-boot/c-BOZXFTZN.mjs +8 -0
- package/dist-boot/c-BRNYJWZL.mjs +28 -0
- package/dist-boot/c-C3N4Z2HO.mjs +93 -0
- package/dist-boot/c-C4IV7ZFG.mjs +717 -0
- package/dist-boot/c-C5NK6UYV.mjs +793 -0
- package/dist-boot/c-C67644MB.mjs +1659 -0
- package/dist-boot/c-C6S2YB53.mjs +620 -0
- package/dist-boot/c-CDBEJSBF.mjs +37 -0
- package/dist-boot/c-CG47HBKU.mjs +435 -0
- package/dist-boot/c-CKCTWCT5.mjs +51 -0
- package/dist-boot/c-CN77DCGF.mjs +60 -0
- package/dist-boot/c-CRBXNKFO.mjs +1795 -0
- package/dist-boot/c-CRIHASQ6.mjs +973 -0
- package/dist-boot/c-CU4NGAUO.mjs +3786 -0
- package/dist-boot/c-CWRFLGQU.mjs +1883 -0
- package/dist-boot/c-CYQB2USO.mjs +32 -0
- package/dist-boot/c-DEE67DJO.mjs +379 -0
- package/dist-boot/c-DIFDBYOP.mjs +1258 -0
- package/dist-boot/c-DOSGVXDZ.mjs +34879 -0
- package/dist-boot/c-DR7XQI32.mjs +381 -0
- package/dist-boot/c-DTGPSB46.mjs +14666 -0
- package/dist-boot/c-DTHDNA4P.mjs +320 -0
- package/dist-boot/c-E4Z3Y5B5.mjs +3864 -0
- package/dist-boot/c-E66Z2TI7.mjs +203 -0
- package/dist-boot/c-EBU6RLRV.mjs +1527 -0
- package/dist-boot/c-EBZZNGSF.mjs +432 -0
- package/dist-boot/c-EC3LJ2KF.mjs +1032 -0
- package/dist-boot/c-EQBKXWNX.mjs +15829 -0
- package/dist-boot/c-EUEPIW4S.mjs +574 -0
- package/dist-boot/c-EX4YVWAT.mjs +378 -0
- package/dist-boot/c-EYZGSAJU.mjs +98 -0
- package/dist-boot/c-F75VRKY4.mjs +172 -0
- package/dist-boot/c-FH4NXKHV.mjs +177 -0
- package/dist-boot/c-FHNUCTEM.mjs +140 -0
- package/dist-boot/c-FJ5T42DS.mjs +5349 -0
- package/dist-boot/c-FPCNRL7G.mjs +1728 -0
- package/dist-boot/c-G4DLN7Q4.mjs +8 -0
- package/dist-boot/c-G56GYQFZ.mjs +2507 -0
- package/dist-boot/c-GLIOERDQ.mjs +1200 -0
- package/dist-boot/c-GMJ5HUBM.mjs +14 -0
- package/dist-boot/c-H3HSGMAQ.mjs +461 -0
- package/dist-boot/c-HIKTO6P7.mjs +275 -0
- package/dist-boot/c-I2MCJ34O.mjs +464 -0
- package/dist-boot/c-I3C6LBW4.mjs +765 -0
- package/dist-boot/c-I54OKQHW.mjs +387 -0
- package/dist-boot/c-IFSP3R4D.mjs +80 -0
- package/dist-boot/c-IZK77VB7.mjs +171 -0
- package/dist-boot/c-J3Y25UGE.mjs +54 -0
- package/dist-boot/c-J5IESS7W.mjs +27750 -0
- package/dist-boot/c-JJWZBY7L.mjs +254 -0
- package/dist-boot/c-JKTFXTGF.mjs +463 -0
- package/dist-boot/c-JN57AXQ4.mjs +77 -0
- package/dist-boot/c-KFIO6LUW.mjs +1096 -0
- package/dist-boot/c-KIEMEFWW.mjs +478 -0
- package/dist-boot/c-KIVXWBYD.mjs +28 -0
- package/dist-boot/c-KP6CRIP4.mjs +580 -0
- package/dist-boot/c-L26VOJX4.mjs +11558 -0
- package/dist-boot/c-L5GHWG5G.mjs +5988 -0
- package/dist-boot/c-M7NSQAKK.mjs +353 -0
- package/dist-boot/c-MCEWOPBW.mjs +56 -0
- package/dist-boot/c-MGPIEG7I.mjs +20 -0
- package/dist-boot/c-NREXJV3M.mjs +393 -0
- package/dist-boot/c-O5PP6CTX.mjs +162 -0
- package/dist-boot/c-OBQDHSXM.mjs +1774 -0
- package/dist-boot/c-OLQHHDD4.mjs +21 -0
- package/dist-boot/c-OXW4JQQH.mjs +319 -0
- package/dist-boot/c-P3D7ZUWN.mjs +1288 -0
- package/dist-boot/c-P4PQZVV5.mjs +948 -0
- package/dist-boot/c-P63T3XL2.mjs +26373 -0
- package/dist-boot/c-P6N5DQGZ.mjs +194 -0
- package/dist-boot/c-P7MLKQFC.mjs +58 -0
- package/dist-boot/c-PB3PZJL5.mjs +1276 -0
- package/dist-boot/c-PTN4S6G2.mjs +1259 -0
- package/dist-boot/c-PYCE5J7U.mjs +1083 -0
- package/dist-boot/c-Q4HYCRLB.mjs +19410 -0
- package/dist-boot/c-QUXMETGG.mjs +68 -0
- package/dist-boot/c-RDMJZCOX.mjs +356 -0
- package/dist-boot/c-ROGJK76M.mjs +17 -0
- package/dist-boot/c-RQJJ26T4.mjs +708 -0
- package/dist-boot/c-RSKCUPJF.mjs +7559 -0
- package/dist-boot/c-RVJU4O6P.mjs +37 -0
- package/dist-boot/c-S2RVHR3M.mjs +165 -0
- package/dist-boot/c-SKMK3PEE.mjs +91120 -0
- package/dist-boot/c-TI7SM4EG.mjs +20 -0
- package/dist-boot/c-TILJ6GXD.mjs +1235 -0
- package/dist-boot/c-TT6BCUJD.mjs +114 -0
- package/dist-boot/c-U4ITOXAN.mjs +2107 -0
- package/dist-boot/c-UGERXVO2.mjs +7120 -0
- package/dist-boot/c-UPBH5AXY.mjs +1363 -0
- package/dist-boot/c-US2PUNZL.mjs +597 -0
- package/dist-boot/c-UU4WZPPE.mjs +20 -0
- package/dist-boot/c-UWVIYPQS.mjs +39 -0
- package/dist-boot/c-V4RHQBPQ.mjs +17683 -0
- package/dist-boot/c-V5MRVK47.mjs +351 -0
- package/dist-boot/c-V6CL266R.mjs +1755 -0
- package/dist-boot/c-VJTMFKYE.mjs +14975 -0
- package/dist-boot/c-VJTRUKIB.mjs +773 -0
- package/dist-boot/c-W4IFSHPW.mjs +43 -0
- package/dist-boot/c-WETGB2CF.mjs +113 -0
- package/dist-boot/c-WO3QSZUU.mjs +1337 -0
- package/dist-boot/c-WQLH73TY.mjs +242 -0
- package/dist-boot/c-XL735JW5.mjs +500 -0
- package/dist-boot/c-Y7HADL5B.mjs +1107 -0
- package/dist-boot/c-YGQHSVSK.mjs +41 -0
- package/dist-boot/c-YMP2AMEB.mjs +10350 -0
- package/dist-boot/c-YRDO2WEF.mjs +12012 -0
- package/dist-boot/c-YUSTRATJ.mjs +8 -0
- package/dist-boot/c-Z2262R22.mjs +2697 -0
- package/dist-boot/c-Z4ALQMJC.mjs +709 -0
- package/dist-boot/c-Z5ZUQVUY.mjs +62 -0
- package/dist-boot/c-ZDZUKXF7.mjs +874 -0
- package/dist-boot/c-ZJYLGIC3.mjs +32 -0
- package/dist-boot/c-ZNA5CDMI.mjs +77 -0
- package/dist-boot/c-ZSO6DI3M.mjs +204 -0
- package/dist-boot/c-ZWUVHKMK.mjs +100 -0
- package/dist-boot/c-ZY4MESEW.mjs +832 -0
- package/dist-boot/c-ZZ5REI4L.mjs +329 -0
- package/dist-boot/cli.mjs +51 -0
- package/dist-boot/ext-anthropic-attribution.mjs +207 -0
- package/dist-boot/ext-pi-background-tasks.mjs +7234 -0
- package/dist-boot/ext-pi-subagents.mjs +37 -0
- package/dist-boot/ext-privateer-account.mjs +4426 -0
- package/dist-boot/ext-privateer-brand.mjs +5274 -0
- package/dist-boot/ext-privateer-codemode.mjs +37 -0
- package/dist-boot/ext-privateer-computer.mjs +626 -0
- package/dist-boot/ext-privateer-connect.mjs +1862 -0
- package/dist-boot/ext-privateer-context.mjs +323 -0
- package/dist-boot/ext-privateer-desktop.mjs +92 -0
- package/dist-boot/ext-privateer-final-audit.mjs +48 -0
- package/dist-boot/ext-privateer-fresh.mjs +81 -0
- package/dist-boot/ext-privateer-gate.mjs +5959 -0
- package/dist-boot/ext-privateer-hints.mjs +236 -0
- package/dist-boot/ext-privateer-media.mjs +2626 -0
- package/dist-boot/ext-privateer-models.mjs +3397 -0
- package/dist-boot/ext-privateer-posture.mjs +3006 -0
- package/dist-boot/ext-privateer-privacy.mjs +4578 -0
- package/dist-boot/ext-privateer-recovery.mjs +287 -0
- package/dist-boot/ext-privateer-speak.mjs +4754 -0
- package/dist-boot/ext-privateer-terminals.mjs +725 -0
- package/dist-boot/ext-privateer-tools.mjs +528 -0
- package/dist-boot/ext-privateer-truncation.mjs +74 -0
- package/dist-boot/ext-privateer-update.mjs +210 -0
- package/dist-boot/ext-privateer-vision.mjs +148 -0
- package/dist-boot/ext-privateer-web.mjs +543 -0
- package/dist-boot/ext-rpiv-ask-user-question.mjs +710 -0
- package/dist-boot/manifest.json +9 -0
- package/extensions/privateer-brand.ts +3 -1
- package/extensions/privateer-context.ts +4 -2
- package/extensions/privateer-final-audit.ts +17 -0
- package/extensions/privateer-gate.ts +55 -9
- package/extensions/privateer-recovery.ts +175 -0
- package/extensions/privateer-web.ts +4 -4
- package/package.json +3 -1
- package/patches/@earendil-works+pi-coding-agent+1.3.0.patch +199 -2
- package/patches/pi-background-tasks+2.6.10.patch +91 -7
- package/src/cli/chat.ts +7 -1
- package/src/config/moatManifest.json +2 -0
- package/src/config/whatsNew.json +4 -4
- package/src/context.ts +33 -5
- package/src/engine/finalAudit.ts +38 -0
- package/src/engine/stallWatchdog.ts +8 -1
- package/src/providers/account.ts +34 -3
- package/src/remote/attentionPush.ts +40 -0
- package/src/remote/liveTaskSession.ts +7 -1
- package/src/remote/relayClient.ts +38 -4
- package/src/remote/remoteBridge.ts +17 -0
- package/src/remote/transcriptSnapshot.ts +104 -0
|
@@ -0,0 +1,973 @@
|
|
|
1
|
+
import{createRequire as __pvCR}from"node:module";import{fileURLToPath as __pvF}from"node:url";import{dirname as __pvD}from"node:path";const require=__pvCR(import.meta.url);const __pvUrl=(r)=>new URL(r,import.meta.url).href;const __pvFile=(r)=>__pvF(new URL(r,import.meta.url));
|
|
2
|
+
import {
|
|
3
|
+
CURRENT_MODEL_SELECTION
|
|
4
|
+
} from "./c-G4DLN7Q4.mjs";
|
|
5
|
+
import {
|
|
6
|
+
FUSION_MODEL_CONFIG_SCHEMA_VERSION,
|
|
7
|
+
FusionError
|
|
8
|
+
} from "./c-37GM3GMU.mjs";
|
|
9
|
+
import {
|
|
10
|
+
replaceFileDurable
|
|
11
|
+
} from "./c-DR7XQI32.mjs";
|
|
12
|
+
import {
|
|
13
|
+
isJsonObject,
|
|
14
|
+
parseJsonText
|
|
15
|
+
} from "./c-I3C6LBW4.mjs";
|
|
16
|
+
import {
|
|
17
|
+
getAgentDir
|
|
18
|
+
} from "./c-PTN4S6G2.mjs";
|
|
19
|
+
import {
|
|
20
|
+
__name
|
|
21
|
+
} from "./c-CN77DCGF.mjs";
|
|
22
|
+
|
|
23
|
+
// node_modules/pi-background-tasks/src/core/fusion/config.ts?ext=pi-background-tasks
|
|
24
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
25
|
+
import { chmod, mkdir, open, readFile, rm } from "node:fs/promises";
|
|
26
|
+
import { basename, dirname, join } from "node:path";
|
|
27
|
+
|
|
28
|
+
// node_modules/pi-background-tasks/src/core/anthropic-attribution.ts?ext=pi-background-tasks
|
|
29
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
30
|
+
var CLAUDE_CODE_VERSION = "2.1.280";
|
|
31
|
+
var CLAUDE_CODE_ENTRYPOINT = "sdk-cli";
|
|
32
|
+
var ANTHROPIC_1M_CONTEXT_BETA = "context-1m-2025-08-07";
|
|
33
|
+
var CLAUDE_CODE_200K_SUBSCRIPTION_CONTEXT_WINDOW = 2e5;
|
|
34
|
+
var CLAUDE_CODE_LEGACY_BETA_VALUES = [
|
|
35
|
+
"claude-code-20250219",
|
|
36
|
+
"oauth-2025-04-20",
|
|
37
|
+
"interleaved-thinking-2025-05-14",
|
|
38
|
+
"thinking-token-count-2026-05-13",
|
|
39
|
+
"context-management-2025-06-27",
|
|
40
|
+
"prompt-caching-scope-2026-01-05",
|
|
41
|
+
"advisor-tool-2026-03-01",
|
|
42
|
+
"structured-outputs-2025-12-15"
|
|
43
|
+
];
|
|
44
|
+
var CLAUDE_CODE_ADAPTIVE_200K_BETA_VALUES = [
|
|
45
|
+
"claude-code-20250219",
|
|
46
|
+
"oauth-2025-04-20",
|
|
47
|
+
"interleaved-thinking-2025-05-14",
|
|
48
|
+
"thinking-token-count-2026-05-13",
|
|
49
|
+
"context-management-2025-06-27",
|
|
50
|
+
"prompt-caching-scope-2026-01-05",
|
|
51
|
+
"mid-conversation-system-2026-04-07"
|
|
52
|
+
];
|
|
53
|
+
var CLAUDE_CODE_FABLE_5_1_200K_BETA_VALUES = [
|
|
54
|
+
...CLAUDE_CODE_ADAPTIVE_200K_BETA_VALUES,
|
|
55
|
+
"thinking-binding-controls-2026-08-01",
|
|
56
|
+
"cache-diagnosis-2026-04-07"
|
|
57
|
+
];
|
|
58
|
+
function build200KSubscriptionBetaHeader(values) {
|
|
59
|
+
if (values.includes(ANTHROPIC_1M_CONTEXT_BETA)) {
|
|
60
|
+
throw new Error(
|
|
61
|
+
`Anthropic attribution 200K subscription policy must not emit ${ANTHROPIC_1M_CONTEXT_BETA}`
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
return values.join(",");
|
|
65
|
+
}
|
|
66
|
+
__name(build200KSubscriptionBetaHeader, "build200KSubscriptionBetaHeader");
|
|
67
|
+
var CLAUDE_CODE_BETA = build200KSubscriptionBetaHeader(CLAUDE_CODE_LEGACY_BETA_VALUES);
|
|
68
|
+
var CLAUDE_CODE_ADAPTIVE_200K_BETA = build200KSubscriptionBetaHeader(
|
|
69
|
+
CLAUDE_CODE_ADAPTIVE_200K_BETA_VALUES
|
|
70
|
+
);
|
|
71
|
+
var CLAUDE_CODE_FABLE_5_1_200K_BETA = build200KSubscriptionBetaHeader(
|
|
72
|
+
CLAUDE_CODE_FABLE_5_1_200K_BETA_VALUES
|
|
73
|
+
);
|
|
74
|
+
var CLAUDE_AGENT_SDK_SYSTEM_TEXT = "You are a Claude agent, built on Anthropic's Claude Agent SDK.";
|
|
75
|
+
var ANTHROPIC_LINEAGE_DIAGNOSTIC_TYPE = "anthropic-cache-lineage";
|
|
76
|
+
var ANTHROPIC_LINEAGE_SCHEMA = "pi-anthropic-attribution.lineage.v1";
|
|
77
|
+
var ANTHROPIC_PROJECTION_VERSION = 3;
|
|
78
|
+
var ANTHROPIC_OFFICIAL_ORIGIN = "https://api.anthropic.com";
|
|
79
|
+
var ANTHROPIC_BETA_MESSAGES_URL = `${ANTHROPIC_OFFICIAL_ORIGIN}/v1/messages?beta=true`;
|
|
80
|
+
var COMPACTION_SUMMARY_PREFIX = "The conversation history before this point was compacted into the following summary:";
|
|
81
|
+
var parseJsonSource = JSON.parse.bind(JSON);
|
|
82
|
+
function claudeCode200KSubscriptionPolicy(modelId, beta, thinkingPolicy, features = {}) {
|
|
83
|
+
if (beta.split(",").includes(ANTHROPIC_1M_CONTEXT_BETA)) {
|
|
84
|
+
throw new Error(
|
|
85
|
+
`Anthropic attribution 200K subscription policy for ${modelId} must not emit ${ANTHROPIC_1M_CONTEXT_BETA}`
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
modelId,
|
|
90
|
+
beta,
|
|
91
|
+
thinkingPolicy,
|
|
92
|
+
contextWindow: CLAUDE_CODE_200K_SUBSCRIPTION_CONTEXT_WINDOW,
|
|
93
|
+
enforcesThinkingPrefixBinding: features.enforcesThinkingPrefixBinding === true,
|
|
94
|
+
supportsCacheDiagnostics: features.supportsCacheDiagnostics === true
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
__name(claudeCode200KSubscriptionPolicy, "claudeCode200KSubscriptionPolicy");
|
|
98
|
+
var CLAUDE_CODE_MODEL_POLICIES = Object.freeze({
|
|
99
|
+
"claude-3-5-haiku-20241022": claudeCode200KSubscriptionPolicy(
|
|
100
|
+
"claude-3-5-haiku-20241022",
|
|
101
|
+
CLAUDE_CODE_BETA,
|
|
102
|
+
"fixed-budget"
|
|
103
|
+
),
|
|
104
|
+
"claude-3-5-haiku-latest": claudeCode200KSubscriptionPolicy(
|
|
105
|
+
"claude-3-5-haiku-latest",
|
|
106
|
+
CLAUDE_CODE_BETA,
|
|
107
|
+
"fixed-budget"
|
|
108
|
+
),
|
|
109
|
+
"claude-3-5-sonnet-20240620": claudeCode200KSubscriptionPolicy(
|
|
110
|
+
"claude-3-5-sonnet-20240620",
|
|
111
|
+
CLAUDE_CODE_BETA,
|
|
112
|
+
"fixed-budget"
|
|
113
|
+
),
|
|
114
|
+
"claude-3-5-sonnet-20241022": claudeCode200KSubscriptionPolicy(
|
|
115
|
+
"claude-3-5-sonnet-20241022",
|
|
116
|
+
CLAUDE_CODE_BETA,
|
|
117
|
+
"fixed-budget"
|
|
118
|
+
),
|
|
119
|
+
"claude-3-7-sonnet-20250219": claudeCode200KSubscriptionPolicy(
|
|
120
|
+
"claude-3-7-sonnet-20250219",
|
|
121
|
+
CLAUDE_CODE_BETA,
|
|
122
|
+
"fixed-budget"
|
|
123
|
+
),
|
|
124
|
+
"claude-3-haiku-20240307": claudeCode200KSubscriptionPolicy(
|
|
125
|
+
"claude-3-haiku-20240307",
|
|
126
|
+
CLAUDE_CODE_BETA,
|
|
127
|
+
"fixed-budget"
|
|
128
|
+
),
|
|
129
|
+
"claude-3-opus-20240229": claudeCode200KSubscriptionPolicy(
|
|
130
|
+
"claude-3-opus-20240229",
|
|
131
|
+
CLAUDE_CODE_BETA,
|
|
132
|
+
"fixed-budget"
|
|
133
|
+
),
|
|
134
|
+
"claude-3-sonnet-20240229": claudeCode200KSubscriptionPolicy(
|
|
135
|
+
"claude-3-sonnet-20240229",
|
|
136
|
+
CLAUDE_CODE_BETA,
|
|
137
|
+
"fixed-budget"
|
|
138
|
+
),
|
|
139
|
+
"claude-fable-5": claudeCode200KSubscriptionPolicy(
|
|
140
|
+
"claude-fable-5",
|
|
141
|
+
CLAUDE_CODE_ADAPTIVE_200K_BETA,
|
|
142
|
+
"adaptive-effort"
|
|
143
|
+
),
|
|
144
|
+
"claude-fable-5-1": claudeCode200KSubscriptionPolicy(
|
|
145
|
+
"claude-fable-5-1",
|
|
146
|
+
CLAUDE_CODE_FABLE_5_1_200K_BETA,
|
|
147
|
+
"adaptive-effort",
|
|
148
|
+
{ enforcesThinkingPrefixBinding: true, supportsCacheDiagnostics: true }
|
|
149
|
+
),
|
|
150
|
+
"claude-haiku-4-5": claudeCode200KSubscriptionPolicy(
|
|
151
|
+
"claude-haiku-4-5",
|
|
152
|
+
CLAUDE_CODE_BETA,
|
|
153
|
+
"fixed-budget"
|
|
154
|
+
),
|
|
155
|
+
"claude-haiku-4-5-20251001": claudeCode200KSubscriptionPolicy(
|
|
156
|
+
"claude-haiku-4-5-20251001",
|
|
157
|
+
CLAUDE_CODE_BETA,
|
|
158
|
+
"fixed-budget"
|
|
159
|
+
),
|
|
160
|
+
"claude-opus-4-0": claudeCode200KSubscriptionPolicy(
|
|
161
|
+
"claude-opus-4-0",
|
|
162
|
+
CLAUDE_CODE_BETA,
|
|
163
|
+
"fixed-budget"
|
|
164
|
+
),
|
|
165
|
+
"claude-opus-4-1": claudeCode200KSubscriptionPolicy(
|
|
166
|
+
"claude-opus-4-1",
|
|
167
|
+
CLAUDE_CODE_BETA,
|
|
168
|
+
"fixed-budget"
|
|
169
|
+
),
|
|
170
|
+
"claude-opus-4-1-20250805": claudeCode200KSubscriptionPolicy(
|
|
171
|
+
"claude-opus-4-1-20250805",
|
|
172
|
+
CLAUDE_CODE_BETA,
|
|
173
|
+
"fixed-budget"
|
|
174
|
+
),
|
|
175
|
+
"claude-opus-4-20250514": claudeCode200KSubscriptionPolicy(
|
|
176
|
+
"claude-opus-4-20250514",
|
|
177
|
+
CLAUDE_CODE_BETA,
|
|
178
|
+
"fixed-budget"
|
|
179
|
+
),
|
|
180
|
+
"claude-opus-4-5": claudeCode200KSubscriptionPolicy(
|
|
181
|
+
"claude-opus-4-5",
|
|
182
|
+
CLAUDE_CODE_BETA,
|
|
183
|
+
"fixed-budget"
|
|
184
|
+
),
|
|
185
|
+
"claude-opus-4-5-20251101": claudeCode200KSubscriptionPolicy(
|
|
186
|
+
"claude-opus-4-5-20251101",
|
|
187
|
+
CLAUDE_CODE_BETA,
|
|
188
|
+
"fixed-budget"
|
|
189
|
+
),
|
|
190
|
+
"claude-opus-4-6": claudeCode200KSubscriptionPolicy(
|
|
191
|
+
"claude-opus-4-6",
|
|
192
|
+
CLAUDE_CODE_ADAPTIVE_200K_BETA,
|
|
193
|
+
"adaptive-effort"
|
|
194
|
+
),
|
|
195
|
+
"claude-opus-4-7": claudeCode200KSubscriptionPolicy(
|
|
196
|
+
"claude-opus-4-7",
|
|
197
|
+
CLAUDE_CODE_ADAPTIVE_200K_BETA,
|
|
198
|
+
"adaptive-effort"
|
|
199
|
+
),
|
|
200
|
+
"claude-opus-4-8": claudeCode200KSubscriptionPolicy(
|
|
201
|
+
"claude-opus-4-8",
|
|
202
|
+
CLAUDE_CODE_ADAPTIVE_200K_BETA,
|
|
203
|
+
"adaptive-effort"
|
|
204
|
+
),
|
|
205
|
+
"claude-opus-5": claudeCode200KSubscriptionPolicy(
|
|
206
|
+
"claude-opus-5",
|
|
207
|
+
CLAUDE_CODE_ADAPTIVE_200K_BETA,
|
|
208
|
+
"adaptive-effort"
|
|
209
|
+
),
|
|
210
|
+
"claude-opus-5-5": claudeCode200KSubscriptionPolicy(
|
|
211
|
+
"claude-opus-5-5",
|
|
212
|
+
CLAUDE_CODE_ADAPTIVE_200K_BETA,
|
|
213
|
+
"adaptive-effort"
|
|
214
|
+
),
|
|
215
|
+
"claude-sonnet-4-0": claudeCode200KSubscriptionPolicy(
|
|
216
|
+
"claude-sonnet-4-0",
|
|
217
|
+
CLAUDE_CODE_BETA,
|
|
218
|
+
"fixed-budget"
|
|
219
|
+
),
|
|
220
|
+
"claude-sonnet-4-20250514": claudeCode200KSubscriptionPolicy(
|
|
221
|
+
"claude-sonnet-4-20250514",
|
|
222
|
+
CLAUDE_CODE_BETA,
|
|
223
|
+
"fixed-budget"
|
|
224
|
+
),
|
|
225
|
+
"claude-sonnet-4-5": claudeCode200KSubscriptionPolicy(
|
|
226
|
+
"claude-sonnet-4-5",
|
|
227
|
+
CLAUDE_CODE_BETA,
|
|
228
|
+
"fixed-budget"
|
|
229
|
+
),
|
|
230
|
+
"claude-sonnet-4-5-20250929": claudeCode200KSubscriptionPolicy(
|
|
231
|
+
"claude-sonnet-4-5-20250929",
|
|
232
|
+
CLAUDE_CODE_BETA,
|
|
233
|
+
"fixed-budget"
|
|
234
|
+
),
|
|
235
|
+
"claude-sonnet-4-6": claudeCode200KSubscriptionPolicy(
|
|
236
|
+
"claude-sonnet-4-6",
|
|
237
|
+
CLAUDE_CODE_ADAPTIVE_200K_BETA,
|
|
238
|
+
"adaptive-effort"
|
|
239
|
+
),
|
|
240
|
+
"claude-sonnet-5": claudeCode200KSubscriptionPolicy(
|
|
241
|
+
"claude-sonnet-5",
|
|
242
|
+
CLAUDE_CODE_ADAPTIVE_200K_BETA,
|
|
243
|
+
"adaptive-effort"
|
|
244
|
+
),
|
|
245
|
+
"claude-sonnet-5-5": claudeCode200KSubscriptionPolicy(
|
|
246
|
+
"claude-sonnet-5-5",
|
|
247
|
+
CLAUDE_CODE_ADAPTIVE_200K_BETA,
|
|
248
|
+
"adaptive-effort"
|
|
249
|
+
)
|
|
250
|
+
});
|
|
251
|
+
function isPlainObject(value) {
|
|
252
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
253
|
+
}
|
|
254
|
+
__name(isPlainObject, "isPlainObject");
|
|
255
|
+
function cloneAnthropicCacheControl(value) {
|
|
256
|
+
if (value === void 0) return void 0;
|
|
257
|
+
if (!isPlainObject(value)) {
|
|
258
|
+
throw new Error(
|
|
259
|
+
"Anthropic attribution cannot safely process malformed cache_control; expected an object"
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
if (value["type"] !== "ephemeral") {
|
|
263
|
+
throw new Error(
|
|
264
|
+
'Anthropic attribution cannot safely process malformed cache_control.type; expected "ephemeral"'
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
const ttl = value["ttl"];
|
|
268
|
+
if (ttl !== void 0 && ttl !== "1h" && ttl !== "5m") {
|
|
269
|
+
throw new Error(
|
|
270
|
+
'Anthropic attribution cannot safely process malformed cache_control.ttl; expected "1h" or "5m"'
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
...value,
|
|
275
|
+
type: "ephemeral",
|
|
276
|
+
...ttl === void 0 ? {} : { ttl }
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
__name(cloneAnthropicCacheControl, "cloneAnthropicCacheControl");
|
|
280
|
+
function inspectCacheControls(payload) {
|
|
281
|
+
let count = 0;
|
|
282
|
+
let hasLong = false;
|
|
283
|
+
const inspectBlock = /* @__PURE__ */ __name((block) => {
|
|
284
|
+
if (!isPlainObject(block) || block["cache_control"] === void 0) return;
|
|
285
|
+
const cacheControl = cloneAnthropicCacheControl(block["cache_control"]);
|
|
286
|
+
count += 1;
|
|
287
|
+
if (cacheControl?.ttl === "1h") hasLong = true;
|
|
288
|
+
}, "inspectBlock");
|
|
289
|
+
const system = payload["system"];
|
|
290
|
+
if (Array.isArray(system)) {
|
|
291
|
+
for (const block of system) inspectBlock(block);
|
|
292
|
+
}
|
|
293
|
+
const tools = payload["tools"];
|
|
294
|
+
if (Array.isArray(tools)) {
|
|
295
|
+
for (const tool of tools) inspectBlock(tool);
|
|
296
|
+
}
|
|
297
|
+
const messages = payload["messages"];
|
|
298
|
+
if (Array.isArray(messages)) {
|
|
299
|
+
for (const message of messages) {
|
|
300
|
+
if (!isPlainObject(message)) continue;
|
|
301
|
+
const content = message["content"];
|
|
302
|
+
if (Array.isArray(content)) {
|
|
303
|
+
for (const block of content) inspectBlock(block);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return { count, retention: count === 0 ? void 0 : hasLong ? "long" : "short" };
|
|
308
|
+
}
|
|
309
|
+
__name(inspectCacheControls, "inspectCacheControls");
|
|
310
|
+
function normalizedAnthropicModelId(model) {
|
|
311
|
+
if (typeof model.id !== "string" || model.id.trim().length === 0) {
|
|
312
|
+
throw new Error("Anthropic attribution requires a non-empty model id");
|
|
313
|
+
}
|
|
314
|
+
const providerPrefix = "anthropic/";
|
|
315
|
+
return model.id.startsWith(providerPrefix) ? model.id.slice(providerPrefix.length) : model.id;
|
|
316
|
+
}
|
|
317
|
+
__name(normalizedAnthropicModelId, "normalizedAnthropicModelId");
|
|
318
|
+
function isClaudeCodeIdentityText(text) {
|
|
319
|
+
return text.startsWith("x-anthropic-billing-header:") || text === CLAUDE_AGENT_SDK_SYSTEM_TEXT || text === "You are Claude Code, Anthropic's official CLI for Claude." || text === "You are Claude Code, Anthropic's official CLI for Claude, running within the Claude Agent SDK.";
|
|
320
|
+
}
|
|
321
|
+
__name(isClaudeCodeIdentityText, "isClaudeCodeIdentityText");
|
|
322
|
+
function canonicalizeJson(value) {
|
|
323
|
+
if (Array.isArray(value)) return value.map(canonicalizeJson);
|
|
324
|
+
if (!isPlainObject(value)) return value;
|
|
325
|
+
const output = {};
|
|
326
|
+
for (const key of Object.keys(value).sort()) {
|
|
327
|
+
const child = value[key];
|
|
328
|
+
if (child !== void 0) output[key] = canonicalizeJson(child);
|
|
329
|
+
}
|
|
330
|
+
return output;
|
|
331
|
+
}
|
|
332
|
+
__name(canonicalizeJson, "canonicalizeJson");
|
|
333
|
+
function canonicalJson(value) {
|
|
334
|
+
return JSON.stringify(canonicalizeJson(value));
|
|
335
|
+
}
|
|
336
|
+
__name(canonicalJson, "canonicalJson");
|
|
337
|
+
function sha256Canonical(value) {
|
|
338
|
+
return createHash("sha256").update(canonicalJson(value), "utf8").digest("hex");
|
|
339
|
+
}
|
|
340
|
+
__name(sha256Canonical, "sha256Canonical");
|
|
341
|
+
function isSha256(value) {
|
|
342
|
+
return typeof value === "string" && /^[a-f0-9]{64}$/u.test(value);
|
|
343
|
+
}
|
|
344
|
+
__name(isSha256, "isSha256");
|
|
345
|
+
function isNonEmptyString(value) {
|
|
346
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
347
|
+
}
|
|
348
|
+
__name(isNonEmptyString, "isNonEmptyString");
|
|
349
|
+
function blockWithoutCacheControl(block) {
|
|
350
|
+
if (!isPlainObject(block)) return block;
|
|
351
|
+
const output = { ...block };
|
|
352
|
+
delete output["cache_control"];
|
|
353
|
+
return output;
|
|
354
|
+
}
|
|
355
|
+
__name(blockWithoutCacheControl, "blockWithoutCacheControl");
|
|
356
|
+
function promptMessagesWithoutCacheControls(messages) {
|
|
357
|
+
return messages.map((message) => {
|
|
358
|
+
const content = message["content"];
|
|
359
|
+
return {
|
|
360
|
+
...message,
|
|
361
|
+
...Array.isArray(content) ? { content: content.map(blockWithoutCacheControl) } : {}
|
|
362
|
+
};
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
__name(promptMessagesWithoutCacheControls, "promptMessagesWithoutCacheControls");
|
|
366
|
+
function promptMessagesHash(messages) {
|
|
367
|
+
return sha256Canonical(promptMessagesWithoutCacheControls(messages));
|
|
368
|
+
}
|
|
369
|
+
__name(promptMessagesHash, "promptMessagesHash");
|
|
370
|
+
function assistantContentHash(content) {
|
|
371
|
+
return sha256Canonical(content);
|
|
372
|
+
}
|
|
373
|
+
__name(assistantContentHash, "assistantContentHash");
|
|
374
|
+
function parseAnthropicLineageDetails(message) {
|
|
375
|
+
const diagnostic = [...message.diagnostics ?? []].reverse().find((candidate) => candidate.type === ANTHROPIC_LINEAGE_DIAGNOSTIC_TYPE);
|
|
376
|
+
const details = diagnostic?.details;
|
|
377
|
+
if (!isPlainObject(details)) return void 0;
|
|
378
|
+
const sourceModel = details["source_model"];
|
|
379
|
+
const responseId = details["response_id"];
|
|
380
|
+
const assistantContentSha256 = details["assistant_content_sha256"];
|
|
381
|
+
const conversationStaticSha256 = details["conversation_static_sha256"];
|
|
382
|
+
const requestMessageCount = details["request_message_count"];
|
|
383
|
+
const requestMessagesSha256 = details["request_messages_sha256"];
|
|
384
|
+
const cacheProfileSha256 = details["cache_profile_sha256"];
|
|
385
|
+
const cacheRetention = details["cache_retention"];
|
|
386
|
+
const compactionBoundarySha256 = details["compaction_boundary_sha256"];
|
|
387
|
+
const signatureEpochSha256 = details["signature_epoch_sha256"];
|
|
388
|
+
const signatureEpochInheritsPrior = details["signature_epoch_inherits_prior"];
|
|
389
|
+
const previousMessageId = details["previous_message_id"];
|
|
390
|
+
if (details["schema_version"] !== ANTHROPIC_LINEAGE_SCHEMA || details["projection_version"] !== ANTHROPIC_PROJECTION_VERSION || details["source_provider"] !== "anthropic" || details["source_api"] !== "anthropic-messages" || !isNonEmptyString(sourceModel) || !isNonEmptyString(responseId) || !isSha256(assistantContentSha256) || !isSha256(conversationStaticSha256) || typeof requestMessageCount !== "number" || !Number.isSafeInteger(requestMessageCount) || requestMessageCount < 0 || !isSha256(requestMessagesSha256) || !isSha256(cacheProfileSha256) || cacheRetention !== "none" && cacheRetention !== "short" && cacheRetention !== "long" || compactionBoundarySha256 !== null && !isSha256(compactionBoundarySha256) || !isSha256(signatureEpochSha256) || typeof signatureEpochInheritsPrior !== "boolean" || previousMessageId !== null && !isNonEmptyString(previousMessageId)) {
|
|
391
|
+
return void 0;
|
|
392
|
+
}
|
|
393
|
+
return {
|
|
394
|
+
schema_version: ANTHROPIC_LINEAGE_SCHEMA,
|
|
395
|
+
projection_version: ANTHROPIC_PROJECTION_VERSION,
|
|
396
|
+
source_provider: "anthropic",
|
|
397
|
+
source_api: "anthropic-messages",
|
|
398
|
+
source_model: sourceModel,
|
|
399
|
+
response_id: responseId,
|
|
400
|
+
assistant_content_sha256: assistantContentSha256,
|
|
401
|
+
conversation_static_sha256: conversationStaticSha256,
|
|
402
|
+
request_message_count: requestMessageCount,
|
|
403
|
+
request_messages_sha256: requestMessagesSha256,
|
|
404
|
+
cache_profile_sha256: cacheProfileSha256,
|
|
405
|
+
cache_retention: cacheRetention,
|
|
406
|
+
compaction_boundary_sha256: compactionBoundarySha256,
|
|
407
|
+
signature_epoch_sha256: signatureEpochSha256,
|
|
408
|
+
signature_epoch_inherits_prior: signatureEpochInheritsPrior,
|
|
409
|
+
previous_message_id: previousMessageId
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
__name(parseAnthropicLineageDetails, "parseAnthropicLineageDetails");
|
|
413
|
+
function isSuccessfulLineageStopReason(stopReason) {
|
|
414
|
+
return stopReason === "stop" || stopReason === "length" || stopReason === "toolUse";
|
|
415
|
+
}
|
|
416
|
+
__name(isSuccessfulLineageStopReason, "isSuccessfulLineageStopReason");
|
|
417
|
+
function lineageBindsContainingAssistant(message, lineage) {
|
|
418
|
+
return message.provider === lineage.source_provider && message.api === lineage.source_api && isNonEmptyString(message.model) && message.model === lineage.source_model && isSuccessfulLineageStopReason(message.stopReason) && isNonEmptyString(message.responseId) && message.responseId === lineage.response_id && lineage.assistant_content_sha256 === assistantContentHash(message.content);
|
|
419
|
+
}
|
|
420
|
+
__name(lineageBindsContainingAssistant, "lineageBindsContainingAssistant");
|
|
421
|
+
function conversationStaticHash(system, tools) {
|
|
422
|
+
const normalizedSystem = system.filter(
|
|
423
|
+
(block) => !isPlainObject(block) || typeof block["text"] !== "string" || !isClaudeCodeIdentityText(block["text"])
|
|
424
|
+
).map(blockWithoutCacheControl);
|
|
425
|
+
return sha256Canonical({
|
|
426
|
+
attribution_profile: {
|
|
427
|
+
claude_code_version: CLAUDE_CODE_VERSION,
|
|
428
|
+
entrypoint: CLAUDE_CODE_ENTRYPOINT
|
|
429
|
+
},
|
|
430
|
+
system: normalizedSystem,
|
|
431
|
+
tools: tools.map(blockWithoutCacheControl)
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
__name(conversationStaticHash, "conversationStaticHash");
|
|
435
|
+
function requestMessagesFromPayload(payload) {
|
|
436
|
+
const messages = payload["messages"];
|
|
437
|
+
if (!Array.isArray(messages) || messages.some((message) => !isPlainObject(message))) {
|
|
438
|
+
throw new Error("Anthropic attribution final payload.messages must be an object array");
|
|
439
|
+
}
|
|
440
|
+
for (const message of messages) {
|
|
441
|
+
if (message["role"] !== "user" && message["role"] !== "assistant") {
|
|
442
|
+
throw new Error("Anthropic attribution final payload message has an unsupported role");
|
|
443
|
+
}
|
|
444
|
+
const content = message["content"];
|
|
445
|
+
if (!Array.isArray(content) || content.some((block) => !isPlainObject(block))) {
|
|
446
|
+
throw new Error(
|
|
447
|
+
"Anthropic attribution final payload message content must use canonical block arrays"
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return messages;
|
|
452
|
+
}
|
|
453
|
+
__name(requestMessagesFromPayload, "requestMessagesFromPayload");
|
|
454
|
+
function systemBlocksFromPayload(payload) {
|
|
455
|
+
const system = payload["system"];
|
|
456
|
+
if (system === void 0) return [];
|
|
457
|
+
if (typeof system === "string") return [{ type: "text", text: system }];
|
|
458
|
+
if (!Array.isArray(system))
|
|
459
|
+
throw new Error("Anthropic attribution final payload.system must be a string or block array");
|
|
460
|
+
return system;
|
|
461
|
+
}
|
|
462
|
+
__name(systemBlocksFromPayload, "systemBlocksFromPayload");
|
|
463
|
+
function toolsFromPayload(payload) {
|
|
464
|
+
const tools = payload["tools"];
|
|
465
|
+
if (tools === void 0) return [];
|
|
466
|
+
if (!Array.isArray(tools) || tools.some((tool) => !isPlainObject(tool))) {
|
|
467
|
+
throw new Error("Anthropic attribution final payload.tools must be an object array");
|
|
468
|
+
}
|
|
469
|
+
return tools;
|
|
470
|
+
}
|
|
471
|
+
__name(toolsFromPayload, "toolsFromPayload");
|
|
472
|
+
function cacheProfileHash(model, policy, payload, staticSha256) {
|
|
473
|
+
return sha256Canonical({
|
|
474
|
+
projection_version: ANTHROPIC_PROJECTION_VERSION,
|
|
475
|
+
model: normalizedAnthropicModelId(model),
|
|
476
|
+
beta: policy.beta,
|
|
477
|
+
conversation_static_sha256: staticSha256,
|
|
478
|
+
thinking: payload["thinking"],
|
|
479
|
+
output_config: payload["output_config"],
|
|
480
|
+
tool_choice: payload["tool_choice"]
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
__name(cacheProfileHash, "cacheProfileHash");
|
|
484
|
+
function cacheRetentionFromPayload(payload) {
|
|
485
|
+
return inspectCacheControls(payload).retention ?? "none";
|
|
486
|
+
}
|
|
487
|
+
__name(cacheRetentionFromPayload, "cacheRetentionFromPayload");
|
|
488
|
+
function untrustedAssistantSha256(message) {
|
|
489
|
+
return sha256Canonical({
|
|
490
|
+
provider: message.provider ?? null,
|
|
491
|
+
api: message.api ?? null,
|
|
492
|
+
model: message.model ?? null,
|
|
493
|
+
response_id: message.responseId ?? null,
|
|
494
|
+
stop_reason: message.stopReason ?? null,
|
|
495
|
+
assistant_content_sha256: assistantContentHash(message.content),
|
|
496
|
+
lineage_diagnostics: (message.diagnostics ?? []).filter(
|
|
497
|
+
(diagnostic) => diagnostic.type === ANTHROPIC_LINEAGE_DIAGNOSTIC_TYPE
|
|
498
|
+
)
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
__name(untrustedAssistantSha256, "untrustedAssistantSha256");
|
|
502
|
+
function targetLineageState(context, targetModelId) {
|
|
503
|
+
for (let index = context.messages.length - 1; index >= 0; index -= 1) {
|
|
504
|
+
const message = context.messages[index];
|
|
505
|
+
if (message?.role !== "assistant") continue;
|
|
506
|
+
const lineageDiagnostics = (message.diagnostics ?? []).filter(
|
|
507
|
+
(diagnostic) => diagnostic.type === ANTHROPIC_LINEAGE_DIAGNOSTIC_TYPE
|
|
508
|
+
);
|
|
509
|
+
const latestRawDetails = lineageDiagnostics.at(-1)?.details;
|
|
510
|
+
const receiptClaimsTarget = latestRawDetails?.["source_model"] === targetModelId;
|
|
511
|
+
const assistantClaimsTarget = message.model === targetModelId;
|
|
512
|
+
if (!assistantClaimsTarget && !receiptClaimsTarget) continue;
|
|
513
|
+
if ((message.stopReason === "error" || message.stopReason === "aborted") && lineageDiagnostics.length === 0) {
|
|
514
|
+
continue;
|
|
515
|
+
}
|
|
516
|
+
const lineage = parseAnthropicLineageDetails(message);
|
|
517
|
+
if (lineage?.source_model === targetModelId && lineageBindsContainingAssistant(message, lineage)) {
|
|
518
|
+
return { kind: "trusted", lineage };
|
|
519
|
+
}
|
|
520
|
+
return { kind: "untrusted", assistantSha256: untrustedAssistantSha256(message) };
|
|
521
|
+
}
|
|
522
|
+
return { kind: "none" };
|
|
523
|
+
}
|
|
524
|
+
__name(targetLineageState, "targetLineageState");
|
|
525
|
+
function latestLineageForTarget(context, targetModelId) {
|
|
526
|
+
const state = targetLineageState(context, targetModelId);
|
|
527
|
+
return state.kind === "trusted" ? state.lineage : void 0;
|
|
528
|
+
}
|
|
529
|
+
__name(latestLineageForTarget, "latestLineageForTarget");
|
|
530
|
+
function declaredCompactionBoundarySha256(messages) {
|
|
531
|
+
const firstMessage = messages[0];
|
|
532
|
+
if (firstMessage?.["role"] !== "user" || !Array.isArray(firstMessage["content"])) return null;
|
|
533
|
+
const declaresCompaction = firstMessage["content"].some(
|
|
534
|
+
(block) => isPlainObject(block) && block["type"] === "text" && typeof block["text"] === "string" && block["text"].startsWith(COMPACTION_SUMMARY_PREFIX)
|
|
535
|
+
);
|
|
536
|
+
if (!declaresCompaction) return null;
|
|
537
|
+
return sha256Canonical(promptMessagesWithoutCacheControls([firstMessage])[0]);
|
|
538
|
+
}
|
|
539
|
+
__name(declaredCompactionBoundarySha256, "declaredCompactionBoundarySha256");
|
|
540
|
+
function hasLineageRequestPrefix(messages, previous) {
|
|
541
|
+
return messages.length >= previous.request_message_count && promptMessagesHash(messages.slice(0, previous.request_message_count)) === previous.request_messages_sha256;
|
|
542
|
+
}
|
|
543
|
+
__name(hasLineageRequestPrefix, "hasLineageRequestPrefix");
|
|
544
|
+
function prepareAnthropicLineageDetails(args) {
|
|
545
|
+
const targetModelId = normalizedAnthropicModelId(args.model);
|
|
546
|
+
const messages = requestMessagesFromPayload(args.payload);
|
|
547
|
+
const staticSha256 = conversationStaticHash(
|
|
548
|
+
systemBlocksFromPayload(args.payload),
|
|
549
|
+
toolsFromPayload(args.payload)
|
|
550
|
+
);
|
|
551
|
+
const profileSha256 = cacheProfileHash(args.model, args.policy, args.payload, staticSha256);
|
|
552
|
+
const cacheRetention = cacheRetentionFromPayload(args.payload);
|
|
553
|
+
const compactionBoundarySha256 = declaredCompactionBoundarySha256(messages);
|
|
554
|
+
const signatureEpoch = args.signatureEpoch;
|
|
555
|
+
let previous = latestLineageForTarget(args.context, targetModelId);
|
|
556
|
+
if (previous !== void 0 && (signatureEpoch.sha256 !== previous.signature_epoch_sha256 || !hasLineageRequestPrefix(messages, previous) || previous.cache_profile_sha256 !== profileSha256 || previous.cache_retention !== cacheRetention)) {
|
|
557
|
+
previous = void 0;
|
|
558
|
+
}
|
|
559
|
+
return {
|
|
560
|
+
schema_version: ANTHROPIC_LINEAGE_SCHEMA,
|
|
561
|
+
projection_version: ANTHROPIC_PROJECTION_VERSION,
|
|
562
|
+
source_provider: "anthropic",
|
|
563
|
+
source_api: "anthropic-messages",
|
|
564
|
+
source_model: targetModelId,
|
|
565
|
+
conversation_static_sha256: staticSha256,
|
|
566
|
+
request_message_count: messages.length,
|
|
567
|
+
request_messages_sha256: promptMessagesHash(messages),
|
|
568
|
+
cache_profile_sha256: profileSha256,
|
|
569
|
+
cache_retention: cacheRetention,
|
|
570
|
+
compaction_boundary_sha256: compactionBoundarySha256,
|
|
571
|
+
signature_epoch_sha256: signatureEpoch.sha256,
|
|
572
|
+
signature_epoch_inherits_prior: signatureEpoch.inheritsPrior,
|
|
573
|
+
previous_message_id: previous?.response_id ?? null
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
__name(prepareAnthropicLineageDetails, "prepareAnthropicLineageDetails");
|
|
577
|
+
var AnthropicLineageCoordinator = class {
|
|
578
|
+
static {
|
|
579
|
+
__name(this, "AnthropicLineageCoordinator");
|
|
580
|
+
}
|
|
581
|
+
inFlight = /* @__PURE__ */ new Set();
|
|
582
|
+
prepare(args) {
|
|
583
|
+
const targetModelId = normalizedAnthropicModelId(args.model);
|
|
584
|
+
const key = `${args.sessionId}\0${targetModelId}`;
|
|
585
|
+
if (this.inFlight.has(key)) {
|
|
586
|
+
throw new Error(
|
|
587
|
+
`Anthropic cache lineage already has an in-flight request for ${targetModelId}; concurrent continuations must fork`
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
const details = prepareAnthropicLineageDetails(args);
|
|
591
|
+
this.inFlight.add(key);
|
|
592
|
+
return { key, details };
|
|
593
|
+
}
|
|
594
|
+
release(prepared) {
|
|
595
|
+
this.inFlight.delete(prepared.key);
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
var anthropicLineageCoordinator = new AnthropicLineageCoordinator();
|
|
599
|
+
|
|
600
|
+
// node_modules/pi-background-tasks/src/core/fusion/config.ts?ext=pi-background-tasks
|
|
601
|
+
var FUSION_MODEL_CONFIG_FILE = "fusion-models.json";
|
|
602
|
+
function defaultFusionModelConfig() {
|
|
603
|
+
return {
|
|
604
|
+
schema_version: FUSION_MODEL_CONFIG_SCHEMA_VERSION,
|
|
605
|
+
candidates: [CURRENT_MODEL_SELECTION, CURRENT_MODEL_SELECTION, CURRENT_MODEL_SELECTION],
|
|
606
|
+
evaluator: CURRENT_MODEL_SELECTION,
|
|
607
|
+
merger: CURRENT_MODEL_SELECTION
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
__name(defaultFusionModelConfig, "defaultFusionModelConfig");
|
|
611
|
+
function fusionModelConfigPath(agentDir = getAgentDir()) {
|
|
612
|
+
return join(agentDir, FUSION_MODEL_CONFIG_FILE);
|
|
613
|
+
}
|
|
614
|
+
__name(fusionModelConfigPath, "fusionModelConfigPath");
|
|
615
|
+
function sha256Hex(bytes) {
|
|
616
|
+
return createHash2("sha256").update(bytes).digest("hex");
|
|
617
|
+
}
|
|
618
|
+
__name(sha256Hex, "sha256Hex");
|
|
619
|
+
async function revisionForPath(path) {
|
|
620
|
+
try {
|
|
621
|
+
const bytes = await readFile(path);
|
|
622
|
+
return { path, exists: true, sha256: sha256Hex(bytes) };
|
|
623
|
+
} catch (error) {
|
|
624
|
+
if (errorHasCode(error, "ENOENT")) return { path, exists: false, sha256: null };
|
|
625
|
+
throw error;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
__name(revisionForPath, "revisionForPath");
|
|
629
|
+
function errorHasCode(error, code) {
|
|
630
|
+
return isJsonObject(error) && error["code"] === code;
|
|
631
|
+
}
|
|
632
|
+
__name(errorHasCode, "errorHasCode");
|
|
633
|
+
function keysOf(value) {
|
|
634
|
+
return Object.keys(value).sort();
|
|
635
|
+
}
|
|
636
|
+
__name(keysOf, "keysOf");
|
|
637
|
+
function assertClosed(record, expected, label) {
|
|
638
|
+
const expectedSet = new Set(expected);
|
|
639
|
+
for (const key of Object.keys(record)) {
|
|
640
|
+
if (!expectedSet.has(key)) throw configError(`${label} contains unknown key ${key}`);
|
|
641
|
+
}
|
|
642
|
+
for (const key of expected) {
|
|
643
|
+
if (!Object.prototype.hasOwnProperty.call(record, key)) {
|
|
644
|
+
throw configError(`${label} is missing key ${key}`);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
__name(assertClosed, "assertClosed");
|
|
649
|
+
function configError(message) {
|
|
650
|
+
return new FusionError(message, { code: "config_invalid", childCreated: false });
|
|
651
|
+
}
|
|
652
|
+
__name(configError, "configError");
|
|
653
|
+
function requireSelection(value, label) {
|
|
654
|
+
if (typeof value !== "string") throw configError(`${label} must be a string`);
|
|
655
|
+
if (value === CURRENT_MODEL_SELECTION) return value;
|
|
656
|
+
const trimmed = value.trim();
|
|
657
|
+
if (trimmed.length === 0) throw configError(`${label} must not be blank`);
|
|
658
|
+
if (trimmed !== value) throw configError(`${label} must not have surrounding whitespace`);
|
|
659
|
+
if (!trimmed.includes("/")) throw configError(`${label} must be a qualified provider/model key`);
|
|
660
|
+
return trimmed;
|
|
661
|
+
}
|
|
662
|
+
__name(requireSelection, "requireSelection");
|
|
663
|
+
function requireCandidateSelections(value) {
|
|
664
|
+
if (!Array.isArray(value)) throw configError("candidates must be an array");
|
|
665
|
+
if (value.length !== 3) throw configError("candidates must contain exactly three entries");
|
|
666
|
+
const first = requireSelection(value[0], "candidates[0]");
|
|
667
|
+
const second = requireSelection(value[1], "candidates[1]");
|
|
668
|
+
const third = requireSelection(value[2], "candidates[2]");
|
|
669
|
+
return [first, second, third];
|
|
670
|
+
}
|
|
671
|
+
__name(requireCandidateSelections, "requireCandidateSelections");
|
|
672
|
+
function parseFusionModelConfig(value) {
|
|
673
|
+
if (!isJsonObject(value) || Array.isArray(value))
|
|
674
|
+
throw configError("fusion model config must be an object");
|
|
675
|
+
const record = value;
|
|
676
|
+
assertClosed(
|
|
677
|
+
record,
|
|
678
|
+
["schema_version", "candidates", "evaluator", "merger"],
|
|
679
|
+
"fusion model config"
|
|
680
|
+
);
|
|
681
|
+
if (record["schema_version"] !== FUSION_MODEL_CONFIG_SCHEMA_VERSION) {
|
|
682
|
+
throw configError("fusion model config schema_version mismatch");
|
|
683
|
+
}
|
|
684
|
+
return {
|
|
685
|
+
schema_version: FUSION_MODEL_CONFIG_SCHEMA_VERSION,
|
|
686
|
+
candidates: requireCandidateSelections(record["candidates"]),
|
|
687
|
+
evaluator: requireSelection(record["evaluator"], "evaluator"),
|
|
688
|
+
merger: requireSelection(record["merger"], "merger")
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
__name(parseFusionModelConfig, "parseFusionModelConfig");
|
|
692
|
+
async function loadFusionModelConfig(path = fusionModelConfigPath()) {
|
|
693
|
+
const revision = await revisionForPath(path);
|
|
694
|
+
if (!revision.exists) return { config: defaultFusionModelConfig(), revision };
|
|
695
|
+
let parsed;
|
|
696
|
+
try {
|
|
697
|
+
parsed = parseJsonText(await readFile(path, "utf8"));
|
|
698
|
+
} catch (error) {
|
|
699
|
+
throw configError(
|
|
700
|
+
`fusion model config is not valid JSON at ${path}: ${error instanceof Error ? error.message : String(error)}`
|
|
701
|
+
);
|
|
702
|
+
}
|
|
703
|
+
const config = parseFusionModelConfig(parsed);
|
|
704
|
+
return { config, revision };
|
|
705
|
+
}
|
|
706
|
+
__name(loadFusionModelConfig, "loadFusionModelConfig");
|
|
707
|
+
function qualifiedModelKey(model) {
|
|
708
|
+
return `${model.provider}/${model.id}`;
|
|
709
|
+
}
|
|
710
|
+
__name(qualifiedModelKey, "qualifiedModelKey");
|
|
711
|
+
function requireContextWindow(model, label) {
|
|
712
|
+
const value = model.contextWindow;
|
|
713
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
714
|
+
throw new FusionError(`${label} has no positive context window`, {
|
|
715
|
+
code: "model_unavailable",
|
|
716
|
+
childCreated: false
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
return Math.floor(value);
|
|
720
|
+
}
|
|
721
|
+
__name(requireContextWindow, "requireContextWindow");
|
|
722
|
+
function transportContextWindow(model, label) {
|
|
723
|
+
const advertised = requireContextWindow(model, label);
|
|
724
|
+
return model.provider === "anthropic" ? Math.min(advertised, CLAUDE_CODE_200K_SUBSCRIPTION_CONTEXT_WINDOW) : advertised;
|
|
725
|
+
}
|
|
726
|
+
__name(transportContextWindow, "transportContextWindow");
|
|
727
|
+
function requireMaxOutputTokens(model, label) {
|
|
728
|
+
const value = model.maxTokens;
|
|
729
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
730
|
+
throw new FusionError(`${label} has no positive maximum output token capacity`, {
|
|
731
|
+
code: "model_unavailable",
|
|
732
|
+
childCreated: false
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
return Math.floor(value);
|
|
736
|
+
}
|
|
737
|
+
__name(requireMaxOutputTokens, "requireMaxOutputTokens");
|
|
738
|
+
function modelIndex(models) {
|
|
739
|
+
const out = /* @__PURE__ */ new Map();
|
|
740
|
+
for (const model of models) out.set(qualifiedModelKey(model), model);
|
|
741
|
+
return out;
|
|
742
|
+
}
|
|
743
|
+
__name(modelIndex, "modelIndex");
|
|
744
|
+
var FRONTIER_MODEL_PATTERN = /(?:^|[-_/])(?:gpt|codex|claude|opus|sonnet|o[134](?:-[a-z0-9.]+)*)(?:[-_/]|$)/iu;
|
|
745
|
+
var TRUSTED_SUBSCRIPTION_ENDPOINTS = Object.freeze({
|
|
746
|
+
anthropic: "https://api.anthropic.com",
|
|
747
|
+
"openai-codex": "https://chatgpt.com/backend-api"
|
|
748
|
+
});
|
|
749
|
+
var AUTH_HEADER_NAMES = /* @__PURE__ */ new Set(["authorization", "proxy-authorization", "x-api-key", "api-key"]);
|
|
750
|
+
function isKnownFrontierEndpoint(baseUrl) {
|
|
751
|
+
if (baseUrl === void 0 || baseUrl.trim().length === 0) return false;
|
|
752
|
+
try {
|
|
753
|
+
const hostname = new URL(baseUrl).hostname.toLowerCase().replace(/\.+$/u, "");
|
|
754
|
+
return hostname === "api.openai.com" || hostname === "api.anthropic.com" || hostname === "openrouter.ai" || hostname === "chatgpt.com" || hostname.endsWith(".openai.azure.com") || hostname.endsWith(".cognitiveservices.azure.com") || hostname.endsWith(".ai.azure.com");
|
|
755
|
+
} catch {
|
|
756
|
+
return false;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
__name(isKnownFrontierEndpoint, "isKnownFrontierEndpoint");
|
|
760
|
+
function assertTrustedSubscriptionEndpoint(model, slotLabel, provider) {
|
|
761
|
+
const expectedText = TRUSTED_SUBSCRIPTION_ENDPOINTS[provider];
|
|
762
|
+
const effectiveText = model.baseUrl?.trim() || expectedText;
|
|
763
|
+
let effective;
|
|
764
|
+
try {
|
|
765
|
+
effective = new URL(effectiveText);
|
|
766
|
+
} catch {
|
|
767
|
+
throw new FusionError(
|
|
768
|
+
`${slotLabel} route ${model.provider}/${model.id} has a malformed subscription endpoint`,
|
|
769
|
+
{ code: "model_unavailable", childCreated: false }
|
|
770
|
+
);
|
|
771
|
+
}
|
|
772
|
+
const expected = new URL(expectedText);
|
|
773
|
+
const effectivePath = effective.href.slice(effective.origin.length).replace(/\/+$/u, "");
|
|
774
|
+
const expectedPath = expected.href.slice(expected.origin.length).replace(/\/+$/u, "");
|
|
775
|
+
if (effective.protocol !== "https:" || effective.username !== "" || effective.password !== "" || effective.search !== "" || effective.hash !== "" || effective.origin !== expected.origin || effectivePath !== expectedPath) {
|
|
776
|
+
throw new FusionError(
|
|
777
|
+
`${slotLabel} route ${model.provider}/${model.id} does not use the trusted Pi subscription endpoint ${expectedText}`,
|
|
778
|
+
{ code: "model_unavailable", childCreated: false }
|
|
779
|
+
);
|
|
780
|
+
}
|
|
781
|
+
const unsafeHeader = Object.keys(model.headers ?? {}).find(
|
|
782
|
+
(name) => AUTH_HEADER_NAMES.has(name.toLowerCase())
|
|
783
|
+
);
|
|
784
|
+
if (unsafeHeader !== void 0) {
|
|
785
|
+
throw new FusionError(
|
|
786
|
+
`${slotLabel} route ${model.provider}/${model.id} overrides subscription authentication header ${unsafeHeader}`,
|
|
787
|
+
{ code: "model_unavailable", childCreated: false }
|
|
788
|
+
);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
__name(assertTrustedSubscriptionEndpoint, "assertTrustedSubscriptionEndpoint");
|
|
792
|
+
function assertSubscriptionRoute(model, slotLabel, registry) {
|
|
793
|
+
const provider = model.provider.toLowerCase();
|
|
794
|
+
const frontier = provider === "openai" || provider === "openrouter" || provider === "anthropic" || provider === "openai-codex" || provider.includes("azure") || FRONTIER_MODEL_PATTERN.test(`${provider}/${model.id}`) || isKnownFrontierEndpoint(model.baseUrl);
|
|
795
|
+
if (!frontier) return;
|
|
796
|
+
if (provider !== "anthropic" && provider !== "openai-codex") {
|
|
797
|
+
throw new FusionError(
|
|
798
|
+
`${slotLabel} route ${model.provider}/${model.id} is a frontier-model API channel; Fusion requires the Pi Anthropic or Codex subscription route`,
|
|
799
|
+
{ code: "model_unavailable", childCreated: false }
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
assertTrustedSubscriptionEndpoint(model, slotLabel, provider);
|
|
803
|
+
if (registry.isUsingOAuth === void 0) {
|
|
804
|
+
throw new FusionError(
|
|
805
|
+
`${slotLabel} route ${model.provider}/${model.id} cannot be admitted because ModelRegistry OAuth observation is unavailable`,
|
|
806
|
+
{ code: "model_unavailable", childCreated: false }
|
|
807
|
+
);
|
|
808
|
+
}
|
|
809
|
+
if (!registry.isUsingOAuth(model)) {
|
|
810
|
+
throw new FusionError(
|
|
811
|
+
`${slotLabel} route ${model.provider}/${model.id} is not using subscription OAuth; metered API credentials are forbidden for Fusion`,
|
|
812
|
+
{ code: "model_unavailable", childCreated: false }
|
|
813
|
+
);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
__name(assertSubscriptionRoute, "assertSubscriptionRoute");
|
|
817
|
+
function resolveSelection(selection, slotLabel, availableByKey, currentModel, thinkingLevel, registry) {
|
|
818
|
+
if (selection === CURRENT_MODEL_SELECTION) {
|
|
819
|
+
if (currentModel === void 0) {
|
|
820
|
+
throw new FusionError(`${slotLabel} uses $current but Pi has no current model`, {
|
|
821
|
+
code: "model_unavailable",
|
|
822
|
+
childCreated: false
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
const qualifiedId = qualifiedModelKey(currentModel);
|
|
826
|
+
const available = availableByKey.get(qualifiedId);
|
|
827
|
+
if (available === void 0) {
|
|
828
|
+
throw new FusionError(
|
|
829
|
+
`${slotLabel} current model is not available to child Pi: ${qualifiedId}`,
|
|
830
|
+
{
|
|
831
|
+
code: "model_unavailable",
|
|
832
|
+
childCreated: false
|
|
833
|
+
}
|
|
834
|
+
);
|
|
835
|
+
}
|
|
836
|
+
assertSubscriptionRoute(available, slotLabel, registry);
|
|
837
|
+
return {
|
|
838
|
+
selection,
|
|
839
|
+
source: "current",
|
|
840
|
+
provider: available.provider,
|
|
841
|
+
model: available.id,
|
|
842
|
+
qualifiedId,
|
|
843
|
+
thinkingLevel,
|
|
844
|
+
contextWindow: transportContextWindow(available, slotLabel),
|
|
845
|
+
maxOutputTokens: requireMaxOutputTokens(available, slotLabel)
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
const model = availableByKey.get(selection);
|
|
849
|
+
if (model === void 0) {
|
|
850
|
+
throw new FusionError(`${slotLabel} configured model is unavailable: ${selection}`, {
|
|
851
|
+
code: "model_unavailable",
|
|
852
|
+
childCreated: false
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
assertSubscriptionRoute(model, slotLabel, registry);
|
|
856
|
+
return {
|
|
857
|
+
selection,
|
|
858
|
+
source: "configured",
|
|
859
|
+
provider: model.provider,
|
|
860
|
+
model: model.id,
|
|
861
|
+
qualifiedId: selection,
|
|
862
|
+
thinkingLevel,
|
|
863
|
+
contextWindow: transportContextWindow(model, slotLabel),
|
|
864
|
+
maxOutputTokens: requireMaxOutputTokens(model, slotLabel)
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
__name(resolveSelection, "resolveSelection");
|
|
868
|
+
function resolveFusionModels(input) {
|
|
869
|
+
const availableByKey = modelIndex(input.modelRegistry.getAvailable());
|
|
870
|
+
const [first, second, third] = input.config.candidates;
|
|
871
|
+
const resolve = /* @__PURE__ */ __name((selection, slot) => resolveSelection(
|
|
872
|
+
selection,
|
|
873
|
+
slot,
|
|
874
|
+
availableByKey,
|
|
875
|
+
input.currentModel,
|
|
876
|
+
input.thinkingLevel,
|
|
877
|
+
input.modelRegistry
|
|
878
|
+
), "resolve");
|
|
879
|
+
return {
|
|
880
|
+
candidates: [
|
|
881
|
+
resolve(first, "candidate 1"),
|
|
882
|
+
resolve(second, "candidate 2"),
|
|
883
|
+
resolve(third, "candidate 3")
|
|
884
|
+
],
|
|
885
|
+
evaluator: resolve(input.config.evaluator, "evaluator"),
|
|
886
|
+
merger: resolve(input.config.merger, "merger")
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
__name(resolveFusionModels, "resolveFusionModels");
|
|
890
|
+
async function delay(ms) {
|
|
891
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
892
|
+
}
|
|
893
|
+
__name(delay, "delay");
|
|
894
|
+
async function withConfigLock(path, fn) {
|
|
895
|
+
const dir = dirname(path);
|
|
896
|
+
const lockPath = join(dir, `.${basename(path)}.lock`);
|
|
897
|
+
const started = Date.now();
|
|
898
|
+
let handle;
|
|
899
|
+
while (handle === void 0) {
|
|
900
|
+
try {
|
|
901
|
+
handle = await open(lockPath, "wx", 384);
|
|
902
|
+
} catch (error) {
|
|
903
|
+
if (!errorHasCode(error, "EEXIST")) throw error;
|
|
904
|
+
if (Date.now() - started > 1e4) {
|
|
905
|
+
throw new FusionError(`timed out waiting for fusion model config lock: ${path}`, {
|
|
906
|
+
code: "config_conflict",
|
|
907
|
+
childCreated: false
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
await delay(25);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
try {
|
|
914
|
+
await handle.writeFile(`${String(process.pid)}
|
|
915
|
+
`);
|
|
916
|
+
await handle.sync();
|
|
917
|
+
return await fn();
|
|
918
|
+
} finally {
|
|
919
|
+
await handle.close();
|
|
920
|
+
await rm(lockPath, { force: true });
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
__name(withConfigLock, "withConfigLock");
|
|
924
|
+
function prettyConfig(config) {
|
|
925
|
+
const sorted = {
|
|
926
|
+
schema_version: config.schema_version,
|
|
927
|
+
candidates: [...config.candidates],
|
|
928
|
+
evaluator: config.evaluator,
|
|
929
|
+
merger: config.merger
|
|
930
|
+
};
|
|
931
|
+
return `${JSON.stringify(sorted, null, 2)}
|
|
932
|
+
`;
|
|
933
|
+
}
|
|
934
|
+
__name(prettyConfig, "prettyConfig");
|
|
935
|
+
function revisionsMatch(expected, current) {
|
|
936
|
+
if (expected.path !== current.path) return false;
|
|
937
|
+
if (expected.exists !== current.exists) return false;
|
|
938
|
+
return expected.sha256 === current.sha256;
|
|
939
|
+
}
|
|
940
|
+
__name(revisionsMatch, "revisionsMatch");
|
|
941
|
+
async function saveFusionModelConfig(path, config, expectedRevision) {
|
|
942
|
+
parseFusionModelConfig(config);
|
|
943
|
+
const dir = dirname(path);
|
|
944
|
+
await mkdir(dir, { recursive: true, mode: 448 });
|
|
945
|
+
await chmod(dir, 448);
|
|
946
|
+
return withConfigLock(path, async () => {
|
|
947
|
+
const current = await revisionForPath(path);
|
|
948
|
+
if (!revisionsMatch(expectedRevision, current)) {
|
|
949
|
+
throw new FusionError(`fusion model config changed on disk: ${path}`, {
|
|
950
|
+
code: "config_conflict",
|
|
951
|
+
childCreated: false
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
await replaceFileDurable(path, prettyConfig(config));
|
|
955
|
+
return revisionForPath(path);
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
__name(saveFusionModelConfig, "saveFusionModelConfig");
|
|
959
|
+
function describeFusionModelConfig(config) {
|
|
960
|
+
return keysOf(config).join(", ");
|
|
961
|
+
}
|
|
962
|
+
__name(describeFusionModelConfig, "describeFusionModelConfig");
|
|
963
|
+
|
|
964
|
+
export {
|
|
965
|
+
FUSION_MODEL_CONFIG_FILE,
|
|
966
|
+
defaultFusionModelConfig,
|
|
967
|
+
fusionModelConfigPath,
|
|
968
|
+
parseFusionModelConfig,
|
|
969
|
+
loadFusionModelConfig,
|
|
970
|
+
resolveFusionModels,
|
|
971
|
+
saveFusionModelConfig,
|
|
972
|
+
describeFusionModelConfig
|
|
973
|
+
};
|