devez-vibe 1.7.50 → 1.7.52

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 (64) hide show
  1. package/LICENSE +33 -33
  2. package/README.md +5 -5
  3. package/bin/dvz.exe +0 -0
  4. package/bridge/claude-agent-sdk-bridge.mjs +39 -36
  5. package/install-skills.mjs +21 -16
  6. package/package.json +4 -2
  7. package/prepare-search-deps.mjs +42 -0
  8. package/skills/insane-search/LICENSE +21 -0
  9. package/skills/insane-search/SKILL.md +378 -0
  10. package/skills/insane-search/engine/__init__.py +40 -0
  11. package/skills/insane-search/engine/__main__.py +148 -0
  12. package/skills/insane-search/engine/bias_check.py +183 -0
  13. package/skills/insane-search/engine/content_safety.py +155 -0
  14. package/skills/insane-search/engine/executor.py +419 -0
  15. package/skills/insane-search/engine/fetch_chain.py +1276 -0
  16. package/skills/insane-search/engine/learning.py +179 -0
  17. package/skills/insane-search/engine/observations_log.py +62 -0
  18. package/skills/insane-search/engine/phase0.py +273 -0
  19. package/skills/insane-search/engine/safety.py +91 -0
  20. package/skills/insane-search/engine/templates/nodriver_fetch.py +48 -0
  21. package/skills/insane-search/engine/templates/package.json +12 -0
  22. package/skills/insane-search/engine/templates/patchright_fetch.py +49 -0
  23. package/skills/insane-search/engine/templates/playwright_mobile_chrome.js +115 -0
  24. package/skills/insane-search/engine/templates/playwright_real_chrome.js +168 -0
  25. package/skills/insane-search/engine/tests/test_smoke.py +152 -0
  26. package/skills/insane-search/engine/tests/test_t1_retry.py +149 -0
  27. package/skills/insane-search/engine/tests/test_t2_rescue.py +311 -0
  28. package/skills/insane-search/engine/tests/test_t3_markdown.py +137 -0
  29. package/skills/insane-search/engine/tests/test_t4_maincontent.py +128 -0
  30. package/skills/insane-search/engine/tests/test_t5_pdfplumber.py +140 -0
  31. package/skills/insane-search/engine/tests/test_t6_differential.py +92 -0
  32. package/skills/insane-search/engine/tests/test_t7_browser_gate.py +229 -0
  33. package/skills/insane-search/engine/tests/test_u1.py +200 -0
  34. package/skills/insane-search/engine/tests/test_u4.py +145 -0
  35. package/skills/insane-search/engine/tests/test_u5.py +163 -0
  36. package/skills/insane-search/engine/tests/test_u7.py +124 -0
  37. package/skills/insane-search/engine/tests/test_u8.py +216 -0
  38. package/skills/insane-search/engine/tests/test_u9.py +117 -0
  39. package/skills/insane-search/engine/tests/test_url_masking.py +123 -0
  40. package/skills/insane-search/engine/transport.py +310 -0
  41. package/skills/insane-search/engine/url_masking.py +70 -0
  42. package/skills/insane-search/engine/url_transforms.py +98 -0
  43. package/skills/insane-search/engine/validators.py +349 -0
  44. package/skills/insane-search/engine/waf_detector.py +214 -0
  45. package/skills/insane-search/engine/waf_profiles.yaml +221 -0
  46. package/skills/insane-search/engine/x_search.py +289 -0
  47. package/skills/insane-search/engine/x_search_io.py +46 -0
  48. package/skills/insane-search/engine/x_search_types.py +42 -0
  49. package/skills/insane-search/references/cache-archive.md +83 -0
  50. package/skills/insane-search/references/fallback.md +159 -0
  51. package/skills/insane-search/references/jina.md +128 -0
  52. package/skills/insane-search/references/json-api.md +170 -0
  53. package/skills/insane-search/references/media.md +148 -0
  54. package/skills/insane-search/references/metadata.md +116 -0
  55. package/skills/insane-search/references/naver.md +107 -0
  56. package/skills/insane-search/references/playwright.md +146 -0
  57. package/skills/insane-search/references/public-api.md +119 -0
  58. package/skills/insane-search/references/rss.md +128 -0
  59. package/skills/insane-search/references/tls-impersonate.md +188 -0
  60. package/skills/insane-search/references/twitter.md +141 -0
  61. package/skills/insane-search/tests/coverage_battery.py +297 -0
  62. package/skills/insane-search/tests/live_benchmark/bench.py +100 -0
  63. package/skills/insane-search/tests/test_x_search.py +251 -0
  64. package/skills/luna-loop/agents/openai.yaml +7 -7
package/LICENSE CHANGED
@@ -1,33 +1,33 @@
1
- DevezCode source code license
2
-
3
- The MIT License below applies only to the DevezCode source code and to files
4
- that are not listed in the exception below.
5
-
6
- Exceptions:
7
-
8
- * `Resources/Images/FileTypes/` and `Resources/Licenses/` are Microsoft Visual
9
- Studio Image Library materials, subject to the included Microsoft terms.
10
- * `Resources/Images/ShellPresets/` contains third-party brand assets, subject
11
- to their respective owners' terms.
12
-
13
- MIT License
14
-
15
- Copyright (c) 2026 DevezCode contributors
16
-
17
- Permission is hereby granted, free of charge, to any person obtaining a copy
18
- of this software and associated documentation files (the "Software"), to deal
19
- in the Software without restriction, including without limitation the rights
20
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21
- copies of the Software, and to permit persons to whom the Software is
22
- furnished to do so, subject to the following conditions:
23
-
24
- The above copyright notice and this permission notice shall be included in all
25
- copies or substantial portions of the Software.
26
-
27
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33
- SOFTWARE.
1
+ DevezCode source code license
2
+
3
+ The MIT License below applies only to the DevezCode source code and to files
4
+ that are not listed in the exception below.
5
+
6
+ Exceptions:
7
+
8
+ * `Resources/Images/FileTypes/` and `Resources/Licenses/` are Microsoft Visual
9
+ Studio Image Library materials, subject to the included Microsoft terms.
10
+ * `Resources/Images/ShellPresets/` contains third-party brand assets, subject
11
+ to their respective owners' terms.
12
+
13
+ MIT License
14
+
15
+ Copyright (c) 2026 DevezCode contributors
16
+
17
+ Permission is hereby granted, free of charge, to any person obtaining a copy
18
+ of this software and associated documentation files (the "Software"), to deal
19
+ in the Software without restriction, including without limitation the rights
20
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21
+ copies of the Software, and to permit persons to whom the Software is
22
+ furnished to do so, subject to the following conditions:
23
+
24
+ The above copyright notice and this permission notice shall be included in all
25
+ copies or substantial portions of the Software.
26
+
27
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33
+ SOFTWARE.
package/README.md CHANGED
@@ -10,11 +10,11 @@
10
10
  npm install -g devez-vibe
11
11
  ```
12
12
 
13
- 설치하면 `dvz` 명령을 사용할 수 있습니다.
14
-
15
- 설치 과정에서 `luna-loop` 스킬도 Codex와 Claude의 사용자 스킬 경로에 함께 설치됩니다.
16
- 스킬은 자동 적용되지 않으며 `$luna-loop`로 직접 호출해야 합니다. 실제
17
- `gpt-5.6-luna` 검증을 사용하려면 Codex provider와 Luna 위임 기능이 연결돼 있어야 합니다.
13
+ 설치하면 `dvz` 명령을 사용할 수 있습니다.
14
+
15
+ 설치 과정에서 `luna-loop` 스킬도 Codex와 Claude의 사용자 스킬 경로에 함께 설치됩니다.
16
+ 스킬은 자동 적용되지 않으며 `$luna-loop`로 직접 호출해야 합니다. 실제
17
+ `gpt-5.6-luna` 검증을 사용하려면 Codex provider와 Luna 위임 기능이 연결돼 있어야 합니다.
18
18
 
19
19
  | 요건 | 값 |
20
20
  | --- | --- |
package/bin/dvz.exe CHANGED
Binary file
@@ -700,6 +700,9 @@ function makeOptions(params, sessionId, resume) {
700
700
  // Task tools left the default surface in SDK 0.3.233. Listing them here
701
701
  // keeps the plan panel available without replacing the Claude Code preset.
702
702
  allowedTools: [...CLAUDE_TASK_TOOLS],
703
+ // The fixed-model lanes the Planner and Goal Runner roles dispatch. The
704
+ // host owns the definitions so Claude and Codex read the same text.
705
+ ...(params.agents ? { agents: params.agents } : {}),
703
706
  // DevezVibe keeps per-task controls available through Claude's TaskStop
704
707
  // tool, so a turn interrupt must not tear down independent background work.
705
708
  perTaskStopAffordance: true,
@@ -1546,9 +1549,9 @@ function processAssistant(session, message) {
1546
1549
  capabilities,
1547
1550
  message.message?.model,
1548
1551
  session.model,
1549
- );
1550
- const content = Array.isArray(message.message?.content) ? message.message.content : [];
1551
- // Without partial SDK events, replay completed text before tool items so the
1552
+ );
1553
+ const content = Array.isArray(message.message?.content) ? message.message.content : [];
1554
+ // Without partial SDK events, replay completed text before tool items so the
1552
1555
  // visible order still matches the assistant content order.
1553
1556
  if (!session.streamBlocks.size && !session.turn.sawStreamText) {
1554
1557
  for (const block of content) {
@@ -2898,22 +2901,22 @@ function historyState(messages) {
2898
2901
  }));
2899
2902
  turn.items.push({ id: "claude-plan-latest", type: "plan", text, steps });
2900
2903
  }
2901
- return {
2902
- tasks,
2903
- turns: turns
2904
- .filter((candidate) => !candidate.synthetic)
2905
- .map(({ synthetic: _, ...candidate }) => {
2906
- const answered = candidate.items.some((item) =>
2907
- item.type === "agentMessage" && String(item.text || "").trim());
2908
- // Claude persists the user record before an immediate interrupt. Native
2909
- // resume hides that dangling prompt, so expose it as interrupted for the
2910
- // common host history filter instead of calling every transcript turn
2911
- // completed.
2912
- if (!answered) candidate.status = "interrupted";
2913
- return candidate;
2914
- }),
2915
- };
2916
- }
2904
+ return {
2905
+ tasks,
2906
+ turns: turns
2907
+ .filter((candidate) => !candidate.synthetic)
2908
+ .map(({ synthetic: _, ...candidate }) => {
2909
+ const answered = candidate.items.some((item) =>
2910
+ item.type === "agentMessage" && String(item.text || "").trim());
2911
+ // Claude persists the user record before an immediate interrupt. Native
2912
+ // resume hides that dangling prompt, so expose it as interrupted for the
2913
+ // common host history filter instead of calling every transcript turn
2914
+ // completed.
2915
+ if (!answered) candidate.status = "interrupted";
2916
+ return candidate;
2917
+ }),
2918
+ };
2919
+ }
2917
2920
 
2918
2921
  function historyTurns(messages) {
2919
2922
  return historyState(messages).turns;
@@ -3604,15 +3607,15 @@ async function runSelfTest() {
3604
3607
  ["say hello", "claude:claude-sonnet-5"],
3605
3608
  ["hay zzz", "claude:claude-haiku-4-5-20251001"],
3606
3609
  ];
3607
- if (turns.length !== expected.length
3608
- || prompts.some((prompt, index) => prompt?.content?.[0]?.text !== expected[index][0]
3609
- || prompt.model !== expected[index][1])) {
3610
- throw new Error(`Claude history self-test failed: ${JSON.stringify(turns)}`);
3611
- }
3612
- const interrupted = historyTurns([user("cancelled", "취소한 요청")]);
3613
- if (interrupted.length !== 1 || interrupted[0].status !== "interrupted") {
3614
- throw new Error(`Claude interrupted prompt history self-test failed: ${JSON.stringify(interrupted)}`);
3615
- }
3610
+ if (turns.length !== expected.length
3611
+ || prompts.some((prompt, index) => prompt?.content?.[0]?.text !== expected[index][0]
3612
+ || prompt.model !== expected[index][1])) {
3613
+ throw new Error(`Claude history self-test failed: ${JSON.stringify(turns)}`);
3614
+ }
3615
+ const interrupted = historyTurns([user("cancelled", "취소한 요청")]);
3616
+ if (interrupted.length !== 1 || interrupted[0].status !== "interrupted") {
3617
+ throw new Error(`Claude interrupted prompt history self-test failed: ${JSON.stringify(interrupted)}`);
3618
+ }
3616
3619
  const taskUse = (uuid, id, name, input) => ({
3617
3620
  type: "assistant",
3618
3621
  uuid,
@@ -4434,14 +4437,14 @@ async function runSelfTest() {
4434
4437
  .split("\n")
4435
4438
  .filter(Boolean)
4436
4439
  .map((line) => JSON.parse(line));
4437
- const openingMessageIndex = openingEvents.findIndex((event) =>
4438
- event.method === "item/completed"
4439
- && event.params?.item?.type === "agentMessage");
4440
- const openingToolIndex = openingEvents.findIndex((event) =>
4441
- event.method === "item/started" && event.params?.item?.type === "dynamicToolCall");
4442
- if (openingMessageIndex >= 0 || openingToolIndex < 0) {
4443
- throw new Error(`Claude tool-first turn self-test failed: ${JSON.stringify(openingEvents)}`);
4444
- }
4440
+ const openingMessageIndex = openingEvents.findIndex((event) =>
4441
+ event.method === "item/completed"
4442
+ && event.params?.item?.type === "agentMessage");
4443
+ const openingToolIndex = openingEvents.findIndex((event) =>
4444
+ event.method === "item/started" && event.params?.item?.type === "dynamicToolCall");
4445
+ if (openingMessageIndex >= 0 || openingToolIndex < 0) {
4446
+ throw new Error(`Claude tool-first turn self-test failed: ${JSON.stringify(openingEvents)}`);
4447
+ }
4445
4448
  const languageCaptured = [];
4446
4449
  process.stdout.write = (chunk) => {
4447
4450
  languageCaptured.push(String(chunk));
@@ -10,14 +10,14 @@ import { dirname, join } from "node:path";
10
10
  import { fileURLToPath } from "node:url";
11
11
 
12
12
  const packageRoot = dirname(fileURLToPath(import.meta.url));
13
- const sourceRoot = join(packageRoot, "skills", "luna-loop");
13
+ const skillNames = ["luna-loop", "insane-search"];
14
14
  const userHome = homedir();
15
15
  const codexHome = process.env.CODEX_HOME?.trim() || join(userHome, ".codex");
16
16
  const claudeHome = process.env.CLAUDE_CONFIG_DIR?.trim() || join(userHome, ".claude");
17
17
 
18
- const targets = [
19
- { name: "Codex", path: join(codexHome, "skills", "luna-loop") },
20
- { name: "Claude", path: join(claudeHome, "skills", "luna-loop") },
18
+ const homes = [
19
+ { name: "Codex", root: join(codexHome, "skills") },
20
+ { name: "Claude", root: join(claudeHome, "skills") },
21
21
  ];
22
22
 
23
23
  function copyTree(source, destination) {
@@ -47,20 +47,25 @@ function pruneTree(source, destination) {
47
47
  }
48
48
  }
49
49
 
50
- if (!existsSync(join(sourceRoot, "SKILL.md"))) {
51
- console.error(`스킬 원본(luna-loop)을 찾지 못했습니다: ${sourceRoot}`);
52
- process.exit(1);
53
- }
54
-
55
50
  let failed = false;
56
- for (const target of targets) {
57
- try {
58
- copyTree(sourceRoot, target.path);
59
- pruneTree(sourceRoot, target.path);
60
- console.log(`스킬 설치 완료 (${target.name}): ${target.path}`);
61
- } catch (error) {
51
+ for (const skill of skillNames) {
52
+ const sourceRoot = join(packageRoot, "skills", skill);
53
+ // 원본이 없으면 그 스킬만 건너뛴다. 하나가 빠졌다고 나머지 설치까지 막지 않는다.
54
+ if (!existsSync(join(sourceRoot, "SKILL.md"))) {
62
55
  failed = true;
63
- console.error(`스킬 설치 실패 (${target.name}): ${error instanceof Error ? error.message : error}`);
56
+ console.error(`스킬 원본(${skill}) 찾지 못했습니다: ${sourceRoot}`);
57
+ continue;
58
+ }
59
+ for (const home of homes) {
60
+ const target = join(home.root, skill);
61
+ try {
62
+ copyTree(sourceRoot, target);
63
+ pruneTree(sourceRoot, target);
64
+ console.log(`스킬 설치 완료 (${home.name}/${skill}): ${target}`);
65
+ } catch (error) {
66
+ failed = true;
67
+ console.error(`스킬 설치 실패 (${home.name}/${skill}): ${error instanceof Error ? error.message : error}`);
68
+ }
64
69
  }
65
70
  }
66
71
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devez-vibe",
3
- "version": "1.7.50",
3
+ "version": "1.7.52",
4
4
  "description": "Stable terminal UI for Codex and Claude Agent SDK",
5
5
  "keywords": [
6
6
  "codex",
@@ -24,7 +24,9 @@
24
24
  "bin/dvz.exe",
25
25
  "bridge/claude-agent-sdk-bridge.mjs",
26
26
  "install-skills.mjs",
27
+ "prepare-search-deps.mjs",
27
28
  "skills/luna-loop/",
29
+ "skills/insane-search/",
28
30
  "README.md",
29
31
  "LICENSE"
30
32
  ],
@@ -38,7 +40,7 @@
38
40
  "node": ">=18"
39
41
  },
40
42
  "scripts": {
41
- "postinstall": "node install-skills.mjs"
43
+ "postinstall": "node install-skills.mjs && node prepare-search-deps.mjs"
42
44
  },
43
45
  "dependencies": {
44
46
  "@anthropic-ai/claude-agent-sdk": "0.3.260"
@@ -0,0 +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
+ }
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 fivetaku
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.