zigrix 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +10 -2
  2. package/dist/dashboard/.next/BUILD_ID +1 -1
  3. package/dist/dashboard/.next/app-build-manifest.json +22 -22
  4. package/dist/dashboard/.next/app-path-routes-manifest.json +1 -1
  5. package/dist/dashboard/.next/build-manifest.json +5 -5
  6. package/dist/dashboard/.next/prerender-manifest.json +10 -10
  7. package/dist/dashboard/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  8. package/dist/dashboard/.next/server/app/_not-found.html +1 -1
  9. package/dist/dashboard/.next/server/app/_not-found.rsc +1 -1
  10. package/dist/dashboard/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  11. package/dist/dashboard/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  12. package/dist/dashboard/.next/server/app/api/auth/session/route_client-reference-manifest.js +1 -1
  13. package/dist/dashboard/.next/server/app/api/auth/setup/route_client-reference-manifest.js +1 -1
  14. package/dist/dashboard/.next/server/app/api/overview/route_client-reference-manifest.js +1 -1
  15. package/dist/dashboard/.next/server/app/api/stream/route_client-reference-manifest.js +1 -1
  16. package/dist/dashboard/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  17. package/dist/dashboard/.next/server/app/api/tasks/[taskId]/conversation/route_client-reference-manifest.js +1 -1
  18. package/dist/dashboard/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  19. package/dist/dashboard/.next/server/app/login/page_client-reference-manifest.js +1 -1
  20. package/dist/dashboard/.next/server/app/login.html +1 -1
  21. package/dist/dashboard/.next/server/app/login.rsc +1 -1
  22. package/dist/dashboard/.next/server/app/page.js +2 -2
  23. package/dist/dashboard/.next/server/app/page_client-reference-manifest.js +1 -1
  24. package/dist/dashboard/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  25. package/dist/dashboard/.next/server/app/setup.html +1 -1
  26. package/dist/dashboard/.next/server/app/setup.rsc +1 -1
  27. package/dist/dashboard/.next/server/app-paths-manifest.json +1 -1
  28. package/dist/dashboard/.next/server/chunks/331.js +1 -1
  29. package/dist/dashboard/.next/server/chunks/972.js +1 -1
  30. package/dist/dashboard/.next/server/functions-config-manifest.json +4 -4
  31. package/dist/dashboard/.next/server/middleware-build-manifest.js +1 -1
  32. package/dist/dashboard/.next/server/middleware.js +1 -1
  33. package/dist/dashboard/.next/server/pages/404.html +1 -1
  34. package/dist/dashboard/.next/server/pages/500.html +1 -1
  35. package/dist/dashboard/.next/server/pages/_error.js +1 -1
  36. package/dist/dashboard/.next/static/chunks/{255-ebd51be49873d76c.js → 255-4f212684648fcab9.js} +1 -1
  37. package/dist/dashboard/.next/static/chunks/app/page-0104be5a259641e4.js +1 -0
  38. package/dist/dashboard/.next/static/chunks/main-cec07dc17fdd452c.js +1 -0
  39. package/dist/dashboard/.next/static/css/{c3a7306cb2ba3f6c.css → 819f4ef2c68a9009.css} +1 -1
  40. package/dist/dashboard/package.json +2 -2
  41. package/dist/index.js +25 -2
  42. package/dist/onboard.d.ts +1 -1
  43. package/dist/onboard.js +2 -2
  44. package/dist/orchestration/dispatch.js +16 -71
  45. package/dist/orchestration/prompt-compose.d.ts +35 -0
  46. package/dist/orchestration/prompt-compose.js +172 -0
  47. package/dist/orchestration/worker.d.ts +4 -1
  48. package/dist/orchestration/worker.js +132 -52
  49. package/dist/state/tasks.d.ts +6 -0
  50. package/dist/state/tasks.js +39 -0
  51. package/package.json +3 -3
  52. package/rules/defaults/orchestrator-agent.md +4 -2
  53. package/rules/defaults/worker-common.md +3 -0
  54. package/skills/oz/SKILL.md +117 -0
  55. package/skills/oz/references/examples.md +44 -0
  56. package/skills/oz/references/routing-rubric.md +71 -0
  57. package/skills/zigrix-main-agent-guide/SKILL.md +37 -7
  58. package/dist/dashboard/.next/static/chunks/app/page-0314989c31e18b4b.js +0 -1
  59. package/dist/dashboard/.next/static/chunks/main-da2d845a416cfa3f.js +0 -1
  60. /package/dist/dashboard/.next/static/{EZjkAnODdTglaMXuBw76E → j9XNuQEcfIYIh8oRB9Yp_}/_buildManifest.js +0 -0
  61. /package/dist/dashboard/.next/static/{EZjkAnODdTglaMXuBw76E → j9XNuQEcfIYIh8oRB9Yp_}/_ssgManifest.js +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigrix",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "type": "module",
5
5
  "description": "Multi-project parallel task orchestration CLI for agent-assisted development",
6
6
  "license": "Apache-2.0",
@@ -70,11 +70,11 @@
70
70
  "@inquirer/prompts": "^8.3.2",
71
71
  "bcryptjs": "^2.4.3",
72
72
  "commander": "^14.0.0",
73
- "next": "^15.2.3",
73
+ "next": "^15.5.15",
74
74
  "react": "^19.0.0",
75
75
  "react-dom": "^19.0.0",
76
76
  "react-markdown": "^10.1.0",
77
- "yaml": "^2.8.1",
77
+ "yaml": "^2.8.3",
78
78
  "zod": "^4.1.5"
79
79
  },
80
80
  "devDependencies": {
@@ -1,6 +1,7 @@
1
1
  # orchestrator-agent Rules (Orchestrator)
2
2
 
3
3
  > orchestrator-agent는 오케스트레이터로서 worker-common이 아닌 자체 규칙을 따른다.
4
+ > 이 문서 안의 `frontend-agent`/`backend-agent`/`qa-agent`/`orchestrator-agent` 표기는 **role label 예시**다. 실제 runtime agentId는 dispatch overlay의 `roleAgentMap`, `orchestratorId`, `qaAgentId`를 따른다.
4
5
 
5
6
  ## 1) Mission
6
7
  - 사용자 개발 요청을 `simple|normal|risky|large`로 분류하고,
@@ -23,7 +24,8 @@
23
24
  11. **오케스트레이션 파이프라인 필수 경유:**
24
25
  - 작업은 `zigrix task dispatch`로 등록한 상태에서만 수신
25
26
  - 오케스트레이션 미등록(taskId/spec 미존재) 작업은 수행 거부
26
- 12. **CLI 체인 워크플로우 (필수):**
27
+ 12. **메인 전용 스킬 사용 금지:** `zigrix-main-agent-guide`는 main agent 전용이며, orchestrator runtime 세션은 dispatch prompt + Zigrix role rule만 canonical instruction으로 사용한다.
28
+ 13. **CLI 체인 워크플로우 (필수):**
27
29
  - orchestrator-agent의 task prompt(boot prompt)는 **`zigrix task start` 실행 지시**만 포함한다.
28
30
  - **태스크 메타 및 dispatch prompt가 태스크 브리핑이자 작업 지시서**이다.
29
31
  - 모든 상태 추적은 CLI 체인을 통해 자동 기록된다.
@@ -33,7 +35,7 @@
33
35
  1. **착수:** `zigrix task start <taskId> --json`
34
36
  2. **태스크 경로 확인:** `zigrix task status <taskId> --json` → `specPath`, `metaPath`, `projectDir` 확보
35
37
  3. **워커 prompt 생성:** `zigrix worker prepare --task-id <taskId> --agent-id <workerId> --description "..." --json` → `promptPath`, `specPath`, `metaPath`, `projectDir`를 확인하고 sessions_spawn에 prompt를 전달
36
- 4. **워커 등록:** `zigrix worker register --task-id <taskId> --agent-id <workerId> --session-key <key> --run-id <rid>` → 다음 행동 출력
38
+ 4. **워커 등록:** `zigrix worker register --task-id <taskId> --agent-id <workerId> --session-key <key> --label <spawnLabel> --project-dir <projectDir> --run-id <rid>` → 다음 행동 출력
37
39
  5. **워커 완료:** `zigrix worker complete --task-id <taskId> --agent-id <workerId> --session-key <key> --run-id <rid>` → 완료 여부 + 다음 행동 출력
38
40
  6. **최종 보고:** `zigrix task finalize <taskId> --auto-report`
39
41
  13. task는 크게 유지하고 내부 실행은 `workPackages[]` + `executionUnits[]`로 세분화한다.
@@ -1,5 +1,7 @@
1
1
  # Worker Common Rules (front/back/sys/sec/qa)
2
2
 
3
+ > 이 문서 안의 역할명은 role label 기준이다. 실제 runtime agentId / projectDir / task context는 worker overlay prompt를 우선 따른다.
4
+
3
5
  ## 1) Mission
4
6
  - orchestrator-agent가 분배한 task를 역할 범위 내에서 수행하고,
5
7
  - 결과를 검증 가능한 증적과 함께 반환한다.
@@ -13,6 +15,7 @@
13
15
  6. **모든 문제는 근본적인 해결을 원칙으로 한다. 임시방편(workaround) 금지.**
14
16
  7. **오케스트레이션 필수 (owner 고정, 2026-03-04):** 오케스트레이션에 등록되지 않은 작업은 수행 거부. 확인은 `zigrix task status <taskId> --json`의 성공 여부와 반환된 `specPath`/`metaPath`를 기준으로 한다. taskId가 있더라도 조회가 실패하면 orchestrator-agent에 확인 요청.
15
17
  8. **CLI 체인 정합:** 워커 lifecycle 기록(`worker_dispatched`/`worker_done`/`worker_skipped`)은 orchestrator-agent가 `zigrix worker prepare → zigrix worker register → zigrix worker complete` 체인으로 처리한다.
18
+ 9. **메인 전용 스킬 사용 금지:** `zigrix-main-agent-guide`는 main agent 전용이며, worker runtime 세션은 worker overlay prompt + Zigrix role rule만 canonical instruction으로 사용한다.
16
19
  9. **Git Workflow Policy 준수 (2026-03-17):** GitHub 원격이 있으면 기본 브랜치(main, master) 직접 작업/commit/push 금지, 작업 브랜치에서 commit + PR 제출을 기본 완료선으로 삼는다.
17
20
  10. **완료 상태 불변성 (2026-03-17):** `REPORTED` task에 대한 후행 completion/event는 상태 전이를 만들지 않는다. 워커는 중복 완료 알림이 와도 추가 상태 변경 시도를 하지 않고 NO-OP로 처리한다.
18
21
  11. **Git 조작 금지 (2026-03-23):** non-orchestrator 역할 워커(frontend/backend/system/security/qa)는 `git commit`, `git push`, `git branch`, `git checkout -b`, PR 생성 등 **Git 상태를 변경하는 모든 조작을 수행하지 않는다.** 워커의 역할은 파일 수정/생성/삭제까지이며, 작업 완료 시 **변경된 파일 목록**을 orchestrator 역할에 반환한다. commit/push/PR은 orchestrator가 QA 통과 확인 후 전담한다.
@@ -0,0 +1,117 @@
1
+ ---
2
+ name: oz
3
+ version: 0.2.0
4
+ description: Official OpenClaw Zigrix entrypoint. Force Zigrix delegation when a message starts with `/oz`, and semantically route plain-language requests to hand work off, assign it, or have Zigrix take it instead of doing the work directly.
5
+ metadata:
6
+ openclaw:
7
+ requires:
8
+ bins: ["zigrix"]
9
+ cliHelp: "zigrix task dispatch --help"
10
+ ---
11
+
12
+ # /oz — OpenClaw Zigrix Entrypoint
13
+
14
+ Use this skill when either of the following is true:
15
+
16
+ 1. the user message starts with `/oz `
17
+ 2. the user is clearly asking, in natural language, to have work **delegated / handed off / assigned / orchestrated through Zigrix** instead of having the current main agent do it directly
18
+
19
+ This skill is the public OpenClaw-facing entrypoint for Zigrix after `zigrix onboard` installs bundled skills.
20
+
21
+ ## 1) Route selection
22
+
23
+ ### `/oz` prefix
24
+ If the message starts with `/oz `, treat it as:
25
+ - `route = delegate`
26
+ - `delegateMode = force`
27
+
28
+ Remove the `/oz` prefix and use the remaining text as the delegation payload.
29
+
30
+ ### Natural-language delegation
31
+ If there is no `/oz` prefix, judge the user's intent **semantically**.
32
+
33
+ - Use the full meaning of the request and nearby context.
34
+ - Do **not** rely on keyword tables or regex lists as the decision mechanism.
35
+ - When helpful, read:
36
+ - `references/routing-rubric.md`
37
+ - `references/examples.md`
38
+
39
+ Classify the turn into one of:
40
+ - `delegate`
41
+ - `direct`
42
+ - `answer`
43
+
44
+ ### Semantic routing policy
45
+ - Choose **`delegate`** when the user wants work to be handed off, assigned, orchestrated, or otherwise run through Zigrix rather than performed directly by the current main agent.
46
+ - Choose **`direct`** only when the user explicitly wants the current agent to do it directly.
47
+ - Choose **`answer`** when the user is asking for explanation, status, architecture, policy, or other non-execution discussion.
48
+ - If the request is ambiguous but points toward tracked execution / implementation / multi-step change, bias toward `delegate` unless the user explicitly asked for direct execution.
49
+
50
+ ## 2) Delegate flow
51
+
52
+ If `route = delegate`, use the canonical Zigrix handoff chain:
53
+
54
+ 1. Turn the user request into:
55
+ - `title`
56
+ - `description`
57
+ - `scale`
58
+ - optional `projectDir`
59
+ 2. Run:
60
+
61
+ ```bash
62
+ zigrix task dispatch \
63
+ --title "..." \
64
+ --description "..." \
65
+ --scale simple|normal|risky|large \
66
+ --project-dir /path/to/project \
67
+ --json
68
+ ```
69
+
70
+ 3. Read the JSON result and extract:
71
+ - `taskId`
72
+ - `orchestratorId`
73
+ - `orchestratorPrompt`
74
+ - `projectDir`
75
+ 4. Spawn the orchestrator with the returned prompt.
76
+
77
+ Preferred pattern:
78
+
79
+ ```text
80
+ sessions_spawn(
81
+ agentId: <orchestratorId>,
82
+ mode: "session",
83
+ thread: true when the current surface supports stable Zigrix thread orchestration, otherwise false,
84
+ label: "[<orchestratorId>] <taskId>",
85
+ task: <orchestratorPrompt>,
86
+ cwd: <projectDir when present>
87
+ )
88
+ ```
89
+
90
+ 5. Reply briefly with the handoff result (`taskId`, orchestrator/session/thread info).
91
+
92
+ ## 3) Delegate-only guard
93
+
94
+ Once this skill decides `route = delegate`:
95
+ - do **not** directly implement the task
96
+ - do **not** directly edit/write project files as a substitute for Zigrix handoff
97
+ - do **not** fallback to direct execution if dispatch or spawn fails
98
+
99
+ If dispatch or spawn fails:
100
+ - report the failure clearly
101
+ - include the failing step
102
+ - stop there
103
+
104
+ ## 4) Empty or underspecified payloads
105
+
106
+ If `/oz` is used but the remaining payload is empty or too underspecified to create a task:
107
+ - ask the user to restate the task in one clear sentence
108
+ - do not silently guess
109
+ - do not direct-execute instead
110
+
111
+ ## 5) Direct / answer cases
112
+
113
+ If semantic routing chooses:
114
+ - `direct` → current agent may proceed with direct execution
115
+ - `answer` → answer normally without creating a Zigrix task
116
+
117
+ This skill exists to decide **whether the request should enter Zigrix orchestration** and, when yes, to force the canonical delegation path.
@@ -0,0 +1,44 @@
1
+ # `/oz` Routing Examples
2
+
3
+ These examples are here to anchor semantic routing. They are examples, not an exhaustive phrase list.
4
+
5
+ ## Force delegate
6
+ - `/oz 로그인 세션 버그 고쳐`
7
+ - `/oz hand this to Zigrix and fix the auth flow`
8
+ - `/oz investigate why onboard is skipping skills`
9
+
10
+ Expected route: `delegate`
11
+
12
+ ## Natural-language delegate
13
+ - `이거 맡겨`
14
+ - `이 작업 위임해라`
15
+ - `오케스트레이터로 넘겨서 처리해`
16
+ - `이건 네가 직접 하지 말고 Zigrix로 태워`
17
+ - `hand this off`
18
+ - `route this through Zigrix`
19
+ - `assign this to the orchestrator`
20
+
21
+ Expected route: `delegate`
22
+
23
+ ## Direct execution
24
+ - `이건 네가 직접 해`
25
+ - `위임하지 말고 지금 네가 수정해`
26
+ - `don’t delegate this, do it yourself`
27
+
28
+ Expected route: `direct`
29
+
30
+ ## Answer only
31
+ - `왜 task dispatch 다음에 sessions_spawn이 필요한데?`
32
+ - `현재 Zigrix/OpenClaw 통합 구조 설명해라`
33
+ - `what does zigrix onboard actually register?`
34
+
35
+ Expected route: `answer`
36
+
37
+ ## Ambiguous but execution-oriented
38
+ - `로그인 버그 고쳐`
39
+ - `이 이슈 조사해서 정리해`
40
+ - `세션/thread 진입점 구조 정리하고 필요한 수정 진행해`
41
+
42
+ Default bias:
43
+ - if the surrounding context implies tracked orchestration / handoff, choose `delegate`
44
+ - if the surrounding context clearly asks the current agent to do it directly, choose `direct`
@@ -0,0 +1,71 @@
1
+ # `/oz` Semantic Routing Rubric
2
+
3
+ This reference exists to keep natural-language delegation routing **semantic-first**.
4
+
5
+ ## Core principle
6
+ Do **not** implement delegation routing as a keyword table or regex checklist.
7
+
8
+ Instead, decide from the user's **meaning**:
9
+ - who should own the work
10
+ - whether execution is being requested
11
+ - whether the user wants Zigrix/orchestration/another agent to take the task
12
+ - whether the user is explicitly asking for direct execution instead
13
+
14
+ ## Route categories
15
+
16
+ ### 1) `delegate`
17
+ Choose `delegate` when the user wants work to be:
18
+ - handed off
19
+ - assigned
20
+ - orchestrated
21
+ - run through Zigrix
22
+ - taken by another agent / worker / orchestrator
23
+
24
+ Also choose `delegate` when the request is clearly about **tracked execution** and the intent is to kick off work rather than just discuss it.
25
+
26
+ Typical shapes:
27
+ - implementation / bug fix / refactor / investigation / multi-step execution
28
+ - “don’t do this yourself — pass it through the orchestration flow”
29
+ - “make Zigrix take this task”
30
+
31
+ ### 2) `direct`
32
+ Choose `direct` only when the user clearly wants the **current main agent** to do the work directly.
33
+
34
+ Typical signs:
35
+ - explicit direct instruction
36
+ - explicit anti-delegation instruction
37
+ - small bounded task with no request to hand it off
38
+
39
+ ### 3) `answer`
40
+ Choose `answer` when the user is not asking to execute or hand off work, but instead wants:
41
+ - explanation
42
+ - architecture discussion
43
+ - status
44
+ - comparison
45
+ - policy/design reasoning
46
+ - review of an idea without starting execution
47
+
48
+ ## Bias rule
49
+ If the request is ambiguous but points toward:
50
+ - state-changing work
51
+ - multi-step implementation
52
+ - tracked execution
53
+ - “someone else / Zigrix should take this”
54
+
55
+ bias toward `delegate` unless the user clearly requested direct execution.
56
+
57
+ ## Hard rules
58
+ - `/oz ...` is always `delegate`.
59
+ - Once `delegate` is chosen, do not direct-execute as a fallback.
60
+ - If the task text is too thin to dispatch safely, ask for clarification instead of direct-executing.
61
+ - Use the existing canonical Zigrix chain:
62
+ - `zigrix task dispatch --json`
63
+ - `sessions_spawn(... orchestratorPrompt ...)`
64
+
65
+ ## What this rubric is not
66
+ This rubric is not:
67
+ - a regex spec
68
+ - an exhaustive phrase list
69
+ - a locale-locked keyword matcher
70
+
71
+ It is a semantic decision guide for LLM-based routing.
@@ -1,17 +1,27 @@
1
1
  ---
2
2
  name: zigrix-main-agent-guide
3
- version: 0.2.0
4
- description: Main-agent guide for using Zigrix CLI (task issuance, orchestrator spawn, dashboard, and path resolution).
3
+ version: 0.3.0
4
+ description: Main-agent-only guide for Zigrix CLI (task issuance, orchestrator spawn, `/oz` handoff guard, dashboard, and path resolution). Never use this skill as orchestrator/worker runtime instruction.
5
5
  metadata:
6
6
  openclaw:
7
7
  requires:
8
8
  bins: ["zigrix"]
9
9
  ---
10
10
 
11
- # Zigrix Main Agent Guide
11
+ # Zigrix Main Agent Guide (MAIN-ONLY)
12
12
 
13
13
  메인 에이전트가 Zigrix를 사용할 때의 표준 흐름.
14
14
 
15
+ ## 0) Scope Guard (Critical)
16
+
17
+ 이 스킬은 **main agent 전용**이다.
18
+
19
+ - 허용 주체: 사용자 요청을 받아 `dispatch/spawn/report`를 수행하는 **main agent**
20
+ - 금지 주체: orchestrator/worker runtime 세션(역할 워커 세션 전반)
21
+
22
+ 오케스트레이터/워커는 이 스킬을 런타임 규칙으로 사용하지 않는다.
23
+ 오케스트레이터/워커의 canonical instruction은 `zigrix/rules/defaults/*` + dispatch/worker overlay prompt다.
24
+
15
25
  ## 1) 기본 명령
16
26
 
17
27
  ```bash
@@ -47,6 +57,7 @@ zigrix task dispatch \
47
57
  - `baselineRequiredAgents`
48
58
  - `candidateAgents`
49
59
  - `orchestratorPrompt`
60
+ - `orchestratorLabel`
50
61
  - `specPath` — resolved absolute path to spec markdown
51
62
  - `metaPath` — resolved absolute path to metadata JSON
52
63
  - `promptPath` — resolved absolute path to dispatch prompt
@@ -59,20 +70,39 @@ zigrix task dispatch \
59
70
  ```text
60
71
  sessions_spawn(
61
72
  agentId: <orchestratorId>,
73
+ label: <dispatchResult.orchestratorLabel>,
74
+ cwd: <dispatchResult.projectDir>,
62
75
  task: <dispatchResult.orchestratorPrompt>
63
76
  )
64
77
  ```
65
78
 
79
+ spawn 직후 main agent는 반환된 실제 세션 ref를 즉시 바인딩한다.
80
+
81
+ ```bash
82
+ zigrix task bind-orchestrator --task-id <taskId> --agent-id <orchestratorId> --session-key <childSessionKey> --session-id <childSessionId> --json
83
+ ```
84
+
66
85
  오케스트레이터는 이후 워커를 `zigrix worker prepare/register/complete` 체인으로 관리한다.
67
86
 
87
+ ### `/oz` and delegation guard
88
+
89
+ `/oz` skill 또는 자연어 위임 라우팅이 현재 턴을 **delegate** 로 판정했다면, 메인 에이전트는 실행자가 아니라 **router** 다.
90
+
91
+ 이 경우:
92
+ - 허용: `zigrix task dispatch`, dispatch 결과 확인, `sessions_spawn`, 상태/실패 보고
93
+ - 금지: 직접 구현, 직접 파일 수정으로 우회, direct fallback
94
+ - dispatch/spawn 실패 시: 실패를 보고하고 중단
95
+
96
+ 즉, Zigrix handoff가 시작된 이후에는 메인 에이전트가 로컬 직접 작업으로 대체하지 않는다.
97
+
68
98
  ## 4) 워커/검증/최종 보고 체인
69
99
 
70
100
  ```bash
71
- # 워커 준비 (returns promptPath, specPath, metaPath, projectDir)
101
+ # 워커 준비 (returns promptPath, specPath, metaPath, projectDir, spawnLabel)
72
102
  zigrix worker prepare --task-id <taskId> --agent-id <agentId> --description "..." --json
73
103
 
74
104
  # 워커 세션 등록
75
- zigrix worker register --task-id <taskId> --agent-id <agentId> --session-key <sessionKey> --run-id <runId> --json
105
+ zigrix worker register --task-id <taskId> --agent-id <agentId> --session-key <sessionKey> --label <spawnLabel> --project-dir <projectDir> --run-id <runId> --json
76
106
 
77
107
  # 워커 완료
78
108
  zigrix worker complete --task-id <taskId> --agent-id <agentId> --session-key <sessionKey> --run-id <runId> --json
@@ -116,9 +146,9 @@ bare symbolic key(`paths.tasksDir`, `workspace.projectsBaseDir`)를 파일 경
116
146
 
117
147
  | Step | Command | Key resolved path fields |
118
148
  |------|---------|--------------------------|
119
- | Dispatch | `zigrix task dispatch` | `specPath`, `metaPath`, `promptPath`, `projectDir` |
149
+ | Dispatch | `zigrix task dispatch` | `specPath`, `metaPath`, `promptPath`, `projectDir`, `orchestratorLabel` |
120
150
  | Start | `zigrix task start` | |
121
- | Worker prepare | `zigrix worker prepare` | `promptPath`, `specPath`, `metaPath`, `projectDir` |
151
+ | Worker prepare | `zigrix worker prepare` | `promptPath`, `specPath`, `metaPath`, `projectDir`, `spawnLabel` |
122
152
  | Worker register | `zigrix worker register` | |
123
153
  | Worker complete | `zigrix worker complete` | |
124
154
  | Evidence collect | `zigrix evidence collect` | `evidencePath` |
@@ -1 +0,0 @@
1
- (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[974],{109:e=>{e.exports={badge:"StatusBadge_badge__M4ZLM",status_OPEN:"StatusBadge_status_OPEN__0Pm_x",status_IN_PROGRESS:"StatusBadge_status_IN_PROGRESS__JhYac",status_BLOCKED:"StatusBadge_status_BLOCKED__8FFag",status_DONE_PENDING_REPORT:"StatusBadge_status_DONE_PENDING_REPORT__yVdnt",status_REPORTED:"StatusBadge_status_REPORTED__0p67U",status_UNKNOWN:"StatusBadge_status_UNKNOWN__VkyXw"}},594:e=>{e.exports={wrap:"ConversationTab_wrap__1QSeD",toggle:"ConversationTab_toggle__3CZ5X",list:"ConversationTab_list__3x9W9",message:"ConversationTab_message__ATEZY",header:"ConversationTab_header__JCM4X",agent:"ConversationTab_agent__y3KdF",meta:"ConversationTab_meta__dMgwn",body:"ConversationTab_body__uCFH9",markdown:"ConversationTab_markdown__A8qFO",thinking:"ConversationTab_thinking__9ksh2",toolBox:"ConversationTab_toolBox__z6pL2",toolName:"ConversationTab_toolName__SLqEU",notice:"ConversationTab_notice__wCw5J",empty:"ConversationTab_empty__aB__j"}},2357:e=>{e.exports={wrap:"EventLogTab_wrap__x2X_J",empty:"EventLogTab_empty__LRJDo",list:"EventLogTab_list__nm_mD",item:"EventLogTab_item__VL0dt",ts:"EventLogTab_ts__vQ9nA",name:"EventLogTab_name__4A39l"}},6143:e=>{e.exports={main:"DashboardClient_main__eZK1S",header:"DashboardClient_header__21U6H",brand:"DashboardClient_brand__1Ljqy",headerRight:"DashboardClient_headerRight__EinuX",sseWrap:"DashboardClient_sseWrap__dCBYi",dot:"DashboardClient_dot__NxKpZ",dot_connected:"DashboardClient_dot_connected__3UnYe",dot_disconnected:"DashboardClient_dot_disconnected__0IqOj",dot_connecting:"DashboardClient_dot_connecting__NNLev",statusBar:"DashboardClient_statusBar__eP3FN",statusItem:"DashboardClient_statusItem__Yi9TP",error:"DashboardClient_error__Tv__n",layout:"DashboardClient_layout__s4BTz",left:"DashboardClient_left__WqNyg",right:"DashboardClient_right__EWclx",tabs:"DashboardClient_tabs__tx3BS",tabActive:"DashboardClient_tabActive__5oF9r",panel:"DashboardClient_panel__bWB7I"}},6297:(e,t,a)=>{Promise.resolve().then(a.bind(a,9843))},6583:e=>{e.exports={wrap:"TaskDetailTab_wrap__dFSwq",empty:"TaskDetailTab_empty__wxQD4",header:"TaskDetailTab_header___564C",badges:"TaskDetailTab_badges__xm9EG",metaRow:"TaskDetailTab_metaRow__OSbDu",cancelButton:"TaskDetailTab_cancelButton__ReU0K",section:"TaskDetailTab_section__4dUxv",muted:"TaskDetailTab_muted__VWQMQ",units:"TaskDetailTab_units__XIBtG",unitCard:"TaskDetailTab_unitCard__jY43J",unitTop:"TaskDetailTab_unitTop__yZ5FK",unitMeta:"TaskDetailTab_unitMeta__LnHSZ",progressTrack:"TaskDetailTab_progressTrack__VlE22",progressFill:"TaskDetailTab_progressFill__JVS7w",evidenceList:"TaskDetailTab_evidenceList__xGfBZ",toggle:"TaskDetailTab_toggle__ujWwI",markdown:"TaskDetailTab_markdown__eoDyT"}},8157:e=>{e.exports={badge:"ScaleBadge_badge__Ufu_B",scale_simple:"ScaleBadge_scale_simple__MbInQ",scale_normal:"ScaleBadge_scale_normal__vPQOk",scale_risky:"ScaleBadge_scale_risky__pWko0",scale_large:"ScaleBadge_scale_large__aXng2",scale_unknown:"ScaleBadge_scale_unknown__gCQWs"}},9221:e=>{e.exports={wrap:"TaskList_wrap__JJmVD",filters:"TaskList_filters__P_eut",tabs:"TaskList_tabs__MrUoG",tab:"TaskList_tab__PJ3u6",tabActive:"TaskList_tabActive__hqEIw",input:"TaskList_input__069mt",select:"TaskList_select__07ygx",list:"TaskList_list__zaHPI",card:"TaskList_card__UWMn4",cardSelected:"TaskList_cardSelected__e4ZHd",cardTop:"TaskList_cardTop__ogfsJ",taskId:"TaskList_taskId__RiYub",title:"TaskList_title__BjaLg",metaRow:"TaskList_metaRow__zxzxl",dot:"TaskList_dot__zkHSK",pagination:"TaskList_pagination__3aWZh"}},9843:(e,t,a)=>{"use strict";a.d(t,{DashboardClient:()=>R});var s=a(5155),n=a(2115),l=a(109),i=a.n(l);let r={OPEN:{label:"대기",icon:"\uD83D\uDD35"},IN_PROGRESS:{label:"진행 중",icon:"\uD83D\uDFE0"},BLOCKED:{label:"차단",icon:"\uD83D\uDD34"},DONE_PENDING_REPORT:{label:"보고 대기",icon:"\uD83D\uDFE3"},REPORTED:{label:"보고 완료",icon:"\uD83D\uDFE2"}};function c(e){let{status:t}=e,a=(t||"UNKNOWN").toUpperCase(),n=r[a]||{label:t||"알 수 없음",icon:"⚪"};return(0,s.jsxs)("span",{className:"".concat(i().badge," ").concat(i()["status_".concat(a)]||i().status_UNKNOWN),children:[(0,s.jsx)("span",{"aria-hidden":!0,children:n.icon}),(0,s.jsx)("span",{children:n.label})]})}var o=a(8157),d=a.n(o);let u={simple:"simple",normal:"normal",risky:"risky",large:"large"};function _(e){let{scale:t}=e,a=(t||"unknown").toLowerCase(),n=u[a]||a;return(0,s.jsx)("span",{className:"".concat(d().badge," ").concat(d()["scale_".concat(a)]||d().scale_unknown),children:n})}function h(e){let{value:t}=e,[,a]=(0,n.useReducer)(e=>e+1,0);return(0,n.useEffect)(()=>{let e=setInterval(a,6e4);return()=>clearInterval(e)},[]),(0,s.jsx)("span",{title:t||"",children:function(e){if(!e)return"-";let t=new Date(e).getTime();if(!Number.isFinite(t))return e;let a=Math.floor((Date.now()-t)/1e3);if(a<5)return"방금 전";if(a<60)return"".concat(a,"초 전");let s=Math.floor(a/60);if(s<60)return"".concat(s,"분 전");let n=Math.floor(s/60);if(n<24)return"".concat(n,"시간 전");let l=Math.floor(n/24);return l<30?"".concat(l,"일 전"):new Date(e).toLocaleString("ko-KR")}(t)})}var m=a(9221),p=a.n(m);let x=["ALL","OPEN","IN_PROGRESS","BLOCKED","DONE_PENDING_REPORT","REPORTED"];function v(e){let{tasks:t,selectedTaskId:a,onSelectTask:l}=e,[i,r]=(0,n.useState)("ALL"),[o,d]=(0,n.useState)(""),[u,m]=(0,n.useState)("newest"),[v,g]=(0,n.useState)(1),k=(0,n.useMemo)(()=>{let e=o.trim().toLowerCase();return[...t.filter(t=>("ALL"===i||(t.status||"")===i)&&(!e||[t.taskId,t.title||"",t.actor||""].some(t=>t.toLowerCase().includes(e))))].sort((e,t)=>{if("taskId"===u)return e.taskId.localeCompare(t.taskId);let a=Date.parse(e.updatedAt||"")||0,s=Date.parse(t.updatedAt||"")||0;return"newest"===u?s-a:a-s})},[t,o,u,i]),N=Math.max(1,Math.ceil(k.length/12)),b=Math.min(v,N),j=k.slice((b-1)*12,12*b);return(0,s.jsxs)("section",{className:p().wrap,children:[(0,s.jsxs)("div",{className:p().filters,children:[(0,s.jsx)("div",{className:p().tabs,children:x.map(e=>(0,s.jsx)("button",{type:"button",className:"".concat(p().tab," ").concat(i===e?p().tabActive:""),onClick:()=>{r(e),g(1)},children:e},e))}),(0,s.jsx)("input",{className:p().input,placeholder:"taskId / title / actor 검색",value:o,onChange:e=>{d(e.target.value),g(1)}}),(0,s.jsxs)("select",{className:p().select,value:u,onChange:e=>{m(e.target.value),g(1)},children:[(0,s.jsx)("option",{value:"newest",children:"최신순"}),(0,s.jsx)("option",{value:"oldest",children:"오래된순"}),(0,s.jsx)("option",{value:"taskId",children:"taskId순"})]})]}),(0,s.jsx)("ul",{className:p().list,children:j.map(e=>(0,s.jsx)("li",{children:(0,s.jsxs)("button",{type:"button",className:"".concat(p().card," ").concat(a===e.taskId?p().cardSelected:""),onClick:()=>l(e.taskId),children:[(0,s.jsxs)("div",{className:p().cardTop,children:[(0,s.jsx)("code",{className:p().taskId,children:e.taskId}),(0,s.jsx)(c,{status:e.status})]}),(0,s.jsx)("p",{className:p().title,children:e.title||"(제목 없음)"}),(0,s.jsxs)("div",{className:p().metaRow,children:[(0,s.jsx)(_,{scale:e.scale}),(0,s.jsx)("span",{children:e.actor||"-"}),(0,s.jsx)("span",{className:p().dot,children:"•"}),(0,s.jsx)(h,{value:e.updatedAt})]})]})},e.taskId))}),(0,s.jsxs)("div",{className:p().pagination,children:[(0,s.jsx)("button",{type:"button",disabled:b<=1,onClick:()=>g(e=>Math.max(1,e-1)),children:"이전"}),(0,s.jsxs)("span",{children:[b," / ",N]}),(0,s.jsx)("button",{type:"button",disabled:b>=N,onClick:()=>g(e=>Math.min(N,e+1)),children:"다음"})]})]})}var g=a(856),k=a(6583),N=a.n(k);function b(e){var t,a;let{detail:l,onCancelTask:i,cancelling:r}=e,[o,d]=(0,n.useState)(!1),u=(0,n.useMemo)(()=>{var e,t;let a=null==l||null==(t=l.meta)||null==(e=t.data)?void 0:e.executionUnits;return Array.isArray(a)?a:[]},[l]);if(!l)return(0,s.jsx)("div",{className:N().empty,children:"태스크를 선택해 주세요."});let m=l.task.status,p=(l.spec.preview||"").split(/\r?\n/),x=o?p:p.slice(0,20),v=new Set(l.evidence.agents.map(e=>e.agentId)),k=Array.isArray(null==(t=l.evidence.merged)?void 0:t.requiredAgents)?null==(a=l.evidence.merged)?void 0:a.requiredAgents:Array.from(v);return(0,s.jsxs)("div",{className:N().wrap,children:[(0,s.jsxs)("div",{className:N().header,children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h3",{children:l.task.title||"(제목 없음)"}),(0,s.jsx)("code",{children:l.task.taskId})]}),(0,s.jsxs)("div",{className:N().badges,children:[(0,s.jsx)(c,{status:m}),(0,s.jsx)(_,{scale:l.task.scale})]})]}),(0,s.jsxs)("div",{className:N().metaRow,children:[(0,s.jsxs)("span",{children:["생성: ",(0,s.jsx)(h,{value:l.spec.metadata.createdAt||null})]}),(0,s.jsxs)("span",{children:["업데이트: ",(0,s.jsx)(h,{value:l.task.updatedAt})]})]}),("OPEN"===m||"IN_PROGRESS"===m)&&(0,s.jsx)("button",{type:"button",className:N().cancelButton,onClick:()=>i(l.task.taskId),disabled:r,children:r?"취소 중...":"태스크 취소"}),(0,s.jsxs)("section",{className:N().section,children:[(0,s.jsx)("h4",{children:"Execution Units"}),0===u.length?(0,s.jsx)("p",{className:N().muted,children:"Execution Units 정보가 없습니다."}):(0,s.jsx)("div",{className:N().units,children:u.map((e,t)=>{let a=Array.isArray(e.workPackages)?e.workPackages:[],n=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];return e.filter(e=>["DONE","REPORTED","DONE_PENDING_REPORT","COMPLETED"].includes((e.status||"").toUpperCase())).length}(a),l=a.length,i=l>0?Math.round(n/l*100):0;return(0,s.jsxs)("article",{className:N().unitCard,children:[(0,s.jsxs)("div",{className:N().unitTop,children:[(0,s.jsx)("strong",{children:e.title||e.unitId||"Unit ".concat(t+1)}),(0,s.jsx)("span",{children:e.status||"-"})]}),(0,s.jsxs)("div",{className:N().unitMeta,children:[(0,s.jsxs)("span",{children:["unitId: ",e.unitId||"-"]}),(0,s.jsxs)("span",{children:["owner: ",e.owner||e.workerAgent||"-"]}),(0,s.jsxs)("span",{children:[n,"/",l]})]}),(0,s.jsx)("div",{className:N().progressTrack,children:(0,s.jsx)("div",{className:N().progressFill,style:{width:"".concat(i,"%")}})})]},e.unitId||"".concat(e.title||"unit","-").concat(t))})})]}),(0,s.jsxs)("section",{className:N().section,children:[(0,s.jsx)("h4",{children:"Evidence"}),0===k.length?(0,s.jsx)("p",{className:N().muted,children:"증적 제출 정보가 없습니다."}):(0,s.jsx)("ul",{className:N().evidenceList,children:k.map(e=>(0,s.jsxs)("li",{children:[(0,s.jsx)("span",{children:e}),(0,s.jsx)("span",{children:v.has(e)?"제출됨":"미제출"})]},e))})]}),(0,s.jsxs)("section",{className:N().section,children:[(0,s.jsx)("h4",{children:"Spec Preview"}),0===p.length?(0,s.jsx)("p",{className:N().muted,children:"스펙 파일이 없습니다."}):(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("button",{type:"button",className:N().toggle,onClick:()=>d(e=>!e),children:o?"접기":"펼치기"}),(0,s.jsx)("div",{className:N().markdown,children:(0,s.jsx)(g.oz,{children:x.join("\n")})})]})]})]})}var j=a(2357),T=a.n(j);function y(e){let{events:t}=e,a=(0,n.useRef)(null);return(0,n.useEffect)(()=>{a.current&&(a.current.scrollTop=0)},[t.length]),(0,s.jsx)("div",{ref:a,className:T().wrap,children:0===t.length?(0,s.jsx)("p",{className:T().empty,children:"이벤트가 없습니다."}):(0,s.jsx)("ul",{className:T().list,children:t.map((e,t)=>{let a=e.event||"unknown";return(0,s.jsxs)("li",{className:T().item,children:[(0,s.jsxs)("span",{className:T().ts,children:["[",function(e){if(!e)return"-";let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleTimeString("ko-KR")}(e.ts),"]"]})," ",(0,s.jsx)("span",{className:T().name,children:a})," | ",(0,s.jsxs)("span",{children:["task=",e.taskId||"-"]})," | ",(0,s.jsxs)("span",{children:["status=",e.status||"-"]})," | ","worker_dispatched"===a?(0,s.jsxs)("strong",{children:[e.actor||e.agentId||"-"," → ",e.targetAgent||"-"]}):(0,s.jsxs)("span",{children:["actor=",e.actor||e.agentId||"-"]})]},"".concat(e.ts||"no-ts","-").concat(a,"-").concat(t))})})})}var w=a(594),E=a.n(w);function C(e){let{conversation:t}=e,[a,l]=(0,n.useState)(!1),i=(0,n.useRef)(null);(0,n.useEffect)(()=>{let e=i.current;e&&e.scrollHeight-e.scrollTop-e.clientHeight<200&&(e.scrollTop=e.scrollHeight)},[null==t?void 0:t.stream.length]);let r=(0,n.useMemo)(()=>(null==t?void 0:t.stream)||[],[t]);return t?t.openclawAvailable?(0,s.jsxs)("div",{className:E().wrap,children:[(0,s.jsxs)("label",{className:E().toggle,children:[(0,s.jsx)("input",{type:"checkbox",checked:a,onChange:e=>l(e.target.checked)}),(0,s.jsx)("span",{children:"Debug"})]}),(0,s.jsx)("div",{ref:i,className:E().list,children:r.map((e,t)=>{var n,l;let i=(n=e.content,l=e.toolName,"string"==typeof n?[{type:"text",text:n}]:Array.isArray(n)?n.flatMap(e=>{var t,a,s;if(!e||"object"!=typeof e)return[];let n=String(e.type||"text");return("text"===n||"markdown"===n)&&"string"==typeof e.text?[{type:"text",text:e.text}]:"thinking"===n&&"string"==typeof e.thinking?[{type:"thinking",text:e.thinking}]:("tool_use"===n||"toolCall"===n)&&("string"==typeof e.name||"string"==typeof e.toolName)?[{type:"toolCall",toolName:e.name||e.toolName||l||"tool",text:JSON.stringify(null!=(a=null!=(t=e.input)?t:e.arguments)?a:{},null,2)}]:"tool_result"===n||"toolResult"===n?[{type:"toolResult",toolName:l||"tool",text:"string"==typeof e.content?e.content:JSON.stringify(null!=(s=e.content)?s:e,null,2)}]:"string"==typeof e.text?[{type:"text",text:e.text}]:[{type:"text",text:JSON.stringify(e,null,2)}]}):[{type:"text",text:null==n?"":JSON.stringify(n,null,2)}]),r=function(e){let t=0;for(let a=0;a<e.length;a+=1)t=(t<<5)-t+e.charCodeAt(a);let a=Math.abs(t)%360;return"hsl(".concat(a," 65% 45%)")}(e.agentId||e.agentName||"agent");return(0,s.jsxs)("article",{className:E().message,children:[(0,s.jsxs)("header",{className:E().header,children:[(0,s.jsx)("span",{className:E().agent,style:{backgroundColor:r},children:e.agentName||e.agentId}),(0,s.jsx)("span",{className:E().meta,children:e.role||"unknown"}),(0,s.jsx)("span",{className:E().meta,children:e.ts?new Date(e.ts).toLocaleTimeString("ko-KR"):"-"})]}),(0,s.jsx)("div",{className:E().body,children:i.filter(t=>{var s;return s=e.role,"text"===t.type?"assistant"===s||"user"===s:a}).map((e,t)=>"thinking"===e.type?(0,s.jsxs)("details",{className:E().thinking,children:[(0,s.jsx)("summary",{children:"thinking"}),(0,s.jsx)("pre",{children:e.text})]},t):"toolCall"===e.type||"toolResult"===e.type?(0,s.jsxs)("div",{className:E().toolBox,children:[(0,s.jsxs)("span",{className:E().toolName,children:[e.type,": ",e.toolName]}),(0,s.jsx)("pre",{children:e.text})]},t):(0,s.jsx)("div",{className:E().markdown,children:(0,s.jsx)(g.oz,{children:e.text||""})},t))})]},"".concat(e.sessionKey,"-").concat(e.timestamp||t))})})]}):(0,s.jsx)("div",{className:E().notice,children:"OpenClaw 연동 필요"}):(0,s.jsx)("div",{className:E().empty,children:"태스크를 선택해 주세요."})}var f=a(6143),D=a.n(f);let S=["OPEN","IN_PROGRESS","BLOCKED","DONE_PENDING_REPORT","REPORTED"];async function I(e,t){let a=await fetch(e,{...t,cache:"no-store"});if(!a.ok){let e=await a.json().catch(()=>({}));throw Error("string"==typeof(null==e?void 0:e.error)?e.error:"HTTP ".concat(a.status))}return await a.json()}function R(e){var t;let{initialOverview:a,initialTaskDetail:l,initialConversation:i,initialSelectedTaskId:r}=e,[c,o]=(0,n.useState)(a),[d,u]=(0,n.useState)(r),[_,h]=(0,n.useState)(l),[m,p]=(0,n.useState)(i),[x,g]=(0,n.useState)("detail"),[k,N]=(0,n.useState)("connecting"),[j,T]=(0,n.useState)(!1),[w,E]=(0,n.useState)(null),[f,R]=(0,n.useState)(!1),O=(0,n.useRef)((null==(t=a.recentEvents[0])?void 0:t.ts)||null),L=(0,n.useRef)(null),P=(0,n.useRef)(null),A=(0,n.useMemo)(()=>null===d?[]:c.recentEvents.filter(e=>e.taskId===d),[c.recentEvents,d]),B=(0,n.useMemo)(()=>(function(e){let t=new Map(e.activeTasks.map(e=>[e.taskId,e])),a=new Map(e.taskHistory.map(e=>[e.taskId,e]));return Array.from(new Set([...e.taskHistory.map(e=>e.taskId),...e.activeTasks.map(e=>e.taskId)])).map(e=>{let s=a.get(e),n=t.get(e);return{taskId:e,status:(null==s?void 0:s.status)||(null==n?void 0:n.status)||null,title:(null==s?void 0:s.title)||(null==n?void 0:n.title)||null,scale:(null==s?void 0:s.scale)||(null==n?void 0:n.scale)||null,actor:(null==s?void 0:s.actor)||null,updatedAt:(null==s?void 0:s.ts)||(null==n?void 0:n.updatedAt)||null}})})(c),[c]),M=(0,n.useCallback)(async e=>{let[t,a]=await Promise.all([I("/api/tasks/".concat(encodeURIComponent(e))),I("/api/tasks/".concat(encodeURIComponent(e),"/conversation"))]);h(t),p(a)},[]),U=(0,n.useCallback)(async()=>{T(!0),E(null);try{var e,t;let a=await I("/api/overview");o(a);let s=(null==(e=a.recentEvents[0])?void 0:e.ts)||null;s&&(O.current=s);let n=d||(null==(t=a.taskHistory[0])?void 0:t.taskId)||null;n&&(u(n),await M(n))}catch(e){E(e.message||"새로고침 실패")}finally{T(!1)}},[M,d]),K=(0,n.useCallback)(async()=>{await fetch("/api/auth/logout",{method:"POST"}),window.location.href="/login"},[]),J=(0,n.useCallback)(async e=>{try{R(!0),E(null),await I("/api/tasks/".concat(encodeURIComponent(e),"/cancel"),{method:"POST"}),await U()}catch(e){E(e.message||"태스크 취소 실패")}finally{R(!1)}},[U]);return(0,n.useEffect)(()=>{d&&M(d).catch(e=>{E(e.message||"태스크 로딩 실패")})},[M,d]),(0,n.useEffect)(()=>{let e=!1,t=()=>{if(e)return;N("connecting");let a=new URLSearchParams;d&&a.set("taskId",d),O.current&&a.set("lastEventTs",O.current);let s=new EventSource("/api/stream".concat(a.toString()?"?".concat(a.toString()):""));P.current=s,s.onopen=()=>N("connected"),s.addEventListener("update",e=>{let t=JSON.parse(e.data);if(t.ts&&(O.current=t.ts),t.overview){var a,s;o(t.overview),!d&&(null==(a=t.overview.taskHistory[0])?void 0:a.taskId)&&u(t.overview.taskHistory[0].taskId);let e=null==(s=t.overview.recentEvents[0])?void 0:s.ts;e&&(O.current=e)}}),s.addEventListener("event_update",e=>{let t=JSON.parse(e.data);t.ts&&(O.current=t.ts),o(e=>({...e,recentEvents:t.recentEvents||e.recentEvents,taskHistory:t.taskHistory||e.taskHistory,bucketCounts:t.bucketCounts||e.bucketCounts}))}),s.addEventListener("task_detail_update",e=>{let t=JSON.parse(e.data);t.ts&&(O.current=t.ts),t.taskId&&t.taskId===d&&t.detail&&h(t.detail)}),s.addEventListener("conversation_update",e=>{let t=JSON.parse(e.data);t.ts&&(O.current=t.ts),t.taskId&&t.taskId===d&&p(e=>{var a,s;return{generatedAt:new Date().toISOString(),taskId:t.taskId||d,sessionKeys:t.sessionKeys||(null==e?void 0:e.sessionKeys)||[],stream:t.stream||(null==e?void 0:e.stream)||[],recentEvents:t.recentEvents||(null==e?void 0:e.recentEvents)||[],sessions:(null==e?void 0:e.sessions)||[],openclawAvailable:null!=(s=null!=(a=t.openclawAvailable)?a:null==e?void 0:e.openclawAvailable)&&s}})}),s.onerror=()=>{N("disconnected"),s.close(),L.current&&clearTimeout(L.current),L.current=setTimeout(t,1500)}};return t(),()=>{e=!0,L.current&&clearTimeout(L.current),P.current&&P.current.close()}},[d]),(0,s.jsxs)("main",{className:D().main,children:[(0,s.jsxs)("header",{className:D().header,children:[(0,s.jsx)("div",{className:D().brand,children:"Zigrix"}),(0,s.jsxs)("div",{className:D().headerRight,children:[(0,s.jsxs)("div",{className:D().sseWrap,children:[(0,s.jsx)("span",{className:"".concat(D().dot," ").concat(D()["dot_".concat(k)])}),(0,s.jsx)("span",{children:k})]}),(0,s.jsx)("button",{type:"button",onClick:()=>void U(),disabled:j,children:"새로고침"}),(0,s.jsx)("button",{type:"button",onClick:()=>void K(),children:"로그아웃"})]})]}),(0,s.jsx)("div",{className:D().statusBar,children:S.map(e=>(0,s.jsxs)("span",{className:D().statusItem,children:[e," (",c.bucketCounts[e]||0,")"]},e))}),w?(0,s.jsx)("p",{className:D().error,children:w}):null,(0,s.jsxs)("section",{className:D().layout,children:[(0,s.jsx)("aside",{className:D().left,children:(0,s.jsx)(v,{tasks:B,selectedTaskId:d,onSelectTask:u})}),(0,s.jsxs)("section",{className:D().right,children:[(0,s.jsxs)("nav",{className:D().tabs,children:[(0,s.jsx)("button",{type:"button",className:"detail"===x?D().tabActive:"",onClick:()=>g("detail"),children:"태스크 상세"}),(0,s.jsx)("button",{type:"button",className:"events"===x?D().tabActive:"",onClick:()=>g("events"),children:"이벤트 로그"}),(0,s.jsx)("button",{type:"button",className:"conversation"===x?D().tabActive:"",onClick:()=>g("conversation"),children:"대화 내역"})]}),(0,s.jsxs)("div",{className:D().panel,children:["detail"===x&&(0,s.jsx)(b,{detail:_,onCancelTask:J,cancelling:f}),"events"===x&&(0,s.jsx)(y,{events:A}),"conversation"===x&&(0,s.jsx)(C,{conversation:m})]})]})]})]})}}},e=>{e.O(0,[963,856,441,255,358],()=>e(e.s=6297)),_N_E=e.O()}]);