@acosmi/sdk-ts 2.19.0 → 2.19.2
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/CHANGELOG.md +16 -0
- package/README.md +2 -1
- package/dist/browser/index.mjs +1205 -160
- package/dist/browser/index.mjs.map +1 -1
- package/dist/index.mjs +1205 -160
- package/dist/index.mjs.map +1 -1
- package/dist/node/adapters/anthropic.cjs +2 -0
- package/dist/node/adapters/anthropic.cjs.map +1 -1
- package/dist/node/adapters/anthropic.d.cts +1 -1
- package/dist/node/adapters/anthropic.d.ts +1 -1
- package/dist/node/adapters/anthropic.mjs +2 -0
- package/dist/node/adapters/anthropic.mjs.map +1 -1
- package/dist/node/adapters/openai.cjs +122 -49
- package/dist/node/adapters/openai.cjs.map +1 -1
- package/dist/node/adapters/openai.d.cts +2 -2
- package/dist/node/adapters/openai.d.ts +2 -2
- package/dist/node/adapters/openai.mjs +122 -49
- package/dist/node/adapters/openai.mjs.map +1 -1
- package/dist/node/{index-C2oh157O.d.cts → index-CqxPqbsl.d.cts} +2 -1
- package/dist/node/{index-C2oh157O.d.ts → index-CqxPqbsl.d.ts} +2 -1
- package/dist/node/index.cjs +1206 -159
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.cts +346 -151
- package/dist/node/index.d.ts +346 -151
- package/dist/node/index.mjs +1205 -160
- package/dist/node/index.mjs.map +1 -1
- package/dist/node/{openai-DR_KhEdM.d.cts → openai-Ce85qh14.d.cts} +30 -3
- package/dist/node/{openai-Cyvi8g6B.d.ts → openai-mkTSir6E.d.ts} +30 -3
- package/package.json +1 -1
|
@@ -46,10 +46,13 @@ var OpenAIAdapter = class {
|
|
|
46
46
|
if (req.tools != null) {
|
|
47
47
|
body["tools"] = req.tools;
|
|
48
48
|
}
|
|
49
|
-
const eff = resolveOpenAIReasoningEffort(req);
|
|
49
|
+
const eff = resolveOpenAIReasoningEffort(req, _caps.supports_max_effort);
|
|
50
50
|
if (eff !== "") {
|
|
51
51
|
body["reasoning_effort"] = eff;
|
|
52
52
|
}
|
|
53
|
+
if (_caps.supports_thinking && req.thinking?.level === ThinkingOff) {
|
|
54
|
+
body["thinking"] = { type: "disabled" };
|
|
55
|
+
}
|
|
53
56
|
if (req.speed && req.speed !== "") {
|
|
54
57
|
body["speed"] = req.speed;
|
|
55
58
|
}
|
|
@@ -118,23 +121,28 @@ var OpenAIAdapter = class {
|
|
|
118
121
|
return { event: { event: eventType, data }, done: false };
|
|
119
122
|
}
|
|
120
123
|
};
|
|
121
|
-
function resolveOpenAIReasoningEffort(req) {
|
|
124
|
+
function resolveOpenAIReasoningEffort(req, supportsMax = false) {
|
|
122
125
|
if (req.effort && req.effort.level !== "") {
|
|
123
126
|
switch (req.effort.level) {
|
|
124
127
|
case "low":
|
|
125
128
|
case "medium":
|
|
126
129
|
case "high":
|
|
130
|
+
case "xhigh":
|
|
127
131
|
return req.effort.level;
|
|
128
132
|
case "max":
|
|
129
|
-
return "high";
|
|
133
|
+
return supportsMax ? "max" : "high";
|
|
130
134
|
}
|
|
131
135
|
}
|
|
132
136
|
if (req.thinking) {
|
|
133
137
|
switch (req.thinking.level) {
|
|
138
|
+
case "low":
|
|
139
|
+
case "medium":
|
|
140
|
+
case "xhigh":
|
|
141
|
+
return req.thinking.level;
|
|
134
142
|
case ThinkingHigh:
|
|
135
143
|
return "high";
|
|
136
144
|
case ThinkingMax:
|
|
137
|
-
return "high";
|
|
145
|
+
return supportsMax ? "max" : "high";
|
|
138
146
|
case ThinkingOff:
|
|
139
147
|
return "";
|
|
140
148
|
}
|
|
@@ -306,16 +314,90 @@ var OpenAIStreamConverter = class {
|
|
|
306
314
|
* 可能已被 text/tool 推进的 this.blockIndex (否则 content_block_stop 索引错配)。 */
|
|
307
315
|
thinkingBlockIndex = 0;
|
|
308
316
|
textStarted = false;
|
|
309
|
-
/** OpenAI tool_call
|
|
317
|
+
/** OpenAI tool_call 键 → Anthropic block index。键正常是 `tc.index`;上游省略
|
|
318
|
+
* index 时退化为 `id:<tool_call_id>`,两者都没有时沿用上一个键(见
|
|
319
|
+
* {@link resolveToolKey})。 */
|
|
310
320
|
toolBlockIndex = /* @__PURE__ */ new Map();
|
|
311
321
|
blockIndex = 0;
|
|
322
|
+
/** 每个 tool block 已发出的 `partial_json` 累积,用于识别「每片重发全量参数」
|
|
323
|
+
* 的上游(见 tool_calls 分支的累计判别)。 */
|
|
324
|
+
toolArgsAccum = /* @__PURE__ */ new Map();
|
|
325
|
+
/** 上一次解析出的 tool 键,供缺 index 且缺 id 的后续增量沿用。 */
|
|
326
|
+
lastToolKey = null;
|
|
327
|
+
/** 已发出 message_delta/message_stop,避免 finish_reason 与 `[DONE]` 各收一次。 */
|
|
328
|
+
messageClosed = false;
|
|
329
|
+
/**
|
|
330
|
+
* 解析一条 tool_call delta 归属的块键。
|
|
331
|
+
*
|
|
332
|
+
* OpenAI 流式规范里 `index` 是必填,但兼容实现常有省略。此前这里直接用
|
|
333
|
+
* `tc.index` 做 Map 键:两个都省略 index 的 tool_call 会共用键 `undefined`,
|
|
334
|
+
* 于是只开一个块、两段参数拼进同一条 `partial_json` 流,产出 `{…}{…}` 这种
|
|
335
|
+
* 必然非法的 JSON。这里按「index → id → 沿用上一个」三级降级,让至少一种
|
|
336
|
+
* 稳定标识生效。
|
|
337
|
+
*/
|
|
338
|
+
resolveToolKey(tc) {
|
|
339
|
+
if (typeof tc.index === "number" && Number.isFinite(tc.index)) {
|
|
340
|
+
this.lastToolKey = tc.index;
|
|
341
|
+
return tc.index;
|
|
342
|
+
}
|
|
343
|
+
if (typeof tc.id === "string" && tc.id !== "") {
|
|
344
|
+
const key = `id:${tc.id}`;
|
|
345
|
+
this.lastToolKey = key;
|
|
346
|
+
return key;
|
|
347
|
+
}
|
|
348
|
+
if (this.lastToolKey !== null) return this.lastToolKey;
|
|
349
|
+
this.lastToolKey = 0;
|
|
350
|
+
return 0;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* 关闭仍打开的 text / thinking / tool 块,并收口 message。
|
|
354
|
+
*
|
|
355
|
+
* 由 `finish_reason` 分支与 `[DONE]` 分支共用:上游断流或只发 `[DONE]` 而不发
|
|
356
|
+
* `finish_reason` 时,此前一个 `content_block_stop` 都不会发,下游拿到的是一个
|
|
357
|
+
* 永不闭合的 tool_use 块。
|
|
358
|
+
*/
|
|
359
|
+
closeOpenBlocks(events, stopReason) {
|
|
360
|
+
if (this.messageClosed) return;
|
|
361
|
+
this.messageClosed = true;
|
|
362
|
+
if (this.textStarted) {
|
|
363
|
+
events.push({
|
|
364
|
+
event: "content_block_stop",
|
|
365
|
+
data: JSON.stringify({ type: "content_block_stop", index: this.blockIndex })
|
|
366
|
+
});
|
|
367
|
+
this.textStarted = false;
|
|
368
|
+
} else if (this.thinkingStarted && !this.thinkingStopped) {
|
|
369
|
+
this.thinkingStopped = true;
|
|
370
|
+
events.push({
|
|
371
|
+
event: "content_block_stop",
|
|
372
|
+
data: JSON.stringify({ type: "content_block_stop", index: this.thinkingBlockIndex })
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
for (const idx of this.toolBlockIndex.values()) {
|
|
376
|
+
events.push({
|
|
377
|
+
event: "content_block_stop",
|
|
378
|
+
data: JSON.stringify({ type: "content_block_stop", index: idx })
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
events.push({
|
|
382
|
+
event: "message_delta",
|
|
383
|
+
data: JSON.stringify({ type: "message_delta", delta: { stop_reason: stopReason } })
|
|
384
|
+
});
|
|
385
|
+
events.push({
|
|
386
|
+
event: "message_stop",
|
|
387
|
+
data: JSON.stringify({ type: "message_stop" })
|
|
388
|
+
});
|
|
389
|
+
}
|
|
312
390
|
/**
|
|
313
391
|
* 将一行 OpenAI SSE data 转换为零或多个 Anthropic 格式 StreamEvent
|
|
314
392
|
* 返回 { events, done }
|
|
315
393
|
*/
|
|
316
394
|
convert(data) {
|
|
317
395
|
if (data === "[DONE]") {
|
|
318
|
-
|
|
396
|
+
const events2 = [];
|
|
397
|
+
if (this.messageStarted) {
|
|
398
|
+
this.closeOpenBlocks(events2, "end_turn");
|
|
399
|
+
}
|
|
400
|
+
return { events: events2, done: true };
|
|
319
401
|
}
|
|
320
402
|
let chunk;
|
|
321
403
|
try {
|
|
@@ -387,7 +469,9 @@ var OpenAIStreamConverter = class {
|
|
|
387
469
|
events.push({ event: "content_block_delta", data: deltaJSON });
|
|
388
470
|
}
|
|
389
471
|
for (const tc of choice.delta.tool_calls ?? []) {
|
|
390
|
-
|
|
472
|
+
const fn = tc.function;
|
|
473
|
+
const toolKey = this.resolveToolKey(tc);
|
|
474
|
+
if (!this.toolBlockIndex.has(toolKey)) {
|
|
391
475
|
if (this.thinkingStarted && !this.thinkingStopped) {
|
|
392
476
|
this.thinkingStopped = true;
|
|
393
477
|
const stopJSON = JSON.stringify({
|
|
@@ -406,56 +490,46 @@ var OpenAIStreamConverter = class {
|
|
|
406
490
|
this.blockIndex++;
|
|
407
491
|
this.textStarted = false;
|
|
408
492
|
}
|
|
409
|
-
this.toolBlockIndex.set(
|
|
493
|
+
this.toolBlockIndex.set(toolKey, this.blockIndex);
|
|
410
494
|
const blockJSON = JSON.stringify({
|
|
411
495
|
type: "content_block_start",
|
|
412
496
|
index: this.blockIndex,
|
|
413
497
|
content_block: {
|
|
414
498
|
type: "tool_use",
|
|
415
499
|
id: tc.id,
|
|
416
|
-
name:
|
|
500
|
+
name: fn?.name,
|
|
417
501
|
input: {}
|
|
418
502
|
}
|
|
419
503
|
});
|
|
420
504
|
events.push({ event: "content_block_start", data: blockJSON });
|
|
421
505
|
this.blockIndex++;
|
|
422
506
|
}
|
|
423
|
-
if (
|
|
424
|
-
const
|
|
425
|
-
const
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
}
|
|
433
|
-
|
|
507
|
+
if (fn?.arguments !== void 0 && fn.arguments !== null && fn.arguments !== "") {
|
|
508
|
+
const rawArgs = typeof fn.arguments === "string" ? fn.arguments : JSON.stringify(fn.arguments);
|
|
509
|
+
const accum = this.toolArgsAccum.get(toolKey) ?? "";
|
|
510
|
+
let emit = rawArgs;
|
|
511
|
+
if (accum !== "" && rawArgs.length > accum.length && rawArgs.startsWith(accum)) {
|
|
512
|
+
emit = rawArgs.slice(accum.length);
|
|
513
|
+
this.toolArgsAccum.set(toolKey, rawArgs);
|
|
514
|
+
} else {
|
|
515
|
+
this.toolArgsAccum.set(toolKey, accum + rawArgs);
|
|
516
|
+
}
|
|
517
|
+
if (emit !== "") {
|
|
518
|
+
const idx = this.toolBlockIndex.get(toolKey);
|
|
519
|
+
const deltaJSON = JSON.stringify({
|
|
520
|
+
type: "content_block_delta",
|
|
521
|
+
index: idx,
|
|
522
|
+
delta: {
|
|
523
|
+
type: "input_json_delta",
|
|
524
|
+
partial_json: emit
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
events.push({ event: "content_block_delta", data: deltaJSON });
|
|
528
|
+
}
|
|
434
529
|
}
|
|
435
530
|
}
|
|
436
531
|
if (choice.finish_reason != null && choice.finish_reason !== "") {
|
|
437
|
-
|
|
438
|
-
const stopJSON2 = JSON.stringify({
|
|
439
|
-
type: "content_block_stop",
|
|
440
|
-
index: this.blockIndex
|
|
441
|
-
});
|
|
442
|
-
events.push({ event: "content_block_stop", data: stopJSON2 });
|
|
443
|
-
} else if (this.thinkingStarted && !this.thinkingStopped) {
|
|
444
|
-
this.thinkingStopped = true;
|
|
445
|
-
const stopJSON2 = JSON.stringify({
|
|
446
|
-
type: "content_block_stop",
|
|
447
|
-
index: this.thinkingBlockIndex
|
|
448
|
-
});
|
|
449
|
-
events.push({ event: "content_block_stop", data: stopJSON2 });
|
|
450
|
-
}
|
|
451
|
-
for (const idx of this.toolBlockIndex.values()) {
|
|
452
|
-
const stopJSON2 = JSON.stringify({
|
|
453
|
-
type: "content_block_stop",
|
|
454
|
-
index: idx
|
|
455
|
-
});
|
|
456
|
-
events.push({ event: "content_block_stop", data: stopJSON2 });
|
|
457
|
-
}
|
|
458
|
-
let stopReason = "end_turn";
|
|
532
|
+
let stopReason;
|
|
459
533
|
switch (choice.finish_reason) {
|
|
460
534
|
case "tool_calls":
|
|
461
535
|
stopReason = "tool_use";
|
|
@@ -463,14 +537,13 @@ var OpenAIStreamConverter = class {
|
|
|
463
537
|
case "length":
|
|
464
538
|
stopReason = "max_tokens";
|
|
465
539
|
break;
|
|
540
|
+
case "stop":
|
|
541
|
+
stopReason = "end_turn";
|
|
542
|
+
break;
|
|
543
|
+
default:
|
|
544
|
+
stopReason = choice.finish_reason;
|
|
466
545
|
}
|
|
467
|
-
|
|
468
|
-
type: "message_delta",
|
|
469
|
-
delta: { stop_reason: stopReason }
|
|
470
|
-
});
|
|
471
|
-
events.push({ event: "message_delta", data: deltaJSON });
|
|
472
|
-
const stopJSON = JSON.stringify({ type: "message_stop" });
|
|
473
|
-
events.push({ event: "message_stop", data: stopJSON });
|
|
546
|
+
this.closeOpenBlocks(events, stopReason);
|
|
474
547
|
}
|
|
475
548
|
return { events, done: false };
|
|
476
549
|
}
|