@vellumai/assistant 0.8.11 → 0.8.12-staging.2
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/ARCHITECTURE.md +15 -17
- package/README.md +0 -6
- package/bun.lock +6 -122
- package/node_modules/@vellumai/gateway-client/bun.lock +1 -0
- package/node_modules/@vellumai/gateway-client/package.json +3 -1
- package/node_modules/@vellumai/gateway-client/src/__tests__/gateway-client.test.ts +1 -1
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +87 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +3 -5
- package/openapi.yaml +633 -4
- package/package.json +1 -3
- package/src/__tests__/adaptive-thinking-repair.test.ts +185 -0
- package/src/__tests__/agent-loop-compaction-events.test.ts +7 -6
- package/src/__tests__/anthropic-provider.test.ts +129 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +4 -1
- package/src/__tests__/btw-routes.test.ts +7 -34
- package/src/__tests__/checker.test.ts +6 -12
- package/src/__tests__/config-loader-backfill.test.ts +4 -2
- package/src/__tests__/config-loader-quarantine-notice.test.ts +167 -0
- package/src/__tests__/config-watcher.test.ts +2 -2
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
- package/src/__tests__/conversation-error.test.ts +2 -6
- package/src/__tests__/conversation-history-web-search.test.ts +8 -0
- package/src/__tests__/conversation-title-service.test.ts +2 -1
- package/src/__tests__/credential-security-invariants.test.ts +1 -1
- package/src/__tests__/disk-pressure-tools.test.ts +1 -1
- package/src/__tests__/exploration-drift-hook.test.ts +692 -0
- package/src/__tests__/filing-service.test.ts +8 -3
- package/src/__tests__/guardian-action-store.test.ts +0 -167
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +1 -1
- package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -1
- package/src/__tests__/heartbeat-service.test.ts +5 -2
- package/src/__tests__/identity-intro-cache.test.ts +12 -5
- package/src/__tests__/identity-routes.test.ts +16 -57
- package/src/__tests__/injector-chain.test.ts +8 -3
- package/src/__tests__/injector-config-quarantine-notice.test.ts +115 -0
- package/src/__tests__/llm-catalog-parity.test.ts +16 -0
- package/src/__tests__/llm-usage-store.test.ts +11 -0
- package/src/__tests__/log-export-workspace.test.ts +468 -3
- package/src/__tests__/memory-v2-static-injector.test.ts +22 -0
- package/src/__tests__/model-intents.test.ts +1 -1
- package/src/__tests__/oauth-cli.test.ts +19 -8
- package/src/__tests__/openai-provider.test.ts +34 -0
- package/src/__tests__/prechat-onboarding-contract.test.ts +0 -1
- package/src/__tests__/recurrence-engine.test.ts +45 -0
- package/src/__tests__/schedule-routes.test.ts +34 -0
- package/src/__tests__/scheduler-disk-pressure.test.ts +1 -1
- package/src/__tests__/script-proxy-conversation-manager.test.ts +10 -5
- package/src/__tests__/secret-fixtures.ts +20 -0
- package/src/__tests__/skill-tool-factory.test.ts +49 -0
- package/src/__tests__/subagent-role-registry.test.ts +24 -1
- package/src/__tests__/subagent-tools.test.ts +1 -0
- package/src/__tests__/system-prompt.test.ts +109 -11
- package/src/__tests__/tool-approval-handler.test.ts +85 -0
- package/src/__tests__/tool-audit-listener.test.ts +86 -0
- package/src/__tests__/tool-error-hook.test.ts +1 -0
- package/src/__tests__/tool-result-spool.test.ts +337 -0
- package/src/__tests__/tool-result-truncate-hook.test.ts +1 -0
- package/src/__tests__/validate-input.test.ts +95 -1
- package/src/__tests__/workspace-migration-098-remove-stale-updates-bulletin-file.test.ts +65 -0
- package/src/__tests__/workspace-migration-099-disable-cache-one-shot-callsites.test.ts +139 -0
- package/src/__tests__/workspace-migration-100-upgrade-quality-profile-to-fable-5.test.ts +174 -0
- package/src/__tests__/workspace-migration-101-upgrade-balanced-economy-to-minimax-m3.test.ts +162 -0
- package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +45 -95
- package/src/acp/__tests__/agent-process.test.ts +315 -2
- package/src/acp/__tests__/prepare-agent-env.test.ts +79 -5
- package/src/acp/agent-process.ts +163 -34
- package/src/acp/prepare-agent-env.ts +55 -15
- package/src/agent/loop.ts +81 -24
- package/src/api/events/usage-progress.ts +28 -0
- package/src/api/index.ts +6 -0
- package/src/background-wake/wake-intent-hooks.test.ts +2 -0
- package/src/bundler/app-bundler.ts +25 -42
- package/src/bundler/app-compiler.ts +8 -0
- package/src/calls/call-controller.ts +1 -1
- package/src/cli/commands/plugins.ts +248 -15
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +318 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +16 -9
- package/src/cli/lib/__tests__/plugin-artifact.test.ts +183 -0
- package/src/cli/lib/__tests__/plugin-details.test.ts +158 -0
- package/src/cli/lib/__tests__/plugin-fingerprint.test.ts +245 -0
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +307 -0
- package/src/cli/lib/inspect-plugin.ts +252 -0
- package/src/cli/lib/install-from-github.ts +214 -21
- package/src/cli/lib/list-installed-plugins.ts +17 -6
- package/src/cli/lib/plugin-artifact.ts +103 -0
- package/src/cli/lib/plugin-details.ts +18 -1
- package/src/cli/lib/plugin-fingerprint.ts +197 -0
- package/src/cli/lib/upgrade-plugin.ts +225 -0
- package/src/config/bundled-skills/subagent/SKILL.md +2 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +8 -2
- package/src/config/call-site-defaults.ts +13 -2
- package/src/config/feature-flag-registry.json +8 -16
- package/src/config/loader.ts +52 -59
- package/src/config/schema.ts +0 -2
- package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
- package/src/config/schemas/__tests__/memory-v3.test.ts +10 -0
- package/src/config/schemas/llm.ts +10 -0
- package/src/config/schemas/memory-v2.ts +13 -0
- package/src/config/schemas/memory-v3.ts +92 -0
- package/src/config/seed-inference-profiles.ts +4 -8
- package/src/context/post-turn-tool-result-truncation.ts +32 -18
- package/src/context/tool-result-spool.ts +104 -0
- package/src/credential-execution/feature-gates.ts +0 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +41 -16
- package/src/daemon/conversation-error.ts +6 -15
- package/src/daemon/conversation.ts +9 -0
- package/src/daemon/disk-pressure-policy.ts +0 -1
- package/src/daemon/lifecycle.ts +1 -20
- package/src/daemon/message-types/conversations.ts +2 -15
- package/src/daemon/trust-context.ts +1 -1
- package/src/events/tool-audit-listener.ts +40 -9
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -1
- package/src/home/__tests__/home-content-refresh.test.ts +114 -0
- package/src/home/__tests__/suggested-prompts.test.ts +86 -5
- package/src/home/home-content-refresh.ts +43 -31
- package/src/home/home-greeting-cache.ts +8 -1
- package/src/home/home-greeting.ts +13 -9
- package/src/home/suggested-prompts.ts +77 -24
- package/src/ipc/routes/trust-rules.test.ts +66 -72
- package/src/media/image-credentials.ts +2 -2
- package/src/memory/__tests__/compaction-log-store-clickhouse.test.ts +432 -0
- package/src/memory/{compaction-log-writer-clickhouse.ts → compaction-log-store-clickhouse.ts} +264 -55
- package/src/memory/conversation-attention-store.ts +1 -0
- package/src/memory/conversation-bootstrap.ts +18 -9
- package/src/memory/conversation-crud.ts +12 -2
- package/src/memory/conversation-title-service.ts +53 -9
- package/src/memory/delivery-channels.ts +0 -69
- package/src/memory/graph/extraction-job.ts +0 -15
- package/src/memory/guardian-action-store.ts +1 -376
- package/src/memory/llm-usage-store.ts +5 -1
- package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +2 -2
- package/src/memory/v2/__tests__/consolidation-job.test.ts +183 -2
- package/src/memory/v2/__tests__/injection.test.ts +70 -0
- package/src/memory/v2/__tests__/static-context.test.ts +12 -0
- package/src/memory/v2/consolidation-job.ts +93 -9
- package/src/memory/v2/injection.ts +53 -0
- package/src/memory/v2/prompts/consolidation.ts +1 -0
- package/src/memory/v2/static-context.ts +13 -1
- package/src/memory/v2/sweep-job.ts +1 -1
- package/src/memory/v2/types.ts +5 -0
- package/src/plugin-api/types.ts +7 -0
- package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +300 -0
- package/src/plugins/defaults/exploration-drift/package.json +15 -0
- package/src/plugins/defaults/index.ts +25 -0
- package/src/plugins/defaults/memory-retrieval/injectors.ts +132 -4
- package/src/plugins/defaults/memory-v3-shadow/__tests__/card.test.ts +92 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +2 -1
- package/src/plugins/defaults/memory-v3-shadow/__tests__/fresh-set.test.ts +52 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/live-integration.test.ts +2 -1
- package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +136 -5
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +17 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +6 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +5 -1
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +68 -4
- package/src/plugins/defaults/memory-v3-shadow/card.ts +49 -5
- package/src/plugins/defaults/memory-v3-shadow/fresh-set.ts +59 -0
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +4 -2
- package/src/plugins/defaults/memory-v3-shadow/learned-edges.test.ts +169 -0
- package/src/plugins/defaults/memory-v3-shadow/learned-edges.ts +178 -0
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +115 -26
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +13 -9
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +144 -22
- package/src/plugins/defaults/memory-v3-shadow/types.ts +24 -6
- package/src/plugins/defaults/title-generate/hooks/stop.ts +13 -0
- package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +16 -0
- package/src/prompts/cache-boundary.ts +17 -0
- package/src/prompts/sections.ts +50 -17
- package/src/prompts/system-prompt.ts +12 -4
- package/src/prompts/templates/system-sections.ts +22 -0
- package/src/providers/__tests__/unparseable-tool-args.test.ts +53 -0
- package/src/providers/anthropic/client.ts +74 -28
- package/src/providers/gemini/client.ts +5 -1
- package/src/providers/minimax/client.ts +9 -0
- package/src/providers/model-catalog.ts +28 -0
- package/src/providers/model-intents.ts +3 -3
- package/src/providers/openai/chat-completions-provider.ts +4 -2
- package/src/providers/openai/responses-provider.ts +7 -2
- package/src/providers/retry.ts +8 -0
- package/src/providers/types.ts +11 -0
- package/src/providers/unparseable-tool-args.ts +56 -0
- package/src/runtime/AGENTS.md +6 -0
- package/src/runtime/__tests__/agent-wake.test.ts +2 -2
- package/src/runtime/agent-wake.ts +5 -5
- package/src/runtime/background-job-runner.ts +2 -2
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +150 -3
- package/src/runtime/migrations/vbundle-import-analyzer.ts +29 -6
- package/src/runtime/migrations/vbundle-import-policy.ts +23 -0
- package/src/runtime/migrations/vbundle-importer.ts +9 -4
- package/src/runtime/migrations/vbundle-streaming-importer.ts +8 -3
- package/src/runtime/pre-first-message-gate.ts +1 -1
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +241 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +132 -0
- package/src/runtime/routes/__tests__/gateway-log-routes.test.ts +97 -185
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +17 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +348 -0
- package/src/runtime/routes/__tests__/task-routes.test.ts +3 -3
- package/src/runtime/routes/btw-routes.ts +0 -14
- package/src/runtime/routes/conversation-compaction-routes.ts +86 -19
- package/src/runtime/routes/conversation-list-routes.ts +77 -5
- package/src/runtime/routes/conversation-management-routes.ts +54 -0
- package/src/runtime/routes/conversation-query-routes.ts +79 -4
- package/src/runtime/routes/gateway-log-routes.ts +14 -64
- package/src/runtime/routes/home-feed-routes.ts +10 -0
- package/src/runtime/routes/identity-intro-cache.ts +1 -1
- package/src/runtime/routes/identity-routes.ts +76 -20
- package/src/runtime/routes/inbound-message-handler.ts +0 -36
- package/src/runtime/routes/log-export-routes.ts +143 -96
- package/src/runtime/routes/plugins-routes.ts +380 -0
- package/src/runtime/routes/redact-staged-export.ts +259 -0
- package/src/runtime/routes/schedule-routes.ts +19 -2
- package/src/runtime/routes/trust-rules-routes.ts +14 -67
- package/src/schedule/recurrence-engine.ts +34 -0
- package/src/schedule/scheduler.ts +1 -0
- package/src/security/redact-json.ts +61 -0
- package/src/skills/validate-input.ts +41 -1
- package/src/subagent/types.ts +26 -1
- package/src/telemetry/types.ts +15 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +6 -1
- package/src/telemetry/usage-telemetry-reporter.ts +1 -0
- package/src/tools/apps/executors.ts +1 -1
- package/src/tools/skills/skill-tool-factory.ts +19 -8
- package/src/tools/tool-approval-handler.ts +31 -0
- package/src/usage/types.ts +8 -1
- package/src/util/platform.ts +16 -0
- package/src/watcher/engine.ts +1 -0
- package/src/workspace/adaptive-thinking-repair.ts +113 -0
- package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +70 -67
- package/src/workspace/migrations/098-remove-stale-updates-bulletin-file.ts +31 -0
- package/src/workspace/migrations/099-disable-cache-one-shot-callsites.ts +81 -0
- package/src/workspace/migrations/100-upgrade-quality-profile-to-fable-5.ts +86 -0
- package/src/workspace/migrations/101-upgrade-balanced-economy-to-minimax-m3.ts +70 -0
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/__tests__/config-loader-quarantine-bulletin.test.ts +0 -202
- package/src/__tests__/conversation-starters-cadence.test.ts +0 -161
- package/src/__tests__/guardian-action-followup-executor.test.ts +0 -322
- package/src/__tests__/guardian-action-followup-store.test.ts +0 -373
- package/src/__tests__/guardian-action-late-reply.test.ts +0 -1083
- package/src/__tests__/update-bulletin-job.test.ts +0 -292
- package/src/config/schemas/updates.ts +0 -14
- package/src/memory/__tests__/compaction-log-writer-clickhouse.test.ts +0 -227
- package/src/memory/conversation-starters-cadence.ts +0 -78
- package/src/prompts/update-bulletin-job.ts +0 -180
- package/src/runtime/guardian-action-followup-executor.ts +0 -306
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Anthropic from "@anthropic-ai/sdk";
|
|
2
2
|
|
|
3
|
+
import { SYSTEM_PROMPT_CACHE_BOUNDARY } from "../../prompts/cache-boundary.js";
|
|
3
4
|
import { isAbortReason } from "../../util/abort-reasons.js";
|
|
4
5
|
import { ProviderError } from "../../util/errors.js";
|
|
5
6
|
import { getLogger } from "../../util/logger.js";
|
|
@@ -809,6 +810,12 @@ export class AnthropicProvider implements Provider {
|
|
|
809
810
|
const mutableLatestUserMessage =
|
|
810
811
|
(config as Record<string, unknown> | undefined)
|
|
811
812
|
?.mutableLatestUserMessage === true;
|
|
813
|
+
// Full prompt-caching opt-out: send no cache breakpoints at all and strip
|
|
814
|
+
// caller-stamped block-level markers. Resolved per call site (see
|
|
815
|
+
// `disableCache` in the LLM config schema) for one-shot prompts where
|
|
816
|
+
// every breakpoint is a paid cache write with no future read.
|
|
817
|
+
const disableCache =
|
|
818
|
+
(config as Record<string, unknown> | undefined)?.disableCache === true;
|
|
812
819
|
let sentMessages: Anthropic.MessageParam[] | undefined;
|
|
813
820
|
const startedAt = Date.now();
|
|
814
821
|
// Hoisted so the catch block can distinguish our inner stream timeout
|
|
@@ -998,6 +1005,7 @@ export class AnthropicProvider implements Provider {
|
|
|
998
1005
|
cacheTtl: _cacheTtl,
|
|
999
1006
|
disableTurnStartCache: _disableTurnStartCache,
|
|
1000
1007
|
mutableLatestUserMessage: _mutableLatestUserMessage,
|
|
1008
|
+
disableCache: _disableCache,
|
|
1001
1009
|
max_tokens: callerMaxTokens,
|
|
1002
1010
|
usageAttributionHeaders,
|
|
1003
1011
|
...restConfig
|
|
@@ -1054,19 +1062,34 @@ export class AnthropicProvider implements Provider {
|
|
|
1054
1062
|
};
|
|
1055
1063
|
|
|
1056
1064
|
if (systemPrompt) {
|
|
1057
|
-
// The
|
|
1058
|
-
//
|
|
1059
|
-
//
|
|
1060
|
-
//
|
|
1061
|
-
|
|
1062
|
-
|
|
1065
|
+
// The system prompt may carry a cache boundary (placed by the
|
|
1066
|
+
// section pipeline — see `prompts/sections.ts`) splitting it into
|
|
1067
|
+
// a stable-prefix block and a volatile-suffix block, each with
|
|
1068
|
+
// its own breakpoint so a volatile-section change doesn't
|
|
1069
|
+
// re-create the stable prefix. A 1-hour cache TTL is used (when
|
|
1070
|
+
// supported by the model) so the breakpoints survive turn gaps
|
|
1071
|
+
// that exceed the default 5-minute window.
|
|
1072
|
+
params.system = systemPrompt
|
|
1073
|
+
.split(SYSTEM_PROMPT_CACHE_BOUNDARY)
|
|
1074
|
+
.filter((text) => text.length > 0)
|
|
1075
|
+
.map((text) => ({
|
|
1063
1076
|
type: "text" as const,
|
|
1064
|
-
text
|
|
1065
|
-
cache_control: cacheControl,
|
|
1066
|
-
}
|
|
1067
|
-
|
|
1077
|
+
text,
|
|
1078
|
+
...(disableCache ? {} : { cache_control: cacheControl }),
|
|
1079
|
+
}));
|
|
1080
|
+
if (params.system.length === 0) delete params.system;
|
|
1068
1081
|
}
|
|
1069
1082
|
|
|
1083
|
+
// Tools precede the system blocks in the cached prefix, so the first
|
|
1084
|
+
// system breakpoint already covers the tool definitions. When the
|
|
1085
|
+
// system prompt is split into two blocks, skip the explicit last-tool
|
|
1086
|
+
// breakpoint to stay within Anthropic's 4-breakpoint budget; with a
|
|
1087
|
+
// single (or no) system block the tool breakpoint is kept.
|
|
1088
|
+
const systemBlockCount = Array.isArray(params.system)
|
|
1089
|
+
? params.system.length
|
|
1090
|
+
: 0;
|
|
1091
|
+
const applyToolCacheControl = systemBlockCount < 2;
|
|
1092
|
+
|
|
1070
1093
|
if (tools && tools.length > 0) {
|
|
1071
1094
|
if (
|
|
1072
1095
|
this.useNativeWebSearch &&
|
|
@@ -1077,7 +1100,9 @@ export class AnthropicProvider implements Provider {
|
|
|
1077
1100
|
name: t.name,
|
|
1078
1101
|
description: t.description,
|
|
1079
1102
|
input_schema: t.input_schema as Anthropic.Tool["input_schema"],
|
|
1080
|
-
...(
|
|
1103
|
+
...(applyToolCacheControl &&
|
|
1104
|
+
!disableCache &&
|
|
1105
|
+
i === otherTools.length - 1
|
|
1081
1106
|
? { cache_control: cacheControl }
|
|
1082
1107
|
: {}),
|
|
1083
1108
|
}));
|
|
@@ -1092,7 +1117,9 @@ export class AnthropicProvider implements Provider {
|
|
|
1092
1117
|
name: t.name,
|
|
1093
1118
|
description: t.description,
|
|
1094
1119
|
input_schema: t.input_schema as Anthropic.Tool["input_schema"],
|
|
1095
|
-
...(i === tools.length - 1
|
|
1120
|
+
...(applyToolCacheControl && !disableCache && i === tools.length - 1
|
|
1121
|
+
? { cache_control: cacheControl }
|
|
1122
|
+
: {}),
|
|
1096
1123
|
}));
|
|
1097
1124
|
}
|
|
1098
1125
|
}
|
|
@@ -1140,6 +1167,7 @@ export class AnthropicProvider implements Provider {
|
|
|
1140
1167
|
mutableLatestUserMessage && turnStartIdx === msgs.length - 1;
|
|
1141
1168
|
if (
|
|
1142
1169
|
turnStartIdx >= 0 &&
|
|
1170
|
+
!disableCache &&
|
|
1143
1171
|
!disableTurnStartCache &&
|
|
1144
1172
|
!skipVolatileTurnStartAnchor
|
|
1145
1173
|
) {
|
|
@@ -1156,7 +1184,11 @@ export class AnthropicProvider implements Provider {
|
|
|
1156
1184
|
// cache_creation tokens per new turn). Skipped during tool-use loops
|
|
1157
1185
|
// where the current turn-start already covers the same prefix and a
|
|
1158
1186
|
// second anchor would blow the 4-breakpoint budget.
|
|
1159
|
-
if (
|
|
1187
|
+
if (
|
|
1188
|
+
!disableCache &&
|
|
1189
|
+
turnStartIdx === msgs.length - 1 &&
|
|
1190
|
+
turnStartIdx > 0
|
|
1191
|
+
) {
|
|
1160
1192
|
const prevTurnAnchorIdx = findUserTextMsgIdx(turnStartIdx - 1);
|
|
1161
1193
|
if (prevTurnAnchorIdx >= 0)
|
|
1162
1194
|
applyCacheControlToLastBlock(prevTurnAnchorIdx);
|
|
@@ -1168,7 +1200,11 @@ export class AnthropicProvider implements Provider {
|
|
|
1168
1200
|
// cheaply without conflicting with the 1h breakpoints above.
|
|
1169
1201
|
// Skip thinking/redacted_thinking blocks — Anthropic doesn't allow
|
|
1170
1202
|
// cache_control on those types.
|
|
1171
|
-
if (
|
|
1203
|
+
if (
|
|
1204
|
+
!disableCache &&
|
|
1205
|
+
turnStartIdx >= 0 &&
|
|
1206
|
+
turnStartIdx < sentMessages.length - 1
|
|
1207
|
+
) {
|
|
1172
1208
|
const lastMsg = sentMessages[sentMessages.length - 1];
|
|
1173
1209
|
if (Array.isArray(lastMsg.content) && lastMsg.content.length > 0) {
|
|
1174
1210
|
const NON_CACHEABLE_TYPES = new Set([
|
|
@@ -1193,11 +1229,12 @@ export class AnthropicProvider implements Provider {
|
|
|
1193
1229
|
}
|
|
1194
1230
|
}
|
|
1195
1231
|
|
|
1196
|
-
// Cache-breakpoint accounting: system(
|
|
1197
|
-
//
|
|
1198
|
-
//
|
|
1199
|
-
//
|
|
1200
|
-
//
|
|
1232
|
+
// Cache-breakpoint accounting: system(≤2) + tools(1, only when the
|
|
1233
|
+
// system is a single block or absent) + turn-start(1) +
|
|
1234
|
+
// (tail OR prev-turn-anchor)(1) ≤ 4 — Anthropic's per-request cap.
|
|
1235
|
+
// Tail and prev-turn-anchor are mutually exclusive (the latter only
|
|
1236
|
+
// fires when turn-start is the last message, which suppresses the
|
|
1237
|
+
// tail), so the total can't drift past 4.
|
|
1201
1238
|
|
|
1202
1239
|
// Strip orphaned UTF-16 surrogates so the Anthropic JSON parser never
|
|
1203
1240
|
// sees invalid strings produced by upstream surrogate-splitting `.slice()` calls.
|
|
@@ -1208,19 +1245,28 @@ export class AnthropicProvider implements Provider {
|
|
|
1208
1245
|
sentMessages = params.messages;
|
|
1209
1246
|
}
|
|
1210
1247
|
|
|
1211
|
-
//
|
|
1212
|
-
//
|
|
1213
|
-
//
|
|
1214
|
-
//
|
|
1215
|
-
//
|
|
1216
|
-
|
|
1248
|
+
// Callers can stamp `cache_control` on message blocks before the
|
|
1249
|
+
// provider sees them. Two repairs apply:
|
|
1250
|
+
// - `disableCache`: strip the marker entirely — this call opted out of
|
|
1251
|
+
// prompt caching, and a leftover block-level marker would still incur
|
|
1252
|
+
// a cache write.
|
|
1253
|
+
// - Haiku: strip only the `ttl` field — Haiku does not support the
|
|
1254
|
+
// extended-cache-ttl beta, so a `ttl` would make the request invalid.
|
|
1255
|
+
// The client's own breakpoints already omit it for Haiku.
|
|
1256
|
+
if (disableCache || isHaiku) {
|
|
1217
1257
|
for (const msg of sentMessages) {
|
|
1218
1258
|
if (!Array.isArray(msg.content)) continue;
|
|
1219
1259
|
for (const block of msg.content) {
|
|
1220
1260
|
if (typeof block === "string") continue;
|
|
1221
|
-
const
|
|
1222
|
-
|
|
1223
|
-
|
|
1261
|
+
const blockRecord = block as {
|
|
1262
|
+
cache_control?: { ttl?: unknown };
|
|
1263
|
+
};
|
|
1264
|
+
if (!blockRecord.cache_control) continue;
|
|
1265
|
+
if (disableCache) {
|
|
1266
|
+
delete blockRecord.cache_control;
|
|
1267
|
+
} else if ("ttl" in blockRecord.cache_control) {
|
|
1268
|
+
delete blockRecord.cache_control.ttl;
|
|
1269
|
+
}
|
|
1224
1270
|
}
|
|
1225
1271
|
}
|
|
1226
1272
|
}
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
THINKING_LEVELS,
|
|
6
6
|
type ThinkingLevel as ThinkingLevelName,
|
|
7
7
|
} from "../../config/schemas/llm.js";
|
|
8
|
+
import { SYSTEM_PROMPT_CACHE_BOUNDARY } from "../../prompts/cache-boundary.js";
|
|
8
9
|
import { isAbortReason } from "../../util/abort-reasons.js";
|
|
9
10
|
import { ProviderError } from "../../util/errors.js";
|
|
10
11
|
import { getLogger } from "../../util/logger.js";
|
|
@@ -314,7 +315,10 @@ export class GeminiProvider implements Provider {
|
|
|
314
315
|
const geminiConfig: genai.GenerateContentConfig = {};
|
|
315
316
|
|
|
316
317
|
if (systemPrompt) {
|
|
317
|
-
geminiConfig.systemInstruction = systemPrompt
|
|
318
|
+
geminiConfig.systemInstruction = systemPrompt.replaceAll(
|
|
319
|
+
SYSTEM_PROMPT_CACHE_BOUNDARY,
|
|
320
|
+
"\n\n",
|
|
321
|
+
);
|
|
318
322
|
}
|
|
319
323
|
if (maxTokens) {
|
|
320
324
|
geminiConfig.maxOutputTokens = maxTokens;
|
|
@@ -101,6 +101,15 @@ export class MinimaxProvider extends OpenAIChatCompletionsProvider {
|
|
|
101
101
|
providerName: "minimax",
|
|
102
102
|
providerLabel: "MiniMax",
|
|
103
103
|
streamTimeoutMs: options.streamTimeoutMs,
|
|
104
|
+
// Without reasoning_split, MiniMax embeds reasoning in `content`
|
|
105
|
+
// wrapped in <think>...</think> tags (and also mirrors it into
|
|
106
|
+
// reasoning deltas), so raw tags leak into user-visible text. With it,
|
|
107
|
+
// reasoning arrives only via `reasoning_content`/`reasoning_details`,
|
|
108
|
+
// which the base provider already parses into thinking blocks.
|
|
109
|
+
extraCreateParams: { reasoning_split: true },
|
|
110
|
+
// MiniMax models reason between tool calls (interleaved thinking) and
|
|
111
|
+
// expect prior-turn reasoning replayed on multi-turn requests.
|
|
112
|
+
assistantReasoningField: "reasoning_content",
|
|
104
113
|
});
|
|
105
114
|
}
|
|
106
115
|
}
|
|
@@ -691,6 +691,24 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
|
|
|
691
691
|
outputPer1mTokens: 2.5,
|
|
692
692
|
},
|
|
693
693
|
},
|
|
694
|
+
{
|
|
695
|
+
id: "accounts/fireworks/models/minimax-m3",
|
|
696
|
+
displayName: "MiniMax M3",
|
|
697
|
+
// The model supports 1M context, but Fireworks serves it with a
|
|
698
|
+
// 512K (524,288-token) window; advertise the served limit.
|
|
699
|
+
contextWindowTokens: 524288,
|
|
700
|
+
maxOutputTokens: 512000,
|
|
701
|
+
supportsThinking: true,
|
|
702
|
+
supportsCaching: true,
|
|
703
|
+
supportsVision: true,
|
|
704
|
+
supportsToolUse: true,
|
|
705
|
+
maxEffort: "high",
|
|
706
|
+
pricing: {
|
|
707
|
+
inputPer1mTokens: 0.3,
|
|
708
|
+
outputPer1mTokens: 1.2,
|
|
709
|
+
cacheReadPer1mTokens: 0.06,
|
|
710
|
+
},
|
|
711
|
+
},
|
|
694
712
|
{
|
|
695
713
|
id: "accounts/fireworks/models/minimax-m2p7",
|
|
696
714
|
displayName: "MiniMax M2.7",
|
|
@@ -1241,6 +1259,16 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
|
|
|
1241
1259
|
linkLabel: "Open MiniMax Dashboard",
|
|
1242
1260
|
},
|
|
1243
1261
|
models: [
|
|
1262
|
+
{
|
|
1263
|
+
id: "MiniMax-M3",
|
|
1264
|
+
displayName: "MiniMax M3",
|
|
1265
|
+
contextWindowTokens: 1000000,
|
|
1266
|
+
maxOutputTokens: 512000,
|
|
1267
|
+
supportsThinking: true,
|
|
1268
|
+
supportsCaching: true,
|
|
1269
|
+
supportsVision: true,
|
|
1270
|
+
supportsToolUse: true,
|
|
1271
|
+
},
|
|
1244
1272
|
{
|
|
1245
1273
|
id: "MiniMax-M2.7",
|
|
1246
1274
|
displayName: "MiniMax M2.7",
|
|
@@ -13,7 +13,7 @@ const PROVIDER_MODEL_INTENTS: Record<string, Record<ModelIntent, string>> = {
|
|
|
13
13
|
anthropic: {
|
|
14
14
|
balanced: "claude-sonnet-4-6",
|
|
15
15
|
"latency-optimized": "claude-haiku-4-5-20251001",
|
|
16
|
-
"quality-optimized": "claude-
|
|
16
|
+
"quality-optimized": "claude-fable-5",
|
|
17
17
|
"vision-optimized": "claude-opus-4-6",
|
|
18
18
|
},
|
|
19
19
|
openai: {
|
|
@@ -35,7 +35,7 @@ const PROVIDER_MODEL_INTENTS: Record<string, Record<ModelIntent, string>> = {
|
|
|
35
35
|
"vision-optimized": "llama3.2",
|
|
36
36
|
},
|
|
37
37
|
fireworks: {
|
|
38
|
-
balanced: "accounts/fireworks/models/
|
|
38
|
+
balanced: "accounts/fireworks/models/minimax-m3",
|
|
39
39
|
"latency-optimized": "accounts/fireworks/models/kimi-k2p5",
|
|
40
40
|
"quality-optimized": "accounts/fireworks/models/kimi-k2p6",
|
|
41
41
|
"vision-optimized": "accounts/fireworks/models/kimi-k2p6",
|
|
@@ -43,7 +43,7 @@ const PROVIDER_MODEL_INTENTS: Record<string, Record<ModelIntent, string>> = {
|
|
|
43
43
|
openrouter: {
|
|
44
44
|
balanced: "anthropic/claude-sonnet-4.6",
|
|
45
45
|
"latency-optimized": "anthropic/claude-haiku-4.5",
|
|
46
|
-
"quality-optimized": "anthropic/claude-
|
|
46
|
+
"quality-optimized": "anthropic/claude-fable-5",
|
|
47
47
|
"vision-optimized": "anthropic/claude-opus-4.6",
|
|
48
48
|
},
|
|
49
49
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import OpenAI from "openai";
|
|
2
2
|
|
|
3
|
+
import { SYSTEM_PROMPT_CACHE_BOUNDARY } from "../../prompts/cache-boundary.js";
|
|
3
4
|
import { isAbortReason } from "../../util/abort-reasons.js";
|
|
4
5
|
import { ProviderError } from "../../util/errors.js";
|
|
5
6
|
import { extractRetryAfterMs } from "../../util/retry.js";
|
|
@@ -17,6 +18,7 @@ import {
|
|
|
17
18
|
ContextOverflowError,
|
|
18
19
|
extractOverflowTokensFromMessage,
|
|
19
20
|
} from "../types.js";
|
|
21
|
+
import { wrapUnparseableToolArgs } from "../unparseable-tool-args.js";
|
|
20
22
|
|
|
21
23
|
/**
|
|
22
24
|
* Detect OpenAI-compatible context-overflow signals on an `OpenAI.APIError`.
|
|
@@ -634,7 +636,7 @@ export class OpenAIChatCompletionsProvider implements Provider {
|
|
|
634
636
|
try {
|
|
635
637
|
input = JSON.parse(tc.args);
|
|
636
638
|
} catch {
|
|
637
|
-
input =
|
|
639
|
+
input = wrapUnparseableToolArgs(tc.args);
|
|
638
640
|
}
|
|
639
641
|
content.push({
|
|
640
642
|
type: "tool_use",
|
|
@@ -797,7 +799,7 @@ export class OpenAIChatCompletionsProvider implements Provider {
|
|
|
797
799
|
if (systemPrompt) {
|
|
798
800
|
result.push({
|
|
799
801
|
role: "system",
|
|
800
|
-
content: systemPrompt,
|
|
802
|
+
content: systemPrompt.replaceAll(SYSTEM_PROMPT_CACHE_BOUNDARY, "\n\n"),
|
|
801
803
|
});
|
|
802
804
|
}
|
|
803
805
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import OpenAI from "openai";
|
|
2
2
|
|
|
3
|
+
import { SYSTEM_PROMPT_CACHE_BOUNDARY } from "../../prompts/cache-boundary.js";
|
|
3
4
|
import { isAbortReason } from "../../util/abort-reasons.js";
|
|
4
5
|
import { ProviderError } from "../../util/errors.js";
|
|
5
6
|
import { getLogger } from "../../util/logger.js";
|
|
@@ -14,6 +15,7 @@ import type {
|
|
|
14
15
|
SendMessageOptions,
|
|
15
16
|
} from "../types.js";
|
|
16
17
|
import { ContextOverflowError } from "../types.js";
|
|
18
|
+
import { wrapUnparseableToolArgs } from "../unparseable-tool-args.js";
|
|
17
19
|
import { detectOpenAICompatibleContextOverflow } from "./chat-completions-provider.js";
|
|
18
20
|
|
|
19
21
|
const log = getLogger("openai-responses");
|
|
@@ -216,7 +218,10 @@ export class OpenAIResponsesProvider implements Provider {
|
|
|
216
218
|
};
|
|
217
219
|
|
|
218
220
|
if (systemPrompt) {
|
|
219
|
-
params.instructions = systemPrompt
|
|
221
|
+
params.instructions = systemPrompt.replaceAll(
|
|
222
|
+
SYSTEM_PROMPT_CACHE_BOUNDARY,
|
|
223
|
+
"\n\n",
|
|
224
|
+
);
|
|
220
225
|
}
|
|
221
226
|
|
|
222
227
|
if (maxTokens && !this.codexSubscription) {
|
|
@@ -461,7 +466,7 @@ export class OpenAIResponsesProvider implements Provider {
|
|
|
461
466
|
try {
|
|
462
467
|
input = JSON.parse(tc.args);
|
|
463
468
|
} catch {
|
|
464
|
-
input =
|
|
469
|
+
input = wrapUnparseableToolArgs(tc.args);
|
|
465
470
|
}
|
|
466
471
|
content.push({
|
|
467
472
|
type: "tool_use",
|
package/src/providers/retry.ts
CHANGED
|
@@ -268,6 +268,14 @@ function normalizeSendMessageOptions(
|
|
|
268
268
|
if (nextConfig.thinking === undefined && resolved.thinking !== undefined) {
|
|
269
269
|
nextConfig.thinking = resolved.thinking;
|
|
270
270
|
}
|
|
271
|
+
// Not a wire field: consumed (and stripped) by provider clients that
|
|
272
|
+
// implement prompt caching, like `cacheTtl` / `disableTurnStartCache`.
|
|
273
|
+
if (
|
|
274
|
+
nextConfig.disableCache === undefined &&
|
|
275
|
+
resolved.disableCache !== undefined
|
|
276
|
+
) {
|
|
277
|
+
nextConfig.disableCache = resolved.disableCache;
|
|
278
|
+
}
|
|
271
279
|
// Forward OpenRouter-only routing preferences so `OpenRouterProvider` can
|
|
272
280
|
// translate `openrouter.only` into the wire-format `provider: { only: [...] }`
|
|
273
281
|
// body field on both the OpenAI-compat and Anthropic-compat endpoints.
|
package/src/providers/types.ts
CHANGED
|
@@ -222,6 +222,17 @@ export interface SendMessageConfig {
|
|
|
222
222
|
* behavior.
|
|
223
223
|
*/
|
|
224
224
|
mutableLatestUserMessage?: boolean;
|
|
225
|
+
/**
|
|
226
|
+
* When true, the provider sends no prompt-cache breakpoints at all (and
|
|
227
|
+
* strips any block-level `cache_control` markers callers stamped on
|
|
228
|
+
* messages). For one-shot call sites whose prompts are unique per call or
|
|
229
|
+
* whose call cadence exceeds the cache TTL, every breakpoint is a paid
|
|
230
|
+
* cache write that will never be read — opting out saves the write
|
|
231
|
+
* premium. Resolved per call site via `resolveCallSiteConfig` (see
|
|
232
|
+
* `disableCache` in the LLM config schema); a per-call explicit value
|
|
233
|
+
* wins. Default false — existing behavior.
|
|
234
|
+
*/
|
|
235
|
+
disableCache?: boolean;
|
|
225
236
|
[key: string]: unknown;
|
|
226
237
|
}
|
|
227
238
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Marker shape for tool-call arguments that failed JSON parsing.
|
|
3
|
+
*
|
|
4
|
+
* Streaming providers accumulate tool-call argument deltas as a string and
|
|
5
|
+
* parse the result once the stream completes. Some models/gateways emit
|
|
6
|
+
* truncated or malformed argument JSON (e.g. MiniMax M3 via OpenRouter cutting
|
|
7
|
+
* the stream mid-object). The provider cannot drop the tool_use block — the
|
|
8
|
+
* protocol requires a paired tool_result for every tool_use id — so it wraps
|
|
9
|
+
* the raw string under this marker key instead.
|
|
10
|
+
*
|
|
11
|
+
* The tool execution layer detects the marker and rejects the invocation with
|
|
12
|
+
* an error tool result, so the model sees the failure and can retry, instead
|
|
13
|
+
* of a tool executing with garbage input.
|
|
14
|
+
*/
|
|
15
|
+
const UNPARSEABLE_TOOL_ARGS_KEY = "_raw";
|
|
16
|
+
|
|
17
|
+
/** Wrap raw, unparseable tool-call argument text in the marker shape. */
|
|
18
|
+
export function wrapUnparseableToolArgs(raw: string): Record<string, unknown> {
|
|
19
|
+
return { [UNPARSEABLE_TOOL_ARGS_KEY]: raw };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Detect input produced by {@link wrapUnparseableToolArgs}: exactly one key,
|
|
24
|
+
* the marker key, holding the raw argument string. The exact-shape check
|
|
25
|
+
* avoids false positives on hypothetical legitimate inputs that merely
|
|
26
|
+
* contain a `_raw` field among others.
|
|
27
|
+
*/
|
|
28
|
+
export function isUnparseableToolArgs(
|
|
29
|
+
input: Record<string, unknown>,
|
|
30
|
+
): input is { _raw: string } {
|
|
31
|
+
const keys = Object.keys(input);
|
|
32
|
+
return (
|
|
33
|
+
keys.length === 1 &&
|
|
34
|
+
keys[0] === UNPARSEABLE_TOOL_ARGS_KEY &&
|
|
35
|
+
typeof input[UNPARSEABLE_TOOL_ARGS_KEY] === "string"
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Build the error message returned to the model when it sends unparseable
|
|
41
|
+
* tool arguments. Includes a bounded prefix of what was received so the model
|
|
42
|
+
* can see where its output was cut off or malformed.
|
|
43
|
+
*/
|
|
44
|
+
export function unparseableToolArgsMessage(
|
|
45
|
+
toolName: string,
|
|
46
|
+
raw: string,
|
|
47
|
+
): string {
|
|
48
|
+
const PREVIEW_LIMIT = 200;
|
|
49
|
+
const preview =
|
|
50
|
+
raw.length > PREVIEW_LIMIT ? `${raw.slice(0, PREVIEW_LIMIT)}…` : raw;
|
|
51
|
+
return (
|
|
52
|
+
`Error: the arguments for "${toolName}" were not valid JSON — the argument stream was malformed or truncated, so the tool was NOT executed. ` +
|
|
53
|
+
`Received: ${preview || "(empty)"}\n` +
|
|
54
|
+
`Retry the call with complete, valid JSON arguments.`
|
|
55
|
+
);
|
|
56
|
+
}
|
package/src/runtime/AGENTS.md
CHANGED
|
@@ -20,6 +20,12 @@ SSE handlers built on `ReadableStream` shed slow subscribers when `controller.de
|
|
|
20
20
|
|
|
21
21
|
GET handlers must be safe and side-effect-free — they must not enqueue background jobs, mutate database state, or trigger writes. If a feature needs server-initiated work in response to a client request, use an explicit POST endpoint or a push-based flow (SSE event → client refetch). See [RFC 9110 §9.2.1 — Safe Methods](https://httpwg.org/specs/rfc9110.html#safe.methods).
|
|
22
22
|
|
|
23
|
+
Accepted exceptions (stale-while-revalidate caches): a GET handler may kick off a bounded, fire-and-forget background refresh of a generated-content cache when no fresh cache exists, provided the handler itself stays read-only and returns immediately with cached/fallback copy, the refresh is single-flight (concurrent GETs share one regeneration), and a TTL bounds regeneration frequency. Current instances:
|
|
24
|
+
|
|
25
|
+
- `GET /v1/identity/intro` — refreshes the generated greeting cache; the background prompt may only depend on static identity/soul context plus caller-supplied local hour/minute.
|
|
26
|
+
- `GET /v1/home/feed` — refreshes the personalized home greeting and suggested-prompt caches via `revalidateHomeContentInBackground()`, which publishes `home_feed_updated` when fresh content lands so clients refetch. This is intentional: home content is generated on demand (when a user actually views Home), never at daemon startup or on a timer.
|
|
27
|
+
- `GET /v1/conversation-starters` — enqueues a `generate_conversation_starters` memory job when the starter set is stale, cooldown-gated and deduped against in-flight jobs.
|
|
28
|
+
|
|
23
29
|
### Approvals (confirmations, secrets, trust rules)
|
|
24
30
|
|
|
25
31
|
Approvals are **orthogonal to message sending**. The assistant asks for approval whenever it needs one — this is a separate concern from how a message enters the system.
|
|
@@ -173,7 +173,7 @@ mock.module("../../config/loader.js", () => ({
|
|
|
173
173
|
getNestedValue: () => undefined,
|
|
174
174
|
setNestedValue: () => {},
|
|
175
175
|
API_KEY_PROVIDERS: [],
|
|
176
|
-
|
|
176
|
+
_writeQuarantineNotice: () => {},
|
|
177
177
|
invalidateConfigCache: () => {},
|
|
178
178
|
}));
|
|
179
179
|
|
|
@@ -837,7 +837,7 @@ describe("wakeAgentForOpportunity", () => {
|
|
|
837
837
|
});
|
|
838
838
|
|
|
839
839
|
test("applies caller-supplied trustContext to the target before the agent loop runs", async () => {
|
|
840
|
-
// Background system jobs (memory consolidation
|
|
840
|
+
// Background system jobs (e.g. memory consolidation) need
|
|
841
841
|
// guardian trust to clear the side-effect approval gate. The wake must
|
|
842
842
|
// call setTrustContext BEFORE agentLoop.run so the per-turn snapshot
|
|
843
843
|
// captures the elevated trust.
|
|
@@ -66,7 +66,7 @@ import {
|
|
|
66
66
|
import {
|
|
67
67
|
recordCompactionEndBestEffort,
|
|
68
68
|
recordCompactionStartBestEffort,
|
|
69
|
-
} from "../memory/compaction-log-
|
|
69
|
+
} from "../memory/compaction-log-store-clickhouse.js";
|
|
70
70
|
import { getConversationOverrideProfile } from "../memory/conversation-crud.js";
|
|
71
71
|
import {
|
|
72
72
|
buildProviderErrorResponsePayload,
|
|
@@ -167,10 +167,10 @@ export interface WakeOptions {
|
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
/**
|
|
170
|
-
* Reason a wake returned `invoked: false`. Callers (CLI
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
170
|
+
* Reason a wake returned `invoked: false`. Callers (e.g. the CLI) need to
|
|
171
|
+
* distinguish "conversation doesn't exist" from "conversation exists but
|
|
172
|
+
* stayed busy past the wait-until-idle timeout" — the former is a
|
|
173
|
+
* user-visible error, the latter is an expected transient condition.
|
|
174
174
|
*/
|
|
175
175
|
export type WakeSkipReason =
|
|
176
176
|
| "not_found"
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* `runBackgroundJob()` consolidates the bootstrap → processMessage → timeout
|
|
5
5
|
* pattern that every background producer (heartbeat, filing, scheduler, memory
|
|
6
|
-
* consolidation, watcher,
|
|
6
|
+
* consolidation, watcher, subagent, sequence) has been
|
|
7
7
|
* open-coding. Wrapping it here lets us:
|
|
8
8
|
*
|
|
9
9
|
* - apply a single timeout policy
|
|
@@ -182,7 +182,7 @@ export async function runBackgroundJob(
|
|
|
182
182
|
// failed" rows visible in the sidebar the moment a real user hatches the
|
|
183
183
|
// assistant — see `pre-first-message-gate.ts` for the rationale.
|
|
184
184
|
//
|
|
185
|
-
// Service-level callers (heartbeat
|
|
185
|
+
// Service-level callers (e.g. heartbeat) are expected to gate
|
|
186
186
|
// earlier and never reach this point; reaching the gate here means a
|
|
187
187
|
// caller either forgot to gate or deliberately opted in via
|
|
188
188
|
// `allowPreFirstUserMessage`. We log at `info` (not `warn`) because the
|