@arcote.tech/arc-ai 0.7.7 → 0.7.9
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 +3 -3
- package/src/aggregates/credit-ledger.ts +57 -49
- package/src/tool/tool.ts +4 -4
- package/src/types.ts +69 -19
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcote.tech/arc-ai",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.9",
|
|
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.7.
|
|
14
|
-
"@arcote.tech/arc-auth": "^0.7.
|
|
13
|
+
"@arcote.tech/arc": "^0.7.9",
|
|
14
|
+
"@arcote.tech/arc-auth": "^0.7.9",
|
|
15
15
|
"typescript": "^5.0.0"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
@@ -96,63 +96,73 @@ export function creditLedger(config: {
|
|
|
96
96
|
},
|
|
97
97
|
)
|
|
98
98
|
|
|
99
|
-
// ─── topUp — add credits
|
|
99
|
+
// ─── topUp — add credits (server-internal: listeners, cron, ai-orchestration)
|
|
100
100
|
.mutateMethod(
|
|
101
101
|
"topUp",
|
|
102
|
-
(fn) => fn
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
102
|
+
(fn) => fn
|
|
103
|
+
.private()
|
|
104
|
+
.withParams({
|
|
105
|
+
scopeId,
|
|
106
|
+
amount: number(),
|
|
107
|
+
reason: string(),
|
|
108
|
+
metadata: string().optional(),
|
|
109
|
+
})
|
|
110
|
+
.handle(
|
|
111
|
+
ONLY_SERVER &&
|
|
112
|
+
(async (ctx, params) => {
|
|
113
|
+
const entryId = ledgerId.generate();
|
|
114
|
+
await ctx.credited.emit({
|
|
115
|
+
ledgerId: entryId,
|
|
116
|
+
scopeId: params.scopeId,
|
|
117
|
+
amount: params.amount,
|
|
118
|
+
reason: params.reason,
|
|
119
|
+
metadata: params.metadata,
|
|
120
|
+
});
|
|
121
|
+
return { ok: true };
|
|
122
|
+
}),
|
|
123
|
+
),
|
|
121
124
|
)
|
|
122
125
|
|
|
123
|
-
// ─── deduct — remove credits
|
|
126
|
+
// ─── deduct — remove credits (server-internal: ai consumers)
|
|
124
127
|
.mutateMethod(
|
|
125
128
|
"deduct",
|
|
126
|
-
(fn) => fn
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
129
|
+
(fn) => fn
|
|
130
|
+
.private()
|
|
131
|
+
.withParams({
|
|
132
|
+
scopeId,
|
|
133
|
+
amount: number(),
|
|
134
|
+
reason: string(),
|
|
135
|
+
model: string().optional(),
|
|
136
|
+
metadata: string().optional(),
|
|
137
|
+
})
|
|
138
|
+
.handle(
|
|
139
|
+
ONLY_SERVER &&
|
|
140
|
+
(async (ctx, params) => {
|
|
141
|
+
const entryId = ledgerId.generate();
|
|
142
|
+
await ctx.debited.emit({
|
|
143
|
+
ledgerId: entryId,
|
|
144
|
+
scopeId: params.scopeId,
|
|
145
|
+
amount: params.amount,
|
|
146
|
+
reason: params.reason,
|
|
147
|
+
model: params.model,
|
|
148
|
+
metadata: params.metadata,
|
|
149
|
+
});
|
|
150
|
+
return { ok: true };
|
|
151
|
+
}),
|
|
152
|
+
),
|
|
147
153
|
)
|
|
148
154
|
|
|
149
|
-
// ─── checkBalance — query current balance
|
|
155
|
+
// ─── checkBalance — query current scope's balance ───────────
|
|
150
156
|
.clientQuery(
|
|
151
157
|
"checkBalance",
|
|
152
158
|
(fn) => fn
|
|
153
|
-
.
|
|
154
|
-
|
|
155
|
-
|
|
159
|
+
.protectedBy(protectBy, (p: any) => ({
|
|
160
|
+
scopeId: p.workspaceId ?? p.accountId,
|
|
161
|
+
}))
|
|
162
|
+
.handle(async (ctx) => {
|
|
163
|
+
// Scope filter (z protectedBy) jest aplikowany automatycznie do
|
|
164
|
+
// ctx.$query — findOne({}) zwraca tylko wiersz aktualnego scope'u.
|
|
165
|
+
const entry = await ctx.$query.findOne({});
|
|
156
166
|
const balance = entry?.balance ?? 0;
|
|
157
167
|
return {
|
|
158
168
|
balance,
|
|
@@ -161,9 +171,7 @@ export function creditLedger(config: {
|
|
|
161
171
|
totalDebited: entry?.totalDebited ?? 0,
|
|
162
172
|
};
|
|
163
173
|
}),
|
|
164
|
-
)
|
|
165
|
-
|
|
166
|
-
.protectBy(protectBy, (p: any) => ({ scopeId: p.workspaceId ?? p.accountId }));
|
|
174
|
+
);
|
|
167
175
|
|
|
168
176
|
const elements = [Ledger];
|
|
169
177
|
|
package/src/tool/tool.ts
CHANGED
|
@@ -122,14 +122,14 @@ export class ArcTool<
|
|
|
122
122
|
Data["handler"] extends Function
|
|
123
123
|
? ServerToolViewProps<
|
|
124
124
|
Data["params"] extends ArcObjectAny ? $type<Data["params"]> : {},
|
|
125
|
-
Data
|
|
126
|
-
? $type<
|
|
125
|
+
Data extends { result: infer R extends ArcObjectAny }
|
|
126
|
+
? $type<R>
|
|
127
127
|
: unknown
|
|
128
128
|
>
|
|
129
129
|
: InteractiveToolViewProps<
|
|
130
130
|
Data["params"] extends ArcObjectAny ? $type<Data["params"]> : {},
|
|
131
|
-
Data
|
|
132
|
-
? $type<
|
|
131
|
+
Data extends { result: infer R extends ArcObjectAny }
|
|
132
|
+
? $type<R>
|
|
133
133
|
: unknown
|
|
134
134
|
>
|
|
135
135
|
>,
|
package/src/types.ts
CHANGED
|
@@ -119,6 +119,12 @@ export interface CompletionRequest {
|
|
|
119
119
|
webSearch?: boolean;
|
|
120
120
|
temperature?: number;
|
|
121
121
|
maxTokens?: number;
|
|
122
|
+
/**
|
|
123
|
+
* Reasoning effort dla modeli z reasoning (gpt-5, o-series). "minimal"
|
|
124
|
+
* pomija reasoning step → szybki time-to-first-token. Domyślnie provider
|
|
125
|
+
* wybiera (gpt-5 = medium). Adaptery bez wsparcia ignorują pole.
|
|
126
|
+
*/
|
|
127
|
+
reasoningEffort?: "minimal" | "low" | "medium" | "high";
|
|
122
128
|
}
|
|
123
129
|
|
|
124
130
|
export interface CompletionResult {
|
|
@@ -140,22 +146,34 @@ export interface CompletionResult {
|
|
|
140
146
|
|
|
141
147
|
// ─── Streaming ───────────────────────────────────────────────────
|
|
142
148
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
/**
|
|
150
|
+
* Provider emit'uje cztery fazy tool calla:
|
|
151
|
+
* started → arguments_delta(*) → arguments_complete → (server-side execute)
|
|
152
|
+
*
|
|
153
|
+
* "started" daje klientowi `name` od razu (gdy provider go zna), żeby UI
|
|
154
|
+
* mogło pokazać "Przygotowuję: {name}..." przed completion args.
|
|
155
|
+
*/
|
|
156
|
+
export type StreamChunkType =
|
|
157
|
+
| "text_delta"
|
|
158
|
+
| "tool_call_started"
|
|
159
|
+
| "tool_call_arguments_delta"
|
|
160
|
+
| "tool_call_arguments_complete"
|
|
161
|
+
| "usage_update";
|
|
151
162
|
|
|
152
163
|
export interface StreamChunk {
|
|
153
|
-
type:
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
164
|
+
type: StreamChunkType;
|
|
165
|
+
/** text_delta */
|
|
166
|
+
textDelta?: string;
|
|
167
|
+
/** tool_call_* — stable id z provider'a (np. OpenAI call_id). */
|
|
168
|
+
toolCallId?: string;
|
|
169
|
+
/** tool_call_started — nazwa funkcji, jeśli provider ją zna od razu. */
|
|
170
|
+
toolCallName?: string;
|
|
171
|
+
/** tool_call_arguments_delta — surowy fragment JSON arguments. */
|
|
172
|
+
argumentsDelta?: string;
|
|
173
|
+
/** tool_call_arguments_complete — sparsed pełne arguments. */
|
|
174
|
+
arguments?: Record<string, unknown>;
|
|
175
|
+
/** usage_update */
|
|
157
176
|
usage?: TokenUsage;
|
|
158
|
-
finishReason?: FinishReason;
|
|
159
177
|
}
|
|
160
178
|
|
|
161
179
|
// ─── LLM Provider ────────────────────────────────────────────────
|
|
@@ -181,10 +199,19 @@ export interface LLMProvider {
|
|
|
181
199
|
|
|
182
200
|
// ─── Chat Stream (SSE events for chat streaming) ────────────────
|
|
183
201
|
|
|
202
|
+
/**
|
|
203
|
+
* SSE event types pomiędzy listenerem (serwer) a `chat-component.tsx` (klient).
|
|
204
|
+
*
|
|
205
|
+
* Każdy event niesie monotonicznie rosnące `seq` per session — klient trzyma
|
|
206
|
+
* `lastSeq` i odrzuca eventy które już zaaplikował (deduplication przy
|
|
207
|
+
* replay buffer / SSE reconnect).
|
|
208
|
+
*/
|
|
184
209
|
export type ChatStreamEventType =
|
|
185
|
-
| "
|
|
186
|
-
| "
|
|
187
|
-
| "
|
|
210
|
+
| "text_delta"
|
|
211
|
+
| "tool_call_pending"
|
|
212
|
+
| "tool_call_arguments_delta"
|
|
213
|
+
| "tool_call_arguments_complete"
|
|
214
|
+
| "tool_call_executed"
|
|
188
215
|
| "interactive_tool_request"
|
|
189
216
|
| "usage_update"
|
|
190
217
|
| "done"
|
|
@@ -193,13 +220,36 @@ export type ChatStreamEventType =
|
|
|
193
220
|
export interface ChatStreamEvent {
|
|
194
221
|
type: ChatStreamEventType;
|
|
195
222
|
sessionId: string;
|
|
196
|
-
|
|
197
|
-
|
|
223
|
+
/** Monotonicznie rosnący per session — klient dedupuje. */
|
|
224
|
+
seq: number;
|
|
225
|
+
/** ID wiadomości asystenta do której event się odnosi. */
|
|
226
|
+
messageId?: string;
|
|
227
|
+
|
|
228
|
+
/** text_delta */
|
|
229
|
+
textDelta?: string;
|
|
230
|
+
|
|
231
|
+
/** tool_call_pending / tool_call_arguments_delta / tool_call_arguments_complete / tool_call_executed */
|
|
232
|
+
toolCallId?: string;
|
|
233
|
+
toolCallName?: string;
|
|
234
|
+
argumentsDelta?: string;
|
|
235
|
+
arguments?: Record<string, unknown>;
|
|
236
|
+
|
|
237
|
+
/** tool_call_executed */
|
|
198
238
|
toolResult?: ToolResult;
|
|
239
|
+
executionCount?: number;
|
|
240
|
+
|
|
241
|
+
/** interactive_tool_request — multi tools awaiting user input */
|
|
199
242
|
toolCalls?: ToolCall[];
|
|
243
|
+
|
|
244
|
+
/** usage_update */
|
|
200
245
|
usage?: TokenUsage;
|
|
246
|
+
|
|
247
|
+
/** done */
|
|
201
248
|
finishReason?: FinishReason;
|
|
202
|
-
|
|
249
|
+
/** done — total liczba seq w tej sesji (klient może sanity-checkować). */
|
|
250
|
+
lastSeq?: number;
|
|
251
|
+
|
|
252
|
+
/** error */
|
|
203
253
|
error?: string;
|
|
204
254
|
}
|
|
205
255
|
|