claude-code-session-manager 0.115.0 → 0.116.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 (51) hide show
  1. package/dist/assets/{AgentLibrary-CjsZLl5e.js → AgentLibrary-CkS69HnN.js} +1 -1
  2. package/dist/assets/{Button-mj0vvcdc.js → Button-BQxkfIbW.js} +1 -1
  3. package/dist/assets/{DataModel-CG6ycpfG.js → DataModel-YVgdJTZF.js} +1 -1
  4. package/dist/assets/{History-DDqLQiAN.js → History-DneHh4jI.js} +2 -2
  5. package/dist/assets/{Hooks-dRje24Nk.js → Hooks-Bt4xIjfo.js} +3 -3
  6. package/dist/assets/{Library-Dl71nylN.js → Library-DoP5FdXq.js} +7 -7
  7. package/dist/assets/{ListDetail-DcAD_cuA.js → ListDetail-BYxyl13e.js} +1 -1
  8. package/dist/assets/{McpServers-BbvbhemH.js → McpServers-CKm_iZsf.js} +1 -1
  9. package/dist/assets/Memory-BWMQuAoC.js +18 -0
  10. package/dist/assets/{Panel-BkfK-W74.js → Panel-Cv8aYElQ.js} +1 -1
  11. package/dist/assets/{Permissions-BnjsXblr.js → Permissions-CFmWwqyV.js} +3 -3
  12. package/dist/assets/Plugins-CuYNgf_d.js +2 -0
  13. package/dist/assets/{ProvenanceBadge-CQXSiPHq.js → ProvenanceBadge-BMLVPyHr.js} +1 -1
  14. package/dist/assets/{RemoteMachines-li6EBPAt.js → RemoteMachines-D04Mby_W.js} +1 -1
  15. package/dist/assets/{SaveBar-0aiuy1L2.js → SaveBar-Cb4Q8TBK.js} +1 -1
  16. package/dist/assets/{Scheduler-Ul4jiK7q.js → Scheduler-ysJHQvW4.js} +1 -1
  17. package/dist/assets/{ScopeSwitcher-DR262W_R.js → ScopeSwitcher-BTOWfifI.js} +1 -1
  18. package/dist/assets/{Settings-BwUcGuar.js → Settings-C6fH8diZ.js} +4 -4
  19. package/dist/assets/{SkillReferenceGraph-fv2FJUNK.js → SkillReferenceGraph-esAcniTQ.js} +1 -1
  20. package/dist/assets/Skills-4_vqzrSF.js +2 -0
  21. package/dist/assets/SystemPrompt-CdUq4KXx.js +1 -0
  22. package/dist/assets/TagLibrary-CVFIphBv.js +1 -0
  23. package/dist/assets/{TiptapBody-CBxxEulT.js → TiptapBody-EkZlmD9k.js} +1 -1
  24. package/dist/assets/{Toggle-W944m375.js → Toggle-CpR97XGM.js} +1 -1
  25. package/dist/assets/{ViewTabs-BLQrBE2n.js → ViewTabs-ekJfFek8.js} +1 -1
  26. package/dist/assets/{historyTotals-BUeyjlNY.js → historyTotals-Bg0GVcsF.js} +1 -1
  27. package/dist/assets/{index-HpEbvDiE.css → index-CZsDDyLy.css} +1 -1
  28. package/dist/assets/{index-t37UuEZu.js → index-DQSEUdx0.js} +54 -54
  29. package/dist/assets/{settingsSchema-HwiOXtC7.js → settingsSchema-BG5jZbhn.js} +1 -1
  30. package/dist/assets/skillFrontmatter-DF6xI6Wb.js +10 -0
  31. package/dist/assets/{useAgentsDirWatch-D0rI9G_h.js → useAgentsDirWatch-Dox-xCx9.js} +1 -1
  32. package/dist/assets/{useRemotePeers-BipAySOB.js → useRemotePeers-DHo62LbA.js} +1 -1
  33. package/dist/index.html +2 -2
  34. package/package.json +2 -1
  35. package/scripts/README.md +2 -0
  36. package/src/main/build-info.json +4 -4
  37. package/src/main/ipcSchemas.cjs +26 -0
  38. package/src/main/lib/memoryOps.cjs +116 -0
  39. package/src/main/lib/memoryStale.cjs +24 -1
  40. package/src/main/memoryAssist.cjs +156 -0
  41. package/src/main/memoryTool.cjs +34 -0
  42. package/src/main/webRemote.cjs +52 -23
  43. package/src/preload/api.d.ts +21 -1
  44. package/src/preload/index.cjs +7 -0
  45. package/dist/assets/MarkdownEditor-D7JTNOOp.js +0 -1
  46. package/dist/assets/Memory-dyz8ZU1e.js +0 -8
  47. package/dist/assets/Plugins-DSyTJtTp.js +0 -2
  48. package/dist/assets/Skills-BA2I-iRE.js +0 -2
  49. package/dist/assets/SystemPrompt-BgvyrAKx.js +0 -1
  50. package/dist/assets/TagLibrary-B5rKEDVT.js +0 -1
  51. package/dist/assets/skillFrontmatter-Dif5JIg7.js +0 -10
@@ -216,10 +216,15 @@ async function getDeviceTicket(deviceToken) {
216
216
  return result.ticket;
217
217
  }
218
218
 
219
+ // Per-client-key time of the last e2e:rekey sent, so a burst of stale boxes yields one rekey.
220
+ const REKEY_THROTTLE_MS = 5000;
221
+ const _lastRekeyMs = new Map();
222
+
219
223
  // ─── E2E state helpers ────────────────────────────────────────────────────────
220
224
 
221
225
  // Tear down every client session (connection-level reset).
222
226
  function resetE2e() {
227
+ _lastRekeyMs.clear();
223
228
  teardownAllClients();
224
229
  }
225
230
 
@@ -371,9 +376,9 @@ async function connect() {
371
376
  if (!cfg.remoteEnabled) return;
372
377
 
373
378
  const devices = cfg.devices || [];
374
- // Use the most recently paired credential. The relay's device-token store is
375
- // in-memory and wiped on every relay redeploy, so an older credential can hold a
376
- // dead token that 401s forever; picking the newest lets a fresh re-pair recover.
379
+ // Use the most recently paired credential. The relay persists device tokens in its
380
+ // DB, but a revoked or superseded credential can still 401 forever; picking the
381
+ // newest lets a fresh re-pair recover.
377
382
  const device = devices
378
383
  .filter((d) => d.deviceToken)
379
384
  .sort((a, b) => String(b.issuedAt || '').localeCompare(String(a.issuedAt || '')))[0];
@@ -426,6 +431,7 @@ async function connect() {
426
431
  _missedPongs = 0;
427
432
  startHeartbeat();
428
433
  // Update lastConnectedAt without exposing token
434
+ invalidateConfigCache(); // a pin written since the last cached read must not be overwritten
429
435
  loadConfig().then(async (c) => {
430
436
  const devs = (c.devices || []).map((d) =>
431
437
  d.deviceId === device.deviceId
@@ -529,6 +535,7 @@ function pruneSessionWatchers() {
529
535
 
530
536
  /** Tear down one client (its PTY streams + subscriptions) without touching others. */
531
537
  function teardownClient(key) {
538
+ _lastRekeyMs.delete(key);
532
539
  const rec = _clients.teardown(key);
533
540
  pruneSessionWatchers();
534
541
  return rec;
@@ -895,7 +902,10 @@ async function handleMessage(raw, device) {
895
902
  // manually SAS-confirmed once, skip pending_sas and auto-authenticate — the
896
903
  // user already verified this browser. A different/first-seen pubKey always
897
904
  // falls through to the manual pending_sas flow below, unchanged.
898
- if (isPinnedPeerKey(device, browserPubKey)) {
905
+ // Read pins from the CURRENT config: `device` is the connect-time snapshot and
906
+ // never sees pins that webRemote:confirm-sas wrote afterwards.
907
+ const live = ((await loadConfig()).devices || []).find((d) => d.deviceId === device.deviceId) || device;
908
+ if (isPinnedPeerKey(live, browserPubKey)) {
899
909
  client.e2e = makeState('authenticated', sessionKey, null);
900
910
  finalizeE2eAuthenticated('E2E session auto-authenticated — pinned browser key matched', client);
901
911
  respond(id, undefined, 'e2e:ready', client);
@@ -918,6 +928,11 @@ async function handleMessage(raw, device) {
918
928
  if (type === 'e2e:box') {
919
929
  if (!client.e2e.sessionKey) {
920
930
  logs.writeLine({ scope: 'webRemote', level: 'warn', message: 'e2e:box received but no session key — dropping' });
931
+ const now = Date.now();
932
+ if (now - (_lastRekeyMs.get(client.key) || 0) >= REKEY_THROTTLE_MS) {
933
+ _lastRekeyMs.set(client.key, now);
934
+ respond(id, { reason: 'no_session' }, 'e2e:rekey', client);
935
+ }
921
936
  return;
922
937
  }
923
938
  const { nonce, ciphertext } = payload || {};
@@ -1278,11 +1293,20 @@ async function dispatchCommand(type, payload, client) {
1278
1293
  // ─── Pairing ─────────────────────────────────────────────────────────────────
1279
1294
 
1280
1295
  async function pair(otp) {
1281
- const deviceId = crypto.randomUUID();
1296
+ const cfg = await loadConfig();
1297
+ // Re-pairing an existing machine keeps its identity (deviceId, E2E keypair, pinned
1298
+ // phone keys) so the relay row is replaced in place and no new SAS is needed.
1299
+ // Explicit revocation empties cfg.devices, which forces a fresh identity.
1300
+ const prev = (cfg.devices || [])
1301
+ .filter((d) => d.deviceId && d.e2ePrivateKey && d.e2ePublicKey)
1302
+ .sort((a, b) => String(b.issuedAt || '').localeCompare(String(a.issuedAt || '')))[0];
1282
1303
 
1283
- // Generate E2E keypair at pair time — public key is sent to relay and stored
1284
- // alongside the device token so the browser can do key agreement.
1285
- const { e2ePrivateKey, e2ePublicKey } = generateE2EKeyPair();
1304
+ const deviceId = prev ? prev.deviceId : crypto.randomUUID();
1305
+ // E2E public key is sent to relay and stored alongside the device token so the
1306
+ // browser can do key agreement.
1307
+ const { e2ePrivateKey, e2ePublicKey } = prev
1308
+ ? { e2ePrivateKey: prev.e2ePrivateKey, e2ePublicKey: prev.e2ePublicKey }
1309
+ : generateE2EKeyPair();
1286
1310
 
1287
1311
  const body = JSON.stringify({
1288
1312
  code: otp.trim().toUpperCase(),
@@ -1301,25 +1325,29 @@ async function pair(otp) {
1301
1325
  return { ok: false, error: 'relay returned no device token' };
1302
1326
  }
1303
1327
 
1304
- const cfg = await loadConfig();
1305
1328
  // A desktop only ever connects to the relay as ONE device; all of the user's
1306
1329
  // browsers route to it (the relay isolates by email, not per-credential). So keep
1307
1330
  // only the newly paired credential — accumulating stale entries is pure cruft that
1308
1331
  // would otherwise shadow this one and trap reconnection on a dead token.
1309
- const devices = [{
1310
- deviceId: response.deviceId,
1311
- deviceToken: response.deviceToken, // stored only on disk at 0600
1312
- // Private key stored at 0600 — same security model as device token.
1313
- e2ePrivateKey,
1314
- e2ePublicKey,
1315
- deviceName: `Device (paired ${new Date().toISOString().slice(0, 10)})`,
1316
- issuedAt: new Date().toISOString(),
1317
- lastConnectedAt: null,
1318
- // Set once a browser's SAS is manually confirmed; TOFU-pinned for auto-trust
1319
- // on future reconnects from the same (deviceId, browserPubKey) pair.
1320
- verifiedPeerPubKey: null,
1321
- verifiedPeerPubKeys: [],
1322
- }];
1332
+ const now = new Date().toISOString();
1333
+ // Pins are only carried onto a deviceId the relay confirmed.
1334
+ const reused = prev && response.deviceId === deviceId;
1335
+ const devices = [reused
1336
+ ? { ...prev, deviceId, deviceToken: response.deviceToken, issuedAt: now, lastConnectedAt: null }
1337
+ : {
1338
+ deviceId: response.deviceId,
1339
+ deviceToken: response.deviceToken, // stored only on disk at 0600
1340
+ // Private key stored at 0600 — same security model as device token.
1341
+ e2ePrivateKey,
1342
+ e2ePublicKey,
1343
+ deviceName: `Device (paired ${now.slice(0, 10)})`,
1344
+ issuedAt: now,
1345
+ lastConnectedAt: null,
1346
+ // Set once a browser's SAS is manually confirmed; TOFU-pinned for auto-trust
1347
+ // on future reconnects from the same (deviceId, browserPubKey) pair.
1348
+ verifiedPeerPubKey: null,
1349
+ verifiedPeerPubKeys: [],
1350
+ }];
1323
1351
 
1324
1352
  await saveConfig({ ...cfg, devices });
1325
1353
  _repairNeeded = false;
@@ -1533,6 +1561,7 @@ module.exports = {
1533
1561
  finalizeE2eAuthenticated,
1534
1562
  getClient: (clientKey = LEGACY_CLIENT_KEY) => _clients.getOrCreate(clientKey),
1535
1563
  revokeAllDevices,
1564
+ pair,
1536
1565
  streamCount: () => _clients.values().reduce((n, c) => n + c.ptyStreams.size, 0),
1537
1566
  },
1538
1567
  };
@@ -1340,6 +1340,11 @@ export interface MemoryStaleEntry {
1340
1340
  deadRefs: string[];
1341
1341
  stale: boolean;
1342
1342
  reasons: string[];
1343
+ description: string | null;
1344
+ type: string | null;
1345
+ originSessionId: string | null;
1346
+ outLinks: string[];
1347
+ danglingLinks: string[];
1343
1348
  }
1344
1349
 
1345
1350
  export interface MemoryStaleResult {
@@ -1634,7 +1639,8 @@ export interface RemoteClientDevice {
1634
1639
  deviceId: string;
1635
1640
  email: string;
1636
1641
  issuedAt: string;
1637
- expiresAt: string;
1642
+ /** null = never expires (relay keeps tokens until revoked). */
1643
+ expiresAt: string | null;
1638
1644
  isOnline: boolean;
1639
1645
  devicePubKey: string;
1640
1646
  }
@@ -2114,6 +2120,20 @@ export interface SessionManagerAPI {
2114
2120
  stale: (target?: MemoryTarget) => Promise<MemoryStaleResult>;
2115
2121
  /** Agents (user + project) with their `memory:` frontmatter scope. */
2116
2122
  agents: (cwd?: string) => Promise<{ agents: MemoryAgent[] }>;
2123
+ /** Stamp a memory as verified (refreshes its freshness). */
2124
+ verify: (name: string, target?: MemoryTarget) => Promise<{ ok: boolean; error: string | null }>;
2125
+ /** Move a memory into the archive. */
2126
+ archive: (name: string, target?: MemoryTarget) => Promise<{ ok: boolean; error: string | null }>;
2127
+ /** Restore an archived memory. */
2128
+ restore: (name: string, target?: MemoryTarget) => Promise<{ ok: boolean; error: string | null }>;
2129
+ /** Names of archived memories. */
2130
+ listArchived: (target?: MemoryTarget) => Promise<{ names: string[]; error: string | null }>;
2131
+ /** Gated `claude -p` question over the memory folder. */
2132
+ ask: (input: { question: string; target?: MemoryTarget; contextName?: string }) =>
2133
+ Promise<{ ok: boolean; answer: string; citations: string[]; error?: string }>;
2134
+ /** Gated `claude -p` proposed rewrite fixing a memory's dead refs; requires `target.cwd`. */
2135
+ proposeFix: (input: { name: string; target?: MemoryTarget }) =>
2136
+ Promise<{ ok: boolean; content: string; summary: string; error?: string }>;
2117
2137
  };
2118
2138
  projectBrief: {
2119
2139
  /** Read brief.json (or null if none yet) plus cheaply-computed source/drift metadata. Never fires an LLM call. */
@@ -359,6 +359,13 @@ contextBridge.exposeInMainWorld('api', {
359
359
  ipcRenderer.invoke('memory:aggregate', { workspace, ...(refresh ? { refresh: true } : {}), ...(cwd ? { cwd } : {}) }),
360
360
  stale: (target) => ipcRenderer.invoke('memory:stale', memoryTarget(target)),
361
361
  agents: (cwd) => ipcRenderer.invoke('memory:agents', cwd ? { cwd } : {}),
362
+ verify: (name, target) => ipcRenderer.invoke('memory:verify', { name, ...memoryTarget(target) }),
363
+ archive: (name, target) => ipcRenderer.invoke('memory:archive', { name, ...memoryTarget(target) }),
364
+ restore: (name, target) => ipcRenderer.invoke('memory:restore', { name, ...memoryTarget(target) }),
365
+ listArchived: (target) => ipcRenderer.invoke('memory:listArchived', memoryTarget(target)),
366
+ ask: ({ question, target, contextName }) =>
367
+ ipcRenderer.invoke('memory:ask', { question, ...(contextName ? { contextName } : {}), ...memoryTarget(target) }),
368
+ proposeFix: ({ name, target }) => ipcRenderer.invoke('memory:proposeFix', { name, ...memoryTarget(target) }),
362
369
  },
363
370
  projectBrief: {
364
371
  get: (cwd) => ipcRenderer.invoke('project-brief:get', { cwd }),
@@ -1 +0,0 @@
1
- import{ap as i,F as r}from"./index-t37UuEZu.js";function l({value:e,onChange:n,path:o,readOnly:a}){return i.jsx(r,{path:`file://${o}`,defaultLanguage:"markdown",value:e,onChange:t=>n(t??""),theme:"vs-dark",options:{minimap:{enabled:!1},fontSize:13,fontFamily:"JetBrains Mono, ui-monospace, Menlo, monospace",lineNumbers:"on",renderLineHighlight:"line",scrollBeyondLastLine:!1,tabSize:2,wordWrap:"on",readOnly:a,automaticLayout:!0}})}export{l as M};
@@ -1,8 +0,0 @@
1
- import{b3 as ne,aX as G,aF as a,aW as $,ap as e,n as A,Z as xe,ad as X,ah as Z}from"./index-t37UuEZu.js";import{V as ae}from"./ViewTabs-BLQrBE2n.js";import{P as ue}from"./Panel-BkfK-W74.js";import{L as fe}from"./ListDetail-DcAD_cuA.js";import{M as he}from"./MarkdownEditor-D7JTNOOp.js";import"./monaco-editor-BsIlgG7c.js";function pe(t){return!t||!t.trim()?"default":t.replace(/[^a-zA-Z0-9]/g,"-")}const oe=/^[a-z0-9-_]+$/;function ge(t,n,s,l){return t.filter(p=>!n||p.name.toLowerCase().includes(n.toLowerCase())).filter(p=>{var b;return!s||((b=l[p.name])==null?void 0:b.stale)===!0})}const be=["Commands:"," list — show all memory entries"," show <slug> — read one entry"," search <text> — find entries containing <text>"," forget <slug> — delete an entry (with confirm)"," remember <free-form> — ask Claude to save this"," help — this message","","Anything else: I will offer to send it to Claude in the terminal,","or add it as a new memory entry directly."].join(`
2
- `);function ye(t){const n=t.trim();if(!n)return{kind:"freeform",arg:"",raw:t};const s=n.toLowerCase();if(s==="help"||s==="?")return{kind:"help",arg:"",raw:t};if(s==="list"||s==="ls"||s==="list memories"||s==="list all"||s==="what do you remember"||s==="what do you remember?")return{kind:"list",arg:"",raw:t};const l=n.match(/^(?:show|read|open)\s+(.+)$/i);if(l)return{kind:"show",arg:l[1].trim(),raw:t};const p=n.match(/^(?:forget|delete|remove)\s+(.+)$/i);if(p)return{kind:"forget",arg:p[1].trim(),raw:t};const b=n.match(/^(?:search|find)\s+(.+)$/i)||n.match(/^what (?:do )?you know about\s+(.+?)\??$/i);if(b)return{kind:"search",arg:b[1].trim(),raw:t};const d=n.match(/^remember(?:\s+that)?\s+(.+)$/i)||n.match(/^note(?:\s+that)?\s+(.+)$/i)||n.match(/^save(?:\s+that)?\s+(.+)$/i);return d?{kind:"remember",arg:d[1].trim(),raw:t}:{kind:"freeform",arg:n,raw:t}}function q(t,n){const s=t.toLowerCase().replace(/\.md$/,""),l=n.find(d=>d.name.replace(/\.md$/,"").toLowerCase()===s);if(l)return l;const p=n.filter(d=>d.name.replace(/\.md$/,"").toLowerCase().startsWith(s));if(p.length===1)return p[0];const b=n.filter(d=>d.name.replace(/\.md$/,"").toLowerCase().includes(s));return b.length===1?b[0]:null}function ee(t){const n=new Set(["the","a","an","is","are","to","of","in","for","and","or"]);return t.toLowerCase().replace(/[^a-z0-9\s-]/g," ").split(/\s+/).filter(p=>p&&!n.has(p)).slice(0,4).join("-").replace(/-+/g,"-").replace(/^-|-$/g,"")||`note-${Date.now().toString(36).slice(-4)}`}function te(t,n){return[`Please save this to my workspace memory (workspace: ${t}).`,`Use the memory tool (or write a markdown file under ~/.claude/projects/${t}/memory/).`,"Pick a short kebab-case filename and add a one-line title at the top.","","Memory to save:",n].join(`
3
- `)}function se(){return`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`}function je({workspace:t,cwd:n,entries:s,onChanged:l}){const p=ne(),b=G(),d=(b==null?void 0:b.id)??null,[v,h]=a.useState(""),[j,x]=a.useState(()=>[{id:se(),role:"system",text:"Hi — I am the memory assistant for this workspace. Type `help` for what I understand, or just talk to me."}]),[f,i]=a.useState(!1),N=a.useRef(null),w=a.useRef(null);a.useEffect(()=>{const r=N.current;r&&(r.scrollTop=r.scrollHeight)},[j]);const c=a.useCallback(r=>{x(u=>[...u,{...r,id:se()}])},[]),k=a.useCallback(()=>{if(s.length===0){c({role:"result",text:"No memories saved for this workspace yet."});return}c({role:"result",text:`Found ${s.length} ${s.length===1?"memory":"memories"}:`,payload:{kind:"entries",entries:s}})},[s,c]),B=a.useCallback(async r=>{const u=q(r,s);if(!u){c({role:"result",text:`No memory matches "${r}". Try \`list\` to see what is here.`});return}const g=await window.api.memory.read(u.name,{workspace:t,cwd:n});if(g.error){$.error(`Memory read failed: ${g.error}`),c({role:"result",text:`Read failed: ${g.error}`});return}c({role:"result",text:`${u.name}`,payload:{kind:"entry",entry:u,content:g.content}})},[s,t,n,c]),F=a.useCallback(async r=>{const u=r.toLowerCase(),g=s.filter(S=>S.name.toLowerCase().includes(u)),M=[];for(const S of s){if(g.includes(S))continue;const C=await window.api.memory.read(S.name,{workspace:t,cwd:n});if(C.error)continue;const T=C.content.split(`
4
- `),I=T.findIndex(L=>L.toLowerCase().includes(u));I>=0&&M.push({entry:S,snippet:T[I].trim().slice(0,200)})}const E=[...g.map(S=>({entry:S,snippet:"(filename match)"})),...M];if(E.length===0){c({role:"result",text:`No matches for "${r}".`});return}c({role:"result",text:`Found ${E.length} ${E.length===1?"match":"matches"} for "${r}":`,payload:{kind:"search",query:r,hits:E}})},[s,t,n,c]),W=a.useCallback(async r=>{const u=q(r,s);if(!u){c({role:"result",text:`No memory matches "${r}". Try \`list\` to see what is here.`});return}if(!window.confirm(`Delete memory "${u.name}"? This cannot be undone.`))return;const g=await window.api.memory.delete(u.name,{workspace:t,cwd:n});if(!g.ok){$.error(`Memory delete failed: ${g.error??"unknown error"}`),c({role:"result",text:`Delete failed: ${g.error??"unknown error"}`});return}c({role:"result",text:`Deleted ${u.name}.`}),l()},[s,t,n,c,l]),D=a.useCallback(r=>{const u=ee(r),g=te(t,r);c({role:"result",text:"I do not write to memory from this panel. Send the request to Claude in the active terminal, or add it directly as a new memory entry below.",payload:{kind:"suggest-send",prompt:g,original:r}}),c({role:"result",text:`Add it directly as \`${u}.md\` instead?`,payload:{kind:"suggest-add",slug:u,content:r}})},[t,c]),H=a.useCallback(r=>{const u=ee(r),g=te(t,r);c({role:"result",text:"Not a recognised command. Options:",payload:{kind:"suggest-send",prompt:g,original:r}}),c({role:"result",text:`…or save it directly as \`${u}.md\`.`,payload:{kind:"suggest-add",slug:u,content:r}})},[t,c]),z=a.useCallback(async r=>{i(!0);try{switch(r.kind){case"list":k();break;case"show":await B(r.arg);break;case"search":await F(r.arg);break;case"forget":await W(r.arg);break;case"help":c({role:"result",text:be});break;case"remember":D(r.arg);break;case"freeform":H(r.arg);break}}finally{i(!1)}},[k,B,F,W,D,H,c]),K=a.useCallback(async()=>{const r=v.trim();!r||f||(h(""),c({role:"user",text:r}),await z(ye(r)))},[v,f,z,c]),R=r=>{r.key==="Enter"&&!r.shiftKey&&(r.preventDefault(),K())},V=a.useCallback(r=>{if(!d){$.error("No active terminal session — open or focus a tab first.");return}window.api.pty.write({tabId:d,data:r}),$.info("Prompt sent to active terminal (not submitted)")},[d]),Y=a.useCallback(async(r,u)=>{if(!oe.test(r)){$.error(`Invalid slug "${r}" — must be [a-z0-9-_]+`);return}const g=`${r}.md`,M=await window.api.memory.create(g,void 0,{workspace:t,cwd:n});if(!M.ok){$.error(`Create failed: ${M.error??"unknown error"}`);return}const E=await window.api.memory.read(g,{workspace:t,cwd:n}),S=E.error?u:`${E.content.trimEnd()}
5
-
6
- ${u}
7
- `,C=await window.api.memory.write(g,S,{workspace:t,cwd:n});if(!C.ok){$.error(`Write failed: ${C.error??"unknown error"}`);return}c({role:"result",text:`Saved as ${g}.`}),l()},[t,n,c,l]),O=a.useMemo(()=>[{label:"List memories",value:"list"},{label:"Help",value:"help"},{label:"Search…",value:"search "},{label:"Remember…",value:"remember "}],[]);return p?e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsxs("div",{ref:N,className:"flex-1 min-h-0 overflow-y-auto px-3 py-2 space-y-2",children:[j.map(r=>e.jsx(ve,{message:r,entries:s,onShow:u=>{var g;h(`show ${u.replace(/\.md$/,"")}`),(g=w.current)==null||g.focus()},onSendToClaude:V,onAddDirect:Y},r.id)),f&&e.jsx("div",{className:"text-xs text-fg-faint italic",children:"working…"})]}),e.jsxs("div",{className:"shrink-0 border-t border-line px-3 py-2 space-y-2",children:[e.jsx("div",{className:"flex gap-1 flex-wrap",children:O.map(r=>e.jsx("button",{onClick:()=>{var u;h(r.value),(u=w.current)==null||u.focus()},className:"px-2 py-0.5 text-[11px] text-fg-faint hover:text-fg-dim border border-line hover:border-fg-faint rounded transition-colors",children:r.label},r.label))}),e.jsxs("div",{className:"flex gap-2 items-end",children:[e.jsx(xe,{}),e.jsx("textarea",{ref:w,value:v,onChange:r=>h(r.target.value),onKeyDown:R,placeholder:"Type `list`, `show <slug>`, `search <text>`, `remember …`, or talk freely. Enter to send, Shift+Enter for newline.",rows:2,className:"flex-1 bg-bg border border-line rounded px-2 py-1 text-xs text-fg resize-none focus:outline-none focus:border-fg-faint"}),e.jsx("button",{onClick:K,disabled:!v.trim()||f,className:"px-3 py-1 text-xs text-fg border border-line hover:bg-bg-hi rounded transition-colors disabled:opacity-40 disabled:cursor-not-allowed",children:"Send"})]}),e.jsxs("div",{className:"text-[10px] text-fg-faint",children:["Workspace: ",e.jsx("span",{className:"font-mono",children:t}),!d&&e.jsx("span",{className:"ml-2 text-amber-400",children:"(no active terminal — Send-to-Claude disabled)"})]})]})]}):e.jsx(A,{title:"loading…"})}function ve({message:t,entries:n,onShow:s,onSendToClaude:l,onAddDirect:p}){var d,v,h,j,x;const b=t.role==="user"?"bg-bg-hi text-fg ml-8":t.role==="system"?"bg-bg text-fg-dim italic":"bg-bg text-fg-dim";return e.jsxs("div",{className:`text-xs rounded border border-line px-3 py-2 ${b}`,children:[e.jsx("div",{className:"whitespace-pre-wrap font-mono text-[11px] leading-relaxed",children:t.text}),((d=t.payload)==null?void 0:d.kind)==="entries"&&e.jsx("div",{className:"mt-2 space-y-0.5",children:t.payload.entries.map(f=>e.jsxs("button",{onClick:()=>s(f.name),className:"block w-full text-left px-2 py-0.5 text-[11px] text-fg-dim hover:text-fg hover:bg-bg-hi rounded font-mono",children:[f.name," ",e.jsxs("span",{className:"text-fg-faint",children:["(",X(f.bytes),")"]})]},f.name))}),((v=t.payload)==null?void 0:v.kind)==="entry"&&e.jsx("pre",{className:"mt-2 max-h-64 overflow-auto px-2 py-1 bg-bg-hi rounded text-[11px] whitespace-pre-wrap text-fg",children:t.payload.content}),((h=t.payload)==null?void 0:h.kind)==="search"&&e.jsx("div",{className:"mt-2 space-y-1",children:t.payload.hits.map((f,i)=>e.jsxs("button",{onClick:()=>s(f.entry.name),className:"block w-full text-left px-2 py-1 hover:bg-bg-hi rounded",children:[e.jsx("div",{className:"font-mono text-[11px] text-fg-dim",children:f.entry.name}),e.jsx("div",{className:"text-[10px] text-fg-faint truncate",children:f.snippet})]},`${f.entry.name}-${i}`))}),((j=t.payload)==null?void 0:j.kind)==="suggest-send"&&e.jsxs("div",{className:"mt-2 flex gap-2 items-center",children:[e.jsx("button",{onClick:()=>l(t.payload.kind==="suggest-send"?t.payload.prompt:""),className:"px-2 py-0.5 text-[11px] text-fg-dim hover:text-fg border border-line hover:border-fg-faint rounded transition-colors",children:"Send to Claude in terminal"}),e.jsx("span",{className:"text-[10px] text-fg-faint",children:"paste-only — you press Enter"})]}),((x=t.payload)==null?void 0:x.kind)==="suggest-add"&&e.jsxs("div",{className:"mt-2 flex gap-2 items-center",children:[e.jsx("button",{onClick:()=>{var f;return((f=t.payload)==null?void 0:f.kind)==="suggest-add"&&p(t.payload.slug,t.payload.content)},className:"px-2 py-0.5 text-[11px] text-fg-dim hover:text-fg border border-line hover:border-fg-faint rounded transition-colors",children:"Add as new memory"}),e.jsxs("span",{className:"text-[10px] text-fg-faint font-mono",children:[t.payload.slug,".md"]})]})]})}function we({workspace:t,cwd:n,onOpenMember:s}){const[l,p]=a.useState(null),[b,d]=a.useState(!1),[v,h]=a.useState(!1),j=a.useRef(0),x=a.useCallback(async w=>{const c=++j.current;d(!0);try{const k=await window.api.memory.aggregate(t,w,n??void 0);if(j.current!==c)return;p(k)}catch(k){if(j.current!==c)return;$.error(`Memory aggregate failed: ${k instanceof Error?k.message:String(k)}`)}finally{j.current===c&&(d(!1),h(!0))}},[t,n]);a.useEffect(()=>{p(null),h(!1),x(!1)},[x]);const f=(l==null?void 0:l.clusters)??[],i=(l==null?void 0:l.orphans)??[],N=f.length>0||i.length>0;return e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsxs("div",{className:"shrink-0 flex items-center gap-2 px-3 py-2 border-b border-line text-xs",children:[e.jsx("span",{className:"text-fg-faint",children:l!=null&&l.generatedAt?`generated ${Z(l.generatedAt)} ago`:"not yet aggregated"}),e.jsx("div",{className:"flex-1"}),e.jsx("button",{onClick:()=>x(!0),disabled:b,className:"px-2 py-0.5 text-xs text-fg-dim hover:text-fg border border-line hover:border-fg-faint rounded transition-colors disabled:opacity-40 disabled:cursor-not-allowed",children:b?"Aggregating…":l!=null&&l.generatedAt?"Refresh":"Aggregate"})]}),e.jsx("div",{className:"flex-1 min-h-0 overflow-auto p-3",children:v?N?e.jsxs("div",{className:"space-y-4",children:[f.length>0&&e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-3",children:f.map(w=>e.jsx(Ne,{cluster:w,onOpenMember:s},w.id))}),i.length>0&&e.jsxs("div",{className:"border border-line rounded p-3",children:[e.jsx("div",{className:"text-xs text-fg mb-2",children:"Unclustered"}),e.jsx("div",{className:"flex flex-wrap gap-1",children:i.map(w=>e.jsx("button",{onClick:()=>s(w),className:"px-2 py-0.5 text-[11px] font-mono text-fg-dim hover:text-fg border border-line hover:border-fg-faint rounded transition-colors",children:w},w))})]})]}):e.jsx(A,{title:"no clusters yet",hint:"Click Aggregate to organize this workspace's memories into named clusters."}):e.jsx(A,{title:"loading…"})})]})}function Ne({cluster:t,onOpenMember:n}){return e.jsxs("div",{className:"border border-line rounded p-3",children:[e.jsx("div",{className:"text-sm text-fg",children:t.name}),t.summary&&e.jsx("div",{className:"text-xs text-fg-faint mt-0.5",children:t.summary}),e.jsx("div",{className:"mt-2 flex flex-wrap gap-1",children:t.memberSlugs.map(s=>e.jsx("button",{onClick:()=>n(s),className:"px-2 py-0.5 text-[11px] font-mono text-fg-dim hover:text-fg border border-line hover:border-fg-faint rounded transition-colors",children:s},s))}),t.links.length>0&&e.jsx("div",{className:"mt-2 space-y-0.5",children:t.links.map((s,l)=>e.jsxs("div",{className:"text-[10px] text-fg-faint font-mono",children:[s.from," → ",s.to,s.label?` (${s.label})`:""]},`${s.from}-${s.to}-${l}`))})]})}function ke({index:t,autoMemoryEnabled:n}){const s=t!=null&&t.overBudget?"text-red-400 border-red-400/40 bg-red-400/10":t!=null&&t.nearBudget?"text-amber-400 border-amber-400/40 bg-amber-400/10":"text-fg-faint border-line";return e.jsxs(e.Fragment,{children:[!n&&e.jsx("div",{"data-testid":"memory-auto-off-banner",className:"shrink-0 px-3 py-1.5 text-xs text-amber-400 border-b border-amber-400/40 bg-amber-400/10",children:"Auto memory is off — Claude Code will not read or write these memories"}),t&&e.jsxs("div",{"data-testid":"memory-index-strip",className:`shrink-0 flex items-center gap-3 px-3 py-1 text-[11px] border-b ${s}`,children:[e.jsxs("span",{children:["MEMORY.md ",t.lines,"/",t.maxLines," lines · ",(t.bytes/1024).toFixed(1),"/",Math.round(t.maxBytes/1024)," KB"]}),t.orphans.length>0&&e.jsxs("span",{children:[t.orphans.length," not in index"]}),t.dangling.length>0&&e.jsxs("span",{children:[t.dangling.length," dangling index lines"]})]})]})}function le({target:t,cwd:n,toolbarExtra:s,enableNatural:l=!1,enableClusters:p=!1}){const b=JSON.stringify(t),d=a.useMemo(()=>t,[b]),v=d.workspace??"",[h,j]=a.useState("classic"),[x,f]=a.useState([]),[i,N]=a.useState(null),[w,c]=a.useState(""),[k,B]=a.useState({}),[F,W]=a.useState(!1),[D,H]=a.useState(""),[z,K]=a.useState(!0),[R,V]=a.useState(void 0),[Y,O]=a.useState({}),[r,u]=a.useState({}),[g,M]=a.useState(!1),[E,S]=a.useState(!1),C=a.useCallback(async()=>{const o=await window.api.memory.list(d);f(o.entries),H(o.dir??""),K(o.autoMemoryEnabled!==!1),o.error&&$.error(`Memory list failed: ${o.error}`),N(m=>{var y;return m&&o.entries.some(me=>me.name===m)?m:((y=o.entries[0])==null?void 0:y.name)??null});try{const m=await window.api.memory.stale(d);B(Object.fromEntries(m.entries.map(y=>[y.name,y]))),V(m.index)}catch(m){B({}),V(void 0),$.error(`Memory staleness check failed: ${m instanceof Error?m.message:String(m)}`)}},[d]);a.useEffect(()=>{O({}),u({}),N(null),S(!1),C()},[C]),a.useEffect(()=>{if(!D)return;const o=D;window.api.config.watch([o]);const m=window.api.config.onChanged(({path:y})=>{(y===o||y.startsWith(o+"/"))&&C()});return()=>{m(),window.api.config.unwatch([o])}},[D,C]),a.useEffect(()=>{if(!i||Y[i]!==void 0)return;let o=!1;return(async()=>{const m=await window.api.memory.read(i,d);if(!o){if(m.error){$.error(`Memory read failed: ${m.error}`);return}O(y=>({...y,[i]:m.content})),u(y=>({...y,[i]:m.content}))}})(),()=>{o=!0}},[i,d]);const T=x.reduce((o,m)=>{var y;return o+((y=k[m.name])!=null&&y.stale?1:0)},0),I=ge(x,w,F,k),L=x.find(o=>o.name===i)??null,P=i?k[i]:void 0,U=i?Y[i]??"":"",ie=i?r[i]??"":"",J=i?U!==ie:!1,Q=[{key:"classic",label:"Editor"},...l?[{key:"natural",label:"Natural"}]:[],...p?[{key:"clusters",label:"Clusters"}]:[]],ce=async()=>{if(!i)return;M(!0);const o=await window.api.memory.write(i,U,d);if(M(!1),!o.ok){$.error(`Memory save failed: ${o.error??"unknown error"}`);return}u(m=>({...m,[i]:U})),C()},de=async()=>{if(!i||!window.confirm(`Delete memory "${i}"? This cannot be undone.`))return;M(!0);const o=await window.api.memory.delete(i,d);if(M(!1),!o.ok){$.error(`Memory delete failed: ${o.error??"unknown error"}`);return}O(m=>{const y={...m};return delete y[i],y}),u(m=>{const y={...m};return delete y[i],y}),N(null),C()};return e.jsxs(ue,{toolbar:e.jsxs(e.Fragment,{children:[Q.length>1&&e.jsxs(e.Fragment,{children:[e.jsx(ae,{options:Q,active:h,onChange:j}),e.jsx("span",{className:"mx-2 text-fg-faint",children:"·"})]}),s,s&&e.jsx("span",{className:"mx-2 text-fg-faint",children:"·"}),e.jsxs("span",{className:"text-fg-faint",children:[x.length," ",x.length===1?"entry":"entries"]}),e.jsx("div",{className:"flex-1"}),h==="classic"&&T>0&&e.jsxs("button",{onClick:()=>W(o=>!o),className:`px-2 py-0.5 text-xs border rounded transition-colors ${F?"text-amber-400 border-amber-400/50 bg-amber-400/10":"text-fg-dim hover:text-fg border-line hover:border-fg-faint"}`,children:["Stale only (",T,")"]}),h==="classic"&&e.jsx("button",{onClick:()=>S(!0),className:"px-2 py-0.5 text-xs text-fg-dim hover:text-fg border border-line hover:border-fg-faint rounded transition-colors",children:"+ New memory"}),h!=="clusters"&&e.jsx("button",{onClick:C,className:"ml-2 px-2 py-0.5 text-xs text-fg-faint hover:text-fg-dim border border-line hover:border-fg-faint rounded transition-colors",children:"Refresh"})]}),footer:h==="classic"&&L?e.jsxs("div",{className:"px-3 py-1.5 flex items-center gap-3 text-xs",children:[e.jsx("button",{onClick:ce,disabled:!J||g,className:"px-2 py-0.5 text-xs text-fg-dim hover:text-fg border border-line hover:border-fg-faint rounded transition-colors disabled:opacity-40 disabled:cursor-not-allowed",children:g?"Saving…":"Save"}),e.jsx("button",{onClick:de,disabled:g,className:"px-2 py-0.5 text-xs text-red-400 hover:text-red-300 border border-line hover:border-red-400/50 rounded transition-colors disabled:opacity-40",children:"Delete"}),(P==null?void 0:P.stale)&&e.jsxs("span",{className:"text-amber-400/90 truncate",title:P.reasons.join("; "),children:["stale · ",P.reasons.join(", ")]}),e.jsx("span",{className:"text-fg-faint truncate flex-1",children:L.path}),J&&e.jsx("span",{className:"text-accent",children:"unsaved"})]}):null,children:[h==="classic"&&e.jsx(ke,{index:R,autoMemoryEnabled:z}),h==="natural"&&l?e.jsx(je,{workspace:v,cwd:n??void 0,entries:x,onChanged:C}):h==="clusters"&&p?e.jsx(we,{workspace:v,cwd:n,onOpenMember:o=>{N(`${o}.md`),j("classic")}}):e.jsx(fe,{sidebar:e.jsxs("div",{className:"py-1",children:[e.jsx("div",{className:"px-2 pb-1",children:e.jsx("input",{value:w,onChange:o=>c(o.target.value),placeholder:"filter…",className:"w-full bg-bg border border-line rounded px-2 py-0.5 text-xs text-fg"})}),I.length===0?e.jsx("div",{className:"px-3 py-2 text-xs text-fg-faint italic",children:x.length===0?"no memories yet":"no matches"}):I.map(o=>{const m=k[o.name],y=m!=null&&m.stale?`${o.path}
8
- stale: ${m.reasons.join(", ")}`:o.path;return e.jsxs("button",{onClick:()=>N(o.name),className:`w-full text-left px-3 py-1 text-xs flex items-center justify-between ${i===o.name?"bg-bg-hi text-fg":"text-fg-dim hover:text-fg hover:bg-bg-hi"}`,title:y,children:[e.jsxs("span",{className:"truncate flex items-center",children:[e.jsx("span",{className:"truncate",children:o.name.replace(/\.md$/,"")}),(m==null?void 0:m.stale)&&e.jsx("span",{className:"ml-1.5 shrink-0 px-1 rounded text-[9px] uppercase tracking-wide text-amber-400/90 border border-amber-400/30",children:"stale"}),(R==null?void 0:R.orphans.includes(o.name))&&e.jsx("span",{className:"ml-1.5 shrink-0 px-1 rounded text-[9px] uppercase tracking-wide text-amber-400/90 border border-amber-400/30",title:"Not listed in MEMORY.md — Claude won't see it",children:"not in index"})]}),e.jsxs("span",{className:"ml-2 text-fg-faint shrink-0 text-[10px]",children:[X(o.bytes)," · ",Z(o.mtimeMs)]})]},o.name)})]}),detail:E?e.jsx(Ce,{target:d,dir:D,onCancel:()=>S(!1),onCreated:o=>{S(!1),N(o),C()}}):L&&i?e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsxs("div",{className:"shrink-0 px-3 py-2 border-b border-line text-xs",children:[e.jsx("div",{className:"text-fg truncate",children:L.name}),e.jsxs("div",{className:"text-fg-faint truncate",children:[X(L.bytes)," · modified ",Z(L.mtimeMs)]})]}),e.jsx("div",{className:"flex-1 min-h-0",children:e.jsx(he,{path:L.path,value:U,onChange:o=>O(m=>({...m,[i]:o}))})})]}):e.jsx(A,{title:x.length===0?"no memories yet":"select a memory",hint:x.length===0?"Claude writes to memories during sessions when you ask it to remember things, or you can create one manually with the + New memory button.":void 0})})]})}function Ce({target:t,dir:n,onCancel:s,onCreated:l}){const[p,b]=a.useState(""),[d,v]=a.useState(""),[h,j]=a.useState(!1),[x,f]=a.useState(null),i=p.trim().toLowerCase(),N=oe.test(i),w=async()=>{if(!N){f("Slug must match [a-z0-9-_]+");return}j(!0),f(null);const c=`${i}.md`,k=await window.api.memory.create(c,d.trim()||void 0,t);if(j(!1),!k.ok){f(k.error??"create failed");return}l(c)};return e.jsxs("div",{className:"p-4 max-w-xl space-y-3",children:[e.jsx("div",{className:"text-sm text-fg",children:"New memory"}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{className:"block text-xs text-fg-faint",children:"Slug"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{autoFocus:!0,value:p,onChange:c=>b(c.target.value),placeholder:"my-notes",className:"flex-1 bg-bg border border-line rounded px-2 py-1 text-xs text-fg font-mono"}),e.jsx("span",{className:"text-xs text-fg-faint",children:".md"})]}),e.jsxs("div",{className:"text-[10px] text-fg-faint",children:["Lowercase letters, digits, dashes, underscores. The file is created at",e.jsxs("code",{className:"ml-1 font-mono text-fg-dim",children:[n||"…","/",i||"…",".md"]})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{className:"block text-xs text-fg-faint",children:"Description (optional)"}),e.jsx("input",{value:d,onChange:c=>v(c.target.value),placeholder:"one-line summary",className:"w-full bg-bg border border-line rounded px-2 py-1 text-xs text-fg"})]}),x&&e.jsx("div",{className:"text-xs text-red-400",children:x}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:w,disabled:!N||h,className:"px-3 py-1 text-xs text-fg border border-line hover:bg-bg-hi rounded transition-colors disabled:opacity-40",children:h?"Creating…":"Create"}),e.jsx("button",{onClick:s,disabled:h,className:"px-3 py-1 text-xs text-fg-faint hover:text-fg-dim rounded transition-colors",children:"Cancel"})]})]})}const Se={user:"user — all projects",project:"project — shared via git",local:"local — this machine, not committed"},_=t=>`${t.origin}:${t.name}`;function $e(){const t=G(),n=(t==null?void 0:t.cwd)??null,[s,l]=a.useState([]),[p,b]=a.useState(!1),[d,v]=a.useState(null);a.useEffect(()=>{let x=!1;return window.api.memory.agents(n??void 0).then(f=>{x||(l(f.agents),b(!0),v(i=>i&&f.agents.some(N=>_(N)===i)?i:f.agents[0]?_(f.agents[0]):null))}).catch(()=>{x||(l([]),b(!0))}),()=>{x=!0}},[n]);const h=s.find(x=>_(x)===d)??null,j=e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"text-fg-faint",children:"Agent"}),e.jsxs("select",{value:d??"",onChange:x=>v(x.target.value||null),className:"bg-bg border border-line rounded px-2 py-0.5 text-xs text-fg max-w-[16rem]",children:[s.length===0&&e.jsx("option",{value:"",children:"(no agents found)"}),s.map(x=>e.jsxs("option",{value:_(x),children:[x.name," · ",x.origin]},_(x)))]})]});return p?h?h.memoryScope?e.jsx(le,{target:{cwd:n??void 0,agent:{name:h.name,scope:h.memoryScope}},cwd:n,toolbarExtra:e.jsxs(e.Fragment,{children:[j,e.jsx("span",{className:"mx-2 text-fg-faint",children:"·"}),e.jsx("span",{className:"text-fg-faint",children:Se[h.memoryScope]})]})}):e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsx("div",{className:"shrink-0 px-3 py-1.5 border-b border-line flex items-center gap-2 text-xs",children:j}),e.jsx("div",{className:"flex-1 min-h-0",children:e.jsx(A,{title:`${h.name} has no persistent memory`,hint:"Add `memory: project` (or `user` / `local`) to its frontmatter in the Agent Library to enable it."})})]}):e.jsx(A,{title:"no agents found",hint:"Create an agent in the Agent Library; add `memory: project` to its frontmatter to give it persistent memory."}):e.jsx(A,{title:"loading…"})}const Me=[{key:"workspace",label:"Workspace"},{key:"subagent",label:"Subagent"}],re="sm.memoryTab.scope";function Ee(){const[t,n]=a.useState(()=>localStorage.getItem(re)==="subagent"?"subagent":"workspace");return a.useEffect(()=>{localStorage.setItem(re,t)},[t]),e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsxs("div",{className:"shrink-0 flex items-center gap-3 px-3 py-2 border-b border-line",children:[e.jsx(ae,{options:Me,active:t,onChange:n}),e.jsx("span",{className:"text-[11px] text-fg-faint",children:t==="workspace"?"memories scoped to the active project":"long-term memory per subagent"})]}),e.jsx("div",{className:"flex-1 min-h-0",children:t==="workspace"?e.jsx(Le,{}):e.jsx($e,{})})]})}const Te=a.memo(Ee);function Le(){const t=ne(),n=G(),s=(n==null?void 0:n.cwd)??null,l=a.useMemo(()=>pe(s),[s]),p=a.useMemo(()=>({workspace:l,cwd:s??void 0}),[l,s]);return t?e.jsx(le,{target:p,cwd:s,enableNatural:!0,enableClusters:!0,toolbarExtra:e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"text-fg-faint",children:"Workspace"}),e.jsx("span",{className:"font-mono text-fg-dim truncate max-w-[24rem]",title:l,children:l})]})}):e.jsx(A,{title:"loading…"})}export{Te as Memory};
@@ -1,2 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./SkillReferenceGraph-fv2FJUNK.js","./index-t37UuEZu.js","./monaco-editor-BsIlgG7c.js","./monaco-editor-Cu5D__1H.css","./index-HpEbvDiE.css"])))=>i.map(i=>d[i]);
2
- import{ap as t,aF as c,n as S,b3 as pe,aW as q,a_ as ae,a as xe}from"./index-t37UuEZu.js";import{P as ee}from"./Panel-BkfK-W74.js";import{P as re}from"./ProvenanceBadge-CQXSiPHq.js";import{e as ge}from"./Library-Dl71nylN.js";import{p as le}from"./skillFrontmatter-Dif5JIg7.js";import{l as je}from"./listSkills-C1aWKf0T.js";import{_ as be}from"./monaco-editor-BsIlgG7c.js";import{L as ye}from"./ListDetail-DcAD_cuA.js";import{M as ve}from"./MarkdownEditor-D7JTNOOp.js";import"./Button-mj0vvcdc.js";function ke({columns:e,rows:n,getKey:i,onRowClick:s,activeKey:a,empty:d}){return n.length===0?t.jsx("div",{className:"p-6 text-fg-faint text-xs text-center",children:d??"no entries"}):t.jsxs("table",{className:"w-full text-xs",children:[t.jsx("thead",{className:"sticky top-0 bg-bg-elev text-fg-faint uppercase tracking-wider",children:t.jsx("tr",{className:"border-b border-line",children:e.map(l=>t.jsx("th",{className:`text-left font-normal px-3 py-1.5 ${l.className??""}`,style:l.width?{width:l.width}:void 0,children:l.header},l.key))})}),t.jsx("tbody",{children:n.map(l=>{const h=i(l),o=a===h;return t.jsx("tr",{"data-row-key":h,onClick:()=>s==null?void 0:s(l),className:`border-b border-line/50 transition-colors ${s?"cursor-pointer":""} ${o?"bg-bg-hi text-fg":"text-fg-dim hover:bg-bg-hi/50"}`,children:e.map(u=>t.jsx("td",{className:`px-3 py-1 ${u.className??""}`,children:u.render(l)},u.key))},h)})})]})}async function oe(e){const n=`${e}/skills`;return await window.api.config.exists(n)?n:null}async function ce(e){const{entries:n}=await je(e,{nested:!1});return n.map(i=>{const s=le(i.text);return{id:i.name,name:s.name,description:s.description,dir:i.dir,path:i.path,body:s.body}})}function Ne(e){const n=[],i=new Set;for(const s of e)for(const a of e){if(s.id===a.id)continue;const d=a.id.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),l=[`/${d}\\b`,`\`${d}\``];if(a.id.length>=4&&l.push(`\\b${d}\\b`),!l.some(u=>new RegExp(u,"i").test(s.body)))continue;const o=`${s.id}->${a.id}`;i.has(o)||(i.add(o),n.push({from:s.id,to:a.id}))}return n}const we=c.lazy(()=>be(()=>import("./SkillReferenceGraph-fv2FJUNK.js"),__vite__mapDeps([0,1,2,3,4]),import.meta.url).then(e=>({default:e.SkillReferenceGraph})));function Se({pluginName:e,skills:n,onBack:i,initialSelectedId:s}){var N;const[a,d]=c.useState(s??((N=n[0])==null?void 0:N.id)??null),l=a?n.find(m=>m.id===a)??null:null,h=c.useMemo(()=>Ne(n),[n]),[o,u]=c.useState("list");return t.jsxs("div",{className:"flex flex-col h-full min-h-0 overflow-hidden",children:[t.jsxs("div",{className:"shrink-0 h-11 flex items-baseline gap-3.5 px-3 border-b border-line bg-bg",children:[t.jsxs("button",{type:"button",onClick:i,className:"font-mono text-accent hover:underline shrink-0 text-xs",children:["← ",e]}),t.jsx("span",{className:"font-serif text-[22px] text-fg shrink-0 truncate max-w-[16rem]",children:(l==null?void 0:l.name)??(l==null?void 0:l.id)??"skill"}),t.jsx("span",{className:"flex-1"}),t.jsx("div",{className:"flex items-center gap-1.5 shrink-0",children:t.jsxs("div",{className:"flex rounded border border-line overflow-hidden",children:[t.jsx("button",{onClick:()=>u("list"),className:`px-2 py-0.5 text-xs ${o==="list"?"bg-bg-hi text-fg":"text-fg-dim hover:text-fg hover:bg-bg-hi"}`,children:"list"}),t.jsx("button",{onClick:()=>u("graph"),className:`px-2 py-0.5 text-xs ${o==="graph"?"bg-bg-hi text-fg":"text-fg-dim hover:text-fg hover:bg-bg-hi"}`,children:"graph"})]})})]}),t.jsxs("div",{className:"shrink-0 h-[26px] flex items-center gap-[18px] px-3 bg-bg-elev border-b border-line text-[9px] font-mono uppercase tracking-wide overflow-hidden",children:[l!=null&&l.description?t.jsx("span",{className:"text-fg-dim truncate normal-case",children:l.description}):null,t.jsxs("span",{className:"ml-auto text-fg-faint truncate normal-case",children:[n.length," ",n.length===1?"skill":"skills"," · ",h.length," ",h.length===1?"reference":"references"]})]}),t.jsx("div",{className:"flex-1 min-h-0 overflow-hidden",children:n.length===0?t.jsx(S,{title:"no skills in this plugin"}):o==="graph"?t.jsx(c.Suspense,{fallback:t.jsx("div",{className:"p-6 text-xs text-fg-faint",children:"Loading graph…"}),children:t.jsx(we,{skills:n,edges:h,selectedId:a,onSelect:d})}):t.jsx(ye,{sidebar:t.jsx("div",{className:"py-1",children:n.map(m=>t.jsxs("button",{onClick:()=>d(m.id),className:`w-full px-3 py-1 text-xs text-left ${a===m.id?"bg-bg-hi text-fg":"text-fg-dim hover:text-fg hover:bg-bg-hi"}`,children:[t.jsx("div",{className:"truncate",children:m.name??m.id}),m.description?t.jsx("div",{className:"truncate text-fg-faint",children:m.description}):null]},m.id))}),detail:l?t.jsx("div",{className:"h-full min-h-0",children:t.jsx(ve,{path:l.path,value:l.body,onChange:()=>{},readOnly:!0})}):t.jsx(S,{title:"select a skill"})})})]})}const de=e=>{var n,i;return{type:"plugin",name:e.name,repository:(n=e.manifest)==null?void 0:n.repository,homepage:(i=e.manifest)==null?void 0:i.homepage}};function $e(){const e=pe(),[n,i]=c.useState([]),[s,a]=c.useState(!0),[d,l]=c.useState(null),[h,o]=c.useState(null),[u,N]=c.useState("installed"),[m,I]=c.useState(null),[D,F]=c.useState(new Set);c.useEffect(()=>{var g,k;let r=!1;return(k=(g=window.api.app).seedStatus)==null||k.call(g).then($=>{r||I($)}).catch(()=>{}),()=>{r=!0}},[]);const E=c.useRef(0),C=c.useRef(!1),b=c.useCallback(async()=>{const r=++E.current;if(!e)return;C.current||a(!0);const g=`${e}/.claude/plugins/installed_plugins.json`;let k=[],$=null;try{const x=await window.api.config.readJson(g);if(x.exists&&x.parseError)$=`could not parse installed_plugins.json${x.error?`: ${x.error}`:""}`;else if(x.exists&&x.data&&typeof x.data=="object"){const T=x.data,J=[];for(const[W,R]of Object.entries(T.plugins??{})){if(!Array.isArray(R))continue;const[_,O]=W.split("@");for(const j of R)j!=null&&j.installPath&&J.push({name:_,marketplace:O,entry:j})}k=await De(J,Le,async({name:W,marketplace:R,entry:_})=>{var H;const O={name:W,path:_.installPath,isDirectory:!0,isFile:!1,mtimeMs:0,size:0};let j;try{j=await _e(O)}catch(B){j=Re(O,B instanceof Error?B.message:String(B))}return(H=j.manifest)!=null&&H.version||(j.manifest={...j.manifest??{},version:_.version}),j.marketplace=R,j.scope=_.scope,j})}}catch(x){$=`could not read installed_plugins.json: ${x instanceof Error?x.message:String(x)}`}E.current===r&&(l($),$?q.error(`Plugins: ${$}`):(k.sort((x,T)=>x.name.localeCompare(T.name)),C.current=k.length>0,i(k)),a(!1))},[e]);c.useEffect(()=>{b()},[b]),c.useEffect(()=>()=>{E.current+=1},[]),ae(e?[`${e}/.claude/plugins/installed_plugins.json`]:[],b);const f=[{key:"name",header:"name",render:r=>{var g;return t.jsxs("div",{style:{maxWidth:"16rem"},children:[t.jsx("div",{className:"truncate",children:r.name}),(g=r.manifest)!=null&&g.description?t.jsx("div",{className:"truncate text-fg-faint",title:r.manifest.description,children:r.manifest.description}):null]})},width:"16rem"},{key:"origin",header:"origin",render:r=>t.jsx(re,{interactive:!1,input:de(r)}),width:"7rem"},{key:"scope",header:"scope",render:r=>r.scope?t.jsx("span",{"data-testid":"plugin-scope",children:r.scope}):t.jsx("span",{className:"text-fg-faint",children:"—"}),width:"5rem"},{key:"version",header:"version",render:r=>{var g;return((g=r.manifest)==null?void 0:g.version)??t.jsx("span",{className:"text-fg-faint",children:"—"})},width:"6rem"},{key:"manifest",header:"manifest",render:r=>r.hasManifest?"plugin.json":t.jsx("span",{className:"text-fg-faint",children:"—"}),width:"8rem"},{key:"contents",header:"contents",render:r=>t.jsx("span",{className:"font-mono text-fg-faint text-xs",children:[r.agents>0?`${r.agents} agents`:null,r.commands>0?`${r.commands} commands`:null,r.skills>0?`${r.skills} skills`:null,r.hooks>0?`${r.hooks} hooks`:null,r.monitors>0?`${r.monitors} monitors`:null,r.binCount>0?`${r.binCount} bin`:null,r.hasLsp?"lsp":null,r.hasMcp?"mcp":null,r.error?"inspection failed":null].filter(Boolean).join(" · ")||"—"})},{key:"path",header:"path",render:r=>t.jsx("span",{className:"font-mono text-fg-faint truncate",children:r.path})}],p=c.useMemo(()=>m?Object.keys(m).filter(r=>m[r].status==="exhausted"&&!D.has(r)):[],[m,D]),w=p.length>0?t.jsx(Pe,{seeders:p,seedStatus:m,onDismiss:r=>F(g=>new Set(g).add(r)),onOpenLibrary:()=>N("library")}):null;if(u==="library")return t.jsxs(ee,{toolbar:t.jsx(ne,{active:u,onChange:N}),children:[w,t.jsx(ge,{})]});const y=h?n.find(r=>r.path===h)??null:null;return t.jsxs(ee,{toolbar:t.jsxs(t.Fragment,{children:[t.jsx(ne,{active:u,onChange:N}),t.jsx("span",{className:"mx-2 text-fg-faint",children:"·"}),t.jsxs("span",{className:"text-fg-faint",children:[n.length," plugins"]}),t.jsx("div",{className:"flex-1"}),t.jsx("span",{className:"text-fg-faint font-mono truncate",children:"~/.claude/plugins/installed_plugins.json"})]}),children:[w,d?t.jsxs("div",{role:"alert",className:"shrink-0 px-3 py-2 border-b border-line bg-red-950/20 text-xs text-red-300",children:[d,n.length>0?" — showing the last known list":null]}):null,s&&n.length===0?t.jsx(S,{title:"scanning plugins…"}):d&&n.length===0?null:y?t.jsx(Ae,{row:y,home:e,onBack:()=>o(null)},y.path):t.jsx("div",{className:"flex flex-col h-full",children:t.jsx("div",{className:"flex-1 min-h-0 overflow-auto",children:t.jsx(ke,{columns:f,rows:n,getKey:r=>r.path,activeKey:h,onRowClick:r=>o(r.path),empty:t.jsxs(t.Fragment,{children:["no plugins installed",t.jsxs("div",{className:"mt-2 text-fg-faint",children:["install one from the Library view or run ",t.jsx("code",{children:"claude plugin install"})]})]})})})})]})}const Xe=c.memo($e),te={"dev-plugin":"session-manager-dev plugin","scheduler-mcp":"Scheduler MCP server","agent-personas":"Agent personas (Architect, Dev Lead)"};function Pe({seeders:e,seedStatus:n,onDismiss:i,onOpenLibrary:s}){return t.jsx("div",{className:"shrink-0 flex flex-col gap-1.5 px-3 py-2 border-b border-line bg-yellow-950/20",children:e.map(a=>t.jsxs("div",{className:"flex items-start gap-2 text-xs text-yellow-300",children:[t.jsxs("div",{className:"flex-1 min-w-0",children:[t.jsxs("div",{className:"font-medium",children:[te[a]," setup failed after retrying — manual fix needed"]}),a==="dev-plugin"?t.jsxs("div",{className:"text-yellow-400/80 mt-0.5",children:["Click ",t.jsx("button",{onClick:s,className:"underline hover:no-underline",children:"here"}),' to open the Library tab, then click Install next to "session-manager-dev".']}):t.jsx("div",{className:"text-yellow-400/80 mt-0.5 font-mono",children:n[a].fix})]}),t.jsx("button",{onClick:()=>i(a),className:"shrink-0 text-yellow-400/70 hover:text-yellow-300","aria-label":`Dismiss ${te[a]} warning`,children:"✕"})]},a))})}function ne({active:e,onChange:n}){const i=[["installed","Installed"],["library","Library"]];return t.jsx("div",{className:"flex rounded border border-line overflow-hidden",role:"tablist","aria-label":"Plugins view",children:i.map(([s,a])=>t.jsx("button",{onClick:()=>n(s),role:"tab","aria-selected":e===s,className:`px-2 py-0.5 text-xs ${e===s?"bg-bg-hi text-fg":"text-fg-dim hover:text-fg hover:bg-bg-hi"}`,children:a},s))})}const Ee=250,Ce=["hooks/hooks.json",".mcp.json",".lsp.json","agents","skills","commands",".claude-plugin/plugin.json"];function Ae({row:e,home:n,onBack:i}){var O,j,H,B,U;const[s,a]=c.useState([]),[d,l]=c.useState([]),[h,o]=c.useState([]),[u,N]=c.useState([]),[m,I]=c.useState([]),[D,F]=c.useState("skills"),[E,C]=c.useState(null),[b,f]=c.useState(!0),[p,w]=c.useState([]),y=c.useRef(0),r=c.useRef(!1),g=c.useCallback(async()=>{if(!n)return;const v=++y.current;try{const{manifest:M}=await ue(e.path),[z,V,he]=await Promise.all([oe(e.path),me(e.path,M),K(`${e.path}/bin`,{filesOnly:!0})]),G=z?await ce(z):[],[X,Y]=await Promise.all([ie(V.agentFiles),ie(V.commandFiles)]),Q=V.mcpServers,fe=await Promise.all([...new Set([...Ce.map(A=>`${e.path}/${A}`),...V.sourcePaths])].map(async A=>await window.api.config.exists(A)?A:null));if(v!==y.current)return;a(G),l(X),o(Y),N(Q),I(he);const Z=fe.filter(A=>A!==null);w(A=>A.join("\0")===Z.join("\0")?A:Z),r.current||(r.current=!0,F(G.length>0?"skills":X.length>0?"agents":Y.length>0?"commands":Q.length>0?"mcp":e.hooks>0?"hooks":e.monitors>0?"monitors":e.hasLsp?"lsp":"files"))}catch(M){if(v!==y.current)return;q.error(`Failed to load plugin contents: ${M instanceof Error?M.message:String(M)}`)}finally{v===y.current&&f(!1)}},[e.path,e.name,e.hooks,e.monitors,e.hasLsp,n]);c.useEffect(()=>(f(!0),g(),()=>{y.current+=1}),[g]);const k=c.useRef(null),$=c.useRef(!1),x=c.useRef(!1),T=c.useCallback(async()=>{if($.current){x.current=!0;return}$.current=!0;try{do x.current=!1,await g();while(x.current)}finally{$.current=!1}},[g]),J=c.useCallback(()=>{k.current&&clearTimeout(k.current),k.current=setTimeout(()=>{k.current=null,T()},Ee)},[T]);c.useEffect(()=>()=>{k.current&&clearTimeout(k.current)},[]),ae(p,J,{depth:0});const W=[{key:"skills",label:"Skills",count:s.length},{key:"agents",label:"Agents",count:d.length},{key:"commands",label:"Commands",count:h.length},{key:"mcp",label:"MCP server",count:u.length},{key:"hooks",label:"Hooks",count:e.hooks},{key:"monitors",label:"Monitors",count:e.monitors},{key:"lsp",label:"LSP",count:e.hasLsp?1:0},{key:"files",label:"Bin",count:m.length}],R=(O=e.manifest)!=null&&O.author?typeof e.manifest.author=="string"?e.manifest.author:e.manifest.author.name??null:null,_=async v=>{const M=await window.api.shell.open({as:"external",url:v});M.ok||q.error(M.error??`Failed to open ${v}`)};return E?t.jsx(Se,{pluginName:((j=e.manifest)==null?void 0:j.name)??e.name,skills:s,initialSelectedId:E.id,onBack:()=>C(null)},E.id):t.jsxs("div",{className:"flex flex-col h-full min-h-0 overflow-hidden",children:[t.jsxs("div",{className:"shrink-0 h-11 flex items-baseline gap-3.5 px-3 border-b border-line bg-bg",children:[t.jsx("button",{type:"button",onClick:i,className:"font-mono text-accent hover:underline shrink-0 text-xs",children:"← Plugins"}),t.jsx("span",{className:"font-serif text-[22px] text-fg shrink-0 truncate max-w-[16rem]",children:((H=e.manifest)==null?void 0:H.name)??e.name}),(B=e.manifest)!=null&&B.version?t.jsxs("span",{className:"font-mono text-fg-faint text-xs shrink-0",children:["v",e.manifest.version]}):null,(U=e.manifest)!=null&&U.description?t.jsx("span",{className:"text-fg-dim text-xs min-w-0 flex-1 overflow-hidden text-ellipsis whitespace-nowrap",children:e.manifest.description}):t.jsx("span",{className:"flex-1"}),t.jsxs("div",{className:"flex items-center gap-1.5 shrink-0",children:[t.jsx(re,{input:de(e)}),e.hasMcp?t.jsx(xe,{tone:"accent",children:"MCP"}):null]})]}),e.manifest?t.jsxs("div",{className:"shrink-0 h-[26px] flex items-center gap-[18px] px-3 bg-bg-elev border-b border-line text-[9px] font-mono uppercase tracking-wide overflow-hidden",children:[R?t.jsxs("span",{className:"text-fg-dim truncate",children:[t.jsx("span",{className:"text-fg-faint",children:"Author "}),R]}):null,e.manifest.license?t.jsxs("span",{className:"text-fg-dim truncate",children:[t.jsx("span",{className:"text-fg-faint",children:"License "}),e.manifest.license]}):null,e.manifest.homepage?t.jsxs("button",{onClick:()=>_(e.manifest.homepage),className:"text-accent hover:underline truncate normal-case",title:e.manifest.homepage,children:[t.jsx("span",{className:"text-fg-faint uppercase",children:"Homepage "}),e.manifest.homepage]}):null,t.jsx("span",{className:"ml-auto text-fg-faint truncate normal-case",children:e.path})]}):t.jsx("div",{className:"shrink-0 h-[26px] flex items-center px-3 bg-bg-elev border-b border-line text-[9px] font-mono uppercase tracking-wide overflow-hidden",children:t.jsx("span",{className:"ml-auto text-fg-faint truncate normal-case",children:e.path})}),t.jsxs("div",{className:"flex-1 min-h-0 grid overflow-hidden",style:{gridTemplateColumns:"170px 1fr"},children:[t.jsx("div",{className:"min-h-0 overflow-auto bg-bg-elev border-r border-line py-1",children:W.map(v=>t.jsxs("button",{type:"button",disabled:v.count===0,onClick:()=>F(v.key),className:`w-full text-left px-3 py-1.5 text-xs flex items-center justify-between ${v.count===0?"text-fg-faint opacity-50 cursor-default":D===v.key?"bg-bg-hi text-fg":"text-fg-dim hover:text-fg hover:bg-bg-hi"}`,children:[t.jsx("span",{children:v.label}),v.count>0?t.jsx("span",{className:"font-mono text-fg-faint",children:v.count}):null]},v.key))}),t.jsx("div",{className:"min-h-0 overflow-auto",children:b?t.jsx(S,{title:"scanning…"}):t.jsx(Me,{active:D,row:e,skills:s,agents:d,commands:h,mcpServers:u,files:m,onOpenSkill:C})})]})]})}function Me({active:e,row:n,skills:i,agents:s,commands:a,mcpServers:d,files:l,onOpenSkill:h}){return e==="skills"?i.length===0?t.jsx(S,{title:"no components"}):t.jsx("div",{children:i.map((o,u)=>t.jsx(L,{n:u+1,name:o.name??o.id,description:o.description,onClick:()=>h(o)},o.id))}):e==="agents"?s.length===0?t.jsx(S,{title:"no components"}):t.jsx("div",{children:s.map((o,u)=>t.jsx(L,{n:u+1,name:o.name??o.id,description:o.description},o.id))}):e==="commands"?a.length===0?t.jsx(S,{title:"no components"}):t.jsx("div",{children:a.map((o,u)=>t.jsx(L,{n:u+1,name:o.name??o.id,description:o.description},o.id))}):e==="mcp"?d.length===0?t.jsx(S,{title:"no components"}):t.jsx("div",{children:d.map((o,u)=>t.jsx(L,{n:u+1,name:o.name,description:o.description},o.id))}):e==="hooks"?n.hooks===0?t.jsx(S,{title:"no components"}):t.jsx("div",{children:t.jsx(L,{n:1,name:`${n.hooks} ${n.hooks===1?"hook":"hooks"} configured`,description:`${n.path}/hooks/hooks.json`})}):e==="monitors"?n.monitors===0?t.jsx(S,{title:"no components"}):t.jsx("div",{children:t.jsx(L,{n:1,name:`${n.monitors} ${n.monitors===1?"monitor":"monitors"} configured`,description:`${n.path}/monitors/monitors.json`})}):e==="lsp"?n.hasLsp?t.jsx("div",{children:t.jsx(L,{n:1,name:"LSP server enabled",description:`${n.path}/.lsp.json`})}):t.jsx(S,{title:"no components"}):l.length===0?t.jsx(S,{title:"no components"}):t.jsx("div",{children:l.map((o,u)=>t.jsx(L,{n:u+1,name:o,description:null},o))})}function L({n:e,name:n,description:i,onClick:s}){const a=s?"button":"div";return t.jsxs(a,{onClick:s,className:`w-full flex items-baseline gap-2.5 py-[9px] px-3 border-b border-line text-left min-w-0 ${s?"hover:bg-bg-hi cursor-pointer":""}`,children:[t.jsx("span",{className:"font-serif text-fg-faint text-xs shrink-0 w-6 text-right",children:String(e).padStart(2,"0")}),t.jsxs("div",{className:"min-w-0 flex-1",children:[t.jsx("div",{className:"font-mono font-semibold text-accent truncate",children:n}),i?t.jsx("div",{className:"text-fg-dim text-xs truncate",children:i}):null]})]})}const Le=4;async function De(e,n,i){const s=new Array(e.length);let a=0;const d=Array.from({length:Math.min(n,e.length)},async()=>{for(;a<e.length;){const l=a++;s[l]=await i(e[l])}});return await Promise.all(d),s}function Re(e,n){return{name:e.name,path:e.path,mtimeMs:e.mtimeMs,hasManifest:!1,manifest:null,hasLsp:!1,monitors:0,hooks:0,agents:0,commands:0,skills:0,binCount:0,hasMcp:!1,error:n}}async function _e(e){const{hasManifest:n,manifest:i}=await ue(e.path),[s,a]=await Promise.all([window.api.config.exists(`${e.path}/.lsp.json`),window.api.config.exists(`${e.path}/monitors/monitors.json`)]);let d=0;if(a){const m=await window.api.config.readJson(`${e.path}/monitors/monitors.json`);Array.isArray(m.data)?d=m.data.length:m.data&&typeof m.data=="object"&&Array.isArray(m.data.monitors)&&(d=m.data.monitors.length)}const[l,h,o]=await Promise.all([me(e.path,i),K(`${e.path}/bin`,{filesOnly:!0}),oe(e.path)]),u=h.length,N=o?(await ce(o)).length:0;return{name:e.name,path:e.path,mtimeMs:e.mtimeMs,hasManifest:n,manifest:i,hasLsp:s,monitors:d,hooks:l.hooks,agents:l.agentFiles.length,commands:l.commandFiles.length,skills:N,binCount:u,hasMcp:l.mcpServers.length>0}}async function ue(e){let n=`${e}/.claude-plugin/plugin.json`,i=await window.api.config.exists(n);if(i||(n=`${e}/plugin.json`,i=await window.api.config.exists(n)),!i)return{hasManifest:i,manifest:null};const s=await window.api.config.readJson(n),a=s.exists&&!s.parseError&&s.data&&typeof s.data=="object"&&!Array.isArray(s.data);return{hasManifest:i,manifest:a?s.data:null}}const P=e=>!!e&&typeof e=="object"&&!Array.isArray(e);function Oe(e,n){const i=n.startsWith("/")?n.startsWith(`${e}/`)?n.slice(e.length+1):null:n;if(i===null)return se(n);const s=[];for(const a of i.split("/"))if(!(a===""||a===".")){if(a!=="..")s.push(a);else if(s.pop()===void 0)return se(n)}return s.length>0?`${e}/${s.join("/")}`:e}function se(e){return console.warn(`[plugins] ignoring manifest path outside the plugin root: ${e}`),null}function Fe(e){return typeof e=="string"?[e]:Array.isArray(e)?e.filter(n=>typeof n=="string"):[]}function Te(e){if(!P(e))return null;if(P(e.mcpServers))return e.mcpServers;const n=Object.values(e);return n.length>0&&n.every(s=>P(s)&&(typeof s.command=="string"||typeof s.url=="string"))?e:null}function Be(e){if(!P(e))return 0;const n=P(e.hooks)?e.hooks:e;return Object.values(n).reduce((i,s)=>Array.isArray(s)?i+s.reduce((a,d)=>a+(P(d)&&Array.isArray(d.hooks)?d.hooks.length:0),0):i,0)}async function me(e,n){const i=(b,f)=>{const p=new Set;for(const w of Fe(b)){const y=Oe(e,w);y&&p.add(y)}return p.add(`${e}/${f}`),[...p]},s=async b=>{const f=new Set;for(const p of b)if(p.endsWith(".md"))f.add(p);else for(const w of await K(p,{filesOnly:!0}))w.endsWith(".md")&&f.add(`${p}/${w}`);return[...f]},a=async b=>{try{const f=await window.api.config.readJson(b);return f.exists&&!f.parseError?f.data:null}catch{return null}},d=i(n==null?void 0:n.commands,"commands"),l=i(n==null?void 0:n.agents,"agents"),h=n==null?void 0:n.hooks,o=i(typeof h=="string"||Array.isArray(h)?h:void 0,"hooks/hooks.json"),u=n==null?void 0:n.mcpServers,N=i(typeof u=="string"||Array.isArray(u)?u:void 0,".mcp.json"),[m,I,D,F]=await Promise.all([s(d),s(l),Promise.all(o.map(a)),Promise.all(N.map(a))]),E=[...P(h)?[h]:[],...D].reduce((b,f)=>b+Be(f),0),C=new Map;for(const b of[...P(u)?[u]:[],...F])for(const[f,p]of Object.entries(Te(b)??{})){if(C.has(f))continue;const w=P(p)?p.command:void 0,y=P(p)?p.url:void 0;C.set(f,{id:f,name:f,description:typeof w=="string"?w:typeof y=="string"?y:null})}return{commandFiles:m,agentFiles:I,hooks:E,mcpServers:[...C.values()],sourcePaths:[...d,...l,...o,...N]}}async function ie(e){const n=await Promise.all(e.map(s=>window.api.config.readText(s))),i=[];return e.forEach((s,a)=>{if(!n[a].exists)return;const d=s.slice(s.lastIndexOf("/")+1),l=le(n[a].text);i.push({id:s,name:l.name??d.replace(/\.md$/,""),description:l.description})}),i}async function K(e,n){try{return(await window.api.config.listDir(e,n)).entries.map(s=>s.name)}catch{return[]}}export{Xe as Plugins};
@@ -1,2 +0,0 @@
1
- import{aF as a,b3 as ce,aX as de,b5 as ue,aW as E,aZ as d,a_ as fe,ap as s,n as T}from"./index-t37UuEZu.js";import{P as I}from"./Panel-BkfK-W74.js";import{L as me}from"./ListDetail-DcAD_cuA.js";import{M as pe}from"./MarkdownEditor-D7JTNOOp.js";import{S as he}from"./SaveBar-0aiuy1L2.js";import{S as K}from"./ScopeSwitcher-DR262W_R.js";import{T as xe}from"./Toggle-W944m375.js";import{P as Q}from"./ProvenanceBadge-CQXSiPHq.js";import{l as ve}from"./listSkills-C1aWKf0T.js";import{S as ge,V}from"./Library-Dl71nylN.js";import{p as ke,r as je,s as be}from"./skillFrontmatter-Dif5JIg7.js";import"./monaco-editor-BsIlgG7c.js";import"./Button-mj0vvcdc.js";const Se=250,we=2e3;function ye(m,p){return{user:{skills:`${m}/.claude/skills`,commands:`${m}/.claude/commands`},project:p?{skills:`${p}/.claude/skills`,commands:`${p}/.claude/commands`}:null}}function Ce(){const m=ce(),p=de(),x=(p==null?void 0:p.cwd)??null,v=ue(t=>t.navFace),S=a.useRef(!1),B=a.useRef(v),[u,$]=a.useState(()=>v==="project"&&x?"project":"user"),[f,w]=a.useState([]),[o,D]=a.useState(null),[y,L]=a.useState("installed"),[O,Y]=a.useState(""),[q,H]=a.useState([]),[U,F]=a.useState(null),C=a.useMemo(()=>m?ye(m,x):null,[m,x]);a.useEffect(()=>{if(B.current!==v){if(B.current=v,S.current){S.current=!1;return}$(v==="project"&&x?"project":"user")}},[v,x]);const c=a.useMemo(()=>C?u==="user"?C.user:C.project:null,[u,C]),P=a.useRef(0),N=a.useCallback(async()=>{const t=++P.current;if(!c){w([]),H([]);return}const l=[],n=[];try{const e=await ve(c.skills);n.push(...e.errors);for(const r of e.entries)l.push({kind:"skills",scope:u,name:r.name,path:r.path,dir:r.dir,disabled:je(r.text),description:ke(r.text).description??void 0})}catch(e){n.push({path:c.skills,error:e instanceof Error?e.message:String(e)})}try{const e=await window.api.config.listDir(c.commands,{filesOnly:!0});e.ok||n.push({path:c.commands,error:e.error??"failed to list directory"});for(const r of e.entries)r.name.endsWith(".md")&&l.push({kind:"commands",scope:u,name:r.name.replace(/\.md$/,""),path:r.path,dir:null,disabled:!1})}catch(e){n.push({path:c.commands,error:e instanceof Error?e.message:String(e)})}if(P.current===t){for(const e of n)E.error(`Could not read ${e.path}: ${e.error}`);H(n),l.sort((e,r)=>e.kind===r.kind?e.name.localeCompare(r.name):e.kind==="skills"?-1:1),w(l),D(e=>{var r;return l.find(i=>i.path===e)?e:((r=l[0])==null?void 0:r.path)??null})}},[c,u]);a.useEffect(()=>{N()},[N]),a.useEffect(()=>()=>{P.current+=1},[]);const X=a.useRef(N);X.current=N;const Z=a.useRef(f);Z.current=f;const z=a.useRef(o);z.current=o;const g=a.useRef(null),W=a.useRef(!1),A=a.useRef(!1),M=a.useCallback(async()=>{if(W.current){A.current=!0;return}W.current=!0;try{await X.current()}finally{W.current=!1}A.current&&(A.current=!1,M())},[]);a.useEffect(()=>()=>{g.current&&clearTimeout(g.current)},[]);const ee=a.useCallback(t=>{var r;const l=z.current,n=l?Z.current.find(i=>i.path===l):null,e=l?(r=d.getState().files[l])==null?void 0:r.lastSavedAt:null;n!=null&&n.dir&&e&&Date.now()-e<we&&(t===n.dir||n.dir.startsWith(`${t}/`))||(g.current&&clearTimeout(g.current),g.current=setTimeout(()=>{g.current=null,M()},Se))},[M]);fe(c?[c.skills,c.commands]:[],ee);const b=d(t=>t.files),te=d(t=>t.loadText),se=d(t=>t.setDraft),re=d(t=>t.saveText),ae=d(t=>t.revert),ne=d(t=>t.watchFile),G=d(t=>t.unwatchFile);async function le(t,l){const n=await window.api.config.readText(t.path);if(!n.exists)return;const e=be(n.text,l);if(e===n.text)return;const r=await window.api.config.writeText(t.path,e);if(!r.ok){E.error(r.error??"failed to update skill");return}w(i=>i.map(j=>j.path===t.path?{...j,disabled:l}:j)),d.getState().files[t.path]&&d.getState().loadText(t.path,!0)}async function oe(t){if(!t.dir)return;F(null);const l=await window.api.files.delete(t.dir);if(!l.ok){E.error(l.error??"failed to remove skill");return}E.info(`Removed "${t.name}" — moved to trash`),G(t.path),w(n=>{const e=n.filter(r=>r.path!==t.path);return D(r=>{var i;return r!==t.path?r:((i=e[0])==null?void 0:i.path)??null}),e})}a.useEffect(()=>{if(o)return b[o]||te(o),ne(o),()=>G(o)},[o]);const[ie,R]=a.useState(null);if(!m)return s.jsx(T,{title:"loading…"});if(y==="library")return s.jsx(I,{toolbar:s.jsx(V,{active:y,onChange:L,installedLabel:"Installed",libraryLabel:"Library"}),children:s.jsx(ge,{})});if(u==="project"&&!x)return s.jsx(I,{toolbar:s.jsxs(s.Fragment,{children:[s.jsx(V,{active:y,onChange:L}),s.jsx("span",{className:"mx-2 text-fg-faint",children:"·"}),s.jsx(K,{scopes:["user","project"],active:u,onChange:t=>{S.current=!0,$(t)}})]}),children:s.jsx(T,{title:"no active project",hint:"open a tab in a project directory to view project skills & commands"})});const h=f.find(t=>t.path===o)??null,k=o?b[o]:null;return s.jsx(I,{toolbar:s.jsxs(s.Fragment,{children:[s.jsx(V,{active:y,onChange:L}),s.jsx("span",{className:"mx-2 text-fg-faint",children:"·"}),s.jsx(K,{scopes:["user","project"],active:u,onChange:t=>{S.current=!0,$(t)}}),s.jsxs("span",{className:"ml-3 text-fg-faint",children:[f.length," ",f.length===1?"item":"items"]}),s.jsx("div",{className:"flex-1"}),h&&s.jsx(Q,{scope:h.scope,input:{type:h.kind==="commands"?"command":"skill",name:h.name}}),s.jsx("span",{className:"ml-2 text-fg-faint truncate",children:(h==null?void 0:h.path)??""})]}),footer:o&&k?s.jsx(he,{dirty:k.dirty,busy:k.busy,parseError:ie,lastSavedAt:k.lastSavedAt,onSave:async()=>{R(null);const t=await re(o);t.ok||R(t.error??"save failed")},onRevert:()=>{R(null),ae(o)}}):null,children:s.jsx(me,{sidebar:s.jsxs("div",{className:"py-1",children:[s.jsx("div",{className:"px-2 pb-1",children:s.jsx("input",{value:O,onChange:t=>Y(t.target.value),placeholder:"filter…",className:"w-full bg-bg border border-line rounded px-2 py-0.5 text-xs text-fg"})}),["skills","commands"].map(t=>{const l=O.toLowerCase(),n=f.filter(e=>e.kind===t&&(!l||e.name.toLowerCase().includes(l)));return s.jsxs("div",{className:"mb-3",children:[s.jsx("div",{className:"px-3 py-1 text-xs uppercase tracking-wider text-fg-faint",children:t==="skills"?"Skills":"Slash Commands"}),n.length===0?s.jsx("div",{className:"px-3 py-1 text-xs text-fg-faint italic",children:"none"}):n.map(e=>{var i,j,J;const r=e.kind==="skills";return s.jsxs("div",{className:`w-full px-3 py-1 text-xs flex items-center justify-between gap-2 ${o===e.path?"bg-bg-hi text-fg":"text-fg-dim hover:text-fg hover:bg-bg-hi"}`,children:[s.jsxs("button",{onClick:()=>D(e.path),className:"flex-1 min-w-0 text-left",children:[s.jsxs("div",{className:`truncate ${e.disabled?"line-through opacity-50":""}`,title:e.disabled?"Disabled — Claude will not auto-invoke this skill":void 0,children:[e.kind==="commands"?"/":"",e.name]}),e.description&&s.jsx("div",{className:"truncate text-fg-faint",children:e.description})]}),s.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[s.jsx(Q,{interactive:!1,scope:e.scope,input:{type:e.kind==="commands"?"command":"skill",name:e.name}}),((i=b[e.path])==null?void 0:i.dirty)&&s.jsx("span",{className:"w-1 h-1 rounded-full bg-accent"}),r&&s.jsx("span",{title:(j=b[e.path])!=null&&j.dirty?"This skill has unsaved edits — save or revert before toggling":void 0,children:s.jsx(xe,{checked:!e.disabled,disabled:!!((J=b[e.path])!=null&&J.dirty),onChange:_=>void le(e,!_)})}),e.kind==="skills"&&U===e.path&&s.jsxs("span",{className:"flex items-center gap-1",children:[s.jsx("button",{onClick:()=>void oe(e),title:`Remove ${e.name} — moves the folder to trash; reinstall from the Library`,className:"text-[10px] font-semibold text-red-400 hover:text-red-300",children:"confirm"}),s.jsx("button",{onClick:()=>F(null),title:"Cancel",className:"text-[10px] text-fg-faint hover:text-fg",children:"cancel"})]}),e.kind==="skills"&&U!==e.path&&s.jsx("button",{onClick:_=>{_.stopPropagation(),F(e.path)},title:"Remove skill — moves the folder to trash; reinstall from the Library","aria-label":`Remove ${e.name}`,className:"text-fg-faint hover:text-red-400 leading-none px-0.5",children:"✕"})]})]},e.path)})]},t)})]}),detail:o&&k?s.jsx("div",{className:"h-full",children:s.jsx(pe,{path:o,value:k.draftRaw,onChange:t=>{R(null),se(o,t)}})}):f.length===0&&q.length>0?s.jsx("div",{"data-testid":"skills-list-error",children:s.jsx(T,{title:"could not list skills or commands",hint:q.map(t=>`${t.path}: ${t.error}`).join(`
2
- `)})}):s.jsx(T,{title:f.length===0?"no skills or commands":"select an item"})})})}const Ie=a.memo(Ce);export{Ie as Skills};
@@ -1 +0,0 @@
1
- import{aF as i,aZ as g,ap as e,a1 as R,aW as O,b2 as _,an as B,ao as I,aS as V,a6 as $,e as z,h as M,t as D,s as T,l as H,ab as W,b3 as Z,C as q,n as A,aa as G}from"./index-t37UuEZu.js";import{P as F}from"./Panel-BkfK-W74.js";import{S as J}from"./SaveBar-0aiuy1L2.js";import{f as K,V as P}from"./Library-Dl71nylN.js";import"./monaco-editor-BsIlgG7c.js";import"./Button-mj0vvcdc.js";import"./listSkills-C1aWKf0T.js";const Q=300;function X({activePath:s,selectedPath:o,onSelect:f}){const[l,a]=i.useState([]),h=i.useRef(0),r=i.useRef(f);r.current=f;const y=g(n=>{var d;return s?(d=n.files[s])==null?void 0:d.diskRaw:void 0}),u=i.useRef(null);if(i.useEffect(()=>{r.current(null)},[s]),i.useEffect(()=>{if(h.current+=1,!s){u.current=null,a([]);return}const n=u.current!==s;u.current=s;let d=!1;const m=()=>{h.current+=1;const b=h.current;window.api.config.parseImports(s).then(v=>{d||h.current!==b||(v.ok?a(v.imports):(a([]),O.error(v.error||"failed to parse @-imports")))})},j=n?null:setTimeout(m,Q);return n&&m(),()=>{d=!0,j&&clearTimeout(j)}},[s,y]),l.length===0||!s)return null;const x=o===s||o===null;return e.jsxs("div",{className:"w-64 shrink-0 border-r border-line bg-bg-elev overflow-auto","data-testid":"referenced-files-rail",children:[e.jsxs("div",{className:"px-3 py-2 text-[10px] uppercase tracking-wide text-fg-faint border-b border-line",children:["Documents · ",l.length+1]}),e.jsxs("button",{type:"button",onClick:()=>f(null),"aria-current":x,"data-testid":"referenced-file-root",className:`w-full text-left px-3 py-2 border-b border-line ${x?"bg-bg-hi text-fg":"text-fg-dim hover:bg-bg"}`,children:[e.jsx("div",{className:"text-[11.5px] font-medium truncate",children:R(s)}),e.jsx("div",{className:"text-[10px] text-fg-faint truncate",title:s,children:"this system prompt"})]}),l.map(n=>{const d=!n.ok||!n.exists,m=o===n.path;return e.jsxs("button",{type:"button",onClick:()=>f(n),"aria-current":m,"data-testid":"referenced-file-row",className:`w-full text-left px-3 py-2 border-b border-line last:border-b-0 ${m?"bg-bg-hi text-fg":"text-fg-dim hover:bg-bg"}`,children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"text-[11.5px] font-medium truncate flex-1",children:R(n.path)}),d&&e.jsx("span",{className:"shrink-0 px-1.5 py-0.5 rounded text-[9px] uppercase tracking-wide text-amber-400/90 border border-amber-400/30","data-testid":"referenced-file-missing",children:"missing"})]}),e.jsx("div",{className:"text-[10px] text-fg-faint truncate",title:n.path,children:n.path}),e.jsxs("div",{className:"text-[10px] text-fg-faint",children:[n.sizeBytes.toLocaleString()," bytes · ~",n.tokenEstimate.toLocaleString()," tokens"]})]},n.path)})]})}function Y({path:s,value:o,onChange:f,onSave:l,readOnly:a,defaultMode:h,headerRight:r,hideStatusBar:y}){const u=_(),x=B(s),n=I(s),d=V(s),[m,j]=i.useState(()=>a&&n?"preview":h??$(s)),[b,v]=i.useState(!0),[w,L]=i.useState(null),S=i.useRef(null),c=i.useRef(null),k=i.useCallback(t=>{S.current=t},[]),E=i.useCallback(()=>S.current,[]),C=a?n?["preview","edit"]:[]:d?["edit","preview","split"]:n?["edit","preview"]:[],p=n?m:"edit",N=e.jsx(z,{path:s,name:R(s),value:o,onChange:f,onSave:()=>l==null?void 0:l(),onReady:k,onCursor:L,readOnly:a});return e.jsxs("div",{className:"flex flex-col h-full min-h-0","data-testid":"document-editor-pane",children:[e.jsxs("div",{className:"flex items-center gap-1 px-2 h-7 shrink-0 border-b border-line bg-bg-elev",children:[e.jsx("span",{className:"text-[11px] font-medium text-fg truncate",children:R(s)}),a&&e.jsx("span",{className:"ml-1 px-1.5 py-0.5 rounded text-[9px] uppercase tracking-wide text-fg-faint border border-line",children:"read-only"}),e.jsx("div",{className:"flex-1"}),r,x&&(p==="preview"||p==="split")&&e.jsx("button",{onClick:()=>v(t=>!t),"data-testid":"document-outline-toggle",className:`px-2 py-0.5 text-[10px] border border-line rounded ${b?"bg-bg-hi text-fg":"text-fg-faint hover:text-fg"}`,title:"Toggle document outline",children:"Outline"}),C.length>0&&e.jsx("div",{className:"flex items-center ml-1 rounded border border-line overflow-hidden","data-testid":"document-mode-toggle",children:C.map(t=>e.jsx("button",{onClick:()=>j(t),className:`px-2 py-0.5 text-[10px] capitalize transition-colors ${p===t?"bg-bg-hi text-fg":"text-fg-faint hover:text-fg"}`,children:t},t))})]}),e.jsx("div",{className:"flex-1 min-h-0",children:p==="split"&&x?e.jsxs("div",{className:"flex h-full",children:[b&&e.jsx(M,{text:o,scrollRef:c}),e.jsxs("div",{className:"flex-1 min-w-0 flex flex-col border-r border-line",children:[!a&&e.jsx(D,{getEditor:E}),e.jsx("div",{className:"flex-1 min-h-0",children:N})]}),e.jsx("div",{className:"flex-1 min-w-0",children:e.jsx(T,{ref:c,text:o,flush:!0,wideMeasure:u.wideMeasure})})]}):p==="preview"&&x?e.jsxs("div",{className:"flex h-full",children:[b&&e.jsx(M,{text:o,scrollRef:c}),e.jsx("div",{className:"flex-1 min-w-0",children:e.jsx(T,{ref:c,text:o,wideMeasure:u.wideMeasure})})]}):x?e.jsxs("div",{className:"flex flex-col h-full",children:[!a&&e.jsx(D,{getEditor:E}),e.jsx("div",{className:"flex-1 min-h-0",children:N})]}):N}),!y&&e.jsx(H,{text:o,cursor:w,language:W(s)||void 0})]})}const U={title:"User system prompt",body:"This is the real ~/.claude/CLAUDE.md on disk — the instructions the claude CLI loads into every session it starts on this machine, in every project. A project's own CLAUDE.md / CLAUDE.local.md are read from that project's directory when a session launches there; they are not edited here."};function ee(){const s=Z(),[o,f]=i.useState("installed"),l=i.useMemo(()=>s?q.resolve("user",s,null):null,[s]),[a,h]=i.useState(null),r=(a==null?void 0:a.path)??l,y=!!a&&(!a.ok||!a.exists),u=g(t=>t.files),x=g(t=>t.loadText),n=g(t=>t.setDraft),d=g(t=>t.saveText),m=g(t=>t.revert),j=g(t=>t.watchFile),b=g(t=>t.unwatchFile);i.useEffect(()=>{if(l)return x(l,!0),j(l),()=>{b(l)}},[l]),i.useEffect(()=>{if(!(!r||r===l))return x(r,!0),j(r),()=>{b(r)}},[r,l]);const[v,w]=i.useState(null),L=i.useCallback(t=>{w(null),h(t)},[]);if(!s)return e.jsx(A,{title:"loading…"});if(o==="library")return e.jsx(F,{toolbar:e.jsx(P,{active:o,onChange:f,installedLabel:"Editor",libraryLabel:"Presets"}),children:e.jsx(K,{})});const S=l?u[l]:null,c=r?u[r]:null,k=(c==null?void 0:c.draftRaw)??"",E=G(k),C=k.length,p=y,N=async()=>{if(!r)return;w(null);const t=await d(r);t.ok||w(t.error??"save failed")};return e.jsx(F,{toolbar:e.jsxs(e.Fragment,{children:[e.jsx(P,{active:o,onChange:f,installedLabel:"Editor",libraryLabel:"Presets"}),e.jsx("span",{className:"mx-2 text-fg-faint",children:"·"}),e.jsx("span",{className:"text-fg-dim",children:"User scope"}),e.jsx("span",{className:"ml-3 text-fg-faint truncate",children:r??"—"}),e.jsx("div",{className:"flex-1"}),e.jsxs("span",{className:"text-fg-faint",children:[C.toLocaleString()," chars · ~",E.toLocaleString()," tokens"]})]}),footer:r&&c&&!p?e.jsx(J,{dirty:c.dirty,busy:c.busy,parseError:v,lastSavedAt:c.lastSavedAt,leading:c.exists?a?e.jsx("span",{children:"editing an imported file"}):null:e.jsx("span",{children:"file will be created on save"}),onSave:N,onRevert:()=>{w(null),m(r)}}):null,children:l&&S?e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsxs("div",{"data-testid":"system-prompt-scope-note",className:"shrink-0 border-b border-line bg-bg-elev px-3 py-2 text-[11.5px] leading-snug",children:[e.jsx("span",{className:"font-semibold text-fg",children:U.title}),e.jsx("span",{className:"mx-1.5 text-fg-faint",children:"·"}),e.jsx("span",{className:"text-fg-dim",children:U.body}),e.jsx("span",{className:"ml-1.5 font-mono text-fg-faint",children:l})]}),e.jsxs("div",{className:"flex-1 min-h-0 flex",children:[e.jsx(X,{activePath:l,selectedPath:r,onSelect:L}),e.jsxs("div",{className:"flex-1 min-w-0 flex flex-col",children:[p&&e.jsx("div",{"data-testid":"system-prompt-missing-note",className:"shrink-0 border-b border-line bg-bg-elev px-3 py-1.5 text-[11px] text-amber-400/90",children:"This import does not resolve to a readable file — the CLI will skip it."}),r&&e.jsx("div",{className:"flex-1 min-h-0",children:e.jsx(Y,{path:r,value:k,readOnly:p,defaultMode:"split",onChange:t=>{w(null),n(r,t)},onSave:()=>{N()}},r)})]})]})]}):e.jsx(A,{title:"resolving…"})})}const oe=i.memo(ee);export{oe as SystemPrompt};
@@ -1 +0,0 @@
1
- import{aF as r,V as p,ap as e,n as k,aV as w,aW as b,a0 as y}from"./index-t37UuEZu.js";import{P}from"./Panel-BkfK-W74.js";import{L as E}from"./ListDetail-DcAD_cuA.js";import{u as S,a as v,t as N}from"./useAgentsDirWatch-D0rI9G_h.js";import"./monaco-editor-BsIlgG7c.js";function $(){const[s,i]=r.useState(p[0].tag),[l,g]=r.useState(null),[h,x]=r.useState(!1),c=r.useRef(!0);r.useEffect(()=>()=>{c.current=!1},[]);const f=r.useRef(0),o=async()=>{const t=++f.current;try{const n=await window.api.agents.listPersonas();c.current&&f.current===t&&g(n)}catch(n){if(!c.current||f.current!==t)return;g([]),b.error(n.message||"failed to load agent personas")}};r.useEffect(()=>{o()},[]),r.useEffect(()=>window.api.agents.onChanged(()=>o()),[]),S(null,()=>o());const m=p.find(t=>t.tag===s)??null,a=async(t,n)=>{try{await window.api.agents.savePersona(v(t,{tags:N([...t.tags,n])})),x(!1),await o()}catch(d){b.error(d.message||"failed to assign tag")}},u=async(t,n)=>{try{await window.api.agents.savePersona(v(t,{tags:N(t.tags.filter(d=>d!==n))})),await o()}catch(d){b.error(d.message||"failed to remove tag")}};return e.jsx(P,{toolbar:e.jsxs("span",{className:"text-fg-faint",children:[p.length," tag",p.length===1?"":"s"]}),children:e.jsx(E,{sidebar:e.jsx("div",{className:"py-1",children:p.map(t=>{const n=w(t.tag),d=s===t.tag,j=(l==null?void 0:l.filter(T=>T.tags.includes(t.tag)).length)??0;return e.jsxs("button",{onClick:()=>{i(t.tag),x(!1)},className:`w-full text-left px-3 py-1.5 text-xs flex items-center gap-2 border-l-2 ${d?"bg-bg-hi text-fg border-accent":"text-fg-dim hover:text-fg hover:bg-bg-hi border-transparent"}`,children:[e.jsxs("span",{className:`px-1.5 py-0.5 rounded text-[10px] font-mono font-semibold ${n.bg} ${n.text} ${n.border?"border border-current/30":""}`,children:["#",t.tag]}),e.jsx("span",{className:"truncate",children:t.label}),j>0&&e.jsx("span",{className:"ml-auto text-[10.5px] text-fg-faint font-mono shrink-0",children:j})]},t.tag)})}),detail:m?e.jsx(C,{entry:m,personas:l,adding:h,setAdding:x,onAssign:a,onUnassign:u}):e.jsx(k,{title:"select a tag"})})})}const q=r.memo($);function C({entry:s,personas:i,adding:l,setAdding:g,onAssign:h,onUnassign:x}){const c=w(s.tag),f=y(s.tag),o=(i==null?void 0:i.filter(a=>a.tags.includes(s.tag)))??[],m=(i==null?void 0:i.filter(a=>!a.tags.includes(s.tag)))??[];return e.jsxs("div",{className:"p-4 space-y-4 max-w-3xl",children:[e.jsxs("div",{className:"flex items-center gap-2.5",children:[e.jsxs("span",{className:`px-2 py-1 rounded text-xs font-mono font-semibold ${c.bg} ${c.text} ${c.border?"border border-current/30":""}`,children:["#",s.tag]}),e.jsx("span",{className:"text-sm font-semibold text-fg",children:s.label})]}),e.jsx("div",{className:"text-xs text-fg-dim leading-relaxed",children:s.description}),e.jsxs("div",{children:[e.jsx("div",{className:"text-[10.5px] uppercase tracking-wide text-fg-faint mb-1.5 font-mono",children:"/develop eagerness"}),e.jsx("span",{className:"px-1.5 py-0.5 text-[10px] rounded border border-line text-fg-dim font-mono",children:s.developEagerness})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-[10.5px] uppercase tracking-wide text-fg-faint mb-1.5 font-mono",children:"develops via"}),e.jsx("span",{className:"px-1.5 py-0.5 text-[10px] rounded border border-line text-fg-dim font-mono",children:s.developsVia})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-[10.5px] uppercase tracking-wide text-fg-faint mb-1.5 font-mono",children:"agents carrying this tag"}),i===null?e.jsx("div",{className:"text-xs text-fg-faint italic",children:"loading…"}):e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5",children:[o.map(a=>e.jsxs("span",{className:"inline-flex items-center gap-1.5 bg-bg-elev border border-line rounded px-2 py-0.5 text-[11px] font-mono text-fg-dim",children:[a.name,e.jsx("button",{onClick:()=>x(a,s.tag),title:"Remove this tag from the agent",className:"text-fg-faint hover:text-fg",children:"×"})]},a.name)),o.length===0&&!l&&e.jsx("span",{className:"text-xs text-fg-faint italic mr-1",children:"no agent carries this tag yet."}),l?m.length>0?e.jsxs("select",{autoFocus:!0,defaultValue:"",onChange:a=>{const u=i.find(t=>t.name===a.target.value);u&&h(u,s.tag)},onBlur:()=>g(!1),className:"bg-bg border border-line rounded px-2 py-0.5 text-[11px] text-fg font-mono",children:[e.jsx("option",{value:"",disabled:!0,children:"pick an agent…"}),m.map(a=>e.jsx("option",{value:a.name,children:a.name},a.name))]}):e.jsx("span",{className:"text-xs text-fg-faint italic",children:"every agent already carries this tag."}):e.jsx("button",{onClick:()=>g(!0),className:"px-2 py-0.5 rounded-full text-[11px] font-mono border border-line text-fg-faint hover:text-fg hover:bg-bg-hi",children:"+ assign agent"})]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-[10.5px] uppercase tracking-wide text-fg-faint mb-1.5 font-mono",children:"opening framing — sent before the human's goal"}),e.jsx("pre",{className:"text-xs text-fg-dim whitespace-pre-wrap bg-bg-elev border border-line rounded p-3 leading-relaxed font-sans",children:f.initialPromptTemplate})]})]})}export{q as TagLibrary};
@@ -1,10 +0,0 @@
1
- const f=/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/,a="disable-model-invocation",$=/^\s*disable-model-invocation\s*:/;function E(t){const n=t.match(f);if(!n)return!1;for(const e of n[1].split(/\r?\n/)){if(!$.test(e))continue;const l=e.slice(e.indexOf(":")+1).trim().toLowerCase();return l==="true"||l==="yes"}return!1}function k(t){const n=t.trim();return n.length>=2&&(n[0]==='"'&&n[n.length-1]==='"'||n[0]==="'"&&n[n.length-1]==="'")?n.slice(1,-1):n}function p(t){return t.length-t.trimStart().length}function S(t){const n=t.match(f);if(!n)return{name:null,description:null,body:t};const e=n[1].split(/\r?\n/),l=n[2]??"";let s=null,r=null;for(let i=0;i<e.length;i++){const m=e[i],d=m.match(/^(\s*)(name|description)\s*:(.*)$/);if(!d)continue;const[,,g,y]=d,o=y.trim(),b=p(m);let u;if(o===""||o===">-"||o===">"||o==="|-"||o==="|"){const h=[];let c=i+1;for(;c<e.length&&e[c].trim()!==""&&p(e[c])>b;)h.push(e[c].trim()),c++;u=h.join(" ")}else u=k(o);g==="name"?s=u:r=u}return{name:s,description:r,body:l}}function v(t,n){const e=t.match(f);if(!e){if(!n)return t;const i=t.startsWith(`
2
- `)?"":`
3
- `;return`---
4
- ${a}: true
5
- ---
6
- ${i}${t}`}const l=e[2]??"",s=e[1].split(/\r?\n/),r=s.findIndex(i=>$.test(i));if(n)r>=0?s[r]=`${a}: true`:s.push(`${a}: true`);else{if(r<0)return t;s.splice(r,1)}return`---
7
- ${s.join(`
8
- `)}
9
- ---
10
- ${l}`}export{S as p,E as r,v as s};