@ykurilov/agent-chat-flows 0.61.0 → 0.63.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/dist/index.js CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  sideTaskFieldKnown,
15
15
  sideTaskRecord,
16
16
  sideTaskStanding
17
- } from "./chunk-CKY5KG7N.js";
17
+ } from "./chunk-H3AN5YUN.js";
18
18
  import {
19
19
  FACT_PREFIX,
20
20
  MAX_FACTS,
@@ -26,7 +26,7 @@ import {
26
26
  fieldValueText,
27
27
  isFactEntry,
28
28
  sameFact
29
- } from "./chunk-3PTJI2XY.js";
29
+ } from "./chunk-KGWXTWBZ.js";
30
30
  import {
31
31
  AGENT_FLOW_FORMAT,
32
32
  AGENT_FLOW_FORMAT_VERSION,
@@ -105,7 +105,7 @@ import {
105
105
  withDayAnchor,
106
106
  withNudgeStep,
107
107
  withoutUndeliveredTouch
108
- } from "./chunk-BOV6FJGU.js";
108
+ } from "./chunk-LT4QELAZ.js";
109
109
  import {
110
110
  appliedInTime,
111
111
  byVersionAndState,
@@ -841,6 +841,7 @@ var DEFAULT_JUDGE_THRESHOLD = 0.7;
841
841
  var DEFAULT_JUDGE_MODEL = "microsoft/microsoft-decision-1";
842
842
  var DEFAULT_JUDGE_TIMEOUT_MS = 5e3;
843
843
  var OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1";
844
+ var JOURNAL_CHARS = 300;
844
845
  var FALLBACK_INSTRUCTIONS = "\u0422\u044B \u0441\u0443\u0434\u044C\u044F \u0432 \u0434\u0438\u0430\u043B\u043E\u0433\u0435 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430 \u0441 \u0418\u0418-\u0430\u0433\u0435\u043D\u0442\u043E\u043C. \u0414\u043B\u044F \u043A\u0430\u0436\u0434\u043E\u0433\u043E \u0443\u0441\u043B\u043E\u0432\u0438\u044F \u0440\u0435\u0448\u0438, \u0432\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u043E \u043B\u0438 \u043E\u043D\u043E \u043F\u043E \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u043C \u0440\u0435\u043F\u043B\u0438\u043A\u0430\u043C. \u0412\u0435\u0440\u043D\u0438 \u0432 met \u043D\u043E\u043C\u0435\u0440\u0430 (id) \u0442\u043E\u043B\u044C\u043A\u043E \u0442\u0435\u0445 \u0443\u0441\u043B\u043E\u0432\u0438\u0439, \u043A\u043E\u0442\u043E\u0440\u044B\u0435 \u044F\u0432\u043D\u043E \u0432\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u044B. \u0421\u043E\u043C\u043D\u0435\u0432\u0430\u0435\u0448\u044C\u0441\u044F \u2014 \u043D\u0435 \u0432\u043A\u043B\u044E\u0447\u0430\u0439.";
845
846
  var FALLBACK_SCHEMA = {
846
847
  type: "object",
@@ -856,6 +857,34 @@ function createFlowJudge(settings, port, deps = {}) {
856
857
  const env = deps.env ?? process.env;
857
858
  const logError = deps.logError ?? (() => {
858
859
  });
860
+ const journal = settings.journal;
861
+ function writeJournal(question, context, verdicts) {
862
+ if (!deps.logJudge || journal === "off") return;
863
+ const confirmed = verdicts?.some((verdict) => verdict.confirmed) ?? false;
864
+ const withTexts = journal === "always" || question.testChat === true || journal === "transitions" && confirmed;
865
+ if (!withTexts && !confirmed) return;
866
+ const { goal, conversation, agent_words: agentWords } = context.state;
867
+ try {
868
+ deps.logJudge({
869
+ ownerId: question.ownerId,
870
+ chatId: question.chatId,
871
+ kind: question.kind,
872
+ model,
873
+ threshold,
874
+ source: verdicts?.[0]?.source ?? null,
875
+ ...goal !== void 0 && { goal: clip2(goal) },
876
+ ...withTexts && agentWords !== void 0 && { agentWords: clip2(agentWords) },
877
+ ...withTexts && { conversation: conversation.map(({ role, text }) => ({ role, text: clip2(text) })) },
878
+ replies: conversation.map(({ role, text }) => ({ role, length: text.length })),
879
+ conditions: context.conditions.map(({ exitId, text }) => {
880
+ const verdict = verdicts?.find((item) => item.exitId === exitId);
881
+ return { exitId, text: clip2(text), probability: verdict?.probability ?? null, confirmed: verdict?.confirmed ?? false };
882
+ })
883
+ });
884
+ } catch (error) {
885
+ logError(`\u0421\u0443\u0434\u044C\u044F: \u0436\u0443\u0440\u043D\u0430\u043B \u043D\u0435 \u0437\u0430\u043F\u0438\u0441\u0430\u043D \u2014 ${errorText2(error)}`);
886
+ }
887
+ }
859
888
  async function askDecision(question, conditions, state) {
860
889
  const apiKey = settings.openrouter?.apiKey ?? env.OPENROUTER_API_KEY;
861
890
  if (!apiKey) {
@@ -925,6 +954,11 @@ function createFlowJudge(settings, port, deps = {}) {
925
954
  logError(`\u0421\u0443\u0434\u044C\u044F \u043D\u0435 \u0441\u043F\u0440\u043E\u0448\u0435\u043D: ${errorText2(error)}`);
926
955
  return null;
927
956
  }
957
+ const verdicts = await ask(question, context);
958
+ writeJournal(question, context, verdicts);
959
+ return verdicts;
960
+ }
961
+ async function ask(question, context) {
928
962
  const answers = await askDecision(question, context.conditions, context.state);
929
963
  if (answers) {
930
964
  return context.conditions.map(({ exitId }) => ({ exitId, probability: answers[exitId], confirmed: answers[exitId] >= threshold, source: "decision" }));
@@ -935,25 +969,37 @@ function createFlowJudge(settings, port, deps = {}) {
935
969
  return context.conditions.map(({ exitId }) => ({ exitId, probability: met.has(exitId) ? 1 : 0, confirmed: met.has(exitId), source: "fallback" }));
936
970
  }
937
971
  return {
938
- async checkClaim({ ownerId, chatId, exitId, condition, goal, why, messages, signal }) {
972
+ async checkClaim({ ownerId, chatId, exitId, condition, goal, why, messages, signal, testChat }) {
939
973
  const verdicts = await judge({
974
+ kind: "claim",
940
975
  ownerId,
941
976
  chatId,
942
977
  ...goal !== void 0 && { goal },
943
978
  ...why !== void 0 && { why },
944
979
  messages,
945
980
  conditions: [{ exitId, text: condition }],
946
- ...signal && { signal }
981
+ ...signal && { signal },
982
+ ...testChat && { testChat }
947
983
  });
948
984
  return verdicts?.[0] ?? null;
949
985
  },
950
- async checkAll({ ownerId, chatId, goal, conditions, messages, signal }) {
986
+ async checkAll({ ownerId, chatId, goal, conditions, messages, signal, testChat }) {
951
987
  if (conditions.length === 0) return [];
952
- const verdicts = await judge({ ownerId, chatId, ...goal !== void 0 && { goal }, messages, conditions, ...signal && { signal } });
988
+ const verdicts = await judge({
989
+ kind: "after_turn",
990
+ ownerId,
991
+ chatId,
992
+ ...goal !== void 0 && { goal },
993
+ messages,
994
+ conditions,
995
+ ...signal && { signal },
996
+ ...testChat && { testChat }
997
+ });
953
998
  return verdicts?.filter((verdict) => verdict.confirmed) ?? [];
954
999
  }
955
1000
  };
956
1001
  }
1002
+ var clip2 = (text) => text.length <= JOURNAL_CHARS ? text : `${text.slice(0, JOURNAL_CHARS - 1)}\u2026`;
957
1003
  function errorText2(error) {
958
1004
  return error instanceof Error ? error.message : String(error);
959
1005
  }
@@ -2081,7 +2127,8 @@ function flowExitTool(input, model) {
2081
2127
  goal: stateGoal(state.instructions),
2082
2128
  why,
2083
2129
  messages: await input.history(model.ownerId, model.chatId),
2084
- ...abortSignal && { signal: abortSignal }
2130
+ ...abortSignal && { signal: abortSignal },
2131
+ ...turn.run.timeOffset !== void 0 && { testChat: true }
2085
2132
  });
2086
2133
  } catch (error) {
2087
2134
  runtime.logError(`[\u0441\u0446\u0435\u043D\u0430\u0440\u0438\u0439] \u0447\u0430\u0442=${model.chatId} \u0441\u0443\u0434\u044C\u044F \u0443\u043F\u0430\u043B: ${error instanceof Error ? error.message : String(error)}`);
@@ -2337,6 +2384,12 @@ function judgeMessages(messages) {
2337
2384
  return text ? [{ role: message.role === "user" ? "human" : "agent", text }] : [];
2338
2385
  });
2339
2386
  }
2387
+ function turnWindow(messages, run, answer) {
2388
+ const answerAt = messages.findIndex((message) => message.id === answer.id);
2389
+ const upToAnswer = answerAt >= 0 ? messages.slice(0, answerAt + 1) : [...messages, { role: "assistant", parts: answer.parts }];
2390
+ const enteredAt = run.enteredAfterAnswer === void 0 ? -1 : upToAnswer.findIndex((message) => message.id === run.enteredAfterAnswer);
2391
+ return enteredAt >= 0 ? upToAnswer.slice(enteredAt) : upToAnswer;
2392
+ }
2340
2393
  function buildAgentFlow(options, modules = {}) {
2341
2394
  const { store } = options;
2342
2395
  const clock = options.now ?? (() => /* @__PURE__ */ new Date());
@@ -2394,7 +2447,8 @@ function buildAgentFlow(options, modules = {}) {
2394
2447
  }
2395
2448
  });
2396
2449
  }
2397
- const judge = lazy(() => modules.judge ?? createFlowJudge(options.judge, portOf, { logError }));
2450
+ const logJudge = options.logJudge ?? ((entry) => console.info(`[\u0441\u0446\u0435\u043D\u0430\u0440\u0438\u0439] \u0441\u0443\u0434\u044C\u044F: ${JSON.stringify(entry)}`));
2451
+ const judge = lazy(() => modules.judge ?? createFlowJudge(options.judge, portOf, { logError, logJudge }));
2398
2452
  const firstMessages = lazy(() => modules.firstMessages !== void 0 ? modules.firstMessages : createFirstMessageRules(options.firstMessages, store));
2399
2453
  let lastAppTimeZone;
2400
2454
  const portZones = /* @__PURE__ */ new WeakMap();
@@ -2659,9 +2713,9 @@ function buildAgentFlow(options, modules = {}) {
2659
2713
  onUndelivered: rescheduleUndelivered
2660
2714
  })
2661
2715
  );
2662
- async function history(ownerId, chatId) {
2716
+ async function history(ownerId, chatId, turn) {
2663
2717
  const { messages } = await (await portOf({ ownerId, chatId })).peekHistory(ownerId, chatId);
2664
- return judgeMessages(messages).slice(-JUDGE_HISTORY);
2718
+ return judgeMessages(turn ? turnWindow(messages, turn.run, turn.answer) : messages).slice(-JUDGE_HISTORY);
2665
2719
  }
2666
2720
  async function reschedule(ownerId, chatId, run, branchHead, failedAt) {
2667
2721
  try {
@@ -2725,7 +2779,15 @@ function buildAgentFlow(options, modules = {}) {
2725
2779
  if (!state || isFinal(state)) return;
2726
2780
  const conditions = judgeExits(pinned.flow, run.state);
2727
2781
  if (conditions.length === 0) return;
2728
- const verdicts = await judge().checkAll({ ownerId, chatId, goal: stateGoal(state.instructions), conditions, messages: await history(ownerId, chatId) });
2782
+ const verdicts = await judge().checkAll({
2783
+ ownerId,
2784
+ chatId,
2785
+ goal: stateGoal(state.instructions),
2786
+ conditions,
2787
+ messages: await history(ownerId, chatId, { run, answer: { id: messageId, parts: result.parts } }),
2788
+ // Сдвиг часов есть только у тестового чата редактора.
2789
+ ...run.timeOffset !== void 0 && { testChat: true }
2790
+ });
2729
2791
  const met = conditions.map(({ exitId }) => verdicts.find((verdict) => verdict.exitId === exitId && verdict.confirmed)).find(Boolean);
2730
2792
  if (!met) return;
2731
2793
  const transition = nextTransition(pinned.flow, run, { type: "verdict", exitId: met.exitId, probability: met.probability, decidedBy: "judge" }, chatTime(run, now()));