devez-vibe 1.10.14 → 1.10.15
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 +65 -22
- package/package.json +1 -1
package/bin/dvz.exe
CHANGED
|
Binary file
|
|
@@ -4910,10 +4910,16 @@ async function dispatch(method, params = {}) {
|
|
|
4910
4910
|
// re-stamps session metadata, so a rename from here survives a live session.
|
|
4911
4911
|
if (method === "session/rename") {
|
|
4912
4912
|
const id = liveSessionId(params.sessionId);
|
|
4913
|
+
const session = sessions.get(id);
|
|
4914
|
+
if (!params.unnamedOnly && session) delete session.inheritedTitle;
|
|
4913
4915
|
const dir = await readableCwd(id, params.cwd);
|
|
4914
|
-
//
|
|
4915
|
-
if (params.unnamedOnly
|
|
4916
|
+
// /clear가 복사한 제목만 교체한다. 그 뒤 직접 지정한 이름은 그대로 둔다.
|
|
4917
|
+
if (params.unnamedOnly) {
|
|
4918
|
+
const title = (await getSessionInfo(id, { dir }))?.customTitle;
|
|
4919
|
+
if (title && title !== session?.inheritedTitle) return {};
|
|
4920
|
+
}
|
|
4916
4921
|
await renameSession(id, String(params.name ?? ""), { dir });
|
|
4922
|
+
if (session) delete session.inheritedTitle;
|
|
4917
4923
|
return {};
|
|
4918
4924
|
}
|
|
4919
4925
|
// dvz titles a new session with one Haiku reply.
|
|
@@ -4968,6 +4974,8 @@ async function dispatch(method, params = {}) {
|
|
|
4968
4974
|
|| session.pendingPrompts?.length || session.queue?.values?.length) {
|
|
4969
4975
|
return { released: false, busy: true };
|
|
4970
4976
|
}
|
|
4977
|
+
const inheritedTitle = getSessionInfo(session.id, { dir: session.cwd })
|
|
4978
|
+
.then((info) => info?.customTitle).catch(() => undefined);
|
|
4971
4979
|
let timer;
|
|
4972
4980
|
const id = await new Promise((resolve) => {
|
|
4973
4981
|
session.clearWaiter = resolve;
|
|
@@ -4980,6 +4988,7 @@ async function dispatch(method, params = {}) {
|
|
|
4980
4988
|
});
|
|
4981
4989
|
});
|
|
4982
4990
|
clearTimeout(timer);
|
|
4991
|
+
if (id) session.inheritedTitle = await inheritedTitle;
|
|
4983
4992
|
session.clearWaiter = null;
|
|
4984
4993
|
session.clearPending = false;
|
|
4985
4994
|
// CLI가 /clear에 답하지 않아도 남은 작업이 없으면 연결을 닫고 새 대화를 연다.
|
|
@@ -5526,29 +5535,63 @@ async function runSelfTest() {
|
|
|
5526
5535
|
await resumedConsumer;
|
|
5527
5536
|
// 백그라운드 작업만 남은 세션은 같은 프로세스에서 새 대화로 넘어가 작업을 이어받는다.
|
|
5528
5537
|
const { session: clearSession } = await createSession({ cwd: process.cwd() });
|
|
5529
|
-
const clearPreviousId = clearSession.id;
|
|
5530
5538
|
const clearConsumer = clearSession.consumer;
|
|
5539
|
+
const titleProjectDir = join(releaseConfigDir, "projects", process.cwd().replace(/[^a-zA-Z0-9]/g, "-"));
|
|
5540
|
+
await mkdir(titleProjectDir, { recursive: true });
|
|
5541
|
+
const titleTranscript = (id, title, prompt) => [
|
|
5542
|
+
{ type: "custom-title", sessionId: id, customTitle: title },
|
|
5543
|
+
{ type: "user", uuid: randomUUID(), parentUuid: null, sessionId: id, cwd: process.cwd(),
|
|
5544
|
+
message: { role: "user", content: prompt } },
|
|
5545
|
+
].map((entry) => JSON.stringify(entry)).join("\n") + "\n";
|
|
5546
|
+
await writeFile(join(titleProjectDir, `${clearSession.id}.jsonl`),
|
|
5547
|
+
titleTranscript(clearSession.id, "앞 대화 제목", "앞 대화 질문"));
|
|
5531
5548
|
clearSession.subagents.set("clear-child", { id: "clear-child", background: true, taskId: "clear-task" });
|
|
5532
|
-
const
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5549
|
+
for (const mode of ["automatic", "manual-same", "external", "automatic-again"]) {
|
|
5550
|
+
const previousId = clearSession.id;
|
|
5551
|
+
const previousPath = join(titleProjectDir, `${previousId}.jsonl`);
|
|
5552
|
+
const previousTranscript = await readFile(previousPath, "utf8");
|
|
5553
|
+
const previousTitle = (await getSessionInfo(previousId, { dir: process.cwd() }))?.customTitle;
|
|
5554
|
+
const nextId = randomUUID();
|
|
5555
|
+
const nextPrompt = `새 질문 ${mode}`;
|
|
5556
|
+
// CLI의 /clear가 새 전사에 이전 customTitle을 복사하는 조건을 재현한다.
|
|
5557
|
+
await writeFile(join(titleProjectDir, `${nextId}.jsonl`), titleTranscript(nextId, previousTitle, nextPrompt));
|
|
5558
|
+
const clearing = dispatch("session/clear", { sessionId: previousId });
|
|
5559
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
5560
|
+
if (clearSession.queue.values.at(-1)?.message?.content !== "/clear") {
|
|
5561
|
+
throw new Error("Claude clear did not send /clear to the live query");
|
|
5562
|
+
}
|
|
5563
|
+
clearSession.queue.values.length = 0;
|
|
5564
|
+
clearSession.query.events.push({ type: "conversation_reset", session_id: previousId, new_conversation_id: randomUUID() });
|
|
5565
|
+
clearSession.query.events.push({ type: "system", subtype: "init", session_id: nextId });
|
|
5566
|
+
const cleared = await clearing;
|
|
5567
|
+
const clearRows = releaseNotices.filter((notice) => notice.method === "turn/subagents/updated");
|
|
5568
|
+
if (cleared.id !== nextId || lookupSession(nextId) !== clearSession
|
|
5569
|
+
|| lookupSession(previousId) || clearSession.query.closeCalls
|
|
5570
|
+
|| !clearRows.some((notice) => notice.params.threadId === nextId
|
|
5571
|
+
&& notice.params.subagents.some((row) => row.id === "clear-child"))) {
|
|
5572
|
+
throw new Error("Claude in-process clear did not move the live work to a new conversation");
|
|
5573
|
+
}
|
|
5574
|
+
const autoTitle = `새 대화 제목 ${mode}`;
|
|
5575
|
+
let expectedTitle = autoTitle;
|
|
5576
|
+
if (mode === "manual-same") {
|
|
5577
|
+
expectedTitle = previousTitle;
|
|
5578
|
+
await dispatch("session/rename", { sessionId: nextId, cwd: process.cwd(), name: expectedTitle });
|
|
5579
|
+
} else if (mode === "external") {
|
|
5580
|
+
expectedTitle = "다른 클라이언트가 지정한 제목";
|
|
5581
|
+
await renameSession(nextId, expectedTitle, { dir: process.cwd() });
|
|
5582
|
+
}
|
|
5583
|
+
await dispatch("session/rename", { sessionId: nextId, cwd: process.cwd(), name: autoTitle, unnamedOnly: true });
|
|
5584
|
+
const listed = await claudeSessionList({ cwd: process.cwd() });
|
|
5585
|
+
const prompt = transcriptPreview(await sessionMessages(nextId, process.cwd()));
|
|
5586
|
+
if (listed.find((row) => row.id === visibleSession(nextId))?.name !== expectedTitle
|
|
5587
|
+
|| prompt !== nextPrompt || await readFile(previousPath, "utf8") !== previousTranscript) {
|
|
5588
|
+
throw new Error(`Claude clear title self-test failed: ${mode}`);
|
|
5589
|
+
}
|
|
5590
|
+
releaseNotices.splice(0, releaseNotices.length,
|
|
5591
|
+
...releaseNotices.filter((notice) => !clearRows.includes(notice)));
|
|
5592
|
+
}
|
|
5550
5593
|
clearSession.subagents.clear();
|
|
5551
|
-
await dispatch("session/release", { sessionId:
|
|
5594
|
+
await dispatch("session/release", { sessionId: clearSession.id });
|
|
5552
5595
|
await clearConsumer;
|
|
5553
5596
|
const { session: mainSession } = await createSession({ cwd: process.cwd() });
|
|
5554
5597
|
const mainQuery = mainSession.query;
|