@vellumai/assistant 0.8.11 → 0.8.12-staging.1
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 +126 -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-usage-store.test.ts +11 -0
- 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__/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-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-release-notes-feature-flag-guard.test.ts +45 -95
- 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/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 +301 -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 +219 -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/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/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/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-intents.ts +2 -2
- package/src/providers/openai/chat-completions-provider.ts +2 -1
- package/src/providers/openai/responses-provider.ts +5 -1
- package/src/providers/retry.ts +8 -0
- package/src/providers/types.ts +11 -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__/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 +1 -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/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/plugins-routes.ts +21 -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/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/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/registry.ts +4 -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
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared IPC contracts for assistant-to-gateway gateway-owned reads.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
|
|
7
|
+
export const GATEWAY_LOG_LEVEL_NAMES = [
|
|
8
|
+
"trace",
|
|
9
|
+
"debug",
|
|
10
|
+
"info",
|
|
11
|
+
"warn",
|
|
12
|
+
"error",
|
|
13
|
+
"fatal",
|
|
14
|
+
] as const;
|
|
15
|
+
export type GatewayLogLevelName = (typeof GATEWAY_LOG_LEVEL_NAMES)[number];
|
|
16
|
+
|
|
17
|
+
const GatewayLogsTailIpcParamsShape = {
|
|
18
|
+
n: z.number().int().min(1).max(1000).optional(),
|
|
19
|
+
level: z.enum(GATEWAY_LOG_LEVEL_NAMES).optional(),
|
|
20
|
+
module: z.string().optional(),
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const GatewayLogsTailIpcParamsSchema = z
|
|
24
|
+
.object(GatewayLogsTailIpcParamsShape)
|
|
25
|
+
.strict()
|
|
26
|
+
.default({});
|
|
27
|
+
|
|
28
|
+
export type GatewayLogsTailIpcParams = z.infer<
|
|
29
|
+
typeof GatewayLogsTailIpcParamsSchema
|
|
30
|
+
>;
|
|
31
|
+
|
|
32
|
+
export const GatewayLogsTailRouteParamsSchema = z
|
|
33
|
+
.object({
|
|
34
|
+
...GatewayLogsTailIpcParamsShape,
|
|
35
|
+
n: z.coerce.number().int().min(1).max(1000).optional(),
|
|
36
|
+
})
|
|
37
|
+
.strict();
|
|
38
|
+
|
|
39
|
+
export type GatewayLogsTailRouteParams = z.infer<
|
|
40
|
+
typeof GatewayLogsTailRouteParamsSchema
|
|
41
|
+
>;
|
|
42
|
+
|
|
43
|
+
export const GatewayLogsTailIpcResponseSchema = z.object({
|
|
44
|
+
lines: z.array(z.record(z.string(), z.unknown())),
|
|
45
|
+
truncated: z.boolean(),
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
export type GatewayLogsTailIpcResponse = z.infer<
|
|
49
|
+
typeof GatewayLogsTailIpcResponseSchema
|
|
50
|
+
>;
|
|
51
|
+
|
|
52
|
+
export const TrustRulesListIpcParamsSchema = z
|
|
53
|
+
.object({
|
|
54
|
+
origin: z.string().optional(),
|
|
55
|
+
tool: z.string().optional(),
|
|
56
|
+
include_all: z.boolean().optional(),
|
|
57
|
+
include_deleted: z.boolean().optional(),
|
|
58
|
+
})
|
|
59
|
+
.strict()
|
|
60
|
+
.default({});
|
|
61
|
+
|
|
62
|
+
export type TrustRulesListIpcParams = z.infer<
|
|
63
|
+
typeof TrustRulesListIpcParamsSchema
|
|
64
|
+
>;
|
|
65
|
+
|
|
66
|
+
export const TrustRuleSchema = z.object({
|
|
67
|
+
id: z.string(),
|
|
68
|
+
tool: z.string(),
|
|
69
|
+
pattern: z.string(),
|
|
70
|
+
risk: z.enum(["low", "medium", "high"]),
|
|
71
|
+
description: z.string(),
|
|
72
|
+
origin: z.enum(["default", "user_defined"]),
|
|
73
|
+
userModified: z.boolean(),
|
|
74
|
+
deleted: z.boolean(),
|
|
75
|
+
createdAt: z.string(),
|
|
76
|
+
updatedAt: z.string(),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
export type TrustRule = z.infer<typeof TrustRuleSchema>;
|
|
80
|
+
|
|
81
|
+
export const TrustRulesListIpcResponseSchema = z.object({
|
|
82
|
+
rules: z.array(TrustRuleSchema),
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
export type TrustRulesListIpcResponse = z.infer<
|
|
86
|
+
typeof TrustRulesListIpcResponseSchema
|
|
87
|
+
>;
|
|
@@ -15,11 +15,9 @@ export {
|
|
|
15
15
|
deliverChannelReply,
|
|
16
16
|
} from "./http-delivery.js";
|
|
17
17
|
|
|
18
|
-
export
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
PersistentIpcClient,
|
|
22
|
-
} from "./ipc-client.js";
|
|
18
|
+
export * from "./gateway-ipc-contracts.js";
|
|
19
|
+
|
|
20
|
+
export { ipcCall, IpcCallError, PersistentIpcClient } from "./ipc-client.js";
|
|
23
21
|
|
|
24
22
|
export type {
|
|
25
23
|
ApprovalActionOption,
|
package/openapi.yaml
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
openapi: 3.1.0
|
|
4
4
|
info:
|
|
5
5
|
title: Vellum Assistant API
|
|
6
|
-
version: 0.8.
|
|
6
|
+
version: 0.8.12
|
|
7
7
|
description: Auto-generated OpenAPI specification for the Vellum Assistant runtime HTTP server.
|
|
8
8
|
servers:
|
|
9
9
|
- url: http://127.0.0.1:7821
|
|
@@ -5937,6 +5937,7 @@ paths:
|
|
|
5937
5937
|
- macos_notification_view
|
|
5938
5938
|
- macos_conversation_opened
|
|
5939
5939
|
- ios_conversation_opened
|
|
5940
|
+
- web_bulk_mark_read
|
|
5940
5941
|
- telegram_inbound_message
|
|
5941
5942
|
- telegram_callback
|
|
5942
5943
|
- slack_inbound_message
|
|
@@ -6300,6 +6301,7 @@ paths:
|
|
|
6300
6301
|
- macos_notification_view
|
|
6301
6302
|
- macos_conversation_opened
|
|
6302
6303
|
- ios_conversation_opened
|
|
6304
|
+
- web_bulk_mark_read
|
|
6303
6305
|
- telegram_inbound_message
|
|
6304
6306
|
- telegram_callback
|
|
6305
6307
|
- slack_inbound_message
|
|
@@ -6500,6 +6502,7 @@ paths:
|
|
|
6500
6502
|
- macos_notification_view
|
|
6501
6503
|
- macos_conversation_opened
|
|
6502
6504
|
- ios_conversation_opened
|
|
6505
|
+
- web_bulk_mark_read
|
|
6503
6506
|
- telegram_inbound_message
|
|
6504
6507
|
- telegram_callback
|
|
6505
6508
|
- slack_inbound_message
|
|
@@ -6628,9 +6631,10 @@ paths:
|
|
|
6628
6631
|
description:
|
|
6629
6632
|
Return the chronological list of compaction events that ran in the same agent turn as the call identified
|
|
6630
6633
|
by `callId`. Turn bounds are walked from the `messages` table (real user messages — tool-result user messages
|
|
6631
|
-
are not boundaries).
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
+
are not boundaries). Served from the first-class compaction log when `compactionLogs.destination = "clickhouse"`
|
|
6635
|
+
is configured, falling back to the legacy projection over `llm_request_logs` rows where `call_site =
|
|
6636
|
+
"compactionAgent"`. When the conversation has no other messages around the selected call, every compaction
|
|
6637
|
+
strictly before the call's `createdAt` is in scope. Drives the Inspector's Compaction tab.
|
|
6634
6638
|
tags:
|
|
6635
6639
|
- conversations
|
|
6636
6640
|
responses:
|
|
@@ -7095,6 +7099,44 @@ paths:
|
|
|
7095
7099
|
required: true
|
|
7096
7100
|
schema:
|
|
7097
7101
|
type: string
|
|
7102
|
+
/v1/conversations/archive/bulk:
|
|
7103
|
+
post:
|
|
7104
|
+
operationId: conversations_archive_bulk_post
|
|
7105
|
+
summary: Bulk archive conversations
|
|
7106
|
+
description: Archive multiple conversations in one request. Emits a single sync invalidation for the entire batch.
|
|
7107
|
+
tags:
|
|
7108
|
+
- conversations
|
|
7109
|
+
responses:
|
|
7110
|
+
"200":
|
|
7111
|
+
description: Successful response
|
|
7112
|
+
content:
|
|
7113
|
+
application/json:
|
|
7114
|
+
schema:
|
|
7115
|
+
type: object
|
|
7116
|
+
properties:
|
|
7117
|
+
ok:
|
|
7118
|
+
type: boolean
|
|
7119
|
+
archived:
|
|
7120
|
+
type: number
|
|
7121
|
+
required:
|
|
7122
|
+
- ok
|
|
7123
|
+
- archived
|
|
7124
|
+
additionalProperties: false
|
|
7125
|
+
requestBody:
|
|
7126
|
+
required: true
|
|
7127
|
+
content:
|
|
7128
|
+
application/json:
|
|
7129
|
+
schema:
|
|
7130
|
+
type: object
|
|
7131
|
+
properties:
|
|
7132
|
+
conversationIds:
|
|
7133
|
+
minItems: 1
|
|
7134
|
+
type: array
|
|
7135
|
+
items:
|
|
7136
|
+
type: string
|
|
7137
|
+
required:
|
|
7138
|
+
- conversationIds
|
|
7139
|
+
additionalProperties: false
|
|
7098
7140
|
/v1/conversations/attention:
|
|
7099
7141
|
get:
|
|
7100
7142
|
operationId: conversations_attention_get
|
|
@@ -7515,6 +7557,7 @@ paths:
|
|
|
7515
7557
|
- macos_notification_view
|
|
7516
7558
|
- macos_conversation_opened
|
|
7517
7559
|
- ios_conversation_opened
|
|
7560
|
+
- web_bulk_mark_read
|
|
7518
7561
|
- telegram_inbound_message
|
|
7519
7562
|
- telegram_callback
|
|
7520
7563
|
- slack_inbound_message
|
|
@@ -8522,6 +8565,46 @@ paths:
|
|
|
8522
8565
|
required:
|
|
8523
8566
|
- conversationId
|
|
8524
8567
|
additionalProperties: false
|
|
8568
|
+
/v1/conversations/seen/bulk:
|
|
8569
|
+
post:
|
|
8570
|
+
operationId: conversations_seen_bulk_post
|
|
8571
|
+
summary: Bulk mark conversations as seen
|
|
8572
|
+
description:
|
|
8573
|
+
Mark multiple conversations as seen in one request. Emits a single sync invalidation for the entire batch
|
|
8574
|
+
instead of per-conversation events.
|
|
8575
|
+
tags:
|
|
8576
|
+
- conversations
|
|
8577
|
+
responses:
|
|
8578
|
+
"200":
|
|
8579
|
+
description: Successful response
|
|
8580
|
+
content:
|
|
8581
|
+
application/json:
|
|
8582
|
+
schema:
|
|
8583
|
+
type: object
|
|
8584
|
+
properties:
|
|
8585
|
+
ok:
|
|
8586
|
+
type: boolean
|
|
8587
|
+
updated:
|
|
8588
|
+
type: number
|
|
8589
|
+
required:
|
|
8590
|
+
- ok
|
|
8591
|
+
- updated
|
|
8592
|
+
additionalProperties: false
|
|
8593
|
+
requestBody:
|
|
8594
|
+
required: true
|
|
8595
|
+
content:
|
|
8596
|
+
application/json:
|
|
8597
|
+
schema:
|
|
8598
|
+
type: object
|
|
8599
|
+
properties:
|
|
8600
|
+
conversationIds:
|
|
8601
|
+
minItems: 1
|
|
8602
|
+
type: array
|
|
8603
|
+
items:
|
|
8604
|
+
type: string
|
|
8605
|
+
required:
|
|
8606
|
+
- conversationIds
|
|
8607
|
+
additionalProperties: false
|
|
8525
8608
|
/v1/conversations/switch:
|
|
8526
8609
|
post:
|
|
8527
8610
|
operationId: conversations_switch_post
|
|
@@ -12920,6 +13003,23 @@ paths:
|
|
|
12920
13003
|
- source
|
|
12921
13004
|
- refreshing
|
|
12922
13005
|
additionalProperties: false
|
|
13006
|
+
parameters:
|
|
13007
|
+
- name: localHour
|
|
13008
|
+
in: query
|
|
13009
|
+
required: false
|
|
13010
|
+
schema:
|
|
13011
|
+
type: integer
|
|
13012
|
+
minimum: 0
|
|
13013
|
+
maximum: 23
|
|
13014
|
+
description: Optional client-local hour of day used only when refreshing generated greetings.
|
|
13015
|
+
- name: localMinute
|
|
13016
|
+
in: query
|
|
13017
|
+
required: false
|
|
13018
|
+
schema:
|
|
13019
|
+
type: integer
|
|
13020
|
+
minimum: 0
|
|
13021
|
+
maximum: 59
|
|
13022
|
+
description: Optional client-local minute used only when refreshing generated greetings.
|
|
12923
13023
|
/v1/image-generation/generate:
|
|
12924
13024
|
post:
|
|
12925
13025
|
operationId: imagegeneration_generate_post
|
|
@@ -19464,6 +19564,27 @@ paths:
|
|
|
19464
19564
|
ref:
|
|
19465
19565
|
type: string
|
|
19466
19566
|
description: Git ref the catalog metadata / README were resolved at.
|
|
19567
|
+
artifact:
|
|
19568
|
+
anyOf:
|
|
19569
|
+
- type: object
|
|
19570
|
+
properties:
|
|
19571
|
+
url:
|
|
19572
|
+
type: string
|
|
19573
|
+
description: HTTPS URL the prebuilt client artifact is downloaded from.
|
|
19574
|
+
sha256:
|
|
19575
|
+
type: string
|
|
19576
|
+
description: Lowercase 64-char hex SHA-256 the download is verified against.
|
|
19577
|
+
label:
|
|
19578
|
+
description: Optional human label for the download (e.g. "Download for macOS"); absent when the plugin doesn't name it.
|
|
19579
|
+
type: string
|
|
19580
|
+
required:
|
|
19581
|
+
- url
|
|
19582
|
+
- sha256
|
|
19583
|
+
additionalProperties: false
|
|
19584
|
+
- type: "null"
|
|
19585
|
+
description:
|
|
19586
|
+
Prebuilt client artifact from `package.json` `vellum.artifact`, or null when the plugin ships none or its
|
|
19587
|
+
descriptor is incomplete (e.g. a placeholder sha256).
|
|
19467
19588
|
required:
|
|
19468
19589
|
- name
|
|
19469
19590
|
- installed
|
|
@@ -19474,6 +19595,7 @@ paths:
|
|
|
19474
19595
|
- source
|
|
19475
19596
|
- readme
|
|
19476
19597
|
- ref
|
|
19598
|
+
- artifact
|
|
19477
19599
|
additionalProperties: false
|
|
19478
19600
|
"400":
|
|
19479
19601
|
description: The plugin name failed sanitization (e.g. contained slashes, dots, or uppercase letters).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vellumai/assistant",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.12-staging.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -50,7 +50,6 @@
|
|
|
50
50
|
"@vellumai/skill-host-contracts": "file:../packages/skill-host-contracts",
|
|
51
51
|
"@vellumai/slack-text": "file:../packages/slack-text",
|
|
52
52
|
"@vellumai/twilio-client": "file:../packages/twilio-client",
|
|
53
|
-
"archiver": "7.0.1",
|
|
54
53
|
"commander": "13.1.0",
|
|
55
54
|
"croner": "10.0.1",
|
|
56
55
|
"dotenv": "17.3.1",
|
|
@@ -97,7 +96,6 @@
|
|
|
97
96
|
},
|
|
98
97
|
"devDependencies": {
|
|
99
98
|
"@microsoft/api-extractor": "7.58.8",
|
|
100
|
-
"@types/archiver": "7.0.0",
|
|
101
99
|
"@types/bun": "1.3.10",
|
|
102
100
|
"@types/node": "25.5.0",
|
|
103
101
|
"@types/semver": "7.5.8",
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import {
|
|
2
|
+
existsSync,
|
|
3
|
+
mkdirSync,
|
|
4
|
+
readFileSync,
|
|
5
|
+
rmSync,
|
|
6
|
+
writeFileSync,
|
|
7
|
+
} from "node:fs";
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
11
|
+
|
|
12
|
+
import { repairAdaptiveThinkingOnManagedProfiles } from "../workspace/adaptive-thinking-repair.js";
|
|
13
|
+
import { enableAdaptiveThinkingManagedProfilesMigration } from "../workspace/migrations/097-enable-adaptive-thinking-managed-profiles.js";
|
|
14
|
+
|
|
15
|
+
const ADAPTIVE = { enabled: true, streamThinking: true };
|
|
16
|
+
|
|
17
|
+
let workspaceDir: string;
|
|
18
|
+
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
workspaceDir = join(
|
|
21
|
+
tmpdir(),
|
|
22
|
+
`vellum-adaptive-thinking-repair-test-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
23
|
+
);
|
|
24
|
+
mkdirSync(workspaceDir, { recursive: true });
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
if (existsSync(workspaceDir)) {
|
|
29
|
+
rmSync(workspaceDir, { recursive: true, force: true });
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
function writeConfig(data: Record<string, unknown>): void {
|
|
34
|
+
writeFileSync(
|
|
35
|
+
join(workspaceDir, "config.json"),
|
|
36
|
+
JSON.stringify(data, null, 2) + "\n",
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function readConfig(): Record<string, unknown> {
|
|
41
|
+
return JSON.parse(readFileSync(join(workspaceDir, "config.json"), "utf-8"));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function profile(name: string): Record<string, unknown> {
|
|
45
|
+
const config = readConfig();
|
|
46
|
+
const llm = config.llm as Record<string, unknown>;
|
|
47
|
+
const profiles = llm.profiles as Record<string, unknown>;
|
|
48
|
+
return profiles[name] as Record<string, unknown>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// The startup repair and migration 097 keep frozen copies of the same logic
|
|
52
|
+
// (migration modules must stay self-contained). Run every scenario against
|
|
53
|
+
// both so the copies can't drift.
|
|
54
|
+
const implementations: Array<[string, (dir: string) => void]> = [
|
|
55
|
+
["startup repair", repairAdaptiveThinkingOnManagedProfiles],
|
|
56
|
+
[
|
|
57
|
+
"migration 097",
|
|
58
|
+
(dir) => enableAdaptiveThinkingManagedProfilesMigration.run(dir),
|
|
59
|
+
],
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
describe.each(implementations)("%s", (_label, run) => {
|
|
63
|
+
test("patches managed Anthropic profiles missing thinking", () => {
|
|
64
|
+
writeConfig({
|
|
65
|
+
llm: {
|
|
66
|
+
default: { provider: "anthropic", model: "claude-sonnet-4-6" },
|
|
67
|
+
profiles: {
|
|
68
|
+
balanced: { source: "managed", provider: "anthropic" },
|
|
69
|
+
"quality-optimized": {
|
|
70
|
+
source: "managed",
|
|
71
|
+
provider: "anthropic",
|
|
72
|
+
thinking: { enabled: false },
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
run(workspaceDir);
|
|
79
|
+
|
|
80
|
+
expect(profile("balanced").thinking).toEqual(ADAPTIVE);
|
|
81
|
+
expect(profile("quality-optimized").thinking).toEqual(ADAPTIVE);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("skips source-less empty shells when llm.default.provider is non-Anthropic", () => {
|
|
85
|
+
// Migration 052 seeds empty {} shells (no source, no provider) on legacy
|
|
86
|
+
// non-Anthropic workspaces. They inherit the non-Anthropic provider from
|
|
87
|
+
// llm.default and must stay off the Anthropic-specific repair.
|
|
88
|
+
writeConfig({
|
|
89
|
+
llm: {
|
|
90
|
+
default: { provider: "gemini", model: "gemini-2.5-pro" },
|
|
91
|
+
profiles: {
|
|
92
|
+
balanced: {},
|
|
93
|
+
"quality-optimized": {},
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
run(workspaceDir);
|
|
99
|
+
|
|
100
|
+
expect(profile("balanced")).toEqual({});
|
|
101
|
+
expect(profile("quality-optimized")).toEqual({});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("treats absent llm.default.provider as Anthropic for source-less profiles", () => {
|
|
105
|
+
writeConfig({
|
|
106
|
+
llm: {
|
|
107
|
+
default: { model: "claude-sonnet-4-6" },
|
|
108
|
+
profiles: {
|
|
109
|
+
balanced: {},
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
run(workspaceDir);
|
|
115
|
+
|
|
116
|
+
expect(profile("balanced").thinking).toEqual(ADAPTIVE);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test("explicit Anthropic provider on the profile wins over a non-Anthropic default", () => {
|
|
120
|
+
writeConfig({
|
|
121
|
+
llm: {
|
|
122
|
+
default: { provider: "gemini" },
|
|
123
|
+
profiles: {
|
|
124
|
+
balanced: { provider: "anthropic" },
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
run(workspaceDir);
|
|
130
|
+
|
|
131
|
+
expect(profile("balanced").thinking).toEqual(ADAPTIVE);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("skips profiles with an explicit non-Anthropic provider", () => {
|
|
135
|
+
writeConfig({
|
|
136
|
+
llm: {
|
|
137
|
+
default: { provider: "anthropic" },
|
|
138
|
+
profiles: {
|
|
139
|
+
balanced: { provider: "gemini" },
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
run(workspaceDir);
|
|
145
|
+
|
|
146
|
+
expect(profile("balanced").thinking).toBeUndefined();
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("skips source: user profiles", () => {
|
|
150
|
+
writeConfig({
|
|
151
|
+
llm: {
|
|
152
|
+
default: { provider: "anthropic" },
|
|
153
|
+
profiles: {
|
|
154
|
+
balanced: { source: "user", provider: "anthropic" },
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
run(workspaceDir);
|
|
160
|
+
|
|
161
|
+
expect(profile("balanced").thinking).toBeUndefined();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("is idempotent when thinking is already enabled", () => {
|
|
165
|
+
const config = {
|
|
166
|
+
llm: {
|
|
167
|
+
default: { provider: "anthropic" },
|
|
168
|
+
profiles: {
|
|
169
|
+
balanced: {
|
|
170
|
+
source: "managed",
|
|
171
|
+
thinking: { enabled: true, streamThinking: false },
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
writeConfig(config);
|
|
177
|
+
|
|
178
|
+
run(workspaceDir);
|
|
179
|
+
|
|
180
|
+
expect(profile("balanced").thinking).toEqual({
|
|
181
|
+
enabled: true,
|
|
182
|
+
streamThinking: false,
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
});
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
* The compaction pipeline between `context_compacting` (start) and
|
|
5
5
|
* `compaction_completed` (end) is plugin-owned, so consumers reconstruct a
|
|
6
6
|
* compaction attempt purely from the pair — correlated by `compactionId`.
|
|
7
|
-
* These tests pin the pairing contract: shared id, trigger, timestamps,
|
|
8
|
-
* pre-compaction state on the start event
|
|
7
|
+
* These tests pin the pairing contract: shared id, trigger, timestamps,
|
|
8
|
+
* pre-compaction state on the start event, and the unnested
|
|
9
|
+
* `ContextWindowResult` fields on the end event.
|
|
9
10
|
*/
|
|
10
11
|
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
11
12
|
|
|
@@ -185,11 +186,11 @@ describe("AgentLoop compaction start/end event pair", () => {
|
|
|
185
186
|
expect(end!.finishedAt).toBeGreaterThanOrEqual(end!.startedAt);
|
|
186
187
|
expect(end!.finishedAt).toBeLessThanOrEqual(after);
|
|
187
188
|
|
|
188
|
-
// Start carries the pre-compaction history; end carries the
|
|
189
|
-
//
|
|
189
|
+
// Start carries the pre-compaction history; end carries the
|
|
190
|
+
// ContextWindowResult fields unnested on the event.
|
|
190
191
|
expect(start!.messages.length).toBeGreaterThan(0);
|
|
191
|
-
expect(end!.
|
|
192
|
-
expect(end!.
|
|
192
|
+
expect(end!.compacted).toBe(true);
|
|
193
|
+
expect(end!.exhausted).toBe(false);
|
|
193
194
|
|
|
194
195
|
// Start precedes end in the event stream.
|
|
195
196
|
expect(events.indexOf(start!)).toBeLessThan(events.indexOf(end!));
|
|
@@ -106,6 +106,7 @@ mock.module("@anthropic-ai/sdk", () => ({
|
|
|
106
106
|
}));
|
|
107
107
|
|
|
108
108
|
// Import after mocking
|
|
109
|
+
import { SYSTEM_PROMPT_CACHE_BOUNDARY } from "../prompts/cache-boundary.js";
|
|
109
110
|
import { AnthropicProvider } from "../providers/anthropic/client.js";
|
|
110
111
|
import {
|
|
111
112
|
isPlaceholderSentinelText,
|
|
@@ -308,6 +309,91 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
|
|
|
308
309
|
});
|
|
309
310
|
});
|
|
310
311
|
|
|
312
|
+
test("splits a boundary-carrying system prompt into two cached blocks and drops the tool breakpoint", async () => {
|
|
313
|
+
/**
|
|
314
|
+
* Tests that the SYSTEM_PROMPT_CACHE_BOUNDARY marker yields two
|
|
315
|
+
* independently cached system blocks, and that the explicit
|
|
316
|
+
* last-tool breakpoint is suppressed (the first system breakpoint
|
|
317
|
+
* already covers tools) so the total stays within Anthropic's
|
|
318
|
+
* 4-breakpoint budget.
|
|
319
|
+
*/
|
|
320
|
+
// GIVEN a system prompt carrying a cache boundary, plus tools and a
|
|
321
|
+
// tool-use loop (so turn-start and tail breakpoints also apply)
|
|
322
|
+
const prompt = `stable sections${SYSTEM_PROMPT_CACHE_BOUNDARY}volatile sections`;
|
|
323
|
+
const messages: Message[] = [
|
|
324
|
+
userMsg("Do something"),
|
|
325
|
+
toolUseMsg("tu_1", "bash"),
|
|
326
|
+
toolResultMsg("tu_1", "output"),
|
|
327
|
+
];
|
|
328
|
+
|
|
329
|
+
// WHEN the message is sent
|
|
330
|
+
await provider.sendMessage(messages, {
|
|
331
|
+
tools: sampleTools,
|
|
332
|
+
systemPrompt: prompt,
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// THEN the system prompt is split into two blocks, each 1h-cached
|
|
336
|
+
const system = lastStreamParams!.system as Array<{
|
|
337
|
+
type: string;
|
|
338
|
+
text: string;
|
|
339
|
+
cache_control?: { type: string; ttl?: string };
|
|
340
|
+
}>;
|
|
341
|
+
expect(system).toHaveLength(2);
|
|
342
|
+
expect(system[0].text).toBe("stable sections");
|
|
343
|
+
expect(system[1].text).toBe("volatile sections");
|
|
344
|
+
expect(system[0].cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
|
|
345
|
+
expect(system[1].cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
|
|
346
|
+
|
|
347
|
+
// AND no tool carries a breakpoint (system block 1 covers them)
|
|
348
|
+
const tools = lastStreamParams!.tools as Array<{
|
|
349
|
+
cache_control?: { type: string; ttl?: string };
|
|
350
|
+
}>;
|
|
351
|
+
for (const tool of tools) {
|
|
352
|
+
expect(tool.cache_control).toBeUndefined();
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// AND the turn-start and tail message breakpoints are unchanged,
|
|
356
|
+
// keeping the total at the 4-breakpoint cap
|
|
357
|
+
const sent = lastStreamParams!.messages as Array<{
|
|
358
|
+
role: string;
|
|
359
|
+
content: Array<{
|
|
360
|
+
type: string;
|
|
361
|
+
cache_control?: { type: string; ttl?: string };
|
|
362
|
+
}>;
|
|
363
|
+
}>;
|
|
364
|
+
const turnStart = sent[0];
|
|
365
|
+
expect(
|
|
366
|
+
turnStart.content[turnStart.content.length - 1].cache_control,
|
|
367
|
+
).toEqual({ type: "ephemeral", ttl: "1h" });
|
|
368
|
+
const lastMsg = sent[sent.length - 1];
|
|
369
|
+
expect(lastMsg.content[lastMsg.content.length - 1].cache_control).toEqual({
|
|
370
|
+
type: "ephemeral",
|
|
371
|
+
ttl: "5m",
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
test("keeps the last-tool breakpoint when the system prompt has no boundary", async () => {
|
|
376
|
+
/**
|
|
377
|
+
* Tests that a boundary-free system prompt preserves the explicit
|
|
378
|
+
* tool breakpoint (single system block leaves budget for it).
|
|
379
|
+
*/
|
|
380
|
+
// GIVEN a system prompt without a cache boundary and tools
|
|
381
|
+
// WHEN the message is sent
|
|
382
|
+
await provider.sendMessage([userMsg("Hi")], {
|
|
383
|
+
tools: sampleTools,
|
|
384
|
+
systemPrompt: "You are helpful.",
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
// THEN the last tool keeps its breakpoint
|
|
388
|
+
const tools = lastStreamParams!.tools as Array<{
|
|
389
|
+
cache_control?: { type: string; ttl?: string };
|
|
390
|
+
}>;
|
|
391
|
+
expect(tools[tools.length - 1].cache_control).toEqual({
|
|
392
|
+
type: "ephemeral",
|
|
393
|
+
ttl: "1h",
|
|
394
|
+
});
|
|
395
|
+
});
|
|
396
|
+
|
|
311
397
|
// -----------------------------------------------------------------------
|
|
312
398
|
// Tool cache control
|
|
313
399
|
// -----------------------------------------------------------------------
|
|
@@ -389,6 +475,49 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
|
|
|
389
475
|
).not.toContain("extended-cache-ttl-2025-04-11");
|
|
390
476
|
});
|
|
391
477
|
|
|
478
|
+
test("disableCache sends no cache_control anywhere and strips caller-stamped block markers", async () => {
|
|
479
|
+
// A one-shot call site that opted out of prompt caching: no breakpoint
|
|
480
|
+
// on system, tools, turn-start, or tail — and a caller-stamped block
|
|
481
|
+
// marker is removed rather than forwarded.
|
|
482
|
+
const messages: Message[] = [
|
|
483
|
+
{
|
|
484
|
+
role: "user",
|
|
485
|
+
content: [
|
|
486
|
+
cachedPrefixBlock("stable pages block"),
|
|
487
|
+
{ type: "text", text: "Do something" },
|
|
488
|
+
],
|
|
489
|
+
},
|
|
490
|
+
toolUseMsg("tu_1", "bash"),
|
|
491
|
+
toolResultMsg("tu_1", "output"),
|
|
492
|
+
];
|
|
493
|
+
await provider.sendMessage(messages, {
|
|
494
|
+
tools: sampleTools,
|
|
495
|
+
systemPrompt: "You are a helpful assistant.",
|
|
496
|
+
config: { disableCache: true },
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
const system = lastStreamParams!.system as Array<{
|
|
500
|
+
cache_control?: unknown;
|
|
501
|
+
}>;
|
|
502
|
+
expect(system[0].cache_control).toBeUndefined();
|
|
503
|
+
|
|
504
|
+
const tools = lastStreamParams!.tools as Array<{
|
|
505
|
+
cache_control?: unknown;
|
|
506
|
+
}>;
|
|
507
|
+
for (const tool of tools) {
|
|
508
|
+
expect(tool.cache_control).toBeUndefined();
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
const sent = lastStreamParams!.messages as Array<{
|
|
512
|
+
content: Array<{ cache_control?: unknown }>;
|
|
513
|
+
}>;
|
|
514
|
+
for (const message of sent) {
|
|
515
|
+
for (const block of message.content) {
|
|
516
|
+
expect(block.cache_control).toBeUndefined();
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
|
|
392
521
|
test("v3-shape call (system + tools + cached prefix block) stays within the 4-breakpoint cap", async () => {
|
|
393
522
|
// Mirrors a v3 L2 selector call: a system prompt, a forced tool, and a user
|
|
394
523
|
// message whose stable <pages> block carries a cache_control breakpoint
|