devez-vibe 1.7.90 → 1.7.92

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/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
@@ -50,25 +50,25 @@ dvz [--resume [SESSION] | --continue] [--model MODEL] [--effort EFFORT]
50
50
  [--cwd PATH] [--codex PATH] [--claude PATH] [--theme THEME]
51
51
  ```
52
52
 
53
- `--resume`만 입력하면 검색 가능한 세션 피커를 열고, `--continue`는 현재 폴더의 가장 최근
54
- 세션을 바로 이어갑니다. 실행 중 전체 명령은 `/help`에서 확인합니다.
55
-
56
- 설치 상태와 제공자 연결 준비 상태는 다음 명령으로 점검합니다.
57
-
58
- ```powershell
59
- dvz doctor
60
- ```
61
-
62
- ## 업데이트
63
-
64
- 새 버전이 배포되면 시작 시 안내 배너가 표시됩니다. 배너의 안내대로 실행하면 됩니다.
65
-
53
+ `--resume`만 입력하면 검색 가능한 세션 피커를 열고, `--continue`는 현재 폴더의 가장 최근
54
+ 세션을 바로 이어갑니다. 실행 중 전체 명령은 `/help`에서 확인합니다.
55
+
56
+ 설치 상태와 제공자 연결 준비 상태는 다음 명령으로 점검합니다.
57
+
58
+ ```powershell
59
+ dvz doctor
60
+ ```
61
+
62
+ ## 업데이트
63
+
64
+ 새 버전이 배포되면 시작 시 안내 배너가 표시됩니다. 배너의 안내대로 실행하면 됩니다.
65
+
66
66
  ```powershell
67
67
  dvz update
68
68
  ```
69
69
 
70
- 새 버전을 별도 경로에 내려받아 실행 파일을 검증한 뒤 다음 실행 버전으로 전환합니다.
71
- 실행 중인 `dvz` 세션은 이전 버전을 유지하고, 새로 시작하는 세션부터 새 버전을 사용합니다.
70
+ 새 버전을 별도 경로에 내려받아 실행 파일을 검증한 뒤 다음 실행 버전으로 전환합니다.
71
+ 실행 중인 `dvz` 세션은 이전 버전을 유지하고, 새로 시작하는 세션부터 새 버전을 사용합니다.
72
72
 
73
73
  업데이트 확인을 끄려면 `DEVEZ_VIBE_NO_UPDATE_CHECK` 환경변수를 설정합니다.
74
74
 
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
+ }
@@ -1634,6 +1634,19 @@ function processAssistant(session, message) {
1634
1634
  message.message?.model,
1635
1635
  session.model,
1636
1636
  );
1637
+ // Usage used to reach the host only with the turn's result, so a session's
1638
+ // first turn read 0k on screen for its whole run. The assistant message
1639
+ // already names the window it occupies, so publish it as it lands. No
1640
+ // `total`: the billing tally is only whole at the result.
1641
+ if (session.lastContextUsage) {
1642
+ notify("thread/tokenUsage/updated", {
1643
+ threadId: session.id,
1644
+ tokenUsage: {
1645
+ last: session.lastContextUsage,
1646
+ modelContextWindow: session.lastContextWindow || undefined,
1647
+ },
1648
+ });
1649
+ }
1637
1650
  const content = Array.isArray(message.message?.content) ? message.message.content : [];
1638
1651
  // Without partial SDK events, replay completed text before tool items so the
1639
1652
  // visible order still matches the assistant content order.
@@ -4656,6 +4669,34 @@ async function runSelfTest() {
4656
4669
  if (openingMessageIndex >= 0 || openingToolIndex < 0) {
4657
4670
  throw new Error(`Claude tool-first turn self-test failed: ${JSON.stringify(openingEvents)}`);
4658
4671
  }
4672
+ const contextCaptured = [];
4673
+ process.stdout.write = (chunk) => {
4674
+ contextCaptured.push(String(chunk));
4675
+ return true;
4676
+ };
4677
+ try {
4678
+ processAssistant(openingSession, {
4679
+ message: {
4680
+ model: "claude-opus-5[1m]",
4681
+ usage: { input_tokens: 400, cache_read_input_tokens: 96_000, output_tokens: 0 },
4682
+ content: [],
4683
+ },
4684
+ });
4685
+ } finally {
4686
+ process.stdout.write = stdoutWrite;
4687
+ }
4688
+ const contextEvent = contextCaptured
4689
+ .join("")
4690
+ .trim()
4691
+ .split("\n")
4692
+ .filter(Boolean)
4693
+ .map((line) => JSON.parse(line))
4694
+ .find((event) => event.method === "thread/tokenUsage/updated");
4695
+ if (contextEvent?.params?.tokenUsage?.last?.totalTokens !== 96_400
4696
+ || contextEvent.params.tokenUsage.modelContextWindow !== 1_000_000
4697
+ || contextEvent.params.tokenUsage.total !== undefined) {
4698
+ throw new Error(`Claude mid-turn context self-test failed: ${JSON.stringify(contextEvent)}`);
4699
+ }
4659
4700
  const languageCaptured = [];
4660
4701
  process.stdout.write = (chunk) => {
4661
4702
  languageCaptured.push(String(chunk));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devez-vibe",
3
- "version": "1.7.90",
3
+ "version": "1.7.92",
4
4
  "type": "module",
5
5
  "description": "Stable terminal UI for Codex and Claude Agent SDK",
6
6
  "keywords": [
@@ -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
+ }
@@ -1,7 +1,7 @@
1
- interface:
2
- display_name: "루프 검증"
3
- short_description: "수정 후 Luna 반복 검증과 병렬 재검수를 자동화"
4
- default_prompt: "직접 $luna-loop을 호출해 수정 사항을 검증하고 문제가 남으면 재수정한 뒤 다시 검증해 주세요."
5
-
6
- policy:
7
- allow_implicit_invocation: false
1
+ interface:
2
+ display_name: "루프 검증"
3
+ short_description: "수정 후 Luna 반복 검증과 병렬 재검수를 자동화"
4
+ default_prompt: "직접 $luna-loop을 호출해 수정 사항을 검증하고 문제가 남으면 재수정한 뒤 다시 검증해 주세요."
5
+
6
+ policy:
7
+ allow_implicit_invocation: false