kiro-memory 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -83,7 +83,7 @@ kiro-memory install --cline # Cline (instructions + MCP)
83
83
  Or from source:
84
84
 
85
85
  ```bash
86
- git clone https://github.com/auriti-web-design/kiro-memory.git
86
+ git clone https://github.com/Auriti-Labs/kiro-memory.git
87
87
  cd kiro-memory
88
88
  npm install && npm run build
89
89
  npm run install:kiro
@@ -441,7 +441,7 @@ Kiro Memory runs **locally only** on `127.0.0.1` and implements multiple layers
441
441
  - **Input Validation** on all POST endpoints (type checking, length limits, safe character patterns)
442
442
  - **SSE Connection Limit** (max 50 concurrent clients)
443
443
 
444
- To report a security vulnerability, please open a [private security advisory](https://github.com/auriti-web-design/kiro-memory/security/advisories/new).
444
+ To report a security vulnerability, please open a [private security advisory](https://github.com/Auriti-Labs/kiro-memory/security/advisories/new).
445
445
 
446
446
  ## Contributing
447
447
 
@@ -453,7 +453,7 @@ Contributions are welcome. Please open an issue to discuss proposed changes befo
453
453
 
454
454
  ---
455
455
 
456
- Built by [auriti-web-design](https://github.com/auriti-web-design)
456
+ Built by [Auriti Labs](https://github.com/Auriti-Labs)
457
457
 
458
458
  ---
459
459
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kiro-memory",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "description": "Persistent cross-session memory for AI coding assistants. Works with Claude Code, Cursor, Windsurf, Cline, and any MCP-compatible editor.",
5
5
  "keywords": [
6
6
  "kiro",
@@ -18,15 +18,15 @@
18
18
  "typescript",
19
19
  "ai-tools"
20
20
  ],
21
- "author": "auriti-web-design",
21
+ "author": "Auriti Labs",
22
22
  "license": "AGPL-3.0",
23
23
  "repository": {
24
24
  "type": "git",
25
- "url": "https://github.com/auriti-web-design/kiro-memory.git"
25
+ "url": "https://github.com/Auriti-Labs/kiro-memory.git"
26
26
  },
27
- "homepage": "https://github.com/auriti-web-design/kiro-memory#readme",
27
+ "homepage": "https://github.com/Auriti-Labs/kiro-memory#readme",
28
28
  "bugs": {
29
- "url": "https://github.com/auriti-web-design/kiro-memory/issues"
29
+ "url": "https://github.com/Auriti-Labs/kiro-memory/issues"
30
30
  },
31
31
  "type": "module",
32
32
  "exports": {
@@ -41,7 +41,8 @@
41
41
  },
42
42
  "files": [
43
43
  "dist",
44
- "plugin"
44
+ "plugin",
45
+ "scripts/postinstall.cjs"
45
46
  ],
46
47
  "bin": {
47
48
  "kiro-memory": "./plugin/dist/cli/contextkit.js"
@@ -75,6 +76,7 @@
75
76
  "test:infra": "bun test tests/infrastructure/",
76
77
  "test:server": "bun test tests/server/",
77
78
  "install:kiro": "bash scripts/install-kiro.sh",
79
+ "postinstall": "node scripts/postinstall.cjs",
78
80
  "prepublishOnly": "npm run build",
79
81
  "release": "np",
80
82
  "release:patch": "np patch --no-cleanup",
@@ -2483,6 +2483,71 @@ function formatReportJson(data) {
2483
2483
  return JSON.stringify(data, null, 2);
2484
2484
  }
2485
2485
 
2486
+ // src/cli/banner.ts
2487
+ var G = [
2488
+ "\x1B[38;5;135m",
2489
+ // viola
2490
+ "\x1B[38;5;99m",
2491
+ // viola-blu
2492
+ "\x1B[38;5;63m",
2493
+ // indaco
2494
+ "\x1B[38;5;33m",
2495
+ // blu
2496
+ "\x1B[38;5;39m",
2497
+ // blu chiaro
2498
+ "\x1B[38;5;44m"
2499
+ // ciano
2500
+ ];
2501
+ var R = "\x1B[0m";
2502
+ var B = "\x1B[1m";
2503
+ var D = "\x1B[2m";
2504
+ var U = "\x1B[4m";
2505
+ var GRN = "\x1B[32m";
2506
+ var CYN = "\x1B[36m";
2507
+ var LOGO = [
2508
+ " \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ",
2509
+ " \u2588\u2588\u2551 \u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557",
2510
+ " \u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551",
2511
+ " \u2588\u2588\u2554\u2550\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551",
2512
+ " \u2588\u2588\u2551 \u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D",
2513
+ " \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D"
2514
+ ];
2515
+ var MEMORY_TAG = " M E M O R Y";
2516
+ var LINE = "\u2500".repeat(48);
2517
+ function supportsColor() {
2518
+ if (process.env.NO_COLOR || process.env.TERM === "dumb") return false;
2519
+ return process.stdout.isTTY ?? false;
2520
+ }
2521
+ function printBanner(opts) {
2522
+ const color = supportsColor();
2523
+ const c = (code, text) => color ? `${code}${text}${R}` : text;
2524
+ console.log("");
2525
+ for (let i = 0; i < LOGO.length; i++) {
2526
+ console.log(` ${c(G[i], LOGO[i])}`);
2527
+ }
2528
+ console.log(` ${c(`${G[G.length - 1]}${B}`, MEMORY_TAG)}`);
2529
+ console.log("");
2530
+ console.log(` ${c(D, LINE)}`);
2531
+ console.log("");
2532
+ console.log(` ${c(`${GRN}${B}`, "\u2713 Installation complete!")} v${opts.version}`);
2533
+ console.log(` ${c(D, `Editor: ${opts.editor}`)}`);
2534
+ console.log("");
2535
+ console.log(` ${c(`${CYN}${B}`, "Installed:")}`);
2536
+ for (const p of opts.configPaths) {
2537
+ console.log(` ${c(D, "\u2192")} ${p}`);
2538
+ }
2539
+ console.log(` ${c(D, "\u2192")} Data: ${opts.dataDir}`);
2540
+ console.log("");
2541
+ console.log(` ${c(`${CYN}${B}`, "Dashboard:")} ${c(U, opts.dashboardUrl)}`);
2542
+ console.log(` ${c(D, "Docs: https://auritidesign.it/docs/kiro-memory/")}`);
2543
+ console.log("");
2544
+ console.log(` ${c(D, LINE)}`);
2545
+ console.log(` ${c(G[2], "Your AI assistant now has persistent memory.")}`);
2546
+ console.log(` ${c(G[3], "Every session builds on the last.")}`);
2547
+ console.log(` ${c(D, LINE)}`);
2548
+ console.log("");
2549
+ }
2550
+
2486
2551
  // src/cli/contextkit.ts
2487
2552
  import { execSync } from "child_process";
2488
2553
  import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync, appendFileSync as appendFileSync2 } from "fs";
@@ -2495,6 +2560,12 @@ var command = args[0];
2495
2560
  var __filename = fileURLToPath2(import.meta.url);
2496
2561
  var __dirname2 = dirname2(__filename);
2497
2562
  var DIST_DIR = dirname2(__dirname2);
2563
+ var PKG_VERSION = "unknown";
2564
+ try {
2565
+ const pkgPath = join3(DIST_DIR, "..", "..", "package.json");
2566
+ PKG_VERSION = JSON.parse(readFileSync2(pkgPath, "utf8")).version;
2567
+ } catch {
2568
+ }
2498
2569
  var AGENT_TEMPLATE = JSON.stringify({
2499
2570
  name: "kiro-memory",
2500
2571
  description: "Agent with persistent cross-session memory. Uses Kiro Memory to remember context from previous sessions and automatically save what it learns.",
@@ -2917,17 +2988,23 @@ ${aliasLine}
2917
2988
  }
2918
2989
  }
2919
2990
  console.log("\n[4/4] Done!\n");
2920
- console.log(" \x1B[32m\u2550\u2550\u2550 Installation complete! \u2550\u2550\u2550\x1B[0m\n");
2991
+ printBanner({
2992
+ editor: "Kiro CLI",
2993
+ version: PKG_VERSION,
2994
+ dashboardUrl: "http://localhost:3001",
2995
+ dataDir,
2996
+ configPaths: [
2997
+ `Agent: ${agentDestPath}`,
2998
+ `MCP: ${mcpFilePath}`,
2999
+ `Steering: ${steeringDestPath}`
3000
+ ]
3001
+ });
2921
3002
  console.log(" Start Kiro with memory:");
2922
3003
  if (aliasAlreadySet) {
2923
- console.log(" \x1B[1mkiro\x1B[0m");
3004
+ console.log(" \x1B[1mkiro\x1B[0m\n");
2924
3005
  } else {
2925
- console.log(" \x1B[1mkiro-cli --agent kiro-memory\x1B[0m");
3006
+ console.log(" \x1B[1mkiro-cli --agent kiro-memory\x1B[0m\n");
2926
3007
  }
2927
- console.log("");
2928
- console.log(" The worker starts automatically when a Kiro session begins.");
2929
- console.log(` Web dashboard: \x1B[4mhttp://localhost:3001\x1B[0m
2930
- `);
2931
3008
  }
2932
3009
  var CLAUDE_CODE_STEERING = `# Kiro Memory - Persistent Cross-Session Memory
2933
3010
 
@@ -3052,12 +3129,17 @@ async function installClaudeCode() {
3052
3129
  }
3053
3130
  console.log(` \u2192 Data dir: ${dataDir}`);
3054
3131
  console.log("\n[3/3] Done!\n");
3055
- console.log(" \x1B[32m\u2550\u2550\u2550 Claude Code integration complete! \u2550\u2550\u2550\x1B[0m\n");
3056
- console.log(" Memory hooks are now active for Claude Code.");
3057
- console.log(" Start a new Claude Code session to begin tracking context.\n");
3058
- console.log(" The worker starts automatically on first session.");
3059
- console.log(` Web dashboard: \x1B[4mhttp://localhost:3001\x1B[0m
3060
- `);
3132
+ printBanner({
3133
+ editor: "Claude Code",
3134
+ version: PKG_VERSION,
3135
+ dashboardUrl: "http://localhost:3001",
3136
+ dataDir,
3137
+ configPaths: [
3138
+ `Hooks: ${settingsPath}`,
3139
+ `MCP: ${mcpPath}`,
3140
+ `Steering: ${steeringPath}`
3141
+ ]
3142
+ });
3061
3143
  }
3062
3144
  async function installCursor() {
3063
3145
  console.log("\n=== Kiro Memory - Cursor Installation ===\n");
@@ -3139,12 +3221,16 @@ async function installCursor() {
3139
3221
  console.log(` \u2192 MCP config: ${mcpPath}`);
3140
3222
  console.log(` \u2192 Data dir: ${dataDir}`);
3141
3223
  console.log("\n[3/3] Done!\n");
3142
- console.log(" \x1B[32m\u2550\u2550\u2550 Cursor integration complete! \u2550\u2550\u2550\x1B[0m\n");
3143
- console.log(" Memory hooks are now active for Cursor IDE.");
3144
- console.log(" Start a new Cursor Agent session to begin tracking context.\n");
3145
- console.log(" The worker starts automatically on first session.");
3146
- console.log(` Web dashboard: \x1B[4mhttp://localhost:3001\x1B[0m
3147
- `);
3224
+ printBanner({
3225
+ editor: "Cursor",
3226
+ version: PKG_VERSION,
3227
+ dashboardUrl: "http://localhost:3001",
3228
+ dataDir,
3229
+ configPaths: [
3230
+ `Hooks: ${hooksPath}`,
3231
+ `MCP: ${mcpPath}`
3232
+ ]
3233
+ });
3148
3234
  }
3149
3235
  async function installWindsurf() {
3150
3236
  console.log("\n=== Kiro Memory - Windsurf Installation ===\n");
@@ -3193,12 +3279,15 @@ async function installWindsurf() {
3193
3279
  console.log(` \u2192 MCP config: ${mcpPath}`);
3194
3280
  console.log(` \u2192 Data dir: ${dataDir}`);
3195
3281
  console.log("\n[3/3] Done!\n");
3196
- console.log(" \x1B[32m\u2550\u2550\u2550 Windsurf integration complete! \u2550\u2550\u2550\x1B[0m\n");
3197
- console.log(" Kiro Memory MCP server is now registered for Windsurf.");
3198
- console.log(" Restart Windsurf to activate the MCP server.\n");
3199
- console.log(" The worker starts automatically on first use.");
3200
- console.log(` Web dashboard: \x1B[4mhttp://localhost:3001\x1B[0m
3201
- `);
3282
+ printBanner({
3283
+ editor: "Windsurf",
3284
+ version: PKG_VERSION,
3285
+ dashboardUrl: "http://localhost:3001",
3286
+ dataDir,
3287
+ configPaths: [
3288
+ `MCP: ${mcpPath}`
3289
+ ]
3290
+ });
3202
3291
  console.log(" \x1B[2mTip: Add a .windsurfrules file to your project with instructions");
3203
3292
  console.log(" to use the kiro-memory MCP tools for persistent context.\x1B[0m\n");
3204
3293
  }
@@ -3255,12 +3344,15 @@ async function installCline() {
3255
3344
  console.log(` \u2192 MCP config: ${mcpPath}`);
3256
3345
  console.log(` \u2192 Data dir: ${dataDir}`);
3257
3346
  console.log("\n[3/3] Done!\n");
3258
- console.log(" \x1B[32m\u2550\u2550\u2550 Cline integration complete! \u2550\u2550\u2550\x1B[0m\n");
3259
- console.log(" Kiro Memory MCP server is now registered for Cline.");
3260
- console.log(" Restart VS Code to activate the MCP server in Cline.\n");
3261
- console.log(" The worker starts automatically on first use.");
3262
- console.log(` Web dashboard: \x1B[4mhttp://localhost:3001\x1B[0m
3263
- `);
3347
+ printBanner({
3348
+ editor: "Cline",
3349
+ version: PKG_VERSION,
3350
+ dashboardUrl: "http://localhost:3001",
3351
+ dataDir,
3352
+ configPaths: [
3353
+ `MCP: ${mcpPath}`
3354
+ ]
3355
+ });
3264
3356
  console.log(" \x1B[2mTip: Add a .clinerules file to your project with instructions");
3265
3357
  console.log(" to use the kiro-memory MCP tools for persistent context.\x1B[0m\n");
3266
3358
  }
@@ -46,6 +46,10 @@ function getActiveSessions(db) {
46
46
  const query = db.query("SELECT * FROM sessions WHERE status = 'active' ORDER BY started_at_epoch DESC");
47
47
  return query.all();
48
48
  }
49
+ function getAllSessions(db, limit = 100) {
50
+ const query = db.query("SELECT * FROM sessions ORDER BY started_at_epoch DESC LIMIT ?");
51
+ return query.all(limit);
52
+ }
49
53
  function getSessionsByProject(db, project, limit = 100) {
50
54
  const query = db.query("SELECT * FROM sessions WHERE project = ? ORDER BY started_at_epoch DESC LIMIT ?");
51
55
  return query.all(project, limit);
@@ -55,6 +59,7 @@ export {
55
59
  createSession,
56
60
  failSession,
57
61
  getActiveSessions,
62
+ getAllSessions,
58
63
  getSessionByContentId,
59
64
  getSessionById,
60
65
  getSessionsByProject,
@@ -769,6 +769,10 @@ function getActiveSessions(db) {
769
769
  const query = db.query("SELECT * FROM sessions WHERE status = 'active' ORDER BY started_at_epoch DESC");
770
770
  return query.all();
771
771
  }
772
+ function getAllSessions(db, limit = 100) {
773
+ const query = db.query("SELECT * FROM sessions ORDER BY started_at_epoch DESC LIMIT ?");
774
+ return query.all(limit);
775
+ }
772
776
  function getSessionsByProject(db, project, limit = 100) {
773
777
  const query = db.query("SELECT * FROM sessions WHERE project = ? ORDER BY started_at_epoch DESC LIMIT ?");
774
778
  return query.all(project, limit);
@@ -1373,6 +1377,7 @@ export {
1373
1377
  deleteSummary,
1374
1378
  failSession,
1375
1379
  getActiveSessions,
1380
+ getAllSessions,
1376
1381
  getCheckpointsBySession,
1377
1382
  getDatabase,
1378
1383
  getLatestCheckpoint,
@@ -25,17 +25,31 @@
25
25
  mono: ['"JetBrains Mono"', 'ui-monospace', 'monospace'],
26
26
  },
27
27
  colors: {
28
+ /* Superfici e bordi — cambiano via CSS vars */
28
29
  surface: {
29
- 0: '#0A0B10',
30
- 1: '#111218',
31
- 2: '#191A22',
32
- 3: '#21222D',
33
- 4: '#2A2B38',
30
+ 0: 'var(--surface-0)',
31
+ 1: 'var(--surface-1)',
32
+ 2: 'var(--surface-2)',
33
+ 3: 'var(--surface-3)',
34
+ 4: 'var(--surface-4)',
34
35
  },
35
36
  border: {
36
- DEFAULT: '#2A2B38',
37
- subtle: '#1E1F2A',
38
- hover: '#3A3B4A',
37
+ DEFAULT: 'var(--border)',
38
+ subtle: 'var(--border-subtle)',
39
+ hover: 'var(--border-hover)',
40
+ },
41
+ /* Scala zinc sovrascritta con CSS vars per inversione light/dark */
42
+ zinc: {
43
+ 50: 'var(--zinc-50)',
44
+ 100: 'var(--zinc-100)',
45
+ 200: 'var(--zinc-200)',
46
+ 300: 'var(--zinc-300)',
47
+ 400: 'var(--zinc-400)',
48
+ 500: 'var(--zinc-500)',
49
+ 600: 'var(--zinc-600)',
50
+ 700: 'var(--zinc-700)',
51
+ 800: 'var(--zinc-800)',
52
+ 900: 'var(--zinc-900)',
39
53
  },
40
54
  accent: {
41
55
  violet: '#7C5AFF',
@@ -48,11 +62,11 @@
48
62
  },
49
63
  },
50
64
  boxShadow: {
51
- 'card': '0 1px 3px rgba(0,0,0,0.4), 0 1px 2px rgba(0,0,0,0.3)',
52
- 'card-hover': '0 4px 12px rgba(0,0,0,0.5), 0 2px 4px rgba(0,0,0,0.3)',
65
+ 'card': 'var(--shadow-card)',
66
+ 'card-hover': 'var(--shadow-card-hover)',
53
67
  'glow-violet': '0 0 20px rgba(124,90,255,0.15)',
54
68
  'glow-blue': '0 0 20px rgba(59,130,246,0.15)',
55
- 'panel': '0 0 0 1px rgba(255,255,255,0.03), 0 2px 8px rgba(0,0,0,0.4)',
69
+ 'panel': 'var(--shadow-panel)',
56
70
  },
57
71
  keyframes: {
58
72
  'slide-up': {
@@ -94,11 +108,76 @@
94
108
  </script>
95
109
 
96
110
  <style>
97
- /* Scrollbar */
98
- ::-webkit-scrollbar { width: 6px; }
99
- ::-webkit-scrollbar-track { background: transparent; }
100
- ::-webkit-scrollbar-thumb { background: #2A2B38; border-radius: 3px; }
101
- ::-webkit-scrollbar-thumb:hover { background: #3A3B4A; }
111
+ /* ── Tema Light (default) ── */
112
+ :root {
113
+ --surface-0: #F5F6FA;
114
+ --surface-1: #FFFFFF;
115
+ --surface-2: #ECEDF3;
116
+ --surface-3: #E0E2EB;
117
+ --surface-4: #D3D6E0;
118
+ --border: #D3D6E0;
119
+ --border-subtle: #E6E8EF;
120
+ --border-hover: #B5B9C8;
121
+ /* Zinc invertita: 100=scuro, 700=chiaro */
122
+ --zinc-50: #f8f9fa;
123
+ --zinc-100: #131520;
124
+ --zinc-200: #1f2233;
125
+ --zinc-300: #343750;
126
+ --zinc-400: #4b5068;
127
+ --zinc-500: #6b7085;
128
+ --zinc-600: #9499aa;
129
+ --zinc-700: #bfc3ce;
130
+ --zinc-800: #e4e6ec;
131
+ --zinc-900: #f3f4f6;
132
+ /* Ombre leggere */
133
+ --shadow-card: 0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04);
134
+ --shadow-card-hover: 0 4px 12px rgba(0,0,0,0.08), 0 2px 4px rgba(0,0,0,0.04);
135
+ --shadow-panel: 0 0 0 1px rgba(0,0,0,0.04), 0 2px 8px rgba(0,0,0,0.06);
136
+ /* Scrollbar — toni accent per coerenza brand */
137
+ --scrollbar-thumb: #B5B9C8;
138
+ --scrollbar-hover: #8B7FD4;
139
+ --scrollbar-track: #ECEDF3;
140
+ }
141
+
142
+ /* ── Tema Dark ── */
143
+ .dark {
144
+ --surface-0: #0E1015;
145
+ --surface-1: #161820;
146
+ --surface-2: #1E202A;
147
+ --surface-3: #272935;
148
+ --surface-4: #313342;
149
+ --border: #313342;
150
+ --border-subtle: #222430;
151
+ --border-hover: #434558;
152
+ /* Zinc standard dark (contrasti migliorati) */
153
+ --zinc-50: #18181b;
154
+ --zinc-100: #f0f1f4;
155
+ --zinc-200: #e0e2e8;
156
+ --zinc-300: #c8ccd6;
157
+ --zinc-400: #9ea3b2;
158
+ --zinc-500: #757a8c;
159
+ --zinc-600: #555968;
160
+ --zinc-700: #3d4050;
161
+ --zinc-800: #272935;
162
+ --zinc-900: #1a1c24;
163
+ /* Ombre profonde */
164
+ --shadow-card: 0 1px 3px rgba(0,0,0,0.4), 0 1px 2px rgba(0,0,0,0.3);
165
+ --shadow-card-hover: 0 4px 12px rgba(0,0,0,0.5), 0 2px 4px rgba(0,0,0,0.3);
166
+ --shadow-panel: 0 0 0 1px rgba(255,255,255,0.03), 0 2px 8px rgba(0,0,0,0.4);
167
+ /* Scrollbar — toni accent per coerenza brand */
168
+ --scrollbar-thumb: #434558;
169
+ --scrollbar-hover: #7C5AFF;
170
+ --scrollbar-track: #1E202A;
171
+ }
172
+
173
+ /* Scrollbar — accent brand con hover viola */
174
+ ::-webkit-scrollbar { width: 8px; height: 8px; }
175
+ ::-webkit-scrollbar-track { background: var(--scrollbar-track); border-radius: 4px; margin: 2px; }
176
+ ::-webkit-scrollbar-thumb { background: var(--scrollbar-thumb); border-radius: 4px; border: 2px solid var(--scrollbar-track); transition: background 0.2s; }
177
+ ::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-hover); }
178
+ ::-webkit-scrollbar-corner { background: transparent; }
179
+ /* Firefox */
180
+ * { scrollbar-width: auto; scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track); }
102
181
 
103
182
  /* Stagger */
104
183
  .stagger-1 { animation-delay: 30ms; }
@@ -23652,7 +23652,7 @@ var SOURCE_BADGE = {
23652
23652
  keyword: { bg: "bg-amber-500/15", text: "text-amber-400", label: "keyword" },
23653
23653
  hybrid: { bg: "bg-cyan-500/15", text: "text-cyan-400", label: "hybrid" }
23654
23654
  };
23655
- function SearchBar() {
23655
+ function SearchBar({ onNavigate }) {
23656
23656
  const [query, setQuery] = (0, import_react.useState)("");
23657
23657
  const [results, setResults] = (0, import_react.useState)([]);
23658
23658
  const [isOpen, setIsOpen] = (0, import_react.useState)(false);
@@ -23696,13 +23696,11 @@ function SearchBar() {
23696
23696
  if (total === 0) return;
23697
23697
  const item = results[selectedIndex];
23698
23698
  if (!item) return;
23699
- const targetId = `obs-${item.id}`;
23700
23699
  close();
23701
- setTimeout(() => {
23702
- const el = document.querySelector(`[data-id="${targetId}"]`);
23703
- if (el) el.scrollIntoView({ behavior: "smooth", block: "center" });
23704
- }, 100);
23705
- }, [results, selectedIndex, total, close]);
23700
+ if (onNavigate) {
23701
+ onNavigate(item.project, parseInt(String(item.id), 10));
23702
+ }
23703
+ }, [results, selectedIndex, total, close, onNavigate]);
23706
23704
  (0, import_react.useEffect)(() => {
23707
23705
  const handler = (e) => {
23708
23706
  if ((e.metaKey || e.ctrlKey) && e.key === "k") {
@@ -23773,7 +23771,7 @@ function SearchBar() {
23773
23771
  }
23774
23772
  },
23775
23773
  /* @__PURE__ */ import_react.default.createElement("div", { className: `w-2 h-2 rounded-full mt-1.5 flex-shrink-0 ${badge.dot}` }),
23776
- /* @__PURE__ */ import_react.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "text-sm text-zinc-200 truncate" }, item.title), item.content && /* @__PURE__ */ import_react.default.createElement("div", { className: "text-xs text-zinc-500 truncate mt-0.5" }, item.content.substring(0, 120)), /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center gap-2 mt-1" }, /* @__PURE__ */ import_react.default.createElement("span", { className: `text-[10px] font-medium px-1.5 py-0.5 rounded ${badge.bg} ${badge.text}` }, item.type), /* @__PURE__ */ import_react.default.createElement("span", { className: `text-[10px] font-medium px-1.5 py-0.5 rounded ${srcBadge.bg} ${srcBadge.text}` }, srcBadge.label), /* @__PURE__ */ import_react.default.createElement("span", { className: "text-[10px] text-zinc-600 font-mono" }, timeAgo(item.created_at_epoch)), item.score > 0 && /* @__PURE__ */ import_react.default.createElement("span", { className: "text-[10px] text-zinc-700 font-mono" }, (item.score * 100).toFixed(0), "%")))
23774
+ /* @__PURE__ */ import_react.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "text-sm text-zinc-200 truncate" }, item.title), item.content && /* @__PURE__ */ import_react.default.createElement("div", { className: "text-xs text-zinc-500 truncate mt-0.5" }, item.content.substring(0, 120)), /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center gap-2 mt-1 flex-wrap" }, /* @__PURE__ */ import_react.default.createElement("span", { className: `text-[10px] font-medium px-1.5 py-0.5 rounded ${badge.bg} ${badge.text}` }, item.type), /* @__PURE__ */ import_react.default.createElement("span", { className: "text-[10px] font-medium px-1.5 py-0.5 rounded bg-accent-violet/10 text-accent-violet" }, item.project), /* @__PURE__ */ import_react.default.createElement("span", { className: `text-[10px] font-medium px-1.5 py-0.5 rounded ${srcBadge.bg} ${srcBadge.text}` }, srcBadge.label), /* @__PURE__ */ import_react.default.createElement("span", { className: "text-[10px] text-zinc-600 font-mono" }, timeAgo(item.created_at_epoch)), item.score > 0 && /* @__PURE__ */ import_react.default.createElement("span", { className: "text-[10px] text-zinc-700 font-mono" }, (item.score * 100).toFixed(0), "%")))
23777
23775
  );
23778
23776
  })), /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center gap-4 px-4 py-2.5 border-t border-border text-[11px] text-zinc-600" }, /* @__PURE__ */ import_react.default.createElement("span", null, /* @__PURE__ */ import_react.default.createElement("kbd", { className: "px-1 py-0.5 rounded bg-surface-3 border border-border font-mono mr-1" }, "\u2191\u2193"), "navigate"), /* @__PURE__ */ import_react.default.createElement("span", null, /* @__PURE__ */ import_react.default.createElement("kbd", { className: "px-1 py-0.5 rounded bg-surface-3 border border-border font-mono mr-1" }, "\u21B5"), "open"), /* @__PURE__ */ import_react.default.createElement("span", null, /* @__PURE__ */ import_react.default.createElement("kbd", { className: "px-1 py-0.5 rounded bg-surface-3 border border-border font-mono mr-1" }, "esc"), "close"))))));
23779
23777
  }
@@ -23788,7 +23786,7 @@ function formatAgo(ms) {
23788
23786
  if (min < 60) return `${min}m ago`;
23789
23787
  return `${Math.floor(min / 60)}h ago`;
23790
23788
  }
23791
- function Header({ isConnected, lastEventTime, resolvedTheme, themePreference, onThemeChange, currentView, onViewChange, onMenuToggle }) {
23789
+ function Header({ isConnected, lastEventTime, resolvedTheme, themePreference, onThemeChange, currentView, onViewChange, onMenuToggle, onSearchNavigate }) {
23792
23790
  const cycleTheme = () => {
23793
23791
  const order = ["dark", "light", "system"];
23794
23792
  const current = order.indexOf(themePreference);
@@ -23809,7 +23807,7 @@ function Header({ isConnected, lastEventTime, resolvedTheme, themePreference, on
23809
23807
  "aria-label": "Apri menu laterale"
23810
23808
  },
23811
23809
  /* @__PURE__ */ import_react2.default.createElement("svg", { className: "w-4 h-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react2.default.createElement("line", { x1: "4", y1: "6", x2: "20", y2: "6" }), /* @__PURE__ */ import_react2.default.createElement("line", { x1: "4", y1: "12", x2: "20", y2: "12" }), /* @__PURE__ */ import_react2.default.createElement("line", { x1: "4", y1: "18", x2: "20", y2: "18" }))
23812
- ), /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex items-center gap-3 flex-shrink-0" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "w-8 h-8 rounded-lg bg-accent-violet flex items-center justify-center" }, /* @__PURE__ */ import_react2.default.createElement("svg", { className: "w-[18px] h-[18px] text-white", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react2.default.createElement("path", { d: "M12 2a4 4 0 0 1 4 4c0 1.95-1.4 3.58-3.25 3.93a1 1 0 0 0-.75.97V13" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M12 2a4 4 0 0 0-4 4c0 1.95 1.4 3.58 3.25 3.93a1 1 0 0 1 .75.97V13" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M9 18h6" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M10 22h4" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M12 13v5" }))), /* @__PURE__ */ import_react2.default.createElement("div", null, /* @__PURE__ */ import_react2.default.createElement("h1", { className: "text-[15px] font-bold text-zinc-100 leading-none" }, "Kiro Memory"), /* @__PURE__ */ import_react2.default.createElement("span", { className: "text-[11px] text-zinc-500 mt-0.5 block" }, "Memory Dashboard"))), /* @__PURE__ */ import_react2.default.createElement("div", { className: "hidden md:block w-px h-6 bg-border" }), /* @__PURE__ */ import_react2.default.createElement(SearchBar, null), /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex-1" }), /* @__PURE__ */ import_react2.default.createElement("div", { className: "hidden sm:flex items-center gap-2 px-3 py-1.5 rounded-lg bg-surface-2 border border-border" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: `w-2 h-2 rounded-full transition-all ${isFresh ? "bg-accent-green scale-125" : isConnected ? "bg-accent-green animate-pulse-dot" : "bg-zinc-500"}` }), /* @__PURE__ */ import_react2.default.createElement("span", { className: `text-xs font-medium ${isConnected ? "text-accent-green" : "text-zinc-500"}` }, isConnected ? "Live" : "Offline"), agoText && /* @__PURE__ */ import_react2.default.createElement("span", { className: "text-[10px] text-zinc-600 ml-1" }, agoText)), /* @__PURE__ */ import_react2.default.createElement("div", { className: "hidden sm:flex items-center rounded-lg bg-surface-2 border border-border p-0.5", role: "tablist", "aria-label": "View mode" }, /* @__PURE__ */ import_react2.default.createElement(
23810
+ ), /* @__PURE__ */ import_react2.default.createElement(SearchBar, { onNavigate: onSearchNavigate }), /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex-1" }), /* @__PURE__ */ import_react2.default.createElement("div", { className: "hidden sm:flex items-center gap-2 px-3 py-1.5 rounded-lg bg-surface-2 border border-border" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: `w-2 h-2 rounded-full transition-all ${isFresh ? "bg-accent-green scale-125" : isConnected ? "bg-accent-green animate-pulse-dot" : "bg-zinc-500"}` }), /* @__PURE__ */ import_react2.default.createElement("span", { className: `text-xs font-medium ${isConnected ? "text-accent-green" : "text-zinc-500"}` }, isConnected ? "Live" : "Offline"), agoText && /* @__PURE__ */ import_react2.default.createElement("span", { className: "text-[10px] text-zinc-600 ml-1" }, agoText)), /* @__PURE__ */ import_react2.default.createElement("div", { className: "hidden sm:flex items-center rounded-lg bg-surface-2 border border-border p-0.5", role: "tablist", "aria-label": "View mode" }, /* @__PURE__ */ import_react2.default.createElement(
23813
23811
  "button",
23814
23812
  {
23815
23813
  onClick: () => onViewChange("feed"),
@@ -23891,7 +23889,9 @@ function Sidebar({
23891
23889
  const [editingProject, setEditingProject] = (0, import_react3.useState)(null);
23892
23890
  const [editValue, setEditValue] = (0, import_react3.useState)("");
23893
23891
  const [renameFeedback, setRenameFeedback] = (0, import_react3.useState)(null);
23892
+ const [projectSearch, setProjectSearch] = (0, import_react3.useState)("");
23894
23893
  const editInputRef = (0, import_react3.useRef)(null);
23894
+ const filteredProjects = projectSearch ? projects.filter((p) => getDisplayName(p).toLowerCase().includes(projectSearch.toLowerCase()) || p.toLowerCase().includes(projectSearch.toLowerCase())) : projects;
23895
23895
  (0, import_react3.useEffect)(() => {
23896
23896
  if (editingProject && editInputRef.current) {
23897
23897
  editInputRef.current.focus();
@@ -23923,7 +23923,7 @@ function Sidebar({
23923
23923
  if (e.key === "Enter") confirmEdit();
23924
23924
  if (e.key === "Escape") cancelEdit();
23925
23925
  };
23926
- return /* @__PURE__ */ import_react3.default.createElement("aside", { className: "h-full overflow-y-auto bg-surface-1 border-r border-border flex flex-col" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "p-4" }, /* @__PURE__ */ import_react3.default.createElement("h3", { className: "text-[11px] font-semibold uppercase tracking-wider text-zinc-500 mb-3 px-2" }, "Projects"), /* @__PURE__ */ import_react3.default.createElement(
23926
+ return /* @__PURE__ */ import_react3.default.createElement("aside", { className: "h-full overflow-y-auto bg-surface-1 border-r border-border flex flex-col" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex items-center gap-3 px-4 h-14 border-b border-border flex-shrink-0" }, /* @__PURE__ */ import_react3.default.createElement("svg", { className: "w-8 h-8 flex-shrink-0", viewBox: "0 0 96 96" }, /* @__PURE__ */ import_react3.default.createElement("defs", null, /* @__PURE__ */ import_react3.default.createElement("linearGradient", { id: "km-grad", x1: "0%", y1: "0%", x2: "100%", y2: "100%" }, /* @__PURE__ */ import_react3.default.createElement("stop", { offset: "0%", stopColor: "#7C5AFF" }), /* @__PURE__ */ import_react3.default.createElement("stop", { offset: "100%", stopColor: "#3B82F6" }))), /* @__PURE__ */ import_react3.default.createElement("circle", { cx: "48", cy: "48", r: "44", fill: "none", stroke: "url(#km-grad)", strokeWidth: "1.5", opacity: "0.4" }), /* @__PURE__ */ import_react3.default.createElement("circle", { cx: "48", cy: "48", r: "10", fill: "url(#km-grad)", opacity: "0.9" }), /* @__PURE__ */ import_react3.default.createElement("circle", { cx: "48", cy: "8", r: "5", fill: "#7C5AFF", opacity: "0.9" }), /* @__PURE__ */ import_react3.default.createElement("circle", { cx: "82", cy: "28", r: "4", fill: "#6366F1", opacity: "0.7" }), /* @__PURE__ */ import_react3.default.createElement("circle", { cx: "82", cy: "68", r: "3.5", fill: "#3B82F6", opacity: "0.5" }), /* @__PURE__ */ import_react3.default.createElement("circle", { cx: "48", cy: "88", r: "3", fill: "#2563EB", opacity: "0.4" }), /* @__PURE__ */ import_react3.default.createElement("circle", { cx: "14", cy: "68", r: "2.5", fill: "#3B82F6", opacity: "0.3" }), /* @__PURE__ */ import_react3.default.createElement("circle", { cx: "14", cy: "28", r: "2", fill: "#7C5AFF", opacity: "0.25" }), /* @__PURE__ */ import_react3.default.createElement("line", { x1: "48", y1: "13", x2: "48", y2: "38", stroke: "#7C5AFF", strokeWidth: "1", opacity: "0.3", strokeDasharray: "3 4" }), /* @__PURE__ */ import_react3.default.createElement("line", { x1: "78", y1: "30", x2: "56", y2: "44", stroke: "#6366F1", strokeWidth: "1", opacity: "0.25", strokeDasharray: "3 4" }), /* @__PURE__ */ import_react3.default.createElement("line", { x1: "78", y1: "66", x2: "56", y2: "52", stroke: "#3B82F6", strokeWidth: "1", opacity: "0.2", strokeDasharray: "3 4" }), /* @__PURE__ */ import_react3.default.createElement("line", { x1: "48", y1: "85", x2: "48", y2: "58", stroke: "#2563EB", strokeWidth: "1", opacity: "0.15", strokeDasharray: "3 4" }), /* @__PURE__ */ import_react3.default.createElement("line", { x1: "17", y1: "66", x2: "40", y2: "52", stroke: "#3B82F6", strokeWidth: "1", opacity: "0.15", strokeDasharray: "3 4" })), /* @__PURE__ */ import_react3.default.createElement("div", null, /* @__PURE__ */ import_react3.default.createElement("h1", { className: "text-[15px] font-bold text-zinc-100 leading-none" }, "Kiro Memory"), /* @__PURE__ */ import_react3.default.createElement("span", { className: "text-[11px] text-zinc-500 mt-0.5 block" }, "Memory Dashboard"))), /* @__PURE__ */ import_react3.default.createElement("div", { className: "p-4" }, /* @__PURE__ */ import_react3.default.createElement("h3", { className: "text-[11px] font-semibold uppercase tracking-wider text-zinc-500 mb-3 px-2" }, "Projects"), /* @__PURE__ */ import_react3.default.createElement(
23927
23927
  "button",
23928
23928
  {
23929
23929
  onClick: () => onFilterChange(""),
@@ -23932,7 +23932,16 @@ function Sidebar({
23932
23932
  /* @__PURE__ */ import_react3.default.createElement("div", { className: "w-7 h-7 rounded-md bg-accent-violet/15 flex items-center justify-center flex-shrink-0" }, /* @__PURE__ */ import_react3.default.createElement("svg", { className: "w-3.5 h-3.5 text-accent-violet", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react3.default.createElement("rect", { x: "3", y: "3", width: "7", height: "7" }), /* @__PURE__ */ import_react3.default.createElement("rect", { x: "14", y: "3", width: "7", height: "7" }), /* @__PURE__ */ import_react3.default.createElement("rect", { x: "3", y: "14", width: "7", height: "7" }), /* @__PURE__ */ import_react3.default.createElement("rect", { x: "14", y: "14", width: "7", height: "7" }))),
23933
23933
  /* @__PURE__ */ import_react3.default.createElement("span", { className: "flex-1" }, "All projects"),
23934
23934
  /* @__PURE__ */ import_react3.default.createElement("span", { className: "text-xs text-zinc-600 font-mono tabular-nums" }, projects.length)
23935
- ), /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex flex-col gap-0.5 mt-1" }, projects.map((project) => {
23935
+ ), projects.length >= 6 && /* @__PURE__ */ import_react3.default.createElement("div", { className: "relative mt-1 mb-2" }, /* @__PURE__ */ import_react3.default.createElement("svg", { className: "absolute left-2.5 top-1/2 -translate-y-1/2 w-3 h-3 text-zinc-600", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react3.default.createElement("circle", { cx: "11", cy: "11", r: "8" }), /* @__PURE__ */ import_react3.default.createElement("path", { d: "m21 21-4.3-4.3" })), /* @__PURE__ */ import_react3.default.createElement(
23936
+ "input",
23937
+ {
23938
+ type: "text",
23939
+ value: projectSearch,
23940
+ onChange: (e) => setProjectSearch(e.target.value),
23941
+ placeholder: "Filter projects...",
23942
+ className: "w-full bg-surface-2 border border-border rounded-md text-xs text-zinc-300 placeholder-zinc-600 pl-7 pr-2 py-1.5 outline-none focus:border-accent-violet/50 transition-colors"
23943
+ }
23944
+ )), /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex flex-col gap-0.5 mt-1 max-h-[40vh] overflow-y-auto" }, filteredProjects.map((project) => {
23936
23945
  const pc = getProjectColorByName(project);
23937
23946
  const isEditing = editingProject === project;
23938
23947
  const isActive = currentFilter === project;
@@ -23949,10 +23958,18 @@ function Sidebar({
23949
23958
  className: "flex-1 min-w-0 bg-transparent border-none outline-none text-sm text-zinc-200"
23950
23959
  }
23951
23960
  ), /* @__PURE__ */ import_react3.default.createElement("button", { onClick: confirmEdit, className: "text-accent-green hover:text-accent-green/80 p-0.5" }, /* @__PURE__ */ import_react3.default.createElement("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5" }, /* @__PURE__ */ import_react3.default.createElement("polyline", { points: "20 6 9 17 4 12" }))), /* @__PURE__ */ import_react3.default.createElement("button", { onClick: cancelEdit, className: "text-zinc-500 hover:text-zinc-300 p-0.5" }, /* @__PURE__ */ import_react3.default.createElement("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5" }, /* @__PURE__ */ import_react3.default.createElement("path", { d: "M18 6 6 18M6 6l12 12" })))) : /* @__PURE__ */ import_react3.default.createElement(
23952
- "button",
23961
+ "div",
23953
23962
  {
23963
+ role: "button",
23964
+ tabIndex: 0,
23954
23965
  onClick: () => onFilterChange(project),
23955
- className: `w-full flex items-center gap-3 px-3 py-2 rounded-lg text-sm transition-all text-left ${isActive ? "bg-surface-3 text-zinc-100 font-medium" : "text-zinc-400 hover:text-zinc-200 hover:bg-surface-2"}`
23966
+ onKeyDown: (e) => {
23967
+ if (e.key === "Enter" || e.key === " ") {
23968
+ e.preventDefault();
23969
+ onFilterChange(project);
23970
+ }
23971
+ },
23972
+ className: `w-full flex items-center gap-3 px-3 py-2 rounded-lg text-sm transition-all text-left cursor-pointer ${isActive ? "bg-surface-3 text-zinc-100 font-medium" : "text-zinc-400 hover:text-zinc-200 hover:bg-surface-2"}`
23956
23973
  },
23957
23974
  /* @__PURE__ */ import_react3.default.createElement("div", { className: `w-7 h-7 rounded-md flex items-center justify-center flex-shrink-0 text-[11px] font-bold ${pc.bg} ${pc.text}` }, initials),
23958
23975
  /* @__PURE__ */ import_react3.default.createElement("span", { className: "flex-1 truncate" }, getDisplayName(project)),
@@ -23992,7 +24009,7 @@ function Sidebar({
23992
24009
  className: "h-full bg-gradient-to-r from-emerald-500 to-emerald-400 transition-all",
23993
24010
  style: { width: `${Math.min(100, Math.round(stats.tokenEconomics.readTokens / stats.tokenEconomics.discoveryTokens * 100))}%` }
23994
24011
  }
23995
- )), stats.tokenEconomics.discoveryTokens > 0 && /* @__PURE__ */ import_react3.default.createElement("p", { className: "text-[10px] text-zinc-600 text-center" }, Math.round((1 - stats.tokenEconomics.readTokens / stats.tokenEconomics.discoveryTokens) * 100), "% token reduction")))), /* @__PURE__ */ import_react3.default.createElement("div", { className: "mt-auto px-4 py-4 space-y-2" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex items-center justify-center gap-3" }, /* @__PURE__ */ import_react3.default.createElement("a", { href: "https://github.com/auriti-web-design/kiro-memory", target: "_blank", rel: "noopener noreferrer", className: "text-zinc-600 hover:text-zinc-400 transition-colors", title: "GitHub" }, /* @__PURE__ */ import_react3.default.createElement("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ import_react3.default.createElement("path", { d: "M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0 1 12 6.844a9.59 9.59 0 0 1 2.504.337c1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.02 10.02 0 0 0 22 12.017C22 6.484 17.522 2 12 2z" }))), /* @__PURE__ */ import_react3.default.createElement("a", { href: "https://auritidesign.it/docs/kiro-memory/", target: "_blank", rel: "noopener noreferrer", className: "text-zinc-600 hover:text-zinc-400 transition-colors", title: "Documentazione" }, /* @__PURE__ */ import_react3.default.createElement("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react3.default.createElement("path", { d: "M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z" }), /* @__PURE__ */ import_react3.default.createElement("path", { d: "M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z" })))), /* @__PURE__ */ import_react3.default.createElement("div", { className: "text-[10px] text-zinc-700 font-mono text-center" }, "Kiro Memory v1.8.0")));
24012
+ )), stats.tokenEconomics.discoveryTokens > 0 && /* @__PURE__ */ import_react3.default.createElement("p", { className: "text-[10px] text-zinc-600 text-center" }, Math.round((1 - stats.tokenEconomics.readTokens / stats.tokenEconomics.discoveryTokens) * 100), "% token reduction")))), /* @__PURE__ */ import_react3.default.createElement("div", { className: "mt-auto px-4 py-4 space-y-2" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex items-center justify-center gap-3" }, /* @__PURE__ */ import_react3.default.createElement("a", { href: "https://github.com/Auriti-Labs/kiro-memory", target: "_blank", rel: "noopener noreferrer", className: "text-zinc-600 hover:text-zinc-400 transition-colors", title: "GitHub" }, /* @__PURE__ */ import_react3.default.createElement("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ import_react3.default.createElement("path", { d: "M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0 1 12 6.844a9.59 9.59 0 0 1 2.504.337c1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.02 10.02 0 0 0 22 12.017C22 6.484 17.522 2 12 2z" }))), /* @__PURE__ */ import_react3.default.createElement("a", { href: "https://auritidesign.it/docs/kiro-memory/", target: "_blank", rel: "noopener noreferrer", className: "text-zinc-600 hover:text-zinc-400 transition-colors", title: "Documentazione" }, /* @__PURE__ */ import_react3.default.createElement("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react3.default.createElement("path", { d: "M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z" }), /* @__PURE__ */ import_react3.default.createElement("path", { d: "M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z" })))), /* @__PURE__ */ import_react3.default.createElement("div", { className: "text-[10px] text-zinc-700 font-mono text-center" }, "Kiro Memory v1.9.0")));
23996
24013
  }
23997
24014
 
23998
24015
  // src/ui/viewer/components/Feed.tsx
@@ -24129,7 +24146,7 @@ function ObservationCard({ obs, getDisplayName }) {
24129
24146
  const style = getTypeStyle(obs.type);
24130
24147
  const narrative = generateNarrative(obs);
24131
24148
  const detail = getDetailLine(obs);
24132
- return /* @__PURE__ */ import_react4.default.createElement("div", { className: `bg-surface-1 border border-border rounded-lg border-l-[3px] ${style.border} shadow-card hover:shadow-card-hover hover:border-border-hover transition-all` }, /* @__PURE__ */ import_react4.default.createElement("div", { className: "px-4 py-3.5" }, /* @__PURE__ */ import_react4.default.createElement("div", { className: "flex items-center gap-2 mb-2" }, /* @__PURE__ */ import_react4.default.createElement("span", { className: `inline-flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide px-2 py-0.5 rounded-md ${style.bg} ${style.text}` }, /* @__PURE__ */ import_react4.default.createElement("span", { className: `w-1.5 h-1.5 rounded-full ${style.dot}` }), style.label), /* @__PURE__ */ import_react4.default.createElement("span", { className: "inline-flex items-center text-[11px] font-medium px-2 py-0.5 rounded-md bg-accent-violet/10 text-accent-violet" }, getDisplayName(obs.project)), obs.is_stale === 1 && /* @__PURE__ */ import_react4.default.createElement("span", { className: "inline-flex items-center gap-1 text-[10px] font-medium px-1.5 py-0.5 rounded-md bg-amber-500/10 text-amber-400 ring-1 ring-amber-500/25", title: "File modificato dopo l'osservazione" }, "stale"), /* @__PURE__ */ import_react4.default.createElement("span", { className: "text-[11px] text-zinc-500 font-mono ml-auto tabular-nums" }, timeAgo(obs.created_at_epoch))), /* @__PURE__ */ import_react4.default.createElement("h4", { className: "text-sm text-zinc-200 leading-snug" }, renderMarkdown(narrative)), obs.subtitle && obs.subtitle !== obs.title && /* @__PURE__ */ import_react4.default.createElement("p", { className: "text-[12px] text-zinc-500 mt-1 font-mono truncate" }, stripProjectRoot(obs.subtitle)), detail && /* @__PURE__ */ import_react4.default.createElement("p", { className: "text-[11px] text-zinc-600 mt-1.5" }, detail), /* @__PURE__ */ import_react4.default.createElement("div", { className: "flex items-center gap-2 mt-2.5" }, obs.concepts && /* @__PURE__ */ import_react4.default.createElement("div", { className: "flex flex-wrap gap-1" }, obs.concepts.split(", ").map((concept, i) => {
24149
+ return /* @__PURE__ */ import_react4.default.createElement("div", { className: `bg-surface-1 border border-border rounded-lg border-l-[3px] ${style.border} shadow-card hover:shadow-card-hover hover:border-border-hover transition-all overflow-hidden` }, /* @__PURE__ */ import_react4.default.createElement("div", { className: "px-4 py-3.5 min-w-0" }, /* @__PURE__ */ import_react4.default.createElement("div", { className: "flex items-center gap-2 mb-2 flex-wrap" }, /* @__PURE__ */ import_react4.default.createElement("span", { className: `inline-flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide px-2 py-0.5 rounded-md ${style.bg} ${style.text}` }, /* @__PURE__ */ import_react4.default.createElement("span", { className: `w-1.5 h-1.5 rounded-full ${style.dot}` }), style.label), /* @__PURE__ */ import_react4.default.createElement("span", { className: "inline-flex items-center text-[11px] font-medium px-2 py-0.5 rounded-md bg-accent-violet/10 text-accent-violet" }, getDisplayName(obs.project)), obs.is_stale === 1 && /* @__PURE__ */ import_react4.default.createElement("span", { className: "inline-flex items-center gap-1 text-[10px] font-medium px-1.5 py-0.5 rounded-md bg-amber-500/10 text-amber-400 ring-1 ring-amber-500/25", title: "File modificato dopo l'osservazione" }, "stale"), /* @__PURE__ */ import_react4.default.createElement("span", { className: "text-[11px] text-zinc-500 font-mono ml-auto tabular-nums" }, timeAgo(obs.created_at_epoch))), /* @__PURE__ */ import_react4.default.createElement("h4", { className: "text-sm text-zinc-200 leading-snug break-words" }, renderMarkdown(narrative)), obs.subtitle && obs.subtitle !== obs.title && /* @__PURE__ */ import_react4.default.createElement("p", { className: "text-[12px] text-zinc-500 mt-1 font-mono truncate" }, stripProjectRoot(obs.subtitle)), detail && /* @__PURE__ */ import_react4.default.createElement("p", { className: "text-[11px] text-zinc-600 mt-1.5" }, detail), /* @__PURE__ */ import_react4.default.createElement("div", { className: "flex items-center gap-2 mt-2.5" }, obs.concepts && /* @__PURE__ */ import_react4.default.createElement("div", { className: "flex flex-wrap gap-1" }, obs.concepts.split(", ").map((concept, i) => {
24133
24150
  const colorClass = CONCEPT_COLORS[concept.trim()] || "bg-zinc-500/15 text-zinc-400 ring-zinc-500/25";
24134
24151
  return /* @__PURE__ */ import_react4.default.createElement("span", { key: i, className: `text-[10px] font-medium px-1.5 py-0.5 rounded ring-1 ${colorClass}` }, concept.trim());
24135
24152
  })), /* @__PURE__ */ import_react4.default.createElement("span", { className: "text-[10px] text-zinc-700 font-mono ml-auto tabular-nums" }, "#", obs.id))));
@@ -24142,10 +24159,10 @@ function SummaryCard({ summary, getDisplayName }) {
24142
24159
  { label: "Next Steps", value: summary.next_steps, color: "text-amber-400" },
24143
24160
  { label: "Notes", value: summary.notes, color: "text-zinc-400" }
24144
24161
  ].filter((s) => s.value);
24145
- return /* @__PURE__ */ import_react4.default.createElement("div", { className: "bg-surface-1 border border-border rounded-lg border-l-[3px] border-l-cyan-500 shadow-card hover:shadow-card-hover hover:border-border-hover transition-all" }, /* @__PURE__ */ import_react4.default.createElement("div", { className: "px-4 pt-4 pb-2" }, /* @__PURE__ */ import_react4.default.createElement("div", { className: "flex items-center gap-2 mb-2" }, /* @__PURE__ */ import_react4.default.createElement("span", { className: "inline-flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide px-2 py-0.5 rounded-md bg-cyan-500/10 text-cyan-400" }, /* @__PURE__ */ import_react4.default.createElement("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react4.default.createElement("path", { d: "M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z" }), /* @__PURE__ */ import_react4.default.createElement("path", { d: "M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z" })), "Session Summary"), /* @__PURE__ */ import_react4.default.createElement("span", { className: "inline-flex items-center text-[11px] font-medium px-2 py-0.5 rounded-md bg-accent-violet/10 text-accent-violet" }, getDisplayName(summary.project)), /* @__PURE__ */ import_react4.default.createElement("span", { className: "text-[11px] text-zinc-500 font-mono ml-auto" }, timeAgo(summary.created_at_epoch))), summary.request && /* @__PURE__ */ import_react4.default.createElement("h3", { className: "text-[15px] font-semibold text-zinc-100 leading-snug" }, summary.request)), /* @__PURE__ */ import_react4.default.createElement("div", { className: "px-4 pb-4 space-y-2" }, sections.map(({ label, value, color }) => /* @__PURE__ */ import_react4.default.createElement("div", { key: label, className: "p-3 rounded-md bg-surface-2 border border-border" }, /* @__PURE__ */ import_react4.default.createElement("span", { className: `block text-[10px] font-semibold uppercase tracking-wider mb-1 ${color}` }, label), /* @__PURE__ */ import_react4.default.createElement("p", { className: "text-xs text-zinc-400 leading-relaxed" }, value)))));
24162
+ return /* @__PURE__ */ import_react4.default.createElement("div", { className: "bg-surface-1 border border-border rounded-lg border-l-[3px] border-l-cyan-500 shadow-card hover:shadow-card-hover hover:border-border-hover transition-all overflow-hidden" }, /* @__PURE__ */ import_react4.default.createElement("div", { className: "px-4 pt-4 pb-2 min-w-0" }, /* @__PURE__ */ import_react4.default.createElement("div", { className: "flex items-center gap-2 mb-2 flex-wrap" }, /* @__PURE__ */ import_react4.default.createElement("span", { className: "inline-flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide px-2 py-0.5 rounded-md bg-cyan-500/10 text-cyan-400" }, /* @__PURE__ */ import_react4.default.createElement("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react4.default.createElement("path", { d: "M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z" }), /* @__PURE__ */ import_react4.default.createElement("path", { d: "M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z" })), "Session Summary"), /* @__PURE__ */ import_react4.default.createElement("span", { className: "inline-flex items-center text-[11px] font-medium px-2 py-0.5 rounded-md bg-accent-violet/10 text-accent-violet" }, getDisplayName(summary.project)), /* @__PURE__ */ import_react4.default.createElement("span", { className: "text-[11px] text-zinc-500 font-mono ml-auto" }, timeAgo(summary.created_at_epoch))), summary.request && /* @__PURE__ */ import_react4.default.createElement("h3", { className: "text-[15px] font-semibold text-zinc-100 leading-snug break-words" }, summary.request)), /* @__PURE__ */ import_react4.default.createElement("div", { className: "px-4 pb-4 space-y-2" }, sections.map(({ label, value, color }) => /* @__PURE__ */ import_react4.default.createElement("div", { key: label, className: "p-3 rounded-md bg-surface-2 border border-border" }, /* @__PURE__ */ import_react4.default.createElement("span", { className: `block text-[10px] font-semibold uppercase tracking-wider mb-1 ${color}` }, label), /* @__PURE__ */ import_react4.default.createElement("p", { className: "text-xs text-zinc-400 leading-relaxed" }, value)))));
24146
24163
  }
24147
24164
  function PromptCard({ prompt, getDisplayName }) {
24148
- return /* @__PURE__ */ import_react4.default.createElement("div", { className: "bg-surface-1 border border-border rounded-lg border-l-[3px] border-l-rose-500 shadow-card hover:shadow-card-hover hover:border-border-hover transition-all" }, /* @__PURE__ */ import_react4.default.createElement("div", { className: "px-4 pt-4 pb-2" }, /* @__PURE__ */ import_react4.default.createElement("div", { className: "flex items-center gap-2 mb-2" }, /* @__PURE__ */ import_react4.default.createElement("span", { className: "inline-flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide px-2 py-0.5 rounded-md bg-rose-500/10 text-rose-400" }, /* @__PURE__ */ import_react4.default.createElement("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react4.default.createElement("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" })), "Prompt #", prompt.prompt_number), /* @__PURE__ */ import_react4.default.createElement("span", { className: "inline-flex items-center text-[11px] font-medium px-2 py-0.5 rounded-md bg-accent-violet/10 text-accent-violet" }, getDisplayName(prompt.project)), /* @__PURE__ */ import_react4.default.createElement("span", { className: "text-[11px] text-zinc-500 font-mono ml-auto" }, timeAgo(prompt.created_at_epoch)))), /* @__PURE__ */ import_react4.default.createElement("div", { className: "px-4 pb-4" }, /* @__PURE__ */ import_react4.default.createElement("div", { className: "p-3 rounded-md bg-surface-0 border border-border text-sm text-zinc-300 leading-relaxed whitespace-pre-wrap break-words" }, prompt.prompt_text)));
24165
+ return /* @__PURE__ */ import_react4.default.createElement("div", { className: "bg-surface-1 border border-border rounded-lg border-l-[3px] border-l-rose-500 shadow-card hover:shadow-card-hover hover:border-border-hover transition-all overflow-hidden" }, /* @__PURE__ */ import_react4.default.createElement("div", { className: "px-4 pt-4 pb-2 min-w-0" }, /* @__PURE__ */ import_react4.default.createElement("div", { className: "flex items-center gap-2 mb-2 flex-wrap" }, /* @__PURE__ */ import_react4.default.createElement("span", { className: "inline-flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide px-2 py-0.5 rounded-md bg-rose-500/10 text-rose-400" }, /* @__PURE__ */ import_react4.default.createElement("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react4.default.createElement("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" })), "Prompt #", prompt.prompt_number), /* @__PURE__ */ import_react4.default.createElement("span", { className: "inline-flex items-center text-[11px] font-medium px-2 py-0.5 rounded-md bg-accent-violet/10 text-accent-violet" }, getDisplayName(prompt.project)), /* @__PURE__ */ import_react4.default.createElement("span", { className: "text-[11px] text-zinc-500 font-mono ml-auto" }, timeAgo(prompt.created_at_epoch)))), /* @__PURE__ */ import_react4.default.createElement("div", { className: "px-4 pb-4" }, /* @__PURE__ */ import_react4.default.createElement("div", { className: "p-3 rounded-md bg-surface-0 border border-border text-sm text-zinc-300 leading-relaxed whitespace-pre-wrap break-words" }, prompt.prompt_text)));
24149
24166
  }
24150
24167
 
24151
24168
  // src/ui/viewer/components/Analytics.tsx
@@ -24405,7 +24422,7 @@ function Sessions({ currentFilter, getDisplayName }) {
24405
24422
  /* @__PURE__ */ import_react7.default.createElement("path", { d: "m6 9 6 6 6-6" })
24406
24423
  )
24407
24424
  ),
24408
- isExpanded && /* @__PURE__ */ import_react7.default.createElement("div", { className: "px-4 pb-3 pt-0 border-t border-border space-y-2 animate-fade-in" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "grid grid-cols-2 gap-3 text-xs" }, /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement("span", { className: "text-zinc-600" }, "Session ID"), /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-zinc-400 font-mono text-[11px] truncate" }, session.content_session_id)), /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement("span", { className: "text-zinc-600" }, "Memory ID"), /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-zinc-400 font-mono text-[11px] truncate" }, session.memory_session_id || "\u2014")), /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement("span", { className: "text-zinc-600" }, "Started"), /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-zinc-400 font-mono text-[11px]" }, new Date(session.started_at_epoch).toLocaleString())), /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement("span", { className: "text-zinc-600" }, "Completed"), /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-zinc-400 font-mono text-[11px]" }, session.completed_at_epoch ? new Date(session.completed_at_epoch).toLocaleString() : "\u2014"))), session.user_prompt && /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement("span", { className: "text-[11px] text-zinc-600" }, "Prompt"), /* @__PURE__ */ import_react7.default.createElement("p", { className: "text-xs text-zinc-400 mt-0.5 leading-relaxed" }, session.user_prompt)))
24425
+ isExpanded && /* @__PURE__ */ import_react7.default.createElement("div", { className: "px-4 pb-3 pt-0 border-t border-border space-y-2 animate-fade-in" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "grid grid-cols-2 gap-3 text-xs" }, /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement("span", { className: "text-zinc-600" }, "Session ID"), /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-zinc-400 font-mono text-[11px] truncate" }, session.content_session_id)), /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement("span", { className: "text-zinc-600" }, "Duration"), /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-zinc-400 font-mono text-[11px]" }, formatDuration(duration))), /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement("span", { className: "text-zinc-600" }, "Started"), /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-zinc-400 font-mono text-[11px]" }, new Date(session.started_at_epoch).toLocaleString())), /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement("span", { className: "text-zinc-600" }, "Completed"), /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-zinc-400 font-mono text-[11px]" }, session.completed_at_epoch ? new Date(session.completed_at_epoch).toLocaleString() : session.status === "completed" ? "Before tracking" : "\u2014"))), session.user_prompt && /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement("span", { className: "text-[11px] text-zinc-600" }, "Prompt"), /* @__PURE__ */ import_react7.default.createElement("p", { className: "text-xs text-zinc-400 mt-0.5 leading-relaxed break-words" }, session.user_prompt)))
24409
24426
  );
24410
24427
  })));
24411
24428
  }
@@ -24682,6 +24699,7 @@ function App() {
24682
24699
  const [isLoadingMore, setIsLoadingMore] = (0, import_react11.useState)(false);
24683
24700
  const [hasMore, setHasMore] = (0, import_react11.useState)({ observations: true, summaries: true, prompts: true });
24684
24701
  const [isMobileMenuOpen, setIsMobileMenuOpen] = (0, import_react11.useState)(false);
24702
+ const [highlightObsId, setHighlightObsId] = (0, import_react11.useState)(null);
24685
24703
  const { observations, summaries, prompts, projects, isConnected, lastEventTime } = useSSE();
24686
24704
  const { preference: themePreference, resolvedTheme, setThemePreference } = useTheme();
24687
24705
  const { getDisplayName, updateAlias } = useProjectAliases();
@@ -24791,19 +24809,34 @@ function App() {
24791
24809
  fetchForProject(currentFilter);
24792
24810
  }
24793
24811
  }, [currentFilter, fetchForProject]);
24794
- return /* @__PURE__ */ import_react11.default.createElement("div", { className: "h-screen overflow-hidden flex flex-col bg-surface-0" }, /* @__PURE__ */ import_react11.default.createElement(
24795
- Header,
24796
- {
24797
- isConnected,
24798
- lastEventTime,
24799
- resolvedTheme,
24800
- themePreference,
24801
- onThemeChange: setThemePreference,
24802
- currentView,
24803
- onViewChange: setCurrentView,
24804
- onMenuToggle: () => setIsMobileMenuOpen((prev) => !prev)
24805
- }
24806
- ), /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "hidden md:flex w-[260px] flex-shrink-0" }, /* @__PURE__ */ import_react11.default.createElement(
24812
+ (0, import_react11.useEffect)(() => {
24813
+ if (highlightObsId === null) return;
24814
+ const targetId = `obs-${highlightObsId}`;
24815
+ let attempts = 0;
24816
+ const tryScroll = () => {
24817
+ const el = document.querySelector(`[data-id="${targetId}"]`);
24818
+ if (el) {
24819
+ el.scrollIntoView({ behavior: "smooth", block: "center" });
24820
+ el.classList.add("ring-2", "ring-accent-violet", "ring-offset-2", "ring-offset-surface-0");
24821
+ setTimeout(() => {
24822
+ el.classList.remove("ring-2", "ring-accent-violet", "ring-offset-2", "ring-offset-surface-0");
24823
+ setHighlightObsId(null);
24824
+ }, 3e3);
24825
+ } else if (attempts < 10) {
24826
+ attempts++;
24827
+ setTimeout(tryScroll, 200);
24828
+ } else {
24829
+ setHighlightObsId(null);
24830
+ }
24831
+ };
24832
+ tryScroll();
24833
+ }, [highlightObsId, paginatedObservations, allObservations]);
24834
+ const handleSearchNavigate = (0, import_react11.useCallback)((project, obsId) => {
24835
+ setCurrentView("feed");
24836
+ setCurrentFilter(project);
24837
+ setHighlightObsId(obsId);
24838
+ }, []);
24839
+ return /* @__PURE__ */ import_react11.default.createElement("div", { className: "h-screen overflow-hidden flex bg-surface-0" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "hidden md:flex w-[260px] flex-shrink-0" }, /* @__PURE__ */ import_react11.default.createElement(
24807
24840
  Sidebar,
24808
24841
  {
24809
24842
  projects,
@@ -24836,7 +24869,20 @@ function App() {
24836
24869
  getDisplayName,
24837
24870
  onRenameProject: updateAlias
24838
24871
  }
24839
- ))), /* @__PURE__ */ import_react11.default.createElement("main", { className: "flex-1 overflow-y-auto bg-surface-0" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "max-w-3xl mx-auto px-6 py-6" }, currentFilter && /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center gap-3 mb-6 animate-fade-in" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "w-9 h-9 rounded-lg bg-accent-violet/15 flex items-center justify-center" }, /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-xs font-bold text-accent-violet" }, getDisplayName(currentFilter).substring(0, 2).toUpperCase())), /* @__PURE__ */ import_react11.default.createElement("div", null, /* @__PURE__ */ import_react11.default.createElement("h2", { className: "text-lg font-bold text-zinc-100" }, getDisplayName(currentFilter)), currentFilter !== getDisplayName(currentFilter) && /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-[11px] font-mono text-zinc-600" }, currentFilter))), /* @__PURE__ */ import_react11.default.createElement(
24872
+ ))), /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex-1 min-w-0 flex flex-col overflow-hidden" }, /* @__PURE__ */ import_react11.default.createElement(
24873
+ Header,
24874
+ {
24875
+ isConnected,
24876
+ lastEventTime,
24877
+ resolvedTheme,
24878
+ themePreference,
24879
+ onThemeChange: setThemePreference,
24880
+ currentView,
24881
+ onViewChange: setCurrentView,
24882
+ onMenuToggle: () => setIsMobileMenuOpen((prev) => !prev),
24883
+ onSearchNavigate: handleSearchNavigate
24884
+ }
24885
+ ), /* @__PURE__ */ import_react11.default.createElement("main", { className: "flex-1 min-w-0 overflow-y-auto bg-surface-0" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "max-w-3xl mx-auto px-6 py-6" }, currentFilter && /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center gap-3 mb-6 animate-fade-in" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "w-9 h-9 rounded-lg bg-accent-violet/15 flex items-center justify-center" }, /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-xs font-bold text-accent-violet" }, getDisplayName(currentFilter).substring(0, 2).toUpperCase())), /* @__PURE__ */ import_react11.default.createElement("div", null, /* @__PURE__ */ import_react11.default.createElement("h2", { className: "text-lg font-bold text-zinc-100" }, getDisplayName(currentFilter)), currentFilter !== getDisplayName(currentFilter) && /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-[11px] font-mono text-zinc-600" }, currentFilter))), /* @__PURE__ */ import_react11.default.createElement(
24840
24886
  "button",
24841
24887
  {
24842
24888
  onClick: () => setCurrentFilter(""),
@@ -4595,9 +4595,9 @@ function getLatestCheckpointByProject(db2, project) {
4595
4595
  }
4596
4596
 
4597
4597
  // src/services/sqlite/Sessions.ts
4598
- function getActiveSessions(db2) {
4599
- const query = db2.query("SELECT * FROM sessions WHERE status = 'active' ORDER BY started_at_epoch DESC");
4600
- return query.all();
4598
+ function getAllSessions(db2, limit = 100) {
4599
+ const query = db2.query("SELECT * FROM sessions ORDER BY started_at_epoch DESC LIMIT ?");
4600
+ return query.all(limit);
4601
4601
  }
4602
4602
  function getSessionsByProject(db2, project, limit = 100) {
4603
4603
  const query = db2.query("SELECT * FROM sessions WHERE project = ? ORDER BY started_at_epoch DESC LIMIT ?");
@@ -4915,7 +4915,7 @@ app.get("/health", (req, res) => {
4915
4915
  res.json({
4916
4916
  status: "ok",
4917
4917
  timestamp: Date.now(),
4918
- version: "1.0.0"
4918
+ version: "1.9.0"
4919
4919
  });
4920
4920
  });
4921
4921
  app.get("/events", (req, res) => {
@@ -5475,7 +5475,7 @@ app.get("/api/sessions", (req, res) => {
5475
5475
  return;
5476
5476
  }
5477
5477
  try {
5478
- const sessions = project ? getSessionsByProject(db.db, project, 50) : getActiveSessions(db.db);
5478
+ const sessions = project ? getSessionsByProject(db.db, project, 50) : getAllSessions(db.db, 50);
5479
5479
  res.json(sessions);
5480
5480
  } catch (error) {
5481
5481
  logger.error("WORKER", "Lista sessioni fallita", { project }, error);
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Messaggio post-installazione Kiro Memory
4
+ * Eseguito automaticamente dopo npm install -g kiro-memory
5
+ * File .cjs per compatibilità con "type": "module" nel package.json
6
+ */
7
+
8
+ /* Silenzioso in CI o con npm in modalità silenziosa */
9
+ if (process.env.CI || process.env.npm_config_loglevel === 'silent') {
10
+ process.exit(0);
11
+ }
12
+
13
+ const { readFileSync } = require('fs');
14
+ const { join } = require('path');
15
+
16
+ let version = '';
17
+ try {
18
+ const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8'));
19
+ version = pkg.version || '';
20
+ } catch { /* ignora */ }
21
+
22
+ /* Rileva supporto colori */
23
+ const color = !process.env.NO_COLOR && process.env.TERM !== 'dumb' && (process.stdout.isTTY || false);
24
+ const c = (code, text) => color ? `${code}${text}\x1b[0m` : text;
25
+ const BOLD = '\x1b[1m';
26
+ const DIM = '\x1b[2m';
27
+ const UND = '\x1b[4m';
28
+ const VIOLET = '\x1b[38;5;135m';
29
+ const CYAN = '\x1b[36m';
30
+
31
+ console.log('');
32
+ console.log(` ${c(VIOLET + BOLD, 'Kiro Memory')} ${version ? `v${version}` : ''} installed!`);
33
+ console.log('');
34
+ console.log(` ${c(DIM, 'Get started:')}`);
35
+ console.log(` ${c(BOLD, 'kiro-memory install')} Auto-detect editor`);
36
+ console.log(` ${c(BOLD, 'kiro-memory install --claude-code')} Claude Code`);
37
+ console.log(` ${c(BOLD, 'kiro-memory install --cursor')} Cursor`);
38
+ console.log(` ${c(BOLD, 'kiro-memory install --windsurf')} Windsurf`);
39
+ console.log('');
40
+ console.log(` ${c(CYAN, 'Dashboard:')} ${c(UND, 'http://localhost:3001')}`);
41
+ console.log(` ${c(DIM, 'Docs: ')} ${c(UND, 'https://auritidesign.it/docs/kiro-memory/')}`);
42
+ console.log('');