devez-vibe 1.2.17 → 1.2.18
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/bin/dvz.exe +0 -0
- package/bridge/claude-agent-sdk-bridge.mjs +62 -11
- package/package.json +1 -1
package/bin/dvz.exe
CHANGED
|
Binary file
|
|
@@ -884,7 +884,25 @@ function prepareTaskPlanForCreate(tasks, subject) {
|
|
|
884
884
|
if (numberedTaskIndex(subject) === 1) tasks.clear();
|
|
885
885
|
}
|
|
886
886
|
|
|
887
|
-
|
|
887
|
+
// 한 단계에 걸린 시간은 진행 중으로 바뀐 순간과 완료된 순간의 차이다. 기록에는
|
|
888
|
+
// 항목마다 시각이 남으므로, 다시 읽을 때도 같은 방식으로 되살릴 수 있다.
|
|
889
|
+
function markTaskStatus(task, status, at) {
|
|
890
|
+
if (task.status !== status && at != null) {
|
|
891
|
+
if (status === "in_progress") {
|
|
892
|
+
task.startedAt = task.startedAt ?? at;
|
|
893
|
+
} else if (status === "completed" && task.startedAt != null) {
|
|
894
|
+
task.elapsedMs = Math.max(0, at - task.startedAt);
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
task.status = status;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
function messageTime(message) {
|
|
901
|
+
const parsed = Date.parse(message?.timestamp || "");
|
|
902
|
+
return Number.isNaN(parsed) ? null : parsed;
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
function applyTaskUpdate(tasks, input, turnId, onIntermediate, at) {
|
|
888
906
|
const task = tasks.get(String(input.taskId));
|
|
889
907
|
if (!task) return false;
|
|
890
908
|
if (input.subject) task.subject = input.subject;
|
|
@@ -900,11 +918,11 @@ function applyTaskUpdate(tasks, input, turnId, onIntermediate) {
|
|
|
900
918
|
const previous = entries[index];
|
|
901
919
|
if (previous.status === "completed") continue;
|
|
902
920
|
if (previous.status !== "in_progress") {
|
|
903
|
-
previous
|
|
921
|
+
markTaskStatus(previous, "in_progress", at);
|
|
904
922
|
previous.turnId = turnId;
|
|
905
923
|
onIntermediate?.();
|
|
906
924
|
}
|
|
907
|
-
previous
|
|
925
|
+
markTaskStatus(previous, "completed", at);
|
|
908
926
|
previous.turnId = turnId;
|
|
909
927
|
onIntermediate?.();
|
|
910
928
|
}
|
|
@@ -912,19 +930,19 @@ function applyTaskUpdate(tasks, input, turnId, onIntermediate) {
|
|
|
912
930
|
for (let index = 0; index < entries.length; index++) {
|
|
913
931
|
const other = entries[index];
|
|
914
932
|
if (other === task || other.status !== "in_progress") continue;
|
|
915
|
-
other
|
|
933
|
+
markTaskStatus(other, index < targetIndex ? "completed" : "pending", at);
|
|
916
934
|
other.turnId = turnId;
|
|
917
935
|
onIntermediate?.();
|
|
918
936
|
}
|
|
919
937
|
|
|
920
938
|
if (status === "completed" && task.status !== "in_progress" && task.status !== "completed") {
|
|
921
|
-
task
|
|
939
|
+
markTaskStatus(task, "in_progress", at);
|
|
922
940
|
task.turnId = turnId;
|
|
923
941
|
onIntermediate?.();
|
|
924
942
|
}
|
|
925
|
-
task
|
|
943
|
+
markTaskStatus(task, status, at);
|
|
926
944
|
} else if (status) {
|
|
927
|
-
task
|
|
945
|
+
markTaskStatus(task, status, at);
|
|
928
946
|
}
|
|
929
947
|
task.turnId = turnId;
|
|
930
948
|
return true;
|
|
@@ -955,7 +973,7 @@ function updatePlanFromToolUse(session, name, toolUseId, input) {
|
|
|
955
973
|
return;
|
|
956
974
|
} else if (name === "TaskUpdate") {
|
|
957
975
|
session.planCreatePending = false;
|
|
958
|
-
applyTaskUpdate(session.tasks, input, turnId, () => emitPlan(session));
|
|
976
|
+
applyTaskUpdate(session.tasks, input, turnId, () => emitPlan(session), Date.now());
|
|
959
977
|
}
|
|
960
978
|
if (name === "TaskUpdate") emitPlan(session);
|
|
961
979
|
}
|
|
@@ -1574,7 +1592,7 @@ function historyState(messages) {
|
|
|
1574
1592
|
prepareTaskPlanForCreate(tasks, block.input?.subject);
|
|
1575
1593
|
tasks.set(`pending:${block.id}`, { id: `pending:${block.id}`, subject: block.input?.subject || "작업", status: "pending", turnId: turn.id });
|
|
1576
1594
|
} else if (block.name === "TaskUpdate") {
|
|
1577
|
-
applyTaskUpdate(tasks, block.input || {}, turn.id);
|
|
1595
|
+
applyTaskUpdate(tasks, block.input || {}, turn.id, undefined, messageTime(message));
|
|
1578
1596
|
} else if (!["TaskList", "AskUserQuestion"].includes(block.name)) turn.items.push(pending.item);
|
|
1579
1597
|
}
|
|
1580
1598
|
}
|
|
@@ -1594,7 +1612,19 @@ function historyState(messages) {
|
|
|
1594
1612
|
} else if (pending.name === "TaskList" && Array.isArray(message.tool_use_result?.tasks)) {
|
|
1595
1613
|
const known = new Map(tasks);
|
|
1596
1614
|
tasks.clear();
|
|
1597
|
-
for (const task of message.tool_use_result.tasks)
|
|
1615
|
+
for (const task of message.tool_use_result.tasks) {
|
|
1616
|
+
const previous = known.get(String(task.id));
|
|
1617
|
+
tasks.set(String(task.id), {
|
|
1618
|
+
id: String(task.id),
|
|
1619
|
+
subject: task.subject || "작업",
|
|
1620
|
+
status: task.status || "pending",
|
|
1621
|
+
turnId: previous?.turnId ?? turn.id,
|
|
1622
|
+
// A listing restates the plan; it does not re-run it, so the
|
|
1623
|
+
// timings already measured for these steps have to survive it.
|
|
1624
|
+
startedAt: previous?.startedAt,
|
|
1625
|
+
elapsedMs: previous?.elapsedMs,
|
|
1626
|
+
});
|
|
1627
|
+
}
|
|
1598
1628
|
const current = latestTaskPlan(tasks);
|
|
1599
1629
|
tasks.clear();
|
|
1600
1630
|
for (const [id, task] of current) tasks.set(id, task);
|
|
@@ -1611,7 +1641,14 @@ function historyState(messages) {
|
|
|
1611
1641
|
}
|
|
1612
1642
|
if (turn && tasks.size) {
|
|
1613
1643
|
const text = [...tasks.values()].map((task, index) => `${task.status === "completed" ? "✓" : task.status === "in_progress" ? "▸" : "□"} ${numberedTaskSubject(task.subject, index)}`).join("\n");
|
|
1614
|
-
|
|
1644
|
+
// The text alone cannot say how long a step took, so the measured times ride
|
|
1645
|
+
// alongside it and the restored plan shows its total instead of zero.
|
|
1646
|
+
const steps = [...tasks.values()].map((task, index) => ({
|
|
1647
|
+
step: numberedTaskSubject(task.subject, index),
|
|
1648
|
+
status: task.status || "pending",
|
|
1649
|
+
elapsedMs: task.elapsedMs ?? null,
|
|
1650
|
+
}));
|
|
1651
|
+
turn.items.push({ id: "claude-plan-latest", type: "plan", text, steps });
|
|
1615
1652
|
}
|
|
1616
1653
|
return {
|
|
1617
1654
|
tasks,
|
|
@@ -1937,6 +1974,20 @@ async function runSelfTest() {
|
|
|
1937
1974
|
|| [...restoredTasks.values()].filter((task) => task.status === "in_progress").length !== 1) {
|
|
1938
1975
|
throw new Error(`Claude sequential task update self-test failed: ${JSON.stringify([...restoredTasks])}`);
|
|
1939
1976
|
}
|
|
1977
|
+
// Each transcript record is stamped, so a step's own run is the span between
|
|
1978
|
+
// the update that started it and the one that closed it.
|
|
1979
|
+
const at = (message, timestamp) => ({ ...message, timestamp });
|
|
1980
|
+
const timedMessages = [
|
|
1981
|
+
at(user("timed", "작업을 진행해"), "2026-08-07T01:00:00.000Z"),
|
|
1982
|
+
at(taskUse("timed-create-use", "timed-create", "TaskCreate", { subject: "1. 확인" }), "2026-08-07T01:00:01.000Z"),
|
|
1983
|
+
at(taskResult("timed-create-result", "timed-create", { task: { id: "t1", subject: "1. 확인" } }, "Task #t1 created successfully: 1. 확인"), "2026-08-07T01:00:02.000Z"),
|
|
1984
|
+
at(taskUse("timed-start", "timed-start", "TaskUpdate", { taskId: "t1", status: "in_progress" }), "2026-08-07T01:00:03.000Z"),
|
|
1985
|
+
at(taskUse("timed-done", "timed-done", "TaskUpdate", { taskId: "t1", status: "completed" }), "2026-08-07T01:00:09.000Z"),
|
|
1986
|
+
];
|
|
1987
|
+
const timedPlan = historyState(timedMessages).turns.at(-1)?.items.find((item) => item.type === "plan");
|
|
1988
|
+
if (timedPlan?.steps?.[0]?.elapsedMs !== 6000 || timedPlan.steps[0].status !== "completed") {
|
|
1989
|
+
throw new Error(`Claude plan step timing self-test failed: ${JSON.stringify(timedPlan)}`);
|
|
1990
|
+
}
|
|
1940
1991
|
const skippedTasks = new Map([
|
|
1941
1992
|
["1", { id: "1", subject: "1. 조사", status: "pending" }],
|
|
1942
1993
|
["2", { id: "2", subject: "2. 분석", status: "pending" }],
|