@polka-codes/core 0.9.101 → 0.10.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/README.md +1 -1
- package/dist/_tsup-dts-rollup.d.ts +76 -16
- package/dist/index.d.ts +4 -1
- package/dist/index.js +336 -69
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Core AI services and agent implementations for Polka Codes framework.
|
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
|
-
- Multiple AI provider support (Anthropic, DeepSeek, GoogleVertex,
|
|
11
|
+
- Multiple AI provider support (Anthropic, DeepSeek, GoogleVertex, OpenAI, and OpenRouter)
|
|
12
12
|
- Extensible agent architecture
|
|
13
13
|
- Tool integration system with safety enhancements
|
|
14
14
|
- Type-safe API
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import type { FilePart } from 'ai';
|
|
2
2
|
import type { ImagePart } from 'ai';
|
|
3
3
|
import type { JSONValue } from '@ai-sdk/provider';
|
|
4
|
-
import type {
|
|
5
|
-
import type {
|
|
6
|
-
import type {
|
|
4
|
+
import type { LanguageModelUsage } from 'ai';
|
|
5
|
+
import type { LanguageModelV3 } from '@ai-sdk/provider';
|
|
6
|
+
import type { LanguageModelV3ToolResultOutput } from '@ai-sdk/provider';
|
|
7
|
+
import type { LanguageModelV3Usage } from '@ai-sdk/provider';
|
|
7
8
|
import type { ModelMessage } from '@ai-sdk/provider-utils';
|
|
8
9
|
import type { ProviderOptions } from '@ai-sdk/provider-utils';
|
|
9
10
|
import type { ReasoningPart } from '@ai-sdk/provider-utils';
|
|
10
11
|
import type { SystemModelMessage } from '@ai-sdk/provider-utils';
|
|
11
12
|
import type { TextPart } from 'ai';
|
|
12
13
|
import type { TextPart as TextPart_2 } from '@ai-sdk/provider-utils';
|
|
14
|
+
import type { ToolApprovalRequest } from '@ai-sdk/provider-utils';
|
|
13
15
|
import type { ToolModelMessage } from '@ai-sdk/provider-utils';
|
|
14
16
|
import type { ToolResultPart } from '@ai-sdk/provider-utils';
|
|
15
17
|
import { ToolSet } from 'ai';
|
|
@@ -364,6 +366,12 @@ export { convertJsonSchemaToZod }
|
|
|
364
366
|
export { convertJsonSchemaToZod as convertJsonSchemaToZod_alias_1 }
|
|
365
367
|
export { convertJsonSchemaToZod as convertJsonSchemaToZod_alias_2 }
|
|
366
368
|
|
|
369
|
+
/**
|
|
370
|
+
* Convert Portkey pricing (cents per token) to ModelInfo (USD per 1M tokens)
|
|
371
|
+
* Formula: cents_per_token * 10 = usd_per_1M_tokens
|
|
372
|
+
*/
|
|
373
|
+
export declare function convertPortkeyToModelInfo(portkey: PortkeyPricingResponse): ModelInfo;
|
|
374
|
+
|
|
367
375
|
declare function createContext<TTools extends ToolRegistry>(tools: WorkflowTools<TTools>, stepFn?: StepFn, logger?: Logger): WorkflowContext<TTools>;
|
|
368
376
|
export { createContext }
|
|
369
377
|
export { createContext as createContext_alias_1 }
|
|
@@ -890,6 +898,8 @@ export { ExitReason }
|
|
|
890
898
|
export { ExitReason as ExitReason_alias_1 }
|
|
891
899
|
export { ExitReason as ExitReason_alias_2 }
|
|
892
900
|
|
|
901
|
+
export declare function fetchPricing(provider: string, model: string): Promise<PortkeyPricingResponse | null>;
|
|
902
|
+
|
|
893
903
|
/**
|
|
894
904
|
* File statistics
|
|
895
905
|
*/
|
|
@@ -1135,7 +1145,7 @@ export declare function join(...parts: string[]): string;
|
|
|
1135
1145
|
Content of an assistant message.
|
|
1136
1146
|
It can be a string or an array of text, image, reasoning, redacted reasoning, and tool call parts.
|
|
1137
1147
|
*/
|
|
1138
|
-
declare type JsonAssistantContent = string | Array<TextPart_2 | JsonFilePart | ReasoningPart | JsonToolCallPart | ToolResultPart>;
|
|
1148
|
+
declare type JsonAssistantContent = string | Array<TextPart_2 | JsonFilePart | ReasoningPart | JsonToolCallPart | ToolResultPart | ToolApprovalRequest>;
|
|
1139
1149
|
|
|
1140
1150
|
/**
|
|
1141
1151
|
An assistant message. It can contain text, tool calls, or a combination of text and tool calls.
|
|
@@ -1655,6 +1665,8 @@ declare type ModelInfo = {
|
|
|
1655
1665
|
};
|
|
1656
1666
|
export { ModelInfo }
|
|
1657
1667
|
export { ModelInfo as ModelInfo_alias_1 }
|
|
1668
|
+
export { ModelInfo as ModelInfo_alias_2 }
|
|
1669
|
+
export { ModelInfo as ModelInfo_alias_3 }
|
|
1658
1670
|
|
|
1659
1671
|
/**
|
|
1660
1672
|
* Node.js file system provider implementation
|
|
@@ -1696,12 +1708,51 @@ export { ParseOutputResult }
|
|
|
1696
1708
|
export { ParseOutputResult as ParseOutputResult_alias_1 }
|
|
1697
1709
|
export { ParseOutputResult as ParseOutputResult_alias_2 }
|
|
1698
1710
|
|
|
1711
|
+
declare interface PortkeyPricingConfig {
|
|
1712
|
+
provider: string;
|
|
1713
|
+
model: string;
|
|
1714
|
+
pricing: PortkeyPricingResponse;
|
|
1715
|
+
}
|
|
1716
|
+
export { PortkeyPricingConfig }
|
|
1717
|
+
export { PortkeyPricingConfig as PortkeyPricingConfig_alias_1 }
|
|
1718
|
+
export { PortkeyPricingConfig as PortkeyPricingConfig_alias_2 }
|
|
1719
|
+
|
|
1720
|
+
declare interface PortkeyPricingResponse {
|
|
1721
|
+
request_token?: {
|
|
1722
|
+
price: number;
|
|
1723
|
+
};
|
|
1724
|
+
response_token?: {
|
|
1725
|
+
price: number;
|
|
1726
|
+
};
|
|
1727
|
+
cache_write_input_token?: {
|
|
1728
|
+
price: number;
|
|
1729
|
+
};
|
|
1730
|
+
cache_read_input_token?: {
|
|
1731
|
+
price: number;
|
|
1732
|
+
};
|
|
1733
|
+
additional_units?: Record<string, {
|
|
1734
|
+
price: number;
|
|
1735
|
+
}>;
|
|
1736
|
+
}
|
|
1737
|
+
export { PortkeyPricingResponse }
|
|
1738
|
+
export { PortkeyPricingResponse as PortkeyPricingResponse_alias_1 }
|
|
1739
|
+
export { PortkeyPricingResponse as PortkeyPricingResponse_alias_2 }
|
|
1740
|
+
|
|
1699
1741
|
/**
|
|
1700
1742
|
* Simplify boolean string preprocessing
|
|
1701
1743
|
* Converts 'true'/'false' strings to actual booleans
|
|
1702
1744
|
*/
|
|
1703
1745
|
export declare function preprocessBoolean(val: unknown): unknown;
|
|
1704
1746
|
|
|
1747
|
+
declare class PricingService {
|
|
1748
|
+
#private;
|
|
1749
|
+
constructor(fallbackPrices?: Record<string, Record<string, Partial<ModelInfo>>>);
|
|
1750
|
+
getPricing(provider: string, model: string): Promise<ModelInfo>;
|
|
1751
|
+
}
|
|
1752
|
+
export { PricingService }
|
|
1753
|
+
export { PricingService as PricingService_alias_1 }
|
|
1754
|
+
export { PricingService as PricingService_alias_2 }
|
|
1755
|
+
|
|
1705
1756
|
declare type ProviderConfig = z.infer<typeof providerConfigSchema>;
|
|
1706
1757
|
export { ProviderConfig }
|
|
1707
1758
|
export { ProviderConfig as ProviderConfig_alias_1 }
|
|
@@ -1728,7 +1779,7 @@ export { providerConfigSchema as providerConfigSchema_alias_2 }
|
|
|
1728
1779
|
declare type ProviderMetadataEntry = {
|
|
1729
1780
|
provider: string;
|
|
1730
1781
|
model: string;
|
|
1731
|
-
metadata:
|
|
1782
|
+
metadata: Record<string, unknown>;
|
|
1732
1783
|
timestamp: number;
|
|
1733
1784
|
};
|
|
1734
1785
|
|
|
@@ -1855,7 +1906,7 @@ declare const responsePrompts: {
|
|
|
1855
1906
|
readonly errorInvokeTool: (tool: string, error: unknown) => string;
|
|
1856
1907
|
readonly requireUseTool: "Error: No tool use detected. You MUST use a tool before proceeding.\ne.g. <tool_tool_name>tool_name</tool_tool_name>\n\nEnsure the opening and closing tags are correctly nested and closed, and that you are using the correct tool name.\nAvoid unnecessary text or symbols before or after the tool use.\nAvoid unnecessary escape characters or special characters.\n";
|
|
1857
1908
|
readonly requireUseToolNative: "Error: No tool use detected. You MUST use a tool before proceeding.\n";
|
|
1858
|
-
readonly toolResults: (tool: string, result:
|
|
1909
|
+
readonly toolResults: (tool: string, result: LanguageModelV3ToolResultOutput) => Array<TextPart | ImagePart | FilePart>;
|
|
1859
1910
|
readonly commandResult: (command: string, exitCode: number, stdout: string, stderr: string) => string;
|
|
1860
1911
|
};
|
|
1861
1912
|
export { responsePrompts }
|
|
@@ -2638,16 +2689,20 @@ declare class UsageMeter {
|
|
|
2638
2689
|
constructor(modelInfos?: Record<string, Record<string, Partial<ModelInfo>>>, opts?: {
|
|
2639
2690
|
maxMessages?: number;
|
|
2640
2691
|
maxCost?: number;
|
|
2692
|
+
pricingService?: PricingService;
|
|
2641
2693
|
});
|
|
2642
|
-
addUsage(llm:
|
|
2643
|
-
usage:
|
|
2644
|
-
providerMetadata?:
|
|
2694
|
+
addUsage(llm: LanguageModelV3, resp: {
|
|
2695
|
+
usage: LanguageModelV3Usage;
|
|
2696
|
+
providerMetadata?: Record<string, unknown>;
|
|
2697
|
+
} | {
|
|
2698
|
+
totalUsage: LanguageModelV3Usage;
|
|
2699
|
+
providerMetadata?: Record<string, unknown>;
|
|
2645
2700
|
} | {
|
|
2646
|
-
totalUsage:
|
|
2647
|
-
providerMetadata?:
|
|
2701
|
+
totalUsage: LanguageModelUsage;
|
|
2702
|
+
providerMetadata?: Record<string, unknown>;
|
|
2648
2703
|
}, options?: {
|
|
2649
2704
|
modelInfo?: ModelInfo;
|
|
2650
|
-
}): void
|
|
2705
|
+
}): Promise<void>;
|
|
2651
2706
|
/** Override the running totals (e.g., restore from saved state). */
|
|
2652
2707
|
setUsage(newUsage: Partial<Totals>, options?: {
|
|
2653
2708
|
clearMetadata?: boolean;
|
|
@@ -2688,11 +2743,16 @@ declare class UsageMeter {
|
|
|
2688
2743
|
clearProviderMetadata(): void;
|
|
2689
2744
|
/** Merge another UsageMeter's totals into this one. */
|
|
2690
2745
|
merge(other: UsageMeter): void;
|
|
2746
|
+
/** Wait for all pending usage updates to complete. */
|
|
2747
|
+
waitForPending(): Promise<void>;
|
|
2691
2748
|
getUsageText(): string;
|
|
2692
|
-
onFinishHandler(llm:
|
|
2693
|
-
totalUsage:
|
|
2694
|
-
providerMetadata
|
|
2695
|
-
}
|
|
2749
|
+
onFinishHandler(llm: LanguageModelV3): (evt: {
|
|
2750
|
+
totalUsage: LanguageModelUsage;
|
|
2751
|
+
providerMetadata?: Record<string, unknown>;
|
|
2752
|
+
} | {
|
|
2753
|
+
totalUsage: LanguageModelV3Usage;
|
|
2754
|
+
providerMetadata?: Record<string, unknown>;
|
|
2755
|
+
}) => Promise<void>;
|
|
2696
2756
|
}
|
|
2697
2757
|
export { UsageMeter }
|
|
2698
2758
|
export { UsageMeter as UsageMeter_alias_1 }
|
package/dist/index.d.ts
CHANGED
|
@@ -40,6 +40,10 @@ export { MemoryOperation } from './_tsup-dts-rollup.js';
|
|
|
40
40
|
export { DatabaseStats } from './_tsup-dts-rollup.js';
|
|
41
41
|
export { IMemoryStore } from './_tsup-dts-rollup.js';
|
|
42
42
|
export { MemoryStoreConfig } from './_tsup-dts-rollup.js';
|
|
43
|
+
export { PricingService } from './_tsup-dts-rollup.js';
|
|
44
|
+
export { ModelInfo_alias_1 as ModelInfo } from './_tsup-dts-rollup.js';
|
|
45
|
+
export { PortkeyPricingConfig } from './_tsup-dts-rollup.js';
|
|
46
|
+
export { PortkeyPricingResponse } from './_tsup-dts-rollup.js';
|
|
43
47
|
export { SKILL_LIMITS } from './_tsup-dts-rollup.js';
|
|
44
48
|
export { IGNORED_DIRECTORIES } from './_tsup-dts-rollup.js';
|
|
45
49
|
export { SUSPICIOUS_PATTERNS } from './_tsup-dts-rollup.js';
|
|
@@ -117,7 +121,6 @@ export { UpdateTodoItemInputSchema } from './_tsup-dts-rollup.js';
|
|
|
117
121
|
export { UpdateTodoItemInput } from './_tsup-dts-rollup.js';
|
|
118
122
|
export { UpdateTodoItemOutputSchema } from './_tsup-dts-rollup.js';
|
|
119
123
|
export { UpdateTodoItemOutput } from './_tsup-dts-rollup.js';
|
|
120
|
-
export { ModelInfo_alias_1 as ModelInfo } from './_tsup-dts-rollup.js';
|
|
121
124
|
export { UsageMeter_alias_1 as UsageMeter } from './_tsup-dts-rollup.js';
|
|
122
125
|
export { deepMerge } from './_tsup-dts-rollup.js';
|
|
123
126
|
export { AgentWorkflowInput } from './_tsup-dts-rollup.js';
|
package/dist/index.js
CHANGED
|
@@ -29,6 +29,7 @@ var parseJsonFromMarkdown = (markdown) => {
|
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
// src/Agent/prompts.ts
|
|
32
|
+
var NO_REASON_PROVIDED = "No reason provided";
|
|
32
33
|
var responsePrompts = {
|
|
33
34
|
errorInvokeTool: (tool, error) => `An error occurred while invoking the tool "${tool}": ${error}`,
|
|
34
35
|
requireUseTool: `Error: No tool use detected. You MUST use a tool before proceeding.
|
|
@@ -80,17 +81,23 @@ Avoid unnecessary escape characters or special characters.
|
|
|
80
81
|
if (part.type === "text") {
|
|
81
82
|
return part;
|
|
82
83
|
}
|
|
83
|
-
if (part.mediaType.startsWith("image/")) {
|
|
84
|
+
if ("mediaType" in part && "data" in part && part.mediaType.startsWith("image/")) {
|
|
84
85
|
return {
|
|
85
86
|
type: "image",
|
|
86
87
|
mediaType: part.mediaType,
|
|
87
88
|
image: part.data
|
|
88
89
|
};
|
|
89
90
|
}
|
|
91
|
+
if ("mediaType" in part && "data" in part) {
|
|
92
|
+
return {
|
|
93
|
+
type: "file",
|
|
94
|
+
mediaType: part.mediaType,
|
|
95
|
+
data: part.data
|
|
96
|
+
};
|
|
97
|
+
}
|
|
90
98
|
return {
|
|
91
|
-
type: "
|
|
92
|
-
|
|
93
|
-
data: part.data
|
|
99
|
+
type: "text",
|
|
100
|
+
text: JSON.stringify(part)
|
|
94
101
|
};
|
|
95
102
|
}),
|
|
96
103
|
{
|
|
@@ -98,6 +105,21 @@ Avoid unnecessary escape characters or special characters.
|
|
|
98
105
|
text: "</tool_response>"
|
|
99
106
|
}
|
|
100
107
|
];
|
|
108
|
+
case "execution-denied":
|
|
109
|
+
return [
|
|
110
|
+
{
|
|
111
|
+
type: "text",
|
|
112
|
+
text: `<tool_response_error name=${tool}>Execution denied: ${result.reason ?? NO_REASON_PROVIDED}</tool_response_error>`
|
|
113
|
+
}
|
|
114
|
+
];
|
|
115
|
+
default: {
|
|
116
|
+
return [
|
|
117
|
+
{
|
|
118
|
+
type: "text",
|
|
119
|
+
text: `<tool_response_error name=${tool}>Unknown result type: ${JSON.stringify(result)}</tool_response_error>`
|
|
120
|
+
}
|
|
121
|
+
];
|
|
122
|
+
}
|
|
101
123
|
}
|
|
102
124
|
},
|
|
103
125
|
commandResult: (command, exitCode, stdout, stderr) => `<command>${command}</command>
|
|
@@ -403,6 +425,179 @@ var NodeFileSystemProvider = class {
|
|
|
403
425
|
}
|
|
404
426
|
};
|
|
405
427
|
|
|
428
|
+
// src/pricing/pricing-service.ts
|
|
429
|
+
import { randomUUID } from "crypto";
|
|
430
|
+
import { mkdir, readFile as readFile2, rename, writeFile } from "fs/promises";
|
|
431
|
+
import { homedir } from "os";
|
|
432
|
+
import { dirname, join as join2 } from "path";
|
|
433
|
+
|
|
434
|
+
// src/pricing/converter.ts
|
|
435
|
+
function convertPortkeyToModelInfo(portkey) {
|
|
436
|
+
return {
|
|
437
|
+
inputPrice: (portkey.request_token?.price ?? 0) * 10,
|
|
438
|
+
outputPrice: (portkey.response_token?.price ?? 0) * 10,
|
|
439
|
+
cacheWritesPrice: (portkey.cache_write_input_token?.price ?? 0) * 10,
|
|
440
|
+
cacheReadsPrice: (portkey.cache_read_input_token?.price ?? 0) * 10
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// src/pricing/portkey-client.ts
|
|
445
|
+
var PORTKEY_BASE_URL = "https://api.portkey.ai/model-configs/pricing";
|
|
446
|
+
var TIMEOUT_MS = 5e3;
|
|
447
|
+
var MAX_RETRIES = 2;
|
|
448
|
+
async function fetchWithTimeout(url, timeoutMs) {
|
|
449
|
+
const controller = new AbortController();
|
|
450
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
451
|
+
try {
|
|
452
|
+
const response = await fetch(url, { signal: controller.signal });
|
|
453
|
+
return response;
|
|
454
|
+
} finally {
|
|
455
|
+
clearTimeout(timeout);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
async function sleep(ms) {
|
|
459
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
460
|
+
}
|
|
461
|
+
function shouldRetry(response, error) {
|
|
462
|
+
if (error) return true;
|
|
463
|
+
if (response.status >= 500) return true;
|
|
464
|
+
return false;
|
|
465
|
+
}
|
|
466
|
+
async function fetchPricing(provider, model) {
|
|
467
|
+
const url = `${PORTKEY_BASE_URL}/${provider}/${model}`;
|
|
468
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
469
|
+
try {
|
|
470
|
+
const response = await fetchWithTimeout(url, TIMEOUT_MS);
|
|
471
|
+
if (!response.ok) {
|
|
472
|
+
if (!shouldRetry(response, null)) {
|
|
473
|
+
return null;
|
|
474
|
+
}
|
|
475
|
+
if (attempt < MAX_RETRIES) {
|
|
476
|
+
await sleep(2 ** attempt * 1e3);
|
|
477
|
+
continue;
|
|
478
|
+
}
|
|
479
|
+
return null;
|
|
480
|
+
}
|
|
481
|
+
const data = await response.json();
|
|
482
|
+
return data;
|
|
483
|
+
} catch (error) {
|
|
484
|
+
if (attempt < MAX_RETRIES && shouldRetry(new Response(null, { status: 500 }), error)) {
|
|
485
|
+
await sleep(2 ** attempt * 1e3);
|
|
486
|
+
continue;
|
|
487
|
+
}
|
|
488
|
+
return null;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return null;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// src/pricing/pricing-service.ts
|
|
495
|
+
var CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
496
|
+
var PricingService = class {
|
|
497
|
+
#fallbackPrices;
|
|
498
|
+
#cacheFile;
|
|
499
|
+
#cache = null;
|
|
500
|
+
#loadPromise = null;
|
|
501
|
+
constructor(fallbackPrices = {}) {
|
|
502
|
+
const normalized = {};
|
|
503
|
+
for (const [provider, providerInfo] of Object.entries(fallbackPrices)) {
|
|
504
|
+
const normalizedProvider = provider.split("-")[0];
|
|
505
|
+
normalized[normalizedProvider] = {};
|
|
506
|
+
for (const [model, modelInfo] of Object.entries(providerInfo)) {
|
|
507
|
+
const normalizedModel = model.replace(/[.-]/g, "");
|
|
508
|
+
normalized[normalizedProvider][normalizedModel] = {
|
|
509
|
+
inputPrice: modelInfo.inputPrice ?? 0,
|
|
510
|
+
outputPrice: modelInfo.outputPrice ?? 0,
|
|
511
|
+
cacheWritesPrice: modelInfo.cacheWritesPrice ?? 0,
|
|
512
|
+
cacheReadsPrice: modelInfo.cacheReadsPrice ?? 0
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
this.#fallbackPrices = normalized;
|
|
517
|
+
this.#cacheFile = join2(homedir(), ".config", "polkacodes", "pricing-cache.json");
|
|
518
|
+
}
|
|
519
|
+
async #load() {
|
|
520
|
+
if (this.#loadPromise) {
|
|
521
|
+
return this.#loadPromise;
|
|
522
|
+
}
|
|
523
|
+
this.#loadPromise = (async () => {
|
|
524
|
+
this.#cache = /* @__PURE__ */ new Map();
|
|
525
|
+
try {
|
|
526
|
+
const content = await readFile2(this.#cacheFile, "utf-8");
|
|
527
|
+
const data = JSON.parse(content);
|
|
528
|
+
for (const [key, value] of Object.entries(data)) {
|
|
529
|
+
this.#cache.set(key, value);
|
|
530
|
+
}
|
|
531
|
+
} catch {
|
|
532
|
+
}
|
|
533
|
+
})();
|
|
534
|
+
return this.#loadPromise;
|
|
535
|
+
}
|
|
536
|
+
async #get(provider, model) {
|
|
537
|
+
await this.#load();
|
|
538
|
+
const key = `${provider}:${model}`;
|
|
539
|
+
const entry = this.#cache?.get(key);
|
|
540
|
+
if (!entry) {
|
|
541
|
+
return null;
|
|
542
|
+
}
|
|
543
|
+
if (Date.now() - entry.timestamp > CACHE_TTL_MS) {
|
|
544
|
+
this.#cache?.delete(key);
|
|
545
|
+
return null;
|
|
546
|
+
}
|
|
547
|
+
return entry.pricing;
|
|
548
|
+
}
|
|
549
|
+
async #set(provider, model, pricing) {
|
|
550
|
+
await this.#load();
|
|
551
|
+
const key = `${provider}:${model}`;
|
|
552
|
+
this.#cache?.set(key, {
|
|
553
|
+
pricing,
|
|
554
|
+
timestamp: Date.now()
|
|
555
|
+
});
|
|
556
|
+
await this.#save();
|
|
557
|
+
}
|
|
558
|
+
async #save() {
|
|
559
|
+
if (!this.#cache) {
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
try {
|
|
563
|
+
const dir = dirname(this.#cacheFile);
|
|
564
|
+
await mkdir(dir, { recursive: true });
|
|
565
|
+
const data = {};
|
|
566
|
+
for (const [key, value] of this.#cache.entries()) {
|
|
567
|
+
data[key] = value;
|
|
568
|
+
}
|
|
569
|
+
const tempFile = `${this.#cacheFile}.${randomUUID()}.tmp`;
|
|
570
|
+
await writeFile(tempFile, JSON.stringify(data, null, 2), "utf-8");
|
|
571
|
+
await rename(tempFile, this.#cacheFile);
|
|
572
|
+
} catch {
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
async getPricing(provider, model) {
|
|
576
|
+
const normalizedProvider = provider.split("-")[0];
|
|
577
|
+
const normalizedModel = model.replace(/[.-]/g, "");
|
|
578
|
+
const cached = await this.#get(normalizedProvider, normalizedModel);
|
|
579
|
+
if (cached) {
|
|
580
|
+
return cached;
|
|
581
|
+
}
|
|
582
|
+
const fallbackPrice = this.#fallbackPrices[normalizedProvider]?.[normalizedModel];
|
|
583
|
+
if (fallbackPrice) {
|
|
584
|
+
return fallbackPrice;
|
|
585
|
+
}
|
|
586
|
+
const portkeyPricing = await fetchPricing(normalizedProvider, model);
|
|
587
|
+
if (portkeyPricing) {
|
|
588
|
+
const modelInfo = convertPortkeyToModelInfo(portkeyPricing);
|
|
589
|
+
await this.#set(normalizedProvider, normalizedModel, modelInfo);
|
|
590
|
+
return modelInfo;
|
|
591
|
+
}
|
|
592
|
+
return {
|
|
593
|
+
inputPrice: 0,
|
|
594
|
+
outputPrice: 0,
|
|
595
|
+
cacheWritesPrice: 0,
|
|
596
|
+
cacheReadsPrice: 0
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
};
|
|
600
|
+
|
|
406
601
|
// src/skills/constants.ts
|
|
407
602
|
var SKILL_LIMITS = {
|
|
408
603
|
MAX_FILE_SIZE: 1024 * 1024,
|
|
@@ -456,7 +651,7 @@ var SOURCE_ICONS = {
|
|
|
456
651
|
};
|
|
457
652
|
|
|
458
653
|
// src/skills/discovery.ts
|
|
459
|
-
import { homedir } from "os";
|
|
654
|
+
import { homedir as homedir2 } from "os";
|
|
460
655
|
import { parse } from "yaml";
|
|
461
656
|
import { ZodError } from "zod";
|
|
462
657
|
|
|
@@ -546,7 +741,7 @@ var SkillDiscoveryService = class {
|
|
|
546
741
|
pluginSkillsDirs;
|
|
547
742
|
constructor(options) {
|
|
548
743
|
this.fs = options.fs ?? new NodeFileSystemProvider();
|
|
549
|
-
this.personalSkillsDir = options.personalSkillsDir ?? this.fs.join(
|
|
744
|
+
this.personalSkillsDir = options.personalSkillsDir ?? this.fs.join(homedir2(), ".claude", "skills");
|
|
550
745
|
this.projectSkillsDir = this.fs.join(options.cwd, ".claude", "skills");
|
|
551
746
|
this.pluginSkillsDirs = options.pluginSkillsDirs ?? [];
|
|
552
747
|
}
|
|
@@ -788,19 +983,19 @@ var SkillDiscoveryService = class {
|
|
|
788
983
|
};
|
|
789
984
|
|
|
790
985
|
// src/skills/validation.ts
|
|
791
|
-
import { join as
|
|
986
|
+
import { join as join3, normalize as normalize2 } from "path";
|
|
792
987
|
function validateSkillSecurity(skill) {
|
|
793
988
|
const { MAX_FILE_SIZE, MAX_SKILL_SIZE } = SKILL_LIMITS;
|
|
794
989
|
let totalSize = 0;
|
|
795
990
|
const contentSize = Buffer.byteLength(skill.content, "utf8");
|
|
796
991
|
if (contentSize > MAX_FILE_SIZE) {
|
|
797
|
-
throw new SkillValidationError(`SKILL.md content exceeds size limit (${contentSize} > ${MAX_FILE_SIZE})`,
|
|
992
|
+
throw new SkillValidationError(`SKILL.md content exceeds size limit (${contentSize} > ${MAX_FILE_SIZE})`, join3(skill.path, "SKILL.md"));
|
|
798
993
|
}
|
|
799
994
|
totalSize += contentSize;
|
|
800
995
|
for (const [filename, content] of skill.files) {
|
|
801
996
|
const fileSize = Buffer.byteLength(content, "utf8");
|
|
802
997
|
if (fileSize > MAX_FILE_SIZE) {
|
|
803
|
-
throw new SkillValidationError(`File ${filename} exceeds size limit (${fileSize} > ${MAX_FILE_SIZE})`,
|
|
998
|
+
throw new SkillValidationError(`File ${filename} exceeds size limit (${fileSize} > ${MAX_FILE_SIZE})`, join3(skill.path, filename));
|
|
804
999
|
}
|
|
805
1000
|
totalSize += fileSize;
|
|
806
1001
|
}
|
|
@@ -809,7 +1004,7 @@ function validateSkillSecurity(skill) {
|
|
|
809
1004
|
}
|
|
810
1005
|
validateContentSecurity(skill.content, skill.path);
|
|
811
1006
|
for (const [filename, content] of skill.files) {
|
|
812
|
-
validateContentSecurity(content,
|
|
1007
|
+
validateContentSecurity(content, join3(skill.path, filename));
|
|
813
1008
|
}
|
|
814
1009
|
}
|
|
815
1010
|
function validateContentSecurity(content, path) {
|
|
@@ -2268,12 +2463,22 @@ var writeToFile_default = {
|
|
|
2268
2463
|
};
|
|
2269
2464
|
|
|
2270
2465
|
// src/UsageMeter.ts
|
|
2466
|
+
var ZERO_PRICING = {
|
|
2467
|
+
inputPrice: 0,
|
|
2468
|
+
outputPrice: 0,
|
|
2469
|
+
cacheWritesPrice: 0,
|
|
2470
|
+
cacheReadsPrice: 0
|
|
2471
|
+
};
|
|
2472
|
+
var TOKENS_PER_UNIT = 1e6;
|
|
2473
|
+
var MAX_METADATA_ENTRIES = 1e3;
|
|
2271
2474
|
var UsageMeter = class {
|
|
2272
2475
|
#totals = { input: 0, output: 0, cachedRead: 0, cost: 0, messageCount: 0 };
|
|
2273
2476
|
#providerMetadataEntries = [];
|
|
2477
|
+
#pendingUpdates = /* @__PURE__ */ new Set();
|
|
2274
2478
|
#modelInfos;
|
|
2275
2479
|
#maxMessages;
|
|
2276
2480
|
#maxCost;
|
|
2481
|
+
#pricingService;
|
|
2277
2482
|
constructor(modelInfos = {}, opts = {}) {
|
|
2278
2483
|
const infos = {};
|
|
2279
2484
|
for (const [provider, providerInfo] of Object.entries(modelInfos)) {
|
|
@@ -2289,80 +2494,126 @@ var UsageMeter = class {
|
|
|
2289
2494
|
this.#modelInfos = infos;
|
|
2290
2495
|
this.#maxMessages = opts.maxMessages ?? 1e3;
|
|
2291
2496
|
this.#maxCost = opts.maxCost ?? 100;
|
|
2497
|
+
this.#pricingService = opts.pricingService;
|
|
2292
2498
|
}
|
|
2293
|
-
#
|
|
2499
|
+
#calculateUsageV3(usage, providerMetadata, modelInfo) {
|
|
2500
|
+
if (!usage?.inputTokens || !usage?.outputTokens) {
|
|
2501
|
+
return { input: 0, output: 0, cachedRead: 0, cost: 0 };
|
|
2502
|
+
}
|
|
2503
|
+
const providerMetadataKey = Object.keys(providerMetadata ?? {})[0];
|
|
2504
|
+
const metadata = providerMetadata?.[providerMetadataKey] ?? {};
|
|
2505
|
+
const inputTokens = usage.inputTokens.noCache ?? usage.inputTokens.total ?? 0;
|
|
2506
|
+
const cachedReadTokens = usage.inputTokens.cacheRead ?? 0;
|
|
2507
|
+
const cachedWriteTokens = usage.inputTokens.cacheWrite ?? 0;
|
|
2508
|
+
const outputTokens = usage.outputTokens.total ?? usage.outputTokens.text ?? 0;
|
|
2509
|
+
return this.#calculateCost(inputTokens, outputTokens, cachedReadTokens, cachedWriteTokens, providerMetadataKey, metadata, modelInfo);
|
|
2510
|
+
}
|
|
2511
|
+
#calculateUsageAiPackage(usage, providerMetadata, modelInfo) {
|
|
2512
|
+
if (!usage?.inputTokens || !usage?.outputTokens) {
|
|
2513
|
+
return { input: 0, output: 0, cachedRead: 0, cost: 0 };
|
|
2514
|
+
}
|
|
2294
2515
|
const providerMetadataKey = Object.keys(providerMetadata ?? {})[0];
|
|
2295
2516
|
const metadata = providerMetadata?.[providerMetadataKey] ?? {};
|
|
2517
|
+
const details = usage.inputTokenDetails;
|
|
2518
|
+
const outputDetails = usage.outputTokenDetails;
|
|
2519
|
+
const inputTokens = details?.noCacheTokens ?? usage.inputTokens ?? 0;
|
|
2520
|
+
const cachedReadTokens = details?.cacheReadTokens ?? 0;
|
|
2521
|
+
const cachedWriteTokens = details?.cacheWriteTokens ?? 0;
|
|
2522
|
+
const outputTokens = outputDetails?.textTokens ?? usage.outputTokens ?? 0;
|
|
2523
|
+
return this.#calculateCost(inputTokens, outputTokens, cachedReadTokens, cachedWriteTokens, providerMetadataKey, metadata, modelInfo);
|
|
2524
|
+
}
|
|
2525
|
+
#calculateCost(inputTokens, outputTokens, cachedReadTokens, cachedWriteTokens, providerMetadataKey, metadata, modelInfo) {
|
|
2526
|
+
const getNumber = (obj, key) => {
|
|
2527
|
+
const value = obj[key];
|
|
2528
|
+
return typeof value === "number" ? value : void 0;
|
|
2529
|
+
};
|
|
2296
2530
|
switch (providerMetadataKey) {
|
|
2297
|
-
case "openrouter":
|
|
2531
|
+
case "openrouter": {
|
|
2532
|
+
const usage = metadata.usage;
|
|
2533
|
+
const cost = typeof usage === "object" && usage !== null && "cost" in usage && typeof usage.cost === "number" ? usage.cost : 0;
|
|
2298
2534
|
return {
|
|
2299
|
-
input:
|
|
2300
|
-
output:
|
|
2301
|
-
cachedRead:
|
|
2302
|
-
cost
|
|
2535
|
+
input: inputTokens,
|
|
2536
|
+
output: outputTokens,
|
|
2537
|
+
cachedRead: cachedReadTokens,
|
|
2538
|
+
cost
|
|
2303
2539
|
};
|
|
2540
|
+
}
|
|
2304
2541
|
case "anthropic": {
|
|
2305
|
-
const
|
|
2306
|
-
const cacheWrite = metadata?.promptCacheMissTokens ?? 0;
|
|
2307
|
-
const input = usage.inputTokens ?? 0;
|
|
2308
|
-
const output = usage.outputTokens ?? 0;
|
|
2542
|
+
const cacheWrite = getNumber(metadata, "promptCacheMissTokens") ?? cachedWriteTokens;
|
|
2309
2543
|
return {
|
|
2310
|
-
input:
|
|
2311
|
-
output,
|
|
2312
|
-
cachedRead,
|
|
2313
|
-
cost: (
|
|
2544
|
+
input: inputTokens + cacheWrite + cachedReadTokens,
|
|
2545
|
+
output: outputTokens,
|
|
2546
|
+
cachedRead: cachedReadTokens,
|
|
2547
|
+
cost: (inputTokens * modelInfo.inputPrice + outputTokens * modelInfo.outputPrice + cacheWrite * modelInfo.cacheWritesPrice + cachedReadTokens * modelInfo.cacheReadsPrice) / TOKENS_PER_UNIT
|
|
2314
2548
|
};
|
|
2315
2549
|
}
|
|
2316
2550
|
case "deepseek": {
|
|
2317
|
-
const
|
|
2318
|
-
const cacheWrite = metadata.promptCacheMissTokens ?? 0;
|
|
2319
|
-
const input = usage.inputTokens ?? 0;
|
|
2320
|
-
const output = usage.outputTokens ?? 0;
|
|
2551
|
+
const cacheWrite = getNumber(metadata, "promptCacheMissTokens") ?? cachedWriteTokens;
|
|
2321
2552
|
return {
|
|
2322
|
-
input,
|
|
2323
|
-
output,
|
|
2324
|
-
cachedRead,
|
|
2325
|
-
cost: (
|
|
2553
|
+
input: inputTokens,
|
|
2554
|
+
output: outputTokens,
|
|
2555
|
+
cachedRead: cachedReadTokens,
|
|
2556
|
+
cost: (outputTokens * modelInfo.outputPrice + cacheWrite * modelInfo.inputPrice + cachedReadTokens * modelInfo.cacheReadsPrice) / TOKENS_PER_UNIT
|
|
2326
2557
|
};
|
|
2327
2558
|
}
|
|
2328
2559
|
default: {
|
|
2329
|
-
const cachedRead = usage.cachedInputTokens ?? 0;
|
|
2330
|
-
const input = usage.inputTokens ?? 0;
|
|
2331
|
-
const output = usage.outputTokens ?? 0;
|
|
2332
2560
|
return {
|
|
2333
|
-
input,
|
|
2334
|
-
output,
|
|
2335
|
-
cachedRead,
|
|
2336
|
-
cost: (
|
|
2561
|
+
input: inputTokens,
|
|
2562
|
+
output: outputTokens,
|
|
2563
|
+
cachedRead: cachedReadTokens,
|
|
2564
|
+
cost: (inputTokens * modelInfo.inputPrice + outputTokens * modelInfo.outputPrice) / TOKENS_PER_UNIT
|
|
2337
2565
|
};
|
|
2338
2566
|
}
|
|
2339
2567
|
}
|
|
2340
2568
|
}
|
|
2341
2569
|
addUsage(llm, resp, options = {}) {
|
|
2342
|
-
const
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2570
|
+
const provider = llm.provider.split(".")[0];
|
|
2571
|
+
const normalizedModel = llm.modelId.replace(/[.-]/g, "");
|
|
2572
|
+
const key = `${provider}:${normalizedModel}`;
|
|
2573
|
+
let modelInfo = options.modelInfo ?? this.#modelInfos[key];
|
|
2574
|
+
const updatePromise = (async () => {
|
|
2575
|
+
try {
|
|
2576
|
+
if (!modelInfo && this.#pricingService) {
|
|
2577
|
+
modelInfo = await this.#pricingService.getPricing(provider, llm.modelId);
|
|
2578
|
+
this.#modelInfos[key] = modelInfo;
|
|
2579
|
+
}
|
|
2580
|
+
} catch {
|
|
2581
|
+
modelInfo = ZERO_PRICING;
|
|
2582
|
+
}
|
|
2583
|
+
modelInfo = modelInfo ?? ZERO_PRICING;
|
|
2584
|
+
const usage = "totalUsage" in resp ? resp.totalUsage : resp.usage;
|
|
2585
|
+
let result;
|
|
2586
|
+
if ("inputTokenDetails" in usage || typeof usage.inputTokens === "number") {
|
|
2587
|
+
result = this.#calculateUsageAiPackage(usage, resp.providerMetadata, modelInfo);
|
|
2588
|
+
} else {
|
|
2589
|
+
result = this.#calculateUsageV3(usage, resp.providerMetadata, modelInfo);
|
|
2590
|
+
}
|
|
2591
|
+
this.#totals.input += result.input;
|
|
2592
|
+
this.#totals.output += result.output;
|
|
2593
|
+
this.#totals.cachedRead += result.cachedRead;
|
|
2594
|
+
this.#totals.cost += result.cost;
|
|
2595
|
+
this.#totals.messageCount += 1;
|
|
2596
|
+
if (resp.providerMetadata && Object.keys(resp.providerMetadata).length > 0) {
|
|
2597
|
+
const providerKey = Object.keys(resp.providerMetadata)[0] || llm.provider;
|
|
2598
|
+
const metadata = resp.providerMetadata[providerKey];
|
|
2599
|
+
if (typeof metadata === "object" && metadata !== null && !Array.isArray(metadata)) {
|
|
2600
|
+
this.#providerMetadataEntries.push({
|
|
2601
|
+
provider: providerKey,
|
|
2602
|
+
model: llm.modelId,
|
|
2603
|
+
metadata,
|
|
2604
|
+
timestamp: Date.now()
|
|
2605
|
+
});
|
|
2606
|
+
}
|
|
2607
|
+
if (this.#providerMetadataEntries.length > MAX_METADATA_ENTRIES) {
|
|
2608
|
+
this.#providerMetadataEntries.splice(0, this.#providerMetadataEntries.length - MAX_METADATA_ENTRIES);
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
})();
|
|
2612
|
+
this.#pendingUpdates.add(updatePromise);
|
|
2613
|
+
updatePromise.finally(() => {
|
|
2614
|
+
this.#pendingUpdates.delete(updatePromise);
|
|
2615
|
+
});
|
|
2616
|
+
return updatePromise;
|
|
2366
2617
|
}
|
|
2367
2618
|
/** Override the running totals (e.g., restore from saved state). */
|
|
2368
2619
|
setUsage(newUsage, options = {}) {
|
|
@@ -2421,10 +2672,11 @@ var UsageMeter = class {
|
|
|
2421
2672
|
let requestsWithCache = 0;
|
|
2422
2673
|
for (const entry of entries) {
|
|
2423
2674
|
const metadata = entry.metadata;
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2675
|
+
const getValueAsNumber = (key) => {
|
|
2676
|
+
const value = metadata[key];
|
|
2677
|
+
return typeof value === "number" ? value : void 0;
|
|
2678
|
+
};
|
|
2679
|
+
const cachedTokens = getValueAsNumber("cachedPromptTokens") ?? getValueAsNumber("cacheReadTokens") ?? getValueAsNumber("prompt_cache_hit_tokens") ?? 0;
|
|
2428
2680
|
if (cachedTokens > 0) {
|
|
2429
2681
|
totalCachedTokens += cachedTokens;
|
|
2430
2682
|
requestsWithCache++;
|
|
@@ -2453,13 +2705,18 @@ var UsageMeter = class {
|
|
|
2453
2705
|
this.#totals.messageCount += otherUsage.messageCount;
|
|
2454
2706
|
this.#providerMetadataEntries.push(...other.providerMetadata);
|
|
2455
2707
|
}
|
|
2708
|
+
/** Wait for all pending usage updates to complete. */
|
|
2709
|
+
async waitForPending() {
|
|
2710
|
+
const pending = Array.from(this.#pendingUpdates);
|
|
2711
|
+
await Promise.allSettled(pending);
|
|
2712
|
+
}
|
|
2456
2713
|
getUsageText() {
|
|
2457
2714
|
const u = this.usage;
|
|
2458
2715
|
return `Usage - messages: ${u.messageCount}, input: ${u.input}, cached: ${u.cachedRead}, output: ${u.output}, cost: $${u.cost.toFixed(4)}`;
|
|
2459
2716
|
}
|
|
2460
2717
|
onFinishHandler(llm) {
|
|
2461
|
-
return (evt) => {
|
|
2462
|
-
this.addUsage(llm, evt);
|
|
2718
|
+
return async (evt) => {
|
|
2719
|
+
await this.addUsage(llm, evt);
|
|
2463
2720
|
};
|
|
2464
2721
|
}
|
|
2465
2722
|
};
|
|
@@ -2497,6 +2754,9 @@ var TaskEventKind = /* @__PURE__ */ ((TaskEventKind2) => {
|
|
|
2497
2754
|
})(TaskEventKind || {});
|
|
2498
2755
|
|
|
2499
2756
|
// src/workflow/agent.workflow.ts
|
|
2757
|
+
function isValidToolResultOutput(value) {
|
|
2758
|
+
return typeof value === "object" && value !== null && "type" in value && (value.type === "text" || value.type === "content" || value.type === "execution-denied");
|
|
2759
|
+
}
|
|
2500
2760
|
var agentWorkflow = async (input, { step, tools, logger }) => {
|
|
2501
2761
|
const event = (name, event2) => step(name, () => tools.taskEvent(event2));
|
|
2502
2762
|
const { tools: toolInfo13, maxToolRoundTrips = 200 } = input;
|
|
@@ -2610,6 +2870,9 @@ var agentWorkflow = async (input, { step, tools, logger }) => {
|
|
|
2610
2870
|
tool: toolCall.toolName,
|
|
2611
2871
|
content: toolResponse.message
|
|
2612
2872
|
});
|
|
2873
|
+
if (!isValidToolResultOutput(toolResponse.message)) {
|
|
2874
|
+
throw new Error(`Invalid tool result format from ${toolCall.toolName}`);
|
|
2875
|
+
}
|
|
2613
2876
|
toolResults.push({
|
|
2614
2877
|
toolCallId: toolCall.toolCallId,
|
|
2615
2878
|
toolName: toolCall.toolName,
|
|
@@ -2621,6 +2884,9 @@ var agentWorkflow = async (input, { step, tools, logger }) => {
|
|
|
2621
2884
|
tool: toolCall.toolName,
|
|
2622
2885
|
error: toolResponse.message ?? "Unknown error"
|
|
2623
2886
|
});
|
|
2887
|
+
if (!isValidToolResultOutput(toolResponse.message)) {
|
|
2888
|
+
throw new Error(`Invalid tool result format from ${toolCall.toolName}`);
|
|
2889
|
+
}
|
|
2624
2890
|
toolResults.push({
|
|
2625
2891
|
toolCallId: toolCall.toolCallId,
|
|
2626
2892
|
toolName: toolCall.toolName,
|
|
@@ -3776,6 +4042,7 @@ export {
|
|
|
3776
4042
|
LoadSkillOutputSchema,
|
|
3777
4043
|
MockProvider,
|
|
3778
4044
|
NodeFileSystemProvider,
|
|
4045
|
+
PricingService,
|
|
3779
4046
|
ReadSkillFileInputSchema,
|
|
3780
4047
|
ReadSkillFileOutputSchema,
|
|
3781
4048
|
SKILL_ERROR_MESSAGES,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polka-codes/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"license": "AGPL-3.0",
|
|
5
5
|
"author": "github@polka.codes",
|
|
6
6
|
"type": "module",
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
"build": "tsup src/index.ts --experimental-dts --format esm --clean"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@ai-sdk/provider": "^
|
|
21
|
-
"@ai-sdk/provider-utils": "^
|
|
22
|
-
"ai": "^
|
|
20
|
+
"@ai-sdk/provider": "^3.0.8",
|
|
21
|
+
"@ai-sdk/provider-utils": "^4.0.19",
|
|
22
|
+
"ai": "^6.0.116",
|
|
23
23
|
"yaml": "^2.8.2",
|
|
24
24
|
"zod": "^4.3.5"
|
|
25
25
|
}
|