zeitlich 0.2.46 → 0.2.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -6
- package/dist/{activities-CyeiqK_f.d.cts → activities-CPwKoUlD.d.cts} +3 -3
- package/dist/{activities-Bm4TLTid.d.ts → activities-DlaBxNID.d.ts} +3 -3
- package/dist/adapters/thread/anthropic/index.cjs +105 -6
- package/dist/adapters/thread/anthropic/index.cjs.map +1 -1
- package/dist/adapters/thread/anthropic/index.d.cts +48 -9
- package/dist/adapters/thread/anthropic/index.d.ts +48 -9
- package/dist/adapters/thread/anthropic/index.js +104 -7
- package/dist/adapters/thread/anthropic/index.js.map +1 -1
- package/dist/adapters/thread/anthropic/workflow.cjs +38 -22
- package/dist/adapters/thread/anthropic/workflow.cjs.map +1 -1
- package/dist/adapters/thread/anthropic/workflow.d.cts +5 -4
- package/dist/adapters/thread/anthropic/workflow.d.ts +5 -4
- package/dist/adapters/thread/anthropic/workflow.js +38 -22
- package/dist/adapters/thread/anthropic/workflow.js.map +1 -1
- package/dist/adapters/thread/google-genai/index.d.cts +6 -5
- package/dist/adapters/thread/google-genai/index.d.ts +6 -5
- package/dist/adapters/thread/google-genai/workflow.cjs +38 -22
- package/dist/adapters/thread/google-genai/workflow.cjs.map +1 -1
- package/dist/adapters/thread/google-genai/workflow.d.cts +7 -5
- package/dist/adapters/thread/google-genai/workflow.d.ts +7 -5
- package/dist/adapters/thread/google-genai/workflow.js +38 -22
- package/dist/adapters/thread/google-genai/workflow.js.map +1 -1
- package/dist/adapters/thread/langchain/index.d.cts +6 -5
- package/dist/adapters/thread/langchain/index.d.ts +6 -5
- package/dist/adapters/thread/langchain/workflow.cjs +38 -22
- package/dist/adapters/thread/langchain/workflow.cjs.map +1 -1
- package/dist/adapters/thread/langchain/workflow.d.cts +5 -4
- package/dist/adapters/thread/langchain/workflow.d.ts +5 -4
- package/dist/adapters/thread/langchain/workflow.js +38 -22
- package/dist/adapters/thread/langchain/workflow.js.map +1 -1
- package/dist/{cold-store-CFHwemBJ.d.ts → cold-store-BDgJpwLI.d.ts} +8 -11
- package/dist/{cold-store-BC5L5Z8A.d.cts → cold-store-Z2wvK2cV.d.cts} +8 -11
- package/dist/index.cjs +264 -90
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -9
- package/dist/index.d.ts +21 -9
- package/dist/index.js +265 -93
- package/dist/index.js.map +1 -1
- package/dist/proxy-CDh3Rsa7.d.cts +40 -0
- package/dist/proxy-Du8ggERu.d.ts +40 -0
- package/dist/{thread-manager-D33SUmZa.d.cts → thread-manager-BjoYYXgd.d.cts} +2 -2
- package/dist/{thread-manager-9tezUcLW.d.cts → thread-manager-D8zKNFZ9.d.cts} +2 -2
- package/dist/{thread-manager-B-zy3xrs.d.ts → thread-manager-DtHYws2F.d.ts} +2 -2
- package/dist/{thread-manager-DduoSkvJ.d.ts → thread-manager-Dw96FKH1.d.ts} +2 -2
- package/dist/{types-oxt8GN97.d.cts → types-BMJrsHo0.d.cts} +1 -1
- package/dist/{types-L5bvbF-n.d.ts → types-CtdOquo3.d.ts} +1 -1
- package/dist/{types-CnuN9T6t.d.cts → types-DNEl5uxQ.d.cts} +16 -0
- package/dist/{types-CwN6_tAL.d.ts → types-qQVZfhoT.d.ts} +16 -0
- package/dist/{workflow-DIaIV7L2.d.cts → workflow-BH9ImDGq.d.cts} +17 -2
- package/dist/{workflow-B1TOcHbt.d.ts → workflow-Cdw3-RNB.d.ts} +17 -2
- package/dist/workflow.cjs +33 -3
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +2 -2
- package/dist/workflow.d.ts +2 -2
- package/dist/workflow.js +33 -4
- package/dist/workflow.js.map +1 -1
- package/package.json +9 -3
- package/src/adapters/thread/anthropic/activities.ts +18 -11
- package/src/adapters/thread/anthropic/index.ts +8 -0
- package/src/adapters/thread/anthropic/model-invoker.test.ts +110 -0
- package/src/adapters/thread/anthropic/model-invoker.ts +26 -5
- package/src/adapters/thread/anthropic/prompt-cache.test.ts +134 -0
- package/src/adapters/thread/anthropic/prompt-cache.ts +163 -0
- package/src/adapters/thread/anthropic/proxy.ts +1 -0
- package/src/adapters/thread/google-genai/proxy.ts +1 -0
- package/src/adapters/thread/langchain/proxy.ts +1 -0
- package/src/index.ts +1 -1
- package/src/lib/subagent/define.ts +1 -0
- package/src/lib/subagent/handler.ts +11 -2
- package/src/lib/subagent/subagent.integration.test.ts +139 -0
- package/src/lib/subagent/types.ts +16 -0
- package/src/lib/thread/cold-store.test.ts +33 -5
- package/src/lib/thread/cold-store.ts +50 -31
- package/src/lib/thread/proxy.ts +79 -29
- package/src/tools/edit/handler.test.ts +177 -0
- package/src/tools/edit/handler.ts +249 -47
- package/src/tools/edit/tool.ts +40 -0
- package/src/tools/task-create/handler.ts +1 -1
- package/src/tools/task-update/handler.ts +1 -1
- package/src/workflow.ts +2 -2
- package/dist/proxy-BxFyd6cg.d.cts +0 -24
- package/dist/proxy-Cskmj4Yx.d.ts +0 -24
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
**Durable AI Agents for Temporal**
|
|
10
10
|
|
|
11
|
-
Zeitlich is an opinionated
|
|
11
|
+
Zeitlich is an opinionated harness for building reliable, stateful AI agents using [Temporal](https://temporal.io). It provides the building blocks for creating agents that can survive crashes, handle long-running tasks, and coordinate with other agents—all with full type safety.
|
|
12
12
|
|
|
13
13
|
## Why Zeitlich?
|
|
14
14
|
|
|
@@ -104,6 +104,7 @@ npm install zeitlich ioredis \
|
|
|
104
104
|
- `@google/genai` >= 1.0.0 (optional — only when using the Google GenAI adapter)
|
|
105
105
|
- `@aws-sdk/client-bedrock-agentcore` >= 3.900.0 (optional — only when using the Bedrock adapter)
|
|
106
106
|
- `@aws-sdk/client-s3` >= 3.700.0 (optional — only when using the built-in S3 cold thread tier)
|
|
107
|
+
- `@aws-sdk/lib-storage` >= 3.700.0 (optional — paired with `@aws-sdk/client-s3` for multipart uploads in the S3 cold tier)
|
|
107
108
|
|
|
108
109
|
> **Why peer deps?** Zeitlich's public API surfaces `@temporalio/*` types
|
|
109
110
|
> (`UpdateDefinition`, `ChildWorkflowOptions`, `Duration`, etc.) directly. Peer
|
|
@@ -671,10 +672,10 @@ const continuedSession = await createSession({
|
|
|
671
672
|
|
|
672
673
|
By default every thread lives in Redis with a 90-day TTL — both messages and the persisted state slice. For long-lived agents, that ties up hot memory for inactive conversations and ties durability to your Redis retention. Zeitlich's tiered storage moves cold threads to a durable archive (S3, R2, GCS, …) while keeping Redis as the hot tier only for the duration of a workflow run.
|
|
673
674
|
|
|
674
|
-
| Tier
|
|
675
|
-
|
|
|
676
|
-
| Hot
|
|
677
|
-
| Cold
|
|
675
|
+
| Tier | Backend | Lifetime |
|
|
676
|
+
| ---- | ----------------------------------------- | ------------------------------------------------------ |
|
|
677
|
+
| Hot | Redis | Only while a workflow run is active (configurable TTL) |
|
|
678
|
+
| Cold | Pluggable `ColdThreadStore` (built-in S3) | Durable across runs |
|
|
678
679
|
|
|
679
680
|
The session wiring is fully automatic:
|
|
680
681
|
|
|
@@ -708,6 +709,30 @@ const adapter = createAnthropicAdapter({
|
|
|
708
709
|
|
|
709
710
|
That's the only change required — `createSession`, all `ThreadInit` modes, and every adapter activity are already wired for the lifecycle. When `coldStore` is omitted, the adapter behaves identically to the Redis-only baseline.
|
|
710
711
|
|
|
712
|
+
##### Anthropic prompt caching
|
|
713
|
+
|
|
714
|
+
The Anthropic adapter enables 5-minute ephemeral prompt caching by default. Before each `messages.stream()` call, it adds an explicit block-level `cache_control: { type: "ephemeral", ttl: "5m" }` marker to the last cacheable message content block. Zeitlich intentionally uses the block-level shape instead of Anthropic's top-level automatic cache-control parameter so the same request body works with Anthropic direct API clients and Anthropic-on-Bedrock `InvokeModel` clients.
|
|
715
|
+
|
|
716
|
+
```typescript
|
|
717
|
+
const adapter = createAnthropicAdapter({
|
|
718
|
+
redis,
|
|
719
|
+
client: anthropic,
|
|
720
|
+
model: "claude-sonnet-4-20250514",
|
|
721
|
+
// Optional: 5m is the default; set explicitly if you prefer clarity.
|
|
722
|
+
promptCache: { ttl: "5m" },
|
|
723
|
+
});
|
|
724
|
+
|
|
725
|
+
// Disable if a model/provider route does not support prompt caching.
|
|
726
|
+
const uncachedAdapter = createAnthropicAdapter({
|
|
727
|
+
redis,
|
|
728
|
+
client: anthropic,
|
|
729
|
+
model: "claude-sonnet-4-20250514",
|
|
730
|
+
promptCache: false,
|
|
731
|
+
});
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
If you already provide your own `cache_control` markers, Zeitlich preserves them and skips its automatic marker when the request already has the provider maximum of four cache breakpoints.
|
|
735
|
+
|
|
711
736
|
##### Custom backends
|
|
712
737
|
|
|
713
738
|
`ColdThreadStore` is intentionally minimal:
|
|
@@ -715,7 +740,11 @@ That's the only change required — `createSession`, all `ThreadInit` modes, and
|
|
|
715
740
|
```typescript
|
|
716
741
|
interface ColdThreadStore {
|
|
717
742
|
read(threadKey: string, threadId: string): Promise<ThreadSnapshot | null>;
|
|
718
|
-
write(
|
|
743
|
+
write(
|
|
744
|
+
threadKey: string,
|
|
745
|
+
threadId: string,
|
|
746
|
+
snapshot: ThreadSnapshot
|
|
747
|
+
): Promise<void>;
|
|
719
748
|
delete(threadKey: string, threadId: string): Promise<void>;
|
|
720
749
|
}
|
|
721
750
|
```
|
|
@@ -729,6 +758,23 @@ Any backend that can satisfy these three calls — Cloudflare R2, Google Cloud S
|
|
|
729
758
|
- **`deleteHot: true` by default on flush.** Memory drops immediately; the next continue re-hydrates in one `GetObject`. Override per-call via the tiered manager if you want to keep the hot tier warm.
|
|
730
759
|
- **`mode: "new"` overwrites the cold archive for that `threadId`.** A session entered with `mode: "new"` skips `hydrateThread`; on exit `flushThread` writes the fresh snapshot back, silently replacing any prior cold-tier blob at the same `(threadKey, threadId)`. To resume a thread, use `mode: "continue"` or `mode: "fork"` — passing a previously-used `threadId` with `mode: "new"` is destructive by design.
|
|
731
760
|
|
|
761
|
+
##### Activity timeouts
|
|
762
|
+
|
|
763
|
+
`hydrateThread` and `flushThread` automatically get `startToCloseTimeout: "60s"` and `heartbeatTimeout: "15s"`. The S3 cold store uses multipart `Upload` for writes and streams the `GetObject` response on reads — each part completion / stream chunk emits a heartbeat, so a stalled upload or download trips `heartbeatTimeout` (15s) rather than waiting out `startToCloseTimeout` (60s). The Redis-only ops keep the tight `10s` baseline.
|
|
764
|
+
|
|
765
|
+
To override an individual op without inflating the rest:
|
|
766
|
+
|
|
767
|
+
```typescript
|
|
768
|
+
const threadOps = proxyGoogleGenAIThreadOps(undefined, {
|
|
769
|
+
defaults: { startToCloseTimeout: "5s" }, // applied to every op
|
|
770
|
+
perOp: {
|
|
771
|
+
flushThread: { startToCloseTimeout: "180s" }, // overlays cold-tier defaults; heartbeatTimeout still inherited
|
|
772
|
+
},
|
|
773
|
+
});
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
`perOp[op]` is layered shallow-rightmost over `defaults` and the built-in cold-tier overlays for `hydrateThread` / `flushThread` — so a partial override only replaces the fields you specify. A bare `ActivityOptions` object is also accepted and treated as `{ defaults: <that object> }`, with the cold-tier overlay still applied on top — to raise the cold-tier ceiling above `60s`, use `perOp.flushThread` / `perOp.hydrateThread`.
|
|
777
|
+
|
|
732
778
|
#### Sandbox Initialization (`SandboxInit`)
|
|
733
779
|
|
|
734
780
|
The `sandbox` field controls how a sandbox is created or reused:
|
|
@@ -833,6 +879,17 @@ Trade-off: cleanup is deferred to parent close (no eager GC of superseded thread
|
|
|
833
879
|
|
|
834
880
|
The `thread` field accepts `"new"` (default), `"fork"`, or `"continue"`. When set to `"fork"` or `"continue"`, the parent agent can pass a `threadId` in a subsequent `Task` tool call to resume the conversation. The subagent returns its `threadId` in the response (surfaced as `[Thread ID: ...]`), which the parent can use for continuation.
|
|
835
881
|
|
|
882
|
+
The `newThreadSource` field controls what to do when the parent's tool call omits `threadId`. It accepts `"new"` (default — start a fresh thread) or `"from-parent"` (fork/continue the parent agent's own thread). Useful when you want a subagent that inherits the parent's conversation state by default without requiring the LLM to explicitly thread the id through:
|
|
883
|
+
|
|
884
|
+
```typescript
|
|
885
|
+
export const researcherSubagent = defineSubagent(researcherWorkflow, {
|
|
886
|
+
thread: "fork",
|
|
887
|
+
newThreadSource: "from-parent", // no threadId → fork the parent's thread
|
|
888
|
+
});
|
|
889
|
+
```
|
|
890
|
+
|
|
891
|
+
An explicit `threadId` from the parent's tool call always wins; `newThreadSource` only applies when none is provided. The field has no effect with `thread: "new"`.
|
|
892
|
+
|
|
836
893
|
The `sandbox` field accepts `"none"` (default) or an object with `source`, `continuation`, and optional `init`/`shutdown` fields:
|
|
837
894
|
|
|
838
895
|
- `source: "inherit"` — use the parent's sandbox. `continuation: "continue"` shares it directly; `"fork"` forks from it on every call.
|
|
@@ -1050,6 +1107,7 @@ Framework-agnostic utilities for activities, worker setup, and Node.js code:
|
|
|
1050
1107
|
| --------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
1051
1108
|
| `createRunAgentActivity` | Wraps a handler into a scope-prefixed `RunAgentActivity` with auto-fetched parent workflow state |
|
|
1052
1109
|
| `withParentWorkflowState` | Wraps a tool handler into an `ActivityToolHandler` with auto-fetched parent workflow state |
|
|
1110
|
+
| `getActivityContext` | Safely returns `{ heartbeat, signal }` from the current Temporal activity, or `{}` outside one |
|
|
1053
1111
|
| `createThreadManager` | Generic Redis-backed thread manager factory |
|
|
1054
1112
|
| `createTieredThreadManager` | Redis hot + pluggable cold tier; adds `hydrate()` / `flush()` to `BaseThreadManager<T>` |
|
|
1055
1113
|
| `createS3ColdStore` | Built-in `ColdThreadStore` backed by an `@aws-sdk/client-s3` `S3Client` |
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import Redis from 'ioredis';
|
|
2
2
|
import { Part, Content, GoogleGenAI } from '@google/genai';
|
|
3
|
-
import { a as ModelInvoker, b as PrefixedThreadOps, S as ScopedPrefix, R as RouterContext, c as ToolHandlerResponse, d as ActivityToolHandler } from './types-
|
|
4
|
-
import { C as ColdThreadStore } from './cold-store-
|
|
5
|
-
import { T as ThreadManagerHooks, P as ProviderThreadManager } from './types-
|
|
3
|
+
import { a as ModelInvoker, b as PrefixedThreadOps, S as ScopedPrefix, R as RouterContext, c as ToolHandlerResponse, d as ActivityToolHandler } from './types-DNEl5uxQ.cjs';
|
|
4
|
+
import { C as ColdThreadStore } from './cold-store-Z2wvK2cV.cjs';
|
|
5
|
+
import { T as ThreadManagerHooks, P as ProviderThreadManager } from './types-BMJrsHo0.cjs';
|
|
6
6
|
import { A as ADAPTER_ID } from './adapter-id-BB-mmrts.cjs';
|
|
7
7
|
|
|
8
8
|
/** SDK-native content type for Google GenAI human messages */
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import Redis from 'ioredis';
|
|
2
2
|
import { Part, Content, GoogleGenAI } from '@google/genai';
|
|
3
|
-
import { a as ModelInvoker, b as PrefixedThreadOps, S as ScopedPrefix, R as RouterContext, c as ToolHandlerResponse, d as ActivityToolHandler } from './types-
|
|
4
|
-
import { C as ColdThreadStore } from './cold-store-
|
|
5
|
-
import { T as ThreadManagerHooks, P as ProviderThreadManager } from './types-
|
|
3
|
+
import { a as ModelInvoker, b as PrefixedThreadOps, S as ScopedPrefix, R as RouterContext, c as ToolHandlerResponse, d as ActivityToolHandler } from './types-qQVZfhoT.js';
|
|
4
|
+
import { C as ColdThreadStore } from './cold-store-BDgJpwLI.js';
|
|
5
|
+
import { T as ThreadManagerHooks, P as ProviderThreadManager } from './types-CtdOquo3.js';
|
|
6
6
|
import { A as ADAPTER_ID } from './adapter-id-BB-mmrts.js';
|
|
7
7
|
|
|
8
8
|
/** SDK-native content type for Google GenAI human messages */
|
|
@@ -418,6 +418,94 @@ function createAnthropicThreadManager(config) {
|
|
|
418
418
|
};
|
|
419
419
|
return manager;
|
|
420
420
|
}
|
|
421
|
+
|
|
422
|
+
// src/adapters/thread/anthropic/prompt-cache.ts
|
|
423
|
+
var DEFAULT_MAX_CACHE_BREAKPOINTS = 4;
|
|
424
|
+
var UNCACHEABLE_BLOCK_TYPES = /* @__PURE__ */ new Set(["thinking", "redacted_thinking"]);
|
|
425
|
+
function resolvePromptCacheOptions(promptCache) {
|
|
426
|
+
if (promptCache === false) return void 0;
|
|
427
|
+
if (promptCache === true || promptCache === void 0) return {};
|
|
428
|
+
return promptCache;
|
|
429
|
+
}
|
|
430
|
+
function addPromptCacheControl(payload, options = {}) {
|
|
431
|
+
const maxBreakpoints = options.maxBreakpoints ?? DEFAULT_MAX_CACHE_BREAKPOINTS;
|
|
432
|
+
if (maxBreakpoints <= 0) return payload;
|
|
433
|
+
if (countCacheControls(payload) >= maxBreakpoints) return payload;
|
|
434
|
+
const cacheControl = {
|
|
435
|
+
type: "ephemeral",
|
|
436
|
+
ttl: options.ttl ?? "5m"
|
|
437
|
+
};
|
|
438
|
+
const messages = addCacheControlToLastMessageBlock(
|
|
439
|
+
payload.messages,
|
|
440
|
+
cacheControl
|
|
441
|
+
);
|
|
442
|
+
if (messages === payload.messages) return payload;
|
|
443
|
+
return { ...payload, messages };
|
|
444
|
+
}
|
|
445
|
+
function addCacheControlToLastMessageBlock(messages, cacheControl) {
|
|
446
|
+
for (let messageIndex = messages.length - 1; messageIndex >= 0; messageIndex--) {
|
|
447
|
+
const message = messages[messageIndex];
|
|
448
|
+
if (!message) continue;
|
|
449
|
+
if (typeof message.content === "string") {
|
|
450
|
+
if (message.content.length === 0) continue;
|
|
451
|
+
return replaceMessage(messages, messageIndex, {
|
|
452
|
+
...message,
|
|
453
|
+
content: [
|
|
454
|
+
{ type: "text", text: message.content, cache_control: cacheControl }
|
|
455
|
+
]
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
if (!Array.isArray(message.content)) continue;
|
|
459
|
+
for (let blockIndex = message.content.length - 1; blockIndex >= 0; blockIndex--) {
|
|
460
|
+
const block = message.content[blockIndex];
|
|
461
|
+
if (!isCacheableContentBlock(block)) continue;
|
|
462
|
+
if (hasCacheControl(block)) return messages;
|
|
463
|
+
const content = [...message.content];
|
|
464
|
+
content[blockIndex] = {
|
|
465
|
+
...block,
|
|
466
|
+
cache_control: cacheControl
|
|
467
|
+
};
|
|
468
|
+
return replaceMessage(messages, messageIndex, { ...message, content });
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
return messages;
|
|
472
|
+
}
|
|
473
|
+
function replaceMessage(messages, index, message) {
|
|
474
|
+
const next = [...messages];
|
|
475
|
+
next[index] = message;
|
|
476
|
+
return next;
|
|
477
|
+
}
|
|
478
|
+
function isCacheableContentBlock(block) {
|
|
479
|
+
if (!isRecord(block)) return false;
|
|
480
|
+
const type = typeof block.type === "string" ? block.type : void 0;
|
|
481
|
+
if (type && UNCACHEABLE_BLOCK_TYPES.has(type)) return false;
|
|
482
|
+
if (type === "text" && block.text === "") return false;
|
|
483
|
+
return true;
|
|
484
|
+
}
|
|
485
|
+
function countCacheControls(payload) {
|
|
486
|
+
let count = 0;
|
|
487
|
+
for (const tool of payload.tools ?? []) {
|
|
488
|
+
if (hasCacheControl(tool)) count++;
|
|
489
|
+
}
|
|
490
|
+
if (Array.isArray(payload.system)) {
|
|
491
|
+
for (const block of payload.system) {
|
|
492
|
+
if (hasCacheControl(block)) count++;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
for (const message of payload.messages) {
|
|
496
|
+
if (!Array.isArray(message.content)) continue;
|
|
497
|
+
for (const block of message.content) {
|
|
498
|
+
if (hasCacheControl(block)) count++;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
return count;
|
|
502
|
+
}
|
|
503
|
+
function hasCacheControl(value) {
|
|
504
|
+
return isRecord(value) && value.cache_control != null;
|
|
505
|
+
}
|
|
506
|
+
function isRecord(value) {
|
|
507
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
508
|
+
}
|
|
421
509
|
function getActivityContext() {
|
|
422
510
|
try {
|
|
423
511
|
const ctx = activity.Context.current();
|
|
@@ -440,6 +528,7 @@ function createAnthropicModelInvoker({
|
|
|
440
528
|
client,
|
|
441
529
|
model,
|
|
442
530
|
maxTokens = 16384,
|
|
531
|
+
promptCache,
|
|
443
532
|
hooks
|
|
444
533
|
}) {
|
|
445
534
|
return async function invokeAnthropicModel2(config) {
|
|
@@ -452,15 +541,20 @@ function createAnthropicModelInvoker({
|
|
|
452
541
|
hooks
|
|
453
542
|
});
|
|
454
543
|
await thread.truncateFromId(assistantMessageId);
|
|
455
|
-
const
|
|
544
|
+
const prepared = await thread.prepareForInvocation();
|
|
456
545
|
const anthropicTools = toAnthropicTools(state.tools);
|
|
457
|
-
const
|
|
546
|
+
const preparedPayload = {
|
|
547
|
+
...prepared,
|
|
548
|
+
...anthropicTools.length > 0 ? { tools: anthropicTools } : {}
|
|
549
|
+
};
|
|
550
|
+
const cacheOptions = resolvePromptCacheOptions(promptCache);
|
|
551
|
+
const payload = cacheOptions ? addPromptCacheControl(preparedPayload, cacheOptions) : preparedPayload;
|
|
458
552
|
const params = {
|
|
459
553
|
model,
|
|
460
554
|
max_tokens: maxTokens,
|
|
461
|
-
messages,
|
|
462
|
-
...system ? { system } : {},
|
|
463
|
-
...tools ? { tools } : {}
|
|
555
|
+
messages: payload.messages,
|
|
556
|
+
...payload.system ? { system: payload.system } : {},
|
|
557
|
+
...payload.tools ? { tools: payload.tools } : {}
|
|
464
558
|
};
|
|
465
559
|
const stream = client.messages.stream(params, { signal });
|
|
466
560
|
for await (const _event of stream) {
|
|
@@ -491,6 +585,7 @@ async function invokeAnthropicModel({
|
|
|
491
585
|
client,
|
|
492
586
|
model,
|
|
493
587
|
maxTokens,
|
|
588
|
+
promptCache,
|
|
494
589
|
hooks,
|
|
495
590
|
config
|
|
496
591
|
}) {
|
|
@@ -499,6 +594,7 @@ async function invokeAnthropicModel({
|
|
|
499
594
|
client,
|
|
500
595
|
model,
|
|
501
596
|
maxTokens,
|
|
597
|
+
promptCache,
|
|
502
598
|
hooks
|
|
503
599
|
});
|
|
504
600
|
return invoker(config);
|
|
@@ -584,13 +680,14 @@ function createAnthropicAdapter(config) {
|
|
|
584
680
|
Object.entries(threadOps).map(([k, v]) => [`${prefix}${cap(k)}`, v])
|
|
585
681
|
);
|
|
586
682
|
}
|
|
587
|
-
const makeInvoker = (model, maxTokens) => {
|
|
683
|
+
const makeInvoker = (model, maxTokens, promptCache) => {
|
|
588
684
|
const invokerConfig = {
|
|
589
685
|
redis,
|
|
590
686
|
client,
|
|
591
687
|
model,
|
|
592
688
|
...maxTokens !== void 0 ? { maxTokens } : {},
|
|
593
689
|
...config.maxTokens !== void 0 && maxTokens === void 0 ? { maxTokens: config.maxTokens } : {},
|
|
690
|
+
...promptCache !== void 0 ? { promptCache } : config.promptCache !== void 0 ? { promptCache: config.promptCache } : {},
|
|
594
691
|
hooks: config.hooks
|
|
595
692
|
};
|
|
596
693
|
return createAnthropicModelInvoker(invokerConfig);
|
|
@@ -609,9 +706,11 @@ function createAnthropicAdapter(config) {
|
|
|
609
706
|
}
|
|
610
707
|
|
|
611
708
|
exports.ADAPTER_ID = ADAPTER_ID;
|
|
709
|
+
exports.addPromptCacheControl = addPromptCacheControl;
|
|
612
710
|
exports.createAnthropicAdapter = createAnthropicAdapter;
|
|
613
711
|
exports.createAnthropicModelInvoker = createAnthropicModelInvoker;
|
|
614
712
|
exports.createAnthropicThreadManager = createAnthropicThreadManager;
|
|
615
713
|
exports.invokeAnthropicModel = invokeAnthropicModel;
|
|
714
|
+
exports.resolvePromptCacheOptions = resolvePromptCacheOptions;
|
|
616
715
|
//# sourceMappingURL=index.cjs.map
|
|
617
716
|
//# sourceMappingURL=index.cjs.map
|