codeep 1.2.52 → 1.2.54

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.
@@ -1,6 +1,7 @@
1
1
  // src/acp/server.ts
2
2
  // Codeep ACP adapter — started via `codeep acp` CLI subcommand
3
3
  import { randomUUID } from 'crypto';
4
+ import { basename as pathBasename } from 'path';
4
5
  import { StdioTransport } from './transport.js';
5
6
  import { runAgentSession } from './session.js';
6
7
  import { initWorkspace, loadWorkspace, handleCommand } from './commands.js';
@@ -174,6 +175,21 @@ export function startAcpServer() {
174
175
  };
175
176
  transport.respond(msg.id, result);
176
177
  }
178
+ // ── helpers ──────────────────────────────────────────────────────────────────
179
+ function sendSessionTitle(sessionId, history, fallback) {
180
+ const firstUserMsg = history.find(m => m.role === 'user');
181
+ const title = firstUserMsg
182
+ ? firstUserMsg.content.replace(/\n/g, ' ').trim().slice(0, 60)
183
+ : (fallback ?? 'Codeep session');
184
+ transport.notify('session/update', {
185
+ sessionId,
186
+ update: {
187
+ sessionUpdate: 'session_info_update',
188
+ title,
189
+ updatedAt: new Date().toISOString(),
190
+ },
191
+ });
192
+ }
177
193
  // ── session/new ─────────────────────────────────────────────────────────────
178
194
  function handleSessionNew(msg) {
179
195
  const params = msg.params;
@@ -188,6 +204,7 @@ export function startAcpServer() {
188
204
  abortController: null,
189
205
  currentModeId: 'auto',
190
206
  titleSent: false,
207
+ hadHistory: history.length > 0,
191
208
  });
192
209
  const result = {
193
210
  sessionId: acpSessionId,
@@ -203,6 +220,8 @@ export function startAcpServer() {
203
220
  availableCommands: AVAILABLE_COMMANDS,
204
221
  },
205
222
  });
223
+ // Send title immediately so Zed "Recent" panel shows something useful
224
+ sendSessionTitle(acpSessionId, history, pathBasename(params.cwd));
206
225
  // Send welcome message
207
226
  transport.notify('session/update', {
208
227
  sessionId: acpSessionId,
@@ -237,6 +256,7 @@ export function startAcpServer() {
237
256
  addedFiles: new Map(),
238
257
  abortController: null,
239
258
  titleSent: false,
259
+ hadHistory: history.length > 0,
240
260
  currentModeId: 'auto',
241
261
  });
242
262
  const result = {
@@ -244,6 +264,8 @@ export function startAcpServer() {
244
264
  configOptions: buildConfigOptions(),
245
265
  };
246
266
  transport.respond(msg.id, result);
267
+ // Send title immediately so Zed "Recent" panel shows something useful
268
+ sendSessionTitle(params.sessionId, history, pathBasename(params.cwd));
247
269
  // Send restored session welcome
248
270
  transport.notify('session/update', {
249
271
  sessionId: params.sessionId,
@@ -386,18 +408,10 @@ export function startAcpServer() {
386
408
  },
387
409
  });
388
410
  }
389
- // Send title on first interaction (commands count too)
390
- if (!session.titleSent) {
411
+ // Update title with first real prompt if session had no history
412
+ if (!session.titleSent && !session.hadHistory) {
391
413
  session.titleSent = true;
392
- const title = prompt.slice(0, 60).replace(/\n/g, ' ').trim();
393
- transport.notify('session/update', {
394
- sessionId: params.sessionId,
395
- update: {
396
- sessionUpdate: 'session_info_update',
397
- title,
398
- updatedAt: new Date().toISOString(),
399
- },
400
- });
414
+ sendSessionTitle(params.sessionId, [{ role: 'user', content: prompt }]);
401
415
  }
402
416
  transport.respond(msg.id, { stopReason: 'end_turn' });
403
417
  return;
@@ -462,18 +476,10 @@ export function startAcpServer() {
462
476
  session.history.push({ role: 'assistant', content: agentResponse });
463
477
  }
464
478
  autoSaveSession(session.history, session.workspaceRoot);
465
- // Send session title on first completed prompt (so Zed shows something useful)
466
- if (!session.titleSent) {
479
+ // Update title with first real prompt if session had no history
480
+ if (!session.titleSent && !session.hadHistory) {
467
481
  session.titleSent = true;
468
- const title = prompt.slice(0, 60).replace(/\n/g, ' ').trim();
469
- transport.notify('session/update', {
470
- sessionId: params.sessionId,
471
- update: {
472
- sessionUpdate: 'session_info_update',
473
- title,
474
- updatedAt: new Date().toISOString(),
475
- },
476
- });
482
+ sendSessionTitle(params.sessionId, [{ role: 'user', content: prompt }]);
477
483
  }
478
484
  transport.respond(msg.id, { stopReason: 'end_turn' });
479
485
  }).catch((err) => {
@@ -24,18 +24,22 @@ export function buildProjectContext(workspaceRoot) {
24
24
  };
25
25
  }
26
26
  // Maps internal tool names to ACP tool_call kind values and human titles.
27
- function toolCallMeta(toolName, params) {
27
+ function toolCallMeta(toolName, params, workspaceRoot) {
28
28
  const file = params.path ?? params.file ?? '';
29
- const label = file ? ` ${file.split('/').pop()}` : '';
29
+ // Use full path for edit tools (Zed renders it as a clickable file link)
30
+ const absFile = file
31
+ ? (isAbsolute(file) ? file : join(workspaceRoot, file))
32
+ : '';
33
+ const basename = absFile ? absFile.split('/').pop() ?? '' : '';
30
34
  switch (toolName) {
31
- case 'read_file': return { kind: 'read', title: `Reading${label}` };
32
- case 'write_file': return { kind: 'edit', title: `Writing${label}` };
33
- case 'edit_file': return { kind: 'edit', title: `Editing${label}` };
34
- case 'delete_file': return { kind: 'delete', title: `Deleting${label}` };
35
- case 'move_file': return { kind: 'move', title: `Moving${label}` };
36
- case 'list_files': return { kind: 'read', title: `Listing files${label}` };
37
- case 'search_files': return { kind: 'search', title: `Searching${label || ' files'}` };
38
- case 'run_command': return { kind: 'execute', title: `Running: ${params.command ?? ''}` };
35
+ case 'read_file': return { kind: 'read', title: `Reading ${basename}` };
36
+ case 'write_file': return { kind: 'edit', title: absFile ? `Edit ${absFile}` : 'Writing file' };
37
+ case 'edit_file': return { kind: 'edit', title: absFile ? `Edit ${absFile}` : 'Editing file' };
38
+ case 'delete_file': return { kind: 'delete', title: `Deleting ${basename}` };
39
+ case 'move_file': return { kind: 'move', title: `Moving ${basename}` };
40
+ case 'list_files': return { kind: 'read', title: `Listing files ${basename}` };
41
+ case 'search_files': return { kind: 'search', title: `Searching ${basename || 'files'}` };
42
+ case 'run_command': return { kind: 'execute', title: params.command ?? 'Running command' };
39
43
  case 'web_fetch': return { kind: 'fetch', title: `Fetching ${params.url ?? ''}` };
40
44
  default: return { kind: 'other', title: toolName };
41
45
  }
@@ -60,7 +64,7 @@ export async function runAgentSession(opts) {
60
64
  onToolCall: (toolCall) => {
61
65
  const name = toolCall.tool;
62
66
  const params = (toolCall.parameters ?? {});
63
- const { kind, title } = toolCallMeta(name, params);
67
+ const { kind, title } = toolCallMeta(name, params, opts.workspaceRoot);
64
68
  const toolCallId = `tc_${++toolCallCounter}`;
65
69
  // Resolve file locations for edit/read/delete/move tools
66
70
  // ToolCallLocation.path expects a filesystem path, not a file:// URI
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeep",
3
- "version": "1.2.52",
3
+ "version": "1.2.54",
4
4
  "description": "AI-powered coding assistant built for the terminal. Multiple LLM providers, project-aware context, and a seamless development workflow.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",