devez-vibe 1.9.55 → 1.9.57

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 (38) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +73 -73
  3. package/bin/dvz.exe +0 -0
  4. package/bin/dvz.js +35 -35
  5. package/bridge/claude-agent-sdk-bridge.mjs +80 -2
  6. package/install-skills.mjs +11 -11
  7. package/package.json +50 -50
  8. package/prepare-search-deps.mjs +42 -42
  9. package/skills/insane-search/SKILL.md +36 -36
  10. package/skills/insane-search/engine/__main__.py +44 -44
  11. package/skills/insane-search/engine/executor.py +246 -246
  12. package/skills/insane-search/engine/fetch_chain.py +443 -443
  13. package/skills/insane-search/engine/network.py +108 -108
  14. package/skills/insane-search/engine/phase0.py +380 -380
  15. package/skills/insane-search/engine/session_input.py +120 -120
  16. package/skills/insane-search/engine/templates/invisible_playwright_fetch.py +57 -57
  17. package/skills/insane-search/engine/templates/nodriver_fetch.py +9 -9
  18. package/skills/insane-search/engine/templates/patchright_fetch.py +9 -9
  19. package/skills/insane-search/engine/templates/playwright_mobile_chrome.js +9 -9
  20. package/skills/insane-search/engine/templates/playwright_real_chrome.js +7 -7
  21. package/skills/insane-search/engine/templates/scrapling_fetch.py +46 -46
  22. package/skills/insane-search/engine/tests/test_smoke.py +8 -8
  23. package/skills/insane-search/engine/tests/test_t10_artifact_routes.py +126 -126
  24. package/skills/insane-search/engine/tests/test_t11_session_handoff.py +157 -157
  25. package/skills/insane-search/engine/tests/test_t5_pdfplumber.py +11 -11
  26. package/skills/insane-search/engine/tests/test_t7_browser_gate.py +3 -3
  27. package/skills/insane-search/engine/tests/test_t8_network_routes.py +207 -207
  28. package/skills/insane-search/engine/tests/test_t9_evidence_bundle.py +89 -89
  29. package/skills/insane-search/engine/tests/test_u5.py +9 -9
  30. package/skills/insane-search/engine/transport.py +94 -94
  31. package/skills/insane-search/engine/waf_profiles.yaml +38 -38
  32. package/skills/insane-search/references/cache-archive.md +13 -13
  33. package/skills/insane-search/references/media.md +14 -14
  34. package/skills/insane-search/references/playwright.md +27 -27
  35. package/skills/insane-search/references/research-evidence.md +36 -36
  36. package/skills/insane-search/references/session-handoff.md +26 -26
  37. package/skills/insane-search/tests/test_x_search.py +3 -3
  38. package/skills/luna-loop/agents/openai.yaml +7 -7
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Devez Vibe contributors
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Devez Vibe contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,73 +1,73 @@
1
- # Devez Vibe
2
-
3
- 공식 `codex app-server`와 Claude Agent SDK를 위한 차분한 터미널 클라이언트입니다.
4
- 각 공식 런타임이 인증·도구·스킬·프로젝트 지침을 담당하고, 이 프로젝트는 공통 화면과
5
- 입력 계층을 소유합니다.
6
-
7
- ## 설치
8
-
9
- ```powershell
10
- npm install -g devez-vibe
11
- ```
12
-
13
- 설치하면 `dvz` 명령을 사용할 수 있습니다.
14
-
15
- | 요건 | 값 |
16
- | --- | --- |
17
- | OS | Windows x64 |
18
- | Node.js | 18 이상 (Claude Agent SDK 런타임 포함) |
19
- | Codex 전제 | Codex CLI 설치 및 로그인 완료 |
20
- | Claude 전제 | Claude Code 설치 후 `claude` 구독 로그인 완료 |
21
-
22
- 현재 Windows x64 빌드만 배포합니다. 다른 플랫폼에서는 `EBADPLATFORM`으로 설치가 거부됩니다.
23
-
24
- ## 사용
25
-
26
- Codex CLI가 설치되고 로그인된 환경에서:
27
-
28
- ```powershell
29
- dvz
30
- ```
31
-
32
- 개인 Claude 구독 로그인 재사용:
33
-
34
- ```powershell
35
- dvz --model claude
36
- dvz --model sonnet --effort high
37
- ```
38
-
39
- Claude SDK 자식 프로세스는 API 키 환경변수를 제거하고 설치된 Claude Code 로그인만 사용합니다.
40
- 본인 계정의 로컬 개인 사용만 대상으로 하며 로그인 공유나 제3자 인증은 제공하지 않습니다.
41
-
42
- 주요 옵션:
43
-
44
- ```text
45
- dvz [--resume [SESSION] | --continue] [--model MODEL] [--effort EFFORT]
46
- [--cwd PATH] [--codex PATH] [--claude PATH] [--theme THEME]
47
- ```
48
-
49
- `--resume`만 입력하면 검색 가능한 세션 피커를 열고, `--continue`는 현재 폴더의 가장 최근
50
- 세션을 바로 이어갑니다. 실행 중 전체 명령은 `/help`에서 확인합니다.
51
-
52
- 설치 상태와 제공자 연결 준비 상태는 다음 명령으로 점검합니다.
53
-
54
- ```powershell
55
- dvz doctor
56
- ```
57
-
58
- ## 업데이트
59
-
60
- 새 버전이 배포되면 시작 시 안내 배너가 표시됩니다. 배너의 안내대로 실행하면 됩니다.
61
-
62
- ```powershell
63
- dvz update
64
- ```
65
-
66
- 새 버전을 별도 경로에 내려받아 실행 파일을 검증한 뒤 다음 실행 버전으로 전환합니다.
67
- 실행 중인 `dvz` 세션은 이전 버전을 유지하고, 새로 시작하는 세션부터 새 버전을 사용합니다.
68
-
69
- 업데이트 확인을 끄려면 `DEVEZ_VIBE_NO_UPDATE_CHECK` 환경변수를 설정합니다.
70
-
71
- ## 라이선스
72
-
73
- MIT. 자세한 내용은 [저장소](https://github.com/MrHoje/Devez-vibe)를 참고하세요.
1
+ # Devez Vibe
2
+
3
+ 공식 `codex app-server`와 Claude Agent SDK를 위한 차분한 터미널 클라이언트입니다.
4
+ 각 공식 런타임이 인증·도구·스킬·프로젝트 지침을 담당하고, 이 프로젝트는 공통 화면과
5
+ 입력 계층을 소유합니다.
6
+
7
+ ## 설치
8
+
9
+ ```powershell
10
+ npm install -g devez-vibe
11
+ ```
12
+
13
+ 설치하면 `dvz` 명령을 사용할 수 있습니다.
14
+
15
+ | 요건 | 값 |
16
+ | --- | --- |
17
+ | OS | Windows x64 |
18
+ | Node.js | 18 이상 (Claude Agent SDK 런타임 포함) |
19
+ | Codex 전제 | Codex CLI 설치 및 로그인 완료 |
20
+ | Claude 전제 | Claude Code 설치 후 `claude` 구독 로그인 완료 |
21
+
22
+ 현재 Windows x64 빌드만 배포합니다. 다른 플랫폼에서는 `EBADPLATFORM`으로 설치가 거부됩니다.
23
+
24
+ ## 사용
25
+
26
+ Codex CLI가 설치되고 로그인된 환경에서:
27
+
28
+ ```powershell
29
+ dvz
30
+ ```
31
+
32
+ 개인 Claude 구독 로그인 재사용:
33
+
34
+ ```powershell
35
+ dvz --model claude
36
+ dvz --model sonnet --effort high
37
+ ```
38
+
39
+ Claude SDK 자식 프로세스는 API 키 환경변수를 제거하고 설치된 Claude Code 로그인만 사용합니다.
40
+ 본인 계정의 로컬 개인 사용만 대상으로 하며 로그인 공유나 제3자 인증은 제공하지 않습니다.
41
+
42
+ 주요 옵션:
43
+
44
+ ```text
45
+ dvz [--resume [SESSION] | --continue] [--model MODEL] [--effort EFFORT]
46
+ [--cwd PATH] [--codex PATH] [--claude PATH] [--theme THEME]
47
+ ```
48
+
49
+ `--resume`만 입력하면 검색 가능한 세션 피커를 열고, `--continue`는 현재 폴더의 가장 최근
50
+ 세션을 바로 이어갑니다. 실행 중 전체 명령은 `/help`에서 확인합니다.
51
+
52
+ 설치 상태와 제공자 연결 준비 상태는 다음 명령으로 점검합니다.
53
+
54
+ ```powershell
55
+ dvz doctor
56
+ ```
57
+
58
+ ## 업데이트
59
+
60
+ 새 버전이 배포되면 시작 시 안내 배너가 표시됩니다. 배너의 안내대로 실행하면 됩니다.
61
+
62
+ ```powershell
63
+ dvz update
64
+ ```
65
+
66
+ 새 버전을 별도 경로에 내려받아 실행 파일을 검증한 뒤 다음 실행 버전으로 전환합니다.
67
+ 실행 중인 `dvz` 세션은 이전 버전을 유지하고, 새로 시작하는 세션부터 새 버전을 사용합니다.
68
+
69
+ 업데이트 확인을 끄려면 `DEVEZ_VIBE_NO_UPDATE_CHECK` 환경변수를 설정합니다.
70
+
71
+ ## 라이선스
72
+
73
+ MIT. 자세한 내용은 [저장소](https://github.com/MrHoje/Devez-vibe)를 참고하세요.
package/bin/dvz.exe CHANGED
Binary file
package/bin/dvz.js CHANGED
@@ -1,35 +1,35 @@
1
- #!/usr/bin/env node
2
-
3
- import { existsSync, readFileSync } from "node:fs";
4
- import { spawn } from "node:child_process";
5
- import { dirname, isAbsolute, join } from "node:path";
6
- import { fileURLToPath } from "node:url";
7
-
8
- const packageExecutable = join(dirname(fileURLToPath(import.meta.url)), "dvz.exe");
9
- const pointer = process.env.LOCALAPPDATA
10
- ? join(process.env.LOCALAPPDATA, "DevezVibe", "current-executable.txt")
11
- : "";
12
-
13
- let executable = packageExecutable;
14
- try {
15
- const candidate = pointer ? readFileSync(pointer, "utf8").trim() : "";
16
- if (isAbsolute(candidate) && existsSync(candidate)) executable = candidate;
17
- } catch {
18
- // A missing or incomplete pointer falls back to the npm-packaged executable.
19
- }
20
-
21
- const child = spawn(executable, process.argv.slice(2), { stdio: "inherit" });
22
- child.on("error", (error) => {
23
- console.error(`Devez Vibe 실행 실패: ${error.message}`);
24
- process.exit(1);
25
- });
26
- child.on("exit", (code, signal) => {
27
- if (signal) process.kill(process.pid, signal);
28
- else process.exit(code ?? 1);
29
- });
30
-
31
- for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) {
32
- process.on(signal, () => {
33
- if (!child.killed) child.kill(signal);
34
- });
35
- }
1
+ #!/usr/bin/env node
2
+
3
+ import { existsSync, readFileSync } from "node:fs";
4
+ import { spawn } from "node:child_process";
5
+ import { dirname, isAbsolute, join } from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ const packageExecutable = join(dirname(fileURLToPath(import.meta.url)), "dvz.exe");
9
+ const pointer = process.env.LOCALAPPDATA
10
+ ? join(process.env.LOCALAPPDATA, "DevezVibe", "current-executable.txt")
11
+ : "";
12
+
13
+ let executable = packageExecutable;
14
+ try {
15
+ const candidate = pointer ? readFileSync(pointer, "utf8").trim() : "";
16
+ if (isAbsolute(candidate) && existsSync(candidate)) executable = candidate;
17
+ } catch {
18
+ // A missing or incomplete pointer falls back to the npm-packaged executable.
19
+ }
20
+
21
+ const child = spawn(executable, process.argv.slice(2), { stdio: "inherit" });
22
+ child.on("error", (error) => {
23
+ console.error(`Devez Vibe 실행 실패: ${error.message}`);
24
+ process.exit(1);
25
+ });
26
+ child.on("exit", (code, signal) => {
27
+ if (signal) process.kill(process.pid, signal);
28
+ else process.exit(code ?? 1);
29
+ });
30
+
31
+ for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) {
32
+ process.on(signal, () => {
33
+ if (!child.killed) child.kill(signal);
34
+ });
35
+ }
@@ -749,6 +749,8 @@ function makeOptions(params, sessionId, resume) {
749
749
  // DevezVibe keeps per-task controls available through Claude's TaskStop
750
750
  // tool, so a turn interrupt must not tear down independent background work.
751
751
  perTaskStopAffordance: true,
752
+ // 순정처럼 하위 에이전트 줄의 설명을 약 30초마다 진행 요약으로 바꾼다.
753
+ agentProgressSummaries: true,
752
754
  systemPrompt: {
753
755
  type: "preset",
754
756
  preset: "claude_code",
@@ -2790,6 +2792,10 @@ function upsertStructuredSubagent(session, message) {
2790
2792
  return running;
2791
2793
  }
2792
2794
 
2795
+ function hasLiveChildren(session, taskId) {
2796
+ return !!taskId && [...session.subagents.values()].some((agent) => agent.parentTaskId === taskId);
2797
+ }
2798
+
2793
2799
  function finishStructuredSubagent(session, message) {
2794
2800
  const taskId = firstLine(message.task_id || "", 80);
2795
2801
  const toolUseId = firstLine(message.tool_use_id || "", 80);
@@ -2803,6 +2809,8 @@ function finishStructuredSubagent(session, message) {
2803
2809
  const running = (toolUseId && findSubagent(session, toolUseId))
2804
2810
  || (taskId && findSubagent(session, taskId));
2805
2811
  if (!running) return wasHidden;
2812
+ // 자기 백그라운드 명령을 기다리며 멈춘 에이전트는 그 명령이 끝나면 다시 돌므로 행을 남긴다.
2813
+ if (hasLiveChildren(session, running.taskId)) return true;
2806
2814
  session.subagents.delete(running.id);
2807
2815
  emitSubagents(session);
2808
2816
  return true;
@@ -2827,7 +2835,8 @@ function syncBackgroundSubagents(session, tasks) {
2827
2835
  changed = true;
2828
2836
  continue;
2829
2837
  }
2830
- if (!running.background || !running.taskId || liveIds.has(running.taskId)) continue;
2838
+ if (!running.background || !running.taskId || liveIds.has(running.taskId)
2839
+ || live.some((task) => task?.parent_task_id === running.taskId)) continue;
2831
2840
  session.subagents.delete(id);
2832
2841
  changed = true;
2833
2842
  }
@@ -2902,6 +2911,8 @@ function processSubagentSystemMessage(session, message) {
2902
2911
  if (!running) return false;
2903
2912
  const tool = firstLine(message.last_tool_name || "", 80);
2904
2913
  if (tool) running.tool = tool;
2914
+ const summary = firstLine(message.summary || "", SUBAGENT_DESCRIPTION_LIMIT);
2915
+ if (summary) running.description = summary;
2905
2916
  emitSubagents(session);
2906
2917
  return true;
2907
2918
  }
@@ -3050,11 +3061,17 @@ function emitSubagents(session) {
3050
3061
  clearInterval(session.subagentPulse);
3051
3062
  session.subagentPulse = null;
3052
3063
  }
3064
+ // 작업 창은 명령이 끝난 뒤에도 그 출력과 종료 코드를 읽으므로 행 id의 작업 id를 남겨 둔다.
3065
+ for (const agent of session.subagents.values()) {
3066
+ if (agent.taskId) (session.rowTaskIds ??= new Map()).set(agent.id, agent.taskId);
3067
+ }
3053
3068
  notify("turn/subagents/updated", {
3054
3069
  threadId: session.id,
3055
3070
  turnId: session.turn?.id,
3056
3071
  subagents: subagentRows(session).map(({ agent, depth }) => ({
3057
3072
  id: agent.id,
3073
+ // 스냅숏 자리표시자가 Agent 행에 접혀 사라져도 화면이 끝난 줄로 남기지 않게 한다.
3074
+ taskId: agent.taskId || "",
3058
3075
  name: agent.name,
3059
3076
  description: agent.description,
3060
3077
  backgroundTask: agent.backgroundTask === true,
@@ -4464,6 +4481,17 @@ async function dispatch(method, params = {}) {
4464
4481
  nextCursor: null,
4465
4482
  };
4466
4483
  }
4484
+ // 작업 창이 보는 백그라운드 명령의 출력 끝부분(최대 8KiB). 끝난 명령도 남겨 둔 작업 id로
4485
+ // 마지막 출력을 읽는다. 작업 id를 모르면 출력 없이 답해, 화면이 받은 출력을 그대로 두게 한다.
4486
+ if (method === "session/taskOutput") {
4487
+ const session = lookupSession(params.sessionId);
4488
+ const id = String(params.id || "");
4489
+ const taskId = (session && (findSubagent(session, id)?.taskId || session.rowTaskIds?.get(id)))
4490
+ || (id.startsWith("task:") ? id.slice(5) : "");
4491
+ if (!session || !taskId || typeof session.query.getTaskOutput !== "function") return {};
4492
+ const result = await session.query.getTaskOutput(taskId);
4493
+ return { output: String(result?.output ?? "") };
4494
+ }
4467
4495
  if (method === "session/watchSubagent") {
4468
4496
  const session = lookupSession(params.sessionId);
4469
4497
  if (session) watchSubagent(session, params.id ? String(params.id) : null);
@@ -4919,6 +4947,27 @@ async function runSelfTest() {
4919
4947
  .flatMap((turn) => turn.items)
4920
4948
  .some((item) => item.type === "userMessage" && item.content?.[0]?.text === "subagent");
4921
4949
  if (!subagentPrompt) throw new Error("Claude subagent transcript self-test failed");
4950
+ // 작업 창의 출력은 행 id가 아니라 SDK 작업 id로 읽는다. 작업 id를 모르면 출력 없이 답한다.
4951
+ const outputReads = [];
4952
+ const outputSession = {
4953
+ id: "task-output-self-test",
4954
+ query: { async getTaskOutput(taskId) { outputReads.push(taskId); return { output: "tick 3\n" }; } },
4955
+ subagents: new Map([
4956
+ ["toolu_shell", { id: "toolu_shell", toolUseId: "toolu_shell", taskId: "bash-1" }],
4957
+ ["toolu_pending", { id: "toolu_pending", toolUseId: "toolu_pending", taskId: "" }],
4958
+ ]),
4959
+ rowTaskIds: new Map([["toolu_done", "bash-3"]]),
4960
+ };
4961
+ sessions.set(outputSession.id, outputSession);
4962
+ const shellOutput = await dispatch("session/taskOutput", { sessionId: outputSession.id, id: "toolu_shell" });
4963
+ const placeholderOutput = await dispatch("session/taskOutput", { sessionId: outputSession.id, id: "task:bash-2" });
4964
+ const unknownOutput = await dispatch("session/taskOutput", { sessionId: outputSession.id, id: "toolu_pending" });
4965
+ await dispatch("session/taskOutput", { sessionId: outputSession.id, id: "toolu_done" });
4966
+ sessions.delete(outputSession.id);
4967
+ if (shellOutput.output !== "tick 3\n" || outputReads.join() !== "bash-1,bash-2,bash-3" || "output" in unknownOutput
4968
+ || placeholderOutput.output !== "tick 3\n") {
4969
+ throw new Error(`Claude task output self-test failed: ${outputReads}`);
4970
+ }
4922
4971
  // 끝나서 작업 id를 모르는 행도 meta 파일의 toolUseId로 그 기록을 찾는다.
4923
4972
  const previousConfigDir = process.env.CLAUDE_CONFIG_DIR;
4924
4973
  const configDir = join(tmpdir(), `devez-subagent-self-test-${randomUUID()}`);
@@ -6033,7 +6082,8 @@ async function runSelfTest() {
6033
6082
  summary: "Reading lifecycle source",
6034
6083
  });
6035
6084
  const structured = structuredSession.subagents.get("toolu_structured");
6036
- if (!structured?.background || structured.tool !== "Read" || structured.backgroundTask === true) {
6085
+ if (!structured?.background || structured.tool !== "Read" || structured.backgroundTask === true
6086
+ || structured.description !== "Reading lifecycle source") {
6037
6087
  throw new Error(`Claude structured task progress self-test failed: ${JSON.stringify(structured)}`);
6038
6088
  }
6039
6089
  processSubagentSystemMessage(structuredSession, {
@@ -6106,6 +6156,34 @@ async function runSelfTest() {
6106
6156
  throw new Error("Claude subagent agent_id self-test failed");
6107
6157
  }
6108
6158
  clearSubagents(nestedSession);
6159
+ // 자기 백그라운드 명령을 기다리며 멈춘 에이전트는 그 명령이 도는 동안 행을 지킨다.
6160
+ processSubagentSystemMessage(nestedSession, {
6161
+ type: "system",
6162
+ subtype: "task_started",
6163
+ task_id: "agent-wait",
6164
+ tool_use_id: "toolu_wait",
6165
+ task_type: "local_agent",
6166
+ subagent_type: "general-purpose",
6167
+ });
6168
+ nestedSession.subagents.get("toolu_wait").background = true;
6169
+ const waitSnapshot = (tasks) => processSubagentSystemMessage(nestedSession, {
6170
+ type: "system",
6171
+ subtype: "background_tasks_changed",
6172
+ tasks,
6173
+ });
6174
+ waitSnapshot([{ task_id: "shell-wait", task_type: "local_bash", description: "sleep 300", parent_task_id: "agent-wait" }]);
6175
+ processSubagentSystemMessage(nestedSession, {
6176
+ type: "system",
6177
+ subtype: "task_notification",
6178
+ task_id: "agent-wait",
6179
+ status: "completed",
6180
+ });
6181
+ const waitingKept = nestedSession.subagents.has("toolu_wait");
6182
+ waitSnapshot([]);
6183
+ if (!waitingKept || nestedSession.subagents.size !== 0) {
6184
+ throw new Error(`Claude waiting subagent self-test failed: ${waitingKept} ${nestedSession.subagents.size}`);
6185
+ }
6186
+ clearSubagents(nestedSession);
6109
6187
 
6110
6188
  processSubagentSystemMessage(structuredSession, {
6111
6189
  type: "system",
@@ -1,18 +1,18 @@
1
1
  import {
2
2
  copyFileSync,
3
3
  existsSync,
4
- mkdirSync,
5
- readdirSync,
6
- rmSync,
7
- writeFileSync,
8
- } from "node:fs";
4
+ mkdirSync,
5
+ readdirSync,
6
+ rmSync,
7
+ writeFileSync,
8
+ } from "node:fs";
9
9
  import { homedir } from "node:os";
10
10
  import { dirname, join } from "node:path";
11
11
  import { fileURLToPath } from "node:url";
12
12
 
13
13
  const packageRoot = dirname(fileURLToPath(import.meta.url));
14
- const skillNames = ["luna-loop", "insane-search"];
15
- const bundledMarker = ".devez-vibe-bundled-skill";
14
+ const skillNames = ["luna-loop", "insane-search"];
15
+ const bundledMarker = ".devez-vibe-bundled-skill";
16
16
  const userHome = homedir();
17
17
  const codexHome = process.env.CODEX_HOME?.trim() || join(userHome, ".codex");
18
18
  const claudeHome = process.env.CLAUDE_CONFIG_DIR?.trim() || join(userHome, ".claude");
@@ -61,10 +61,10 @@ for (const skill of skillNames) {
61
61
  for (const home of homes) {
62
62
  const target = join(home.root, skill);
63
63
  try {
64
- copyTree(sourceRoot, target);
65
- pruneTree(sourceRoot, target);
66
- writeFileSync(join(target, bundledMarker), `${skill}\n`, "utf8");
67
- console.log(`스킬 설치 완료 (${home.name}/${skill}): ${target}`);
64
+ copyTree(sourceRoot, target);
65
+ pruneTree(sourceRoot, target);
66
+ writeFileSync(join(target, bundledMarker), `${skill}\n`, "utf8");
67
+ console.log(`스킬 설치 완료 (${home.name}/${skill}): ${target}`);
68
68
  } catch (error) {
69
69
  failed = true;
70
70
  console.error(`스킬 설치 실패 (${home.name}/${skill}): ${error instanceof Error ? error.message : error}`);
package/package.json CHANGED
@@ -1,50 +1,50 @@
1
- {
2
- "name": "devez-vibe",
3
- "version": "1.9.55",
4
- "type": "module",
5
- "description": "Stable terminal UI for Codex and Claude Agent SDK",
6
- "keywords": [
7
- "codex",
8
- "cli",
9
- "tui",
10
- "terminal",
11
- "app-server",
12
- "claude-agent-sdk"
13
- ],
14
- "homepage": "https://github.com/MrHoje/Devez-vibe#readme",
15
- "bugs": "https://github.com/MrHoje/Devez-vibe/issues",
16
- "repository": {
17
- "type": "git",
18
- "url": "git+https://github.com/MrHoje/Devez-vibe.git"
19
- },
20
- "license": "MIT",
21
- "bin": {
22
- "dvz": "bin/dvz.js"
23
- },
24
- "files": [
25
- "bin/dvz.js",
26
- "bin/dvz.exe",
27
- "bridge/claude-agent-sdk-bridge.mjs",
28
- "install-skills.mjs",
29
- "prepare-search-deps.mjs",
30
- "skills/luna-loop/",
31
- "skills/insane-search/",
32
- "README.md",
33
- "LICENSE"
34
- ],
35
- "os": [
36
- "win32"
37
- ],
38
- "cpu": [
39
- "x64"
40
- ],
41
- "engines": {
42
- "node": ">=18"
43
- },
44
- "scripts": {
45
- "postinstall": "node install-skills.mjs && node prepare-search-deps.mjs"
46
- },
47
- "dependencies": {
48
- "@anthropic-ai/claude-agent-sdk": "0.3.296"
49
- }
50
- }
1
+ {
2
+ "name": "devez-vibe",
3
+ "version": "1.9.57",
4
+ "type": "module",
5
+ "description": "Stable terminal UI for Codex and Claude Agent SDK",
6
+ "keywords": [
7
+ "codex",
8
+ "cli",
9
+ "tui",
10
+ "terminal",
11
+ "app-server",
12
+ "claude-agent-sdk"
13
+ ],
14
+ "homepage": "https://github.com/MrHoje/Devez-vibe#readme",
15
+ "bugs": "https://github.com/MrHoje/Devez-vibe/issues",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/MrHoje/Devez-vibe.git"
19
+ },
20
+ "license": "MIT",
21
+ "bin": {
22
+ "dvz": "bin/dvz.js"
23
+ },
24
+ "files": [
25
+ "bin/dvz.js",
26
+ "bin/dvz.exe",
27
+ "bridge/claude-agent-sdk-bridge.mjs",
28
+ "install-skills.mjs",
29
+ "prepare-search-deps.mjs",
30
+ "skills/luna-loop/",
31
+ "skills/insane-search/",
32
+ "README.md",
33
+ "LICENSE"
34
+ ],
35
+ "os": [
36
+ "win32"
37
+ ],
38
+ "cpu": [
39
+ "x64"
40
+ ],
41
+ "engines": {
42
+ "node": ">=18"
43
+ },
44
+ "scripts": {
45
+ "postinstall": "node install-skills.mjs && node prepare-search-deps.mjs"
46
+ },
47
+ "dependencies": {
48
+ "@anthropic-ai/claude-agent-sdk": "0.3.296"
49
+ }
50
+ }
@@ -1,42 +1,42 @@
1
- // insane-search 스킬이 첫 호출에서 받는 파이썬 패키지를 설치 시점에 미리 깔아 둔다.
2
- // 준비는 어디까지나 선택적이다. 파이썬이 없거나 설치가 실패해도 안내만 남기고 정상 종료해서
3
- // devezVibe 설치 자체가 깨지지 않게 한다. 스킬은 첫 사용 때 다시 설치를 시도하므로 손해가 없다.
4
- import { spawnSync } from "node:child_process";
5
-
6
- // SKILL.md의 의존성 가드와 같은 조합이다. 한쪽만 바뀌면 첫 호출에서 다시 설치가 돈다.
7
- const guard = 'import curl_cffi,bs4,yaml,pypdf,markdownify; v=curl_cffi.__version__.split("."); assert (int(v[0]),int(v[1]))>=(0,15)';
8
- const packages = ["curl_cffi>=0.15.0", "beautifulsoup4", "pyyaml", "pypdf", "markdownify"];
9
-
10
- function run(command, args) {
11
- return spawnSync(command, args, { encoding: "utf8", windowsHide: true, timeout: 300000 });
12
- }
13
-
14
- // Windows에는 python3가 없는 대신 실행하면 스토어를 여는 별칭이 잡혀 있을 수 있다.
15
- // 버전 출력을 실제로 확인해서 쓸 수 있는 실행기만 고른다.
16
- function findPython() {
17
- for (const candidate of ["python3", "python", "py"]) {
18
- const probe = run(candidate, ["-c", "import sys; print(sys.version_info[0])"]);
19
- if (probe.status === 0 && probe.stdout.trim() === "3") return candidate;
20
- }
21
- return null;
22
- }
23
-
24
- const python = findPython();
25
- if (!python) {
26
- console.log("insane-search 준비 건너뜀: 파이썬 3을 찾지 못했습니다. 설치하면 첫 사용 때 자동으로 준비됩니다.");
27
- process.exit(0);
28
- }
29
-
30
- if (run(python, ["-c", guard]).status === 0) {
31
- console.log("insane-search 의존성 준비 완료: 이미 설치되어 있습니다.");
32
- process.exit(0);
33
- }
34
-
35
- // --user는 관리자 권한 없이도 설치되게 하고, 가상환경에서는 pip가 알아서 무시한다.
36
- const install = run(python, ["-m", "pip", "install", "-U", "--user", "-q", ...packages]);
37
- if (install.status === 0 && run(python, ["-c", guard]).status === 0) {
38
- console.log("insane-search 의존성 준비 완료");
39
- } else {
40
- const detail = (install.stderr || install.stdout || "").trim().split("\n").pop() || "원인 미상";
41
- console.log(`insane-search 준비 건너뜀 (${detail}). 첫 사용 때 다시 시도합니다.`);
42
- }
1
+ // insane-search 스킬이 첫 호출에서 받는 파이썬 패키지를 설치 시점에 미리 깔아 둔다.
2
+ // 준비는 어디까지나 선택적이다. 파이썬이 없거나 설치가 실패해도 안내만 남기고 정상 종료해서
3
+ // devezVibe 설치 자체가 깨지지 않게 한다. 스킬은 첫 사용 때 다시 설치를 시도하므로 손해가 없다.
4
+ import { spawnSync } from "node:child_process";
5
+
6
+ // SKILL.md의 의존성 가드와 같은 조합이다. 한쪽만 바뀌면 첫 호출에서 다시 설치가 돈다.
7
+ const guard = 'import curl_cffi,bs4,yaml,pypdf,markdownify; v=curl_cffi.__version__.split("."); assert (int(v[0]),int(v[1]))>=(0,15)';
8
+ const packages = ["curl_cffi>=0.15.0", "beautifulsoup4", "pyyaml", "pypdf", "markdownify"];
9
+
10
+ function run(command, args) {
11
+ return spawnSync(command, args, { encoding: "utf8", windowsHide: true, timeout: 300000 });
12
+ }
13
+
14
+ // Windows에는 python3가 없는 대신 실행하면 스토어를 여는 별칭이 잡혀 있을 수 있다.
15
+ // 버전 출력을 실제로 확인해서 쓸 수 있는 실행기만 고른다.
16
+ function findPython() {
17
+ for (const candidate of ["python3", "python", "py"]) {
18
+ const probe = run(candidate, ["-c", "import sys; print(sys.version_info[0])"]);
19
+ if (probe.status === 0 && probe.stdout.trim() === "3") return candidate;
20
+ }
21
+ return null;
22
+ }
23
+
24
+ const python = findPython();
25
+ if (!python) {
26
+ console.log("insane-search 준비 건너뜀: 파이썬 3을 찾지 못했습니다. 설치하면 첫 사용 때 자동으로 준비됩니다.");
27
+ process.exit(0);
28
+ }
29
+
30
+ if (run(python, ["-c", guard]).status === 0) {
31
+ console.log("insane-search 의존성 준비 완료: 이미 설치되어 있습니다.");
32
+ process.exit(0);
33
+ }
34
+
35
+ // --user는 관리자 권한 없이도 설치되게 하고, 가상환경에서는 pip가 알아서 무시한다.
36
+ const install = run(python, ["-m", "pip", "install", "-U", "--user", "-q", ...packages]);
37
+ if (install.status === 0 && run(python, ["-c", guard]).status === 0) {
38
+ console.log("insane-search 의존성 준비 완료");
39
+ } else {
40
+ const detail = (install.stderr || install.stdout || "").trim().split("\n").pop() || "원인 미상";
41
+ console.log(`insane-search 준비 건너뜀 (${detail}). 첫 사용 때 다시 시도합니다.`);
42
+ }