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
@@ -37,8 +37,13 @@ export { nextOffset } from './telegramUpdates';
37
37
  * be mangled by Markdown parsing into something that is not what will run — and
38
38
  * approving a command you were shown incorrectly is the one failure this whole
39
39
  * feature must not have.
40
+ *
41
+ * `reason` is what the file being written decides — "this file controls what
42
+ * commands git runs". The terminal dialog shows it, and someone answering from
43
+ * a phone is the one with the least context, so a message without it asks them
44
+ * to approve on less than the person at the desk had.
40
45
  */
41
- export declare function composeMessage(command: string, toolName: string, isDestructive: boolean): string;
46
+ export declare function composeMessage(command: string, toolName: string, isDestructive: boolean, reason?: string): string;
42
47
  /**
43
48
  * Only the configured chat may decide.
44
49
  *
@@ -102,8 +107,11 @@ export declare class TelegramApproval {
102
107
  * Resolves `null` when no answer arrived — the terminal was used instead, the
103
108
  * caller aborted, or Telegram could not be reached. **A null is never
104
109
  * approval**: the caller keeps its own gate and decides for itself.
110
+ *
111
+ * `reason` says what the file being written decides, when it decides
112
+ * anything, so the phone shows what the terminal shows.
105
113
  */
106
- ask(command: string, toolName: string, isDestructive: boolean, signal?: AbortSignal): Promise<TelegramAnswer | null>;
114
+ ask(command: string, toolName: string, isDestructive: boolean, signal?: AbortSignal, reason?: string): Promise<TelegramAnswer | null>;
107
115
  /**
108
116
  * The terminal answered first. Close the question on the phone so nobody taps
109
117
  * a button that would do nothing, and say where it was decided.
@@ -32,6 +32,15 @@ export { nextOffset } from './telegramUpdates.js';
32
32
  * text; this keeps room for the heading and the fences, and a command longer
33
33
  * than this is not something anyone reads off a phone anyway. */
34
34
  const MAX_COMMAND_CHARS = 300;
35
+ /**
36
+ * Markdown markers neutralised.
37
+ *
38
+ * Telegram rejects a WHOLE message whose markup is unbalanced (these go out
39
+ * with `parse_mode: 'Markdown'`), so a single stray underscore in the text
40
+ * would mean the question never arrives at all. A visible backslash beats a
41
+ * phone that stayed silent.
42
+ */
43
+ const escapeMarkdown = (text) => text.replace(/([_*`[])/g, '\\$1');
35
44
  /**
36
45
  * The message text.
37
46
  *
@@ -39,18 +48,24 @@ const MAX_COMMAND_CHARS = 300;
39
48
  * be mangled by Markdown parsing into something that is not what will run — and
40
49
  * approving a command you were shown incorrectly is the one failure this whole
41
50
  * feature must not have.
51
+ *
52
+ * `reason` is what the file being written decides — "this file controls what
53
+ * commands git runs". The terminal dialog shows it, and someone answering from
54
+ * a phone is the one with the least context, so a message without it asks them
55
+ * to approve on less than the person at the desk had.
42
56
  */
43
- export function composeMessage(command, toolName, isDestructive) {
57
+ export function composeMessage(command, toolName, isDestructive, reason) {
44
58
  const head = isDestructive
45
59
  ? '⚠️ Codeep wants to run a destructive tool'
46
60
  : 'Codeep needs approval';
61
+ const why = reason ? `\n\n⚠️ ${escapeMarkdown(reason)}` : '';
47
62
  const trimmed = command.length > MAX_COMMAND_CHARS
48
63
  ? command.slice(0, MAX_COMMAND_CHARS - 1) + '…'
49
64
  : command;
50
65
  // A fence inside the command would close ours early and leak the rest as
51
66
  // prose. Neutralise it rather than trusting the input.
52
67
  const safe = trimmed.replace(/```/g, "'''");
53
- return `${head}\n\n\`${toolName}\`\n\n\`\`\`\n${safe}\n\`\`\``;
68
+ return `${head}${why}\n\n\`${toolName}\`\n\n\`\`\`\n${safe}\n\`\`\``;
54
69
  }
55
70
  /**
56
71
  * Only the configured chat may decide.
@@ -179,10 +194,13 @@ export class TelegramApproval {
179
194
  * Resolves `null` when no answer arrived — the terminal was used instead, the
180
195
  * caller aborted, or Telegram could not be reached. **A null is never
181
196
  * approval**: the caller keeps its own gate and decides for itself.
197
+ *
198
+ * `reason` says what the file being written decides, when it decides
199
+ * anything, so the phone shows what the terminal shows.
182
200
  */
183
- async ask(command, toolName, isDestructive, signal) {
201
+ async ask(command, toolName, isDestructive, signal, reason) {
184
202
  const token = randomToken();
185
- const messageID = await this.sendQuestion(composeMessage(command, toolName, isDestructive), token);
203
+ const messageID = await this.sendQuestion(composeMessage(command, toolName, isDestructive, reason), token);
186
204
  if (messageID === null) {
187
205
  // Say it once, here, rather than leaving the caller to guess from a null
188
206
  // that also means "answered elsewhere" and "cancelled".
@@ -5,6 +5,7 @@
5
5
  * executeTool() dispatches to individual tool handlers.
6
6
  * listDirectory() and htmlToText() are private helpers.
7
7
  * createActionLog() converts a ToolCall+ToolResult into a history ActionLog.
8
+ * trustBearingWrite() names the writes that decide what runs later.
8
9
  */
9
10
  import { ToolCall, ToolResult, ActionLog } from './tools';
10
11
  export { isBlockedIp, assertFetchUrlAllowed } from './ssrfGuard';
@@ -18,12 +19,56 @@ export declare function validatePath(path: string, projectRoot: string): {
18
19
  absolutePath: string;
19
20
  error?: string;
20
21
  };
22
+ /** Drop the cached hook directories. Call before spawning a command line. */
23
+ export declare function forgetHooksDirectory(): void;
24
+ /**
25
+ * The tail of the refusal one of these writes gets when the run has nobody to
26
+ * ask — no permission callback at all, which is how `codeep review --fix`
27
+ * runs in CI. agent.ts builds the refusal; headlessReview.ts recognises it by
28
+ * this text so it can say so in the run output rather than leave it buried in
29
+ * the agent's tool log.
30
+ *
31
+ * One constant, in the module that owns the classification rather than in
32
+ * agent.ts, for two reasons: a reworded refusal that stopped matching would
33
+ * put CI back to failing silently, and agent.js is a module the fix-run tests
34
+ * replace wholesale — a constant read from there would have been undefined in
35
+ * exactly the test that guards this.
36
+ */
37
+ export declare const NO_CONFIRMER_REFUSAL = "Nobody could be asked to confirm it, so nothing was written.";
38
+ export interface TrustBearingWrite {
39
+ /** The path exactly as the tool call named it, for the prompt. */
40
+ path: string;
41
+ /** The absolute path the classification matched — one spelling per file, so
42
+ * a "never again" answer given for `.git/config` also covers
43
+ * `./.git/config` and the symlink that reaches it. Never shown to anyone;
44
+ * it exists to key that answer (see agent.ts). */
45
+ file: string;
46
+ /** One plain sentence about what the file controls. */
47
+ reason: string;
48
+ }
49
+ /**
50
+ * What a tool call would write that decides what runs later, or null.
51
+ *
52
+ * Callers use this for two things: to force a confirmation the mode would
53
+ * otherwise skip (see agent.ts), and to tell the person answering it what
54
+ * they are approving.
55
+ *
56
+ * A symlink inside the project can point at one of these names — `ln -s .git
57
+ * tools/cfg` makes a write to `tools/cfg/config` land in the real `.git`, and
58
+ * validatePath allows it because it never leaves the project — so the
59
+ * resolved path is classified alongside the one the model asked for.
60
+ */
61
+ export declare function trustBearingWrite(toolCall: ToolCall, projectRoot: string): TrustBearingWrite | null;
21
62
  /**
22
63
  * Optional filesystem delegation. When an ACP client advertises `fs`
23
64
  * capability (Zed always does, VS Code may), the server should route
24
65
  * read/write through the client instead of touching disk directly — that
25
66
  * way the client's unsaved buffers, undo history, and virtual filesystems
26
67
  * stay authoritative. Callbacks must already use absolute paths.
68
+ *
69
+ * A writeTextFile that rejects with AcpRequestError means the client
70
+ * answered and refused the write; the tool then fails instead of writing
71
+ * to disk behind the editor.
27
72
  */
28
73
  export interface FsCallbacks {
29
74
  readTextFile?: (absolutePath: string) => Promise<string>;
@@ -35,9 +80,12 @@ export interface FsCallbacks {
35
80
  * `fs` is optional — if provided and the relevant method is defined, file
36
81
  * read/write is delegated to the client. Otherwise we fall back to direct
37
82
  * disk I/O. A delegated call that throws also falls back to disk so a
38
- * single client hiccup doesn't kill the agent loop.
83
+ * single client hiccup doesn't kill the agent loop — except a write the
84
+ * client explicitly refused, which fails the tool (see isRefusedWrite).
85
+ *
86
+ * `signal` stops a running execute_command when it fires.
39
87
  */
40
- export declare function executeTool(toolCall: ToolCall, projectRoot: string, fs?: FsCallbacks, mcpSessionId?: string): Promise<ToolResult>;
88
+ export declare function executeTool(toolCall: ToolCall, projectRoot: string, fs?: FsCallbacks, mcpSessionId?: string, signal?: AbortSignal): Promise<ToolResult>;
41
89
  /**
42
90
  * Create action log from tool result
43
91
  */