@arcote.tech/arc-ai 0.5.2 → 0.5.6

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@arcote.tech/arc-ai",
3
3
  "type": "module",
4
- "version": "0.5.2",
4
+ "version": "0.5.6",
5
5
  "private": false,
6
6
  "description": "AI provider abstraction, completion tracking, and budget management for Arc framework",
7
7
  "main": "./src/index.ts",
@@ -10,8 +10,8 @@
10
10
  "type-check": "tsc --noEmit"
11
11
  },
12
12
  "peerDependencies": {
13
- "@arcote.tech/arc": "^0.5.2",
14
- "@arcote.tech/arc-auth": "^0.5.2",
13
+ "@arcote.tech/arc": "^0.5.6",
14
+ "@arcote.tech/arc-auth": "^0.5.6",
15
15
  "typescript": "^5.0.0"
16
16
  },
17
17
  "devDependencies": {
package/src/index.ts CHANGED
@@ -25,12 +25,18 @@ export type {
25
25
  ProviderName,
26
26
  CompletionRequest,
27
27
  CompletionResult,
28
+ Conversation,
29
+ ConversationTurn,
30
+ UserTurn,
31
+ AssistantTurn,
32
+ ToolResultTurn,
33
+ AssistantContentBlock,
34
+ TextBlock,
35
+ ToolCallBlock,
28
36
  StreamChunk,
29
37
  StreamEventType,
30
38
  ChatStreamEvent,
31
39
  ChatStreamEventType,
32
- Message,
33
- MessageRole,
34
40
  ToolCall,
35
41
  ToolResult,
36
42
  TokenUsage,
package/src/types.ts CHANGED
@@ -4,32 +4,92 @@ import type { JsonSchemaToolDef } from "./tool/tool";
4
4
 
5
5
  export type ProviderName = "openai" | "gemini" | "claude";
6
6
 
7
- // ─── Messages ────────────────────────────────────────────────────
7
+ // ─── Tool Calls ──────────────────────────────────────────────────
8
8
 
9
- export type MessageRole = "system" | "user" | "assistant" | "tool";
9
+ export interface ToolCall {
10
+ id: string;
11
+ name: string;
12
+ arguments: Record<string, unknown>;
13
+ }
10
14
 
11
- export interface Message {
12
- role: MessageRole;
15
+ export interface ToolResult {
16
+ toolCallId: string;
17
+ name: string;
13
18
  content: string;
14
- name?: string;
15
- toolCallId?: string;
19
+ isError: boolean;
16
20
  }
17
21
 
18
- // ─── Tool Calls ──────────────────────────────────────────────────
22
+ // ─── Assistant content blocks (ordered) ─────────────────────────
23
+
24
+ /**
25
+ * Real model output interleaves text and tool calls — e.g.
26
+ * "Let me check X" → tool_call → "and now Y" → tool_call. Both OpenAI Responses
27
+ * (output[]) and Claude (content[]) preserve this order. We mirror it 1:1 to
28
+ * avoid losing semantic structure.
29
+ */
30
+ export interface TextBlock {
31
+ type: "text";
32
+ text: string;
33
+ }
19
34
 
20
- export interface ToolCall {
35
+ export interface ToolCallBlock {
36
+ type: "tool_call";
21
37
  id: string;
22
38
  name: string;
23
39
  arguments: Record<string, unknown>;
24
40
  }
25
41
 
26
- export interface ToolResult {
42
+ export type AssistantContentBlock = TextBlock | ToolCallBlock;
43
+
44
+ // ─── Conversation turns ─────────────────────────────────────────
45
+
46
+ export interface UserTurn {
47
+ role: "user";
48
+ content: string;
49
+ }
50
+
51
+ export interface AssistantTurn {
52
+ role: "assistant";
53
+ /** Ordered model output: text and tool_call blocks interleaved as produced. */
54
+ blocks: AssistantContentBlock[];
55
+ /**
56
+ * Provider-issued response identifier for the turn this represents. Used by
57
+ * adapters that support server-side continuity (OpenAI Responses API) to
58
+ * anchor `previous_response_id` requests. Other adapters ignore this field.
59
+ */
60
+ responseId?: string;
61
+ }
62
+
63
+ export interface ToolResultTurn {
64
+ role: "tool_result";
27
65
  toolCallId: string;
28
66
  name: string;
29
67
  content: string;
30
- isError: boolean;
68
+ isError?: boolean;
31
69
  }
32
70
 
71
+ export type ConversationTurn = UserTurn | AssistantTurn | ToolResultTurn;
72
+
73
+ // ─── Conversation (full vs continuation) ────────────────────────
74
+
75
+ /**
76
+ * Discriminated union telling the adapter exactly what to send.
77
+ *
78
+ * - `full`: send every turn from `turns`. Used for cold start, or for any
79
+ * provider that does not support server-side continuity (Claude, Gemini).
80
+ *
81
+ * - `continuation`: send only `newTurns` (the delta after the previous
82
+ * response). Used by providers with server-side state (OpenAI Responses API).
83
+ * The provider replays prior context server-side via `previousResponseId`.
84
+ */
85
+ export type Conversation =
86
+ | { mode: "full"; turns: ConversationTurn[] }
87
+ | {
88
+ mode: "continuation";
89
+ previousResponseId: string;
90
+ newTurns: ConversationTurn[];
91
+ };
92
+
33
93
  // ─── Token Usage ─────────────────────────────────────────────────
34
94
 
35
95
  export interface TokenUsage {
@@ -46,20 +106,35 @@ export type FinishReason = "stop" | "tool_call" | "max_tokens" | "error";
46
106
 
47
107
  export interface CompletionRequest {
48
108
  model: string;
49
- messages: Message[];
109
+ /**
110
+ * System prompt for this turn. Sent on every call. Providers that support
111
+ * server-side continuity (OpenAI Responses API) replace previously stored
112
+ * instructions for the new turn. Required — pass empty string if there is
113
+ * nothing to say.
114
+ */
115
+ instructions: string;
116
+ conversation: Conversation;
50
117
  tools?: JsonSchemaToolDef[];
51
118
  toolChoice?: "auto" | "required" | { type: "function"; name: string };
52
119
  webSearch?: boolean;
53
120
  temperature?: number;
54
121
  maxTokens?: number;
55
- previousResponseId?: string;
56
122
  }
57
123
 
58
124
  export interface CompletionResult {
59
- content: string;
60
- toolCalls: ToolCall[];
125
+ /**
126
+ * Ordered output blocks from the model — same shape as `AssistantTurn.blocks`.
127
+ * Caller can persist this directly as a new AssistantTurn in history.
128
+ */
129
+ blocks: AssistantContentBlock[];
61
130
  usage: TokenUsage;
62
131
  finishReason: FinishReason;
132
+ /**
133
+ * Provider-issued response ID. Set by adapters that support server-side
134
+ * continuity (OpenAI). Caller persists this on the resulting AssistantTurn
135
+ * and passes it back as `Conversation.continuation.previousResponseId` next
136
+ * time.
137
+ */
63
138
  responseId?: string;
64
139
  }
65
140
 
@@ -88,6 +163,14 @@ export interface StreamChunk {
88
163
  export interface LLMProvider {
89
164
  name: ProviderName;
90
165
  models: string[];
166
+ /**
167
+ * Capability flag. When `true`, the listener may send
168
+ * `Conversation.mode = "continuation"` with a `previousResponseId` to skip
169
+ * resending history (OpenAI Responses API). When `false`, the listener must
170
+ * always send `Conversation.mode = "full"` with the full conversation
171
+ * history (Claude, Gemini).
172
+ */
173
+ supportsContinuation: boolean;
91
174
  complete(request: CompletionRequest): Promise<CompletionResult>;
92
175
  streamComplete(
93
176
  request: CompletionRequest,