@i14ks/ccv 0.11.0 → 0.12.1

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 (27) hide show
  1. package/bundle/ccv.mjs +69 -5
  2. package/package.json +1 -1
  3. package/web/assets/{codemirror-BVMwXG_R.js → codemirror-D11GWMsB.js} +1 -1
  4. package/web/assets/{index-CrW8SGCA.js → index-09MC_4AF.js} +1 -1
  5. package/web/assets/{index-DLDXVZaf.js → index-4S0cl_O2.js} +1 -1
  6. package/web/assets/index-9Toz507b.js +132 -0
  7. package/web/assets/{index-BlZDoET-.js → index-BDuAzkOQ.js} +1 -1
  8. package/web/assets/{index-gl1MvN4b.js → index-BIhkivIg.js} +1 -1
  9. package/web/assets/{index-BZ8Mi5_8.js → index-BSEf83Uc.js} +1 -1
  10. package/web/assets/{index-DJYXqBtm.js → index-Bg0VD211.js} +1 -1
  11. package/web/assets/{index-BCAmULlL.js → index-Bw0U50QY.js} +1 -1
  12. package/web/assets/{index-BsH-IJBy.js → index-CZF-u-hv.js} +1 -1
  13. package/web/assets/{index-C-geC5VJ.js → index-CmCj0IE6.js} +1 -1
  14. package/web/assets/{index-BFLfK-j6.js → index-Czu0PbLS.js} +1 -1
  15. package/web/assets/{index-DAjl7nVl.js → index-D57ZXpBD.js} +1 -1
  16. package/web/assets/index-D5y0Nk74.css +1 -0
  17. package/web/assets/{index-C59fVtiO.js → index-DABElhgt.js} +1 -1
  18. package/web/assets/{index-C1BT9XMC.js → index-DO1FY4r1.js} +1 -1
  19. package/web/assets/{index-AByrn5FE.js → index-DdCJlB8h.js} +1 -1
  20. package/web/assets/{index-Bu_Ukh1_.js → index-Dn5EQ5YI.js} +1 -1
  21. package/web/assets/{index-CPWAVXhz.js → index-Iwl1w0_V.js} +1 -1
  22. package/web/assets/{index-mnefozuu.js → index-J2jvoYvL.js} +1 -1
  23. package/web/assets/{index-Ey94wZ1k.js → index-ZstREAcb.js} +1 -1
  24. package/web/assets/{index-DKofSKA7.js → index-xSo7_4Td.js} +1 -1
  25. package/web/index.html +2 -2
  26. package/web/assets/index-DRlKZHMW.js +0 -132
  27. package/web/assets/index-c0zvhlqR.css +0 -1
package/bundle/ccv.mjs CHANGED
@@ -3973,8 +3973,10 @@ import { randomUUID as randomUUID2 } from "node:crypto";
3973
3973
  var Folders = class {
3974
3974
  #workspaceFolders = /* @__PURE__ */ new Map();
3975
3975
  #sessionFolders = /* @__PURE__ */ new Map();
3976
+ #pinnedFolders = /* @__PURE__ */ new Map();
3976
3977
  #workspaceAssignments = /* @__PURE__ */ new Map();
3977
3978
  #sessionAssignments = /* @__PURE__ */ new Map();
3979
+ #pinnedAssignments = /* @__PURE__ */ new Map();
3978
3980
  #storePath;
3979
3981
  constructor(dataDir) {
3980
3982
  this.#storePath = path12.join(dataDir, "folders.json");
@@ -3985,13 +3987,17 @@ var Folders = class {
3985
3987
  const parsed = JSON.parse(raw);
3986
3988
  this.#workspaceFolders = new Map(Object.entries(parsed.workspaceFolders ?? {}).filter(([, r]) => isWorkspaceFolder(r)));
3987
3989
  this.#sessionFolders = new Map(Object.entries(parsed.sessionFolders ?? {}).filter(([, r]) => isSessionFolder(r)));
3990
+ this.#pinnedFolders = new Map(Object.entries(parsed.pinnedFolders ?? {}).filter(([, r]) => isPinnedFolder(r)));
3988
3991
  this.#workspaceAssignments = new Map(Object.entries(parsed.workspaceAssignments ?? {}).filter((entry) => typeof entry[1] === "string"));
3989
3992
  this.#sessionAssignments = new Map(Object.entries(parsed.sessionAssignments ?? {}).filter((entry) => typeof entry[1] === "string"));
3993
+ this.#pinnedAssignments = new Map(Object.entries(parsed.pinnedAssignments ?? {}).filter((entry) => typeof entry[1] === "string"));
3990
3994
  } catch {
3991
3995
  this.#workspaceFolders = /* @__PURE__ */ new Map();
3992
3996
  this.#sessionFolders = /* @__PURE__ */ new Map();
3997
+ this.#pinnedFolders = /* @__PURE__ */ new Map();
3993
3998
  this.#workspaceAssignments = /* @__PURE__ */ new Map();
3994
3999
  this.#sessionAssignments = /* @__PURE__ */ new Map();
4000
+ this.#pinnedAssignments = /* @__PURE__ */ new Map();
3995
4001
  }
3996
4002
  }
3997
4003
  /** Все папки — для кадра `folder.list`. */
@@ -4002,7 +4008,8 @@ var Folders = class {
4002
4008
  id,
4003
4009
  name: r.name,
4004
4010
  workspaceId: r.workspaceId
4005
- }))
4011
+ })),
4012
+ pinnedFolders: [...this.#pinnedFolders].map(([id, r]) => ({ id, name: r.name }))
4006
4013
  };
4007
4014
  }
4008
4015
  async createWorkspaceFolder(name) {
@@ -4017,6 +4024,12 @@ var Folders = class {
4017
4024
  await this.#persist();
4018
4025
  return id;
4019
4026
  }
4027
+ async createPinnedFolder(name) {
4028
+ const id = randomUUID2();
4029
+ this.#pinnedFolders.set(id, { name });
4030
+ await this.#persist();
4031
+ return id;
4032
+ }
4020
4033
  /** Переименовать папку любого вида — id уникален между обоими видами. */
4021
4034
  async rename(folderId, name) {
4022
4035
  const ws = this.#workspaceFolders.get(folderId);
@@ -4031,6 +4044,12 @@ var Folders = class {
4031
4044
  await this.#persist();
4032
4045
  return true;
4033
4046
  }
4047
+ const pinned = this.#pinnedFolders.get(folderId);
4048
+ if (pinned) {
4049
+ this.#pinnedFolders.set(folderId, { ...pinned, name });
4050
+ await this.#persist();
4051
+ return true;
4052
+ }
4034
4053
  return false;
4035
4054
  }
4036
4055
  /**
@@ -4049,6 +4068,8 @@ var Folders = class {
4049
4068
  const sess = this.#sessionFolders.get(folderId);
4050
4069
  if (sess && this.#sessionFolders.delete(folderId)) {
4051
4070
  removed = { scope: "session", workspaceId: sess.workspaceId };
4071
+ } else if (this.#pinnedFolders.delete(folderId)) {
4072
+ removed = { scope: "pinned" };
4052
4073
  }
4053
4074
  }
4054
4075
  if (!removed)
@@ -4061,6 +4082,10 @@ var Folders = class {
4061
4082
  if (assigned === folderId)
4062
4083
  this.#sessionAssignments.delete(id);
4063
4084
  }
4085
+ for (const [id, assigned] of this.#pinnedAssignments) {
4086
+ if (assigned === folderId)
4087
+ this.#pinnedAssignments.delete(id);
4088
+ }
4064
4089
  await this.#persist();
4065
4090
  return removed;
4066
4091
  }
@@ -4103,18 +4128,43 @@ var Folders = class {
4103
4128
  await this.#persist();
4104
4129
  return true;
4105
4130
  }
4131
+ /**
4132
+ * Разложить закреплённую сессию по папке закреплённых или вынуть из неё.
4133
+ *
4134
+ * Без проверки проекта — в отличие от `assignSession`, папка закреплённых
4135
+ * общая на все проекты сразу, и сессия любого из них может в неё попасть.
4136
+ */
4137
+ async assignPinnedSession(sessionId, folderId) {
4138
+ if (folderId === null) {
4139
+ if (!this.#pinnedAssignments.delete(sessionId))
4140
+ return false;
4141
+ await this.#persist();
4142
+ return true;
4143
+ }
4144
+ if (!this.#pinnedFolders.has(folderId)) {
4145
+ throw new Error(`\u041F\u0430\u043F\u043A\u0430 \u0437\u0430\u043A\u0440\u0435\u043F\u043B\u0451\u043D\u043D\u044B\u0445 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u0430: ${folderId}`);
4146
+ }
4147
+ this.#pinnedAssignments.set(sessionId, folderId);
4148
+ await this.#persist();
4149
+ return true;
4150
+ }
4106
4151
  folderIdForWorkspace(workspaceId) {
4107
4152
  return this.#workspaceAssignments.get(workspaceId);
4108
4153
  }
4109
4154
  folderIdForSession(sessionId) {
4110
4155
  return this.#sessionAssignments.get(sessionId);
4111
4156
  }
4157
+ folderIdForPinnedSession(sessionId) {
4158
+ return this.#pinnedAssignments.get(sessionId);
4159
+ }
4112
4160
  async #persist() {
4113
4161
  const file = {
4114
4162
  workspaceFolders: Object.fromEntries(this.#workspaceFolders),
4115
4163
  sessionFolders: Object.fromEntries(this.#sessionFolders),
4164
+ pinnedFolders: Object.fromEntries(this.#pinnedFolders),
4116
4165
  workspaceAssignments: Object.fromEntries(this.#workspaceAssignments),
4117
- sessionAssignments: Object.fromEntries(this.#sessionAssignments)
4166
+ sessionAssignments: Object.fromEntries(this.#sessionAssignments),
4167
+ pinnedAssignments: Object.fromEntries(this.#pinnedAssignments)
4118
4168
  };
4119
4169
  await mkdir6(path12.dirname(this.#storePath), { recursive: true });
4120
4170
  await writeFile7(this.#storePath, JSON.stringify(file, null, 2), "utf8");
@@ -4126,6 +4176,9 @@ function isWorkspaceFolder(value) {
4126
4176
  function isSessionFolder(value) {
4127
4177
  return typeof value === "object" && value !== null && typeof value.name === "string" && typeof value.workspaceId === "string";
4128
4178
  }
4179
+ function isPinnedFolder(value) {
4180
+ return typeof value === "object" && value !== null && typeof value.name === "string";
4181
+ }
4129
4182
 
4130
4183
  // ../host/dist/app-settings.js
4131
4184
  import { mkdir as mkdir7, readFile as readFile10, writeFile as writeFile8 } from "node:fs/promises";
@@ -5668,6 +5721,8 @@ var HostServer = class {
5668
5721
  if (!frame.workspaceId)
5669
5722
  throw new Error("\u0414\u043B\u044F \u043F\u0430\u043F\u043A\u0438 \u0441\u0435\u0441\u0441\u0438\u0439 \u043D\u0443\u0436\u0435\u043D workspaceId");
5670
5723
  await this.#folders.createSessionFolder(frame.workspaceId, frame.name);
5724
+ } else if (frame.scope === "pinned") {
5725
+ await this.#folders.createPinnedFolder(frame.name);
5671
5726
  } else {
5672
5727
  await this.#folders.createWorkspaceFolder(frame.name);
5673
5728
  }
@@ -5685,14 +5740,21 @@ var HostServer = class {
5685
5740
  this.#sendFolders();
5686
5741
  if (removed.scope === "workspace")
5687
5742
  this.#broadcastWorkspaces();
5688
- else
5743
+ else if (removed.scope === "session")
5689
5744
  await this.#sendSessionList(removed.workspaceId);
5745
+ else
5746
+ await this.#sendPinned();
5690
5747
  return;
5691
5748
  }
5692
5749
  case "folder.assign": {
5693
- if (frame.workspaceId) {
5750
+ if (frame.scope === "session") {
5751
+ if (!frame.workspaceId)
5752
+ throw new Error("\u0414\u043B\u044F \u043F\u0430\u043F\u043A\u0438 \u0441\u0435\u0441\u0441\u0438\u0439 \u043D\u0443\u0436\u0435\u043D workspaceId");
5694
5753
  await this.#folders.assignSession(frame.itemId, frame.workspaceId, frame.folderId);
5695
5754
  await this.#sendSessionList(frame.workspaceId);
5755
+ } else if (frame.scope === "pinned") {
5756
+ await this.#folders.assignPinnedSession(frame.itemId, frame.folderId);
5757
+ await this.#sendPinned();
5696
5758
  } else {
5697
5759
  await this.#folders.assignWorkspace(frame.itemId, frame.folderId);
5698
5760
  this.#broadcastWorkspaces();
@@ -6766,10 +6828,12 @@ var HostServer = class {
6766
6828
  for (const base of [...live, ...historical].sort((a, b) => b.updatedAt - a.updatedAt)) {
6767
6829
  const pin = this.#pins.find(base.claudeSessionId ?? base.id);
6768
6830
  const folderId = this.#folders.folderIdForSession(base.claudeSessionId ?? base.id);
6831
+ const pinnedFolderId = this.#folders.folderIdForPinnedSession(base.claudeSessionId ?? base.id);
6769
6832
  const summary = {
6770
6833
  ...base,
6771
6834
  ...pin ? { pinned: true, pinnedAt: pin.at } : {},
6772
- ...folderId ? { folderId } : {}
6835
+ ...folderId ? { folderId } : {},
6836
+ ...pinnedFolderId ? { pinnedFolderId } : {}
6773
6837
  };
6774
6838
  const record = this.#archive.find(summary.claudeSessionId ?? summary.id);
6775
6839
  if (!record) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@i14ks/ccv",
3
- "version": "0.11.0",
3
+ "version": "0.12.1",
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-DKofSKA7.js";import{E as e}from"./index-891wE-Rj.js";import{t as o}from"./index-DRlKZHMW.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-xSo7_4Td.js";import{E as e}from"./index-891wE-Rj.js";import{t as o}from"./index-9Toz507b.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};