@ykurilov/agent-chat-core 0.70.0 → 0.71.0
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 +12 -0
- package/dist/{chunk-EW3572B5.js → chunk-YMUK7P4S.js} +57 -18
- package/dist/chunk-YMUK7P4S.js.map +1 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/storage-contract.js +1 -1
- package/dist/types/conversation/answer-reasoning.d.ts +6 -0
- package/dist/types/conversation/types.d.ts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/models/model-catalog.d.ts +5 -0
- package/dist/types/models/model-choice.d.ts +7 -0
- package/package.json +1 -1
- package/dist/chunk-EW3572B5.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @ykurilov/agent-chat-core
|
|
2
2
|
|
|
3
|
+
## 0.71.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 8b8c651: Три вида поля Одуванчик: сжатое, обычное и расширенное. Настройки модели/провайдера/рассуждений из каталога, цена и метки, инструменты приложения, шторка телефона. Сфера и токены из опубликованных ds-react/ds-tokens. Необязательный договор скина v29, сохранение уровня ответа для подписи в истории.
|
|
8
|
+
|
|
9
|
+
## 0.70.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- ba86a4a: Стандартный DeepSeek 4.1 Flash обновлён до 1017 у OpenRouter, Together и Fireworks. У OpenRouter обновлены цены и расписание пикового тарифа; id профиля сохранён.
|
|
14
|
+
|
|
3
15
|
## 0.70.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
|
@@ -5625,6 +5625,22 @@ function parseNestedJson(text, schema, tally) {
|
|
|
5625
5625
|
return coerceBySchema(parsed.value, schema, tally);
|
|
5626
5626
|
}
|
|
5627
5627
|
|
|
5628
|
+
// src/conversation/answer-reasoning.ts
|
|
5629
|
+
var ANSWER_REASONING_PART = "data-answer-reasoning";
|
|
5630
|
+
function answerReasoningOf(parts) {
|
|
5631
|
+
const part = parts.find((item) => item.type === ANSWER_REASONING_PART);
|
|
5632
|
+
if (!part || !("data" in part) || typeof part.data !== "object" || part.data === null) return void 0;
|
|
5633
|
+
const level = part.data.level;
|
|
5634
|
+
return typeof level === "string" ? level : void 0;
|
|
5635
|
+
}
|
|
5636
|
+
function withoutAnswerReasoning(parts) {
|
|
5637
|
+
return parts.some((part) => part.type === ANSWER_REASONING_PART) ? parts.filter((part) => part.type !== ANSWER_REASONING_PART) : parts;
|
|
5638
|
+
}
|
|
5639
|
+
function withAnswerReasoning(parts, level) {
|
|
5640
|
+
if (level === void 0) return parts;
|
|
5641
|
+
return [...withoutAnswerReasoning(parts), { type: ANSWER_REASONING_PART, data: { level } }];
|
|
5642
|
+
}
|
|
5643
|
+
|
|
5628
5644
|
// src/agent-run/run-agent-turn.ts
|
|
5629
5645
|
import { stepCountIs, streamText } from "ai";
|
|
5630
5646
|
|
|
@@ -7209,7 +7225,7 @@ async function runTurn(turnInput, emitRaw) {
|
|
|
7209
7225
|
providerId = fallbackProviderIds[0];
|
|
7210
7226
|
logError(`[\u0437\u0430\u043F\u0430\u0441\u043D\u043E\u0439 \u043F\u0440\u043E\u0432\u0430\u0439\u0434\u0435\u0440] \u0447\u0430\u0442=${input.chatId} \u043C\u043E\u0434\u0435\u043B\u044C=${modelId} \u0441=${input.providerId} \u043D\u0430=${providerId} \u043F\u0440\u0438\u0447\u0438\u043D\u0430=${primaryPaused} \u043E\u0441\u043D\u043E\u0432\u043D\u043E\u0439 \u043D\u0430 \u043F\u0430\u0443\u0437\u0435`);
|
|
7211
7227
|
}
|
|
7212
|
-
emit({ type: "start", messageId, messageMetadata: { modelId, providerId: input.providerId } });
|
|
7228
|
+
emit({ type: "start", messageId, messageMetadata: { modelId, providerId: input.providerId, ...input.reasoning !== void 0 && { reasoningLevel: input.reasoning } } });
|
|
7213
7229
|
if (input.liveDemos && chatHasExternalContent(await storage.listMessages(input.chatId)) && externalContent.announce()) emitRaw(externalContentChunk());
|
|
7214
7230
|
const silenceSetting = resolveSilenceSwitch(input.providerFallback);
|
|
7215
7231
|
if (silenceSetting.onSilence === "restart-step-on-next" && silenceSetting.maxSwitches > 0) {
|
|
@@ -7485,7 +7501,7 @@ async function runTurn(turnInput, emitRaw) {
|
|
|
7485
7501
|
}
|
|
7486
7502
|
}
|
|
7487
7503
|
for (const chunk of seam.flush()) emitNow(chunk);
|
|
7488
|
-
if (!started) emit({ type: "start", messageId, messageMetadata: { modelId, providerId: input.providerId } });
|
|
7504
|
+
if (!started) emit({ type: "start", messageId, messageMetadata: { modelId, providerId: input.providerId, ...input.reasoning !== void 0 && { reasoningLevel: input.reasoning } } });
|
|
7489
7505
|
if (input.waitingWidgets && !input.abortSignal.aborted && errors.length === 0) {
|
|
7490
7506
|
for (const toolCallId of extraWidgetCallIds(await saver.snapshot(), input.waitingWidgets)) {
|
|
7491
7507
|
emitNow({ type: "tool-output-error", toolCallId, errorText: ONE_QUESTION_AT_A_TIME });
|
|
@@ -7564,7 +7580,7 @@ async function runTurn(turnInput, emitRaw) {
|
|
|
7564
7580
|
finished = await finishWithRetries(
|
|
7565
7581
|
storage,
|
|
7566
7582
|
messageId,
|
|
7567
|
-
{ status, parts, usage, reasoningDurationsMs, error, ...answeredByBackup, ...input.afterTurn && { afterTurn: "pending" } },
|
|
7583
|
+
{ status, parts: withAnswerReasoning(parts, input.reasoning), usage, reasoningDurationsMs, error, ...answeredByBackup, ...input.afterTurn && { afterTurn: "pending" } },
|
|
7568
7584
|
logError
|
|
7569
7585
|
);
|
|
7570
7586
|
} catch (failure) {
|
|
@@ -7622,7 +7638,7 @@ async function runTurn(turnInput, emitRaw) {
|
|
|
7622
7638
|
if (input.onFinished) runFinishedHook(input, status, answeredProviderId);
|
|
7623
7639
|
emitToClient({
|
|
7624
7640
|
type: "message-metadata",
|
|
7625
|
-
messageMetadata: { status, reasoningDurationsMs, ...titlesMetadata(parts), ...answeredByBackup, ...usage && { usage }, ...error && { error } }
|
|
7641
|
+
messageMetadata: { status, reasoningDurationsMs, ...input.reasoning !== void 0 && { reasoningLevel: input.reasoning }, ...titlesMetadata(parts), ...answeredByBackup, ...usage && { usage }, ...error && { error } }
|
|
7626
7642
|
});
|
|
7627
7643
|
if (status === "error") for (const chunk of errors) emitToClient(chunk);
|
|
7628
7644
|
if (terminal.length === 0) terminal.push(status === "stopped" ? { type: "abort" } : { type: "finish" });
|
|
@@ -7721,7 +7737,7 @@ function readAnswerAttempt(input, attempt, opened, classify) {
|
|
|
7721
7737
|
// Только id сообщения: SDK дописывает куски в ответ с этим id.
|
|
7722
7738
|
...originalMessage && { originalMessages: [originalMessage] },
|
|
7723
7739
|
sendReasoning: true,
|
|
7724
|
-
messageMetadata: ({ part }) => part.type === "start" ? { modelId: input.modelId, providerId: found.provider.id } : void 0,
|
|
7740
|
+
messageMetadata: ({ part }) => part.type === "start" ? { modelId: input.modelId, providerId: found.provider.id, ...input.reasoning !== void 0 && { reasoningLevel: input.reasoning } } : void 0,
|
|
7725
7741
|
onError
|
|
7726
7742
|
}).pipeThrough(
|
|
7727
7743
|
new TransformStream({
|
|
@@ -9446,10 +9462,10 @@ var deepseek41FlashProfile = {
|
|
|
9446
9462
|
displayName: "DeepSeek 4.1 Flash",
|
|
9447
9463
|
contextWindowTokens: 1e6,
|
|
9448
9464
|
acceptsImages: true,
|
|
9449
|
-
//
|
|
9450
|
-
//
|
|
9451
|
-
//
|
|
9452
|
-
//
|
|
9465
|
+
// 1017: картинка в результате инструмента проверена у DeepSeek, OpenRouter и Fireworks 2026-10-22.
|
|
9466
|
+
// Together: новый id в каталоге; живой вызов вернул 402, отметка сохранена по замеру предыдущей версии.
|
|
9467
|
+
// Запрет хозяев ниже сохранён по ранним замерам (specs/research-openrouter-tool-images.md);
|
|
9468
|
+
// проверка обычного маршрута 1017 не заменяет отдельного замера каждого хозяина.
|
|
9453
9469
|
toolResultImageProviders: ["deepseek", "together", "fireworks", "openrouter"],
|
|
9454
9470
|
reasoning: { replayPastTurns: true, levels: ["off", "on"], defaultLevel: "on" },
|
|
9455
9471
|
// Запрет стоит всегда, а не только при картинке: запрос одинаков в каждом ходе, кэш и выбранный хозяин не теряются.
|
|
@@ -9460,13 +9476,14 @@ var deepseek41FlashProfile = {
|
|
|
9460
9476
|
// прогон 35 учеников «Мастера понятий» — каши 0 из 1036 ответов (было 2 случая). Уходит к Together и OpenRouter;
|
|
9461
9477
|
// DeepSeek напрямую обрезки не принимает.
|
|
9462
9478
|
sampling: { minP: 0.05 },
|
|
9479
|
+
// 1017: прямой DeepSeek обновляет alias сам; остальные провайдеры используют датированный id.
|
|
9463
9480
|
providerModelIds: {
|
|
9464
9481
|
deepseek: "deepseek-flash",
|
|
9465
|
-
fireworks: "accounts/fireworks/models/deepseek-v4p1-flash",
|
|
9466
|
-
together: "deepseek-ai/DeepSeek-V4.1-Flash",
|
|
9467
|
-
openrouter: "deepseek/deepseek-v4.1-flash"
|
|
9482
|
+
fireworks: "accounts/fireworks/models/deepseek-v4p1-flash-1017",
|
|
9483
|
+
together: "deepseek-ai/DeepSeek-V4.1-Flash-1017",
|
|
9484
|
+
openrouter: "deepseek/deepseek-v4.1-flash-1017"
|
|
9468
9485
|
},
|
|
9469
|
-
//
|
|
9486
|
+
// Цены за миллион токенов: каталоги провайдеров 2026-10-22.
|
|
9470
9487
|
pricing: {
|
|
9471
9488
|
// DeepSeek: цена вне пика, в часы пик (будни 01–04 и 06–10 UTC, api-docs.deepseek.com, проверено 2026-10-05) всё
|
|
9472
9489
|
// вдвое, включая попадания в кэш. Праздники Китая (тоже вне пика) не заданы: расход в них чуть завышается.
|
|
@@ -9485,9 +9502,23 @@ var deepseek41FlashProfile = {
|
|
|
9485
9502
|
},
|
|
9486
9503
|
fireworks: { inputPerMillion: 0.3, outputPerMillion: 1.2, cachedInputPerMillion: 6e-3 },
|
|
9487
9504
|
together: { inputPerMillion: 0.3, outputPerMillion: 1.2, cachedInputPerMillion: 6e-3 },
|
|
9488
|
-
// Платной записи в кэш у хозяев OpenRouter нет (ни `input_cache_write`, ни `input_cache_write_1h`, 2026-10-
|
|
9505
|
+
// Платной записи в кэш у хозяев OpenRouter нет (ни `input_cache_write`, ни `input_cache_write_1h`, 2026-10-22): кэш
|
|
9489
9506
|
// сам, записанное идёт по цене входа. Часовая цена — тоже цена входа: срок метки модель не читает.
|
|
9490
|
-
openrouter: {
|
|
9507
|
+
openrouter: {
|
|
9508
|
+
inputPerMillion: 0.15,
|
|
9509
|
+
outputPerMillion: 0.6,
|
|
9510
|
+
cachedInputPerMillion: 3e-3,
|
|
9511
|
+
cacheWrite1hPerMillion: 0.15,
|
|
9512
|
+
// Каталог OpenRouter pricing.overrides: то же расписание пика, что у прямого DeepSeek.
|
|
9513
|
+
peakHours: {
|
|
9514
|
+
timeZone: "UTC",
|
|
9515
|
+
multiplier: 2,
|
|
9516
|
+
windows: [
|
|
9517
|
+
{ days: [1, 2, 3, 4, 5], from: "01:00", to: "04:00" },
|
|
9518
|
+
{ days: [1, 2, 3, 4, 5], from: "06:00", to: "10:00" }
|
|
9519
|
+
]
|
|
9520
|
+
}
|
|
9521
|
+
}
|
|
9491
9522
|
}
|
|
9492
9523
|
};
|
|
9493
9524
|
|
|
@@ -10818,6 +10849,10 @@ function buildModelMenu(catalog, env, defaultChoice) {
|
|
|
10818
10849
|
models: catalog.models.filter((model) => model.providerModelIds[provider.id]).map((model) => ({
|
|
10819
10850
|
id: model.id,
|
|
10820
10851
|
displayName: model.displayName,
|
|
10852
|
+
...model.menu?.group !== void 0 && { group: model.menu.group },
|
|
10853
|
+
...model.menu?.description !== void 0 && { description: model.menu.description },
|
|
10854
|
+
...model.menu?.tags !== void 0 && { tags: [...model.menu.tags] },
|
|
10855
|
+
...model.pricing?.[provider.id] && { price: { inputPerMillion: model.pricing[provider.id].inputPerMillion, outputPerMillion: model.pricing[provider.id].outputPerMillion } },
|
|
10821
10856
|
acceptsImages: modelAcceptsImages(model, provider.id),
|
|
10822
10857
|
reasoning: {
|
|
10823
10858
|
levels: [...model.reasoning.levels ?? []],
|
|
@@ -11413,13 +11448,15 @@ function withRetries(model, context) {
|
|
|
11413
11448
|
function toAgentChatMessage(message) {
|
|
11414
11449
|
if (message.role === "user") return { id: message.id, role: "user", parts: message.parts };
|
|
11415
11450
|
const { pendingSteps: _steps, ...usage } = message.usage ?? {};
|
|
11451
|
+
const reasoningLevel = answerReasoningOf(message.parts);
|
|
11416
11452
|
const thoughtTitles = thoughtTitlesOfParts(message.parts);
|
|
11417
11453
|
return {
|
|
11418
11454
|
id: message.id,
|
|
11419
11455
|
role: "assistant",
|
|
11420
|
-
parts: message.parts,
|
|
11456
|
+
parts: withoutAnswerReasoning(message.parts),
|
|
11421
11457
|
metadata: {
|
|
11422
11458
|
status: message.status,
|
|
11459
|
+
...reasoningLevel !== void 0 && { reasoningLevel },
|
|
11423
11460
|
reasoningDurationsMs: message.reasoningDurationsMs,
|
|
11424
11461
|
...Object.keys(thoughtTitles).length > 0 && { thoughtTitles },
|
|
11425
11462
|
...message.modelId && { modelId: message.modelId },
|
|
@@ -12224,7 +12261,7 @@ var SHOWS_EVERYTHING = {
|
|
|
12224
12261
|
visibleChunks: (stream) => stream,
|
|
12225
12262
|
visibleCompactions: (markers) => markers
|
|
12226
12263
|
};
|
|
12227
|
-
var MODEL_METADATA_KEYS = ["modelId", "providerId", "usage"];
|
|
12264
|
+
var MODEL_METADATA_KEYS = ["modelId", "providerId", "reasoningLevel", "usage"];
|
|
12228
12265
|
var MODEL_CHAT_KEYS = ["ownerId", "modelId", "providerId", "reasoning"];
|
|
12229
12266
|
var withoutErrorDetails = (metadata) => {
|
|
12230
12267
|
const error = metadata.error;
|
|
@@ -12290,6 +12327,7 @@ function clientVisibilityOf(capabilities, sdkScreenTool, { thoughtTitles = false
|
|
|
12290
12327
|
const shownTitles = {};
|
|
12291
12328
|
let serverOrdinal = 0;
|
|
12292
12329
|
const kept = message.parts.flatMap((part) => {
|
|
12330
|
+
if (part.type === ANSWER_REASONING_PART) return [];
|
|
12293
12331
|
if (part.type === "reasoning" && placesThoughts) {
|
|
12294
12332
|
const title = serverTitles[String(serverOrdinal++)];
|
|
12295
12333
|
if (title === void 0) return [];
|
|
@@ -15111,6 +15149,7 @@ export {
|
|
|
15111
15149
|
IMPORT_MAX_IMAGES,
|
|
15112
15150
|
IMPORT_MAX_IMAGE_BYTES,
|
|
15113
15151
|
InvalidModelChoiceError,
|
|
15152
|
+
buildModelMenu,
|
|
15114
15153
|
BASIC_WIDGET_NAMES,
|
|
15115
15154
|
SUGGESTIONS_SHOWN,
|
|
15116
15155
|
defineWidget,
|
|
@@ -15128,4 +15167,4 @@ export {
|
|
|
15128
15167
|
InvalidWidgetAnswerError,
|
|
15129
15168
|
createChatService
|
|
15130
15169
|
};
|
|
15131
|
-
//# sourceMappingURL=chunk-
|
|
15170
|
+
//# sourceMappingURL=chunk-YMUK7P4S.js.map
|