Skip to content
Source
Sign inSign up
Open History to see the last commit

providerRuntime.ts

165 lines6.4 KB

1import * as Effect from "effect/Effect";
2import * as Schema from "effect/Schema";
3import { NonNegativeInt, PositiveInt, TrimmedNonEmptyString } from "./baseSchemas.ts";
4​
5const TrimmedNonEmptyStringSchema = TrimmedNonEmptyString;
6​
7const RuntimeTurnState = Schema.Literals(["completed", "failed", "interrupted", "cancelled"]);
8export type RuntimeTurnState = typeof RuntimeTurnState.Type;
9​
10const RuntimeItemStatus = Schema.Literals(["inProgress", "completed", "failed", "declined"]);
11export type RuntimeItemStatus = typeof RuntimeItemStatus.Type;
12​
13const TOOL_LIFECYCLE_ITEM_TYPES = [
14 "command_execution",
15 "file_change",
16 "mcp_tool_call",
17 "dynamic_tool_call",
18 "collab_agent_tool_call",
19 "web_search",
20 "image_view",
21] as const;
22​
23export const ToolLifecycleItemType = Schema.Literals(TOOL_LIFECYCLE_ITEM_TYPES);
24export type ToolLifecycleItemType = typeof ToolLifecycleItemType.Type;
25​
26export function isToolLifecycleItemType(value: string): value is ToolLifecycleItemType {
27 return TOOL_LIFECYCLE_ITEM_TYPES.includes(value as ToolLifecycleItemType);
29​
30// What occupies the context window, by category. Clients own the labels.
31export const ContextBreakdownKind = Schema.Literals([
32 "system_prompt",
33 "system_tools",
34 "mcp_tools",
35 "t3_tools",
36 "memory_files",
37 "skills",
38 "custom_agents",
39 "messages",
40 "other",
41]);
42export type ContextBreakdownKind = typeof ContextBreakdownKind.Type;
43​
44export const ContextBreakdown = Schema.Array(
45 Schema.Struct({ kind: ContextBreakdownKind, tokens: NonNegativeInt }),
46).check(Schema.isMaxLength(16));
47export type ContextBreakdown = typeof ContextBreakdown.Type;
48​
49export const ThreadTokenUsageSnapshot = Schema.Struct({
50 usedTokens: NonNegativeInt,
51 totalProcessedTokens: Schema.optional(NonNegativeInt),
52 maxTokens: Schema.optional(PositiveInt),
53 inputTokens: Schema.optional(NonNegativeInt),
54 cachedInputTokens: Schema.optional(NonNegativeInt),
55 outputTokens: Schema.optional(NonNegativeInt),
56 reasoningOutputTokens: Schema.optional(NonNegativeInt),
57 lastUsedTokens: Schema.optional(NonNegativeInt),
58 lastInputTokens: Schema.optional(NonNegativeInt),
59 lastCachedInputTokens: Schema.optional(NonNegativeInt),
60 lastOutputTokens: Schema.optional(NonNegativeInt),
61 lastReasoningOutputTokens: Schema.optional(NonNegativeInt),
62 toolUses: Schema.optional(NonNegativeInt),
63 durationMs: Schema.optional(NonNegativeInt),
64 compactsAutomatically: Schema.optional(Schema.Boolean),
65 autoCompactThreshold: Schema.optional(PositiveInt),
66 breakdown: Schema.optional(ContextBreakdown),
67 cost: Schema.optional(
68 Schema.Struct({
69 amount: Schema.Number.check(Schema.isFinite()),
70 currency: TrimmedNonEmptyStringSchema.check(Schema.isMaxLength(32)),
71 }),
72 ),
73});
74export type ThreadTokenUsageSnapshot = typeof ThreadTokenUsageSnapshot.Type;
75​
76// Input includes cache reads/writes; output includes the optional reasoningTokens subset.
77const TurnTokenUsageCommonFields = {
78 usageScope: Schema.Literal("main_agent"),
79 cachedInputTokens: Schema.optional(NonNegativeInt),
80 cacheCreationTokens: Schema.optional(NonNegativeInt),
81 reasoningTokens: Schema.optional(NonNegativeInt),
82 hasSubagents: Schema.Boolean,
83 // Native model ids the provider reported for the main agent's work. Absent means unknown.
84 models: Schema.optional(Schema.Array(TrimmedNonEmptyStringSchema)),
85 // The provider ran a local command; its counters describe that result, not model work.
86 localCommand: Schema.optional(Schema.Boolean),
87 // Provider-ledger counts beyond the main agent, such as native subagents and compaction.
88 otherUsage: Schema.optional(
89 Schema.Struct({ inputTokens: NonNegativeInt, outputTokens: NonNegativeInt }),
90 ),
91};
92export const TurnTokenUsage = Schema.Union([
93 Schema.Struct({
94 ...TurnTokenUsageCommonFields,
95 usageStatus: Schema.Literal("complete"),
96 inputTokens: NonNegativeInt,
97 outputTokens: NonNegativeInt,
98 }),
99 Schema.Struct({
100 ...TurnTokenUsageCommonFields,
101 usageStatus: Schema.Literals(["partial", "unavailable"]),
102 inputTokens: Schema.optional(NonNegativeInt),
103 outputTokens: Schema.optional(NonNegativeInt),
104 }),
105]);
106export type TurnTokenUsage = typeof TurnTokenUsage.Type;
107​
108export const ToolActivitySurface = Schema.Literals(["browser", "computer"]);
109export type ToolActivitySurface = typeof ToolActivitySurface.Type;
110​
111export const ToolActivityNativeAppReference = Schema.Union([
112 Schema.TaggedStruct("app-id", {
113 appId: TrimmedNonEmptyStringSchema.check(
114 Schema.isMaxLength(512),
115 Schema.isPattern(/^[A-Za-z0-9._-]+$/u),
116 ),
117 }),
118 Schema.TaggedStruct("display-name", {
119 displayName: TrimmedNonEmptyStringSchema.check(Schema.isMaxLength(160)),
120 }),
121]);
122export type ToolActivityNativeAppReference = typeof ToolActivityNativeAppReference.Type;
123​
124export const ToolActivityIcon = Schema.Union([
125 Schema.TaggedStruct("website", {
126 pageUrl: TrimmedNonEmptyStringSchema.check(Schema.isMaxLength(4096)),
127 faviconUrl: Schema.optional(TrimmedNonEmptyStringSchema.check(Schema.isMaxLength(4096))),
128 faviconUrlDark: Schema.optional(TrimmedNonEmptyStringSchema.check(Schema.isMaxLength(4096))),
129 }),
130 Schema.TaggedStruct("native-app", {
131 app: ToolActivityNativeAppReference,
132 }),
133 Schema.TaggedStruct("themed-logo", {
134 logoUrl: TrimmedNonEmptyStringSchema.check(Schema.isMaxLength(4096)),
135 logoUrlDark: Schema.optional(TrimmedNonEmptyStringSchema.check(Schema.isMaxLength(4096))),
136 }),
137]);
138export type ToolActivityIcon = typeof ToolActivityIcon.Type;
139​
140export const ToolActivitySource = Schema.Struct({
141 key: TrimmedNonEmptyStringSchema.check(Schema.isMaxLength(512)),
142 name: TrimmedNonEmptyStringSchema.check(Schema.isMaxLength(160)),
143 kind: Schema.Literals(["browser", "computer", "integration"]),
144 icon: Schema.optional(ToolActivityIcon),
145});
146export type ToolActivitySource = typeof ToolActivitySource.Type;
147​
148const UserInputQuestionOption = Schema.Struct({
149 label: TrimmedNonEmptyStringSchema,
150 description: Schema.String,
151 value: Schema.optional(Schema.String),
152});
153​
154export const UserInputQuestion = Schema.Struct({
155 id: TrimmedNonEmptyStringSchema,
156 header: TrimmedNonEmptyStringSchema,
157 question: TrimmedNonEmptyStringSchema,
158 options: Schema.Array(UserInputQuestionOption),
159 allowCustomAnswer: Schema.optional(Schema.Boolean),
160 initialAnswer: Schema.optional(Schema.String),
161 multiSelect: Schema.optional(Schema.Boolean).pipe(
162 Schema.withConstructorDefault(Effect.succeed(false)),
163 ),
164});
165export type UserInputQuestion = typeof UserInputQuestion.Type;