@xopcai/xopc 0.0.201 → 0.0.203
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/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{activity-store-DOhnAQOQ.js → activity-store-SZAay-ze.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-D8Cw0Mve.js → agent-avatar-dicebear-DPLJtxoS.js} +1 -1
- package/dist/gateway/static/root/assets/agents-DyjRuuRa.js +68 -0
- package/dist/gateway/static/root/assets/{api-E9Bk-Idp.js → api-C1cSt2ru.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-BubrReXg.js → app-management-settings-panel-B3PCMqor.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-BY5Az2p4.js → appearance-settings-txSx3REK.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-BEhBaooZ.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-BY8843mB.js → archive-plugin-B2VVc17j.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-DG45KScf.js → attachment-load-Crk7x8qR.js} +1 -1
- package/dist/gateway/static/root/assets/automations-page-BUC6FL6O.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-DGIF2ZAv.js → binary-plugins-CLlJsq5D.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-C1Qktr1g.js → block-editor-cJ5lVNAG.js} +46 -46
- package/dist/gateway/static/root/assets/browser-settings-page-Bq2m4VpX.js +8 -0
- package/dist/gateway/static/root/assets/{browser-workflow-inputs-D_jnndyz.js → browser-workflow-inputs-WRiFG88u.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-DyIRvPaq.js → browser-workflows-page-BHLdVoOC.js} +2 -2
- package/dist/gateway/static/root/assets/capabilities-settings-panel-BiQbVvYU.js +7 -0
- package/dist/gateway/static/root/assets/{capability-presets-api--tz0mGLY.js → capability-presets-api-DmElfgC9.js} +1 -1
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-CYlZQpLY.js +3 -0
- package/dist/gateway/static/root/assets/{channel-recipient-api-CkOKF9nc.js → channel-recipient-api-BUEOtPft.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-DlDiCMhO.js +1 -0
- package/dist/gateway/static/root/assets/channels-status-swr-Dm_-934M.js +1 -0
- package/dist/gateway/static/root/assets/{connectors-api-FBOe9SWC.js → connectors-api-BCdn44_o.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-Ce-eaPHw.js +2 -0
- package/dist/gateway/static/root/assets/cron-expression-D2hF3t68.js +2 -0
- package/dist/gateway/static/root/assets/{date-picker-Dtn7e6TW.js → date-picker-Dvjoq2mB.js} +1 -1
- package/dist/gateway/static/root/assets/dependency-picker-zv1OIhk3.js +1 -0
- package/dist/gateway/static/root/assets/desktop-pet-DJZhKLTb.js +1 -0
- package/dist/gateway/static/root/assets/{desktop-pet-settings-FDmaty3P.js → desktop-pet-settings-B3ubM-eY.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-X2e8xn8j.js → directory-picker-path-field-BZEJIWOT.js} +1 -1
- package/dist/gateway/static/root/assets/download-Dk-ZjtO6.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-Dx4MBfga.js → extension-debug-page-Bvq3E1A1.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-Bf_FEDhM.js → extension-page-CuCJjWNm.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-CrOgZxkf.js → extension-settings-page-CpTk_ajr.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-CZ4r-7qT.js → gateway-config-api-C2yM6qj7.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-Cv2ywpdb.js → gateway-config-swr-CN-JHMAh.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-DpWmVi0w.js → gateway-settings-COwi--2Q.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-undf-k5g.js → gateway-startup-retry-Dq1RyCjz.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-DSQZhSvT.js → heartbeat-settings-Dc6H4VGF.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-BB3RGxwm.js +3 -0
- package/dist/gateway/static/root/assets/index-CPTLS-Zn.js +85 -0
- package/dist/gateway/static/root/assets/index-Dm-cvIpl.css +2 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-Bc3Quw42.js → keyboard-shortcuts-settings-cue30Z5p.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-DfO6FOB9.js +2 -0
- package/dist/gateway/static/root/assets/local-apps-page-DKQSCsa0.js +1 -0
- package/dist/gateway/static/root/assets/{locale-store-CnamlR07.js → locale-store-81Gv0wwo.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-DODbODyl.js +2 -0
- package/dist/gateway/static/root/assets/{management-settings-CJmcaVje.js → management-settings--4H26QR-.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-AcuFp0TH.js → markdown-split-BTvpyjAi.js} +1 -1
- package/dist/gateway/static/root/assets/markdown-view-B12xeflb.css +1 -0
- package/dist/gateway/static/root/assets/markdown-view-B4iBrVWK.js +69 -0
- package/dist/gateway/static/root/assets/{media-plugins-BvFgsiJL.js → media-plugins-DrejWl8t.js} +1 -1
- package/dist/gateway/static/root/assets/messages-ELK_1h2D.js +3 -0
- package/dist/gateway/static/root/assets/{notes-page-IW7IQ9nJ.js → notes-page-DfSzeQKd.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-DxL4GhwV.js +4 -0
- package/dist/gateway/static/root/assets/plus-Q2yW6OE7.js +1 -0
- package/dist/gateway/static/root/assets/preview-open-alternatives-yjh1_7K3.js +1 -0
- package/dist/gateway/static/root/assets/{product-open-page-CWEzLykF.js → product-open-page-DopWBJLa.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-Bl3LJHZB.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-DStOErTC.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-C_hh9ztK.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DAohEZrX.js → runtime-tools-settings-panel-_dHhbYV2.js} +2 -2
- package/dist/gateway/static/root/assets/{schema-form-C_OBW8A5.js → schema-form-DZhORvJZ.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-DDY21KYw.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-BJrHIcw8.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-C7w2WS-A.js → settings-form-section-Du5eAgFS.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-zwibve4m.js → settings-loading-skeleton-DWS27sv1.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-B9W03dSW.js → settings-page-DPD0MwoN.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-CnXN4LH_.js +1 -0
- package/dist/gateway/static/root/assets/share-preview-page-D6HmH2ga.js +2 -0
- package/dist/gateway/static/root/assets/shares-settings-U3lvtO3Y.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-B6GiZgZU.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-XVO7d3fh.js +2 -0
- package/dist/gateway/static/root/assets/{skills-page.utils-D9QT5cxj.js → skills-page.utils-DwxIpWrI.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-c1HVtv1Y.js → system-settings-panel-BmKbxR8_.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-DA6ItYrc.js +1 -0
- package/dist/gateway/static/root/assets/{theme-store-BDyUTObE.js → theme-store-hOF81tUQ.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-D6UkH_Ga.js → use-autosave-GJfDpf66.js} +1 -1
- package/dist/gateway/static/root/assets/user-context-page-CQ1QrRE6.js +1 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-BOxkKbGh.js → voice-api-key-field-B0zve9EE.js} +1 -1
- package/dist/gateway/static/root/assets/work-discovery-overlay-DrIbHnBz.js +1 -0
- package/dist/gateway/static/root/assets/work-discovery-page-CQW8pPec.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-ZA3bP65I.js → workflow-run-setup-panel-D-_zQxim.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-O21l_f5c.js +5 -0
- package/dist/gateway/static/root/assets/{working-directory-picker-modal-BcyiDXU3.js → working-directory-picker-modal-5xYx48tV.js} +1 -1
- package/dist/gateway/static/root/assets/x-B_N4OPjy.js +1 -0
- package/dist/gateway/static/root/index.html +19 -14
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.js +2 -1
- package/dist/src/agent/embedded/run-for-session.js +3 -2
- package/dist/src/agent/embedded/run-turn.js +29 -16
- package/dist/src/agent/embedded/types.d.ts +2 -2
- package/dist/src/agent/embedded/xopc-stream-bridge.d.ts +2 -1
- package/dist/src/agent/embedded/xopc-stream-bridge.js +2 -2
- package/dist/src/agent/memory/context-budget.d.ts +6 -1
- package/dist/src/agent/memory/context-budget.js +94 -2
- package/dist/src/agent/prompt/cache-boundary.d.ts +2 -0
- package/dist/src/agent/prompt/cache-boundary.js +10 -1
- package/dist/src/agent/prompt/sections/project-context.d.ts +1 -4
- package/dist/src/agent/prompt/sections/project-context.js +6 -13
- package/dist/src/agent/prompt/service-prompt-builder.js +2 -1
- package/dist/src/agent/prompt/system-prompt.d.ts +1 -3
- package/dist/src/agent/prompt/system-prompt.js +6 -15
- package/dist/src/agent/tools/cache-stability.d.ts +3 -0
- package/dist/src/agent/tools/cache-stability.js +19 -0
- package/dist/src/agent/tools/factory.js +2 -1
- package/dist/src/agent-manifest/schema.d.ts +40 -20
- package/dist/src/agent-manifest/schema.js +4 -5
- package/dist/src/config/schema.d.ts +40 -20
- package/dist/src/extensions/types/providers.d.ts +0 -2
- package/dist/src/gateway/hono/lib/config-payload.d.ts +4 -1
- package/dist/src/gateway/hono/oauth-async.d.ts +1 -0
- package/dist/src/gateway/hono/oauth-async.js +14 -2
- package/dist/src/providers/extension-stream-bridge.js +0 -2
- package/dist/src/providers/google-managed-prompt-cache.d.ts +14 -0
- package/dist/src/providers/google-managed-prompt-cache.js +125 -0
- package/dist/src/providers/prompt-cache-fingerprint.d.ts +4 -0
- package/dist/src/providers/prompt-cache-fingerprint.js +44 -0
- package/dist/src/providers/prompt-cache-lifecycle.d.ts +9 -0
- package/dist/src/providers/prompt-cache-lifecycle.js +31 -0
- package/dist/src/providers/prompt-cache-observability.d.ts +20 -0
- package/dist/src/providers/prompt-cache-observability.js +44 -0
- package/dist/src/providers/prompt-cache-payload.d.ts +10 -3
- package/dist/src/providers/prompt-cache-payload.js +204 -31
- package/dist/src/providers/prompt-cache-plan.d.ts +15 -0
- package/dist/src/providers/prompt-cache-plan.js +29 -0
- package/package.json +3 -3
- package/dist/gateway/static/root/assets/agents-ANavi648.js +0 -68
- package/dist/gateway/static/root/assets/apps-page-CFh9MBxc.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-751CeNI3.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-CGAWs-TT.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-CghUK68J.js +0 -7
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-XsTfkvUn.js +0 -3
- package/dist/gateway/static/root/assets/channels-settings-DkoAZZMe.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-DNDvMWpl.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-e4vekkAu.js +0 -2
- package/dist/gateway/static/root/assets/cron-expression-Q4QaYjpI.js +0 -2
- package/dist/gateway/static/root/assets/dependency-picker-Br6nPaM6.js +0 -1
- package/dist/gateway/static/root/assets/desktop-pet-DzTM6aH8.js +0 -1
- package/dist/gateway/static/root/assets/home-page-L0uHiu0T.js +0 -3
- package/dist/gateway/static/root/assets/index-Bp8I_eX4.css +0 -1
- package/dist/gateway/static/root/assets/index-DRrjYYzZ.js +0 -152
- package/dist/gateway/static/root/assets/local-app-workbench-page-Copi3sdP.js +0 -2
- package/dist/gateway/static/root/assets/local-apps-page-CP9X_vtz.js +0 -1
- package/dist/gateway/static/root/assets/logs-page-DMKq6e29.js +0 -2
- package/dist/gateway/static/root/assets/messages-D7kOD_o_.js +0 -3
- package/dist/gateway/static/root/assets/notes-workbench-Zb8U0anO.js +0 -4
- package/dist/gateway/static/root/assets/preview-open-alternatives-C-b34dgQ.js +0 -1
- package/dist/gateway/static/root/assets/project-detail-page-BuIbLnan.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-BwUfRqNV.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-BTaXxcEi.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-BnHoTCD3.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-BTB_fxjt.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-C8Hec2Af.js +0 -1
- package/dist/gateway/static/root/assets/share-preview-page-6e3ks2be.js +0 -2
- package/dist/gateway/static/root/assets/shares-settings-Bwc5HfLI.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-D7kunhqy.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-WgkaNzpc.js +0 -2
- package/dist/gateway/static/root/assets/task-detail-page-CjP-6WVU.js +0 -1
- package/dist/gateway/static/root/assets/user-context-page-D8ZhPDNF.js +0 -1
- package/dist/gateway/static/root/assets/work-discovery-overlay-Dd19yK9t.js +0 -1
- package/dist/gateway/static/root/assets/work-discovery-page-DUkdJl1e.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-C2b5W5bw.js +0 -5
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
import { splitPromptCacheBoundary, stripPromptCacheBoundary } from "../agent/prompt/cache-boundary.js";
|
|
2
|
-
import {
|
|
2
|
+
import { canonicalizeCacheValue, digestCacheText } from "./prompt-cache-fingerprint.js";
|
|
3
|
+
import { resolvePromptCachePolicy, resolvePromptCacheProviderMode } from "./prompt-cache-plan.js";
|
|
4
|
+
import { applyGoogleManagedPromptCache } from "./google-managed-prompt-cache.js";
|
|
3
5
|
//#region src/providers/prompt-cache-payload.ts
|
|
4
6
|
function asRecord(value) {
|
|
5
7
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
6
8
|
}
|
|
7
|
-
function
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return model.provider === "openai" || model.baseUrl?.includes("api.openai.com") === true;
|
|
9
|
+
function buildPromptCacheKey(model, context, reasoning) {
|
|
10
|
+
const stablePrompt = context.systemPrompt ? splitPromptCacheBoundary(context.systemPrompt)?.stablePrefix ?? stripPromptCacheBoundary(context.systemPrompt) : "";
|
|
11
|
+
return `xopc-v2-${digestCacheText(`v2\0${model.provider}\0${model.id}\0${reasoning ?? ""}\0${stablePrompt}\0${canonicalizeCacheValue(context.tools ?? [])}`)}`;
|
|
11
12
|
}
|
|
12
|
-
function
|
|
13
|
+
function buildPromptCachePlan(model, context, policyInput, reasoning) {
|
|
14
|
+
const policy = resolvePromptCachePolicy(policyInput);
|
|
15
|
+
const providerMode = resolvePromptCacheProviderMode(model, policy);
|
|
16
|
+
return {
|
|
17
|
+
policy,
|
|
18
|
+
providerMode,
|
|
19
|
+
...providerMode === "implicit" || providerMode === "explicit" ? { cacheKey: buildPromptCacheKey(model, context, reasoning) } : {}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function splitAnthropicSystem(payload, lifetime) {
|
|
13
23
|
const record = asRecord(payload);
|
|
14
24
|
if (!record || !Array.isArray(record.system)) return payload;
|
|
15
25
|
let changed = false;
|
|
@@ -23,7 +33,11 @@ function splitAnthropicSystem(payload) {
|
|
|
23
33
|
return [{
|
|
24
34
|
...rest,
|
|
25
35
|
type: block.type ?? "text",
|
|
26
|
-
text: split.stablePrefix
|
|
36
|
+
text: split.stablePrefix,
|
|
37
|
+
cache_control: lifetime === "long" ? {
|
|
38
|
+
type: "ephemeral",
|
|
39
|
+
ttl: "1h"
|
|
40
|
+
} : { type: "ephemeral" }
|
|
27
41
|
}, ...split.dynamicSuffix ? [{
|
|
28
42
|
type: block.type ?? "text",
|
|
29
43
|
text: split.dynamicSuffix
|
|
@@ -34,6 +48,54 @@ function splitAnthropicSystem(payload) {
|
|
|
34
48
|
system
|
|
35
49
|
} : payload;
|
|
36
50
|
}
|
|
51
|
+
function addAnthropicHistoryBreakpoint(payload, lifetime) {
|
|
52
|
+
const record = asRecord(payload);
|
|
53
|
+
if (!record || !Array.isArray(record.messages)) return payload;
|
|
54
|
+
const messages = [...record.messages];
|
|
55
|
+
const cacheControl = lifetime === "long" ? {
|
|
56
|
+
type: "ephemeral",
|
|
57
|
+
ttl: "1h"
|
|
58
|
+
} : { type: "ephemeral" };
|
|
59
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
60
|
+
const message = asRecord(messages[index]);
|
|
61
|
+
if (!message || message.role !== "user") continue;
|
|
62
|
+
const blocks = Array.isArray(message.content) ? [...message.content] : void 0;
|
|
63
|
+
const containsToolResult = blocks?.some((block) => asRecord(block)?.type === "tool_result") ?? false;
|
|
64
|
+
if (index === messages.length - 1 && !containsToolResult) continue;
|
|
65
|
+
if (!blocks) {
|
|
66
|
+
if (typeof message.content !== "string") continue;
|
|
67
|
+
messages[index] = {
|
|
68
|
+
...message,
|
|
69
|
+
content: [{
|
|
70
|
+
type: "text",
|
|
71
|
+
text: message.content,
|
|
72
|
+
cache_control: cacheControl
|
|
73
|
+
}]
|
|
74
|
+
};
|
|
75
|
+
return {
|
|
76
|
+
...record,
|
|
77
|
+
messages
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
for (let blockIndex = blocks.length - 1; blockIndex >= 0; blockIndex -= 1) {
|
|
81
|
+
const block = asRecord(blocks[blockIndex]);
|
|
82
|
+
if (!block) continue;
|
|
83
|
+
blocks[blockIndex] = {
|
|
84
|
+
...block,
|
|
85
|
+
cache_control: cacheControl
|
|
86
|
+
};
|
|
87
|
+
messages[index] = {
|
|
88
|
+
...message,
|
|
89
|
+
content: blocks
|
|
90
|
+
};
|
|
91
|
+
return {
|
|
92
|
+
...record,
|
|
93
|
+
messages
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return payload;
|
|
98
|
+
}
|
|
37
99
|
function splitBedrockSystem(payload) {
|
|
38
100
|
const record = asRecord(payload);
|
|
39
101
|
if (!record || !Array.isArray(record.system)) return payload;
|
|
@@ -56,7 +118,7 @@ function splitBedrockSystem(payload) {
|
|
|
56
118
|
if (next?.cachePoint) {
|
|
57
119
|
system.push(next);
|
|
58
120
|
index += 1;
|
|
59
|
-
}
|
|
121
|
+
} else system.push({ cachePoint: { type: "default" } });
|
|
60
122
|
if (split.dynamicSuffix) system.push({ text: split.dynamicSuffix });
|
|
61
123
|
}
|
|
62
124
|
return changed ? {
|
|
@@ -64,20 +126,128 @@ function splitBedrockSystem(payload) {
|
|
|
64
126
|
system
|
|
65
127
|
} : payload;
|
|
66
128
|
}
|
|
67
|
-
function
|
|
68
|
-
|
|
69
|
-
if (
|
|
129
|
+
function addBedrockHistoryBreakpoint(payload) {
|
|
130
|
+
const record = asRecord(payload);
|
|
131
|
+
if (!record || !Array.isArray(record.messages)) return payload;
|
|
132
|
+
const messages = [...record.messages];
|
|
133
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
134
|
+
const message = asRecord(messages[index]);
|
|
135
|
+
if (!message || message.role !== "user" || !Array.isArray(message.content)) continue;
|
|
136
|
+
const content = [...message.content];
|
|
137
|
+
const containsToolResult = content.some((block) => "toolResult" in (asRecord(block) ?? {}));
|
|
138
|
+
if (index === messages.length - 1 && !containsToolResult) continue;
|
|
139
|
+
content.push({ cachePoint: { type: "default" } });
|
|
140
|
+
messages[index] = {
|
|
141
|
+
...message,
|
|
142
|
+
content
|
|
143
|
+
};
|
|
144
|
+
return {
|
|
145
|
+
...record,
|
|
146
|
+
messages
|
|
147
|
+
};
|
|
148
|
+
}
|
|
70
149
|
return payload;
|
|
71
150
|
}
|
|
72
|
-
function
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
151
|
+
function addBreakpointToContent(content) {
|
|
152
|
+
if (typeof content === "string") return [{
|
|
153
|
+
type: "input_text",
|
|
154
|
+
text: content,
|
|
155
|
+
prompt_cache_breakpoint: { mode: "explicit" }
|
|
156
|
+
}];
|
|
157
|
+
if (!Array.isArray(content)) return content;
|
|
158
|
+
const blocks = [...content];
|
|
159
|
+
for (let index = blocks.length - 1; index >= 0; index -= 1) {
|
|
160
|
+
const block = asRecord(blocks[index]);
|
|
161
|
+
if (!block) continue;
|
|
162
|
+
blocks[index] = {
|
|
163
|
+
...block,
|
|
164
|
+
prompt_cache_breakpoint: { mode: "explicit" }
|
|
165
|
+
};
|
|
166
|
+
return blocks;
|
|
167
|
+
}
|
|
168
|
+
return content;
|
|
77
169
|
}
|
|
78
|
-
function
|
|
79
|
-
|
|
80
|
-
|
|
170
|
+
function addOpenAIHistoryBreakpoint(items) {
|
|
171
|
+
if (!Array.isArray(items)) return items;
|
|
172
|
+
const next = [...items];
|
|
173
|
+
for (let index = next.length - 1; index >= 0; index -= 1) {
|
|
174
|
+
const item = asRecord(next[index]);
|
|
175
|
+
if (!item) continue;
|
|
176
|
+
if (item.type === "function_call_output") {
|
|
177
|
+
next[index] = {
|
|
178
|
+
...item,
|
|
179
|
+
output: addBreakpointToContent(item.output)
|
|
180
|
+
};
|
|
181
|
+
return next;
|
|
182
|
+
}
|
|
183
|
+
if (!("content" in item)) continue;
|
|
184
|
+
if (index === next.length - 1 && item.role === "user") continue;
|
|
185
|
+
const content = addBreakpointToContent(item.content);
|
|
186
|
+
if (content === item.content) continue;
|
|
187
|
+
next[index] = {
|
|
188
|
+
...item,
|
|
189
|
+
content
|
|
190
|
+
};
|
|
191
|
+
return next;
|
|
192
|
+
}
|
|
193
|
+
return items;
|
|
194
|
+
}
|
|
195
|
+
function applyOpenAIExplicitCache(payload, context, cacheKey) {
|
|
196
|
+
const record = asRecord(payload);
|
|
197
|
+
if (!record) return payload;
|
|
198
|
+
const split = splitPromptCacheBoundary(context.systemPrompt ?? "");
|
|
199
|
+
const stablePrompt = split?.stablePrefix ?? stripPromptCacheBoundary(context.systemPrompt ?? "");
|
|
200
|
+
const dynamicPrompt = split?.dynamicSuffix ?? "";
|
|
201
|
+
const stableContent = [{
|
|
202
|
+
type: "input_text",
|
|
203
|
+
text: stablePrompt,
|
|
204
|
+
prompt_cache_breakpoint: { mode: "explicit" }
|
|
205
|
+
}];
|
|
206
|
+
const dynamicContent = [{
|
|
207
|
+
type: "input_text",
|
|
208
|
+
text: dynamicPrompt
|
|
209
|
+
}];
|
|
210
|
+
if (Array.isArray(record.input)) {
|
|
211
|
+
const expectedInstructions = stripPromptCacheBoundary(context.systemPrompt ?? "");
|
|
212
|
+
const canReplaceInstructions = record.instructions === void 0 || record.instructions === expectedInstructions;
|
|
213
|
+
return {
|
|
214
|
+
...record,
|
|
215
|
+
...canReplaceInstructions ? { instructions: [{
|
|
216
|
+
type: "message",
|
|
217
|
+
role: "system",
|
|
218
|
+
content: stableContent
|
|
219
|
+
}, ...dynamicPrompt ? [{
|
|
220
|
+
type: "message",
|
|
221
|
+
role: "system",
|
|
222
|
+
content: dynamicContent
|
|
223
|
+
}] : []] } : {},
|
|
224
|
+
input: addOpenAIHistoryBreakpoint(record.input),
|
|
225
|
+
prompt_cache_key: cacheKey,
|
|
226
|
+
prompt_cache_options: {
|
|
227
|
+
mode: "explicit",
|
|
228
|
+
ttl: "30m"
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
...record,
|
|
234
|
+
prompt_cache_key: cacheKey,
|
|
235
|
+
prompt_cache_options: {
|
|
236
|
+
mode: "explicit",
|
|
237
|
+
ttl: "30m"
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
function transformPromptCachePayload(model, payload, plan = buildPromptCachePlan(model, {}), context = {}) {
|
|
242
|
+
if (plan.providerMode === "none" || plan.providerMode === "managed") return payload;
|
|
243
|
+
if (model.api === "anthropic-messages") return addAnthropicHistoryBreakpoint(splitAnthropicSystem(payload, plan.policy.lifetime), plan.policy.lifetime);
|
|
244
|
+
if (model.api === "bedrock-converse-stream") return addBedrockHistoryBreakpoint(splitBedrockSystem(payload));
|
|
245
|
+
if (plan.providerMode === "explicit" && plan.cacheKey) return applyOpenAIExplicitCache(payload, context, plan.cacheKey);
|
|
246
|
+
const record = asRecord(payload);
|
|
247
|
+
return record && plan.cacheKey ? {
|
|
248
|
+
...record,
|
|
249
|
+
prompt_cache_key: plan.cacheKey
|
|
250
|
+
} : payload;
|
|
81
251
|
}
|
|
82
252
|
function preparePromptCacheContext(model, context) {
|
|
83
253
|
if (model.api === "anthropic-messages" || model.api === "bedrock-converse-stream") return context;
|
|
@@ -87,24 +257,27 @@ function preparePromptCacheContext(model, context) {
|
|
|
87
257
|
systemPrompt: stripPromptCacheBoundary(context.systemPrompt)
|
|
88
258
|
};
|
|
89
259
|
}
|
|
90
|
-
function withPromptCachePayloadTransform(model, context, options) {
|
|
91
|
-
const
|
|
92
|
-
const openAiCacheKey = supportsPromptCacheKey(model) && options?.cacheRetention !== "none";
|
|
93
|
-
if (!explicitBoundary && !openAiCacheKey) return options;
|
|
260
|
+
function withPromptCachePayloadTransform(model, context, options, policyInput) {
|
|
261
|
+
const plan = buildPromptCachePlan(model, context, policyInput, options?.reasoning);
|
|
94
262
|
const upstream = options?.onPayload;
|
|
95
|
-
const
|
|
263
|
+
const cacheRetention = model.api === "anthropic-messages" || model.api === "bedrock-converse-stream" ? plan.providerMode === "none" ? "none" : plan.policy.lifetime : "none";
|
|
96
264
|
return {
|
|
97
265
|
...options,
|
|
266
|
+
cacheRetention,
|
|
98
267
|
onPayload: async (payload, payloadModel) => {
|
|
99
268
|
const upstreamPayload = await upstream?.(payload, payloadModel);
|
|
100
|
-
const transformed = transformPromptCachePayload(model, upstreamPayload === void 0 ? payload : upstreamPayload);
|
|
101
|
-
|
|
102
|
-
return
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
269
|
+
const transformed = transformPromptCachePayload(model, upstreamPayload === void 0 ? payload : upstreamPayload, plan, context);
|
|
270
|
+
if (plan.providerMode !== "managed") return transformed;
|
|
271
|
+
return applyGoogleManagedPromptCache({
|
|
272
|
+
model,
|
|
273
|
+
context,
|
|
274
|
+
payload: transformed,
|
|
275
|
+
policy: plan.policy,
|
|
276
|
+
apiKey: options?.apiKey,
|
|
277
|
+
fetchImpl: options?.fetch
|
|
278
|
+
});
|
|
106
279
|
}
|
|
107
280
|
};
|
|
108
281
|
}
|
|
109
282
|
//#endregion
|
|
110
|
-
export { buildPromptCacheKey, preparePromptCacheContext, transformPromptCachePayload, withPromptCachePayloadTransform };
|
|
283
|
+
export { buildPromptCacheKey, buildPromptCachePlan, preparePromptCacheContext, transformPromptCachePayload, withPromptCachePayloadTransform };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Api, Model } from '@earendil-works/pi-ai';
|
|
2
|
+
export interface PromptCachePolicy {
|
|
3
|
+
mode: 'off' | 'auto';
|
|
4
|
+
lifetime: 'short' | 'long';
|
|
5
|
+
}
|
|
6
|
+
export type PromptCacheProviderMode = 'none' | 'implicit' | 'explicit' | 'managed';
|
|
7
|
+
export interface PromptCachePlan {
|
|
8
|
+
policy: PromptCachePolicy;
|
|
9
|
+
providerMode: PromptCacheProviderMode;
|
|
10
|
+
cacheKey?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare const DEFAULT_PROMPT_CACHE_POLICY: PromptCachePolicy;
|
|
13
|
+
export declare function resolvePromptCachePolicy(policy?: Partial<PromptCachePolicy>): PromptCachePolicy;
|
|
14
|
+
export declare function isOfficialOpenAIModel(model: Model<Api>): boolean;
|
|
15
|
+
export declare function resolvePromptCacheProviderMode(model: Model<Api>, policy: PromptCachePolicy): PromptCacheProviderMode;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//#region src/providers/prompt-cache-plan.ts
|
|
2
|
+
const DEFAULT_PROMPT_CACHE_POLICY = {
|
|
3
|
+
mode: "auto",
|
|
4
|
+
lifetime: "short"
|
|
5
|
+
};
|
|
6
|
+
function resolvePromptCachePolicy(policy) {
|
|
7
|
+
return {
|
|
8
|
+
mode: policy?.mode ?? DEFAULT_PROMPT_CACHE_POLICY.mode,
|
|
9
|
+
lifetime: policy?.lifetime ?? DEFAULT_PROMPT_CACHE_POLICY.lifetime
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function isOfficialOpenAIModel(model) {
|
|
13
|
+
if (model.api === "openai-codex-responses" || model.api === "azure-openai-responses") return true;
|
|
14
|
+
if (model.api !== "openai-completions" && model.api !== "openai-responses") return false;
|
|
15
|
+
return model.provider === "openai" || model.baseUrl?.includes("api.openai.com") === true;
|
|
16
|
+
}
|
|
17
|
+
function supportsExplicitOpenAICache(model) {
|
|
18
|
+
return model.api === "openai-responses" && isOfficialOpenAIModel(model) && /^gpt-5\.6(?:-|$)/.test(model.id);
|
|
19
|
+
}
|
|
20
|
+
function resolvePromptCacheProviderMode(model, policy) {
|
|
21
|
+
if (policy.mode === "off") return "none";
|
|
22
|
+
if (supportsExplicitOpenAICache(model)) return "explicit";
|
|
23
|
+
if (isOfficialOpenAIModel(model)) return "implicit";
|
|
24
|
+
if (model.api === "anthropic-messages" || model.api === "bedrock-converse-stream") return "explicit";
|
|
25
|
+
if (model.api === "google-generative-ai") return "managed";
|
|
26
|
+
return "none";
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { DEFAULT_PROMPT_CACHE_POLICY, isOfficialOpenAIModel, resolvePromptCachePolicy, resolvePromptCacheProviderMode };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xopcai/xopc",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.203",
|
|
4
4
|
"description": "Local-first AI system that remembers context, coordinates AI, and sustains long-term progress.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -164,8 +164,8 @@
|
|
|
164
164
|
"vue": "^3.5.35",
|
|
165
165
|
"@xopcai/gateway-contract": "0.0.0",
|
|
166
166
|
"@xopcai/endpoint-tools-protocol": "0.0.0",
|
|
167
|
-
"@xopcai/realtime-
|
|
168
|
-
"@xopcai/realtime-
|
|
167
|
+
"@xopcai/realtime-client": "0.0.0",
|
|
168
|
+
"@xopcai/realtime-protocol": "0.0.0"
|
|
169
169
|
},
|
|
170
170
|
"scripts": {
|
|
171
171
|
"assets:brand": "node scripts/generate-brand-assets.mjs",
|