elanous 0.2.25 → 0.2.27
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/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/chunks/{1454-37fd16f479f5554a.js → 1454-a9c338f5bb556f42.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/{page-9360b1285b2a346e.js → page-a1ce306364f08da9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-07110da72c45e68f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-d2d76d4a7eae91bd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-30007380f2e2a3c1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e5a9302c105725a3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-b93c04b5311c97ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-718a49e86bf25f9c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/{page-44eaad486bc98a45.js → page-20662900d6b4b455.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/control/{page-97fa6cf3d34c7eb9.js → page-f707a509515ac50c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/{page-305cd294e754906e.js → page-6a16a48d1aa6e91f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-fcb06e305f515527.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-6acf5ec4e6c6d1af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/{page-45889e7070d11126.js → page-39f82acf619cca23.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/field/{page-16a2e893f83ae4d0.js → page-7c2c8f81b185f9c0.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ae7aff07e32676bb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/{page-56888bc744e08dac.js → page-482c60c1bc540d0a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-7cb996c1aa08b6f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/{page-952c6ceec6d9de38.js → page-623e08fe4477d606.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/{page-6d0202af568f4c63.js → page-db460cd8aecb8490.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-ff27902d0b11ef4f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/{page-74366ae2693a7d95.js → page-8397a5c6ca569bf4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/{page-4fb6fc34e20c07b7.js → page-1917ea87ea71ab6b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-e9502921f4f01b1f.js → page-25a302273b054fd7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/{not-found-b6169ea2f09cf287.js → not-found-670510eda8b9443f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-d73c3f1e00d93986.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-65caacf54389081e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-4bb7556e2e97a750.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-77e04b4f8762c666.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/{page-b9cc8a10bc6078b4.js → page-15c0a4095baddfba.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/{page-3d3fc73dd187ed52.js → page-4eb96fc7241c2456.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-63e272a4cd3b6634.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/{page-9c04dac0831c2bbb.js → page-0d64ff212dc55d03.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-7f096248993fc2d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-04de9ca6d52a3893.js → page-e47fc72049149a38.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/{page-62527677bbc2fdc4.js → page-f7d808e31e005895.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/{page-9a2e09c4a311764c.js → page-5c2b24b5496dad73.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/{page-bfeb35d69e8b24bb.js → page-76cdb531668b5191.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-e2b63345bba1a11f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/{page-b008aff96be56654.js → page-d376e0c83edc041a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-d6db55fe2c04d128.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-87b88f551f421d8b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/{page-6445ac4cbb8dd869.js → page-dab163b338e3b966.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/{page-852170303c6cd755.js → page-08019efef111ed2e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-0260ffc7eda50db1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/{page-97c7361cc2a19319.js → page-980ce6fe36ad95eb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/{page-20162174b77f96cf.js → page-99c4e6c7345a9156.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/{page-8c6901833f897496.js → page-0ab42e0f05823013.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-ad9220422d20ba33.js +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +13 -13
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +13 -13
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +13 -13
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +13 -13
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +13 -13
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +13 -13
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +13 -13
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +13 -13
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +13 -13
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +13 -13
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +13 -13
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +13 -13
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +13 -13
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +13 -13
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +13 -13
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +13 -13
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +13 -13
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +13 -13
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +13 -13
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +13 -13
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +13 -13
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +13 -13
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +13 -13
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +13 -13
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +13 -13
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +13 -13
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +13 -13
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +13 -13
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +14 -14
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +13 -13
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +13 -13
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +13 -13
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +13 -13
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +13 -13
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +13 -13
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +13 -13
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +13 -13
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +13 -13
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +13 -13
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +13 -13
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +13 -13
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +13 -13
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +13 -13
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +13 -13
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +13 -13
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +13 -13
- package/package.json +1 -1
- package/scripts/ci-typecheck-changed.ts +81 -2
- package/scripts/coord-msg-bridge.ts +209 -0
- package/scripts/coord-post.sh +40 -7
- package/scripts/coord-requests-bridge.ts +10 -5
- package/scripts/expose-rubric-suggest.ts +1 -1
- package/scripts/measure-tsc-affected-roots.ts +10 -1
- package/scripts/release-loop/export-check-node.ts +8 -5
- package/scripts/release-loop/node-verdict.ts +7 -2
- package/src/agent/task-notification.ts +30 -1
- package/src/agent-substrate/review-observation.ts +9 -2
- package/src/agent-substrate/self-review-cli.ts +28 -6
- package/src/boot/daemon-tools/self-implement.ts +72 -4
- package/src/budget/llm-cost.ts +5 -1
- package/src/cli/control-cli.ts +29 -0
- package/src/cli/doctor-cli.ts +90 -8
- package/src/cli/msg-cli.ts +15 -5
- package/src/cli/pr-cli.ts +53 -0
- package/src/cli/pr-land-overlap-evidence.ts +18 -10
- package/src/cli/release-cli.ts +32 -5
- package/src/cli/seat-cli.ts +121 -0
- package/src/cli/self-utterances-cli.ts +140 -0
- package/src/cli/tasks-cli.ts +139 -9
- package/src/context-card/cell.ts +40 -0
- package/src/dashboard/boot-timing.ts +35 -0
- package/src/dashboard/index.ts +86 -24
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +26 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +6 -0
- package/src/debug/log.ts +1 -1
- package/src/domains/release-tool.ts +29 -12
- package/src/domains/surface-events.ts +16 -0
- package/src/elanous-config-dir.ts +2 -2
- package/src/fleet/host-doctor.ts +73 -2
- package/src/graph-runner/runner.ts +3 -1
- package/src/harness/harness-cli-command.ts +46 -4
- package/src/harness/harness-stop.ts +11 -7
- package/src/index.ts +35 -4
- package/src/instance/current.ts +2 -6
- package/src/instance/resolve.ts +5 -6
- package/src/llm/openai-sampling-fields.ts +89 -0
- package/src/llm/runtime-model-family.ts +61 -0
- package/src/llm/zai-coding-plan.ts +27 -1
- package/src/llm.ts +13 -89
- package/src/machines/machine-ledger.ts +31 -3
- package/src/maturity/cli-maturity.ts +13 -3
- package/src/msg/msg-store.ts +69 -7
- package/src/ops/overview-collect.ts +3 -2
- package/src/ops/overview-owner.ts +29 -0
- package/src/plugin-hooks/shell-hook.ts +17 -2
- package/src/plugin-missions/evaluator-runner.ts +18 -2
- package/src/plugins/install/plugin-install.ts +11 -1
- package/src/prompt-enhance/enhance.ts +11 -0
- package/src/release-loop/checklist.ts +41 -4
- package/src/release-loop/feature-store.ts +10 -9
- package/src/seat-loop/seat-loop.ts +5 -1
- package/src/self-dev/draft-sweep.ts +23 -14
- package/src/self-dev/orchestrate.ts +6 -2
- package/src/self-dev/run-supervisor.ts +35 -1
- package/src/self-implement/goal-author.ts +3 -27
- package/src/self-implement/goal-command-execution.ts +26 -0
- package/src/self-implement/orchestrator.ts +2 -1
- package/src/self-implement/pwa-import-graph.ts +194 -7
- package/src/self-implement/self-implement-runtime.ts +126 -21
- package/src/session/index.ts +14 -4
- package/src/session-runtime/index.ts +55 -11
- package/src/task-agent/cover.ts +28 -9
- package/src/task-agent/live-moves.ts +14 -6
- package/src/task-agent/rejudge-on-head.ts +220 -23
- package/src/task-agent/review-result-capture.ts +64 -1
- package/src/task-agent/shadow.ts +137 -22
- package/src/task-agent/task-hand.ts +18 -2
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +1 -0
- package/src/tool-runtime/tool-search-runtime.ts +25 -0
- package/src/tui.ts +20 -1
- package/src/user-config.ts +3 -59
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f08f6529d09ffae1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-f000d54d258f9ef6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-b12149c51f7d04b1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-22f674e7e4c2c9d5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-8888733e40cea6d1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-9717ec6964b92276.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-dea4b795741126fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-35e05d7450461a67.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-b2638013c0bf7dfd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-c44f93a41167536f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-1b810474507f3702.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-6a14333d1b1b3967.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-8c91a9a66c9ec90a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-4e634c5b98fd4e93.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ed3070d637850548.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-128458c8d86fbb5f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-cf0c2b0183991d09.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-89cb33bced824e4a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-814394dcbae789b1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-6a87325c87f09dd2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-087ceeb975ef272b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-05a4b2c9b91034aa.js +0 -1
- /package/apps/pwa/out/_next/static/{dRS6lEhSRRBr1abbzp7fJ → Ev2jivDMTSoEc-5rIXdcy}/_buildManifest.js +0 -0
- /package/apps/pwa/out/_next/static/{dRS6lEhSRRBr1abbzp7fJ → Ev2jivDMTSoEc-5rIXdcy}/_ssgManifest.js +0 -0
package/src/task-agent/shadow.ts
CHANGED
|
@@ -10,17 +10,22 @@
|
|
|
10
10
|
* - 관측: `debug.log('task-agent', 'shadow-move', …)` → `elanous logs --category task-agent`.
|
|
11
11
|
*/
|
|
12
12
|
import { lstatSync, readFileSync, readdirSync, realpathSync } from 'node:fs';
|
|
13
|
+
import { randomUUID } from 'node:crypto';
|
|
13
14
|
import { extname, join, relative, resolve } from 'node:path';
|
|
14
15
|
import { debug } from '../debug/log.js';
|
|
15
|
-
import { readTaskAgentState, readTaskCard, taskAgentStatePath, type CompletionKind, type TaskCard } from './task-hand.js';
|
|
16
|
+
import { readTaskAgentState, readTaskCard, taskAgentStatePath, TASK_CARD_PREFIX, type CompletionKind, type TaskCard } from './task-hand.js';
|
|
16
17
|
import type { SupervisorJobResult, SupervisorStopReason } from '../self-dev/run-supervisor.js';
|
|
17
18
|
import { executeNextAction, type DeliveryKind, type NextAction } from './actions.js';
|
|
18
19
|
import { judgeNextMove, type TaskJudgeInput, type TaskJudgement } from './judge.js';
|
|
19
20
|
import { HARNESS_RUN_ID_ENV } from '../harness/harness-space.js';
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
21
|
+
import { appendRunLedgerEntry, loadRunLedger } from '../self-implement/run-ledger.js';
|
|
22
|
+
import { collectWiringEvidence, readCardRunSnapshot, type WiringEvidenceDeps, type CardRunEvidenceDeps } from './card-evidence.js';
|
|
23
|
+
import { remoteLedgerMirrorDir } from './parent-host.js';
|
|
24
|
+
import { prodInstanceRoot } from '../instance/resolve.js';
|
|
25
|
+
import { liveMoveHistoryEntry, recordLiveMoveHistory } from './live-move-history.js';
|
|
26
|
+
import { updateTaskCard } from './task-hand.js';
|
|
22
27
|
import { capturedSelfReview, captureReviewResults, hasCapturedPass } from './review-result-capture.js';
|
|
23
|
-
import { configuredTaskAgentLiveMoves, defaultPrHead, executeLiveGreenProposal, executeLiveLand, executeLiveReview, type LiveMoveDeps, type LiveMoveResult, type TaskAgentLiveMove } from './live-moves.js';
|
|
28
|
+
import { configuredTaskAgentLiveMoves, defaultPrHead, executeLiveDecisionCard, executeLiveGreenProposal, executeLiveLand, executeLiveReview, type LiveMoveDeps, type LiveMoveResult, type TaskAgentLiveMove } from './live-moves.js';
|
|
24
29
|
|
|
25
30
|
export interface TaskAgentShadowInput {
|
|
26
31
|
runId: string | null;
|
|
@@ -46,6 +51,8 @@ export interface TaskAgentShadowMove {
|
|
|
46
51
|
pr: number | null;
|
|
47
52
|
/** TA-JUDGE-LIVE-SAFE — `taskAgent.liveMoves` 가 이 수를 실제로 했을 때만 실린다(없으면 종전 그대로 그림자). */
|
|
48
53
|
liveMove?: LiveMoveResult;
|
|
54
|
+
/** 원격 카드 결선이 미결일 때 런 원장 대기열 보존 결과. */
|
|
55
|
+
cardBinding?: 'pending' | 'queue-failed';
|
|
49
56
|
}
|
|
50
57
|
|
|
51
58
|
export interface TaskAgentShadowDeps {
|
|
@@ -65,8 +72,12 @@ export interface TaskAgentShadowDeps {
|
|
|
65
72
|
wiring?: Omit<WiringEvidenceDeps, 'card'>;
|
|
66
73
|
/** Process env for the launched-run id (`ELANOUS_RUN_ID`) — test seam; default process.env. */
|
|
67
74
|
env?: NodeJS.ProcessEnv;
|
|
75
|
+
/** Remote pending-move ledger seam; defaults to the run ledger. */
|
|
76
|
+
queueMove?: typeof appendRunLedgerEntry;
|
|
68
77
|
}
|
|
69
78
|
|
|
79
|
+
export const REMOTE_CARD_MOVE_PENDING = 'task-agent-card-move-pending';
|
|
80
|
+
|
|
70
81
|
/** 카드 조회 상태 파일 — 조회 경로 전부가 같은 파일을 본다. */
|
|
71
82
|
function cardStatePath(deps: TaskAgentShadowDeps): string {
|
|
72
83
|
return deps.statePath ?? deps.live?.statePath ?? taskAgentStatePath();
|
|
@@ -175,6 +186,13 @@ function shadowCompletion(card: TaskCard | undefined, lookupFailed: boolean): Co
|
|
|
175
186
|
}
|
|
176
187
|
|
|
177
188
|
export async function recordTaskAgentShadowMove(input: TaskAgentShadowInput, deps: TaskAgentShadowDeps = {}): Promise<TaskAgentShadowMove> {
|
|
189
|
+
const env = deps.env ?? process.env;
|
|
190
|
+
const remoteChild = !!env.ELANOUS_POD_NAME;
|
|
191
|
+
const hintedCard = env.ELANOUS_TASK_CARD_ID?.trim();
|
|
192
|
+
const pendingCardId = hintedCard?.startsWith(TASK_CARD_PREFIX) && hintedCard.length <= 63 && /^[A-Za-z0-9._-]+$/.test(hintedCard) ? hintedCard : null;
|
|
193
|
+
const parentRunId = env.ELANOUS_PARENT_RUN_ID?.trim() || null;
|
|
194
|
+
const matchesLaunchCard = (candidate: TaskCard | undefined): boolean => !!candidate && !!parentRunId
|
|
195
|
+
&& candidate.id === pendingCardId && candidate.runId === parentRunId;
|
|
178
196
|
// TA-REVIEW-RESULT-CAPTURE — 판단 «전»에 지난 live review 의 결과 파일을 회수한다(카드 원장을 아는 때만 · 던지지 않는다).
|
|
179
197
|
// 대기 중인 요청이 없으면 아무것도 쓰지 않는다(결과 파일 없는 카드의 동작은 종전과 같다).
|
|
180
198
|
const reviewLedger = cardLedgerPath(deps);
|
|
@@ -188,14 +206,22 @@ export async function recordTaskAgentShadowMove(input: TaskAgentShadowInput, dep
|
|
|
188
206
|
let card: TaskCard | undefined;
|
|
189
207
|
let cardLookupFailed = false;
|
|
190
208
|
try {
|
|
191
|
-
|
|
192
|
-
if (
|
|
209
|
+
// Pod 에 발사 카드 id 가 있으면 그 id 만 믿는다. 같은 문장을 가진 다른 카드가 있어도 묶지 않는다.
|
|
210
|
+
if (remoteChild) {
|
|
211
|
+
if (pendingCardId) {
|
|
212
|
+
const found = deps.readCard ? deps.readCard(pendingCardId) : readTaskCard(pendingCardId, cardStatePath(deps));
|
|
213
|
+
if (matchesLaunchCard(found)) card = found;
|
|
214
|
+
}
|
|
215
|
+
} else if (successful) {
|
|
216
|
+
card = deps.readCard ? deps.readCard(successful.taskId) : readTaskCard(successful.taskId, cardStatePath(deps));
|
|
217
|
+
}
|
|
218
|
+
if (!card && successful && !deps.readCard && !remoteChild) {
|
|
193
219
|
const tasks = readTaskAgentState<{ tasks?: Record<string, TaskCard> }>(cardStatePath(deps)).tasks ?? {};
|
|
194
220
|
const matches = Object.values(tasks).filter(candidate => candidate.status === 'launched' && candidate.text === successful.feature);
|
|
195
221
|
if (matches.length === 1) card = matches[0];
|
|
196
222
|
}
|
|
197
223
|
// TA-OWN-ALL-RUNS — 런 소유 카드: 입력 runId ⊕ 상속 ELANOUS_RUN_ID(Pod 자식의 부모 런) 중 카드 runId 와 «정확히» 같은 것만.
|
|
198
|
-
if (!card && !deps.readCard) card = runCardFor(input.runId, deps);
|
|
224
|
+
if (!card && !deps.readCard && !remoteChild) card = runCardFor(input.runId, deps);
|
|
199
225
|
} catch {
|
|
200
226
|
// Card lookup is optional; preserve the original PR judgement when unavailable — but mark the completion kind as unmeasured.
|
|
201
227
|
cardLookupFailed = true;
|
|
@@ -209,7 +235,7 @@ export async function recordTaskAgentShadowMove(input: TaskAgentShadowInput, dep
|
|
|
209
235
|
try {
|
|
210
236
|
const reviewedPr = judgeInput.pr;
|
|
211
237
|
const prRun = input.results.find((result) => result.prNumber === reviewedPr);
|
|
212
|
-
const prCard = prRun ? (card && successful?.taskId === prRun.taskId ? card : liveCardFor([prRun], deps, input.runId)) : undefined;
|
|
238
|
+
const prCard = prRun ? (remoteChild ? card : card && successful?.taskId === prRun.taskId ? card : liveCardFor([prRun], deps, input.runId)) : undefined;
|
|
213
239
|
// 회수한 판정은 «리뷰한 머리»의 것이다 — 지금 PR 머리의 결과만 입력으로 쓴다(A 의 pass 로 B 를 land 쪽으로 보내지 않게 ·
|
|
214
240
|
// 여러 머리 결과가 역순으로 회수돼도 지금 머리 것을 고른다). 지금 머리 = 그 런 작업 트리에서 PR 머리 조회 ·
|
|
215
241
|
// 작업 트리가 없으면(Pod) 런이 낸 머리. 못 정하면 쓰지 않는다(종전처럼 review 수 → 새 머리면 새 리뷰).
|
|
@@ -278,20 +304,23 @@ export async function recordTaskAgentShadowMove(input: TaskAgentShadowInput, dep
|
|
|
278
304
|
move.reason = wouldDo ?? judgement.reason;
|
|
279
305
|
move.wouldDo = null;
|
|
280
306
|
}
|
|
281
|
-
const liveKind: TaskAgentLiveMove | null = move.move === 'review' || move.move === 'propose-green' || move.move === 'propose-land' ? move.move : null;
|
|
307
|
+
const liveKind: TaskAgentLiveMove | null = move.move === 'review' || move.move === 'propose-green' || move.move === 'propose-land' || move.move === 'decision-card' ? move.move : null;
|
|
282
308
|
// 판단마다 해석한다 — 허용되지 않은 수를 판단할 때도 모르는 항목 경고가 남게.
|
|
283
309
|
const liveMoves = deps.liveMoves ?? await configuredTaskAgentLiveMoves();
|
|
284
|
-
const live = liveKind !== null && liveMoves.has(liveKind);
|
|
285
310
|
// 카드 id 는 모든 판단 관측에 싣는다(그림자 일치율을 카드로 잇는다) — 읽기 전용 조회.
|
|
286
311
|
// live 수는 «근거 결과»에 묶는다 — PR 수는 그 PR 을 낸 결과의 카드·작업 트리, 전달은 전달한 카드(다중 결과에서 남의 카드에 쓰지 않게).
|
|
287
312
|
const prResult = typeof judgeInput.pr === 'number' ? input.results.find((result) => result.prNumber === judgeInput.pr) : undefined;
|
|
288
|
-
const
|
|
313
|
+
const candidateBoundCard = delivery
|
|
289
314
|
? card
|
|
290
315
|
: prResult
|
|
291
|
-
? (card && successful?.taskId === prResult.taskId ? card : liveCardFor([prResult], deps, input.runId))
|
|
292
|
-
: undefined;
|
|
316
|
+
? (card && (successful?.taskId === prResult.taskId || (remoteChild && pendingCardId === card.id)) ? card : liveCardFor([prResult], deps, input.runId))
|
|
317
|
+
: liveKind === 'decision-card' ? card ?? liveCardFor(input.results, deps, input.runId) : undefined;
|
|
318
|
+
const boundCard = remoteChild && !matchesLaunchCard(candidateBoundCard) ? undefined : candidateBoundCard;
|
|
293
319
|
// PR 에 묶인 수는 그 PR 의 카드만 관측에 싣는다(못 찾으면 null — 다른 결과의 카드로 대체하지 않는다).
|
|
294
|
-
const
|
|
320
|
+
const candidateLiveCard = prResult || delivery ? boundCard : card ?? (cardLookupFailed ? undefined : liveCardFor(input.results, deps, input.runId));
|
|
321
|
+
const liveCard = remoteChild && !matchesLaunchCard(candidateLiveCard) ? undefined : candidateLiveCard;
|
|
322
|
+
// 원격 Pod 는 HQ 카드 파일을 갖지 않는다. id 를 전달받아도 현지 원장이 없으면 실행 수는 보류한다.
|
|
323
|
+
const live = liveKind !== null && liveMoves.has(liveKind) && (!remoteChild || boundCard !== undefined);
|
|
295
324
|
let liveMove: LiveMoveResult | undefined;
|
|
296
325
|
if (live) {
|
|
297
326
|
if (liveKind === 'review') {
|
|
@@ -316,6 +345,17 @@ export async function recordTaskAgentShadowMove(input: TaskAgentShadowInput, dep
|
|
|
316
345
|
...(prResult.prUrl ? { prUrl: prResult.prUrl } : {}),
|
|
317
346
|
} } : {}),
|
|
318
347
|
}, liveMoveDeps(deps));
|
|
348
|
+
} else if (liveKind === 'decision-card') {
|
|
349
|
+
// Supervisor results carry failure text and reviewer must-fix items, but no screen tail.
|
|
350
|
+
// A stop reason alone is not evidence: the executor correctly raises no card when both are absent.
|
|
351
|
+
const evidenceResults = prResult ? [prResult] : input.results;
|
|
352
|
+
const signature = evidenceResults.find((result) => result.error?.message?.trim())?.error?.message;
|
|
353
|
+
const mustFix = evidenceResults.flatMap((result) => result.reviewMustFix ?? []);
|
|
354
|
+
liveMove = await executeLiveDecisionCard(boundCard, {
|
|
355
|
+
runId: input.runId, stopReason: input.stopReason, reason: move.reason,
|
|
356
|
+
...(prResult ? { pr: prResult.prNumber } : {}),
|
|
357
|
+
evidence: { ...(signature ? { signature } : {}), mustFix },
|
|
358
|
+
}, liveMoveDeps(deps));
|
|
319
359
|
} else {
|
|
320
360
|
const evidence: Record<string, string> = {};
|
|
321
361
|
if (boundCard && !delivery && judgeInput.prState === 'MERGED' && prResult) evidence[boundCard.id] = `#${prResult.prNumber}`;
|
|
@@ -323,11 +363,6 @@ export async function recordTaskAgentShadowMove(input: TaskAgentShadowInput, dep
|
|
|
323
363
|
liveMove = executeLiveGreenProposal(boundCard, evidence, liveMoveDeps(deps));
|
|
324
364
|
}
|
|
325
365
|
}
|
|
326
|
-
// 판단한 수마다 live/shadow 를 남긴다 — OP 가 «오판 건수»·«그림자 일치율»을 카드·수 종류로 잰다.
|
|
327
|
-
(deps.log ?? ((category, event, data) => debug.log(category, event, data)))('task-agent', 'shadow-move', {
|
|
328
|
-
...move, completion: shadowCompletion(card, cardLookupFailed), card: liveCard?.id ?? null, live, liveExecuted: liveMove?.executed ?? false, ...(liveMove ? { liveOk: liveMove.ok } : {}),
|
|
329
|
-
...(reviewFromCapture ? { reviewSource: 'captured-review-result' } : {}),
|
|
330
|
-
});
|
|
331
366
|
// TA-WIRING-CHECK — 병합 PR 은 판단한 «뒤» 배선 근거를 관측만 한다(move 불변 · 실패는 unknown 으로 남기고 던지지 않는다).
|
|
332
367
|
if (judgeInput.prState === 'MERGED' && typeof judgeInput.pr === 'number' && !delivery && liveCard) {
|
|
333
368
|
try {
|
|
@@ -339,19 +374,51 @@ export async function recordTaskAgentShadowMove(input: TaskAgentShadowInput, dep
|
|
|
339
374
|
}
|
|
340
375
|
// TA-LIVE-MOVE-CARD-HISTORY — live-move 수(review·propose-green·propose-land)는 실행이든 그림자든 그 카드 history 에 한 줄.
|
|
341
376
|
// 결정·실행이 끝난 «뒤»에 덧붙이기만 한다(반환값·관측 무변경) · 실패는 관측만(live-move 를 막지 않는다).
|
|
342
|
-
if (liveKind !== null) recordLiveMoveOnCard({
|
|
377
|
+
if (liveKind !== null && (liveKind !== 'decision-card' || live) && (!remoteChild || liveCard)) recordLiveMoveOnCard({
|
|
343
378
|
liveKind, live, liveMove, card: live ? boundCard : liveCard, runId: input.runId,
|
|
344
379
|
pr: prResult?.prNumber ?? (typeof judgeInput.pr === 'number' ? judgeInput.pr : undefined),
|
|
345
380
|
shadowDetail: move.wouldDo ?? move.reason,
|
|
346
381
|
}, deps);
|
|
347
|
-
|
|
382
|
+
let cardBinding: TaskAgentShadowMove['cardBinding'];
|
|
383
|
+
if (liveKind !== null && !liveCard && remoteChild) {
|
|
384
|
+
const inheritedRunId = parentRunId || env[HARNESS_RUN_ID_ENV]?.trim() || null;
|
|
385
|
+
const reason = !parentRunId ? 'parent run id absent; HQ binding required'
|
|
386
|
+
: pendingCardId ? 'card id carried but ledger unavailable' : 'card id absent; parent run lookup required';
|
|
387
|
+
try {
|
|
388
|
+
if (!input.runId) throw new Error('runId absent');
|
|
389
|
+
(deps.queueMove ?? appendRunLedgerEntry)({
|
|
390
|
+
timestamp: new Date().toISOString(), runId: input.runId, event: REMOTE_CARD_MOVE_PENDING,
|
|
391
|
+
data: { id: randomUUID(), card: pendingCardId, parentRunId: inheritedRunId, kind: liveKind, pr: move.pr,
|
|
392
|
+
detail: move.wouldDo ?? move.reason, reason, executorResult: 'shadow' },
|
|
393
|
+
});
|
|
394
|
+
cardBinding = 'pending';
|
|
395
|
+
} catch (error) {
|
|
396
|
+
cardBinding = 'queue-failed';
|
|
397
|
+
try {
|
|
398
|
+
(deps.log ?? ((c, e, d) => debug.log(c, e, d)))('task-agent', 'card-binding-queue-failed',
|
|
399
|
+
{ card: pendingCardId, runId: input.runId, parentRunId: inheritedRunId, kind: liveKind, reason: error instanceof Error ? error.message : String(error) });
|
|
400
|
+
} catch { /* queue failure remains visible in the return value */ }
|
|
401
|
+
}
|
|
402
|
+
if (cardBinding === 'pending') try {
|
|
403
|
+
(deps.log ?? ((c, e, d) => debug.log(c, e, d)))('task-agent', 'card-binding-pending',
|
|
404
|
+
{ card: pendingCardId, runId: input.runId, parentRunId: inheritedRunId, kind: liveKind, reason });
|
|
405
|
+
} catch { /* queued evidence remains authoritative */ }
|
|
406
|
+
}
|
|
407
|
+
// 판단 관측은 원격 미결 수를 실제 원장에 기록한 결과까지 확정한 뒤 남긴다.
|
|
408
|
+
(deps.log ?? ((category, event, data) => debug.log(category, event, data)))('task-agent', 'shadow-move', {
|
|
409
|
+
...move, completion: shadowCompletion(card, cardLookupFailed), card: liveCard?.id ?? pendingCardId,
|
|
410
|
+
live, liveExecuted: liveMove?.executed ?? false, ...(liveMove ? { liveOk: liveMove.ok } : {}),
|
|
411
|
+
...(cardBinding ? { cardBinding } : {}),
|
|
412
|
+
...(reviewFromCapture ? { reviewSource: 'captured-review-result' } : {}),
|
|
413
|
+
});
|
|
414
|
+
return { ...move, ...(liveMove ? { liveMove } : {}), ...(cardBinding ? { cardBinding } : {}) };
|
|
348
415
|
}
|
|
349
416
|
|
|
350
417
|
/**
|
|
351
418
|
* 런 id 폴백 — 입력 runId(슈퍼바이저 · Pod 면 자식 런) → 상속 `ELANOUS_RUN_ID`(발사기가 넘긴 부모 런) 순으로,
|
|
352
419
|
* 카드 runId 와 정확히 같고 그 카드가 하나뿐일 때만 쓴다. 못 찾으면 추측하지 않고 이유 한 줄을 남긴다(조용한 미스 0).
|
|
353
420
|
*/
|
|
354
|
-
function runCardFor(runId: string | null | undefined, deps: TaskAgentShadowDeps): TaskCard | undefined {
|
|
421
|
+
export function runCardFor(runId: string | null | undefined, deps: TaskAgentShadowDeps): TaskCard | undefined {
|
|
355
422
|
const own = runId?.trim() || undefined;
|
|
356
423
|
const inherited = (deps.env ?? process.env)[HARNESS_RUN_ID_ENV]?.trim() || undefined;
|
|
357
424
|
if (!own && !inherited) return undefined;
|
|
@@ -370,6 +437,54 @@ function runCardFor(runId: string | null | undefined, deps: TaskAgentShadowDeps)
|
|
|
370
437
|
return undefined;
|
|
371
438
|
}
|
|
372
439
|
|
|
440
|
+
/** HQ `tasks show` 가 원격 원장 거울의 미결 수를 카드에 회수한다. 부모→자식 원장 간선과 카드 id 를 함께 확인한다. */
|
|
441
|
+
export async function replayRemoteCardMoves(cardId: string, statePath: string, evidenceDeps: CardRunEvidenceDeps = {},
|
|
442
|
+
log: (category: string, event: string, data: Record<string, unknown>) => void = (c, e, d) => debug.log(c, e, d)): Promise<number> {
|
|
443
|
+
const card = readTaskCard(cardId, statePath);
|
|
444
|
+
if (!card?.runId || !card.parentHost) return 0;
|
|
445
|
+
// 원격 부모와 동일 runId 의 HQ 국소 원장은 발사 영수증만 있을 수 있다. 이 회수는 원격 거울을 우선한다.
|
|
446
|
+
const loadLedger = evidenceDeps.loadLedger ?? ((runId: string) =>
|
|
447
|
+
loadRunLedger(runId, remoteLedgerMirrorDir(prodInstanceRoot(), card.parentHost!.host)));
|
|
448
|
+
const snapshot = await readCardRunSnapshot(card, { ...evidenceDeps, loadLedger });
|
|
449
|
+
if (snapshot.readErrors?.length) {
|
|
450
|
+
log('task-agent', 'card-binding-replay-failed', { card: cardId, runId: card.runId, reason: snapshot.readErrors.join(' · ') });
|
|
451
|
+
return 0;
|
|
452
|
+
}
|
|
453
|
+
// 카드 id 가 빠진 옛 원격 줄은 부모 runId 의 유일 카드일 때만 역조회한다.
|
|
454
|
+
const matches = Object.values(readTaskAgentState<{ tasks?: Record<string, TaskCard> }>(statePath).tasks ?? {})
|
|
455
|
+
.filter((candidate) => candidate.runId === card.runId);
|
|
456
|
+
let written = 0;
|
|
457
|
+
for (const [childRunId, entries] of Object.entries(snapshot.children)) {
|
|
458
|
+
for (const entry of entries ?? []) {
|
|
459
|
+
if (entry.event !== REMOTE_CARD_MOVE_PENDING) continue;
|
|
460
|
+
const data = entry.data;
|
|
461
|
+
const id = data.id;
|
|
462
|
+
const kind = data.kind;
|
|
463
|
+
const linked = data.card === cardId || (data.card == null && matches.length === 1 && matches[0]?.id === cardId);
|
|
464
|
+
const parentMatches = data.parentRunId == null || data.parentRunId === card.runId;
|
|
465
|
+
if (!linked || !parentMatches || typeof id !== 'string' || !/^[a-f0-9-]{36}$/i.test(id)
|
|
466
|
+
|| !['review', 'propose-green', 'propose-land', 'decision-card'].includes(String(kind))) {
|
|
467
|
+
log('task-agent', 'card-binding-replay-skipped', { card: cardId, childRunId, pendingId: typeof id === 'string' ? id : null,
|
|
468
|
+
reason: !linked ? 'card mismatch or ambiguous runId' : !parentMatches ? 'parent run mismatch' : 'invalid pending move' });
|
|
469
|
+
continue;
|
|
470
|
+
}
|
|
471
|
+
const at = entry.timestamp ?? '';
|
|
472
|
+
if (!Number.isFinite(Date.parse(at))) continue;
|
|
473
|
+
const pr = Number.isSafeInteger(data.pr) && (data.pr as number) > 0 ? data.pr as number : undefined;
|
|
474
|
+
updateTaskCard(statePath, cardId, (current) => {
|
|
475
|
+
if (!current || current.runId !== card.runId || current.history.some((item) => item.sourceId === id)) return undefined;
|
|
476
|
+
const item = liveMoveHistoryEntry(current, { at, kind: kind as TaskAgentLiveMove, executorResult: 'shadow',
|
|
477
|
+
shadowDetail: typeof data.detail === 'string' ? data.detail : 'remote card binding pending', runId: childRunId,
|
|
478
|
+
...(pr ? { pr } : {}) });
|
|
479
|
+
written++;
|
|
480
|
+
return { ...current, history: [...current.history, { ...item, sourceId: id }] };
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
if (written) log('task-agent', 'card-binding-replayed', { card: cardId, parentRunId: card.runId, written });
|
|
485
|
+
return written;
|
|
486
|
+
}
|
|
487
|
+
|
|
373
488
|
/**
|
|
374
489
|
* 카드 history 에 live-move 한 줄 — 상태 파일은 카드를 읽은 곳과 같아야 한다: 주입한 경로(`live.statePath`) 또는
|
|
375
490
|
* 기본 리더를 썼을 때의 기본 경로. 주입한 카드 리더(`readCard`)만 있고 경로가 없으면 그 카드의 원장을 모른다 — 적지 않는다.
|
|
@@ -18,6 +18,7 @@ import { effectiveInstanceRoot } from '../instance/resolve.js';
|
|
|
18
18
|
import { withFileLockSync } from '../storage/file-lock.js';
|
|
19
19
|
import { checkCompletionEvidence, deliverableReceiptEvidence } from './completion-evidence.js';
|
|
20
20
|
import { judgeNextMove } from './judge.js';
|
|
21
|
+
import { loadRunLedger, runLedgerDir } from '../self-implement/run-ledger.js';
|
|
21
22
|
|
|
22
23
|
export interface ResolveHandTextDeps {
|
|
23
24
|
cwd: string;
|
|
@@ -94,6 +95,8 @@ export type CompletionKind = typeof COMPLETION_KINDS[number];
|
|
|
94
95
|
*/
|
|
95
96
|
export interface TaskCardEvent {
|
|
96
97
|
at: string; event: string; detail?: string; runId?: string; pr?: number;
|
|
98
|
+
/** 원격 미결 수를 HQ 에 한 번만 회수하기 위한 원장 사건 id. */
|
|
99
|
+
sourceId?: string;
|
|
97
100
|
/** `closed-by-hand` 줄만 — 닫은 사유 · 닫은 자리(`closeTaskCard`). */
|
|
98
101
|
reason?: string; by?: string;
|
|
99
102
|
kind?: string; executed?: boolean; ok?: boolean; executorResult?: 'shadow' | 'live'; head?: string; effect?: string;
|
|
@@ -167,7 +170,9 @@ export interface TaskCard {
|
|
|
167
170
|
*/
|
|
168
171
|
regates?: Array<{ pr: number; head: string; at: string; resultPath?: string; passed?: boolean; status?: string; baseCommit?: string; detail?: string;
|
|
169
172
|
/** REJUDGE base-stale — 같은 머리를 새 base 위에서 다시 잰 재게이트면, land 가 낡았다고 거절한 앞 재게이트의 base(멱등 키 = 머리 ⊕ 이 base). */
|
|
170
|
-
staleBase?: string
|
|
173
|
+
staleBase?: string;
|
|
174
|
+
/** TA-READY-BEFORE-REGATE — draft 때문에 실패한 같은 머리를 ready 뒤 딱 한 번 다시 잰다. */
|
|
175
|
+
readyRetry?: true }>;
|
|
171
176
|
/**
|
|
172
177
|
* Live land attempts, claimed before invocation, once per PR head even if the command fails.
|
|
173
178
|
* TA-LAND-RETRY-ON-INFRA — a failed attempt carries `class`/`reason`: `infra` (TA-side, allow-listed) leaves one more attempt on
|
|
@@ -316,7 +321,8 @@ export function launchArgs(card: Pick<TaskCard, 'text' | 'seat' | 'childLlm'>):
|
|
|
316
321
|
* 이유에 «착지 미확인»을 단다(착지했다/안 했다를 단정하지 않는다).
|
|
317
322
|
* 미션 카드는 스스로 발사하지 않는다 · 아직 안 뜬 조각의 선행이 덜 착지했으면 `wait after <id>`.
|
|
318
323
|
*/
|
|
319
|
-
export function nextMoveFor(card: TaskCard, landed?: ReadonlySet<string
|
|
324
|
+
export function nextMoveFor(card: TaskCard, landed?: ReadonlySet<string>, deps: { ledgerDir?: string } = {}): TaskCardMove {
|
|
325
|
+
// Completion callbacks record a shadow decision; do not suggest the live CLI here.
|
|
320
326
|
if (card.pieces) return { kind: 'wait', reason: `미션 — 조각 ${card.pieces.length}장이 선후대로 발사된다` };
|
|
321
327
|
const unmet = (card.after ?? []).filter((id) => !landed?.has(id));
|
|
322
328
|
if (card.status !== 'launched' && unmet.length > 0) return { kind: 'wait', reason: `after ${unmet.join(', ')}${landed ? '' : ' · 착지 미확인'}` };
|
|
@@ -324,6 +330,16 @@ export function nextMoveFor(card: TaskCard, landed?: ReadonlySet<string>): TaskC
|
|
|
324
330
|
if (card.status === 'launch-failed') return { kind: 'launch', command: launchArgs(card), reason: '직전 발사 실패 — 다시 발사' };
|
|
325
331
|
// live-move·hand-move 줄(관측 기록)은 실패 사유가 아니다 — 그 줄을 뺀 마지막 칸이 사유다(live-move 줄 없는 카드는 종전과 같다).
|
|
326
332
|
if (card.status === 'failed') return { kind: 'wait', reason: card.history.filter((item) => item.event !== LIVE_MOVE_HISTORY_EVENT && item.event !== LIVE_MOVE_RESULT_EVENT && item.event !== HAND_MOVE_HISTORY_EVENT).at(-1)?.detail ?? '런 실패 — PR·수확 가지 없음' };
|
|
333
|
+
if (card.status === 'launched' && card.runId) {
|
|
334
|
+
try {
|
|
335
|
+
const ledger = loadRunLedger(card.runId, deps.ledgerDir ?? runLedgerDir());
|
|
336
|
+
const terminal = ledger?.filter((entry) => entry.event === 'run-status').at(-1);
|
|
337
|
+
if (terminal && ['succeeded', 'failed', 'cancelled', 'abandoned'].includes(String(terminal.data.runStatus))) {
|
|
338
|
+
if (cardPrNumber(card) === undefined) return { kind: 'wait', reason: `런 원장 종료 — ${terminal.data.runStatus} · PR 없음` };
|
|
339
|
+
return { kind: 'wait', reason: `런 원장 종료 — ${terminal.data.runStatus} · 그림자 재판정은 완료 훅이 기록` };
|
|
340
|
+
}
|
|
341
|
+
} catch { /* 원장 결손·손상은 종료로 단정하지 않는다. */ }
|
|
342
|
+
}
|
|
327
343
|
return { kind: 'wait', reason: '발사됨 — 런 멈춤을 슈퍼바이저 그림자 판단(task-agent.shadow-move)이 받는다' };
|
|
328
344
|
}
|
|
329
345
|
|
|
@@ -1108,6 +1108,7 @@ if [ "$found" -eq 0 ]; then echo ELANOUS_RUN_LEDGER_NONE; fi`,
|
|
|
1108
1108
|
env: [
|
|
1109
1109
|
...(o.runId ? [{ name: 'ELANOUS_RUN_ID', value: o.runId }] : []),
|
|
1110
1110
|
...(o.parentRunId ? [{ name: 'ELANOUS_PARENT_RUN_ID', value: o.parentRunId }] : []),
|
|
1111
|
+
...(o.workIdentity?.taskCard ? [{ name: 'ELANOUS_TASK_CARD_ID', value: o.workIdentity.taskCard }] : []),
|
|
1111
1112
|
{ name: 'ELANOUS_SUBSTRATE', value: 'pod' },
|
|
1112
1113
|
...Object.entries(controlInboxEnv(POD_CONTROL_INBOX_DIR)).map(([name, value]) => ({ name, value })),
|
|
1113
1114
|
// ⭐ 런 출처(🅣 RFC run-origin §A3 · #20457/#20468 칸 이름) — Pod 는 자기 elanous_id 를 쓰지 않고 «띄운 감독기»의 hostId 를 물려받는다.
|
|
@@ -29,6 +29,31 @@ export interface ToolSearchRunResult {
|
|
|
29
29
|
[HYDRATED_TOOLS_KEY]?: LLMToolSpec[];
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
/** Session runtime applies this only to the fixed harness turn, using its
|
|
33
|
+
* originating userText. Both the callable catalog and visible schemas must
|
|
34
|
+
* agree, so a later model turn cannot rehydrate Edit or Write from this result. */
|
|
35
|
+
export function blockWriteToolSearchHydration(result: ToolSearchRunResult): ToolSearchRunResult {
|
|
36
|
+
const hydrated = result[HYDRATED_TOOLS_KEY] ?? [];
|
|
37
|
+
const allowed = hydrated.filter((tool) => tool.name !== 'Edit' && tool.name !== 'Write');
|
|
38
|
+
if (allowed.length === hydrated.length) return result;
|
|
39
|
+
const blocked = new Set(['Edit', 'Write']);
|
|
40
|
+
const matched = result.matched.filter((name) => !blocked.has(name));
|
|
41
|
+
const schemas = allowed.length > 0
|
|
42
|
+
? `<functions>\n${allowed.map((tool) => `<function>${JSON.stringify({
|
|
43
|
+
description: tool.description,
|
|
44
|
+
name: tool.name,
|
|
45
|
+
parameters: tool.parameters,
|
|
46
|
+
})}</function>`).join('\n')}\n</functions>`
|
|
47
|
+
: '';
|
|
48
|
+
const output = `# ToolSearch: ${matched.length} allowed match${matched.length === 1 ? '' : 'es'}\n\n${schemas}`;
|
|
49
|
+
return {
|
|
50
|
+
...result,
|
|
51
|
+
output,
|
|
52
|
+
matched,
|
|
53
|
+
[HYDRATED_TOOLS_KEY]: allowed,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
32
57
|
export const toolSearchRuntime: ToolRuntime<ToolSearchArgs, ToolSearchRunResult> = {
|
|
33
58
|
id: 'tool_search',
|
|
34
59
|
spec: buildToolSearchTool(),
|
package/src/tui.ts
CHANGED
|
@@ -978,6 +978,8 @@ export interface RenderOptions {
|
|
|
978
978
|
force?: boolean;
|
|
979
979
|
/** Physical cursor ANSI emitted after overlays as the last bytes of the frame. */
|
|
980
980
|
cursor?: string;
|
|
981
|
+
/** Called after this frame finishes rendering and stdout settles. */
|
|
982
|
+
onWriteComplete?: (error?: Error | null) => void;
|
|
981
983
|
}
|
|
982
984
|
|
|
983
985
|
let _lastFrameLines: string[] = [];
|
|
@@ -1036,7 +1038,22 @@ export function render(lines: string[], opts: RenderOptions = {}): void {
|
|
|
1036
1038
|
}
|
|
1037
1039
|
if (opts.overlay) buf += opts.overlay;
|
|
1038
1040
|
if (opts.cursor) buf += opts.cursor;
|
|
1039
|
-
|
|
1041
|
+
let writeSettled = false;
|
|
1042
|
+
let writeError: Error | null | undefined;
|
|
1043
|
+
let rendered = false;
|
|
1044
|
+
const finishWrite = () => {
|
|
1045
|
+
if (!opts.onWriteComplete || !writeSettled || !rendered) return;
|
|
1046
|
+
try { opts.onWriteComplete(writeError); } catch { /* observation must not break rendering */ }
|
|
1047
|
+
};
|
|
1048
|
+
if (opts.onWriteComplete) {
|
|
1049
|
+
process.stdout.write(buf, (error) => {
|
|
1050
|
+
writeError = error;
|
|
1051
|
+
writeSettled = true;
|
|
1052
|
+
finishWrite();
|
|
1053
|
+
});
|
|
1054
|
+
} else {
|
|
1055
|
+
process.stdout.write(buf);
|
|
1056
|
+
}
|
|
1040
1057
|
perf.recordStdoutWrite(buf.length, true);
|
|
1041
1058
|
perf.markDrawEnd();
|
|
1042
1059
|
|
|
@@ -1053,6 +1070,8 @@ export function render(lines: string[], opts: RenderOptions = {}): void {
|
|
|
1053
1070
|
if (_frameObserver) {
|
|
1054
1071
|
try { _frameObserver(_lastFrameLines, { rows, cols }); } catch { /* swallow */ }
|
|
1055
1072
|
}
|
|
1073
|
+
rendered = true;
|
|
1074
|
+
finishWrite();
|
|
1056
1075
|
}
|
|
1057
1076
|
|
|
1058
1077
|
// ── Utility ──
|
package/src/user-config.ts
CHANGED
|
@@ -27,6 +27,9 @@
|
|
|
27
27
|
// crashed wizard cannot corrupt an existing file. Mode 0600 when the
|
|
28
28
|
// telegram bot token is present.
|
|
29
29
|
|
|
30
|
+
import { isRuntimeLlmModelCompatibleWithProvider } from './llm/runtime-model-family.js';
|
|
31
|
+
export { inferRuntimeLlmModelFamily, isRuntimeLlmModelCompatibleWithProvider } from './llm/runtime-model-family.js';
|
|
32
|
+
export type { RuntimeLlmModelFamily } from './llm/runtime-model-family.js';
|
|
30
33
|
import { DRAFT_ON_STOP_MODES, parseDraftOnStopMode, type DraftOnStopMode } from './self-implement/draft-on-stop-mode.js';
|
|
31
34
|
import { isCodexQuotaPolicy } from './oauth/codex-quota-policy.js';
|
|
32
35
|
import { defaultObsidianVault } from './obsidian/default-vault.js';
|
|
@@ -4530,65 +4533,6 @@ function runtimeLlmProviderOverride(): LLMProviderName | undefined {
|
|
|
4530
4533
|
return requested as LLMProviderName;
|
|
4531
4534
|
}
|
|
4532
4535
|
|
|
4533
|
-
/** Lightweight model-id family — prefix/substring only. No catalog, no
|
|
4534
|
-
* `src/llm/model-defaults.ts` (that module imports this file). */
|
|
4535
|
-
export type RuntimeLlmModelFamily =
|
|
4536
|
-
| 'grok' | 'anthropic' | 'openai' | 'openai-codex' | 'gemini' | 'local'
|
|
4537
|
-
| 'kimi' | 'qwen' | 'glm' | 'openrouter' | 'bedrock' | 'unknown';
|
|
4538
|
-
|
|
4539
|
-
export function inferRuntimeLlmModelFamily(model: string | undefined): RuntimeLlmModelFamily {
|
|
4540
|
-
if (!model) return 'unknown';
|
|
4541
|
-
const m = model.trim().toLowerCase();
|
|
4542
|
-
if (!m) return 'unknown';
|
|
4543
|
-
// ⛔ 2026-09-23 — 게이트웨이 접두가 «먼저»다. 안 그러면 `openrouter/anthropic/claude-…` 가 `anthropic` 으로
|
|
4544
|
-
// 읽혀 openrouter 와 «비호환»이 되고, `openrouter/z-ai/…` 는 `unknown` 이라 아무 provider 와도 «호환»이 됐다.
|
|
4545
|
-
if (m.startsWith('openrouter/')) return 'openrouter';
|
|
4546
|
-
// ⭐ BEDROCK-PROVIDER — Bedrock 전용 꼴(`anthropic.claude-…`·지역 접두·`bedrock/…`)이 `includes('claude')` 보다 «먼저».
|
|
4547
|
-
// 1st-party id(`claude-…`)는 그대로 anthropic 이다(불변).
|
|
4548
|
-
if (m.startsWith('bedrock/') || /^(?:[a-z]{2,6}\.)?anthropic\.claude-/.test(m)) return 'bedrock';
|
|
4549
|
-
if (m.includes('grok')) return 'grok';
|
|
4550
|
-
if (m.includes('claude')) return 'anthropic';
|
|
4551
|
-
if (m.startsWith('gemini-') || m.includes('gemini')) return 'gemini';
|
|
4552
|
-
if (m.startsWith('local:')) return 'local';
|
|
4553
|
-
if (m.startsWith('kimi')) return 'kimi';
|
|
4554
|
-
if (m.startsWith('qwen')) return 'qwen';
|
|
4555
|
-
if (m.startsWith('glm')) return 'glm';
|
|
4556
|
-
// openai-codex 구독 모델만 여기 — gpt-5.5 등 Chat Completions 모델은 openai.
|
|
4557
|
-
// ⛔ openai 와 openai-codex 를 한 계열로 접지 마라. 서로 다른 엔드포인트다.
|
|
4558
|
-
// ✅ 2026-09-23 (대표 ⒜ 결정) — ***`gpt-6` 를 여기 «더했다».***
|
|
4559
|
-
// 종전엔 `gpt-6-*` 가 아래 `startsWith('gpt-')` 로 떨어져 `openai` 가 됐고, 그래서
|
|
4560
|
-
// ***사다리가 «자기 가드가 거부하는 모델»을 가리켰다*** (`CODEX.loaded = gpt-6-astra`).
|
|
4561
|
-
// 📏 구독 경로 실호출로 확인(codex-cli 0.155.1): gpt-6-sol · luna · astra 전부 응답.
|
|
4562
|
-
// ⚠️ 이 셋은 API 로도 불린다(`/v1/models` 에 있다). 「계열」이 재는 것은 «가용성»이 아니라
|
|
4563
|
-
// ***「우리가 어느 문으로 보내나」***다 — 5.6 계열도 API 에 있지만 여기로 온다.
|
|
4564
|
-
if (m.includes('codex') || m.startsWith('gpt-5.6') || m.startsWith('gpt-6')) return 'openai-codex';
|
|
4565
|
-
// Exact o1/o3/o4 ids are standard OpenAI models; prefix-only (`o1-`) misses them.
|
|
4566
|
-
if (
|
|
4567
|
-
m.startsWith('gpt-')
|
|
4568
|
-
|| m === 'o1' || m.startsWith('o1-')
|
|
4569
|
-
|| m === 'o3' || m.startsWith('o3-')
|
|
4570
|
-
|| m === 'o4' || m.startsWith('o4-')
|
|
4571
|
-
) return 'openai';
|
|
4572
|
-
return 'unknown';
|
|
4573
|
-
}
|
|
4574
|
-
|
|
4575
|
-
/** Cycle-safe compatibility: same-provider model overrides pass;
|
|
4576
|
-
* cross-family ids fail. Unknown prefixes and `auto` stay silent.
|
|
4577
|
-
* ⛔ `openai` 와 `openai-codex` 는 별개 provider — 양방향 호환으로 접지 않는다. */
|
|
4578
|
-
export function isRuntimeLlmModelCompatibleWithProvider(
|
|
4579
|
-
provider: LLMProviderName,
|
|
4580
|
-
model: string | undefined,
|
|
4581
|
-
): boolean {
|
|
4582
|
-
if (!model) return true;
|
|
4583
|
-
if (provider === 'auto') return true;
|
|
4584
|
-
const family = inferRuntimeLlmModelFamily(model);
|
|
4585
|
-
if (family === 'unknown') return true;
|
|
4586
|
-
if (provider === 'local') return family === 'local';
|
|
4587
|
-
// bedrock 은 1st-party claude id 도 받는다(공급자가 `anthropic.` 접두로 바꿔 보낸다).
|
|
4588
|
-
if (provider === 'bedrock') return family === 'bedrock' || family === 'anthropic';
|
|
4589
|
-
return provider === family;
|
|
4590
|
-
}
|
|
4591
|
-
|
|
4592
4536
|
function observeRuntimeLlmModelProviderMismatch(provider: LLMProviderName, model: string): void {
|
|
4593
4537
|
debug.log('user-config.llm', 'model-provider-mismatch', { provider, model });
|
|
4594
4538
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"commit":"
|
|
1
|
+
{"commit":"c35a05489ca5528f8c3b63e6adbc04d073b4a430"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[2922],{5794:(e,t,n)=>{"use strict";n.d(t,{r:()=>l});var r=n(77194),s=n(64862),a=n.n(s);let i=[{key:"autopilot",href:"/autopilot",num:"①",label:"미션",sub:"Autopilot"},{key:"tasks",href:"/tasks",num:"②",label:"작업",sub:"Tasks"},{key:"scheduler",href:"/scheduler",num:"③",label:"스케줄",sub:"Schedules"}];function l(e){let{active:t}=e;return(0,r.jsxs)("nav",{"aria-label":"Mission Fabric 파이프라인","data-testid":"fabric-stage-header",className:"flex flex-wrap items-center gap-1 text-xs",children:[(0,r.jsx)("span",{className:"mr-1 text-muted-foreground",children:"Missions"}),i.map((e,n)=>(0,r.jsxs)("span",{className:"flex items-center gap-1",children:[(0,r.jsxs)(a(),{href:e.href,"aria-current":e.key===t?"page":void 0,className:["rounded px-2 py-1 ring-1 transition-colors",e.key===t?"bg-primary/15 font-medium text-foreground ring-primary/40":"text-muted-foreground ring-border hover:bg-muted hover:text-foreground"].join(" "),children:[(0,r.jsx)("span",{className:"mr-1",children:e.num}),e.label,(0,r.jsx)("span",{className:"ml-1 text-[10px] opacity-70",children:e.sub})]}),n<i.length-1&&(0,r.jsx)("span",{className:"text-muted-foreground/50","aria-hidden":!0,children:"→"})]},e.key))]})}},8801:(e,t,n)=>{"use strict";n.d(t,{C:()=>d,DaemonProvider:()=>c,Q:()=>u});var r=n(77194),s=n(49954),a=n(9248),i=n(19631),l=n(49638),o=n(35857);let d=(0,s.createContext)(null);function c(e){let{children:t}=e,n={baseUrl:"",token:"",provider:""},[c,u]=(0,s.useState)(n),[m,x]=(0,s.useState)(""),[p]=(0,s.useState)(()=>new l.ki(n));(0,s.useEffect)(()=>{let e=(0,a.Fp)();u(e),p.updateConfig(e),x((0,i.oD)()),(0,o.cY)("webterm.provider.daemon.init",{baseUrl:e.baseUrl,hasToken:!!e.token})},[p]),(0,s.useEffect)(()=>{let e=e=>{if("elanous.daemon.token"===e.key||"elanous.nexus.baseUrl"===e.key){let t=(0,a.Fp)();p.updateConfig(t),u(t),(0,o.cY)("webterm.provider.daemon.config-cross-tab",{key:e.key,hasToken:!!t.token});return}"elanous.daemon.sessionId"===e.key&&e.newValue&&x(t=>t===e.newValue?t:((0,o.cY)("webterm.provider.daemon.session-cross-tab",{previous:t||"(empty)",next:e.newValue}),e.newValue))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)},[p]);let g=e=>{u(t=>{let n={...t,...e};return(0,a.Qc)(e),p.updateConfig(n),(0,o.cY)("webterm.provider.daemon.config-update",{keys:Object.keys(e)}),n})},h=e=>{x(e),localStorage.setItem("elanous.daemon.sessionId",e),(0,o.cY)("webterm.provider.daemon.session-set",{sessionId:e})},b=(0,s.useMemo)(()=>({config:c,setConfig:g,client:p,sessionId:m,setSessionId:h}),[c,p,m]);return(0,r.jsx)(d.Provider,{value:b,children:t})}function u(){let e=(0,s.useContext)(d);if(!e)throw Error("useDaemon must be used inside <DaemonProvider>");return e}},19631:(e,t,n)=>{"use strict";n.d(t,{Zr:()=>i,f6:()=>s,oD:()=>a});let r="elanous.daemon.sessionId";function s(){return"undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID?crypto.randomUUID():"s-".concat(Date.now().toString(36),"-").concat(Math.random().toString(36).slice(2,10))}function a(){let e=function(){let e=new URLSearchParams(window.location.search).get("session");return e?(localStorage.setItem(r,e),e):localStorage.getItem(r)}();if(e)return e;let t=s();return localStorage.setItem(r,t),t}function i(){let e=s();return localStorage.setItem(r,e),e}},29494:(e,t,n)=>{Promise.resolve().then(n.bind(n,65785))},35083:(e,t,n)=>{"use strict";n.d(t,{cn:()=>a});var r=n(44196),s=n(25080);function a(){for(var e=arguments.length,t=Array(e),n=0;n<e;n++)t[n]=arguments[n];return(0,s.QP)((0,r.$)(t))}},44092:(e,t,n)=>{"use strict";n.d(t,{$:()=>o});var r=n(77194),s=n(51225),a=n(65106),i=n(35083);let l=(0,a.F)("group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",{variants:{variant:{default:"bg-primary text-primary-foreground [a]:hover:bg-primary/80",outline:"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",secondary:"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",ghost:"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",destructive:"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",link:"text-primary underline-offset-4 hover:underline"},size:{default:"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",xs:"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",sm:"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",lg:"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",icon:"size-8","icon-xs":"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3","icon-sm":"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg","icon-lg":"size-9"}},defaultVariants:{variant:"default",size:"default"}});function o(e){let{className:t,variant:n="default",size:a="default",...o}=e;return(0,r.jsx)(s.$,{"data-slot":"button",className:(0,i.cn)(l({variant:n,size:a,className:t})),...o})}},65785:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>A});var r=n(77194),s=n(49954),a=n(8801),i=n(44092);let l=["dig","backtest","trade","retro","replay","delegate","autopilot"],o={trade:"bg-rose-500/15 text-rose-300 ring-rose-500/30",dig:"bg-sky-500/15 text-sky-200 ring-sky-500/30",backtest:"bg-violet-500/15 text-violet-200 ring-violet-500/30",retro:"bg-amber-500/15 text-amber-200 ring-amber-500/30",replay:"bg-indigo-500/15 text-indigo-200 ring-indigo-500/30",delegate:"bg-emerald-500/15 text-emerald-200 ring-emerald-500/30",autopilot:"bg-fuchsia-500/15 text-fuchsia-200 ring-fuchsia-500/30"};function d(e){let{api:t}=e,[n,a]=(0,s.useState)([]),[d,c]=(0,s.useState)(null),[u,m]=(0,s.useState)(!0),x=(0,s.useCallback)(async()=>{m(!0);try{var e;let n=await t.autonomy(80,null!=d?d:void 0);a(null!=(e=n.actions)?e:[])}catch(e){}finally{m(!1)}},[t,d]);return(0,s.useEffect)(()=>{x()},[x]),(0,r.jsxs)("div",{className:"space-y-3",children:[(0,r.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,r.jsx)("button",{type:"button",onClick:()=>c(null),className:["rounded px-2 py-0.5 text-xs ring-1",null===d?"bg-primary/20 text-foreground ring-primary/40":"bg-muted text-muted-foreground ring-border"].join(" "),children:"전체"}),l.map(e=>{var t;return(0,r.jsx)("button",{type:"button",onClick:()=>c(e),className:["rounded px-2 py-0.5 text-xs ring-1",d===e?null!=(t=o[e])?t:"bg-primary/20 ring-primary/40":"bg-muted text-muted-foreground ring-border"].join(" "),children:e},e)}),(0,r.jsx)(i.$,{size:"sm",variant:"outline",className:"ml-auto",onClick:()=>void x(),children:"새로고침"})]}),u?(0,r.jsx)("p",{className:"text-sm text-muted-foreground",children:"불러오는 중…"}):0===n.length?(0,r.jsx)("p",{className:"text-sm text-muted-foreground",children:"아직 기록된 자율행동이 없습니다. 자율루프가 돌면 여기에 “무엇을 왜 했나”가 쌓입니다."}):(0,r.jsx)("ul",{className:"space-y-2",children:n.map((e,t)=>{var n;return(0,r.jsxs)("li",{className:"rounded-lg border border-border bg-card/50 p-3",children:[(0,r.jsxs)("div",{className:"flex items-center gap-2",children:[(0,r.jsx)("span",{className:["rounded px-2 py-0.5 text-xs ring-1",null!=(n=o[e.loop])?n:"bg-muted text-muted-foreground ring-border"].join(" "),children:e.loop}),(0,r.jsx)("span",{className:"text-xs text-muted-foreground",children:function(e){try{return new Intl.DateTimeFormat("ko-KR",{timeZone:"Asia/Seoul",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}).format(new Date(e))}catch(t){return e.slice(5,16)}}(e.ts)}),e.importance>=8&&(0,r.jsx)("span",{className:"rounded bg-rose-500/15 px-1.5 text-[10px] text-rose-300 ring-1 ring-rose-500/30",children:"중요"})]}),(0,r.jsx)("pre",{className:"mt-1.5 whitespace-pre-wrap font-sans text-sm text-foreground/90",children:e.text})]},"".concat(e.ts,"-").concat(t))})})]})}var c=n(64862),u=n.n(c),m=n(72248);let x=new Set(["done","failed","disarmed","rejected","completed","cancelled"]);function p(e){return x.has(null!=e?e:"")}function g(){return"갱신이 ".concat(14,"일 넘게 없으면 \xab멈춤\xbb으로 본다 — 마지막 갱신 이후 진행 흔적이 없다는 뜻이다.")}function h(e){return null==e?"파생 미측정":"파생 ".concat(e.total)}let b={ok:{icon:"✅",tone:"text-emerald-300",label:"정상"},done:{icon:"✅",tone:"text-emerald-300",label:"완료"},stale:{icon:"⏰",tone:"text-amber-300",label:"밀림"},error:{icon:"❌",tone:"text-rose-400",label:"실패"},active:{icon:"\uD83D\uDD35",tone:"text-sky-300",label:"실행중"},pending:{icon:"⏳",tone:"text-muted-foreground",label:"대기"}},f={cron:"크론",task:"태스크",action:"자율행동"};function v(e){var t;let{counts:n,total:s}=e,a=Object.entries(null!=n?n:{}).filter(e=>{let[,t]=e;return t>0});if(!s||0===s)return(0,r.jsx)("span",{className:"text-xs text-muted-foreground",children:"태스크 0"});let i=null!=(t=null==n?void 0:n.done)?t:0;return(0,r.jsxs)("span",{className:"flex items-center gap-1.5",children:[(0,r.jsxs)("span",{className:"text-xs text-muted-foreground",children:["태스크 ",i,"/",s]}),a.map(e=>{let[t,n]=e;return(0,r.jsxs)("span",{className:"text-[11px] text-muted-foreground",children:[t,":",n]},t)})]})}function y(e){let{r:t}=e;if(!t||0===t.total)return(0,r.jsx)("span",{className:"text-xs text-muted-foreground",...t?{}:{title:"서버가 파생 롤업을 싣지 않았다 — \xab파생 0\xbb이 아니라 \xab못 잰\xbb 값이다(구 서버 \xb7 집계 실패)."},children:h(t)});let n=(e,t)=>e>0?(0,r.jsxs)("span",{className:["text-xs",b[t].tone].join(" "),children:[b[t].icon,e]},t):null;return(0,r.jsxs)("span",{className:"flex items-center gap-1.5",children:[(0,r.jsx)("span",{className:"text-xs text-muted-foreground",children:h(t)}),n(t.ok,"ok"),n(t.stale,"stale"),n(t.error,"error"),n(t.active,"active"),n(t.pending,"pending")]})}function j(e){let{api:t,m:n,onDone:a}=e,l="scheduler"===n.model,o="task"===n.model,[d,c]=(0,s.useState)(""),[u,m]=(0,s.useState)(""),[x,p]=(0,s.useState)(""),[g,h]=(0,s.useState)(null),[b,f]=(0,s.useState)(null);if(!l&&!o)return(0,r.jsxs)("p",{className:"text-xs text-muted-foreground",children:["이 실행모델(",n.model,")은 지속 잡을 만들지 않아 구체화 대상이 아닙니다."]});let v=async e=>{h(e),f(null);let r=l?{command:d.trim(),...u.trim()?{cron:u.trim()}:{}}:{...x.trim()?{prompt:x.trim()}:{}};try{let i=await t.missionAction(n.id,e,r);if(i.error)f("오류: ".concat(i.error));else{var s;f("arm"===e?"승인\xb7arming ON 시 자동 실행":"구체화 완료(".concat(null!=(s=i.engine)?s:"",")")),a()}}catch(e){f(e instanceof Error?e.message:String(e))}finally{h(null)}};return(0,r.jsxs)("div",{className:"mt-3 space-y-2 rounded-md border border-border bg-background/50 p-2.5",children:[l&&(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("input",{value:d,onChange:e=>c(e.target.value),placeholder:"실행할 명령 (예: scripts/foo.ts) — 필수",className:"w-full rounded border border-border bg-background px-2 py-1 text-xs"}),(0,r.jsx)("input",{value:u,onChange:e=>m(e.target.value),placeholder:"cron (선택 \xb7 비우면 골에서 추론)",className:"w-full rounded border border-border bg-background px-2 py-1 font-mono text-xs"})]}),o&&(0,r.jsx)("input",{value:x,onChange:e=>p(e.target.value),placeholder:"태스크 내용 (선택 \xb7 비우면 골 사용)",className:"w-full rounded border border-border bg-background px-2 py-1 text-xs"}),(0,r.jsxs)("div",{className:"flex items-center gap-2",children:[(0,r.jsx)(i.$,{size:"sm",disabled:!!g||l&&!d.trim(),onClick:()=>void v("materialize"),children:"materialize"===g?"…":"지금 구체화"}),(0,r.jsx)(i.$,{size:"sm",variant:"outline",disabled:!!g||l&&!d.trim(),onClick:()=>void v("arm"),children:"arm"===g?"…":"승인(arm)"}),b&&(0,r.jsx)("span",{className:"text-xs text-muted-foreground",children:b})]})]})}function N(e){let{api:t,m:n,onMutate:a}=e,l=!1===n.isAutopilot,[o,d]=(0,s.useState)(!1),[c,x]=(0,s.useState)(null),[h,N]=(0,s.useState)(!1),k=n.model?m.NE[n.model]:null,w=function(e,t,n){var r;if(void 0===e||!Number.isFinite(e)||!Number.isFinite(t))return null;let s=new Date(e);if(!Number.isFinite(s.getTime()))return null;let a=new Intl.DateTimeFormat("en-CA",{timeZone:null==n?void 0:n.timeZone,year:"numeric",month:"2-digit",day:"2-digit"}).formatToParts(s),i=e=>{var t;return null==(t=a.find(t=>t.type===e))?void 0:t.value},l="".concat(i("year"),"-").concat(i("month"),"-").concat(i("day")),o=Math.floor((t-e)/864e5);return{stale:!p(null==n?void 0:n.status)&&o>=(null!=(r=null==n?void 0:n.thresholdDays)?r:14),days:o,lastUpdated:l}}(n.updatedAt,Date.now(),{status:n.status}),S=(null==w?void 0:w.stale)?w:null,[C,z]=(0,s.useState)(!1),I=(0,s.useCallback)(async()=>{N(!0);try{x(await t.trace(n.id))}catch(e){}finally{N(!1)}},[t,n.id]),[A,E]=(0,s.useState)(!1),[D,M]=(0,s.useState)(!1),[U,P]=(0,s.useState)(null),$=!l&&"proposed"===n.status,O=(0,s.useCallback)(async()=>{let e=!o;d(e),!e||c||l||await I()},[o,c,I,l]),T=(0,s.useCallback)(async()=>{E(!0),P(null);try{await t.missionAction(n.id,"cancel"),z(!1),await I(),a()}catch(e){}finally{E(!1)}},[t,n.id,I,a]),F=(0,s.useCallback)(async()=>{M(!0),P(null);try{var e;let r=await t.missionAction(n.id,"approve");r.error?P("오류: ".concat(r.error)):P("✅ 승인 — 태스크 ".concat(null!=(e=r.activated)?e:0,"건 실행 시작(ready). 미션 running.")),await I()}catch(e){P(e instanceof Error?e.message:String(e))}finally{M(!1)}},[t,n.id,I]);return(0,r.jsxs)("div",{className:"rounded-lg border border-border bg-card/50",children:[(0,r.jsxs)("div",{className:"flex items-start",children:[(0,r.jsxs)("button",{type:"button",onClick:()=>void O(),className:"flex min-w-0 flex-1 items-start gap-3 p-3 text-left",children:[(0,r.jsx)("span",{className:"mt-0.5 text-muted-foreground",children:o?"▾":"▸"}),(0,r.jsxs)("div",{className:"min-w-0 flex-1 space-y-1.5",children:[(0,r.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[l?(0,r.jsx)("span",{className:"rounded bg-slate-500/15 px-2 py-0.5 text-xs font-medium text-slate-300 ring-1 ring-slate-500/30",children:"사람 \xb7 intake"}):k&&(0,r.jsx)("span",{className:["rounded px-2 py-0.5 text-xs font-medium ring-1",k.tone].join(" "),children:k.label}),!l&&"continuous"===n.kind&&(0,r.jsx)("span",{className:"rounded bg-sky-500/15 px-1.5 py-0.5 text-[11px] text-sky-300 ring-1 ring-sky-500/30",children:"상시"}),!l&&"finite"===n.kind&&(0,r.jsx)("span",{className:"rounded bg-violet-500/15 px-1.5 py-0.5 text-[11px] text-violet-300 ring-1 ring-violet-500/30",children:"유한"}),(0,r.jsx)("span",{className:"rounded bg-muted px-1.5 py-0.5 text-[11px] text-muted-foreground ring-1 ring-border",children:n.source}),$?(0,r.jsx)("span",{className:"rounded bg-amber-500/15 px-1.5 py-0.5 text-[11px] font-medium text-amber-300 ring-1 ring-amber-500/40",children:"승인 대기"}):(0,r.jsx)("span",{className:"rounded bg-muted px-1.5 py-0.5 text-[11px] text-muted-foreground ring-1 ring-border",children:n.status}),n.reviewDue&&(0,r.jsx)("span",{className:"rounded bg-amber-500/15 px-1.5 py-0.5 text-[11px] text-amber-300 ring-1 ring-amber-500/30",children:"⚠ 30일+ 리뷰"}),l?(0,r.jsx)(v,{counts:n.taskCounts,total:n.taskCount}):(0,r.jsx)(y,{r:n.derived}),S&&(0,r.jsx)("span",{className:"rounded bg-amber-500/15 px-1.5 py-0.5 text-[11px] font-medium text-amber-300 ring-1 ring-amber-500/30",title:g(),children:"".concat(S.days,"일 멈춤 \xb7 마지막 갱신 ").concat(S.lastUpdated)})]}),(0,r.jsx)("p",{className:"truncate text-sm text-foreground/90",children:n.goal}),(0,r.jsx)("p",{className:"font-mono text-[10px] text-muted-foreground",children:n.id})]})]}),S&&!l&&(0,r.jsxs)("div",{className:"mr-3 mt-3 flex shrink-0 flex-col items-end gap-1.5",children:[(0,r.jsx)(i.$,{size:"sm",variant:"outline",disabled:A,onClick:()=>z(e=>!e),"aria-expanded":C,"aria-controls":"mission-close-confirm-".concat(n.id),className:"border-amber-500/40 text-amber-300 hover:text-amber-200",children:A?"종료 중…":"닫기 제안"}),C&&(0,r.jsxs)("div",{id:"mission-close-confirm-".concat(n.id),role:"group","aria-label":"미션 종료 확인",className:"w-60 space-y-1.5 rounded-md border border-amber-500/40 bg-amber-500/5 p-2",children:[(0,r.jsx)("p",{className:"text-[11px] leading-snug text-amber-200/90",children:g()}),(0,r.jsxs)("p",{className:"text-[11px] leading-snug text-muted-foreground",children:[S.days,"일째 갱신 없음 \xb7 파생 잡까지 release 되며 되돌릴 수 없다."]}),(0,r.jsxs)("div",{className:"flex items-center justify-end gap-1.5",children:[(0,r.jsx)(i.$,{size:"sm",variant:"ghost",disabled:A,className:"h-7 px-2 text-[11px] text-muted-foreground",onClick:()=>z(!1),children:"취소"}),(0,r.jsx)(i.$,{size:"sm",variant:"outline",disabled:A,className:"h-7 border-rose-500/50 px-2 text-[11px] text-rose-300 hover:text-rose-200",onClick:()=>void T(),children:A?"종료 중…":"종료 확인"})]})]})]}),S&&l&&(0,r.jsxs)("div",{className:"mr-3 mt-3 flex shrink-0 flex-col items-end gap-1.5",children:[(0,r.jsx)(u(),{href:"/tasks",title:"".concat(S.days,"일째 갱신 없음 \xb7 ").concat(g()),className:"inline-flex h-8 items-center rounded-md border border-amber-500/40 px-3 text-xs font-medium text-amber-300 hover:text-amber-200",children:"닫기 제안 — 작업 보드"}),(0,r.jsxs)("span",{className:"max-w-[15rem] text-right text-[11px] leading-snug text-muted-foreground",children:[S.days,"일째 갱신 없음 \xb7 사람 미션은 작업 보드에서 닫습니다"]})]})]}),o&&l&&(0,r.jsxs)("div",{className:"border-t border-border px-4 py-3 space-y-2",children:[(0,r.jsx)("p",{className:"text-xs text-muted-foreground",children:"사람이 Intake 로 만든 미션입니다. 실행은 Task 보드에서 진행됩니다."}),(0,r.jsx)(v,{counts:n.taskCounts,total:n.taskCount}),(0,r.jsx)(u(),{href:"/tasks",className:"inline-block text-xs text-primary hover:underline",children:"② 작업 보드에서 보기 →"})]}),o&&!l&&(0,r.jsxs)("div",{className:"border-t border-border px-4 py-3",children:[$&&(0,r.jsxs)("div",{className:"mb-3 space-y-2 rounded-md border border-amber-500/30 bg-amber-500/5 p-3",children:[(0,r.jsx)("p",{className:"text-sm font-medium text-amber-200",children:"자동 분해 완료 \xb7 승인 대기"}),(0,r.jsxs)("p",{className:"text-xs text-muted-foreground",children:["골을 태스크로 자동 구체화했습니다(아직 ",(0,r.jsx)("b",{children:"실행 안 함"}),"). 승인하면 실행이 시작됩니다.","scheduler"===n.model&&" 반복 스케줄은 승인 후 배선됩니다."]}),(0,r.jsxs)("div",{className:"flex items-center gap-2",children:[(0,r.jsx)(i.$,{size:"sm",disabled:D||A,onClick:()=>void F(),children:D?"승인 중…":"✅ 승인(실행 시작)"}),(0,r.jsx)(i.$,{size:"sm",variant:"ghost",disabled:D||A,onClick:()=>void T(),className:"text-rose-400 hover:text-rose-300",children:A?"거절 중…":"거절"}),U&&(0,r.jsx)("span",{className:"text-xs text-muted-foreground",children:U})]})]}),h&&(0,r.jsx)("p",{className:"text-xs text-muted-foreground",children:"계보 조회 중…"}),c&&0===c.derived.length&&(0,r.jsx)("p",{className:"text-xs text-muted-foreground",children:c.note}),c&&(0,m.on)(c.derived)&&(0,r.jsxs)(u(),{href:(0,m.on)(c.derived),className:"mb-2 inline-block text-xs text-primary hover:underline","data-mission-schedules":!0,children:["이 미션을 부르는 스케줄 ",c.derived.filter(e=>"cron"===e.kind&&e.id).length," →"]}),c&&c.derived.length>0&&(0,r.jsx)("ul",{className:"space-y-1.5",children:c.derived.map((e,t)=>{let n=b[e.status];return(0,r.jsxs)("li",{className:"flex items-start gap-2 text-sm",children:[(0,r.jsx)("span",{className:n.tone,children:n.icon}),(0,r.jsx)("span",{className:"rounded bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground ring-1 ring-border",children:f[e.kind]}),(0,r.jsxs)("span",{className:"min-w-0 flex-1",children:[(0,r.jsx)("span",{className:"text-foreground/90",children:e.name}),e.detail&&(0,r.jsx)("span",{className:"ml-2 text-xs text-muted-foreground",children:e.detail})]})]},t)})}),c&&!p(n.status)&&!$&&(0,r.jsxs)("div",{className:"mt-2 flex items-center gap-2",children:[(0,r.jsx)(i.$,{size:"sm",variant:"ghost",disabled:A,onClick:()=>void T(),className:"text-rose-400 hover:text-rose-300",children:A?"종료 중…":"미션 종료(파생 잡 release)"}),"continuous"===n.kind&&(0,r.jsx)("span",{className:"text-[11px] text-muted-foreground",children:"상시 미션 — 종료 전까지 계속 실행"})]}),c&&!$&&(0,r.jsx)(j,{api:t,m:n,onDone:()=>void I()})]})]})}function k(e){let{api:t,onCommitted:n}=e,[a,l]=(0,s.useState)(""),[o,d]=(0,s.useState)(null),[c,u]=(0,s.useState)(!1),[x,p]=(0,s.useState)(!1),[g,h]=(0,s.useState)(null),b=(0,s.useCallback)(async()=>{let e=a.trim();if(e){u(!0),h(null);try{d((await t.triagePreview(e)).triage)}catch(e){h(e instanceof Error?e.message:String(e))}finally{u(!1)}}},[t,a]),f=(0,s.useCallback)(async()=>{let e=a.trim();if(e){p(!0),h(null);try{(await t.commitMission(e,"intake")).missionId?(l(""),d(null),n()):h("미션 생성 실패")}catch(e){h(e instanceof Error?e.message:String(e))}finally{p(!1)}}},[t,a,n]),v=o?m.NE[o.executionModel]:null;return(0,r.jsxs)("div",{className:"space-y-2 rounded-lg border border-border bg-card/40 p-3",children:[(0,r.jsxs)("div",{className:"flex items-center justify-between",children:[(0,r.jsxs)("span",{className:"text-sm font-medium",children:["골 던지기 ",(0,r.jsx)("span",{className:"text-xs font-normal text-muted-foreground",children:"— 소망을 말하면 미션이 됩니다"})]}),(0,r.jsx)("span",{className:"text-[11px] text-muted-foreground",children:"텔레그램에선 “미션:” 마커로"})]}),(0,r.jsx)("textarea",{value:a,onChange:e=>l(e.target.value),onKeyDown:e=>{"Enter"===e.key&&(e.metaKey||e.ctrlKey)&&b()},placeholder:"예: 삼성전자 급락하면 매매 검토 / 이 주제 끝까지 파봐 / 매일 아침 반도체 뉴스 정리",className:"min-h-[60px] w-full resize-y rounded-md border border-border bg-background px-3 py-2 text-sm"}),(0,r.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,r.jsx)(i.$,{onClick:()=>void b(),disabled:c||!a.trim(),size:"sm",variant:"outline",children:c?"분류 중…":"Triage (⌘↵)"}),(0,r.jsx)(i.$,{onClick:()=>void f(),disabled:x||!a.trim(),size:"sm",children:x?"커밋 중…":"미션 커밋 →"}),o&&v&&(0,r.jsxs)("span",{className:"flex flex-wrap items-center gap-1.5 text-xs",children:[(0,r.jsx)("span",{className:["rounded px-2 py-0.5 ring-1",v.tone].join(" "),children:v.label}),(0,r.jsx)("span",{className:"rounded bg-muted px-1.5 py-0.5 text-muted-foreground ring-1 ring-border",children:"heavy"===o.tier?"무거움":"가벼움"}),(0,r.jsx)("span",{className:"text-muted-foreground",children:o.rationale})]}),g&&(0,r.jsx)("span",{className:"text-xs text-rose-400",children:g})]})]})}function w(e){var t,n;let{api:a}=e,[l,o]=(0,s.useState)(null),[d,c]=(0,s.useState)(null),[u,m]=(0,s.useState)(!1),x=(0,s.useCallback)(async()=>{m(!0),c(null);try{let e=[...(await a.missionsUnified()).missions].sort((e,t)=>e.createdAt<t.createdAt?1:-1);o(e)}catch(e){c(e instanceof Error?e.message:String(e))}finally{m(!1)}},[a]);(0,s.useEffect)(()=>{x()},[x]);let p=(0,s.useCallback)(()=>{x()},[x]),g=null!=(t=null==l?void 0:l.filter(e=>e.isAutopilot).length)?t:0,h=(null!=(n=null==l?void 0:l.length)?n:0)-g;return(0,r.jsxs)("div",{className:"space-y-3",children:[(0,r.jsxs)("div",{className:"flex items-center justify-between",children:[(0,r.jsxs)("p",{className:"text-sm text-muted-foreground",children:["모든 미션(사람 intake + 자율)의 계보\xb7실행 상태.",l&&(0,r.jsxs)("span",{className:"ml-1 text-[11px]",children:["자율 ",g," \xb7 사람 ",h]})]}),(0,r.jsx)(i.$,{onClick:()=>void x(),disabled:u,size:"sm",variant:"outline",children:u?"…":"새로고침"})]}),(0,r.jsx)(k,{api:a,onCommitted:()=>void x()}),d&&(0,r.jsx)("p",{className:"text-xs text-rose-400",children:d}),l&&0===l.length&&(0,r.jsx)("p",{className:"rounded-lg border border-dashed border-border p-6 text-center text-sm text-muted-foreground",children:"아직 미션이 없습니다. 위 “골 던지기”로 자율 미션을 만들거나, Intake 에서 메모를 포착하세요."}),l&&l.length>0&&(0,r.jsx)("div",{className:"space-y-2",children:l.map(e=>(0,r.jsx)(N,{api:a,m:e,onMutate:p},e.id))})]})}var S=n(5794);let C=[{id:"missions",label:"Missions"},{id:"autonomy",label:"자율행동"}];function z(e){var t;let{arming:n}=e;if(!n)return null;let s=(e,t)=>(0,r.jsxs)("span",{className:["rounded px-2 py-0.5 text-xs ring-1",e?"bg-emerald-500/15 text-emerald-300 ring-emerald-500/30":"bg-muted text-muted-foreground ring-border"].join(" "),children:[t," ",e?"ON":"OFF"]});return(0,r.jsxs)("div",{className:"flex flex-wrap items-center gap-2 text-xs text-muted-foreground",children:[(0,r.jsx)("span",{children:"자율 경계:"}),s(n.absorb,"흡수 PR초안(".concat(n.absorbBackend,")")),s(n.merge,"mandate merge"),s(n.reboot,"재부팅"),s(null!=(t=n.materialize)&&t,"자율 구체화"),(0,r.jsx)("span",{className:"text-[11px]",children:"\xb7 재부팅은 항상 HITL \xb7 기본 disarmed(fail-closed)"})]})}function I(){let{client:e}=(0,a.Q)(),t=(0,s.useMemo)(()=>new m.Yt(e),[e]),[n,i]=(0,s.useState)("missions"),[l,o]=(0,s.useState)(null);return(0,s.useEffect)(()=>{let e=!0;return t.arming().then(t=>{e&&o(t.arming)}).catch(()=>{}),()=>{e=!1}},[t]),(0,r.jsxs)("div",{className:"mx-auto max-w-[1400px] px-4 pt-4",children:[(0,r.jsx)("div",{className:"mb-3",children:(0,r.jsx)(S.r,{active:"autopilot"})}),(0,r.jsxs)("div",{className:"mb-3 space-y-2",children:[(0,r.jsxs)("h1",{className:"text-lg font-semibold",children:["Missions ",(0,r.jsx)("span",{className:"text-sm font-normal text-muted-foreground",children:"미션 지휘 센터 \xb7 Autopilot"})]}),(0,r.jsx)("p",{className:"text-sm text-muted-foreground",children:"미션(사람 + 자율)의 계보\xb7상태\xb7자율행동. 아래 “골 던지기” 또는 텔레그램 “미션:” 마커로 소망을 던지면 미션이 됩니다."}),(0,r.jsx)(z,{arming:l})]}),(0,r.jsx)("div",{className:"flex gap-1 border-b border-border",children:C.map(e=>(0,r.jsx)("button",{type:"button",onClick:()=>i(e.id),className:["-mb-px border-b-2 px-4 py-2 text-sm font-medium transition-colors",n===e.id?"border-primary text-foreground":"border-transparent text-muted-foreground hover:text-foreground"].join(" "),children:e.label},e.id))}),(0,r.jsxs)("div",{className:"py-4",children:["missions"===n&&(0,r.jsx)(w,{api:t}),"autonomy"===n&&(0,r.jsx)(d,{api:t})]})]})}function A(){return(0,r.jsx)(I,{})}},72248:(e,t,n)=>{"use strict";function r(e){let t=e.filter(e=>"cron"===e.kind&&e.id).map(e=>e.id);return t.length?"/scheduler?ids=".concat(t.map(encodeURIComponent).join(",")):null}n.d(t,{NE:()=>o,Yt:()=>l,on:()=>r});let s=["task","goal-loop","single-shot"],a=["scheduler","monitor-trigger"];function i(e){var t,n,r,i,l,o,d;let c=e.autopilot,u=null!=(t=null==c?void 0:c.executionModel)?t:null;return{id:e.id,goal:e.title||e.description||e.id,source:null!=(n=null==c?void 0:c.origin)?n:"human",status:null!=(r=null==c?void 0:c.apmStatus)?r:e.status,model:u,tier:null!=(i=null==c?void 0:c.tier)?i:null,engine:null!=(l=null==c?void 0:c.engine)?l:null,kind:(d=null!=(o=null==c?void 0:c.executionModel)?o:null)&&s.includes(d)?"finite":d&&a.includes(d)?"continuous":"other",reviewDue:!1,createdAt:new Date(e.createdAt).toISOString(),updatedAt:e.updatedAt,derived:e.derived,isAutopilot:null!=c,toxStatus:e.status,taskCount:e.taskCount,taskCounts:e.taskStatusCounts}}class l{async triagePreview(e,t){return this.client.fetchJson("/v1/autopilot/triage-preview",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({goal:e,...t?{category:t}:{}})})}async commitMission(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"intake",n=arguments.length>2?arguments[2]:void 0;return this.client.fetchJson("/v1/autopilot/triage-preview",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({goal:e,commit:!0,source:t,...n?{category:n}:{}})})}async missionsUnified(e){var t,n;let r=new URLSearchParams({...e?{status:e}:{}}).toString(),s=await this.client.fetchJson("/v1/missions".concat(r?"?".concat(r):"")),a=null!=(t=s.missions)?t:[];return{ok:!0,total:null!=(n=s.total)?n:a.length,missions:a.map(i)}}async trace(e){return this.client.fetchJson("/v1/autopilot/trace?id=".concat(encodeURIComponent(e)))}async missionArcMap(){var e,t,n;let r=await this.client.fetchJson("/v1/missions"),s=new Map;for(let a of null!=(e=r.missions)?e:[]){let e=null==(t=a.autopilot)?void 0:t.arcs;e&&e.length>0&&s.set(a.id,{apmStatus:null==(n=a.autopilot)?void 0:n.apmStatus,arcs:e})}return s}async missionAction(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return this.client.fetchJson("/v1/autopilot/mission-action",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({id:e,action:t,...n})})}async autonomy(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:50,t=arguments.length>1?arguments[1]:void 0,n=new URLSearchParams({limit:String(e),...t?{loop:t}:{}});return this.client.fetchJson("/v1/autopilot/autonomy?".concat(n.toString()))}async arming(){return this.client.fetchJson("/v1/autopilot/arming")}constructor(e){this.client=e}}let o={task:{label:"작업 분해",tone:"bg-sky-500/15 text-sky-200 ring-sky-500/30"},"goal-loop":{label:"목표 루프",tone:"bg-violet-500/15 text-violet-200 ring-violet-500/30"},scheduler:{label:"스케줄러",tone:"bg-emerald-500/15 text-emerald-200 ring-emerald-500/30"},"monitor-trigger":{label:"감시 트리거",tone:"bg-amber-500/15 text-amber-200 ring-amber-500/30"},hybrid:{label:"하이브리드",tone:"bg-fuchsia-500/15 text-fuchsia-200 ring-fuchsia-500/30"},fanout:{label:"병렬 팬아웃",tone:"bg-cyan-500/15 text-cyan-200 ring-cyan-500/30"},"single-shot":{label:"즉답",tone:"bg-muted text-muted-foreground ring-border"},"hitl-delegate":{label:"HITL 위임",tone:"bg-rose-500/15 text-rose-200 ring-rose-500/30"}}}},e=>{e.O(0,[8085,5194,4862,9638,2201,6356,7358],()=>e(e.s=29494)),_N_E=e.O()}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[7081],{8801:(e,t,s)=>{"use strict";s.d(t,{C:()=>c,DaemonProvider:()=>d,Q:()=>u});var a=s(77194),r=s(49954),n=s(9248),l=s(19631),o=s(49638),i=s(35857);let c=(0,r.createContext)(null);function d(e){let{children:t}=e,s={baseUrl:"",token:"",provider:""},[d,u]=(0,r.useState)(s),[m,p]=(0,r.useState)(""),[f]=(0,r.useState)(()=>new o.ki(s));(0,r.useEffect)(()=>{let e=(0,n.Fp)();u(e),f.updateConfig(e),p((0,l.oD)()),(0,i.cY)("webterm.provider.daemon.init",{baseUrl:e.baseUrl,hasToken:!!e.token})},[f]),(0,r.useEffect)(()=>{let e=e=>{if("elanous.daemon.token"===e.key||"elanous.nexus.baseUrl"===e.key){let t=(0,n.Fp)();f.updateConfig(t),u(t),(0,i.cY)("webterm.provider.daemon.config-cross-tab",{key:e.key,hasToken:!!t.token});return}"elanous.daemon.sessionId"===e.key&&e.newValue&&p(t=>t===e.newValue?t:((0,i.cY)("webterm.provider.daemon.session-cross-tab",{previous:t||"(empty)",next:e.newValue}),e.newValue))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)},[f]);let h=e=>{u(t=>{let s={...t,...e};return(0,n.Qc)(e),f.updateConfig(s),(0,i.cY)("webterm.provider.daemon.config-update",{keys:Object.keys(e)}),s})},x=e=>{p(e),localStorage.setItem("elanous.daemon.sessionId",e),(0,i.cY)("webterm.provider.daemon.session-set",{sessionId:e})},g=(0,r.useMemo)(()=>({config:d,setConfig:h,client:f,sessionId:m,setSessionId:x}),[d,f,m]);return(0,a.jsx)(c.Provider,{value:g,children:t})}function u(){let e=(0,r.useContext)(c);if(!e)throw Error("useDaemon must be used inside <DaemonProvider>");return e}},19631:(e,t,s)=>{"use strict";s.d(t,{Zr:()=>l,f6:()=>r,oD:()=>n});let a="elanous.daemon.sessionId";function r(){return"undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID?crypto.randomUUID():"s-".concat(Date.now().toString(36),"-").concat(Math.random().toString(36).slice(2,10))}function n(){let e=function(){let e=new URLSearchParams(window.location.search).get("session");return e?(localStorage.setItem(a,e),e):localStorage.getItem(a)}();if(e)return e;let t=r();return localStorage.setItem(a,t),t}function l(){let e=r();return localStorage.setItem(a,e),e}},35464:(e,t,s)=>{"use strict";s.r(t),s.d(t,{default:()=>k});var a=s(77194),r=s(73158);function n(e){return e.map(e=>({...(0,r.cj)(e,[]),taskId:e.taskId,...e.wishReply?{wishReply:{surface:e.wishReply.surface,address:null}}:{}}))}var l=s(49954),o=s(8801);function i(e){var t;for(let t of[e.sections.triage,e.sections.intake]){let e=null==t?void 0:t.data.title;if("string"==typeof e&&e.trim())return e.trim()}return(null==(t=e.apiTitle)?void 0:t.trim())||e.taskId}var c=s(45785);let d={green:"순항",yellow:"진행 중",red:"막힘",done:"완료"},u=["intake","triage","gates","relations","memory","workspace","run","landing","release"];function m(e){return null==e?"—":"string"==typeof e?e:JSON.stringify(e)}function p(e){let{entry:t}=e;return(0,a.jsxs)("details",{className:"mt-2 text-xs",children:[(0,a.jsx)("summary",{className:"cursor-pointer text-muted-foreground",children:"JSON"}),(0,a.jsx)("pre",{className:"mt-2 max-h-64 overflow-auto rounded-lg bg-muted p-2 text-xs whitespace-pre-wrap break-all",children:JSON.stringify(t.data,null,2)})]})}function f(e){let{entry:t}=e,s=new Date(t.ts).toISOString();return(0,a.jsxs)("div",{className:"flex flex-wrap gap-x-3 gap-y-1 text-xs text-muted-foreground",children:[(0,a.jsxs)("span",{children:["Owner: ",t.owner]}),(0,a.jsx)("time",{dateTime:s,children:s})]})}function h(e){var t,s,r;let{card:n,placements:o,onClose:c,publicCapture:h=!1}=e,[x,g]=(0,l.useState)(""),[b,y]=(0,l.useState)(!1),[w,k]=(0,l.useState)(null),v=async e=>{if(e.preventDefault(),!(!c||!x.trim()||/[\r\n]/.test(x))&&!b){y(!0),k(null);try{await c(x.trim())}catch(e){k(e instanceof Error?e.message:String(e))}finally{y(!1)}}},j=null==(t=n.sections.gates)?void 0:t.data;return(0,a.jsxs)("section",{"aria-label":"Task card detail",className:"min-w-0 space-y-4 rounded-2xl border border-border bg-card p-4",children:[(0,a.jsxs)("header",{children:[(0,a.jsx)("h2",{className:"text-lg font-semibold",children:i(n)}),(0,a.jsx)("p",{className:"break-all text-xs text-muted-foreground",children:n.taskId}),"closed"===n.status?(0,a.jsxs)("p",{role:"status",children:["닫힘 \xb7 ",null!=(s=n.closedReason)?s:"사유 없음"]}):!h&&c?(0,a.jsxs)("form",{onSubmit:v,className:"mt-3 flex flex-wrap items-end gap-2",children:[(0,a.jsxs)("label",{className:"text-sm",children:["닫기 사유 (한 줄)",(0,a.jsx)("input",{type:"text",required:!0,value:x,onChange:e=>g(e.target.value),className:"block rounded-md border border-border bg-background px-2 py-1"})]}),(0,a.jsx)("button",{type:"submit",disabled:b||!x.trim()||/[\r\n]/.test(x),className:"rounded-md border border-border px-3 py-1 text-sm",children:b?"닫는 중…":"닫기"}),w&&(0,a.jsx)("p",{role:"alert",className:"text-sm text-destructive",children:w})]}):null]}),void 0!==n.wishReply&&(0,a.jsxs)("section",{"aria-label":"Wish reply destination",className:"rounded-xl border border-border p-3 text-sm",children:[(0,a.jsx)("h3",{className:"mb-1 font-semibold",children:"어디로 회신하나"}),(0,a.jsx)("p",{className:"break-all",children:n.wishReply?"".concat(null!=(r=({telegram:"텔레그램 대화",pwa:"PWA",tui:"TUI",linear:"Linear"})[n.wishReply.surface])?r:n.wishReply.surface).concat(n.wishReply.address?" \xb7 ".concat(n.wishReply.address):""):"회신 주소 없음"})]}),void 0!==n.wishReply&&(0,a.jsxs)("section",{"aria-label":"Wish reply history",className:"rounded-xl border border-border p-3 text-sm",children:[(0,a.jsx)("h3",{className:"mb-1 font-semibold",children:"회신 이력"}),(0,a.jsx)("p",{className:"text-muted-foreground",children:"카드 원장에는 회신 발송 이력이 기록되지 않습니다"})]}),o&&(0,a.jsxs)("p",{className:"overflow-x-auto whitespace-nowrap text-sm","aria-label":"Wish placement and progress",children:["배치 \xb7 ",o.length?o.map(e=>{let{cellId:t,cellTitle:s,version:a,status:r}=e;return"".concat(t," ").concat(s," \xb7 ").concat(a,"판 \xb7 ").concat(d[r])}).join(" / "):"아직 배치되지 않음"]}),j&&(0,a.jsxs)("p",{className:"overflow-x-auto whitespace-nowrap text-sm","aria-label":"Gate decisions",children:["Gate \xb7 budget: ",m(j.budget)," \xb7 location: ",m(j.location)]}),u.map(e=>{let t=n.sections[e];return t?(0,a.jsxs)("section",{"aria-label":"".concat(e," section"),className:"rounded-xl border border-border p-3",children:[(0,a.jsx)("h3",{className:"mb-1 text-sm font-semibold capitalize",children:e}),(0,a.jsx)(f,{entry:t}),(0,a.jsx)(p,{entry:t})]},e):null}),(0,a.jsxs)("section",{"aria-label":"Incidents",className:"space-y-2",children:[(0,a.jsxs)("h3",{className:"text-sm font-semibold",children:["Incidents (",n.incidents.length,")"]}),n.incidents.length?(0,a.jsx)("ol",{className:"space-y-2",children:n.incidents.map(e=>(0,a.jsxs)("li",{className:"rounded-xl border border-border p-3",children:[(0,a.jsx)(f,{entry:e}),(0,a.jsx)(p,{entry:e})]},e.key))}):(0,a.jsx)("p",{className:"text-xs text-muted-foreground",children:"No incidents."})]})]})}let x=["steward","execution","landing","release","done"],g=new Set(["intake","triage","gates","relations","memory","workspace","run","landing","release","incidents"]);function b(e){let t=[],s=Date.parse(e.createdAt),a=e.sections.find(e=>"intake:reply:0"===e.key),r=null;if(a)try{let e=JSON.parse(a.content);if(e&&"object"==typeof e&&!Array.isArray(e)){let{surface:t,address:s}=e;"string"==typeof t&&("string"==typeof s||null===s)&&(r={surface:t,address:s})}}catch(e){}for(let a of e.sections){let r;if(!g.has(a.key))continue;try{let e=JSON.parse(a.content);r=e&&"object"==typeof e&&!Array.isArray(e)?e:{content:a.content}}catch(e){r={content:a.content}}let n=Date.parse(a.createdAt);t.push({taskId:e.id,section:a.key,key:"".concat(a.key,":").concat(a.createdAt,":").concat(t.length),owner:a.owner,ts:Number.isFinite(n)?n:s,data:r,..."string"==typeof r.runId?{runId:r.runId}:{}})}if(0===t.length&&t.push({taskId:e.id,section:"triage",key:"api:title",owner:"task-card API",ts:s,data:{title:e.title}}),"closed"===e.status){let a=t.filter(e=>"release"===e.section).sort((e,t)=>t.ts-e.ts)[0];t.push({taskId:e.id,section:"release",key:"api:closed",owner:"task-card API",ts:Math.max(s,...t.map(e=>e.ts)),data:{...null==a?void 0:a.data,status:"done"}})}return{...function(e){let t,s=e[0];if(!s)return null;let a={},r=[],n=new Set,l=s.ts,o=-1/0;for(let i of e)if(!(i.taskId!==s.taskId||n.has(i.key)))if(n.add(i.key),l=Math.max(l,i.ts),i.runId&&i.ts>=o&&(t=i.runId,o=i.ts),"incidents"===i.section)r.push(i);else{let e=a[i.section];(!e||i.ts>=e.ts)&&(a[i.section]=i)}return{taskId:s.taskId,sections:a,incidents:r,updatedAt:l,...t?{runId:t}:{}}}(t),apiTitle:e.title,status:e.status,...void 0===e.closedReason?{}:{closedReason:e.closedReason},...e.goalId.startsWith("wish:")?{wishReply:r}:{}}}function y(e){let{cards:t,selectedId:s,onSelect:r,selectedCard:n,detailError:l,placements:o,onCloseCard:c,publicCapture:d}=e,u=(null==n?void 0:n.taskId)===s?n:null;return(0,a.jsxs)("div",{className:"space-y-4 p-4",children:[(0,a.jsx)("h1",{className:"text-xl font-semibold",children:"보드"}),(0,a.jsx)("div",{className:"grid gap-3 md:grid-cols-2 xl:grid-cols-5",children:x.map(e=>(0,a.jsxs)("section",{"aria-label":"".concat(e," column"),className:"min-w-0 space-y-2 rounded-xl border border-border p-3",children:[(0,a.jsx)("h2",{className:"text-sm font-semibold capitalize",children:e}),t.filter(t=>(function(e){var t;let s=null==(t=e.sections.release)?void 0:t.data;return(null==s?void 0:s.status)==="done"||(null==s?void 0:s.status)==="completed"?"done":s?"release":e.sections.landing?"landing":e.sections.run||e.sections.workspace||e.sections.gates||e.sections.relations||e.sections.memory?"execution":"steward"})(t)===e).map(e=>{var t,n;return(0,a.jsxs)("button",{type:"button",onClick:()=>r(e.taskId),"aria-pressed":s===e.taskId,className:"w-full rounded-lg border border-border bg-card p-3 text-left text-sm hover:bg-accent/40",children:[(0,a.jsx)("span",{className:"block font-medium",children:i(e)}),(0,a.jsx)("span",{className:"block text-xs text-muted-foreground",children:(0,a.jsx)("time",{dateTime:new Date(e.updatedAt).toISOString(),title:new Date(e.updatedAt).toLocaleString(),children:(t=function(e){let t=new Map;for(let a of e.incidents){var s;let e=null!=(s=a.data.incidentId)?s:a.data.id,r="string"==typeof e&&e.trim()?e:a.key,n=t.get(r);(!n||a.ts>=n.ts)&&t.set(r,a)}return Array.from(t.values()).filter(e=>"closed"!==e.data.status&&"resolved"!==e.data.status).length}(e),n=Date.now(),[...t>0?["사고 ".concat(t)]:[],...e.runId?["런 ".concat(e.runId.replace(/^run-/,"").slice(0,8))]:[],function(e,t,s){let a=Math.floor((t-e)/6e4);if(!Number.isFinite(a)||a<1)return"방금";if(a<60)return"".concat(a,"분 전");if(a<1440)return"".concat(Math.floor(a/60),"시간 전");let r=new Intl.DateTimeFormat("ko-KR",{month:"numeric",day:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1,...s?{timeZone:s}:{}}).formatToParts(new Date(e)),n=e=>{var t,s;return null!=(s=null==(t=r.find(t=>t.type===e))?void 0:t.value)?s:""};return"".concat(n("month"),"/").concat(n("day")," ").concat(n("hour"),":").concat(n("minute"))}(e.updatedAt,n,void 0)]).join(" \xb7 ")})})]},e.taskId)})]},e))}),s&&(0,a.jsxs)("aside",{className:"max-w-3xl space-y-2","aria-label":"Selected card",children:[(0,a.jsx)("button",{type:"button",onClick:()=>r(null),"aria-label":"Close card detail",className:"text-sm text-muted-foreground",children:"Close"}),u?(0,a.jsx)(h,{card:u,placements:o,onClose:c,publicCapture:d}):(0,a.jsx)("p",{role:"status",children:null!=l?l:"Loading card detail…"})]})]})}function w(){let{config:e}=(0,o.Q)(),t=(0,l.useMemo)(()=>e.baseUrl?(0,c.xX)({baseUrl:e.baseUrl,...e.token?{token:e.token}:{}}):null,[e.baseUrl,e.token]),[s,i]=(0,l.useState)([]),[d,u]=(0,l.useState)(null),[m,p]=(0,l.useState)(null),[f,h]=(0,l.useState)(void 0),[x,g]=(0,l.useState)(null),[w,k]=(0,l.useState)(null),[v,j]=(0,l.useState)(!1);(0,l.useEffect)(()=>{"public"===new URLSearchParams(window.location.search).get("capture")&&j(!0)},[]);let N=(0,l.useMemo)(()=>v?n(s):s,[s,v]),I=v&&m?n([m])[0]:m,S=v&&f?(0,r.cj)(f,[]):f;(0,l.useEffect)(()=>{let e=!1;if(i([]),u(null),p(null),h(void 0),g(null),!t)return void k("Connect to NEXUS to load task cards.");k(null);let s=()=>t.getTaskCards().then(t=>{let{cards:s}=t;e||(i(s.map(b)),k(null))}).catch(t=>{e||k(t instanceof c.Iu&&404===t.status?"Task cards are not available yet (pre-E1).":t instanceof Error?t.message:String(t))});s();let a=setInterval(()=>{s()},1e4);return()=>{e=!0,clearInterval(a)}},[t]),(0,l.useEffect)(()=>{if(!t||!d)return;let e=!1;return p(null),h(void 0),g(null),t.getTaskCard(d).then(t=>{let{card:s,placements:a}=t;e||(h(a),p(b(s)))}).catch(t=>{e||g(t instanceof Error?t.message:String(t))}),()=>{e=!0}},[t,d]);let C=async e=>{if(!t||!d||v)throw Error("Card close unavailable");let{card:s}=await t.closeTaskCard(d,e);p(e=>(null==e?void 0:e.taskId)===d?b(s):e),i(e=>e.map(e=>e.taskId===s.id?b(s):e))};return(0,a.jsxs)(a.Fragment,{children:[w&&(0,a.jsx)("p",{role:"status",className:"p-4 text-sm text-muted-foreground",children:w}),(0,a.jsx)(y,{cards:N,selectedId:d,selectedCard:I,detailError:x,placements:S,onSelect:e=>{(null===e||d!==e)&&(p(null),h(void 0),g(null),u(e))},onCloseCard:C,publicCapture:v})]})}function k(){return(0,a.jsx)(w,{})}},48731:(e,t,s)=>{Promise.resolve().then(s.bind(s,35464))},73158:(e,t,s)=>{"use strict";s.d(t,{Er:()=>r,cj:()=>c,dc:()=>l,yR:()=>i});let a=/^(oauth\.|harness\.decision|llm\.router)/;function r(e){let t=[],s=e=>{"string"==typeof e&&e.trim()&&!t.includes(e.trim())&&t.push(e.trim())};for(let t of e){var r;let e=null!=(r=t.data)?r:{};if(t.category.startsWith("oauth.")){for(let t of["from","to","name","account"])s(e[t]);if(Array.isArray(e.usage))for(let t of e.usage)s(null==t?void 0:t.name);continue}if(a.test(t.category))for(let t of(s(e.account),["what","why","reason"])){let a=e[t];if("string"==typeof a)for(let e of a.matchAll(/계정\s+([A-Za-z0-9][\w.-]*)/g))s(e[1])}}return t}function n(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function l(e){let t=new Map(e.map((e,t)=>[e,"account-".concat(t+1)])),s=e.length?RegExp("(^|[^\\w-])(".concat(e.map(n).sort((e,t)=>t.length-e.length).join("|"),")(?![\\w-])"),"g"):null,a=new Map;return(e,r)=>{let n=e.replace(/\b[a-z0-9-]+\.tail[0-9a-f]+\.ts\.net\b/gi,"tailnet-host").replace(/\bmsb\d+\b/gi,e=>(e=>{let t=e.toLowerCase();a.has(t)||a.set(t,"remote-".concat(a.size+1));let s=a.get(t);return e===e.toUpperCase()?s.toUpperCase():s})(e)).replace(/\bmbp\b/gi,e=>e===e.toUpperCase()?"LOCAL":"local").replace(/\/Users\/[^/\s"']+/g,"~").replace(/(크레딧|credits?|💳)(\s*[:=]?\s*)[\d][\d,.]*/gi,"$1$2•••").replace(/[\d][\d,.]*(\s*)(크레딧|credits?)/gi,"•••$1$2").replace(/\$\s?[\d][\d,.]*/g,"$•••").replace(/(잔량?|remaining|left)(\s*[:=]?\s*)(?:[A-Za-z0-9][\w.-]*\s+)?\d+(?:\.\d+)?\s?%/gi,"$1$2•••");return r&&s&&(n=n.replace(s,(e,s,a)=>{var r;return"".concat(s).concat(null!=(r=t.get(a))?r:"account")})),n}}function o(e,t){if("string"==typeof e)return t(e);if(Array.isArray(e))return e.map(e=>o(e,t));if(e&&"object"==typeof e){let s={};for(let[a,r]of Object.entries(e))"apiEquivalentUsd"===a||"usd"===a||/credit(s|Balance)?$/i.test(a)||(s[a]=o(r,t));return s}return e}function i(e){let t=l(r(e));return e.map(e=>{let s=a.test(e.category);return{...e,event:t(e.event,!1),data:e.data?o(e.data,e=>t(e,s)):e.data}})}function c(e,t){let s=l(t);return o(e,e=>s(e,!0))}}},e=>{e.O(0,[9638,5785,2201,6356,7358],()=>e(e.s=48731)),_N_E=e.O()}]);
|