@damper/cli 0.9.5 → 0.9.6

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.
@@ -260,6 +260,34 @@ export async function pickTask(options) {
260
260
  action,
261
261
  };
262
262
  }
263
+ async function generateTaskTitle(instructions, type) {
264
+ try {
265
+ const { execa } = await import('execa');
266
+ const prompt = [
267
+ `Generate a task title for a ${type} task.`,
268
+ 'Rules:',
269
+ '- Max 60 characters, sentence case, no trailing period',
270
+ '- Verb prefix matching type: bug → "Fix …", feature → "Add …", improvement → "Improve …", task → "Set up …" / "Update …"',
271
+ '- Specific enough to understand without reading a description',
272
+ '- Examples: "Add dark mode support", "Fix login timeout on slow connections", "Improve search result ranking"',
273
+ 'Return ONLY the title, nothing else.',
274
+ '',
275
+ `User input: ${instructions}`,
276
+ ].join('\n');
277
+ const { stdout } = await execa('claude', ['--print', '--model', 'haiku', prompt], {
278
+ stdio: 'pipe',
279
+ timeout: 15000,
280
+ });
281
+ const title = stdout.trim();
282
+ if (title && title.length <= 80 && !title.includes('\n')) {
283
+ return title;
284
+ }
285
+ return null;
286
+ }
287
+ catch {
288
+ return null;
289
+ }
290
+ }
263
291
  async function handleCreateNewTask(api) {
264
292
  const instructions = await input({
265
293
  message: 'What needs to be done?',
@@ -274,16 +302,23 @@ async function handleCreateNewTask(api) {
274
302
  { name: 'Task', value: 'task' },
275
303
  ],
276
304
  });
277
- // Use instructions as description; derive a placeholder title
278
305
  const trimmed = instructions.trim();
279
- const maxTitleLen = 60;
280
- const placeholderTitle = trimmed.length <= maxTitleLen
281
- ? trimmed
282
- : trimmed.slice(0, trimmed.lastIndexOf(' ', maxTitleLen) || maxTitleLen) + '…';
283
- console.log(pc.dim('\nCreating task in Damper...'));
284
- const task = await api.createTask(placeholderTitle, type, trimmed);
306
+ // Generate title with Claude, fall back to truncation
307
+ console.log(pc.dim('\nGenerating title...'));
308
+ const generatedTitle = await generateTaskTitle(trimmed, type);
309
+ let title;
310
+ if (generatedTitle) {
311
+ title = generatedTitle;
312
+ }
313
+ else {
314
+ const maxTitleLen = 60;
315
+ title = trimmed.length <= maxTitleLen
316
+ ? trimmed
317
+ : trimmed.slice(0, trimmed.lastIndexOf(' ', maxTitleLen) || maxTitleLen) + '…';
318
+ }
319
+ console.log(pc.dim('Creating task in Damper...'));
320
+ const task = await api.createTask(title, type, trimmed);
285
321
  console.log(pc.green(`✓ Created task #${shortIdRaw(task.id)}: ${task.title}`));
286
- console.log(pc.dim(' The agent will refine the title after planning.'));
287
322
  return {
288
323
  task,
289
324
  isResume: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@damper/cli",
3
- "version": "0.9.5",
3
+ "version": "0.9.6",
4
4
  "description": "CLI tool for orchestrating Damper task workflows with Claude Code",
5
5
  "author": "Damper <hello@usedamper.com>",
6
6
  "repository": {