praxis-agent 0.29.0 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/application/top-level-agent-manager.js +8 -0
- package/dist/cli-runtime.js +45 -13
- package/dist/mcp/claude-mcp-tools.js +2 -1
- package/dist/providers/anthropic-compatible.d.ts +3 -0
- package/dist/providers/anthropic-compatible.js +63 -7
- package/dist/providers/anthropic-prompt-cache.d.ts +11 -0
- package/dist/providers/anthropic-prompt-cache.js +58 -0
- package/dist/providers/environment.js +12 -0
- package/package.json +1 -1
|
@@ -30,6 +30,14 @@ const WORKER_RUNTIME_ENVIRONMENT = [
|
|
|
30
30
|
'PRAXIS_MAX_OUTPUT_TOKENS',
|
|
31
31
|
'PRAXIS_ANTHROPIC_VERSION',
|
|
32
32
|
'PRAXIS_ANTHROPIC_WEB_SEARCH',
|
|
33
|
+
'PRAXIS_ANTHROPIC_PROMPT_CACHING',
|
|
34
|
+
'PRAXIS_ANTHROPIC_PROMPT_CACHE_TTL',
|
|
35
|
+
'DISABLE_PROMPT_CACHING',
|
|
36
|
+
'DISABLE_PROMPT_CACHING_HAIKU',
|
|
37
|
+
'DISABLE_PROMPT_CACHING_SONNET',
|
|
38
|
+
'DISABLE_PROMPT_CACHING_OPUS',
|
|
39
|
+
'ENABLE_PROMPT_CACHING_1H',
|
|
40
|
+
'FORCE_PROMPT_CACHING_5M',
|
|
33
41
|
'PRAXIS_CONTEXT_WINDOW_TOKENS',
|
|
34
42
|
'PRAXIS_CONTEXT_RESERVE_TOKENS',
|
|
35
43
|
'PRAXIS_PRICING_JSON',
|
package/dist/cli-runtime.js
CHANGED
|
@@ -39,6 +39,7 @@ import { writeFileAtomically } from './platform/atomic-write.js';
|
|
|
39
39
|
import { detectInstalledClaudeVersion } from './platform/claude-version.js';
|
|
40
40
|
import { redactSensitiveText, sensitiveEnvironmentValues, } from './platform/sensitive-data.js';
|
|
41
41
|
import { AnthropicCompatibleProvider } from './providers/anthropic-compatible.js';
|
|
42
|
+
import { createAnthropicPromptCachePolicyResolver } from './providers/anthropic-prompt-cache.js';
|
|
42
43
|
import { FallbackModelProvider } from './providers/fallback-provider.js';
|
|
43
44
|
import { OpenAICompatibleProvider } from './providers/openai-compatible.js';
|
|
44
45
|
import { parseContextEnvironment, parseProviderEnvironment, } from './providers/environment.js';
|
|
@@ -89,34 +90,37 @@ function fileResourceHeaders(environment, providerEnvironment, credential) {
|
|
|
89
90
|
: {}),
|
|
90
91
|
};
|
|
91
92
|
}
|
|
92
|
-
function createProviderForModel(apiKey,
|
|
93
|
+
function createProviderForModel({ apiKey, environment, dataPlane, provider, context, controls, explicitThinkingControls, }) {
|
|
94
|
+
const resolvePromptCachePolicy = createAnthropicPromptCachePolicyResolver(environment, dataPlane);
|
|
93
95
|
return (selectedModel) => {
|
|
94
96
|
const providerOptions = {
|
|
95
97
|
apiKey,
|
|
96
98
|
model: selectedModel,
|
|
97
|
-
baseUrl:
|
|
99
|
+
baseUrl: provider.baseUrl,
|
|
98
100
|
...('contextWindowTokens' in context
|
|
99
101
|
? { contextWindowTokens: context.contextWindowTokens }
|
|
100
102
|
: {}),
|
|
101
103
|
};
|
|
102
|
-
return
|
|
104
|
+
return provider.provider === 'anthropic'
|
|
103
105
|
? new AnthropicCompatibleProvider({
|
|
104
106
|
...providerOptions,
|
|
107
|
+
promptCaching: resolvePromptCachePolicy({
|
|
108
|
+
baseUrl: provider.baseUrl,
|
|
109
|
+
model: selectedModel,
|
|
110
|
+
}),
|
|
105
111
|
thinking: {
|
|
106
112
|
mode: controls.thinking ?? 'enabled',
|
|
107
113
|
...(controls.maxThinkingTokens === undefined
|
|
108
114
|
? {}
|
|
109
115
|
: { maxTokens: controls.maxThinkingTokens }),
|
|
110
116
|
},
|
|
111
|
-
...('maxOutputTokens' in
|
|
112
|
-
? { maxOutputTokens:
|
|
113
|
-
: {}),
|
|
114
|
-
...('anthropicVersion' in providerEnvironment
|
|
115
|
-
? { anthropicVersion: providerEnvironment.anthropicVersion }
|
|
117
|
+
...('maxOutputTokens' in provider
|
|
118
|
+
? { maxOutputTokens: provider.maxOutputTokens }
|
|
116
119
|
: {}),
|
|
117
|
-
...('
|
|
118
|
-
? {
|
|
120
|
+
...('anthropicVersion' in provider
|
|
121
|
+
? { anthropicVersion: provider.anthropicVersion }
|
|
119
122
|
: {}),
|
|
123
|
+
...('webSearch' in provider ? { webSearch: provider.webSearch } : {}),
|
|
120
124
|
})
|
|
121
125
|
: new OpenAICompatibleProvider({
|
|
122
126
|
...providerOptions,
|
|
@@ -245,6 +249,8 @@ Provider environment:
|
|
|
245
249
|
PRAXIS_PROVIDER=openai|anthropic, PRAXIS_API_KEY, PRAXIS_MODEL
|
|
246
250
|
PRAXIS_BASE_URL, PRAXIS_MAX_OUTPUT_TOKENS, PRAXIS_ANTHROPIC_VERSION
|
|
247
251
|
PRAXIS_ANTHROPIC_WEB_SEARCH=true|false
|
|
252
|
+
PRAXIS_ANTHROPIC_PROMPT_CACHING=true|false
|
|
253
|
+
PRAXIS_ANTHROPIC_PROMPT_CACHE_TTL=5m|1h
|
|
248
254
|
PRAXIS_CONTEXT_WINDOW_TOKENS, PRAXIS_CONTEXT_RESERVE_TOKENS
|
|
249
255
|
`;
|
|
250
256
|
const AGENTS_HELP = `Usage: praxis agents [options]
|
|
@@ -837,7 +843,15 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
|
|
|
837
843
|
if (!providerEnvironment) {
|
|
838
844
|
throw new Error('Provider environment is unavailable');
|
|
839
845
|
}
|
|
840
|
-
providerForModel = createProviderForModel(
|
|
846
|
+
providerForModel = createProviderForModel({
|
|
847
|
+
apiKey,
|
|
848
|
+
environment: runtimeEnvironment,
|
|
849
|
+
dataPlane,
|
|
850
|
+
provider: providerEnvironment,
|
|
851
|
+
context,
|
|
852
|
+
controls: cli,
|
|
853
|
+
explicitThinkingControls: controls,
|
|
854
|
+
});
|
|
841
855
|
const createProvider = providerForModel;
|
|
842
856
|
providerForMainModel = (primaryModel) => {
|
|
843
857
|
const models = [primaryModel, ...(cli.fallbackModels ?? [])].filter((candidate, index, all) => all.indexOf(candidate) === index);
|
|
@@ -1705,7 +1719,16 @@ const createDefaultAutoModeCritic = async ({ model, dataPlane, configRoot, state
|
|
|
1705
1719
|
if (!apiKey || !selectedModel) {
|
|
1706
1720
|
throw new Error('PRAXIS_API_KEY and a model (--model or PRAXIS_MODEL) are required');
|
|
1707
1721
|
}
|
|
1708
|
-
|
|
1722
|
+
const providerEnvironment = parseProviderEnvironment(process.env);
|
|
1723
|
+
return createProviderForModel({
|
|
1724
|
+
apiKey,
|
|
1725
|
+
environment: process.env,
|
|
1726
|
+
dataPlane: resolvedDataPlane,
|
|
1727
|
+
provider: providerEnvironment,
|
|
1728
|
+
context: parseContextEnvironment(process.env),
|
|
1729
|
+
controls: {},
|
|
1730
|
+
explicitThinkingControls: {},
|
|
1731
|
+
})(selectedModel);
|
|
1709
1732
|
};
|
|
1710
1733
|
const defaultPluginEvalRuntimeFactory = {
|
|
1711
1734
|
create: async (options) => {
|
|
@@ -1805,7 +1828,16 @@ const defaultPluginEvalJudge = {
|
|
|
1805
1828
|
const apiKey = environment.PRAXIS_API_KEY;
|
|
1806
1829
|
if (!apiKey)
|
|
1807
1830
|
throw new Error('PRAXIS_API_KEY is required for paid eval graders');
|
|
1808
|
-
const
|
|
1831
|
+
const providerEnvironment = parseProviderEnvironment(environment);
|
|
1832
|
+
const provider = createProviderForModel({
|
|
1833
|
+
apiKey,
|
|
1834
|
+
environment,
|
|
1835
|
+
dataPlane: resolveDataPlane(environment),
|
|
1836
|
+
provider: providerEnvironment,
|
|
1837
|
+
context: parseContextEnvironment(environment),
|
|
1838
|
+
controls: {},
|
|
1839
|
+
explicitThinkingControls: {},
|
|
1840
|
+
})(model);
|
|
1809
1841
|
const prompt = `You are an eval judge. Return only JSON matching {"passed":boolean,"explanation":string}.
|
|
1810
1842
|
|
|
1811
1843
|
Criteria:
|
|
@@ -706,10 +706,11 @@ export class ClaudeMcpToolRegistry {
|
|
|
706
706
|
definitions() {
|
|
707
707
|
return [
|
|
708
708
|
...this.options.base.definitions(),
|
|
709
|
+
...(this.resourceServers.size > 0 ? MCP_RESOURCE_TOOL_DEFINITIONS : []),
|
|
709
710
|
...[...this.connectedTools.entries()]
|
|
710
711
|
.filter(([name]) => !this.reservedTools.has(name))
|
|
712
|
+
.sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
|
|
711
713
|
.map(([, tool]) => tool.definition),
|
|
712
|
-
...(this.resourceServers.size > 0 ? MCP_RESOURCE_TOOL_DEFINITIONS : []),
|
|
713
714
|
];
|
|
714
715
|
}
|
|
715
716
|
schedulingPolicy(call) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ModelProvider, type ModelRequest, type ModelStreamEvent, type ModelThinkingConfig } from '../core/runtime.js';
|
|
2
|
+
import { type AnthropicPromptCachePolicy } from './anthropic-prompt-cache.js';
|
|
2
3
|
export interface AnthropicCompatibleProviderOptions {
|
|
3
4
|
baseUrl: string;
|
|
4
5
|
apiKey: string;
|
|
@@ -6,6 +7,7 @@ export interface AnthropicCompatibleProviderOptions {
|
|
|
6
7
|
maxOutputTokens?: number;
|
|
7
8
|
anthropicVersion?: string;
|
|
8
9
|
webSearch?: boolean;
|
|
10
|
+
promptCaching?: AnthropicPromptCachePolicy;
|
|
9
11
|
contextWindowTokens?: number;
|
|
10
12
|
thinking?: ModelThinkingConfig;
|
|
11
13
|
maxStreamBufferBytes?: number;
|
|
@@ -29,6 +31,7 @@ export declare class AnthropicCompatibleProvider implements ModelProvider {
|
|
|
29
31
|
private readonly maxToolMetadataBytes;
|
|
30
32
|
private readonly maxErrorBodyBytes;
|
|
31
33
|
private readonly thinking;
|
|
34
|
+
private readonly promptCaching;
|
|
32
35
|
constructor(options: AnthropicCompatibleProviderOptions);
|
|
33
36
|
complete(request: ModelRequest): AsyncIterable<ModelStreamEvent>;
|
|
34
37
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ModelProviderError, } from '../core/runtime.js';
|
|
2
2
|
import { transportFailureKind } from './provider-errors.js';
|
|
3
|
+
import { createAnthropicPromptCachePolicyResolver, } from './anthropic-prompt-cache.js';
|
|
3
4
|
function isRecord(value) {
|
|
4
5
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
5
6
|
}
|
|
@@ -451,6 +452,34 @@ function parseSseEvent(data, state, maxToolArgumentsBytes, maxToolCallsPerRespon
|
|
|
451
452
|
}
|
|
452
453
|
return [];
|
|
453
454
|
}
|
|
455
|
+
const ANTHROPIC_CACHE_LOOKBACK_BLOCKS = 20;
|
|
456
|
+
function cacheControl(ttl) {
|
|
457
|
+
return {
|
|
458
|
+
type: 'ephemeral',
|
|
459
|
+
...(ttl === '1h' ? { ttl } : {}),
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
function markLatestCacheableMessageBlock(messages, control) {
|
|
463
|
+
let inspectedBlocks = 0;
|
|
464
|
+
for (let messageIndex = messages.length - 1; messageIndex >= 0; messageIndex--) {
|
|
465
|
+
const content = messages[messageIndex]?.content;
|
|
466
|
+
if (!content)
|
|
467
|
+
continue;
|
|
468
|
+
for (let blockIndex = content.length - 1; blockIndex >= 0; blockIndex--) {
|
|
469
|
+
if (inspectedBlocks >= ANTHROPIC_CACHE_LOOKBACK_BLOCKS)
|
|
470
|
+
return;
|
|
471
|
+
inspectedBlocks += 1;
|
|
472
|
+
const block = content[blockIndex];
|
|
473
|
+
if (!block ||
|
|
474
|
+
block.type === 'thinking' ||
|
|
475
|
+
block.type === 'redacted_thinking') {
|
|
476
|
+
continue;
|
|
477
|
+
}
|
|
478
|
+
content[blockIndex] = { ...block, cache_control: control };
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
454
483
|
function serializeMediaContent(message) {
|
|
455
484
|
const blocks = message.contentBlocks
|
|
456
485
|
? [...message.contentBlocks]
|
|
@@ -481,9 +510,10 @@ function serializeMediaContent(message) {
|
|
|
481
510
|
},
|
|
482
511
|
});
|
|
483
512
|
}
|
|
484
|
-
function serializeMessages(messages) {
|
|
513
|
+
function serializeMessages(messages, stableSystemMessageCount, promptCaching) {
|
|
485
514
|
const system = [];
|
|
486
515
|
const serialized = [];
|
|
516
|
+
let systemIndex = 0;
|
|
487
517
|
const append = (role, content) => {
|
|
488
518
|
if (content.length === 0)
|
|
489
519
|
return;
|
|
@@ -495,7 +525,15 @@ function serializeMessages(messages) {
|
|
|
495
525
|
};
|
|
496
526
|
for (const message of messages) {
|
|
497
527
|
if (message.role === 'system') {
|
|
498
|
-
|
|
528
|
+
const block = {
|
|
529
|
+
type: 'text',
|
|
530
|
+
text: `${systemIndex === 0 ? '' : '\n\n'}${message.content}`,
|
|
531
|
+
...(promptCaching && systemIndex + 1 === stableSystemMessageCount
|
|
532
|
+
? { cache_control: promptCaching }
|
|
533
|
+
: {}),
|
|
534
|
+
};
|
|
535
|
+
system.push(block);
|
|
536
|
+
systemIndex += 1;
|
|
499
537
|
continue;
|
|
500
538
|
}
|
|
501
539
|
if (message.role === 'user') {
|
|
@@ -553,7 +591,10 @@ function serializeMessages(messages) {
|
|
|
553
591
|
}
|
|
554
592
|
append('assistant', content);
|
|
555
593
|
}
|
|
556
|
-
|
|
594
|
+
if (promptCaching) {
|
|
595
|
+
markLatestCacheableMessageBlock(serialized, promptCaching);
|
|
596
|
+
}
|
|
597
|
+
return { system, messages: serialized };
|
|
557
598
|
}
|
|
558
599
|
function validateStableSystemPrefix(request) {
|
|
559
600
|
const count = request.stableSystemMessageCount;
|
|
@@ -583,6 +624,7 @@ export class AnthropicCompatibleProvider {
|
|
|
583
624
|
maxToolMetadataBytes;
|
|
584
625
|
maxErrorBodyBytes;
|
|
585
626
|
thinking;
|
|
627
|
+
promptCaching;
|
|
586
628
|
constructor(options) {
|
|
587
629
|
this.options = options;
|
|
588
630
|
if (options.contextWindowTokens !== undefined) {
|
|
@@ -615,6 +657,16 @@ export class AnthropicCompatibleProvider {
|
|
|
615
657
|
terminalReasons: true,
|
|
616
658
|
};
|
|
617
659
|
this.thinking = validateThinking(options.thinking);
|
|
660
|
+
const promptCaching = options.promptCaching === false
|
|
661
|
+
? undefined
|
|
662
|
+
: (options.promptCaching ??
|
|
663
|
+
createAnthropicPromptCachePolicyResolver({}, 'native')({
|
|
664
|
+
baseUrl: options.baseUrl,
|
|
665
|
+
model: options.model,
|
|
666
|
+
}));
|
|
667
|
+
this.promptCaching = promptCaching
|
|
668
|
+
? cacheControl(promptCaching.ttl)
|
|
669
|
+
: undefined;
|
|
618
670
|
this.anthropicVersion = options.anthropicVersion ?? '2023-06-01';
|
|
619
671
|
this.maxStreamBufferBytes = options.maxStreamBufferBytes ?? 1024 * 1024;
|
|
620
672
|
this.maxToolArgumentsBytes = options.maxToolArgumentsBytes ?? 1024 * 1024;
|
|
@@ -646,7 +698,8 @@ export class AnthropicCompatibleProvider {
|
|
|
646
698
|
? ['interleaved-thinking-2025-05-14']
|
|
647
699
|
: []),
|
|
648
700
|
].filter((beta, index, all) => all.indexOf(beta) === index);
|
|
649
|
-
const serialized = serializeMessages(request.messages);
|
|
701
|
+
const serialized = serializeMessages(request.messages, request.stableSystemMessageCount, this.promptCaching);
|
|
702
|
+
const requestTools = request.tools;
|
|
650
703
|
const requestInit = {
|
|
651
704
|
method: 'POST',
|
|
652
705
|
headers: {
|
|
@@ -664,7 +717,7 @@ export class AnthropicCompatibleProvider {
|
|
|
664
717
|
...(request.effort
|
|
665
718
|
? { output_config: { effort: request.effort } }
|
|
666
719
|
: {}),
|
|
667
|
-
...(serialized.system ? { system: serialized.system } : {}),
|
|
720
|
+
...(serialized.system.length ? { system: serialized.system } : {}),
|
|
668
721
|
...(request.webSearch
|
|
669
722
|
? {
|
|
670
723
|
tools: [
|
|
@@ -682,12 +735,15 @@ export class AnthropicCompatibleProvider {
|
|
|
682
735
|
],
|
|
683
736
|
tool_choice: { type: 'tool', name: 'web_search' },
|
|
684
737
|
}
|
|
685
|
-
:
|
|
738
|
+
: requestTools?.length
|
|
686
739
|
? {
|
|
687
|
-
tools:
|
|
740
|
+
tools: requestTools.map((tool, index) => ({
|
|
688
741
|
name: tool.name,
|
|
689
742
|
description: tool.description,
|
|
690
743
|
input_schema: tool.inputSchema,
|
|
744
|
+
...(this.promptCaching && index === requestTools.length - 1
|
|
745
|
+
? { cache_control: this.promptCaching }
|
|
746
|
+
: {}),
|
|
691
747
|
})),
|
|
692
748
|
}
|
|
693
749
|
: {}),
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type AnthropicPromptCachePolicy = false | {
|
|
2
|
+
ttl: '5m' | '1h';
|
|
3
|
+
};
|
|
4
|
+
export interface AnthropicPromptCacheTarget {
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
model: string;
|
|
7
|
+
}
|
|
8
|
+
/** Captures prompt-cache configuration once, then resolves a policy for each
|
|
9
|
+
* Anthropic model adapter created during the same session. */
|
|
10
|
+
export declare function createAnthropicPromptCachePolicyResolver(environment: NodeJS.ProcessEnv, dataPlane: 'native' | 'claude'): (target: AnthropicPromptCacheTarget) => AnthropicPromptCachePolicy;
|
|
11
|
+
//# sourceMappingURL=anthropic-prompt-cache.d.ts.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
function officialAnthropicEndpoint(baseUrl) {
|
|
2
|
+
try {
|
|
3
|
+
return new URL(baseUrl).hostname === 'api.anthropic.com';
|
|
4
|
+
}
|
|
5
|
+
catch {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
function modelFamily(model) {
|
|
10
|
+
const normalized = model.toLowerCase();
|
|
11
|
+
if (normalized.includes('haiku'))
|
|
12
|
+
return 'haiku';
|
|
13
|
+
if (normalized.includes('sonnet'))
|
|
14
|
+
return 'sonnet';
|
|
15
|
+
if (normalized.includes('opus'))
|
|
16
|
+
return 'opus';
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
/** Captures prompt-cache configuration once, then resolves a policy for each
|
|
20
|
+
* Anthropic model adapter created during the same session. */
|
|
21
|
+
export function createAnthropicPromptCachePolicyResolver(environment, dataPlane) {
|
|
22
|
+
const praxisEnabled = environment.PRAXIS_ANTHROPIC_PROMPT_CACHING;
|
|
23
|
+
if (praxisEnabled !== undefined &&
|
|
24
|
+
praxisEnabled !== 'true' &&
|
|
25
|
+
praxisEnabled !== 'false') {
|
|
26
|
+
throw new Error('PRAXIS_ANTHROPIC_PROMPT_CACHING must be true or false');
|
|
27
|
+
}
|
|
28
|
+
const praxisTtl = environment.PRAXIS_ANTHROPIC_PROMPT_CACHE_TTL;
|
|
29
|
+
if (praxisTtl !== undefined && praxisTtl !== '5m' && praxisTtl !== '1h') {
|
|
30
|
+
throw new Error('PRAXIS_ANTHROPIC_PROMPT_CACHE_TTL must be 5m or 1h');
|
|
31
|
+
}
|
|
32
|
+
if (praxisEnabled === 'false' && praxisTtl !== undefined) {
|
|
33
|
+
throw new Error('PRAXIS_ANTHROPIC_PROMPT_CACHE_TTL cannot be set when prompt caching is false');
|
|
34
|
+
}
|
|
35
|
+
const claudeCompatibility = dataPlane === 'claude';
|
|
36
|
+
const disableAll = environment.DISABLE_PROMPT_CACHING === '1';
|
|
37
|
+
const disabledFamilies = new Set(['haiku', 'sonnet', 'opus'].filter((family) => environment[`DISABLE_PROMPT_CACHING_${family.toUpperCase()}`] === '1'));
|
|
38
|
+
const forceFiveMinutes = environment.FORCE_PROMPT_CACHING_5M === '1';
|
|
39
|
+
const enableOneHour = environment.ENABLE_PROMPT_CACHING_1H === '1';
|
|
40
|
+
return ({ baseUrl, model }) => {
|
|
41
|
+
if (claudeCompatibility) {
|
|
42
|
+
const family = modelFamily(model);
|
|
43
|
+
if (disableAll || (family && disabledFamilies.has(family)))
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
if (praxisEnabled === 'false')
|
|
47
|
+
return false;
|
|
48
|
+
if (claudeCompatibility && forceFiveMinutes)
|
|
49
|
+
return { ttl: '5m' };
|
|
50
|
+
if (claudeCompatibility && enableOneHour)
|
|
51
|
+
return { ttl: '1h' };
|
|
52
|
+
if (praxisEnabled === 'true' || praxisTtl !== undefined) {
|
|
53
|
+
return { ttl: praxisTtl ?? '5m' };
|
|
54
|
+
}
|
|
55
|
+
return officialAnthropicEndpoint(baseUrl) ? { ttl: '5m' } : false;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=anthropic-prompt-cache.js.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createAnthropicPromptCachePolicyResolver } from './anthropic-prompt-cache.js';
|
|
1
2
|
export function parseProviderEnvironment(environment) {
|
|
2
3
|
const provider = environment.PRAXIS_PROVIDER ?? 'openai';
|
|
3
4
|
if (provider !== 'openai' && provider !== 'anthropic') {
|
|
@@ -29,6 +30,17 @@ export function parseProviderEnvironment(environment) {
|
|
|
29
30
|
if (provider === 'openai' && webSearch !== undefined) {
|
|
30
31
|
throw new Error('PRAXIS_ANTHROPIC_WEB_SEARCH requires PRAXIS_PROVIDER=anthropic');
|
|
31
32
|
}
|
|
33
|
+
for (const name of [
|
|
34
|
+
'PRAXIS_ANTHROPIC_PROMPT_CACHING',
|
|
35
|
+
'PRAXIS_ANTHROPIC_PROMPT_CACHE_TTL',
|
|
36
|
+
]) {
|
|
37
|
+
if (provider === 'openai' && environment[name] !== undefined) {
|
|
38
|
+
throw new Error(`${name} requires PRAXIS_PROVIDER=anthropic`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (provider === 'anthropic') {
|
|
42
|
+
createAnthropicPromptCachePolicyResolver(environment, 'native');
|
|
43
|
+
}
|
|
32
44
|
return {
|
|
33
45
|
provider,
|
|
34
46
|
baseUrl: environment.PRAXIS_BASE_URL ??
|