@xopcai/xopc 0.0.46 → 0.0.48
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/README.md +17 -2
- package/README.zh-CN.md +8 -2
- package/dist/extensions/dingtalk/src/plugin.js +1 -1
- package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
- package/dist/extensions/telegram/src/command-handler.js +1 -1
- package/dist/extensions/telegram/src/command-handler.js.map +1 -1
- package/dist/extensions/telegram/src/plugin.js +1 -1
- package/dist/extensions/telegram/src/routing-integration.js +2 -2
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/api/api.js +2 -2
- package/dist/extensions/weixin/src/auth/accounts.js +1 -1
- package/dist/extensions/weixin/src/cdn/upload.js +1 -1
- package/dist/extensions/weixin/src/media/data-url.js +1 -1
- package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
- package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
- package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
- package/dist/extensions/weixin/src/plugin.js +1 -1
- package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
- package/dist/gateway/static/root/assets/{agents-9tPOBNVa.js → agents-BdISC5UA.js} +2 -2
- package/dist/gateway/static/root/assets/{agents-9tPOBNVa.js.map → agents-BdISC5UA.js.map} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-yjXMjZEY.js → apps-page-CXU_Jg95.js} +2 -2
- package/dist/gateway/static/root/assets/{apps-page-yjXMjZEY.js.map → apps-page-CXU_Jg95.js.map} +1 -1
- package/dist/gateway/static/root/assets/{channels-settings-B-vOBJmr.js → channels-settings-Doe1ciOW.js} +2 -2
- package/dist/gateway/static/root/assets/{channels-settings-B-vOBJmr.js.map → channels-settings-Doe1ciOW.js.map} +1 -1
- package/dist/gateway/static/root/assets/{cron-dreaming-jobs-CmdPJHC8.js → cron-dreaming-jobs-C-V4_3vz.js} +2 -2
- package/dist/gateway/static/root/assets/{cron-dreaming-jobs-CmdPJHC8.js.map → cron-dreaming-jobs-C-V4_3vz.js.map} +1 -1
- package/dist/gateway/static/root/assets/{cron-page-aS5nCGTE.js → cron-page-CIIy81K6.js} +2 -2
- package/dist/gateway/static/root/assets/{cron-page-aS5nCGTE.js.map → cron-page-CIIy81K6.js.map} +1 -1
- package/dist/gateway/static/root/assets/{dist-COrWk0va.js → dist-VW7dXc5X.js} +2 -2
- package/dist/gateway/static/root/assets/{dist-COrWk0va.js.map → dist-VW7dXc5X.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-p7Aufdiu.js → extension-debug-page-Cslwx62-.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-debug-page-p7Aufdiu.js.map → extension-debug-page-Cslwx62-.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-Ca_H5bLy.js → extension-page-Dzyebr6T.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-page-Ca_H5bLy.js.map → extension-page-Dzyebr6T.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-f8jERrXK.js → extension-settings-page-B07uetL_.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-settings-page-f8jERrXK.js.map → extension-settings-page-B07uetL_.js.map} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-config-api-BC5dh16N.js → heartbeat-config-api-kmvGNriW.js} +2 -2
- package/dist/gateway/static/root/assets/{heartbeat-config-api-BC5dh16N.js.map → heartbeat-config-api-kmvGNriW.js.map} +1 -1
- package/dist/gateway/static/root/assets/{index-DRnjltLC.js → index-DW6JvymK.js} +11 -11
- package/dist/gateway/static/root/assets/{index-DRnjltLC.js.map → index-DW6JvymK.js.map} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-CBHnie4a.js → logs-page-BiRnV2Ex.js} +2 -2
- package/dist/gateway/static/root/assets/{logs-page-CBHnie4a.js.map → logs-page-BiRnV2Ex.js.map} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-29vp15ci.js → sessions-page-DQq0QaQh.js} +2 -2
- package/dist/gateway/static/root/assets/{sessions-page-29vp15ci.js.map → sessions-page-DQq0QaQh.js.map} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-Bd1rO8dz.js → settings-page-BV_l8nJ3.js} +2 -2
- package/dist/gateway/static/root/assets/{settings-page-Bd1rO8dz.js.map → settings-page-BV_l8nJ3.js.map} +1 -1
- package/dist/gateway/static/root/assets/{skills-page-BYppQ88L.js → skills-page-Bv0pphDM.js} +2 -2
- package/dist/gateway/static/root/assets/{skills-page-BYppQ88L.js.map → skills-page-Bv0pphDM.js.map} +1 -1
- package/dist/gateway/static/root/assets/{use-image-provider-credentials-DlWCe2d_.js → use-image-provider-credentials-BPcW1K0N.js} +2 -2
- package/dist/gateway/static/root/assets/{use-image-provider-credentials-DlWCe2d_.js.map → use-image-provider-credentials-BPcW1K0N.js.map} +1 -1
- package/dist/gateway/static/root/index.html +1 -1
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.js +6 -6
- package/dist/src/agent/context/workspace-seed.js +2 -2
- package/dist/src/agent/goals/checklist-judge.js +21 -17
- package/dist/src/agent/goals/checklist-judge.js.map +1 -1
- package/dist/src/agent/goals/evaluate-turn.js +6 -11
- package/dist/src/agent/goals/evaluate-turn.js.map +1 -1
- package/dist/src/agent/goals/judge.d.ts +16 -0
- package/dist/src/agent/goals/judge.js +61 -13
- package/dist/src/agent/goals/judge.js.map +1 -1
- package/dist/src/agent/goals/post-turn.js +1 -1
- package/dist/src/agent/goals/state.d.ts +7 -0
- package/dist/src/agent/goals/state.js +24 -1
- package/dist/src/agent/goals/state.js.map +1 -1
- package/dist/src/agent/image/load-image-media.js +1 -1
- package/dist/src/agent/ipc/bus.js +1 -1
- package/dist/src/agent/ipc/inbox.js +2 -2
- package/dist/src/agent/ipc/socket.js +1 -1
- package/dist/src/agent/memory/builtin-memory-store.js +1 -1
- package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
- package/dist/src/agent/memory/dreaming/events.js +1 -1
- package/dist/src/agent/memory/dreaming/last-run.js +1 -1
- package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
- package/dist/src/agent/memory/dreaming/preview.js +1 -1
- package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
- package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
- package/dist/src/agent/memory/dreaming/utils.js +1 -1
- package/dist/src/agent/memory/plugin-discovery.js +1 -1
- package/dist/src/agent/models/manager.js +1 -1
- package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
- package/dist/src/agent/service.js +5 -5
- package/dist/src/agent/skills/config.js +1 -1
- package/dist/src/agent/skills/hub-hash.js +2 -2
- package/dist/src/agent/skills/hub-lock.js +1 -1
- package/dist/src/agent/skills/hub-pull.js +1 -1
- package/dist/src/agent/skills/index.js +1 -1
- package/dist/src/agent/skills/managed-store.js +1 -1
- package/dist/src/agent/skills/scanner.js +1 -1
- package/dist/src/agent/skills/skill-manage-ops.js +1 -1
- package/dist/src/agent/skills/skill-manager.js +1 -1
- package/dist/src/agent/tools/dreaming-tool.js +1 -1
- package/dist/src/agent/tools/factory.js +1 -1
- package/dist/src/agent/tools/image-generate-tool.js +1 -1
- package/dist/src/agent/tools/send-media.js +1 -1
- package/dist/src/agent/tools/skill-manage-tool.js +1 -1
- package/dist/src/agent/tools/write.js +1 -1
- package/dist/src/auth/credentials.js +3 -3
- package/dist/src/auth/profiles/store.js +1 -1
- package/dist/src/auth/sync-provider-auth.js +1 -1
- package/dist/src/channels/attachments/inbound-persist.js +1 -1
- package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
- package/dist/src/channels/outbound/persist-store.js +1 -1
- package/dist/src/channels/pairing/allow-from-file.js +1 -1
- package/dist/src/channels/pairing/pairing-store.js +2 -2
- package/dist/src/chat-commands/builtins/config.js +2 -2
- package/dist/src/chat-commands/builtins/model.d.ts +2 -2
- package/dist/src/chat-commands/builtins/model.js +10 -8
- package/dist/src/chat-commands/builtins/model.js.map +1 -1
- package/dist/src/chat-commands/builtins/system.js +1 -1
- package/dist/src/chat-commands/builtins/system.js.map +1 -1
- package/dist/src/chat-commands/context.js +1 -1
- package/dist/src/cli/bin.d.ts +7 -0
- package/dist/src/cli/bin.js +4 -0
- package/dist/src/cli/bootstrap-extensions.js +5 -1
- package/dist/src/cli/bootstrap-extensions.js.map +1 -1
- package/dist/src/cli/cli-log-level-preset.d.ts +7 -0
- package/dist/src/cli/cli-log-level-preset.js +13 -0
- package/dist/src/cli/cli-log-level-preset.js.map +1 -0
- package/dist/src/cli/commands/agent.js +2 -2
- package/dist/src/cli/commands/agents.js +1 -1
- package/dist/src/cli/commands/config.js +2 -2
- package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
- package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -1
- package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
- package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
- package/dist/src/cli/commands/extension-dev.js +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +1 -1
- package/dist/src/cli/commands/extension-pack.js +1 -1
- package/dist/src/cli/commands/gateway.js +1 -1
- package/dist/src/cli/commands/image.js +1 -1
- package/dist/src/cli/commands/init.js +4 -4
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/cli/commands/onboard.js +1 -1
- package/dist/src/cli/commands/update.js +1 -1
- package/dist/src/cli/index.d.ts +0 -1
- package/dist/src/cli/index.js +1 -1
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/cli/utils/init-workspace.js +2 -2
- package/dist/src/config/index.js +2 -2
- package/dist/src/config/loader.js +2 -2
- package/dist/src/config/models-json.js +2 -2
- package/dist/src/config/profile.js +2 -2
- package/dist/src/cron/executor.js +2 -2
- package/dist/src/cron/persistence.js +1 -1
- package/dist/src/cron/run-log-store.js +1 -1
- package/dist/src/daemon/launchd.js +2 -2
- package/dist/src/daemon/systemd.js +2 -2
- package/dist/src/extensions/health.js +1 -1
- package/dist/src/extensions/loader.d.ts +5 -0
- package/dist/src/extensions/loader.js +19 -3
- package/dist/src/extensions/loader.js.map +1 -1
- package/dist/src/extensions/lockfile.js +2 -2
- package/dist/src/gateway/agents-admin.js +2 -2
- package/dist/src/gateway/hono/lib/extension-store.js +1 -1
- package/dist/src/gateway/hono/lib/static-ui.js +1 -1
- package/dist/src/gateway/hono/oauth.js +1 -1
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
- package/dist/src/gateway/hono/routes/config.js +1 -1
- package/dist/src/gateway/hono/routes/dreaming.js +1 -1
- package/dist/src/gateway/hono/routes/host-fs.js +1 -1
- package/dist/src/gateway/hono/routes/models.js +1 -1
- package/dist/src/gateway/hono/routes/workspace.js +3 -3
- package/dist/src/gateway/hono/sse.js +2 -2
- package/dist/src/gateway/lock.js +2 -2
- package/dist/src/gateway/service/run-gateway-agent.js +2 -2
- package/dist/src/gateway/service.js +5 -5
- package/dist/src/gateway/workspace-fs-file-list.js +1 -1
- package/dist/src/gateway/workspace-heartbeat-path.js +1 -1
- package/dist/src/infra/update-check.js +1 -1
- package/dist/src/infra/update-lock.js +3 -3
- package/dist/src/infra/update-runner.js +2 -2
- package/dist/src/infra/update-runner.js.map +1 -1
- package/dist/src/infra/update-startup.js +2 -2
- package/dist/src/infra/write-file-atomic.js +2 -2
- package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
- package/dist/src/providers/index.js +2 -2
- package/dist/src/providers/model-registry.js +1 -1
- package/dist/src/session/config-store.js +2 -2
- package/dist/src/session/search-index-cache.js +1 -1
- package/dist/src/session/search-index.js +1 -1
- package/dist/src/session/session-title.js +1 -1
- package/dist/src/session/store.js +5 -5
- package/dist/src/tui/backends/embedded-backend.d.ts +1 -1
- package/dist/src/tui/backends/embedded-backend.js +25 -4
- package/dist/src/tui/backends/embedded-backend.js.map +1 -1
- package/dist/src/tui/backends/gateway-sse-backend.js +36 -10
- package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
- package/dist/src/tui/tui-commands.js +1 -1
- package/dist/src/tui/tui-commands.js.map +1 -1
- package/dist/src/tui/tui.js +13 -2
- package/dist/src/tui/tui.js.map +1 -1
- package/dist/src/utils/logger/audit.js +1 -1
- package/dist/src/utils/logger/log-store.js +1 -1
- package/dist/src/utils/logger/rotation.js +1 -1
- package/dist/src/voice/tts/audio.js +1 -1
- package/dist/src/voice/tts/providers/edge-speech.js +1 -1
- package/package.json +7 -7
- package/dist/src/cli/agent-chat-log-level-preset.d.ts +0 -8
- package/dist/src/cli/agent-chat-log-level-preset.js +0 -25
- package/dist/src/cli/agent-chat-log-level-preset.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evaluate-turn.js","names":[],"sources":["../../../../src/agent/goals/evaluate-turn.ts"],"sourcesContent":["import type { GoalsConfig } from '../../config/schema.js';\n\nimport { decomposeGoalChecklist, evaluateGoalChecklistJudge } from './checklist-judge.js';\nimport { allChecklistTerminal, checklistCounts, CHECKLIST_ITEM_PENDING } from './checklist-types.js';\nimport {\n buildContinuationPromptFromState,\n checklistProgressSuffix,\n CONTINUATION_PROMPT_TEMPLATE_EN,\n CONTINUATION_PROMPT_WITH_CHECKLIST_TEMPLATE_EN,\n goalEvaluateUserCopy,\n resolveGoalUiLocale,\n type GoalUiLocale,\n} from './goal-locale.js';\nimport { judgeGoalHermesStyle } from './judge.js';\nimport {\n applyJudgeChecklistUpdates,\n renderChecklistNumbered,\n type PersistentGoalState,\n} from './state.js';\n\n/** Hermes `CONTINUATION_PROMPT_TEMPLATE` (English; parity / tests). */\nexport const CONTINUATION_PROMPT_TEMPLATE = CONTINUATION_PROMPT_TEMPLATE_EN;\n\n/** Hermes `CONTINUATION_PROMPT_WITH_CHECKLIST_TEMPLATE` (English; parity / tests). */\nexport const CONTINUATION_PROMPT_WITH_CHECKLIST_TEMPLATE = CONTINUATION_PROMPT_WITH_CHECKLIST_TEMPLATE_EN;\n\nexport type GoalsEvaluateConfigSlice = Pick<\n GoalsConfig,\n 'checklistMode' | 'maxConsecutiveParseFailures' | 'judgeTimeoutMs' | 'checklistHistoryChars'\n>;\n\nexport type GoalPostTurnDecision = {\n newState: PersistentGoalState | null;\n shouldContinue: boolean;\n continuationPrompt: string | null;\n verdict: 'done' | 'continue' | 'skipped' | 'inactive' | 'decompose';\n reason: string;\n message: string;\n};\n\nfunction cloneState(s: PersistentGoalState): PersistentGoalState {\n return {\n ...s,\n checklist: s.checklist?.map((it) => ({ ...it })),\n };\n}\n\n/**\n * Hermes `GoalManager.evaluate_after_turn` equivalent (minus SessionDB I/O).\n */\nexport async function evaluateAfterTurnHermesLike(\n state: PersistentGoalState,\n lastResponse: string,\n judgeModelRef: string,\n signal?: AbortSignal,\n opts?: { goalsSlice?: Partial<GoalsEvaluateConfigSlice>; historyExcerpt?: string; uiLocale?: GoalUiLocale },\n): Promise<GoalPostTurnDecision> {\n const locale = opts?.uiLocale ?? resolveGoalUiLocale(state);\n const copy = goalEvaluateUserCopy(locale);\n\n if (state.status !== 'active') {\n return {\n newState: state,\n shouldContinue: false,\n continuationPrompt: null,\n verdict: 'inactive',\n reason: 'no active goal',\n message: '',\n };\n }\n\n const slice = opts?.goalsSlice;\n const checklistMode = slice?.checklistMode !== false;\n const maxParseFailures = slice?.maxConsecutiveParseFailures ?? 3;\n const judgeTimeoutMs = slice?.judgeTimeoutMs;\n\n const next = cloneState(state);\n next.turnsUsed += 1;\n next.lastTurnAt = Date.now();\n\n const bumpParse = () => {\n next.consecutiveParseFailures = (next.consecutiveParseFailures ?? 0) + 1;\n };\n const resetParse = () => {\n next.consecutiveParseFailures = 0;\n };\n\n const pauseIfParseStorm = (reason: string): GoalPostTurnDecision | null => {\n const n = next.consecutiveParseFailures ?? 0;\n if (n < maxParseFailures) return null;\n next.status = 'paused';\n next.pausedReason = `judge parse failures (${n} consecutive)`;\n return {\n newState: next,\n shouldContinue: false,\n continuationPrompt: null,\n verdict: 'continue',\n reason,\n message: copy.pauseParse(n),\n };\n };\n\n const pauseIfBudget = (reason: string): GoalPostTurnDecision | null => {\n if (next.turnsUsed < next.maxTurns) return null;\n next.status = 'paused';\n next.pausedReason = `turn budget exhausted (${next.turnsUsed}/${next.maxTurns})`;\n return {\n newState: next,\n shouldContinue: false,\n continuationPrompt: null,\n verdict: 'continue',\n reason,\n message: copy.pauseBudget(next.turnsUsed, next.maxTurns),\n };\n };\n\n // ── Phase A: decompose (once per goal when checklist mode is on) ──\n if (checklistMode && !next.decomposed) {\n const dec = await decomposeGoalChecklist({\n goal: next.goal,\n judgeModelRef,\n signal,\n judgeTimeoutMs,\n uiLocale: locale,\n });\n next.decomposed = true;\n if (!dec.parseFailed && dec.items.length > 0) {\n const now = Date.now();\n next.checklist = dec.items.map((it) => ({\n text: it.text,\n status: CHECKLIST_ITEM_PENDING,\n addedBy: 'judge' as const,\n addedAt: now,\n }));\n next.lastVerdict = 'decompose';\n next.lastReason = copy.decomposedReason(dec.items.length);\n resetParse();\n const budgetEarly = pauseIfBudget(next.lastReason);\n if (budgetEarly) return budgetEarly;\n return {\n newState: next,\n shouldContinue: true,\n continuationPrompt: buildContinuationPromptFromState(next, locale),\n verdict: 'decompose',\n reason: next.lastReason ?? '',\n message: copy.checklistReady(dec.items.length),\n };\n }\n next.lastReason = dec.errorReason\n ? copy.decomposeFallbackReason(dec.errorReason)\n : copy.noChecklistFallback();\n }\n\n // ── Phase B: checklist judge ──\n const checklist = next.checklist ?? [];\n if (checklist.length > 0) {\n const evalResult = await evaluateGoalChecklistJudge({\n goal: next.goal,\n numberedChecklist: renderChecklistNumbered(checklist),\n lastResponse,\n historyExcerpt: opts?.historyExcerpt ?? '',\n judgeModelRef,\n signal,\n judgeTimeoutMs,\n uiLocale: locale,\n });\n\n if (evalResult.parseFailed) {\n bumpParse();\n } else {\n resetParse();\n next.checklist = applyJudgeChecklistUpdates(checklist, {\n updates: evalResult.parsed.updates,\n newItems: evalResult.parsed.newItems,\n });\n }\n\n next.lastVerdict = 'continue';\n next.lastReason = evalResult.parsed.reason;\n\n if (!evalResult.parseFailed && allChecklistTerminal(next.checklist ?? [])) {\n next.status = 'done';\n next.lastVerdict = 'done';\n return {\n newState: next,\n shouldContinue: false,\n continuationPrompt: null,\n verdict: 'done',\n reason: evalResult.parsed.reason,\n message: copy.goalAchieved(evalResult.parsed.reason),\n };\n }\n\n const parseStorm = pauseIfParseStorm(evalResult.parsed.reason);\n if (parseStorm) return parseStorm;\n\n const budget = pauseIfBudget(evalResult.parsed.reason);\n if (budget) return budget;\n\n const { total, completed, impossible } = checklistCounts(next.checklist ?? []);\n const done = completed + impossible;\n const progressSuffix = checklistProgressSuffix(done, total, locale);\n\n return {\n newState: next,\n shouldContinue: true,\n continuationPrompt: buildContinuationPromptFromState(next, locale),\n verdict: 'continue',\n reason: evalResult.parsed.reason,\n message: copy.continuingWithProgress(\n next.turnsUsed,\n next.maxTurns,\n progressSuffix,\n evalResult.parsed.reason,\n ),\n };\n }\n\n // ── Freeform judge (no checklist) ──\n const j = await judgeGoalHermesStyle(state.goal, lastResponse, judgeModelRef, signal, {\n judgeTimeoutMs,\n uiLocale: locale,\n });\n next.lastVerdict = j.verdict === 'skipped' ? 'skipped' : j.verdict;\n next.lastReason = j.reason;\n\n if (j.parseFailed) bumpParse();\n else resetParse();\n\n if (j.verdict === 'done') {\n next.status = 'done';\n return {\n newState: next,\n shouldContinue: false,\n continuationPrompt: null,\n verdict: 'done',\n reason: j.reason,\n message: copy.goalAchieved(j.reason),\n };\n }\n\n const parseStorm = pauseIfParseStorm(j.reason);\n if (parseStorm) return parseStorm;\n\n const budget = pauseIfBudget(j.reason);\n if (budget) return budget;\n\n return {\n newState: next,\n shouldContinue: true,\n continuationPrompt: buildContinuationPromptFromState(next, locale),\n verdict: 'continue',\n reason: j.reason,\n message: copy.continuing(next.turnsUsed, next.maxTurns, j.reason),\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"evaluate-turn.js","names":[],"sources":["../../../../src/agent/goals/evaluate-turn.ts"],"sourcesContent":["import type { GoalsConfig } from '../../config/schema.js';\n\nimport { decomposeGoalChecklist, evaluateGoalChecklistJudge } from './checklist-judge.js';\nimport { allChecklistTerminal, checklistCounts } from './checklist-types.js';\nimport {\n buildContinuationPromptFromState,\n checklistProgressSuffix,\n CONTINUATION_PROMPT_TEMPLATE_EN,\n CONTINUATION_PROMPT_WITH_CHECKLIST_TEMPLATE_EN,\n goalEvaluateUserCopy,\n resolveGoalUiLocale,\n type GoalUiLocale,\n} from './goal-locale.js';\nimport { judgeGoalHermesStyle } from './judge.js';\nimport {\n applyJudgeChecklistUpdates,\n mergeDecomposedChecklistItems,\n renderChecklistNumbered,\n type PersistentGoalState,\n} from './state.js';\n\n/** Hermes `CONTINUATION_PROMPT_TEMPLATE` (English; parity / tests). */\nexport const CONTINUATION_PROMPT_TEMPLATE = CONTINUATION_PROMPT_TEMPLATE_EN;\n\n/** Hermes `CONTINUATION_PROMPT_WITH_CHECKLIST_TEMPLATE` (English; parity / tests). */\nexport const CONTINUATION_PROMPT_WITH_CHECKLIST_TEMPLATE = CONTINUATION_PROMPT_WITH_CHECKLIST_TEMPLATE_EN;\n\nexport type GoalsEvaluateConfigSlice = Pick<\n GoalsConfig,\n 'checklistMode' | 'maxConsecutiveParseFailures' | 'judgeTimeoutMs' | 'checklistHistoryChars'\n>;\n\nexport type GoalPostTurnDecision = {\n newState: PersistentGoalState | null;\n shouldContinue: boolean;\n continuationPrompt: string | null;\n verdict: 'done' | 'continue' | 'skipped' | 'inactive' | 'decompose';\n reason: string;\n message: string;\n};\n\nfunction cloneState(s: PersistentGoalState): PersistentGoalState {\n return {\n ...s,\n checklist: s.checklist?.map((it) => ({ ...it })),\n };\n}\n\n/**\n * Hermes `GoalManager.evaluate_after_turn` equivalent (minus SessionDB I/O).\n */\nexport async function evaluateAfterTurnHermesLike(\n state: PersistentGoalState,\n lastResponse: string,\n judgeModelRef: string,\n signal?: AbortSignal,\n opts?: { goalsSlice?: Partial<GoalsEvaluateConfigSlice>; historyExcerpt?: string; uiLocale?: GoalUiLocale },\n): Promise<GoalPostTurnDecision> {\n const locale = opts?.uiLocale ?? resolveGoalUiLocale(state);\n const copy = goalEvaluateUserCopy(locale);\n\n if (state.status !== 'active') {\n return {\n newState: state,\n shouldContinue: false,\n continuationPrompt: null,\n verdict: 'inactive',\n reason: 'no active goal',\n message: '',\n };\n }\n\n const slice = opts?.goalsSlice;\n const checklistMode = slice?.checklistMode !== false;\n const maxParseFailures = slice?.maxConsecutiveParseFailures ?? 3;\n const judgeTimeoutMs = slice?.judgeTimeoutMs;\n\n const next = cloneState(state);\n next.turnsUsed += 1;\n next.lastTurnAt = Date.now();\n\n const bumpParse = () => {\n next.consecutiveParseFailures = (next.consecutiveParseFailures ?? 0) + 1;\n };\n const resetParse = () => {\n next.consecutiveParseFailures = 0;\n };\n\n const pauseIfParseStorm = (reason: string): GoalPostTurnDecision | null => {\n const n = next.consecutiveParseFailures ?? 0;\n if (n < maxParseFailures) return null;\n next.status = 'paused';\n next.pausedReason = `judge parse failures (${n} consecutive)`;\n return {\n newState: next,\n shouldContinue: false,\n continuationPrompt: null,\n verdict: 'continue',\n reason,\n message: copy.pauseParse(n),\n };\n };\n\n const pauseIfBudget = (reason: string): GoalPostTurnDecision | null => {\n if (next.turnsUsed < next.maxTurns) return null;\n next.status = 'paused';\n next.pausedReason = `turn budget exhausted (${next.turnsUsed}/${next.maxTurns})`;\n return {\n newState: next,\n shouldContinue: false,\n continuationPrompt: null,\n verdict: 'continue',\n reason,\n message: copy.pauseBudget(next.turnsUsed, next.maxTurns),\n };\n };\n\n // ── Phase A: decompose (once per goal when checklist mode is on) ──\n if (checklistMode && !next.decomposed) {\n const dec = await decomposeGoalChecklist({\n goal: next.goal,\n judgeModelRef,\n signal,\n judgeTimeoutMs,\n uiLocale: locale,\n });\n next.decomposed = true;\n if (!dec.parseFailed && dec.items.length > 0) {\n const prior = next.checklist ?? [];\n next.checklist = mergeDecomposedChecklistItems(prior, dec.items);\n const mergedCount = next.checklist.length;\n next.lastVerdict = 'decompose';\n next.lastReason = copy.decomposedReason(mergedCount);\n resetParse();\n const budgetEarly = pauseIfBudget(next.lastReason);\n if (budgetEarly) return budgetEarly;\n return {\n newState: next,\n shouldContinue: true,\n continuationPrompt: buildContinuationPromptFromState(next, locale),\n verdict: 'decompose',\n reason: next.lastReason ?? '',\n message: copy.checklistReady(mergedCount),\n };\n }\n next.lastReason = dec.errorReason\n ? copy.decomposeFallbackReason(dec.errorReason)\n : copy.noChecklistFallback();\n }\n\n // ── Phase B: checklist judge ──\n const checklist = next.checklist ?? [];\n if (checklist.length > 0) {\n const evalResult = await evaluateGoalChecklistJudge({\n goal: next.goal,\n numberedChecklist: renderChecklistNumbered(checklist),\n lastResponse,\n historyExcerpt: opts?.historyExcerpt ?? '',\n judgeModelRef,\n signal,\n judgeTimeoutMs,\n uiLocale: locale,\n });\n\n if (evalResult.parseFailed) {\n bumpParse();\n } else {\n resetParse();\n next.checklist = applyJudgeChecklistUpdates(checklist, {\n updates: evalResult.parsed.updates,\n newItems: evalResult.parsed.newItems,\n });\n }\n\n next.lastVerdict = 'continue';\n next.lastReason = evalResult.parsed.reason;\n\n if (!evalResult.parseFailed && allChecklistTerminal(next.checklist ?? [])) {\n next.status = 'done';\n next.lastVerdict = 'done';\n return {\n newState: next,\n shouldContinue: false,\n continuationPrompt: null,\n verdict: 'done',\n reason: evalResult.parsed.reason,\n message: copy.goalAchieved(evalResult.parsed.reason),\n };\n }\n\n const parseStorm = pauseIfParseStorm(evalResult.parsed.reason);\n if (parseStorm) return parseStorm;\n\n const budget = pauseIfBudget(evalResult.parsed.reason);\n if (budget) return budget;\n\n const { total, completed, impossible } = checklistCounts(next.checklist ?? []);\n const done = completed + impossible;\n const progressSuffix = checklistProgressSuffix(done, total, locale);\n\n return {\n newState: next,\n shouldContinue: true,\n continuationPrompt: buildContinuationPromptFromState(next, locale),\n verdict: 'continue',\n reason: evalResult.parsed.reason,\n message: copy.continuingWithProgress(\n next.turnsUsed,\n next.maxTurns,\n progressSuffix,\n evalResult.parsed.reason,\n ),\n };\n }\n\n // ── Freeform judge (no checklist) ──\n const j = await judgeGoalHermesStyle(state.goal, lastResponse, judgeModelRef, signal, {\n judgeTimeoutMs,\n uiLocale: locale,\n });\n next.lastVerdict = j.verdict === 'skipped' ? 'skipped' : j.verdict;\n next.lastReason = j.reason;\n\n if (j.parseFailed) bumpParse();\n else resetParse();\n\n if (j.verdict === 'done') {\n next.status = 'done';\n return {\n newState: next,\n shouldContinue: false,\n continuationPrompt: null,\n verdict: 'done',\n reason: j.reason,\n message: copy.goalAchieved(j.reason),\n };\n }\n\n const parseStorm = pauseIfParseStorm(j.reason);\n if (parseStorm) return parseStorm;\n\n const budget = pauseIfBudget(j.reason);\n if (budget) return budget;\n\n return {\n newState: next,\n shouldContinue: true,\n continuationPrompt: buildContinuationPromptFromState(next, locale),\n verdict: 'continue',\n reason: j.reason,\n message: copy.continuing(next.turnsUsed, next.maxTurns, j.reason),\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,25 @@
|
|
|
1
|
+
import { resolveModel } from '../../providers/index.js';
|
|
1
2
|
import type { GoalUiLocale } from './goal-locale.js';
|
|
3
|
+
/**
|
|
4
|
+
* Extract visible text from a pi-ai `AssistantMessage.content` array.
|
|
5
|
+
* Handles `TextContent` (`type: 'text'`) and falls back to `ThinkingContent`
|
|
6
|
+
* (`type: 'thinking'`) when the text blocks are empty — reasoning models
|
|
7
|
+
* (DeepSeek-R1, Qwen-thinking, etc.) may place the entire response inside
|
|
8
|
+
* thinking blocks, leaving the text portion blank.
|
|
9
|
+
*/
|
|
10
|
+
export declare function extractAssistantText(content: unknown): string;
|
|
11
|
+
/**
|
|
12
|
+
* Strip markdown code fences (opening AND closing) from raw model output.
|
|
13
|
+
* Handles `` ```json ``, `` ``` ``, and trailing `` ``` `` with optional whitespace.
|
|
14
|
+
*/
|
|
15
|
+
export declare function stripCodeFences(raw: string): string;
|
|
2
16
|
/** Mirrors `hermes_cli/goals.py` — strict judge, JSON-only reply. */
|
|
3
17
|
export declare const JUDGE_SYSTEM_PROMPT: string;
|
|
4
18
|
export declare const JUDGE_USER_PROMPT_TEMPLATE: string;
|
|
5
19
|
export declare const DEFAULT_JUDGE_TIMEOUT_MS = 60000;
|
|
6
20
|
export declare function truncateGoalText(text: string, limit: number): string;
|
|
21
|
+
export declare function resolveGoalJudgeApiKey(model: ReturnType<typeof resolveModel>): Promise<string | undefined>;
|
|
22
|
+
export declare function getAssistantMessageErrorReason(message: unknown): string | null;
|
|
7
23
|
/** Parse judge JSON — fail-open to **continue** (Hermes semantics). */
|
|
8
24
|
export declare function parseJudgeResponseFailOpen(raw: string): {
|
|
9
25
|
done: boolean;
|
|
@@ -1,10 +1,45 @@
|
|
|
1
|
-
import { init_providers, resolveModel } from "../../providers/index.js";
|
|
1
|
+
import { getApiKey, init_providers, resolveModel } from "../../providers/index.js";
|
|
2
2
|
import { JUDGE_REASON_EN } from "../../i18n/goals-bundle.js";
|
|
3
3
|
import { goalUiLocaleOrFallback, judgeFreeformBuiltinMessages, judgeResponseLanguageNote, localizeJudgeReasonText } from "./goal-locale.js";
|
|
4
4
|
import { complete } from "@earendil-works/pi-ai";
|
|
5
5
|
//#region src/agent/goals/judge.ts
|
|
6
6
|
init_providers();
|
|
7
7
|
const JUDGE_RESPONSE_SNIPPET_CHARS = 4e3;
|
|
8
|
+
/**
|
|
9
|
+
* Extract visible text from a pi-ai `AssistantMessage.content` array.
|
|
10
|
+
* Handles `TextContent` (`type: 'text'`) and falls back to `ThinkingContent`
|
|
11
|
+
* (`type: 'thinking'`) when the text blocks are empty — reasoning models
|
|
12
|
+
* (DeepSeek-R1, Qwen-thinking, etc.) may place the entire response inside
|
|
13
|
+
* thinking blocks, leaving the text portion blank.
|
|
14
|
+
*/
|
|
15
|
+
function extractAssistantText(content) {
|
|
16
|
+
if (!Array.isArray(content)) return "";
|
|
17
|
+
let textParts = "";
|
|
18
|
+
let thinkingParts = "";
|
|
19
|
+
for (const block of content) {
|
|
20
|
+
if (!block || typeof block !== "object") continue;
|
|
21
|
+
const typed = block;
|
|
22
|
+
const blockType = typed.type;
|
|
23
|
+
if (blockType === "text" && typeof typed.text === "string") textParts += typed.text;
|
|
24
|
+
else if (blockType === "thinking") {
|
|
25
|
+
const thinking = typeof typed.thinking === "string" ? typed.thinking : typeof typed.text === "string" ? typed.text : "";
|
|
26
|
+
thinkingParts += thinking;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return textParts.trim() ? textParts : thinkingParts;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Strip markdown code fences (opening AND closing) from raw model output.
|
|
33
|
+
* Handles `` ```json ``, `` ``` ``, and trailing `` ``` `` with optional whitespace.
|
|
34
|
+
*/
|
|
35
|
+
function stripCodeFences(raw) {
|
|
36
|
+
let text = raw.trim();
|
|
37
|
+
const openMatch = text.match(/^`{3,}[^\n]*\n?/);
|
|
38
|
+
if (openMatch) text = text.slice(openMatch[0].length);
|
|
39
|
+
const closeMatch = text.match(/\n?`{3,}\s*$/);
|
|
40
|
+
if (closeMatch) text = text.slice(0, -closeMatch[0].length);
|
|
41
|
+
return text.trim();
|
|
42
|
+
}
|
|
8
43
|
/** Mirrors `hermes_cli/goals.py` — strict judge, JSON-only reply. */
|
|
9
44
|
const JUDGE_SYSTEM_PROMPT = "You are a strict judge evaluating whether an autonomous agent has achieved a user's stated goal. You receive the goal text and the agent's most recent response. Your only job is to decide whether the goal is fully satisfied based on that response.\n\nA goal is DONE only when:\n- The response explicitly confirms the goal was completed, OR\n- The response clearly shows the final deliverable was produced, OR\n- The response explains the goal is unachievable / blocked / needs user input (treat this as DONE with reason describing the block).\n\nOtherwise the goal is NOT done — CONTINUE.\n\nReply ONLY with a single JSON object on one line:\n{\"done\": <true|false>, \"reason\": \"<one-sentence rationale>\"}";
|
|
10
45
|
const JUDGE_USER_PROMPT_TEMPLATE = "Goal:\n{goal}\n\nAgent's most recent response:\n{response}\n\nIs the goal satisfied?";
|
|
@@ -14,6 +49,21 @@ function truncateGoalText(text, limit) {
|
|
|
14
49
|
if (text.length <= limit) return text;
|
|
15
50
|
return text.slice(0, limit) + "… [truncated]";
|
|
16
51
|
}
|
|
52
|
+
async function resolveGoalJudgeApiKey(model) {
|
|
53
|
+
try {
|
|
54
|
+
return await getApiKey(model.provider);
|
|
55
|
+
} catch {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function getAssistantMessageErrorReason(message) {
|
|
60
|
+
if (!message || typeof message !== "object") return null;
|
|
61
|
+
const record = message;
|
|
62
|
+
const stopReason = record.stopReason;
|
|
63
|
+
const errorMessage = typeof record.errorMessage === "string" ? record.errorMessage.trim() : "";
|
|
64
|
+
if (stopReason === "error") return errorMessage || "Judge model call failed.";
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
17
67
|
/** Parse judge JSON — fail-open to **continue** (Hermes semantics). */
|
|
18
68
|
function parseJudgeResponseFailOpen(raw) {
|
|
19
69
|
if (!raw?.trim()) return {
|
|
@@ -21,12 +71,7 @@ function parseJudgeResponseFailOpen(raw) {
|
|
|
21
71
|
reason: JUDGE_REASON_EN.judge_returned_empty,
|
|
22
72
|
parseFailed: true
|
|
23
73
|
};
|
|
24
|
-
|
|
25
|
-
if (text.startsWith("```")) {
|
|
26
|
-
text = text.replace(/^`+/, "");
|
|
27
|
-
const nl = text.indexOf("\n");
|
|
28
|
-
if (nl !== -1) text = text.slice(nl + 1);
|
|
29
|
-
}
|
|
74
|
+
const text = stripCodeFences(raw);
|
|
30
75
|
let data = null;
|
|
31
76
|
try {
|
|
32
77
|
data = JSON.parse(text);
|
|
@@ -98,16 +143,19 @@ async function judgeGoalHermesStyle(goal, lastResponse, judgeModelRef, signal, o
|
|
|
98
143
|
content: `${JUDGE_SYSTEM_PROMPT}\n\n${userContent}`,
|
|
99
144
|
timestamp: Date.now()
|
|
100
145
|
};
|
|
146
|
+
const apiKey = await resolveGoalJudgeApiKey(model);
|
|
101
147
|
const result = await complete(model, { messages: [combinedUser] }, {
|
|
148
|
+
apiKey,
|
|
102
149
|
maxTokens: 200,
|
|
103
150
|
temperature: 0,
|
|
104
151
|
signal: merged
|
|
105
152
|
});
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
153
|
+
if (getAssistantMessageErrorReason(result)) return {
|
|
154
|
+
verdict: "continue",
|
|
155
|
+
reason: b.callFailed,
|
|
156
|
+
parseFailed: false
|
|
157
|
+
};
|
|
158
|
+
const { done, reason, parseFailed } = parseJudgeResponseFailOpen(extractAssistantText(result.content));
|
|
111
159
|
const reasonOut = localizeJudgeReasonText(reason, locale);
|
|
112
160
|
return {
|
|
113
161
|
verdict: done ? "done" : "continue",
|
|
@@ -125,6 +173,6 @@ async function judgeGoalHermesStyle(goal, lastResponse, judgeModelRef, signal, o
|
|
|
125
173
|
}
|
|
126
174
|
}
|
|
127
175
|
//#endregion
|
|
128
|
-
export { DEFAULT_JUDGE_TIMEOUT_MS, JUDGE_SYSTEM_PROMPT, JUDGE_USER_PROMPT_TEMPLATE, judgeGoalHermesStyle, parseJudgeResponseFailOpen, truncateGoalText };
|
|
176
|
+
export { DEFAULT_JUDGE_TIMEOUT_MS, JUDGE_SYSTEM_PROMPT, JUDGE_USER_PROMPT_TEMPLATE, extractAssistantText, getAssistantMessageErrorReason, judgeGoalHermesStyle, parseJudgeResponseFailOpen, resolveGoalJudgeApiKey, stripCodeFences, truncateGoalText };
|
|
129
177
|
|
|
130
178
|
//# sourceMappingURL=judge.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"judge.js","names":[],"sources":["../../../../src/agent/goals/judge.ts"],"sourcesContent":["import type { UserMessage } from '@earendil-works/pi-ai';\nimport { complete } from '@earendil-works/pi-ai';\n\nimport { resolveModel } from '../../providers/index.js';\n\nimport type { GoalUiLocale } from './goal-locale.js';\nimport {\n goalUiLocaleOrFallback,\n judgeFreeformBuiltinMessages,\n JUDGE_REASON_EN,\n judgeResponseLanguageNote,\n localizeJudgeReasonText,\n} from './goal-locale.js';\n\nconst JUDGE_RESPONSE_SNIPPET_CHARS = 4000;\n\n/** Mirrors `hermes_cli/goals.py` — strict judge, JSON-only reply. */\nexport const JUDGE_SYSTEM_PROMPT =\n 'You are a strict judge evaluating whether an autonomous agent has ' +\n \"achieved a user's stated goal. You receive the goal text and the \" +\n \"agent's most recent response. Your only job is to decide whether \" +\n 'the goal is fully satisfied based on that response.\\n\\n' +\n 'A goal is DONE only when:\\n' +\n '- The response explicitly confirms the goal was completed, OR\\n' +\n '- The response clearly shows the final deliverable was produced, OR\\n' +\n '- The response explains the goal is unachievable / blocked / needs ' +\n 'user input (treat this as DONE with reason describing the block).\\n\\n' +\n 'Otherwise the goal is NOT done — CONTINUE.\\n\\n' +\n 'Reply ONLY with a single JSON object on one line:\\n' +\n '{\"done\": <true|false>, \"reason\": \"<one-sentence rationale>\"}';\n\nexport const JUDGE_USER_PROMPT_TEMPLATE =\n 'Goal:\\n{goal}\\n\\n' + \"Agent's most recent response:\\n{response}\\n\\n\" + 'Is the goal satisfied?';\n\nexport const DEFAULT_JUDGE_TIMEOUT_MS = 60_000;\n\nexport function truncateGoalText(text: string, limit: number): string {\n if (!text) return '';\n if (text.length <= limit) return text;\n return text.slice(0, limit) + '… [truncated]';\n}\n\n/** Parse judge JSON — fail-open to **continue** (Hermes semantics). */\nexport function parseJudgeResponseFailOpen(raw: string): {\n done: boolean;\n reason: string;\n parseFailed: boolean;\n} {\n if (!raw?.trim()) {\n return { done: false, reason: JUDGE_REASON_EN.judge_returned_empty, parseFailed: true };\n }\n\n let text = raw.trim();\n if (text.startsWith('```')) {\n text = text.replace(/^`+/, '');\n const nl = text.indexOf('\\n');\n if (nl !== -1) text = text.slice(nl + 1);\n }\n\n let data: Record<string, unknown> | null = null;\n try {\n data = JSON.parse(text) as Record<string, unknown>;\n } catch {\n const start = text.indexOf('{');\n const end = text.lastIndexOf('}');\n if (start !== -1 && end > start) {\n try {\n data = JSON.parse(text.slice(start, end + 1)) as Record<string, unknown>;\n } catch {\n data = null;\n }\n }\n }\n\n if (!data || typeof data !== 'object') {\n return { done: false, reason: JUDGE_REASON_EN.judge_reply_not_json, parseFailed: true };\n }\n\n const doneVal = data.done;\n let done: boolean;\n if (typeof doneVal === 'string') {\n done = ['true', 'yes', '1', 'done'].includes(doneVal.trim().toLowerCase());\n } else {\n done = Boolean(doneVal);\n }\n const reason = typeof data.reason === 'string' ? data.reason.trim() : '';\n return { done, reason: reason || JUDGE_REASON_EN.no_reason_provided, parseFailed: false };\n}\n\nexport type GoalJudgeVerdict = 'done' | 'continue' | 'skipped';\n\n/**\n * Ask the configured model whether the goal is satisfied.\n * Fail-open: any error → `continue` (Hermes — turn budget is the backstop).\n */\nexport async function judgeGoalHermesStyle(\n goal: string,\n lastResponse: string,\n judgeModelRef: string,\n signal?: AbortSignal,\n opts?: { judgeTimeoutMs?: number; uiLocale?: GoalUiLocale },\n): Promise<{ verdict: GoalJudgeVerdict; reason: string; parseFailed: boolean }> {\n const locale = goalUiLocaleOrFallback(opts?.uiLocale);\n const b = judgeFreeformBuiltinMessages(locale);\n\n if (!goal.trim()) {\n return { verdict: 'skipped', reason: b.emptyGoal, parseFailed: false };\n }\n if (!lastResponse.trim()) {\n return { verdict: 'continue', reason: b.emptyResponse, parseFailed: false };\n }\n\n let model: ReturnType<typeof resolveModel>;\n try {\n model = resolveModel(judgeModelRef);\n } catch {\n return { verdict: 'continue', reason: b.noModel, parseFailed: false };\n }\n\n const userContent =\n JUDGE_USER_PROMPT_TEMPLATE.replace('{goal}', truncateGoalText(goal, 2000)).replace(\n '{response}',\n truncateGoalText(lastResponse, JUDGE_RESPONSE_SNIPPET_CHARS),\n ) + judgeResponseLanguageNote(locale);\n\n const timeoutMs =\n typeof opts?.judgeTimeoutMs === 'number' && Number.isFinite(opts.judgeTimeoutMs)\n ? Math.max(5_000, Math.min(120_000, Math.floor(opts.judgeTimeoutMs)))\n : DEFAULT_JUDGE_TIMEOUT_MS;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n const merged = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal;\n\n try {\n const combinedUser: UserMessage = {\n role: 'user',\n content: `${JUDGE_SYSTEM_PROMPT}\\n\\n${userContent}`,\n timestamp: Date.now(),\n };\n\n const result = await complete(\n model,\n {\n messages: [combinedUser],\n },\n { maxTokens: 200, temperature: 0, signal: merged },\n );\n let text = '';\n if (Array.isArray(result.content)) {\n for (const c of result.content) {\n if (c && typeof c === 'object' && (c as { type?: string }).type === 'text') {\n text += String((c as { text?: string }).text || '');\n }\n }\n }\n const { done, reason, parseFailed } = parseJudgeResponseFailOpen(text);\n const reasonOut = localizeJudgeReasonText(reason, locale);\n return { verdict: done ? 'done' : 'continue', reason: reasonOut, parseFailed };\n } catch {\n return { verdict: 'continue', reason: b.callFailed, parseFailed: false };\n } finally {\n clearTimeout(timer);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"judge.js","names":[],"sources":["../../../../src/agent/goals/judge.ts"],"sourcesContent":["import type { UserMessage } from '@earendil-works/pi-ai';\nimport { complete } from '@earendil-works/pi-ai';\n\nimport { getApiKey, resolveModel } from '../../providers/index.js';\n\nimport type { GoalUiLocale } from './goal-locale.js';\nimport {\n goalUiLocaleOrFallback,\n judgeFreeformBuiltinMessages,\n JUDGE_REASON_EN,\n judgeResponseLanguageNote,\n localizeJudgeReasonText,\n} from './goal-locale.js';\n\nconst JUDGE_RESPONSE_SNIPPET_CHARS = 4000;\n\n/**\n * Extract visible text from a pi-ai `AssistantMessage.content` array.\n * Handles `TextContent` (`type: 'text'`) and falls back to `ThinkingContent`\n * (`type: 'thinking'`) when the text blocks are empty — reasoning models\n * (DeepSeek-R1, Qwen-thinking, etc.) may place the entire response inside\n * thinking blocks, leaving the text portion blank.\n */\nexport function extractAssistantText(content: unknown): string {\n if (!Array.isArray(content)) return '';\n\n let textParts = '';\n let thinkingParts = '';\n\n for (const block of content) {\n if (!block || typeof block !== 'object') continue;\n const typed = block as Record<string, unknown>;\n const blockType = typed.type;\n if (blockType === 'text' && typeof typed.text === 'string') {\n textParts += typed.text;\n } else if (blockType === 'thinking') {\n const thinking =\n typeof typed.thinking === 'string'\n ? typed.thinking\n : typeof typed.text === 'string'\n ? typed.text\n : '';\n thinkingParts += thinking;\n }\n }\n\n // Prefer text blocks; fall back to thinking blocks when text is empty.\n return textParts.trim() ? textParts : thinkingParts;\n}\n\n/**\n * Strip markdown code fences (opening AND closing) from raw model output.\n * Handles `` ```json ``, `` ``` ``, and trailing `` ``` `` with optional whitespace.\n */\nexport function stripCodeFences(raw: string): string {\n let text = raw.trim();\n\n // Remove opening code fence: ```<optional-lang>\\n\n const openMatch = text.match(/^`{3,}[^\\n]*\\n?/);\n if (openMatch) {\n text = text.slice(openMatch[0].length);\n }\n\n // Remove closing code fence: \\n```<optional-whitespace>\n const closeMatch = text.match(/\\n?`{3,}\\s*$/);\n if (closeMatch) {\n text = text.slice(0, -closeMatch[0].length);\n }\n\n return text.trim();\n}\n\n/** Mirrors `hermes_cli/goals.py` — strict judge, JSON-only reply. */\nexport const JUDGE_SYSTEM_PROMPT =\n 'You are a strict judge evaluating whether an autonomous agent has ' +\n \"achieved a user's stated goal. You receive the goal text and the \" +\n \"agent's most recent response. Your only job is to decide whether \" +\n 'the goal is fully satisfied based on that response.\\n\\n' +\n 'A goal is DONE only when:\\n' +\n '- The response explicitly confirms the goal was completed, OR\\n' +\n '- The response clearly shows the final deliverable was produced, OR\\n' +\n '- The response explains the goal is unachievable / blocked / needs ' +\n 'user input (treat this as DONE with reason describing the block).\\n\\n' +\n 'Otherwise the goal is NOT done — CONTINUE.\\n\\n' +\n 'Reply ONLY with a single JSON object on one line:\\n' +\n '{\"done\": <true|false>, \"reason\": \"<one-sentence rationale>\"}';\n\nexport const JUDGE_USER_PROMPT_TEMPLATE =\n 'Goal:\\n{goal}\\n\\n' + \"Agent's most recent response:\\n{response}\\n\\n\" + 'Is the goal satisfied?';\n\nexport const DEFAULT_JUDGE_TIMEOUT_MS = 60_000;\n\nexport function truncateGoalText(text: string, limit: number): string {\n if (!text) return '';\n if (text.length <= limit) return text;\n return text.slice(0, limit) + '… [truncated]';\n}\n\nexport async function resolveGoalJudgeApiKey(\n model: ReturnType<typeof resolveModel>,\n): Promise<string | undefined> {\n try {\n return await getApiKey(model.provider);\n } catch {\n return undefined;\n }\n}\n\nexport function getAssistantMessageErrorReason(message: unknown): string | null {\n if (!message || typeof message !== 'object') return null;\n\n const record = message as Record<string, unknown>;\n const stopReason = record.stopReason;\n const errorMessage = typeof record.errorMessage === 'string' ? record.errorMessage.trim() : '';\n\n if (stopReason === 'error') {\n return errorMessage || 'Judge model call failed.';\n }\n\n return null;\n}\n\n/** Parse judge JSON — fail-open to **continue** (Hermes semantics). */\nexport function parseJudgeResponseFailOpen(raw: string): {\n done: boolean;\n reason: string;\n parseFailed: boolean;\n} {\n if (!raw?.trim()) {\n return { done: false, reason: JUDGE_REASON_EN.judge_returned_empty, parseFailed: true };\n }\n\n const text = stripCodeFences(raw);\n\n let data: Record<string, unknown> | null = null;\n try {\n data = JSON.parse(text) as Record<string, unknown>;\n } catch {\n const start = text.indexOf('{');\n const end = text.lastIndexOf('}');\n if (start !== -1 && end > start) {\n try {\n data = JSON.parse(text.slice(start, end + 1)) as Record<string, unknown>;\n } catch {\n data = null;\n }\n }\n }\n\n if (!data || typeof data !== 'object') {\n return { done: false, reason: JUDGE_REASON_EN.judge_reply_not_json, parseFailed: true };\n }\n\n const doneVal = data.done;\n let done: boolean;\n if (typeof doneVal === 'string') {\n done = ['true', 'yes', '1', 'done'].includes(doneVal.trim().toLowerCase());\n } else {\n done = Boolean(doneVal);\n }\n const reason = typeof data.reason === 'string' ? data.reason.trim() : '';\n return { done, reason: reason || JUDGE_REASON_EN.no_reason_provided, parseFailed: false };\n}\n\nexport type GoalJudgeVerdict = 'done' | 'continue' | 'skipped';\n\n/**\n * Ask the configured model whether the goal is satisfied.\n * Fail-open: any error → `continue` (Hermes — turn budget is the backstop).\n */\nexport async function judgeGoalHermesStyle(\n goal: string,\n lastResponse: string,\n judgeModelRef: string,\n signal?: AbortSignal,\n opts?: { judgeTimeoutMs?: number; uiLocale?: GoalUiLocale },\n): Promise<{ verdict: GoalJudgeVerdict; reason: string; parseFailed: boolean }> {\n const locale = goalUiLocaleOrFallback(opts?.uiLocale);\n const b = judgeFreeformBuiltinMessages(locale);\n\n if (!goal.trim()) {\n return { verdict: 'skipped', reason: b.emptyGoal, parseFailed: false };\n }\n if (!lastResponse.trim()) {\n return { verdict: 'continue', reason: b.emptyResponse, parseFailed: false };\n }\n\n let model: ReturnType<typeof resolveModel>;\n try {\n model = resolveModel(judgeModelRef);\n } catch {\n return { verdict: 'continue', reason: b.noModel, parseFailed: false };\n }\n\n const userContent =\n JUDGE_USER_PROMPT_TEMPLATE.replace('{goal}', truncateGoalText(goal, 2000)).replace(\n '{response}',\n truncateGoalText(lastResponse, JUDGE_RESPONSE_SNIPPET_CHARS),\n ) + judgeResponseLanguageNote(locale);\n\n const timeoutMs =\n typeof opts?.judgeTimeoutMs === 'number' && Number.isFinite(opts.judgeTimeoutMs)\n ? Math.max(5_000, Math.min(120_000, Math.floor(opts.judgeTimeoutMs)))\n : DEFAULT_JUDGE_TIMEOUT_MS;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n const merged = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal;\n\n try {\n const combinedUser: UserMessage = {\n role: 'user',\n content: `${JUDGE_SYSTEM_PROMPT}\\n\\n${userContent}`,\n timestamp: Date.now(),\n };\n\n const apiKey = await resolveGoalJudgeApiKey(model);\n const result = await complete(\n model,\n {\n messages: [combinedUser],\n },\n { apiKey, maxTokens: 200, temperature: 0, signal: merged },\n );\n const errorReason = getAssistantMessageErrorReason(result);\n if (errorReason) {\n return { verdict: 'continue', reason: b.callFailed, parseFailed: false };\n }\n\n const text = extractAssistantText(result.content);\n const { done, reason, parseFailed } = parseJudgeResponseFailOpen(text);\n const reasonOut = localizeJudgeReasonText(reason, locale);\n return { verdict: done ? 'done' : 'continue', reason: reasonOut, parseFailed };\n } catch {\n return { verdict: 'continue', reason: b.callFailed, parseFailed: false };\n } finally {\n clearTimeout(timer);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { getAgentDefaultModelRef, init_schema } from "../../config/schema.js";
|
|
2
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
3
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
|
+
import { getAgentDefaultModelRef, init_schema } from "../../config/schema.js";
|
|
4
4
|
import { PERSISTENT_GOAL_CUSTOM_KEY, mergeCustomDataPatch, readPersistentGoal, serializePersistentGoal } from "./state.js";
|
|
5
5
|
import { resolveGoalUiLocale } from "./goal-locale.js";
|
|
6
6
|
import { evaluateAfterTurnHermesLike } from "./evaluate-turn.js";
|
|
@@ -31,6 +31,13 @@ export declare function serializePersistentGoal(s: PersistentGoalState): Record<
|
|
|
31
31
|
export declare function renderChecklistPlain(items: GoalChecklistItem[]): string;
|
|
32
32
|
/** Numbered checklist for judge user prompts (1-based indices). */
|
|
33
33
|
export declare function renderChecklistNumbered(items: GoalChecklistItem[]): string;
|
|
34
|
+
/**
|
|
35
|
+
* After LLM decomposition, keep existing checklist rows (e.g. user-added acceptance criteria)
|
|
36
|
+
* and append judge-generated items, skipping duplicate text (case-insensitive trim).
|
|
37
|
+
*/
|
|
38
|
+
export declare function mergeDecomposedChecklistItems(existing: GoalChecklistItem[], decomposedTexts: {
|
|
39
|
+
text: string;
|
|
40
|
+
}[]): GoalChecklistItem[];
|
|
34
41
|
export declare function applyJudgeChecklistUpdates(items: GoalChecklistItem[], parsed: {
|
|
35
42
|
updates: {
|
|
36
43
|
index: number;
|
|
@@ -117,6 +117,29 @@ function renderChecklistNumbered(items) {
|
|
|
117
117
|
}
|
|
118
118
|
return lines.join("\n");
|
|
119
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* After LLM decomposition, keep existing checklist rows (e.g. user-added acceptance criteria)
|
|
122
|
+
* and append judge-generated items, skipping duplicate text (case-insensitive trim).
|
|
123
|
+
*/
|
|
124
|
+
function mergeDecomposedChecklistItems(existing, decomposedTexts) {
|
|
125
|
+
const now = Date.now();
|
|
126
|
+
const next = existing.map((it) => ({ ...it }));
|
|
127
|
+
const seen = new Set(next.map((it) => it.text.trim().toLowerCase()));
|
|
128
|
+
for (const row of decomposedTexts) {
|
|
129
|
+
const t = row.text.trim();
|
|
130
|
+
if (!t) continue;
|
|
131
|
+
const key = t.toLowerCase();
|
|
132
|
+
if (seen.has(key)) continue;
|
|
133
|
+
seen.add(key);
|
|
134
|
+
next.push({
|
|
135
|
+
text: t,
|
|
136
|
+
status: CHECKLIST_ITEM_PENDING,
|
|
137
|
+
addedBy: "judge",
|
|
138
|
+
addedAt: now
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
return next;
|
|
142
|
+
}
|
|
120
143
|
function applyJudgeChecklistUpdates(items, parsed) {
|
|
121
144
|
const next = items.map((it) => ({ ...it }));
|
|
122
145
|
const now = Date.now();
|
|
@@ -149,6 +172,6 @@ function mergeCustomDataPatch(existingCustom, patch) {
|
|
|
149
172
|
};
|
|
150
173
|
}
|
|
151
174
|
//#endregion
|
|
152
|
-
export { PERSISTENT_GOAL_CUSTOM_KEY, applyJudgeChecklistUpdates, defaultMaxTurns, mergeCustomDataPatch, readPersistentGoal, renderChecklistNumbered, renderChecklistPlain, serializePersistentGoal };
|
|
175
|
+
export { PERSISTENT_GOAL_CUSTOM_KEY, applyJudgeChecklistUpdates, defaultMaxTurns, mergeCustomDataPatch, mergeDecomposedChecklistItems, readPersistentGoal, renderChecklistNumbered, renderChecklistPlain, serializePersistentGoal };
|
|
153
176
|
|
|
154
177
|
//# sourceMappingURL=state.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","names":[],"sources":["../../../../src/agent/goals/state.ts"],"sourcesContent":["import {\n CHECKLIST_ITEM_PENDING,\n TERMINAL_CHECKLIST_STATUSES,\n type ChecklistItemAddedBy,\n type ChecklistItemStatus,\n type GoalChecklistItem,\n} from './checklist-types.js';\n\nimport type { GoalUiLocale } from './goal-locale.js';\n\n/** Persisted under `SessionMetadata.customData.persistentGoal`. */\nexport const PERSISTENT_GOAL_CUSTOM_KEY = 'persistentGoal';\n\nexport type PersistentGoalStatus = 'active' | 'paused' | 'done' | 'cleared';\n\nexport interface PersistentGoalState {\n goal: string;\n status: PersistentGoalStatus;\n turnsUsed: number;\n maxTurns: number;\n createdAt: number;\n lastTurnAt: number;\n lastVerdict?: 'done' | 'continue' | 'skipped' | 'decompose';\n lastReason?: string;\n pausedReason?: string;\n judgeModelRef?: string;\n /** Hermes-style: judge JSON parse failures in a row (API errors do not increment). */\n consecutiveParseFailures?: number;\n /** After first successful decomposition, checklist drives Phase-B judging. */\n decomposed?: boolean;\n checklist?: GoalChecklistItem[];\n /** Gateway console language: drives judge `reason` language and system messages. */\n uiLocale?: GoalUiLocale;\n}\n\nexport function defaultMaxTurns(cfg: { maxTurns?: number } | undefined): number {\n const n = cfg?.maxTurns;\n if (typeof n === 'number' && Number.isFinite(n)) {\n return Math.max(1, Math.min(500, Math.floor(n)));\n }\n return 20;\n}\n\nfunction coerceStatus(s: unknown): PersistentGoalStatus | undefined {\n if (s === 'active' || s === 'paused' || s === 'done' || s === 'cleared') return s;\n return undefined;\n}\n\nfunction coerceChecklistItem(raw: unknown): GoalChecklistItem | null {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return null;\n const r = raw as Record<string, unknown>;\n const text = typeof r.text === 'string' ? r.text.trim() : '';\n if (!text) return null;\n const st = typeof r.status === 'string' ? r.status.trim().toLowerCase() : '';\n const status: ChecklistItemStatus =\n st === 'completed' || st === 'impossible' || st === 'pending' ? st : CHECKLIST_ITEM_PENDING;\n const ab = typeof r.addedBy === 'string' ? r.addedBy.trim().toLowerCase() : '';\n const addedBy: ChecklistItemAddedBy = ab === 'user' ? 'user' : 'judge';\n const addedAt =\n typeof r.addedAt === 'number' && Number.isFinite(r.addedAt) ? Math.floor(r.addedAt) : Date.now();\n const completedAt =\n typeof r.completedAt === 'number' && Number.isFinite(r.completedAt) ? Math.floor(r.completedAt) : undefined;\n const evidence = typeof r.evidence === 'string' ? r.evidence : undefined;\n return { text, status, addedBy, addedAt, completedAt, evidence };\n}\n\nexport function readPersistentGoal(customData: Record<string, unknown> | undefined): PersistentGoalState | null {\n if (!customData || typeof customData !== 'object') return null;\n\n const raw = customData[PERSISTENT_GOAL_CUSTOM_KEY];\n if (raw && typeof raw === 'object' && !Array.isArray(raw)) {\n const o = raw as Record<string, unknown>;\n const goal = typeof o.goal === 'string' ? o.goal.trim() : '';\n if (!goal) return null;\n const status = coerceStatus(o.status) ?? 'active';\n const maxTurns =\n typeof o.maxTurns === 'number' && Number.isFinite(o.maxTurns)\n ? Math.max(1, Math.min(500, Math.floor(o.maxTurns)))\n : 20;\n const turnsUsed =\n typeof o.turnsUsed === 'number' && Number.isFinite(o.turnsUsed)\n ? Math.max(0, Math.floor(o.turnsUsed))\n : 0;\n const createdAt =\n typeof o.createdAt === 'number' && Number.isFinite(o.createdAt) ? o.createdAt : Date.now();\n const lastTurnAt =\n typeof o.lastTurnAt === 'number' && Number.isFinite(o.lastTurnAt) ? o.lastTurnAt : 0;\n const lastVerdict =\n o.lastVerdict === 'done' ||\n o.lastVerdict === 'continue' ||\n o.lastVerdict === 'skipped' ||\n o.lastVerdict === 'decompose'\n ? o.lastVerdict\n : undefined;\n const lastReason = typeof o.lastReason === 'string' ? o.lastReason : undefined;\n const pausedReason = typeof o.pausedReason === 'string' ? o.pausedReason : undefined;\n const judgeModelRef = typeof o.judgeModelRef === 'string' ? o.judgeModelRef.trim() : undefined;\n const consecutiveParseFailures =\n typeof o.consecutiveParseFailures === 'number' && Number.isFinite(o.consecutiveParseFailures)\n ? Math.max(0, Math.floor(o.consecutiveParseFailures))\n : 0;\n const decomposed = Boolean(o.decomposed);\n const uiLocale = o.uiLocale === 'zh' || o.uiLocale === 'en' ? o.uiLocale : undefined;\n const checklistRaw = o.checklist;\n const checklist: GoalChecklistItem[] = [];\n if (Array.isArray(checklistRaw)) {\n for (const row of checklistRaw) {\n const it = coerceChecklistItem(row);\n if (it) checklist.push(it);\n }\n }\n return {\n goal,\n status,\n turnsUsed,\n maxTurns,\n createdAt,\n lastTurnAt,\n lastVerdict,\n lastReason,\n pausedReason,\n judgeModelRef: judgeModelRef || undefined,\n consecutiveParseFailures,\n decomposed: decomposed || undefined,\n checklist: checklist.length ? checklist : undefined,\n uiLocale,\n };\n }\n\n return null;\n}\n\nexport function serializePersistentGoal(s: PersistentGoalState): Record<string, unknown> {\n return {\n goal: s.goal,\n status: s.status,\n turnsUsed: s.turnsUsed,\n maxTurns: s.maxTurns,\n createdAt: s.createdAt,\n lastTurnAt: s.lastTurnAt,\n ...(s.lastVerdict ? { lastVerdict: s.lastVerdict } : {}),\n ...(s.lastReason ? { lastReason: s.lastReason } : {}),\n ...(s.pausedReason ? { pausedReason: s.pausedReason } : {}),\n ...(s.judgeModelRef ? { judgeModelRef: s.judgeModelRef } : {}),\n ...(s.consecutiveParseFailures ? { consecutiveParseFailures: s.consecutiveParseFailures } : {}),\n ...(s.decomposed ? { decomposed: true } : {}),\n ...(s.uiLocale ? { uiLocale: s.uiLocale } : {}),\n ...(s.checklist?.length\n ? {\n checklist: s.checklist.map((it) => ({\n text: it.text,\n status: it.status,\n addedBy: it.addedBy,\n addedAt: it.addedAt,\n ...(it.completedAt !== undefined ? { completedAt: it.completedAt } : {}),\n ...(it.evidence ? { evidence: it.evidence } : {}),\n })),\n }\n : {}),\n };\n}\n\n/** Render checklist for continuation prompt (Hermes-style, no numbers in body). */\nexport function renderChecklistPlain(items: GoalChecklistItem[]): string {\n if (!items.length) return '(empty)';\n const lines: string[] = [];\n for (const it of items) {\n const marker =\n it.status === 'completed' ? '[x]' : it.status === 'impossible' ? '[!]' : '[ ]';\n let line = `${marker} ${it.text}`;\n if (it.status === 'impossible' && it.evidence) line += ` (impossible: ${it.evidence})`;\n lines.push(line);\n }\n return lines.join('\\n');\n}\n\n/** Numbered checklist for judge user prompts (1-based indices). */\nexport function renderChecklistNumbered(items: GoalChecklistItem[]): string {\n if (!items.length) return '(empty)';\n const lines: string[] = [];\n for (let i = 0; i < items.length; i++) {\n const it = items[i]!;\n const n = i + 1;\n const marker =\n it.status === 'completed' ? '[x]' : it.status === 'impossible' ? '[!]' : '[ ]';\n let line = `${n}. ${marker} ${it.text}`;\n if (it.status === 'impossible' && it.evidence) line += ` (impossible: ${it.evidence})`;\n lines.push(line);\n }\n return lines.join('\\n');\n}\n\nexport function applyJudgeChecklistUpdates(\n items: GoalChecklistItem[],\n parsed: {\n updates: { index: number; status: ChecklistItemStatus; evidence?: string | null }[];\n newItems: { text: string }[];\n },\n): GoalChecklistItem[] {\n const next = items.map((it) => ({ ...it }));\n const now = Date.now();\n for (const upd of parsed.updates) {\n const idx = upd.index;\n if (idx < 0 || idx >= next.length) continue;\n const item = next[idx]!;\n if (TERMINAL_CHECKLIST_STATUSES.has(item.status)) continue;\n if (!TERMINAL_CHECKLIST_STATUSES.has(upd.status)) continue;\n item.status = upd.status;\n item.completedAt = now;\n if (upd.evidence?.trim()) item.evidence = upd.evidence.trim();\n }\n for (const ni of parsed.newItems) {\n const t = ni.text.trim();\n if (!t) continue;\n next.push({\n text: t,\n status: CHECKLIST_ITEM_PENDING,\n addedBy: 'judge',\n addedAt: now,\n });\n }\n return next;\n}\n\n\nexport function mergeCustomDataPatch(\n existingCustom: Record<string, unknown> | undefined,\n patch: Record<string, unknown>,\n): Record<string, unknown> {\n return { ...(existingCustom ?? {}), ...patch };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"state.js","names":[],"sources":["../../../../src/agent/goals/state.ts"],"sourcesContent":["import {\n CHECKLIST_ITEM_PENDING,\n TERMINAL_CHECKLIST_STATUSES,\n type ChecklistItemAddedBy,\n type ChecklistItemStatus,\n type GoalChecklistItem,\n} from './checklist-types.js';\n\nimport type { GoalUiLocale } from './goal-locale.js';\n\n/** Persisted under `SessionMetadata.customData.persistentGoal`. */\nexport const PERSISTENT_GOAL_CUSTOM_KEY = 'persistentGoal';\n\nexport type PersistentGoalStatus = 'active' | 'paused' | 'done' | 'cleared';\n\nexport interface PersistentGoalState {\n goal: string;\n status: PersistentGoalStatus;\n turnsUsed: number;\n maxTurns: number;\n createdAt: number;\n lastTurnAt: number;\n lastVerdict?: 'done' | 'continue' | 'skipped' | 'decompose';\n lastReason?: string;\n pausedReason?: string;\n judgeModelRef?: string;\n /** Hermes-style: judge JSON parse failures in a row (API errors do not increment). */\n consecutiveParseFailures?: number;\n /** After first successful decomposition, checklist drives Phase-B judging. */\n decomposed?: boolean;\n checklist?: GoalChecklistItem[];\n /** Gateway console language: drives judge `reason` language and system messages. */\n uiLocale?: GoalUiLocale;\n}\n\nexport function defaultMaxTurns(cfg: { maxTurns?: number } | undefined): number {\n const n = cfg?.maxTurns;\n if (typeof n === 'number' && Number.isFinite(n)) {\n return Math.max(1, Math.min(500, Math.floor(n)));\n }\n return 20;\n}\n\nfunction coerceStatus(s: unknown): PersistentGoalStatus | undefined {\n if (s === 'active' || s === 'paused' || s === 'done' || s === 'cleared') return s;\n return undefined;\n}\n\nfunction coerceChecklistItem(raw: unknown): GoalChecklistItem | null {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return null;\n const r = raw as Record<string, unknown>;\n const text = typeof r.text === 'string' ? r.text.trim() : '';\n if (!text) return null;\n const st = typeof r.status === 'string' ? r.status.trim().toLowerCase() : '';\n const status: ChecklistItemStatus =\n st === 'completed' || st === 'impossible' || st === 'pending' ? st : CHECKLIST_ITEM_PENDING;\n const ab = typeof r.addedBy === 'string' ? r.addedBy.trim().toLowerCase() : '';\n const addedBy: ChecklistItemAddedBy = ab === 'user' ? 'user' : 'judge';\n const addedAt =\n typeof r.addedAt === 'number' && Number.isFinite(r.addedAt) ? Math.floor(r.addedAt) : Date.now();\n const completedAt =\n typeof r.completedAt === 'number' && Number.isFinite(r.completedAt) ? Math.floor(r.completedAt) : undefined;\n const evidence = typeof r.evidence === 'string' ? r.evidence : undefined;\n return { text, status, addedBy, addedAt, completedAt, evidence };\n}\n\nexport function readPersistentGoal(customData: Record<string, unknown> | undefined): PersistentGoalState | null {\n if (!customData || typeof customData !== 'object') return null;\n\n const raw = customData[PERSISTENT_GOAL_CUSTOM_KEY];\n if (raw && typeof raw === 'object' && !Array.isArray(raw)) {\n const o = raw as Record<string, unknown>;\n const goal = typeof o.goal === 'string' ? o.goal.trim() : '';\n if (!goal) return null;\n const status = coerceStatus(o.status) ?? 'active';\n const maxTurns =\n typeof o.maxTurns === 'number' && Number.isFinite(o.maxTurns)\n ? Math.max(1, Math.min(500, Math.floor(o.maxTurns)))\n : 20;\n const turnsUsed =\n typeof o.turnsUsed === 'number' && Number.isFinite(o.turnsUsed)\n ? Math.max(0, Math.floor(o.turnsUsed))\n : 0;\n const createdAt =\n typeof o.createdAt === 'number' && Number.isFinite(o.createdAt) ? o.createdAt : Date.now();\n const lastTurnAt =\n typeof o.lastTurnAt === 'number' && Number.isFinite(o.lastTurnAt) ? o.lastTurnAt : 0;\n const lastVerdict =\n o.lastVerdict === 'done' ||\n o.lastVerdict === 'continue' ||\n o.lastVerdict === 'skipped' ||\n o.lastVerdict === 'decompose'\n ? o.lastVerdict\n : undefined;\n const lastReason = typeof o.lastReason === 'string' ? o.lastReason : undefined;\n const pausedReason = typeof o.pausedReason === 'string' ? o.pausedReason : undefined;\n const judgeModelRef = typeof o.judgeModelRef === 'string' ? o.judgeModelRef.trim() : undefined;\n const consecutiveParseFailures =\n typeof o.consecutiveParseFailures === 'number' && Number.isFinite(o.consecutiveParseFailures)\n ? Math.max(0, Math.floor(o.consecutiveParseFailures))\n : 0;\n const decomposed = Boolean(o.decomposed);\n const uiLocale = o.uiLocale === 'zh' || o.uiLocale === 'en' ? o.uiLocale : undefined;\n const checklistRaw = o.checklist;\n const checklist: GoalChecklistItem[] = [];\n if (Array.isArray(checklistRaw)) {\n for (const row of checklistRaw) {\n const it = coerceChecklistItem(row);\n if (it) checklist.push(it);\n }\n }\n return {\n goal,\n status,\n turnsUsed,\n maxTurns,\n createdAt,\n lastTurnAt,\n lastVerdict,\n lastReason,\n pausedReason,\n judgeModelRef: judgeModelRef || undefined,\n consecutiveParseFailures,\n decomposed: decomposed || undefined,\n checklist: checklist.length ? checklist : undefined,\n uiLocale,\n };\n }\n\n return null;\n}\n\nexport function serializePersistentGoal(s: PersistentGoalState): Record<string, unknown> {\n return {\n goal: s.goal,\n status: s.status,\n turnsUsed: s.turnsUsed,\n maxTurns: s.maxTurns,\n createdAt: s.createdAt,\n lastTurnAt: s.lastTurnAt,\n ...(s.lastVerdict ? { lastVerdict: s.lastVerdict } : {}),\n ...(s.lastReason ? { lastReason: s.lastReason } : {}),\n ...(s.pausedReason ? { pausedReason: s.pausedReason } : {}),\n ...(s.judgeModelRef ? { judgeModelRef: s.judgeModelRef } : {}),\n ...(s.consecutiveParseFailures ? { consecutiveParseFailures: s.consecutiveParseFailures } : {}),\n ...(s.decomposed ? { decomposed: true } : {}),\n ...(s.uiLocale ? { uiLocale: s.uiLocale } : {}),\n ...(s.checklist?.length\n ? {\n checklist: s.checklist.map((it) => ({\n text: it.text,\n status: it.status,\n addedBy: it.addedBy,\n addedAt: it.addedAt,\n ...(it.completedAt !== undefined ? { completedAt: it.completedAt } : {}),\n ...(it.evidence ? { evidence: it.evidence } : {}),\n })),\n }\n : {}),\n };\n}\n\n/** Render checklist for continuation prompt (Hermes-style, no numbers in body). */\nexport function renderChecklistPlain(items: GoalChecklistItem[]): string {\n if (!items.length) return '(empty)';\n const lines: string[] = [];\n for (const it of items) {\n const marker =\n it.status === 'completed' ? '[x]' : it.status === 'impossible' ? '[!]' : '[ ]';\n let line = `${marker} ${it.text}`;\n if (it.status === 'impossible' && it.evidence) line += ` (impossible: ${it.evidence})`;\n lines.push(line);\n }\n return lines.join('\\n');\n}\n\n/** Numbered checklist for judge user prompts (1-based indices). */\nexport function renderChecklistNumbered(items: GoalChecklistItem[]): string {\n if (!items.length) return '(empty)';\n const lines: string[] = [];\n for (let i = 0; i < items.length; i++) {\n const it = items[i]!;\n const n = i + 1;\n const marker =\n it.status === 'completed' ? '[x]' : it.status === 'impossible' ? '[!]' : '[ ]';\n let line = `${n}. ${marker} ${it.text}`;\n if (it.status === 'impossible' && it.evidence) line += ` (impossible: ${it.evidence})`;\n lines.push(line);\n }\n return lines.join('\\n');\n}\n\n/**\n * After LLM decomposition, keep existing checklist rows (e.g. user-added acceptance criteria)\n * and append judge-generated items, skipping duplicate text (case-insensitive trim).\n */\nexport function mergeDecomposedChecklistItems(\n existing: GoalChecklistItem[],\n decomposedTexts: { text: string }[],\n): GoalChecklistItem[] {\n const now = Date.now();\n const next = existing.map((it) => ({ ...it }));\n const seen = new Set(next.map((it) => it.text.trim().toLowerCase()));\n for (const row of decomposedTexts) {\n const t = row.text.trim();\n if (!t) continue;\n const key = t.toLowerCase();\n if (seen.has(key)) continue;\n seen.add(key);\n next.push({\n text: t,\n status: CHECKLIST_ITEM_PENDING,\n addedBy: 'judge',\n addedAt: now,\n });\n }\n return next;\n}\n\nexport function applyJudgeChecklistUpdates(\n items: GoalChecklistItem[],\n parsed: {\n updates: { index: number; status: ChecklistItemStatus; evidence?: string | null }[];\n newItems: { text: string }[];\n },\n): GoalChecklistItem[] {\n const next = items.map((it) => ({ ...it }));\n const now = Date.now();\n for (const upd of parsed.updates) {\n const idx = upd.index;\n if (idx < 0 || idx >= next.length) continue;\n const item = next[idx]!;\n if (TERMINAL_CHECKLIST_STATUSES.has(item.status)) continue;\n if (!TERMINAL_CHECKLIST_STATUSES.has(upd.status)) continue;\n item.status = upd.status;\n item.completedAt = now;\n if (upd.evidence?.trim()) item.evidence = upd.evidence.trim();\n }\n for (const ni of parsed.newItems) {\n const t = ni.text.trim();\n if (!t) continue;\n next.push({\n text: t,\n status: CHECKLIST_ITEM_PENDING,\n addedBy: 'judge',\n addedAt: now,\n });\n }\n return next;\n}\n\n\nexport function mergeCustomDataPatch(\n existingCustom: Record<string, unknown> | undefined,\n patch: Record<string, unknown>,\n): Record<string, unknown> {\n return { ...(existingCustom ?? {}), ...patch };\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { checkFileSafety } from "../prompt/safety.js";
|
|
2
2
|
import { decodeDataUrl } from "./image-helpers.js";
|
|
3
|
+
import { promises } from "node:fs";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { homedir } from "node:os";
|
|
5
|
-
import { promises } from "node:fs";
|
|
6
6
|
//#region src/agent/image/load-image-media.ts
|
|
7
7
|
function expandUser(p) {
|
|
8
8
|
if (p.startsWith("~/") || p === "~") return path.join(homedir(), p.slice(1));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { init_agent_scope, resolveDefaultAgentId } from "../agent-scope.js";
|
|
2
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
3
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
|
+
import { init_agent_scope, resolveDefaultAgentId } from "../agent-scope.js";
|
|
4
4
|
import { createResponseMessage, createSignalMessage, createTaskMessage } from "./types.js";
|
|
5
5
|
import { AgentInbox } from "./inbox.js";
|
|
6
6
|
//#region src/agent/ipc/bus.ts
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
|
|
1
2
|
import { createLogger } from "../../utils/logger/index.js";
|
|
2
3
|
import { init_logger } from "../../utils/logger.js";
|
|
3
4
|
import { init_paths, resolveAgentDir } from "../../config/paths.js";
|
|
4
|
-
import {
|
|
5
|
+
import { mkdir, readFile, readdir, rename } from "fs/promises";
|
|
5
6
|
import { join } from "path";
|
|
6
7
|
import { existsSync, watch } from "fs";
|
|
7
|
-
import { mkdir, readFile, readdir, rename } from "fs/promises";
|
|
8
8
|
//#region src/agent/ipc/inbox.ts
|
|
9
9
|
init_write_file_atomic();
|
|
10
10
|
init_logger();
|
|
@@ -2,8 +2,8 @@ import { createLogger } from "../../utils/logger/index.js";
|
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
3
|
import { init_paths, resolveSocketPath } from "../../config/paths.js";
|
|
4
4
|
import { isValidIPCMessage } from "./types.js";
|
|
5
|
-
import { dirname } from "path";
|
|
6
5
|
import { mkdir } from "fs/promises";
|
|
6
|
+
import { dirname } from "path";
|
|
7
7
|
import { Socket, createServer } from "net";
|
|
8
8
|
//#region src/agent/ipc/socket.ts
|
|
9
9
|
init_logger();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { join } from "node:path";
|
|
2
1
|
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
3
2
|
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
4
|
import lockfile from "proper-lockfile";
|
|
5
5
|
//#region src/agent/memory/builtin-memory-store.ts
|
|
6
6
|
/**
|
|
@@ -4,8 +4,8 @@ import { MEMORY_MD_FILENAME } from "./constants.js";
|
|
|
4
4
|
import { clamp01, compareCandidatesByScore, computeCandidateScore, extractPromotionMarkers, isContaminatedSnippet, isExpiredEntry, isoDay, readFileLines, resolveDeepDefaults, sliceRange, snippetHash } from "./utils.js";
|
|
5
5
|
import { loadDreamingStore, saveDreamingStore, withDreamingPromotionLock } from "./short-term-store.js";
|
|
6
6
|
import { emptyDeepPhaseSkipped, writeDreamingDeepLastRun } from "./last-run.js";
|
|
7
|
-
import path from "node:path";
|
|
8
7
|
import fs from "node:fs/promises";
|
|
8
|
+
import path from "node:path";
|
|
9
9
|
//#region src/agent/memory/dreaming/deep-promotion.ts
|
|
10
10
|
init_logger();
|
|
11
11
|
const log = createLogger("Dreaming:Deep");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DREAMING_DIR_RELATIVE, DREAMING_EVENTS_LOG_RELATIVE } from "./constants.js";
|
|
2
|
-
import path from "node:path";
|
|
3
2
|
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
4
|
//#region src/agent/memory/dreaming/events.ts
|
|
5
5
|
/**
|
|
6
6
|
* Append a single event line to `memory/.dreams/events.jsonl`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DREAMING_LAST_RUN_RELATIVE } from "./constants.js";
|
|
2
|
-
import path from "node:path";
|
|
3
2
|
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
4
|
//#region src/agent/memory/dreaming/last-run.ts
|
|
5
5
|
const DREAMING_LAST_RUN_FORMAT_VERSION = 2;
|
|
6
6
|
function isRecord(v) {
|
|
@@ -4,8 +4,8 @@ import { DREAMING_DIR_RELATIVE } from "./constants.js";
|
|
|
4
4
|
import { buildEntryKey, isoDay, normalizeMemoryPath, normalizeSnippetForHash, snippetHash } from "./utils.js";
|
|
5
5
|
import { bumpEntryPhaseSignal, loadDreamingStore, saveDreamingStore } from "./short-term-store.js";
|
|
6
6
|
import "./last-run.js";
|
|
7
|
-
import path from "node:path";
|
|
8
7
|
import fs from "node:fs/promises";
|
|
8
|
+
import path from "node:path";
|
|
9
9
|
//#region src/agent/memory/dreaming/light-sweep.ts
|
|
10
10
|
init_logger();
|
|
11
11
|
const log = createLogger("Dreaming:Light");
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { MEMORY_MD_FILENAME } from "./constants.js";
|
|
2
2
|
import { clamp01, compareCandidatesByScore, computeCandidateScore, extractPromotionMarkers, isContaminatedSnippet, isExpiredEntry, readFileLines, resolveDeepDefaults, sliceRange, snippetHash } from "./utils.js";
|
|
3
3
|
import { loadDreamingStore } from "./short-term-store.js";
|
|
4
|
-
import path from "node:path";
|
|
5
4
|
import fs from "node:fs/promises";
|
|
5
|
+
import path from "node:path";
|
|
6
6
|
//#region src/agent/memory/dreaming/preview.ts
|
|
7
7
|
async function previewDreamingDeepPromotion(params) {
|
|
8
8
|
const cfg = resolveDeepDefaults(params.config);
|
|
@@ -4,8 +4,8 @@ import { DREAMING_DIR_RELATIVE, DREAMS_MD_FILENAME, MS_PER_DAY } from "./constan
|
|
|
4
4
|
import { isoDay } from "./utils.js";
|
|
5
5
|
import { bumpEntryPhaseSignal, loadDreamingStore, saveDreamingStore } from "./short-term-store.js";
|
|
6
6
|
import "./last-run.js";
|
|
7
|
-
import path from "node:path";
|
|
8
7
|
import fs from "node:fs/promises";
|
|
8
|
+
import path from "node:path";
|
|
9
9
|
//#region src/agent/memory/dreaming/rem-patterns.ts
|
|
10
10
|
init_logger();
|
|
11
11
|
const log = createLogger("Dreaming:REM");
|
|
@@ -2,9 +2,9 @@ import { createLogger } from "../../../utils/logger/index.js";
|
|
|
2
2
|
import { init_logger } from "../../../utils/logger.js";
|
|
3
3
|
import { SHORT_TERM_PROMOTION_LOCK_RELATIVE, SHORT_TERM_RECALL_STORE_RELATIVE } from "./constants.js";
|
|
4
4
|
import { buildEntryKey, clamp01, isoDay, normalizeMemoryPath } from "./utils.js";
|
|
5
|
-
import path from "node:path";
|
|
6
5
|
import { createHash, randomUUID } from "node:crypto";
|
|
7
6
|
import fs from "node:fs/promises";
|
|
7
|
+
import path from "node:path";
|
|
8
8
|
//#region src/agent/memory/dreaming/short-term-store.ts
|
|
9
9
|
init_logger();
|
|
10
10
|
const log = createLogger("Dreaming:Store");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DEFAULT_DEEP_CRON, DIVERSITY_WEIGHT, MS_PER_DAY, REINFORCEMENT_WEIGHT } from "./constants.js";
|
|
2
|
-
import path from "node:path";
|
|
3
2
|
import { createHash } from "node:crypto";
|
|
4
3
|
import fs from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
5
|
//#region src/agent/memory/dreaming/utils.ts
|
|
6
6
|
/** Normalize a workspace-relative memory path: forward slashes, no odd ../ escapes at start. */
|
|
7
7
|
function normalizeMemoryPath(rel) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { dirname, join } from "node:path";
|
|
2
1
|
import { readdir, stat } from "node:fs/promises";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
//#region src/agent/memory/plugin-discovery.ts
|
|
5
5
|
async function discoverMemoryPlugins() {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { getAgentDefaultModelRef, init_schema } from "../../config/schema.js";
|
|
2
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
3
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
|
+
import { getAgentDefaultModelRef, init_schema } from "../../config/schema.js";
|
|
4
4
|
import { getAllModels, getDefaultModelSync, init_providers, resolveModel } from "../../providers/index.js";
|
|
5
5
|
import { resolveAgentTurnTimeoutMs, runAgentTurnWithTimeout } from "../orchestration/run-agent-turn-with-timeout.js";
|
|
6
6
|
import { isAssistantTurnAborted, isAssistantTurnFailed, maybeRetryTurnAfterTransientLlmFailure } from "../orchestration/llm-turn-retry.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { resolveStateDir } from "../../config/paths-state.js";
|
|
2
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
3
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
|
+
import { resolveStateDir } from "../../config/paths-state.js";
|
|
4
4
|
import { init_paths } from "../../config/paths.js";
|
|
5
5
|
import { DEFAULT_USER_FILENAME, toWorkspaceBootstrapFile } from "../context/workspace.js";
|
|
6
6
|
import { createSkillConfigManager } from "../skills/config.js";
|
|
@@ -8,8 +8,8 @@ import { selectSkillsVisibleInPrompt } from "../skills/format-skills-prompt.js";
|
|
|
8
8
|
import { buildSystemPrompt } from "./system-prompt.js";
|
|
9
9
|
import { mergeTtsConfigFromAppConfig } from "../../voice/tts/merge-config.js";
|
|
10
10
|
import { buildTtsSystemPromptHint } from "../../voice/tts/directives.js";
|
|
11
|
-
import { join } from "node:path";
|
|
12
11
|
import { existsSync, readFileSync } from "node:fs";
|
|
12
|
+
import { join } from "node:path";
|
|
13
13
|
//#region src/agent/prompt/service-prompt-builder.ts
|
|
14
14
|
/**
|
|
15
15
|
* System Prompt Builder - Builds the complete system prompt
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import { runWithLogContext, updateAsyncLogContext } from "../utils/logger/context.js";
|
|
2
|
+
import { createLogger } from "../utils/logger/index.js";
|
|
3
|
+
import { init_logger } from "../utils/logger.js";
|
|
1
4
|
import { init_agent_scope, resolveAgentBootstrapDir, resolveAgentHomeDir, resolveDefaultAgentId } from "./agent-scope.js";
|
|
2
5
|
import { getAgentDefaultModelRef, init_schema } from "../config/schema.js";
|
|
3
|
-
import { applyConfigOverrides } from "../config/runtime-overrides.js";
|
|
4
6
|
import { init_session_key, parseSessionKey } from "../routing/session-key.js";
|
|
7
|
+
import { applyConfigOverrides } from "../config/runtime-overrides.js";
|
|
5
8
|
import { extractProfileAgentId, resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
|
|
6
|
-
import { runWithLogContext, updateAsyncLogContext } from "../utils/logger/context.js";
|
|
7
|
-
import { createLogger } from "../utils/logger/index.js";
|
|
8
|
-
import { init_logger } from "../utils/logger.js";
|
|
9
9
|
import { extractTextContent, loadBootstrapFiles } from "./context/workspace.js";
|
|
10
10
|
import { AgentManager } from "./agent-manager.js";
|
|
11
11
|
import { MessageBusShutdownError } from "../infra/bus/queue.js";
|
|
@@ -64,9 +64,9 @@ import { maybeEmitWebchatTts } from "./service/webchat-tts.js";
|
|
|
64
64
|
import { runProcessDirect } from "./service/process-direct-one-shot.js";
|
|
65
65
|
import { shouldSilence } from "../heartbeat/tokens.js";
|
|
66
66
|
import { createTypingController } from "./lifecycle/typing.js";
|
|
67
|
-
import { join } from "node:path";
|
|
68
67
|
import { existsSync, readFileSync } from "node:fs";
|
|
69
68
|
import { mkdir } from "node:fs/promises";
|
|
69
|
+
import { join } from "node:path";
|
|
70
70
|
//#region src/agent/service.ts
|
|
71
71
|
init_schema();
|
|
72
72
|
init_logger();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { __toCommonJS } from "../../../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { init_write_file_atomic, writeTextAtomicSync } from "../../infra/write-file-atomic.js";
|
|
2
3
|
import { createLogger } from "../../utils/logger/index.js";
|
|
3
4
|
import { init_logger } from "../../utils/logger.js";
|
|
4
|
-
import { init_write_file_atomic, writeTextAtomicSync } from "../../infra/write-file-atomic.js";
|
|
5
5
|
import { init_installer, installer_exports } from "./installer.js";
|
|
6
6
|
import { join } from "path";
|
|
7
7
|
import { existsSync, readFileSync } from "fs";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { join, relative } from "node:path";
|
|
2
|
-
import { createReadStream, existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
3
1
|
import { createHash } from "node:crypto";
|
|
2
|
+
import { createReadStream, existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
3
|
+
import { join, relative } from "node:path";
|
|
4
4
|
//#region src/agent/skills/hub-hash.ts
|
|
5
5
|
/**
|
|
6
6
|
* Deterministic content hash for a skill directory (for hub lock / drift detection).
|