vigthoria-cli 1.9.9 → 1.9.19

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 (52) hide show
  1. package/README.md +5 -5
  2. package/dist/commands/auth.js +48 -65
  3. package/dist/commands/bridge.js +12 -19
  4. package/dist/commands/cancel.js +15 -22
  5. package/dist/commands/chat.d.ts +11 -0
  6. package/dist/commands/chat.js +404 -248
  7. package/dist/commands/config.js +31 -71
  8. package/dist/commands/deploy.js +83 -123
  9. package/dist/commands/device.d.ts +35 -0
  10. package/dist/commands/device.js +239 -0
  11. package/dist/commands/edit.js +32 -39
  12. package/dist/commands/explain.js +18 -25
  13. package/dist/commands/fork.js +22 -27
  14. package/dist/commands/generate.js +37 -44
  15. package/dist/commands/history.js +20 -25
  16. package/dist/commands/hub.js +95 -102
  17. package/dist/commands/index.js +41 -46
  18. package/dist/commands/legion.d.ts +1 -0
  19. package/dist/commands/legion.js +162 -209
  20. package/dist/commands/preview.js +60 -98
  21. package/dist/commands/replay.js +27 -32
  22. package/dist/commands/repo.js +103 -141
  23. package/dist/commands/review.js +29 -36
  24. package/dist/commands/security.js +5 -12
  25. package/dist/commands/update.js +15 -49
  26. package/dist/commands/workflow.d.ts +8 -1
  27. package/dist/commands/workflow.js +53 -19
  28. package/dist/index.js +409 -234
  29. package/dist/utils/api.d.ts +5 -0
  30. package/dist/utils/api.js +398 -176
  31. package/dist/utils/bridge-client.js +11 -52
  32. package/dist/utils/cli-state.d.ts +54 -0
  33. package/dist/utils/cli-state.js +185 -0
  34. package/dist/utils/config.d.ts +5 -0
  35. package/dist/utils/config.js +35 -14
  36. package/dist/utils/context-ranker.js +15 -21
  37. package/dist/utils/files.js +5 -42
  38. package/dist/utils/logger.js +42 -50
  39. package/dist/utils/post-write-validator.js +22 -29
  40. package/dist/utils/project-memory.d.ts +56 -0
  41. package/dist/utils/project-memory.js +289 -0
  42. package/dist/utils/session.d.ts +29 -3
  43. package/dist/utils/session.js +137 -85
  44. package/dist/utils/task-display.js +13 -20
  45. package/dist/utils/tools.d.ts +19 -0
  46. package/dist/utils/tools.js +84 -87
  47. package/dist/utils/workspace-cache.js +18 -26
  48. package/dist/utils/workspace-stream.js +26 -64
  49. package/install.ps1 +14 -0
  50. package/package.json +5 -3
  51. package/scripts/release/LOCAL_MACHINE_USER_VERIFICATION.md +1 -1
  52. package/scripts/release/validate-no-go-gates.sh +2 -2
@@ -1,15 +1,8 @@
1
- "use strict";
2
1
  /**
3
2
  * Logger utility for Vigthoria CLI
4
3
  */
5
- var __importDefault = (this && this.__importDefault) || function (mod) {
6
- return (mod && mod.__esModule) ? mod : { "default": mod };
7
- };
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.Logger = exports.CH = void 0;
10
- exports.createSpinner = createSpinner;
11
- const chalk_1 = __importDefault(require("chalk"));
12
- const ora_1 = __importDefault(require("ora"));
4
+ import chalk from 'chalk';
5
+ import ora from 'ora';
13
6
  /**
14
7
  * Platform-aware character map.
15
8
  *
@@ -21,7 +14,7 @@ const ora_1 = __importDefault(require("ora"));
21
14
  * monospace rendering can break.
22
15
  */
23
16
  const isWin = process.platform === 'win32';
24
- exports.CH = {
17
+ export const CH = {
25
18
  info: 'ℹ',
26
19
  warn: '⚠',
27
20
  error: '✗',
@@ -64,67 +57,67 @@ exports.CH = {
64
57
  * Prefer: spinner.stop() then Logger.error(msg) — which writes to
65
58
  * stdout — instead of spinner.fail(msg).
66
59
  */
67
- function createSpinner(textOrOpts) {
60
+ export function createSpinner(textOrOpts) {
68
61
  const opts = typeof textOrOpts === 'string' ? { text: textOrOpts } : textOrOpts;
69
62
  // Suppress spinner animation when stderr is not a TTY (piped output,
70
63
  // CI, non-interactive terminals). The spinner object still works — its
71
64
  // .start()/.stop()/.succeed() methods are no-ops — so callers don't
72
65
  // need conditional logic.
73
66
  const isSilent = !process.stderr.isTTY;
74
- return (0, ora_1.default)({ ...opts, stream: process.stderr, isSilent });
67
+ return ora({ ...opts, stream: process.stderr, isSilent });
75
68
  }
76
- class Logger {
69
+ export class Logger {
77
70
  verbose = false;
78
71
  setVerbose(verbose) {
79
72
  this.verbose = verbose;
80
73
  }
81
74
  debug(...args) {
82
75
  if (this.verbose) {
83
- console.log(chalk_1.default.gray('[DEBUG]'), ...args);
76
+ console.log(chalk.gray('[DEBUG]'), ...args);
84
77
  }
85
78
  }
86
79
  info(...args) {
87
- console.log(chalk_1.default.blue(exports.CH.info), ...args);
80
+ console.log(chalk.blue(CH.info), ...args);
88
81
  }
89
82
  warn(...args) {
90
- console.log(chalk_1.default.yellow(exports.CH.warn), ...args);
83
+ console.log(chalk.yellow(CH.warn), ...args);
91
84
  }
92
85
  error(...args) {
93
86
  // Write error messages to stdout (not stderr) to avoid triggering
94
87
  // PowerShell NativeCommandError styling. The red ✗ prefix already
95
88
  // signals an error visually; stderr redirection is unnecessary.
96
- console.log(chalk_1.default.red(exports.CH.error), ...args);
89
+ console.log(chalk.red(CH.error), ...args);
97
90
  }
98
91
  success(...args) {
99
- console.log(chalk_1.default.green(exports.CH.success), ...args);
92
+ console.log(chalk.green(CH.success), ...args);
100
93
  }
101
94
  // AI response formatting
102
95
  ai(message) {
103
- console.log(chalk_1.default.cyan(exports.CH.ai), message);
96
+ console.log(chalk.cyan(CH.ai), message);
104
97
  }
105
98
  // User input formatting
106
99
  user(message) {
107
- console.log(chalk_1.default.white(exports.CH.user), message);
100
+ console.log(chalk.white(CH.user), message);
108
101
  }
109
102
  // Code block
110
103
  code(code, language) {
111
- console.log(chalk_1.default.gray(exports.CH.hLine.repeat(60)));
112
- console.log(chalk_1.default.yellow(code));
113
- console.log(chalk_1.default.gray(exports.CH.hLine.repeat(60)));
104
+ console.log(chalk.gray(CH.hLine.repeat(60)));
105
+ console.log(chalk.yellow(code));
106
+ console.log(chalk.gray(CH.hLine.repeat(60)));
114
107
  }
115
108
  // Diff output - enhanced with syntax-highlighted unified diff
116
109
  diff(added, removed) {
117
- removed.forEach(line => console.log(chalk_1.default.red(`- ${line}`)));
118
- added.forEach(line => console.log(chalk_1.default.green(`+ ${line}`)));
110
+ removed.forEach(line => console.log(chalk.red(`- ${line}`)));
111
+ added.forEach(line => console.log(chalk.green(`+ ${line}`)));
119
112
  }
120
113
  // Unified diff display with file context
121
114
  unifiedDiff(filePath, oldText, newText) {
122
115
  const oldLines = oldText.split('\n');
123
116
  const newLines = newText.split('\n');
124
117
  const fileName = filePath.split('/').pop() || filePath;
125
- console.log(chalk_1.default.bold.white(`\n ${exports.CH.hLine.repeat(3)} ${fileName} ${exports.CH.hLine.repeat(Math.max(1, 50 - fileName.length))}`));
126
- console.log(chalk_1.default.gray(` --- a/${filePath}`));
127
- console.log(chalk_1.default.gray(` +++ b/${filePath}`));
118
+ console.log(chalk.bold.white(`\n ${CH.hLine.repeat(3)} ${fileName} ${CH.hLine.repeat(Math.max(1, 50 - fileName.length))}`));
119
+ console.log(chalk.gray(` --- a/${filePath}`));
120
+ console.log(chalk.gray(` +++ b/${filePath}`));
128
121
  // Find diff ranges with context
129
122
  const contextLines = 3;
130
123
  let i = 0;
@@ -140,18 +133,18 @@ class Logger {
140
133
  const startNew = Math.max(0, j - contextLines);
141
134
  // Context before
142
135
  for (let c = startOld; c < i; c++) {
143
- console.log(chalk_1.default.gray(` ${String(c + 1).padStart(4)} │ ${oldLines[c] || ''}`));
136
+ console.log(chalk.gray(` ${String(c + 1).padStart(4)} │ ${oldLines[c] || ''}`));
144
137
  }
145
138
  // Removed lines
146
139
  while (i < oldLines.length && (j >= newLines.length || oldLines[i] !== newLines[j])) {
147
- console.log(chalk_1.default.red(` ${String(i + 1).padStart(4)} │-${oldLines[i]}`));
140
+ console.log(chalk.red(` ${String(i + 1).padStart(4)} │-${oldLines[i]}`));
148
141
  i++;
149
142
  if (j < newLines.length && (i >= oldLines.length || oldLines[i] === newLines[j]))
150
143
  break;
151
144
  }
152
145
  // Added lines
153
146
  while (j < newLines.length && (i >= oldLines.length || oldLines[i] !== newLines[j])) {
154
- console.log(chalk_1.default.green(` ${String(j + 1).padStart(4)} │+${newLines[j]}`));
147
+ console.log(chalk.green(` ${String(j + 1).padStart(4)} │+${newLines[j]}`));
155
148
  j++;
156
149
  if (i < oldLines.length && oldLines[i] === newLines[j])
157
150
  break;
@@ -159,23 +152,23 @@ class Logger {
159
152
  // Context after
160
153
  const endCtx = Math.min(oldLines.length, i + contextLines);
161
154
  for (let c = i; c < endCtx && c < oldLines.length && j < newLines.length && oldLines[c] === newLines[j]; c++) {
162
- console.log(chalk_1.default.gray(` ${String(c + 1).padStart(4)} │ ${oldLines[c] || ''}`));
155
+ console.log(chalk.gray(` ${String(c + 1).padStart(4)} │ ${oldLines[c] || ''}`));
163
156
  i = c + 1;
164
157
  j++;
165
158
  }
166
- console.log(chalk_1.default.gray(` ${exports.CH.hLine.repeat(55)}`));
159
+ console.log(chalk.gray(` ${CH.hLine.repeat(55)}`));
167
160
  }
168
161
  console.log();
169
162
  }
170
163
  // Section header
171
164
  section(title) {
172
165
  console.log();
173
- console.log(chalk_1.default.bold.cyan(`${exports.CH.hDouble.repeat(3)} ${title} ${exports.CH.hDouble.repeat(3)}`));
166
+ console.log(chalk.bold.cyan(`${CH.hDouble.repeat(3)} ${title} ${CH.hDouble.repeat(3)}`));
174
167
  console.log();
175
168
  }
176
169
  // Progress
177
170
  progress(message) {
178
- process.stdout.write(chalk_1.default.gray(`${message}\r`));
171
+ process.stdout.write(chalk.gray(`${message}\r`));
179
172
  }
180
173
  // Clear line
181
174
  clearLine() {
@@ -188,18 +181,18 @@ class Logger {
188
181
  const stripAnsi = (str) => str.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, '');
189
182
  const maxLen = Math.max(...lines.map(l => stripAnsi(l).length), title?.length || 0);
190
183
  const width = maxLen + 4;
191
- console.log(chalk_1.default.cyan(exports.CH.tl + exports.CH.hLine.repeat(width - 2) + exports.CH.tr));
184
+ console.log(chalk.cyan(CH.tl + CH.hLine.repeat(width - 2) + CH.tr));
192
185
  if (title) {
193
- console.log(chalk_1.default.cyan(exports.CH.vLine + ' ') + chalk_1.default.bold.white(title.padEnd(width - 4)) + chalk_1.default.cyan(' ' + exports.CH.vLine));
194
- console.log(chalk_1.default.cyan(exports.CH.teeR + exports.CH.hLine.repeat(width - 2) + exports.CH.teeL));
186
+ console.log(chalk.cyan(CH.vLine + ' ') + chalk.bold.white(title.padEnd(width - 4)) + chalk.cyan(' ' + CH.vLine));
187
+ console.log(chalk.cyan(CH.teeR + CH.hLine.repeat(width - 2) + CH.teeL));
195
188
  }
196
189
  lines.forEach(line => {
197
190
  // Calculate visible length and pad accordingly
198
191
  const visibleLen = stripAnsi(line).length;
199
192
  const padding = ' '.repeat(Math.max(0, width - 4 - visibleLen));
200
- console.log(chalk_1.default.cyan(exports.CH.vLine + ' ') + line + padding + chalk_1.default.cyan(' ' + exports.CH.vLine));
193
+ console.log(chalk.cyan(CH.vLine + ' ') + line + padding + chalk.cyan(' ' + CH.vLine));
201
194
  });
202
- console.log(chalk_1.default.cyan(exports.CH.bl + exports.CH.hLine.repeat(width - 2) + exports.CH.br));
195
+ console.log(chalk.cyan(CH.bl + CH.hLine.repeat(width - 2) + CH.br));
203
196
  }
204
197
  // Table output
205
198
  table(headers, rows) {
@@ -208,19 +201,18 @@ class Logger {
208
201
  return Math.max(h.length, maxData);
209
202
  });
210
203
  // Header
211
- console.log(chalk_1.default.gray(exports.CH.vLine + ' ') +
212
- headers.map((h, i) => chalk_1.default.bold(h.padEnd(colWidths[i]))).join(chalk_1.default.gray(' ' + exports.CH.vLine + ' ')) +
213
- chalk_1.default.gray(' ' + exports.CH.vLine));
204
+ console.log(chalk.gray(CH.vLine + ' ') +
205
+ headers.map((h, i) => chalk.bold(h.padEnd(colWidths[i]))).join(chalk.gray(' ' + CH.vLine + ' ')) +
206
+ chalk.gray(' ' + CH.vLine));
214
207
  // Separator
215
- console.log(chalk_1.default.gray(exports.CH.teeR + exports.CH.hLine) +
216
- colWidths.map(w => exports.CH.hLine.repeat(w)).join(chalk_1.default.gray(exports.CH.hLine + exports.CH.cross + exports.CH.hLine)) +
217
- chalk_1.default.gray(exports.CH.hLine + exports.CH.teeL));
208
+ console.log(chalk.gray(CH.teeR + CH.hLine) +
209
+ colWidths.map(w => CH.hLine.repeat(w)).join(chalk.gray(CH.hLine + CH.cross + CH.hLine)) +
210
+ chalk.gray(CH.hLine + CH.teeL));
218
211
  // Rows
219
212
  rows.forEach(row => {
220
- console.log(chalk_1.default.gray(exports.CH.vLine + ' ') +
221
- row.map((cell, i) => (cell || '').padEnd(colWidths[i])).join(chalk_1.default.gray(' ' + exports.CH.vLine + ' ')) +
222
- chalk_1.default.gray(' ' + exports.CH.vLine));
213
+ console.log(chalk.gray(CH.vLine + ' ') +
214
+ row.map((cell, i) => (cell || '').padEnd(colWidths[i])).join(chalk.gray(' ' + CH.vLine + ' ')) +
215
+ chalk.gray(' ' + CH.vLine));
223
216
  });
224
217
  }
225
218
  }
226
- exports.Logger = Logger;
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * Vigthoria CLI — Post-Write Validator / Self-Healing Layer
4
3
  *
@@ -9,18 +8,12 @@
9
8
  *
10
9
  * Used by runSelfHealingCycle in api.ts to send targeted correction prompts.
11
10
  */
12
- var __importDefault = (this && this.__importDefault) || function (mod) {
13
- return (mod && mod.__esModule) ? mod : { "default": mod };
14
- };
15
- Object.defineProperty(exports, "__esModule", { value: true });
16
- exports.runPostWriteValidation = runPostWriteValidation;
17
- exports.formatValidationErrors = formatValidationErrors;
18
- const node_child_process_1 = require("node:child_process");
19
- const node_fs_1 = __importDefault(require("node:fs"));
20
- const node_path_1 = __importDefault(require("node:path"));
11
+ import { execFileSync } from 'node:child_process';
12
+ import fs from 'node:fs';
13
+ import path from 'node:path';
21
14
  function commandExists(cmd, args = ['--version']) {
22
15
  try {
23
- (0, node_child_process_1.execFileSync)(cmd, args, { stdio: 'pipe', timeout: 4000, windowsHide: true });
16
+ execFileSync(cmd, args, { stdio: 'pipe', timeout: 4000, windowsHide: true });
24
17
  return true;
25
18
  }
26
19
  catch {
@@ -28,23 +21,23 @@ function commandExists(cmd, args = ['--version']) {
28
21
  }
29
22
  }
30
23
  function hasTsConfig(dir) {
31
- return node_fs_1.default.existsSync(node_path_1.default.join(dir, 'tsconfig.json'));
24
+ return fs.existsSync(path.join(dir, 'tsconfig.json'));
32
25
  }
33
26
  /**
34
27
  * Resolve the best available tsc binary for the project.
35
28
  * Prefers local node_modules/.bin/tsc over npx to avoid network fetches.
36
29
  */
37
30
  function resolveTscBin(workspacePath) {
38
- const localTsc = node_path_1.default.join(workspacePath, 'node_modules', '.bin', 'tsc');
39
- if (node_fs_1.default.existsSync(localTsc))
31
+ const localTsc = path.join(workspacePath, 'node_modules', '.bin', 'tsc');
32
+ if (fs.existsSync(localTsc))
40
33
  return { cmd: localTsc, args: ["--noEmit", "--skipLibCheck"] };
41
34
  try {
42
- (0, node_child_process_1.execFileSync)("npx", ["--version"], { stdio: "pipe", timeout: 4000, windowsHide: true });
35
+ execFileSync("npx", ["--version"], { stdio: "pipe", timeout: 4000, windowsHide: true });
43
36
  return { cmd: "npx", args: ["tsc", "--noEmit", "--skipLibCheck"] };
44
37
  }
45
38
  catch { /* npx not available */ }
46
39
  try {
47
- (0, node_child_process_1.execFileSync)("tsc", ["--version"], { stdio: "pipe", timeout: 4000, windowsHide: true });
40
+ execFileSync("tsc", ["--version"], { stdio: "pipe", timeout: 4000, windowsHide: true });
48
41
  return { cmd: "tsc", args: ["--noEmit", "--skipLibCheck"] };
49
42
  }
50
43
  catch { /* tsc not available */ }
@@ -52,10 +45,10 @@ function resolveTscBin(workspacePath) {
52
45
  }
53
46
  function hasRealTestScript(dir) {
54
47
  try {
55
- const pkgPath = node_path_1.default.join(dir, 'package.json');
56
- if (!node_fs_1.default.existsSync(pkgPath))
48
+ const pkgPath = path.join(dir, 'package.json');
49
+ if (!fs.existsSync(pkgPath))
57
50
  return false;
58
- const pkg = JSON.parse(node_fs_1.default.readFileSync(pkgPath, 'utf-8'));
51
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
59
52
  const script = pkg.scripts?.test ?? '';
60
53
  return typeof script === 'string' && script.length > 0
61
54
  && !script.startsWith('echo "Error: no test specified"');
@@ -68,8 +61,8 @@ function hasRealTestScript(dir) {
68
61
  * Run post-write validation in the project directory.
69
62
  * Each check is time-bounded to avoid blocking the CLI.
70
63
  */
71
- async function runPostWriteValidation(workspacePath) {
72
- if (!workspacePath || !node_fs_1.default.existsSync(workspacePath))
64
+ export async function runPostWriteValidation(workspacePath) {
65
+ if (!workspacePath || !fs.existsSync(workspacePath))
73
66
  return [];
74
67
  const results = [];
75
68
  const opts = { cwd: workspacePath, stdio: 'pipe', windowsHide: true };
@@ -77,7 +70,7 @@ async function runPostWriteValidation(workspacePath) {
77
70
  const tscBin = hasTsConfig(workspacePath) ? resolveTscBin(workspacePath) : null;
78
71
  if (tscBin) {
79
72
  try {
80
- (0, node_child_process_1.execFileSync)(tscBin.cmd, tscBin.args, { ...opts, timeout: 45_000 });
73
+ execFileSync(tscBin.cmd, tscBin.args, { ...opts, timeout: 45_000 });
81
74
  results.push({ ran: true, tool: 'tsc', passed: true, output: '' });
82
75
  }
83
76
  catch (err) {
@@ -88,7 +81,7 @@ async function runPostWriteValidation(workspacePath) {
88
81
  // 2. npm test
89
82
  if (hasRealTestScript(workspacePath) && commandExists('npm')) {
90
83
  try {
91
- (0, node_child_process_1.execFileSync)('npm', ['test', '--', '--passWithNoTests'], { ...opts, timeout: 90_000 });
84
+ execFileSync('npm', ['test', '--', '--passWithNoTests'], { ...opts, timeout: 90_000 });
92
85
  results.push({ ran: true, tool: 'npm test', passed: true, output: '' });
93
86
  }
94
87
  catch (err) {
@@ -97,13 +90,13 @@ async function runPostWriteValidation(workspacePath) {
97
90
  }
98
91
  }
99
92
  // 3. Python syntax check
100
- const hasPy = node_fs_1.default.existsSync(node_path_1.default.join(workspacePath, 'requirements.txt'))
101
- || node_fs_1.default.existsSync(node_path_1.default.join(workspacePath, 'setup.py'))
102
- || node_fs_1.default.existsSync(node_path_1.default.join(workspacePath, 'pyproject.toml'));
93
+ const hasPy = fs.existsSync(path.join(workspacePath, 'requirements.txt'))
94
+ || fs.existsSync(path.join(workspacePath, 'setup.py'))
95
+ || fs.existsSync(path.join(workspacePath, 'pyproject.toml'));
103
96
  if (hasPy && commandExists('python3', ['-c', 'import ast'])) {
104
97
  const pyFiles = [];
105
98
  try {
106
- const entries = node_fs_1.default.readdirSync(workspacePath, { withFileTypes: true });
99
+ const entries = fs.readdirSync(workspacePath, { withFileTypes: true });
107
100
  for (const e of entries) {
108
101
  if (e.isFile() && e.name.endsWith('.py'))
109
102
  pyFiles.push(e.name);
@@ -114,7 +107,7 @@ async function runPostWriteValidation(workspacePath) {
114
107
  let pyOut = '';
115
108
  for (const pyFile of pyFiles.slice(0, 20)) {
116
109
  try {
117
- (0, node_child_process_1.execFileSync)('python3', ['-m', 'py_compile', pyFile], { ...opts, timeout: 10_000 });
110
+ execFileSync('python3', ['-m', 'py_compile', pyFile], { ...opts, timeout: 10_000 });
118
111
  }
119
112
  catch (err) {
120
113
  pyPassed = false;
@@ -130,7 +123,7 @@ async function runPostWriteValidation(workspacePath) {
130
123
  /**
131
124
  * Build a clear error summary string from failed validation results.
132
125
  */
133
- function formatValidationErrors(results) {
126
+ export function formatValidationErrors(results) {
134
127
  return results
135
128
  .filter((r) => r.ran && !r.passed)
136
129
  .map((r) => `[${r.tool}]\n${r.output.trim()}`)
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Vigthoria Project Memory Service
3
+ *
4
+ * Local-first project brain stored inside .vigthoria/memory. It keeps durable,
5
+ * compact facts that can be retrieved for follow-up prompts without replaying
6
+ * full chat history or noisy tool traces.
7
+ */
8
+ import { ChatMessage } from './api.js';
9
+ export type ProjectMemoryType = 'fact' | 'decision' | 'task' | 'file' | 'preference' | 'validation' | 'issue';
10
+ export interface ProjectMemoryItem {
11
+ id: string;
12
+ type: ProjectMemoryType;
13
+ text: string;
14
+ tags: string[];
15
+ source: string;
16
+ createdAt: string;
17
+ updatedAt: string;
18
+ weight: number;
19
+ }
20
+ export interface ProjectMemoryBrain {
21
+ version: 1;
22
+ workspaceName: string;
23
+ updatedAt: string;
24
+ items: ProjectMemoryItem[];
25
+ }
26
+ interface RememberOptions {
27
+ source?: string;
28
+ mode?: string;
29
+ model?: string;
30
+ sessionSummary?: string;
31
+ }
32
+ export declare class ProjectMemoryService {
33
+ private workspacePath;
34
+ private memoryDir;
35
+ private brainPath;
36
+ constructor(workspacePath?: string);
37
+ getMemoryDir(): string;
38
+ loadBrain(): ProjectMemoryBrain;
39
+ saveBrain(brain: ProjectMemoryBrain): void;
40
+ remember(type: ProjectMemoryType, text: string, options?: RememberOptions): void;
41
+ rememberConversation(messages: ChatMessage[], options?: RememberOptions): void;
42
+ buildContextForPrompt(prompt: string): string;
43
+ retrieveRelevantMemory(prompt: string, limit?: number): ProjectMemoryItem[];
44
+ getStatus(): {
45
+ memoryDir: string;
46
+ itemCount: number;
47
+ updatedAt: string;
48
+ typeCounts: Record<string, number>;
49
+ };
50
+ private createItem;
51
+ private inferUserMemoryType;
52
+ private dedupeAndTrim;
53
+ private writeMarkdownViews;
54
+ private headingForType;
55
+ }
56
+ export {};