@codehz/ai 0.1.3 → 0.1.4

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.
@@ -207,19 +207,22 @@ function rollbackTrailingAssistantMessages(messages: OllamaMessage[]): void {
207
207
  }
208
208
 
209
209
  function isOllamaToolCalls(value: unknown): value is OllamaToolCall[] {
210
- return Array.isArray(value) && value.every((entry) => {
211
- if (!entry || typeof entry !== "object" || !("function" in entry)) return false;
212
- const fn = (entry as { function?: unknown }).function;
213
- return (
214
- !!fn &&
215
- typeof fn === "object" &&
216
- "name" in fn &&
217
- typeof (fn as { name?: unknown }).name === "string" &&
218
- "arguments" in fn &&
219
- typeof (fn as { arguments?: unknown }).arguments === "object" &&
220
- (fn as { arguments?: unknown }).arguments !== null
221
- );
222
- });
210
+ return (
211
+ Array.isArray(value) &&
212
+ value.every((entry) => {
213
+ if (!entry || typeof entry !== "object" || !("function" in entry)) return false;
214
+ const fn = (entry as { function?: unknown }).function;
215
+ return (
216
+ !!fn &&
217
+ typeof fn === "object" &&
218
+ "name" in fn &&
219
+ typeof (fn as { name?: unknown }).name === "string" &&
220
+ "arguments" in fn &&
221
+ typeof (fn as { arguments?: unknown }).arguments === "object" &&
222
+ (fn as { arguments?: unknown }).arguments !== null
223
+ );
224
+ })
225
+ );
223
226
  }
224
227
 
225
228
  // ── Adapter ───────────────────────────────────────────────────
@@ -264,7 +267,10 @@ export class OllamaAdapter extends AdapterBase {
264
267
  : item.role === "user"
265
268
  ? "user"
266
269
  : "assistant";
267
- messages.push({ role, content: contentBlocksToText(ensureOllamaTextBlocks(item.content, `input message (${item.role}) content`)) });
270
+ messages.push({
271
+ role,
272
+ content: contentBlocksToText(ensureOllamaTextBlocks(item.content, `input message (${item.role}) content`)),
273
+ });
268
274
  break;
269
275
  }
270
276
  case "tool_call": {
@@ -301,7 +307,12 @@ export class OllamaAdapter extends AdapterBase {
301
307
  }
302
308
  case "opaque": {
303
309
  // Best-effort restore from opaque replay
304
- if (item.source === "ollama" && item.purpose === "replay" && typeof item.payload === "object" && item.payload !== null) {
310
+ if (
311
+ item.source === "ollama" &&
312
+ item.purpose === "replay" &&
313
+ typeof item.payload === "object" &&
314
+ item.payload !== null
315
+ ) {
305
316
  const payload = item.payload as Record<string, unknown>;
306
317
  if (payload.role === "assistant" && typeof payload.content === "string") {
307
318
  rollbackTrailingAssistantMessages(messages);
@@ -477,9 +488,10 @@ export class OllamaAdapter extends AdapterBase {
477
488
  {
478
489
  inputTokens: chunk.prompt_eval_count,
479
490
  outputTokens: chunk.eval_count,
480
- totalTokens: chunk.prompt_eval_count !== undefined && chunk.eval_count !== undefined
481
- ? chunk.prompt_eval_count + chunk.eval_count
482
- : undefined,
491
+ totalTokens:
492
+ chunk.prompt_eval_count !== undefined && chunk.eval_count !== undefined
493
+ ? chunk.prompt_eval_count + chunk.eval_count
494
+ : undefined,
483
495
  },
484
496
  "final",
485
497
  {
@@ -164,9 +164,7 @@ function parseSSE(chunk: string): { events: ResponsesSSEEvent[]; rest: string; m
164
164
 
165
165
  function isReplayCanonicalInput(item: ResponsesInputItem): boolean {
166
166
  return (
167
- (item.type === "message" && item.role === "assistant") ||
168
- item.type === "reasoning" ||
169
- item.type === "function_call"
167
+ (item.type === "message" && item.role === "assistant") || item.type === "reasoning" || item.type === "function_call"
170
168
  );
171
169
  }
172
170
 
@@ -452,9 +450,9 @@ export class ResponsesAdapter extends AdapterBase {
452
450
  if (completedResponse.usage) {
453
451
  auxiliary.recordUsage(
454
452
  {
455
- inputTokens: completedResponse.usage.input_tokens,
456
- outputTokens: completedResponse.usage.output_tokens,
457
- totalTokens: completedResponse.usage.total_tokens,
453
+ inputTokens: completedResponse.usage.input_tokens,
454
+ outputTokens: completedResponse.usage.output_tokens,
455
+ totalTokens: completedResponse.usage.total_tokens,
458
456
  },
459
457
  "final",
460
458
  completedResponse.usage,
@@ -122,10 +122,20 @@ function validateInputItem(item: unknown, field: string, issues: ValidationIssue
122
122
  return;
123
123
  case "tool_result":
124
124
  if (typeof item.callId !== "string" || item.callId.length === 0) {
125
- pushIssue(issues, `${field}.callId`, "TOOL_RESULT_CALL_ID_INVALID", `${field}.callId must be a non-empty string`);
125
+ pushIssue(
126
+ issues,
127
+ `${field}.callId`,
128
+ "TOOL_RESULT_CALL_ID_INVALID",
129
+ `${field}.callId must be a non-empty string`,
130
+ );
126
131
  }
127
132
  if (typeof item.toolName !== "string" || item.toolName.length === 0) {
128
- pushIssue(issues, `${field}.toolName`, "TOOL_RESULT_NAME_INVALID", `${field}.toolName must be a non-empty string`);
133
+ pushIssue(
134
+ issues,
135
+ `${field}.toolName`,
136
+ "TOOL_RESULT_NAME_INVALID",
137
+ `${field}.toolName must be a non-empty string`,
138
+ );
129
139
  }
130
140
  if (typeof item.outcome !== "string" || !TOOL_RESULT_OUTCOMES.has(item.outcome)) {
131
141
  pushIssue(
@@ -180,12 +190,7 @@ function validateTools(tools: unknown, issues: ValidationIssue[]): void {
180
190
  }
181
191
 
182
192
  if (!isRecord(tool.inputSchema)) {
183
- pushIssue(
184
- issues,
185
- `${field}.inputSchema`,
186
- "TOOL_INPUT_SCHEMA_INVALID",
187
- `${field}.inputSchema must be an object`,
188
- );
193
+ pushIssue(issues, `${field}.inputSchema`, "TOOL_INPUT_SCHEMA_INVALID", `${field}.inputSchema must be an object`);
189
194
  }
190
195
  }
191
196
  }
@@ -193,8 +198,13 @@ function validateTools(tools: unknown, issues: ValidationIssue[]): void {
193
198
  function validateToolChoice(toolChoice: unknown, issues: ValidationIssue[]): void {
194
199
  if (toolChoice === undefined) return;
195
200
  if (toolChoice === "auto" || toolChoice === "none") return;
196
- if (!isRecord(toolChoice) || toolChoice.type !== "tool" || typeof toolChoice.name !== "string" || toolChoice.name.length === 0) {
197
- pushIssue(issues, "toolChoice", "TOOL_CHOICE_INVALID", "toolChoice must be auto, none, or { type: \"tool\", name }");
201
+ if (
202
+ !isRecord(toolChoice) ||
203
+ toolChoice.type !== "tool" ||
204
+ typeof toolChoice.name !== "string" ||
205
+ toolChoice.name.length === 0
206
+ ) {
207
+ pushIssue(issues, "toolChoice", "TOOL_CHOICE_INVALID", 'toolChoice must be auto, none, or { type: "tool", name }');
198
208
  }
199
209
  }
200
210
 
@@ -211,12 +221,7 @@ export function validateRequest(request: AIRequest): ValidationIssue[] {
211
221
  } else if (Array.isArray(request.instructions)) {
212
222
  validateContentArray(request.instructions, "instructions", issues, "INSTRUCTIONS_INVALID");
213
223
  } else {
214
- pushIssue(
215
- issues,
216
- "instructions",
217
- "INSTRUCTIONS_INVALID",
218
- "instructions must be a string or ContentBlock[]",
219
- );
224
+ pushIssue(issues, "instructions", "INSTRUCTIONS_INVALID", "instructions must be a string or ContentBlock[]");
220
225
  }
221
226
  }
222
227
 
@@ -99,7 +99,9 @@ export class AdapterAuxiliaryState {
99
99
  }
100
100
 
101
101
  if (this.request.include?.usage !== "off" && !built.usage) {
102
- events.push(factory.responseWarning("Usage information was not provided by the provider", WarningCode.USAGE_MISSING));
102
+ events.push(
103
+ factory.responseWarning("Usage information was not provided by the provider", WarningCode.USAGE_MISSING),
104
+ );
103
105
  }
104
106
 
105
107
  if (this.request.include?.billing !== "off") {
@@ -112,7 +112,10 @@ export abstract class AdapterBase implements BackendAdapter {
112
112
  protected buildResponse(request: NormalizedRequest, result: StreamResult, _factory: EventFactory): AIResponse {
113
113
  const text = this.extractText(result.output);
114
114
  const warnings = mergeWarnings(result.warnings, _factory.warnings);
115
- const auxiliary = mergeAuxiliary(result.auxiliary, result.providerMetadata ? { providerMetadata: result.providerMetadata } : undefined);
115
+ const auxiliary = mergeAuxiliary(
116
+ result.auxiliary,
117
+ result.providerMetadata ? { providerMetadata: result.providerMetadata } : undefined,
118
+ );
116
119
 
117
120
  return {
118
121
  id: request.requestId,
@@ -146,10 +149,7 @@ export abstract class AdapterBase implements BackendAdapter {
146
149
  }
147
150
  }
148
151
 
149
- function mergeAuxiliary(
150
- base?: Partial<AuxiliaryInfo>,
151
- patch?: Partial<AuxiliaryInfo>,
152
- ): AuxiliaryInfo | undefined {
152
+ function mergeAuxiliary(base?: Partial<AuxiliaryInfo>, patch?: Partial<AuxiliaryInfo>): AuxiliaryInfo | undefined {
153
153
  if (!base && !patch) return undefined;
154
154
 
155
155
  const merged: AuxiliaryInfo = {
@@ -28,11 +28,7 @@ export type { SSEEvent } from "./sse-parser.js";
28
28
 
29
29
  export { AdapterBase } from "./adapter-base.js";
30
30
  export type { StreamResult } from "./adapter-base.js";
31
- export {
32
- AdapterAuxiliaryState,
33
- emitMalformedStreamWarning,
34
- metadataSourceList,
35
- } from "./adapter-auxiliary.js";
31
+ export { AdapterAuxiliaryState, emitMalformedStreamWarning, metadataSourceList } from "./adapter-auxiliary.js";
36
32
  export type { AuxiliaryFinalizeOptions, AuxiliaryFinalizeResult, BillingPostprocessHook } from "./adapter-auxiliary.js";
37
33
  export { syntheticStream } from "./synthetic-stream.js";
38
34
  export type { SyntheticStreamOptions } from "./synthetic-stream.js";
@@ -46,10 +46,4 @@ export type {
46
46
  } from "./events.js";
47
47
 
48
48
  // Adapter 协议和 client 类型
49
- export type {
50
- BackendAdapter,
51
- FetchFn,
52
- NormalizedRequest,
53
- CreateAIClientOptions,
54
- AIClient,
55
- } from "./adapter.js";
49
+ export type { BackendAdapter, FetchFn, NormalizedRequest, CreateAIClientOptions, AIClient } from "./adapter.js";