codeep 3.3.3 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/acp/commands.d.ts +50 -1
  2. package/dist/acp/commands.js +545 -109
  3. package/dist/acp/protocol.d.ts +14 -5
  4. package/dist/acp/server.d.ts +36 -1
  5. package/dist/acp/server.js +581 -155
  6. package/dist/acp/serverHandlers.d.ts +2 -1
  7. package/dist/acp/serverHandlers.js +3 -0
  8. package/dist/acp/session.d.ts +28 -2
  9. package/dist/acp/session.js +25 -6
  10. package/dist/acp/transport.d.ts +40 -4
  11. package/dist/acp/transport.js +218 -25
  12. package/dist/acp/turns.d.ts +20 -0
  13. package/dist/acp/turns.js +30 -0
  14. package/dist/api/index.js +2 -0
  15. package/dist/api/ollamaNative.d.ts +3 -0
  16. package/dist/api/ollamaNative.js +35 -3
  17. package/dist/config/index.d.ts +21 -4
  18. package/dist/config/index.js +178 -123
  19. package/dist/renderer/agentExecution.d.ts +30 -2
  20. package/dist/renderer/agentExecution.js +248 -92
  21. package/dist/renderer/commands/helpers.d.ts +18 -2
  22. package/dist/renderer/commands/helpers.js +28 -5
  23. package/dist/renderer/commands.d.ts +2 -0
  24. package/dist/renderer/commands.js +180 -64
  25. package/dist/renderer/main.d.ts +41 -0
  26. package/dist/renderer/main.js +181 -80
  27. package/dist/utils/agent.d.ts +69 -4
  28. package/dist/utils/agent.js +416 -248
  29. package/dist/utils/agentChat.js +82 -10
  30. package/dist/utils/agents.d.ts +2 -1
  31. package/dist/utils/agents.js +100 -29
  32. package/dist/utils/auditLog.d.ts +4 -3
  33. package/dist/utils/auditLog.js +92 -9
  34. package/dist/utils/checkpoints.js +11 -6
  35. package/dist/utils/codeReview.js +28 -23
  36. package/dist/utils/codeepCloud.d.ts +14 -2
  37. package/dist/utils/codeepCloud.js +56 -20
  38. package/dist/utils/customCommands.js +7 -2
  39. package/dist/utils/git.d.ts +262 -4
  40. package/dist/utils/git.js +1928 -61
  41. package/dist/utils/gitHookInstaller.d.ts +32 -1
  42. package/dist/utils/gitHookInstaller.js +76 -8
  43. package/dist/utils/gitignore.d.ts +8 -0
  44. package/dist/utils/gitignore.js +41 -10
  45. package/dist/utils/headlessReview.d.ts +11 -0
  46. package/dist/utils/headlessReview.js +33 -5
  47. package/dist/utils/history.d.ts +22 -6
  48. package/dist/utils/history.js +140 -26
  49. package/dist/utils/logger.js +6 -7
  50. package/dist/utils/mcpConfig.d.ts +24 -0
  51. package/dist/utils/mcpConfig.js +36 -5
  52. package/dist/utils/mentions.d.ts +28 -5
  53. package/dist/utils/mentions.js +253 -45
  54. package/dist/utils/personalities.js +16 -6
  55. package/dist/utils/planMode.d.ts +13 -7
  56. package/dist/utils/planMode.js +32 -12
  57. package/dist/utils/projectIntelligence.d.ts +2 -0
  58. package/dist/utils/projectIntelligence.js +27 -8
  59. package/dist/utils/projectPaths.d.ts +53 -0
  60. package/dist/utils/projectPaths.js +146 -0
  61. package/dist/utils/shell.d.ts +119 -0
  62. package/dist/utils/shell.js +417 -45
  63. package/dist/utils/skillBundles.js +17 -7
  64. package/dist/utils/skillBundlesCloud.js +20 -3
  65. package/dist/utils/skills.d.ts +24 -2
  66. package/dist/utils/skills.js +235 -43
  67. package/dist/utils/smartContext.js +97 -23
  68. package/dist/utils/telegramApproval.d.ts +10 -2
  69. package/dist/utils/telegramApproval.js +22 -4
  70. package/dist/utils/toolExecution.d.ts +50 -2
  71. package/dist/utils/toolExecution.js +418 -16
  72. package/dist/utils/toolParsing.d.ts +7 -1
  73. package/dist/utils/toolParsing.js +12 -3
  74. package/dist/utils/userProfile.js +58 -16
  75. package/dist/utils/verify.d.ts +25 -4
  76. package/dist/utils/verify.js +259 -74
  77. package/dist/version.d.ts +1 -1
  78. package/dist/version.js +1 -1
  79. package/package.json +1 -1
@@ -23,8 +23,10 @@
23
23
  * provider+model combos in config.json, see config/index.ts). Different
24
24
  * concept, different storage, different command (`/me` vs `/profile`).
25
25
  */
26
- import { readFileSync, writeFileSync, existsSync, mkdirSync, rmSync } from 'fs';
26
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, rmSync, statSync, openSync, readSync, closeSync } from 'fs';
27
27
  import { join, dirname } from 'path';
28
+ import { StringDecoder } from 'string_decoder';
29
+ import { isSafeProjectWriteTarget, leadsOutsideProject, writeProjectFile } from './projectPaths.js';
28
30
  import { homedir } from 'os';
29
31
  import { config } from '../config/index.js';
30
32
  /** Max bytes read from each profile file — keeps the prompt budget bounded. */
@@ -50,15 +52,40 @@ export function globalLearnedProfilePath() {
50
52
  export function projectLearnedProfilePath(workspaceRoot) {
51
53
  return join(workspaceRoot, '.codeep', 'profile.learned.md');
52
54
  }
53
- /** Read + trim a profile file, capped. Returns '' when missing/empty/broken. */
54
- function readProfile(path) {
55
+ /**
56
+ * Read + trim a profile file, capped. Returns '' when missing/empty/broken.
57
+ * A project's profile files can come with a cloned repo, so for those
58
+ * (`projectRoot` given) a link out of the project is not followed — the
59
+ * profile rides every system prompt — and only a regular file is read, so a
60
+ * link to /dev/zero cannot hang the run.
61
+ */
62
+ function readProfile(path, projectRoot) {
55
63
  try {
56
64
  if (!existsSync(path))
57
65
  return '';
58
- let content = readFileSync(path, 'utf-8');
59
- if (content.length > MAX_PROFILE_BYTES)
60
- content = content.slice(0, MAX_PROFILE_BYTES);
61
- return content.trim();
66
+ if (projectRoot && leadsOutsideProject(path, projectRoot))
67
+ return '';
68
+ const stat = statSync(path, { throwIfNoEntry: false });
69
+ if (stat && !stat.isFile())
70
+ return '';
71
+ if (!stat || stat.size <= MAX_PROFILE_BYTES) {
72
+ return readFileSync(path, 'utf-8').slice(0, MAX_PROFILE_BYTES).trim();
73
+ }
74
+ const fd = openSync(path, 'r');
75
+ try {
76
+ const buf = Buffer.alloc(MAX_PROFILE_BYTES);
77
+ let read = 0;
78
+ while (read < MAX_PROFILE_BYTES) {
79
+ const n = readSync(fd, buf, read, MAX_PROFILE_BYTES - read, read);
80
+ if (n === 0)
81
+ break;
82
+ read += n;
83
+ }
84
+ return new StringDecoder('utf8').write(buf.subarray(0, read)).trim();
85
+ }
86
+ finally {
87
+ closeSync(fd);
88
+ }
62
89
  }
63
90
  catch {
64
91
  return '';
@@ -76,7 +103,7 @@ export function loadUserProfilePrompt(workspaceRoot) {
76
103
  if (global)
77
104
  sections.push(global);
78
105
  if (workspaceRoot) {
79
- const project = readProfile(projectProfilePath(workspaceRoot));
106
+ const project = readProfile(projectProfilePath(workspaceRoot), workspaceRoot);
80
107
  if (project)
81
108
  sections.push(project);
82
109
  }
@@ -87,7 +114,7 @@ export function loadUserProfilePrompt(workspaceRoot) {
87
114
  if (learnedGlobal)
88
115
  sections.push(learnedGlobal);
89
116
  if (workspaceRoot) {
90
- const learnedProject = readProfile(projectLearnedProfilePath(workspaceRoot));
117
+ const learnedProject = readProfile(projectLearnedProfilePath(workspaceRoot), workspaceRoot);
91
118
  if (learnedProject)
92
119
  sections.push(learnedProject);
93
120
  }
@@ -165,8 +192,13 @@ export function scaffoldProfile(scope, workspaceRoot) {
165
192
  if (existsSync(path))
166
193
  return { path, created: false };
167
194
  try {
168
- mkdirSync(dirname(path), { recursive: true });
169
- writeFileSync(path, scope === 'global' ? GLOBAL_TEMPLATE : PROJECT_TEMPLATE, 'utf-8');
195
+ if (scope === 'project' && workspaceRoot) {
196
+ writeProjectFile(workspaceRoot, path, PROJECT_TEMPLATE);
197
+ }
198
+ else {
199
+ mkdirSync(dirname(path), { recursive: true });
200
+ writeFileSync(path, GLOBAL_TEMPLATE, 'utf-8');
201
+ }
170
202
  return { path, created: true };
171
203
  }
172
204
  catch {
@@ -196,9 +228,9 @@ export function formatProfileView(workspaceRoot) {
196
228
  }
197
229
  lines.push('');
198
230
  const globalRaw = readProfile(globalProfilePath());
199
- const projectRaw = workspaceRoot ? readProfile(projectProfilePath(workspaceRoot)) : '';
231
+ const projectRaw = workspaceRoot ? readProfile(projectProfilePath(workspaceRoot), workspaceRoot) : '';
200
232
  const learnedGlobalRaw = readProfile(globalLearnedProfilePath());
201
- const learnedProjectRaw = workspaceRoot ? readProfile(projectLearnedProfilePath(workspaceRoot)) : '';
233
+ const learnedProjectRaw = workspaceRoot ? readProfile(projectLearnedProfilePath(workspaceRoot), workspaceRoot) : '';
202
234
  if (!globalRaw && !projectRaw && !learnedGlobalRaw && !learnedProjectRaw) {
203
235
  lines.push('No profile yet. Run `/me init` to scaffold a global template (or `/me init project` for this project), then edit the file. Or let Codeep build one for you with `/me learn on`.');
204
236
  }
@@ -270,7 +302,8 @@ export async function updateLearnedProfile(history, scope = 'global', workspaceR
270
302
  .map((m) => `${m.role === 'user' ? 'User' : 'Assistant'}: ${String(m.content).replace(/\s+/g, ' ').slice(0, 600)}`)
271
303
  .join('\n')
272
304
  .slice(0, 24000);
273
- const existingFacts = parseFactBullets(readProfile(targetPath)).join('\n');
305
+ const projectRoot = scope === 'project' ? workspaceRoot : undefined;
306
+ const existingFacts = parseFactBullets(readProfile(targetPath, projectRoot)).join('\n');
274
307
  const system = scope === 'global' ? GLOBAL_LEARN_SYSTEM : PROJECT_LEARN_SYSTEM;
275
308
  const user = `EXISTING FACTS:\n${existingFacts || '(none yet)'}\n\nRECENT CONVERSATION:\n${transcript}`;
276
309
  const { chat } = await import('../api/index.js');
@@ -285,8 +318,14 @@ export async function updateLearnedProfile(history, scope = 'global', workspaceR
285
318
  ? 'What Codeep has learned about me'
286
319
  : 'What Codeep has learned about this project';
287
320
  const content = `# ${heading}\n\n<!-- Auto-observed from your Codeep sessions. Edit freely, clear with \`/me forget\`, or turn off with \`/me learn off\`. -->\n\n${facts}\n`;
288
- mkdirSync(dirname(targetPath), { recursive: true });
289
- writeFileSync(targetPath, content, 'utf-8');
321
+ if (projectRoot) {
322
+ // Never through a symlinked .codeep/ that came with the repo.
323
+ writeProjectFile(projectRoot, targetPath, content);
324
+ }
325
+ else {
326
+ mkdirSync(dirname(targetPath), { recursive: true });
327
+ writeFileSync(targetPath, content, 'utf-8');
328
+ }
290
329
  return { updated: true, facts };
291
330
  }
292
331
  catch {
@@ -339,6 +378,9 @@ export function clearLearnedProfile(workspaceRoot) {
339
378
  ];
340
379
  for (const p of paths) {
341
380
  if (p && existsSync(p)) {
381
+ // Through a symlinked .codeep/ the project path would name a file elsewhere.
382
+ if (workspaceRoot && p !== paths[0] && !isSafeProjectWriteTarget(workspaceRoot, p))
383
+ continue;
342
384
  try {
343
385
  rmSync(p);
344
386
  removed = true;
@@ -4,6 +4,13 @@
4
4
  */
5
5
  export interface VerifyResult {
6
6
  success: boolean;
7
+ /**
8
+ * Set when the check never reached a verdict: its command was refused by the
9
+ * shell guard, could not be started, timed out, or the project's
10
+ * dependencies are not installed. `success` is false, but nothing about the
11
+ * code was learned, so it is neither a pass nor a failure to fix.
12
+ */
13
+ notRun?: string;
7
14
  type: 'build' | 'test' | 'lint' | 'typecheck';
8
15
  command: string;
9
16
  output: string;
@@ -24,6 +31,11 @@ export interface VerifyOptions {
24
31
  runLint: boolean;
25
32
  runTypecheck: boolean;
26
33
  timeout: number;
34
+ /**
35
+ * Stops the checks when it fires (the run was stopped): a running command
36
+ * is killed and its check is reported as not run.
37
+ */
38
+ signal?: AbortSignal;
27
39
  }
28
40
  /**
29
41
  * Detect project type and available scripts
@@ -38,19 +50,19 @@ export declare function detectProjectScripts(projectRoot: string): {
38
50
  /**
39
51
  * Run build verification
40
52
  */
41
- export declare function runBuildVerification(projectRoot: string, timeout?: number): Promise<VerifyResult | null>;
53
+ export declare function runBuildVerification(projectRoot: string, timeout?: number, signal?: AbortSignal): Promise<VerifyResult | null>;
42
54
  /**
43
55
  * Run test verification
44
56
  */
45
- export declare function runTestVerification(projectRoot: string, timeout?: number): Promise<VerifyResult | null>;
57
+ export declare function runTestVerification(projectRoot: string, timeout?: number, signal?: AbortSignal): Promise<VerifyResult | null>;
46
58
  /**
47
59
  * Run TypeScript type checking
48
60
  */
49
- export declare function runTypecheckVerification(projectRoot: string, timeout?: number): Promise<VerifyResult | null>;
61
+ export declare function runTypecheckVerification(projectRoot: string, timeout?: number, signal?: AbortSignal): Promise<VerifyResult | null>;
50
62
  /**
51
63
  * Run lint verification
52
64
  */
53
- export declare function runLintVerification(projectRoot: string, timeout?: number): Promise<VerifyResult | null>;
65
+ export declare function runLintVerification(projectRoot: string, timeout?: number, signal?: AbortSignal): Promise<VerifyResult | null>;
54
66
  /**
55
67
  * Run all verifications
56
68
  */
@@ -63,6 +75,14 @@ export declare function formatVerifyResults(results: VerifyResult[]): string;
63
75
  * Format errors for agent to fix
64
76
  */
65
77
  export declare function formatErrorsForAgent(results: VerifyResult[]): string;
78
+ /**
79
+ * Checks that ran and failed. A check that could not run is not among them.
80
+ */
81
+ export declare function failedChecks(results: VerifyResult[]): VerifyResult[];
82
+ /**
83
+ * Checks that could not be carried out (see VerifyResult.notRun).
84
+ */
85
+ export declare function checksNotRun(results: VerifyResult[]): VerifyResult[];
66
86
  /**
67
87
  * Check if any verification failed
68
88
  */
@@ -73,6 +93,7 @@ export declare function hasVerificationErrors(results: VerifyResult[]): boolean;
73
93
  export declare function getVerificationSummary(results: VerifyResult[]): {
74
94
  passed: number;
75
95
  failed: number;
96
+ notRun: number;
76
97
  total: number;
77
98
  errors: number;
78
99
  };