devez-vibe 1.5.20 → 1.5.21

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/bin/dvz.exe CHANGED
Binary file
@@ -149,13 +149,7 @@ function modelCapabilities(models, model) {
149
149
  }
150
150
 
151
151
  function opus48Capabilities(models, existing = {}) {
152
- // The CLI now exposes the Opus alias as `opus[1m]` (and only `default`
153
- // resolves to it), so an exact `value === "opus"` match finds nothing and the
154
- // synthesized Opus 4.8 row loses supportsAutoMode/supportsFastMode. Match the
155
- // Opus family instead, falling back to `default`.
156
- const opus = models.find((model) => String(model.value || "").toLowerCase().startsWith("opus"))
157
- || models.find((model) => model.value === "default")
158
- || {};
152
+ const opus = models.find((model) => model.value === "opus") || {};
159
153
  const opusEfforts = Array.isArray(opus.supportedEffortLevels)
160
154
  ? opus.supportedEffortLevels
161
155
  : [];
@@ -1683,34 +1677,62 @@ function notificationTag(body, name) {
1683
1677
  return match?.[1]?.trim() || "";
1684
1678
  }
1685
1679
 
1680
+ // 완료 통지는 SDK 빌드에 따라 문자열·text 블록·다른 블록 형태로 올 수 있다.
1681
+ // 감지가 본문 구조에 좌우되면 백그라운드 서브에이전트가 영원히 남으므로, 잡을 수
1682
+ // 있는 모든 문자열을 한데 모은다.
1683
+ function messageAllText(message) {
1684
+ const content = message.message?.content;
1685
+ if (typeof content === "string") return content;
1686
+ if (!Array.isArray(content)) return "";
1687
+ const parts = [];
1688
+ for (const block of content) {
1689
+ if (typeof block === "string") parts.push(block);
1690
+ else if (typeof block?.text === "string") parts.push(block.text);
1691
+ else if (typeof block?.content === "string") parts.push(block.content);
1692
+ }
1693
+ return parts.join("\n");
1694
+ }
1695
+
1686
1696
  function taskNotifications(message) {
1687
- if (message.origin?.kind !== "task-notification"
1688
- && !messageTextParts(message).some((text) => text.includes("<task-notification>"))) {
1697
+ const raw = messageAllText(message);
1698
+ if (message.origin?.kind !== "task-notification" && !raw.includes("<task-notification>")) {
1689
1699
  return [];
1690
1700
  }
1691
1701
  const notifications = [];
1692
- for (const text of messageTextParts(message)) {
1693
- for (const match of text.matchAll(/<task-notification>([\s\S]*?)<\/task-notification>/g)) {
1694
- const body = match[1];
1695
- notifications.push({
1696
- taskId: notificationTag(body, "task-id"),
1697
- toolUseId: notificationTag(body, "tool-use-id"),
1698
- status: notificationTag(body, "status"),
1699
- summary: notificationTag(body, "summary"),
1700
- });
1701
- }
1702
+ for (const match of raw.matchAll(/<task-notification>([\s\S]*?)<\/task-notification>/g)) {
1703
+ const body = match[1];
1704
+ notifications.push({
1705
+ taskId: notificationTag(body, "task-id"),
1706
+ toolUseId: notificationTag(body, "tool-use-id"),
1707
+ status: notificationTag(body, "status"),
1708
+ summary: notificationTag(body, "summary"),
1709
+ });
1702
1710
  }
1703
1711
  return notifications;
1704
1712
  }
1705
1713
 
1714
+ // 통지 요약은 보통 `Agent "Explore" finished` 형태로 에이전트 이름을 따옴표로 담는다.
1715
+ function subagentNameFromSummary(summary) {
1716
+ return String(summary || "").match(/"([^"]+)"/)?.[1] || "";
1717
+ }
1718
+
1706
1719
  function finishNotifiedSubagents(session, notifications) {
1707
1720
  for (const notification of notifications) {
1708
1721
  const byToolUse = notification.toolUseId
1709
1722
  ? session.subagents.get(notification.toolUseId)
1710
1723
  : null;
1711
- const running = byToolUse || (notification.taskId
1724
+ let running = byToolUse || (notification.taskId
1712
1725
  ? [...session.subagents.values()].find((agent) => agent.taskId === notification.taskId)
1713
1726
  : null);
1727
+ // 전달 형태에 따라 id가 어긋날 수 있다. 그때는 요약이 지목한 이름의 백그라운드
1728
+ // 에이전트를 지워, 끝난 에이전트가 그래도 행에서 사라지게 한다.
1729
+ if (!running) {
1730
+ const name = subagentNameFromSummary(notification.summary);
1731
+ if (name) {
1732
+ running = [...session.subagents.values()]
1733
+ .find((agent) => agent.background && agent.name === name);
1734
+ }
1735
+ }
1714
1736
  if (!running) continue;
1715
1737
  emitSubagentLine(session, running.id, {
1716
1738
  kind: notification.status === "completed" ? "result" : "error",
@@ -2852,12 +2874,11 @@ async function runSelfTest() {
2852
2874
  }
2853
2875
  const catalogModels = [
2854
2876
  {
2855
- value: "opus[1m]",
2856
- resolvedModel: "claude-opus-5[1m]",
2877
+ value: "opus",
2878
+ resolvedModel: "claude-opus-5",
2857
2879
  displayName: "Opus 5",
2858
2880
  supportsEffort: true,
2859
2881
  supportedEffortLevels: ["high", "max"],
2860
- supportsAutoMode: true,
2861
2882
  },
2862
2883
  { value: "sonnet", resolvedModel: "claude-sonnet-5", displayName: "Sonnet 5" },
2863
2884
  {
@@ -2872,7 +2893,6 @@ async function runSelfTest() {
2872
2893
  if (catalog[0]?.displayName !== "Opus 5"
2873
2894
  || catalog[1]?.displayName !== "Opus 4.8"
2874
2895
  || catalog[1]?.model !== "claude:claude-opus-4-8"
2875
- || catalog[1]?.supportsAutoMode !== true
2876
2896
  || catalog[1]?.supportedReasoningEfforts?.[1]?.reasoningEffort !== "max"
2877
2897
  || supportedEffort(
2878
2898
  modelCapabilities(catalogModels, "claude:claude-opus-4-8"),
@@ -2899,6 +2919,33 @@ async function runSelfTest() {
2899
2919
  || notification[0].summary !== 'Agent "Explore" finished') {
2900
2920
  throw new Error(`Claude task notification self-test failed: ${JSON.stringify(notification)}`);
2901
2921
  }
2922
+ // 통지가 문자열이 아닌 text 블록 배열로 와도 감지해야 한다.
2923
+ const blockNotification = taskNotifications({
2924
+ message: {
2925
+ content: [{
2926
+ type: "text",
2927
+ text: `[SYSTEM NOTIFICATION]\n<task-notification>\n<task-id>agent-9</task-id>\n<tool-use-id>toolu_9</tool-use-id>\n<status>completed</status>\n<summary>Agent "Explore" finished</summary>\n</task-notification>`,
2928
+ }],
2929
+ },
2930
+ });
2931
+ if (blockNotification.length !== 1 || blockNotification[0].taskId !== "agent-9") {
2932
+ throw new Error(`Claude block notification self-test failed: ${JSON.stringify(blockNotification)}`);
2933
+ }
2934
+ // id가 어긋나도 요약의 이름으로 백그라운드 서브에이전트를 정리해야 한다.
2935
+ const nameFallbackSession = {
2936
+ id: "name-fallback-session",
2937
+ turn: { id: "t", sawStreamText: false },
2938
+ subagents: new Map([[
2939
+ "toolu_live",
2940
+ { id: "toolu_live", taskId: "agent-live", background: true, name: "Explore", description: "", tool: "", startedAt: Date.now() },
2941
+ ]]),
2942
+ };
2943
+ finishNotifiedSubagents(nameFallbackSession, [{
2944
+ taskId: "mismatch", toolUseId: "mismatch", status: "completed", summary: 'Agent "Explore" finished',
2945
+ }]);
2946
+ if (nameFallbackSession.subagents.size !== 0) {
2947
+ throw new Error("Claude subagent name fallback self-test failed");
2948
+ }
2902
2949
  const lifecycleSession = {
2903
2950
  id: "self-test-session",
2904
2951
  turn: { id: "parent-turn", sawStreamText: false },
package/package.json CHANGED
@@ -1,41 +1,41 @@
1
- {
2
- "name": "devez-vibe",
3
- "version": "1.5.20",
4
- "description": "Stable terminal UI for Codex and Claude Agent SDK",
5
- "keywords": [
6
- "codex",
7
- "cli",
8
- "tui",
9
- "terminal",
10
- "app-server",
11
- "claude-agent-sdk"
12
- ],
13
- "homepage": "https://github.com/MrHoje/Devez-vibe#readme",
14
- "bugs": "https://github.com/MrHoje/Devez-vibe/issues",
15
- "repository": {
16
- "type": "git",
17
- "url": "git+https://github.com/MrHoje/Devez-vibe.git"
18
- },
19
- "license": "MIT",
20
- "bin": {
21
- "dvz": "bin/dvz.exe"
22
- },
23
- "files": [
24
- "bin/dvz.exe",
25
- "bridge/claude-agent-sdk-bridge.mjs",
26
- "README.md",
27
- "LICENSE"
28
- ],
29
- "os": [
30
- "win32"
31
- ],
32
- "cpu": [
33
- "x64"
34
- ],
35
- "engines": {
36
- "node": ">=18"
37
- },
38
- "dependencies": {
39
- "@anthropic-ai/claude-agent-sdk": "0.3.223"
40
- }
41
- }
1
+ {
2
+ "name": "devez-vibe",
3
+ "version": "1.5.21",
4
+ "description": "Stable terminal UI for Codex and Claude Agent SDK",
5
+ "keywords": [
6
+ "codex",
7
+ "cli",
8
+ "tui",
9
+ "terminal",
10
+ "app-server",
11
+ "claude-agent-sdk"
12
+ ],
13
+ "homepage": "https://github.com/MrHoje/Devez-vibe#readme",
14
+ "bugs": "https://github.com/MrHoje/Devez-vibe/issues",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/MrHoje/Devez-vibe.git"
18
+ },
19
+ "license": "MIT",
20
+ "bin": {
21
+ "dvz": "bin/dvz.exe"
22
+ },
23
+ "files": [
24
+ "bin/dvz.exe",
25
+ "bridge/claude-agent-sdk-bridge.mjs",
26
+ "README.md",
27
+ "LICENSE"
28
+ ],
29
+ "os": [
30
+ "win32"
31
+ ],
32
+ "cpu": [
33
+ "x64"
34
+ ],
35
+ "engines": {
36
+ "node": ">=18"
37
+ },
38
+ "dependencies": {
39
+ "@anthropic-ai/claude-agent-sdk": "0.3.231"
40
+ }
41
+ }