@i14ks/ccv 0.17.1 → 0.17.3

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 (24) hide show
  1. package/bundle/ccv.mjs +51 -17
  2. package/package.json +1 -1
  3. package/web/assets/{codemirror-D06kWEjk.js → codemirror-lu8HamKP.js} +1 -1
  4. package/web/assets/{index-C6krMHZY.js → index-3sshvreD.js} +1 -1
  5. package/web/assets/{index-EFYV7FAa.js → index-B7ozEwgu.js} +1 -1
  6. package/web/assets/{index-C_EZ7hQo.js → index-BJqZWIPR.js} +1 -1
  7. package/web/assets/{index-DvnBnvuw.js → index-BUWJHuYf.js} +1 -1
  8. package/web/assets/{index-DplX5Cz7.js → index-BfxQTveJ.js} +1 -1
  9. package/web/assets/{index-DXQEFZIh.js → index-BuyfXyo4.js} +1 -1
  10. package/web/assets/{index-Bxh08iJ1.js → index-C13Jucn1.js} +1 -1
  11. package/web/assets/{index-DabHibvO.js → index-C4wYlk_J.js} +30 -30
  12. package/web/assets/{index-CMukK-dM.js → index-Cc7JijiI.js} +1 -1
  13. package/web/assets/{index-BsIb1t2X.js → index-CcKtEXQw.js} +1 -1
  14. package/web/assets/{index-WybCya6f.js → index-CqZsTMCh.js} +1 -1
  15. package/web/assets/{index-BVm3si_0.js → index-D37eFo7a.js} +1 -1
  16. package/web/assets/{index-CRlaTdyd.js → index-D5k_lqHb.js} +1 -1
  17. package/web/assets/{index-CZmkFrXR.js → index-D9R4w6Zg.js} +1 -1
  18. package/web/assets/{index-ChvulMgb.js → index-DIGg_HG2.js} +1 -1
  19. package/web/assets/{index-BXWG3kiF.js → index-DNoT5Ala.js} +1 -1
  20. package/web/assets/{index-CtXCrtwJ.js → index-Dj1v9Gkj.js} +1 -1
  21. package/web/assets/{index-DDOlb0VR.js → index-DmaRIPd6.js} +1 -1
  22. package/web/assets/{index-DNA6pyS8.js → index-Drc8TpEz.js} +1 -1
  23. package/web/assets/{index-DoLh1Z4n.js → index-Dvlp7Iqq.js} +1 -1
  24. package/web/index.html +1 -1
package/bundle/ccv.mjs CHANGED
@@ -158,13 +158,18 @@ function isClientFrame(value) {
158
158
  return typeof value === "object" && value !== null && typeof value.type === "string";
159
159
  }
160
160
  function workspaceIdFromPath(absolutePath) {
161
- const slug = legacyWorkspaceIdFromPath(absolutePath).replace(/^-+|-+$/g, "");
162
- const windows = /^[a-zA-Z]:[\\/]|^\\\\/.test(absolutePath);
163
- const hash = hashText(windows ? absolutePath.toLowerCase() : absolutePath);
164
- return `${slug || "project"}-${hash}`;
161
+ const slug = absolutePath.replace(/[^\p{L}\p{N}\p{M}]/gu, "-").replace(/-+/g, "-").toLowerCase().replace(/^-|-$/g, "");
162
+ return `${slug || "project"}-${pathHash(absolutePath)}`;
163
+ }
164
+ function formerWorkspaceIdsFromPath(absolutePath) {
165
+ const plain = absolutePath.replace(/[^a-zA-Z0-9]/g, "-").replace(/-+/g, "-").toLowerCase();
166
+ const hashed = `${plain.replace(/^-+|-+$/g, "") || "project"}-${pathHash(absolutePath)}`;
167
+ const current = workspaceIdFromPath(absolutePath);
168
+ return [plain, hashed].filter((id) => id !== current);
165
169
  }
166
- function legacyWorkspaceIdFromPath(absolutePath) {
167
- return absolutePath.replace(/[^a-zA-Z0-9]/g, "-").replace(/-+/g, "-").toLowerCase();
170
+ function pathHash(absolutePath) {
171
+ const windows = /^[a-zA-Z]:[\\/]|^\\\\/.test(absolutePath);
172
+ return hashText(windows ? absolutePath.toLowerCase() : absolutePath);
168
173
  }
169
174
  function hashText(text) {
170
175
  let h1 = 3735928559;
@@ -184,11 +189,12 @@ function workspaceIdRemap(paths, sessionsOf) {
184
189
  const byLegacy = /* @__PURE__ */ new Map();
185
190
  for (const path25 of paths) {
186
191
  const id = workspaceIdFromPath(path25);
187
- const legacy = legacyWorkspaceIdFromPath(path25);
188
- const group = byLegacy.get(legacy) ?? [];
189
- if (!group.some((target) => target.id === id))
190
- group.push({ id, path: path25 });
191
- byLegacy.set(legacy, group);
192
+ for (const legacy of formerWorkspaceIdsFromPath(path25)) {
193
+ const group = byLegacy.get(legacy) ?? [];
194
+ if (!group.some((target) => target.id === id))
195
+ group.push({ id, path: path25 });
196
+ byLegacy.set(legacy, group);
197
+ }
192
198
  }
193
199
  const owners = /* @__PURE__ */ new Map();
194
200
  return {
@@ -1228,9 +1234,10 @@ var ClaudeSession = class extends EventEmitter {
1228
1234
  * готово. Список нужен ровно для того, чтобы список сессий не называл
1229
1235
  * сессию «готова», пока где-то ещё крутится агент.
1230
1236
  *
1231
- * Очищается не отдельным событием (у уведомления нет надёжной привязки к
1232
- * конкретному toolUseId), а любым переходом обратно в `running` —
1233
- * `#setState` делает это сам, см. там же.
1237
+ * Запуск уходит из набора по `task_notification` с его toolUseId, по
1238
+ * ошибке в результате вызова (задача так и не стартовала) и — на случай,
1239
+ * если уведомление пришло без привязки, — любым переходом обратно в
1240
+ * `running`: `#setState` делает это сам, см. там же.
1234
1241
  */
1235
1242
  #backgroundWork = /* @__PURE__ */ new Set();
1236
1243
  /**
@@ -2570,7 +2577,7 @@ var ClaudeSession = class extends EventEmitter {
2570
2577
  const patch = message.patch ?? {};
2571
2578
  const status = patch.status;
2572
2579
  if (status === "completed" || status === "failed" || status === "killed") {
2573
- this.#tasks.delete(task.id);
2580
+ this.#finishTask(task.id, task.toolUseId);
2574
2581
  } else {
2575
2582
  if (typeof patch.is_backgrounded === "boolean")
2576
2583
  task.background = patch.is_backgrounded;
@@ -2580,11 +2587,15 @@ var ClaudeSession = class extends EventEmitter {
2580
2587
  this.emit("summary", this.summary());
2581
2588
  return true;
2582
2589
  }
2583
- case "task_notification":
2590
+ case "task_notification": {
2584
2591
  this.#lastActiveAt = Date.now();
2585
- if (taskId && this.#tasks.delete(taskId))
2592
+ if (!taskId)
2593
+ return false;
2594
+ const toolUseId = str(message.tool_use_id) ?? this.#tasks.get(taskId)?.toolUseId ?? null;
2595
+ if (this.#finishTask(taskId, toolUseId))
2586
2596
  this.emit("summary", this.summary());
2587
2597
  return false;
2598
+ }
2588
2599
  case "background_tasks_changed": {
2589
2600
  this.#lastActiveAt = Date.now();
2590
2601
  const live = Array.isArray(message.tasks) ? message.tasks.flatMap((t) => typeof t.task_id === "string" ? [t.task_id] : []) : [];
@@ -2602,6 +2613,23 @@ var ClaudeSession = class extends EventEmitter {
2602
2613
  return false;
2603
2614
  }
2604
2615
  }
2616
+ /**
2617
+ * Задача кончилась — убрать её отовсюду, где она числится живой. `true` —
2618
+ * что-то изменилось и сводку пора разослать.
2619
+ *
2620
+ * Уровень и набор запусков чистим здесь же, не дожидаясь их собственных
2621
+ * сигналов: следующий `background_tasks_changed` может не прийти вовсе, а
2622
+ * набор запусков иначе чистит только новый ход — и сессия, чья фоновая
2623
+ * команда тихо доработала, висела бы «в фоне» до следующего промпта.
2624
+ */
2625
+ #finishTask(taskId, toolUseId) {
2626
+ let changed = this.#tasks.delete(taskId);
2627
+ if (this.#backgroundLevel?.delete(taskId))
2628
+ changed = true;
2629
+ if (toolUseId !== null && this.#backgroundWork.delete(toolUseId))
2630
+ changed = true;
2631
+ return changed;
2632
+ }
2605
2633
  /** Сводка по прогрессу задач — не чаще раза в секунду. */
2606
2634
  #emitTasksSoon() {
2607
2635
  if (this.#taskSummaryTimer)
@@ -2680,6 +2708,7 @@ var ClaudeSession = class extends EventEmitter {
2680
2708
  const content = message.message.content;
2681
2709
  if (typeof content === "string")
2682
2710
  return;
2711
+ let backgroundChanged = false;
2683
2712
  for (const block of content) {
2684
2713
  if (block.type !== "tool_result")
2685
2714
  continue;
@@ -2689,7 +2718,12 @@ var ClaudeSession = class extends EventEmitter {
2689
2718
  content: contentToText2(block.content),
2690
2719
  isError: block.is_error === true
2691
2720
  });
2721
+ if (block.is_error === true && this.#backgroundWork.delete(block.tool_use_id)) {
2722
+ backgroundChanged = true;
2723
+ }
2692
2724
  }
2725
+ if (backgroundChanged)
2726
+ this.emit("summary", this.summary());
2693
2727
  }
2694
2728
  /** Индекс очередного блока сообщения — в той же нумерации, что у дельт. */
2695
2729
  #nextBlockIndex(messageId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@i14ks/ccv",
3
- "version": "0.17.1",
3
+ "version": "0.17.3",
4
4
  "license": "UNLICENSED",
5
5
  "description": "GUI для Claude Code: сессии агента в каталогах проектов, дерево файлов и редактор рядом с разговором.",
6
6
  "homepage": "https://claudevisual.com",
@@ -1 +1 @@
1
- import{s as r,H as a}from"./index-CMukK-dM.js";import{E as e}from"./index-891wE-Rj.js";import{t as o}from"./index-DabHibvO.js";import"./index-BHot-lnj.js";const m=e.theme({"&":{height:"100%",color:"var(--text)",backgroundColor:"var(--bg)",fontSize:"13px"},".cm-scroller":{fontFamily:"var(--mono)",lineHeight:"1.6"},".cm-content":{caretColor:"var(--accent)"},".cm-cursor, .cm-dropCursor":{borderLeftColor:"var(--accent)"},"&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection":{backgroundColor:"var(--cm-selection)"},".cm-gutters":{backgroundColor:"var(--bg)",color:"var(--muted)",borderRight:"1px solid var(--border-soft)"},".cm-activeLineGutter":{backgroundColor:"var(--surface-2)",color:"var(--text-2)"},".cm-activeLine":{backgroundColor:"var(--cm-active)"},".cm-selectionMatch":{backgroundColor:"var(--cm-match)"},"&.cm-focused .cm-matchingBracket":{backgroundColor:"var(--cm-match)",outline:"1px solid var(--accent-line)"},".cm-foldPlaceholder":{backgroundColor:"var(--surface-2)",border:"1px solid var(--border)",color:"var(--muted)"},".cm-panels":{backgroundColor:"var(--surface)",color:"var(--text)",border:"1px solid var(--border)"},".cm-panels input, .cm-panels button, .cm-panels select":{fontFamily:"var(--sans)",fontSize:"12px",background:"var(--surface-2)",color:"var(--text)",border:"1px solid var(--border)",borderRadius:"6px",padding:"3px 6px"},".cm-searchMatch":{backgroundColor:"var(--cm-match)"},".cm-searchMatch.cm-searchMatch-selected":{backgroundColor:"var(--accent-soft)"},".cm-tooltip":{background:"var(--surface)",border:"1px solid var(--border)",borderRadius:"8px",boxShadow:"var(--shadow-md)",color:"var(--text)"},".cm-tooltip-autocomplete ul li[aria-selected]":{background:"var(--surface-2)",color:"var(--text)"}}),i=r(a.define([{tag:[o.keyword,o.modifier,o.controlKeyword,o.moduleKeyword],color:"var(--cm-key)"},{tag:[o.name,o.deleted,o.character,o.macroName],color:"var(--text)"},{tag:[o.propertyName],color:"var(--cm-prop)"},{tag:[o.function(o.variableName),o.labelName],color:"var(--cm-fn)"},{tag:[o.color,o.constant(o.name),o.standard(o.name),o.bool],color:"var(--cm-const)"},{tag:[o.definition(o.name),o.separator],color:"var(--text)"},{tag:[o.typeName,o.className,o.changed,o.annotation,o.self,o.namespace],color:"var(--cm-type)"},{tag:[o.number,o.integer,o.float],color:"var(--cm-num)"},{tag:[o.string,o.special(o.string),o.regexp],color:"var(--cm-str)"},{tag:[o.operator,o.operatorKeyword,o.escape],color:"var(--cm-op)"},{tag:[o.meta,o.comment],color:"var(--cm-comment)",fontStyle:"italic"},{tag:o.strong,fontWeight:"650"},{tag:o.emphasis,fontStyle:"italic"},{tag:o.strikethrough,textDecoration:"line-through"},{tag:o.link,color:"var(--cm-str)",textDecoration:"underline"},{tag:o.heading,fontWeight:"650",color:"var(--cm-key)"},{tag:o.invalid,color:"var(--danger)"}]));export{i as editorHighlight,m as editorTheme};
1
+ import{s as r,H as a}from"./index-Cc7JijiI.js";import{E as e}from"./index-891wE-Rj.js";import{t as o}from"./index-C4wYlk_J.js";import"./index-BHot-lnj.js";const m=e.theme({"&":{height:"100%",color:"var(--text)",backgroundColor:"var(--bg)",fontSize:"13px"},".cm-scroller":{fontFamily:"var(--mono)",lineHeight:"1.6"},".cm-content":{caretColor:"var(--accent)"},".cm-cursor, .cm-dropCursor":{borderLeftColor:"var(--accent)"},"&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection":{backgroundColor:"var(--cm-selection)"},".cm-gutters":{backgroundColor:"var(--bg)",color:"var(--muted)",borderRight:"1px solid var(--border-soft)"},".cm-activeLineGutter":{backgroundColor:"var(--surface-2)",color:"var(--text-2)"},".cm-activeLine":{backgroundColor:"var(--cm-active)"},".cm-selectionMatch":{backgroundColor:"var(--cm-match)"},"&.cm-focused .cm-matchingBracket":{backgroundColor:"var(--cm-match)",outline:"1px solid var(--accent-line)"},".cm-foldPlaceholder":{backgroundColor:"var(--surface-2)",border:"1px solid var(--border)",color:"var(--muted)"},".cm-panels":{backgroundColor:"var(--surface)",color:"var(--text)",border:"1px solid var(--border)"},".cm-panels input, .cm-panels button, .cm-panels select":{fontFamily:"var(--sans)",fontSize:"12px",background:"var(--surface-2)",color:"var(--text)",border:"1px solid var(--border)",borderRadius:"6px",padding:"3px 6px"},".cm-searchMatch":{backgroundColor:"var(--cm-match)"},".cm-searchMatch.cm-searchMatch-selected":{backgroundColor:"var(--accent-soft)"},".cm-tooltip":{background:"var(--surface)",border:"1px solid var(--border)",borderRadius:"8px",boxShadow:"var(--shadow-md)",color:"var(--text)"},".cm-tooltip-autocomplete ul li[aria-selected]":{background:"var(--surface-2)",color:"var(--text)"}}),i=r(a.define([{tag:[o.keyword,o.modifier,o.controlKeyword,o.moduleKeyword],color:"var(--cm-key)"},{tag:[o.name,o.deleted,o.character,o.macroName],color:"var(--text)"},{tag:[o.propertyName],color:"var(--cm-prop)"},{tag:[o.function(o.variableName),o.labelName],color:"var(--cm-fn)"},{tag:[o.color,o.constant(o.name),o.standard(o.name),o.bool],color:"var(--cm-const)"},{tag:[o.definition(o.name),o.separator],color:"var(--text)"},{tag:[o.typeName,o.className,o.changed,o.annotation,o.self,o.namespace],color:"var(--cm-type)"},{tag:[o.number,o.integer,o.float],color:"var(--cm-num)"},{tag:[o.string,o.special(o.string),o.regexp],color:"var(--cm-str)"},{tag:[o.operator,o.operatorKeyword,o.escape],color:"var(--cm-op)"},{tag:[o.meta,o.comment],color:"var(--cm-comment)",fontStyle:"italic"},{tag:o.strong,fontWeight:"650"},{tag:o.emphasis,fontStyle:"italic"},{tag:o.strikethrough,textDecoration:"line-through"},{tag:o.link,color:"var(--cm-str)",textDecoration:"underline"},{tag:o.heading,fontWeight:"650",color:"var(--cm-key)"},{tag:o.invalid,color:"var(--danger)"}]));export{i as editorHighlight,m as editorTheme};