opencode-pilot 0.8.0 → 0.9.0

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.
@@ -42,6 +42,8 @@ sources:
42
42
  # completed: false
43
43
  # item:
44
44
  # id: "reminder:{id}"
45
+ # session:
46
+ # name: "{title}" # Optional: custom session name (presets have semantic defaults)
45
47
 
46
48
  # Tool config for custom MCP servers (GitHub/Linear have built-in config)
47
49
  # tools:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-pilot",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "type": "module",
5
5
  "main": "plugin/index.js",
6
6
  "description": "Automation daemon for OpenCode - polls for work and spawns sessions",
@@ -242,7 +242,7 @@ export function getCommandInfoNew(item, config, templatesDir, serverUrl) {
242
242
  // Build session name
243
243
  const sessionName = config.session?.name
244
244
  ? buildSessionName(config.session.name, item)
245
- : `session-${item.number || item.id || Date.now()}`;
245
+ : (item.title || `session-${Date.now()}`);
246
246
 
247
247
  // Build command args
248
248
  const args = ["opencode", "run"];
@@ -297,13 +297,14 @@ function buildPrompt(item, config) {
297
297
  /**
298
298
  * Build command args for action
299
299
  * Uses "opencode run" for non-interactive execution
300
+ * @deprecated Legacy function - not currently used. See getCommandInfoNew instead.
300
301
  * @returns {object} { args: string[], cwd: string }
301
302
  */
302
303
  function buildCommandArgs(item, config) {
303
304
  const repoPath = expandPath(config.repo_path || ".");
304
305
  const sessionTitle = config.session?.name_template
305
306
  ? buildSessionName(config.session.name_template, item)
306
- : `issue-${item.number || Date.now()}`;
307
+ : (item.title || `session-${Date.now()}`);
307
308
 
308
309
  // Build opencode run command args array (non-interactive)
309
310
  // Note: --title sets session title (--session is for continuing existing sessions)
@@ -22,6 +22,8 @@ my-issues:
22
22
  item:
23
23
  id: "{html_url}"
24
24
  repo: "{repository_full_name}"
25
+ session:
26
+ name: "{title}"
25
27
 
26
28
  review-requests:
27
29
  name: review-requests
@@ -33,6 +35,8 @@ review-requests:
33
35
  item:
34
36
  id: "{html_url}"
35
37
  repo: "{repository_full_name}"
38
+ session:
39
+ name: "Review: {title}"
36
40
 
37
41
  my-prs-feedback:
38
42
  name: my-prs-feedback
@@ -46,6 +50,8 @@ my-prs-feedback:
46
50
  item:
47
51
  id: "{html_url}"
48
52
  repo: "{repository_full_name}"
53
+ session:
54
+ name: "Feedback: {title}"
49
55
  # Reprocess when PR is updated (new commits pushed, new comments, etc.)
50
56
  # This ensures we re-trigger after addressing review feedback
51
57
  reprocess_on:
@@ -21,3 +21,5 @@ my-issues:
21
21
  # teamId and assigneeId are required - user must provide
22
22
  item:
23
23
  id: "linear:{id}"
24
+ session:
25
+ name: "{title}"
@@ -260,6 +260,38 @@ describe('actions.js', () => {
260
260
 
261
261
  assert.ok(!cmdInfo.args.includes('--attach'), 'Should not include --attach flag');
262
262
  });
263
+
264
+ test('uses item title as session name when no session.name configured', async () => {
265
+ const { getCommandInfoNew } = await import('../../service/actions.js');
266
+
267
+ const item = { id: 'reminder-123', title: 'Review quarterly reports' };
268
+ const config = {
269
+ path: '~/code/backend',
270
+ prompt: 'default'
271
+ };
272
+
273
+ const cmdInfo = getCommandInfoNew(item, config, templatesDir);
274
+
275
+ const titleIndex = cmdInfo.args.indexOf('--title');
276
+ assert.ok(titleIndex !== -1, 'Should have --title flag');
277
+ assert.strictEqual(cmdInfo.args[titleIndex + 1], 'Review quarterly reports', 'Should use item title as session name');
278
+ });
279
+
280
+ test('falls back to timestamp when no session.name and no title', async () => {
281
+ const { getCommandInfoNew } = await import('../../service/actions.js');
282
+
283
+ const item = { id: 'item-123' };
284
+ const config = {
285
+ path: '~/code/backend',
286
+ prompt: 'default'
287
+ };
288
+
289
+ const cmdInfo = getCommandInfoNew(item, config, templatesDir);
290
+
291
+ const titleIndex = cmdInfo.args.indexOf('--title');
292
+ assert.ok(titleIndex !== -1, 'Should have --title flag');
293
+ assert.ok(cmdInfo.args[titleIndex + 1].startsWith('session-'), 'Should fall back to session-{timestamp}');
294
+ });
263
295
  });
264
296
 
265
297
  describe('discoverOpencodeServer', () => {
@@ -664,6 +664,44 @@ sources:
664
664
  const filteredItem = { repository_full_name: 'other/repo' };
665
665
  assert.deepStrictEqual(resolveRepoForItem(source, filteredItem), []);
666
666
  });
667
+
668
+ test('github presets include semantic session names', async () => {
669
+ writeFileSync(configPath, `
670
+ sources:
671
+ - preset: github/my-issues
672
+ - preset: github/review-requests
673
+ - preset: github/my-prs-feedback
674
+ `);
675
+
676
+ const { loadRepoConfig, getSources } = await import('../../service/repo-config.js');
677
+ loadRepoConfig(configPath);
678
+ const sources = getSources();
679
+
680
+ // my-issues: just the title
681
+ assert.strictEqual(sources[0].session.name, '{title}', 'my-issues should use title');
682
+
683
+ // review-requests: "Review: {title}"
684
+ assert.strictEqual(sources[1].session.name, 'Review: {title}', 'review-requests should prefix with Review:');
685
+
686
+ // my-prs-feedback: "Feedback: {title}"
687
+ assert.strictEqual(sources[2].session.name, 'Feedback: {title}', 'my-prs-feedback should prefix with Feedback:');
688
+ });
689
+
690
+ test('linear preset includes session name', async () => {
691
+ writeFileSync(configPath, `
692
+ sources:
693
+ - preset: linear/my-issues
694
+ args:
695
+ teamId: "team-uuid"
696
+ assigneeId: "user-uuid"
697
+ `);
698
+
699
+ const { loadRepoConfig, getSources } = await import('../../service/repo-config.js');
700
+ loadRepoConfig(configPath);
701
+ const sources = getSources();
702
+
703
+ assert.strictEqual(sources[0].session.name, '{title}', 'linear/my-issues should use title');
704
+ });
667
705
  });
668
706
 
669
707
  describe('shorthand syntax', () => {