@hsupu/copilot-api 0.8.2 → 0.8.3
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/config.example.yaml +6 -2
- package/dist/main.mjs +90 -17
- package/dist/main.mjs.map +1 -1
- package/package.json +1 -1
package/config.example.yaml
CHANGED
|
@@ -129,8 +129,12 @@ anthropic:
|
|
|
129
129
|
# Inject Copilot tool_search helper when the model supports it.
|
|
130
130
|
tool_search: true
|
|
131
131
|
|
|
132
|
-
#
|
|
133
|
-
|
|
132
|
+
# Cache control mode for prompt caching.
|
|
133
|
+
# disabled: strip all cache_control fields (no caching)
|
|
134
|
+
# passthrough: forward client cache_control as-is
|
|
135
|
+
# sanitize: forward but normalize to { type: "ephemeral" } (strip non-standard fields like scope)
|
|
136
|
+
# proxied: proxy controls injection — auto-add breakpoints on tools/system (default)
|
|
137
|
+
cache_control: proxied
|
|
134
138
|
|
|
135
139
|
# Additional tool names that should never be deferred when tool_search is enabled.
|
|
136
140
|
# non_deferred_tools:
|
package/dist/main.mjs
CHANGED
|
@@ -98,7 +98,7 @@ const CONFIG_MANAGED_DEFAULTS = {
|
|
|
98
98
|
contextEditingKeepTools: 3,
|
|
99
99
|
contextEditingKeepThinking: 1,
|
|
100
100
|
toolSearchEnabled: true,
|
|
101
|
-
|
|
101
|
+
cacheControlMode: "proxied",
|
|
102
102
|
nonDeferredTools: [],
|
|
103
103
|
rewriteSystemReminders: false,
|
|
104
104
|
systemPromptOverrides: [],
|
|
@@ -125,7 +125,7 @@ function resetConfigManagedState() {
|
|
|
125
125
|
contextEditingKeepTools: CONFIG_MANAGED_DEFAULTS.contextEditingKeepTools,
|
|
126
126
|
contextEditingKeepThinking: CONFIG_MANAGED_DEFAULTS.contextEditingKeepThinking,
|
|
127
127
|
toolSearchEnabled: CONFIG_MANAGED_DEFAULTS.toolSearchEnabled,
|
|
128
|
-
|
|
128
|
+
cacheControlMode: CONFIG_MANAGED_DEFAULTS.cacheControlMode,
|
|
129
129
|
nonDeferredTools: [...CONFIG_MANAGED_DEFAULTS.nonDeferredTools],
|
|
130
130
|
rewriteSystemReminders: CONFIG_MANAGED_DEFAULTS.rewriteSystemReminders,
|
|
131
131
|
systemPromptOverrides: [...CONFIG_MANAGED_DEFAULTS.systemPromptOverrides],
|
|
@@ -161,7 +161,7 @@ const mutableState = {
|
|
|
161
161
|
contextEditingKeepTools: CONFIG_MANAGED_DEFAULTS.contextEditingKeepTools,
|
|
162
162
|
contextEditingKeepThinking: CONFIG_MANAGED_DEFAULTS.contextEditingKeepThinking,
|
|
163
163
|
toolSearchEnabled: CONFIG_MANAGED_DEFAULTS.toolSearchEnabled,
|
|
164
|
-
|
|
164
|
+
cacheControlMode: CONFIG_MANAGED_DEFAULTS.cacheControlMode,
|
|
165
165
|
nonDeferredTools: [...CONFIG_MANAGED_DEFAULTS.nonDeferredTools],
|
|
166
166
|
stripServerTools: CONFIG_MANAGED_DEFAULTS.stripServerTools,
|
|
167
167
|
immutableThinkingMessages: CONFIG_MANAGED_DEFAULTS.immutableThinkingMessages,
|
|
@@ -1766,7 +1766,12 @@ async function applyConfigToState() {
|
|
|
1766
1766
|
if (a.context_editing_keep_tools !== void 0) setAnthropicBehavior({ contextEditingKeepTools: a.context_editing_keep_tools });
|
|
1767
1767
|
if (a.context_editing_keep_thinking !== void 0) setAnthropicBehavior({ contextEditingKeepThinking: a.context_editing_keep_thinking });
|
|
1768
1768
|
if (a.tool_search !== void 0) setAnthropicBehavior({ toolSearchEnabled: a.tool_search });
|
|
1769
|
-
if (a.
|
|
1769
|
+
if (a.cache_control !== void 0) setAnthropicBehavior({ cacheControlMode: a.cache_control });
|
|
1770
|
+
else if (a.auto_cache_control !== void 0) {
|
|
1771
|
+
const mapped = a.auto_cache_control ? "proxied" : "disabled";
|
|
1772
|
+
consola.warn(`[Config] anthropic.auto_cache_control is deprecated, use cache_control: "${mapped}" instead`);
|
|
1773
|
+
setAnthropicBehavior({ cacheControlMode: mapped });
|
|
1774
|
+
}
|
|
1770
1775
|
if (Array.isArray(a.non_deferred_tools)) setAnthropicBehavior({ nonDeferredTools: a.non_deferred_tools });
|
|
1771
1776
|
if (a.rewrite_system_reminders !== void 0) {
|
|
1772
1777
|
if (typeof a.rewrite_system_reminders === "boolean") setAnthropicBehavior({ rewriteSystemReminders: a.rewrite_system_reminders });
|
|
@@ -4709,20 +4714,29 @@ function finalize(tracker) {
|
|
|
4709
4714
|
function handleShutdownSignal(signal, opts) {
|
|
4710
4715
|
const shutdownFn = opts?.gracefulShutdownFn ?? ((shutdownSignal) => gracefulShutdown(shutdownSignal));
|
|
4711
4716
|
const exitFn = opts?.exitFn ?? ((code) => process.exit(code));
|
|
4712
|
-
if (_isShuttingDown) {
|
|
4713
|
-
|
|
4717
|
+
if (_isShuttingDown) switch (shutdownPhase) {
|
|
4718
|
+
case "phase1":
|
|
4719
|
+
consola.warn("Signal received during Phase 1 setup, waiting for shutdown to proceed");
|
|
4720
|
+
return shutdownPromise ?? void 0;
|
|
4721
|
+
case "phase2":
|
|
4714
4722
|
consola.warn("Second signal received, escalating shutdown to abort active requests");
|
|
4715
4723
|
shutdownDrainAbortController?.abort();
|
|
4716
4724
|
return shutdownPromise ?? void 0;
|
|
4717
|
-
|
|
4718
|
-
if (shutdownPhase === "phase3") {
|
|
4725
|
+
case "phase3":
|
|
4719
4726
|
consola.warn("Additional signal received, escalating shutdown to force-close remaining requests");
|
|
4720
4727
|
shutdownDrainAbortController?.abort();
|
|
4721
4728
|
return shutdownPromise ?? void 0;
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4729
|
+
case "phase4":
|
|
4730
|
+
consola.warn("Additional signal received during forced shutdown, exiting immediately");
|
|
4731
|
+
exitFn(1);
|
|
4732
|
+
return shutdownPromise ?? void 0;
|
|
4733
|
+
case "finalized":
|
|
4734
|
+
consola.info("Signal received after shutdown finalized, ignoring");
|
|
4735
|
+
return shutdownPromise ?? void 0;
|
|
4736
|
+
default:
|
|
4737
|
+
consola.warn("Signal received in unexpected shutdown phase, exiting immediately");
|
|
4738
|
+
exitFn(1);
|
|
4739
|
+
return shutdownPromise ?? void 0;
|
|
4726
4740
|
}
|
|
4727
4741
|
shutdownPromise = shutdownFn(signal).catch((error) => {
|
|
4728
4742
|
consola.error("Fatal error during shutdown:", error);
|
|
@@ -5500,7 +5514,7 @@ const setupClaudeCode = defineCommand({
|
|
|
5500
5514
|
});
|
|
5501
5515
|
//#endregion
|
|
5502
5516
|
//#region package.json
|
|
5503
|
-
var version = "0.8.
|
|
5517
|
+
var version = "0.8.3";
|
|
5504
5518
|
//#endregion
|
|
5505
5519
|
//#region src/lib/system-prompt/override.ts
|
|
5506
5520
|
/**
|
|
@@ -9124,7 +9138,7 @@ configRoutes.get("/", (c) => {
|
|
|
9124
9138
|
contextEditingKeepTools: state.contextEditingKeepTools,
|
|
9125
9139
|
contextEditingKeepThinking: state.contextEditingKeepThinking,
|
|
9126
9140
|
toolSearchEnabled: state.toolSearchEnabled,
|
|
9127
|
-
|
|
9141
|
+
cacheControlMode: state.cacheControlMode,
|
|
9128
9142
|
nonDeferredTools: state.nonDeferredTools,
|
|
9129
9143
|
rewriteSystemReminders: serializeRewriteSystemReminders(state.rewriteSystemReminders),
|
|
9130
9144
|
stripReadToolResultTags: state.stripReadToolResultTags,
|
|
@@ -9227,6 +9241,7 @@ const ANTHROPIC_KEYS = new Set([
|
|
|
9227
9241
|
"context_editing_keep_tools",
|
|
9228
9242
|
"context_editing_keep_thinking",
|
|
9229
9243
|
"tool_search",
|
|
9244
|
+
"cache_control",
|
|
9230
9245
|
"auto_cache_control",
|
|
9231
9246
|
"non_deferred_tools",
|
|
9232
9247
|
"rewrite_system_reminders"
|
|
@@ -9306,7 +9321,20 @@ function validateAnthropic(value, details) {
|
|
|
9306
9321
|
if (hasOwn(value, "context_editing_keep_tools")) validateNonNegativeInteger(value.context_editing_keep_tools, "anthropic.context_editing_keep_tools", details);
|
|
9307
9322
|
if (hasOwn(value, "context_editing_keep_thinking")) validateNonNegativeInteger(value.context_editing_keep_thinking, "anthropic.context_editing_keep_thinking", details);
|
|
9308
9323
|
if (hasOwn(value, "tool_search")) validateBoolean(value.tool_search, "anthropic.tool_search", details);
|
|
9309
|
-
if (hasOwn(value, "
|
|
9324
|
+
if (hasOwn(value, "cache_control")) {
|
|
9325
|
+
const valid = [
|
|
9326
|
+
"disabled",
|
|
9327
|
+
"passthrough",
|
|
9328
|
+
"sanitize",
|
|
9329
|
+
"proxied"
|
|
9330
|
+
];
|
|
9331
|
+
if (!valid.includes(value.cache_control)) details.push({
|
|
9332
|
+
field: "anthropic.cache_control",
|
|
9333
|
+
message: `Must be one of: ${valid.join(", ")}`,
|
|
9334
|
+
value: value.cache_control
|
|
9335
|
+
});
|
|
9336
|
+
}
|
|
9337
|
+
if (hasOwn(value, "auto_cache_control")) validateBoolean(value.auto_cache_control, "anthropic.auto_cache_control (deprecated)", details);
|
|
9310
9338
|
if (hasOwn(value, "non_deferred_tools")) validateStringArray(value.non_deferred_tools, "anthropic.non_deferred_tools", details);
|
|
9311
9339
|
if (hasOwn(value, "rewrite_system_reminders")) {
|
|
9312
9340
|
const rewrite = value.rewrite_system_reminders;
|
|
@@ -11255,7 +11283,7 @@ const EPHEMERAL_CACHE_CONTROL = { type: "ephemeral" };
|
|
|
11255
11283
|
function prepareAnthropicRequest(payload, opts) {
|
|
11256
11284
|
const wire = buildWirePayload(payload);
|
|
11257
11285
|
adjustThinkingBudget(wire, opts?.resolvedModel);
|
|
11258
|
-
|
|
11286
|
+
applyCacheControlMode(wire);
|
|
11259
11287
|
const model = wire.model;
|
|
11260
11288
|
const messages = wire.messages;
|
|
11261
11289
|
const thinking = wire.thinking;
|
|
@@ -11316,8 +11344,29 @@ function adjustThinkingBudget(wire, resolvedModel) {
|
|
|
11316
11344
|
consola.debug(`[DirectAnthropic] Capped thinking.budget_tokens: ${budgetTokens} → ${adjusted} (max_tokens=${maxTokens})`);
|
|
11317
11345
|
}
|
|
11318
11346
|
}
|
|
11347
|
+
/**
|
|
11348
|
+
* Dispatch cache_control handling based on the configured mode.
|
|
11349
|
+
* - disabled: strip all cache_control from the wire payload
|
|
11350
|
+
* - passthrough: leave everything as-is
|
|
11351
|
+
* - sanitize: normalize all cache_control to { type: "ephemeral" }
|
|
11352
|
+
* - proxied: strip client cache_control then auto-inject breakpoints
|
|
11353
|
+
*/
|
|
11354
|
+
function applyCacheControlMode(wire) {
|
|
11355
|
+
switch (state.cacheControlMode) {
|
|
11356
|
+
case "disabled":
|
|
11357
|
+
walkCacheControl(wire, () => void 0);
|
|
11358
|
+
break;
|
|
11359
|
+
case "passthrough": break;
|
|
11360
|
+
case "sanitize":
|
|
11361
|
+
walkCacheControl(wire, () => EPHEMERAL_CACHE_CONTROL);
|
|
11362
|
+
break;
|
|
11363
|
+
case "proxied":
|
|
11364
|
+
walkCacheControl(wire, () => void 0);
|
|
11365
|
+
addToolsAndSystemCacheControl(wire);
|
|
11366
|
+
break;
|
|
11367
|
+
}
|
|
11368
|
+
}
|
|
11319
11369
|
function addToolsAndSystemCacheControl(wire) {
|
|
11320
|
-
if (!state.autoCacheControl) return;
|
|
11321
11370
|
let remaining = CACHE_CONTROL_BREAKPOINT_LIMIT - countExistingCacheBreakpoints(wire);
|
|
11322
11371
|
if (remaining <= 0) return;
|
|
11323
11372
|
const toolResult = addToolCacheControl(wire.tools, remaining);
|
|
@@ -11387,6 +11436,30 @@ function findLastIndex(items, predicate) {
|
|
|
11387
11436
|
for (let index = items.length - 1; index >= 0; index--) if (predicate(items[index])) return index;
|
|
11388
11437
|
return -1;
|
|
11389
11438
|
}
|
|
11439
|
+
/**
|
|
11440
|
+
* Walk all cache_control occurrences in the wire payload (system, messages, tools)
|
|
11441
|
+
* and apply a handler. The handler receives the existing cache_control value and returns:
|
|
11442
|
+
* - undefined: delete the cache_control field
|
|
11443
|
+
* - an object: replace the cache_control field with this value
|
|
11444
|
+
*/
|
|
11445
|
+
function walkCacheControl(wire, handler) {
|
|
11446
|
+
for (const key of [
|
|
11447
|
+
"system",
|
|
11448
|
+
"messages",
|
|
11449
|
+
"tools"
|
|
11450
|
+
]) if (Array.isArray(wire[key])) walkCacheControlArray(wire[key], handler);
|
|
11451
|
+
}
|
|
11452
|
+
function walkCacheControlArray(items, handler) {
|
|
11453
|
+
for (const item of items) {
|
|
11454
|
+
if (!item || typeof item !== "object") continue;
|
|
11455
|
+
if ("cache_control" in item && item.cache_control) {
|
|
11456
|
+
const replacement = handler(item.cache_control);
|
|
11457
|
+
if (replacement === void 0) delete item.cache_control;
|
|
11458
|
+
else item.cache_control = replacement;
|
|
11459
|
+
}
|
|
11460
|
+
if (Array.isArray(item.content)) walkCacheControlArray(item.content, handler);
|
|
11461
|
+
}
|
|
11462
|
+
}
|
|
11390
11463
|
//#endregion
|
|
11391
11464
|
//#region src/lib/anthropic/client.ts
|
|
11392
11465
|
/**
|