argustack 0.1.11 → 0.1.13

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 (99) hide show
  1. package/dist/adapters/board/index.d.ts +6 -0
  2. package/dist/adapters/board/index.d.ts.map +1 -0
  3. package/dist/adapters/board/index.js +6 -0
  4. package/dist/adapters/board/index.js.map +1 -0
  5. package/dist/adapters/board/mapper.d.ts +14 -0
  6. package/dist/adapters/board/mapper.d.ts.map +1 -0
  7. package/dist/adapters/board/mapper.js +25 -0
  8. package/dist/adapters/board/mapper.js.map +1 -0
  9. package/dist/adapters/board/md-parser.d.ts +16 -0
  10. package/dist/adapters/board/md-parser.d.ts.map +1 -0
  11. package/dist/adapters/board/md-parser.js +44 -0
  12. package/dist/adapters/board/md-parser.js.map +1 -0
  13. package/dist/adapters/board/skill-discovery.d.ts +8 -0
  14. package/dist/adapters/board/skill-discovery.d.ts.map +1 -0
  15. package/dist/adapters/board/skill-discovery.js +60 -0
  16. package/dist/adapters/board/skill-discovery.js.map +1 -0
  17. package/dist/adapters/board/skill-runner.d.ts +10 -0
  18. package/dist/adapters/board/skill-runner.d.ts.map +1 -0
  19. package/dist/adapters/board/skill-runner.js +65 -0
  20. package/dist/adapters/board/skill-runner.js.map +1 -0
  21. package/dist/adapters/board/store.d.ts +21 -0
  22. package/dist/adapters/board/store.d.ts.map +1 -0
  23. package/dist/adapters/board/store.js +176 -0
  24. package/dist/adapters/board/store.js.map +1 -0
  25. package/dist/adapters/postgres/storage.d.ts +2 -1
  26. package/dist/adapters/postgres/storage.d.ts.map +1 -1
  27. package/dist/adapters/postgres/storage.js +55 -0
  28. package/dist/adapters/postgres/storage.js.map +1 -1
  29. package/dist/board/assets/index-Bnh8GW_4.css +1 -0
  30. package/dist/board/assets/index-CEXc5QXH.js +68 -0
  31. package/dist/board/favicon.png +0 -0
  32. package/dist/board/index.html +14 -0
  33. package/dist/cli/board-server.d.ts +2 -0
  34. package/dist/cli/board-server.d.ts.map +1 -0
  35. package/dist/cli/board-server.js +124 -0
  36. package/dist/cli/board-server.js.map +1 -0
  37. package/dist/cli/board.d.ts +3 -0
  38. package/dist/cli/board.d.ts.map +1 -0
  39. package/dist/cli/board.js +26 -0
  40. package/dist/cli/board.js.map +1 -0
  41. package/dist/cli/mcp-install.d.ts +9 -0
  42. package/dist/cli/mcp-install.d.ts.map +1 -1
  43. package/dist/cli/mcp-install.js +3 -3
  44. package/dist/cli/mcp-install.js.map +1 -1
  45. package/dist/core/board/board-column.value-object.d.ts +14 -0
  46. package/dist/core/board/board-column.value-object.d.ts.map +1 -0
  47. package/dist/core/board/board-column.value-object.js +36 -0
  48. package/dist/core/board/board-column.value-object.js.map +1 -0
  49. package/dist/core/board/board-task.entity.d.ts +20 -0
  50. package/dist/core/board/board-task.entity.d.ts.map +1 -0
  51. package/dist/core/board/board-task.entity.js +51 -0
  52. package/dist/core/board/board-task.entity.js.map +1 -0
  53. package/dist/core/board/index.d.ts +6 -0
  54. package/dist/core/board/index.d.ts.map +1 -0
  55. package/dist/core/board/index.js +6 -0
  56. package/dist/core/board/index.js.map +1 -0
  57. package/dist/core/board/pipeline.value-object.d.ts +22 -0
  58. package/dist/core/board/pipeline.value-object.d.ts.map +1 -0
  59. package/dist/core/board/pipeline.value-object.js +50 -0
  60. package/dist/core/board/pipeline.value-object.js.map +1 -0
  61. package/dist/core/board/skill-execution.entity.d.ts +18 -0
  62. package/dist/core/board/skill-execution.entity.d.ts.map +1 -0
  63. package/dist/core/board/skill-execution.entity.js +57 -0
  64. package/dist/core/board/skill-execution.entity.js.map +1 -0
  65. package/dist/core/board/task-title.value-object.d.ts +7 -0
  66. package/dist/core/board/task-title.value-object.d.ts.map +1 -0
  67. package/dist/core/board/task-title.value-object.js +20 -0
  68. package/dist/core/board/task-title.value-object.js.map +1 -0
  69. package/dist/core/ports/board-store.d.ts +15 -0
  70. package/dist/core/ports/board-store.d.ts.map +1 -0
  71. package/dist/core/ports/board-store.js +2 -0
  72. package/dist/core/ports/board-store.js.map +1 -0
  73. package/dist/core/ports/skill-runner.d.ts +6 -0
  74. package/dist/core/ports/skill-runner.d.ts.map +1 -0
  75. package/dist/core/ports/skill-runner.js +2 -0
  76. package/dist/core/ports/skill-runner.js.map +1 -0
  77. package/dist/core/ports/storage.d.ts +9 -1
  78. package/dist/core/ports/storage.d.ts.map +1 -1
  79. package/dist/core/types/board.d.ts +21 -0
  80. package/dist/core/types/board.d.ts.map +1 -0
  81. package/dist/core/types/board.js +2 -0
  82. package/dist/core/types/board.js.map +1 -0
  83. package/dist/core/types/index.d.ts +1 -1
  84. package/dist/core/types/index.d.ts.map +1 -1
  85. package/dist/core/types/index.js.map +1 -1
  86. package/dist/core/types/issue.d.ts +5 -0
  87. package/dist/core/types/issue.d.ts.map +1 -1
  88. package/dist/mcp/tools/search.d.ts.map +1 -1
  89. package/dist/mcp/tools/search.js +17 -20
  90. package/dist/mcp/tools/search.js.map +1 -1
  91. package/dist/use-cases/move-task.d.ts +18 -0
  92. package/dist/use-cases/move-task.d.ts.map +1 -0
  93. package/dist/use-cases/move-task.js +45 -0
  94. package/dist/use-cases/move-task.js.map +1 -0
  95. package/dist/use-cases/sync-board.d.ts +13 -0
  96. package/dist/use-cases/sync-board.d.ts.map +1 -0
  97. package/dist/use-cases/sync-board.js +20 -0
  98. package/dist/use-cases/sync-board.js.map +1 -0
  99. package/package.json +13 -3
@@ -0,0 +1,6 @@
1
+ export { SqlJsBoardStore } from './store.js';
2
+ export { ClaudeSkillRunner } from './skill-runner.js';
3
+ export { discoverSkills, type DiscoveredSkill } from './skill-discovery.js';
4
+ export { parseMdFile, parseMdContent, updateMdFrontmatter } from './md-parser.js';
5
+ export { rowToTaskData, taskDataToRow, type SqliteTaskRow } from './mapper.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/board/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { SqlJsBoardStore } from './store.js';
2
+ export { ClaudeSkillRunner } from './skill-runner.js';
3
+ export { discoverSkills } from './skill-discovery.js';
4
+ export { parseMdFile, parseMdContent, updateMdFrontmatter } from './md-parser.js';
5
+ export { rowToTaskData, taskDataToRow } from './mapper.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/board/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAwB,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAsB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { BoardTaskData } from '../../core/types/board.js';
2
+ export interface SqliteTaskRow {
3
+ id: string;
4
+ title: string;
5
+ md_path: string;
6
+ column_name: string;
7
+ jira_key: string | null;
8
+ assignee: string | null;
9
+ created_at: string;
10
+ updated_at: string;
11
+ }
12
+ export declare function rowToTaskData(row: SqliteTaskRow): BoardTaskData;
13
+ export declare function taskDataToRow(task: BoardTaskData): SqliteTaskRow;
14
+ //# sourceMappingURL=mapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapper.d.ts","sourceRoot":"","sources":["../../../src/adapters/board/mapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,aAAa,CAW/D;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,aAAa,CAWhE"}
@@ -0,0 +1,25 @@
1
+ export function rowToTaskData(row) {
2
+ return {
3
+ id: row.id,
4
+ title: row.title,
5
+ mdPath: row.md_path,
6
+ column: row.column_name,
7
+ jiraKey: row.jira_key,
8
+ assignee: row.assignee,
9
+ createdAt: row.created_at,
10
+ updatedAt: row.updated_at,
11
+ };
12
+ }
13
+ export function taskDataToRow(task) {
14
+ return {
15
+ id: task.id,
16
+ title: task.title,
17
+ md_path: task.mdPath,
18
+ column_name: task.column,
19
+ jira_key: task.jiraKey,
20
+ assignee: task.assignee,
21
+ created_at: task.createdAt,
22
+ updated_at: task.updatedAt,
23
+ };
24
+ }
25
+ //# sourceMappingURL=mapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapper.js","sourceRoot":"","sources":["../../../src/adapters/board/mapper.ts"],"names":[],"mappings":"AAaA,MAAM,UAAU,aAAa,CAAC,GAAkB;IAC9C,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,MAAM,EAAE,GAAG,CAAC,OAAO;QACnB,MAAM,EAAE,GAAG,CAAC,WAAW;QACvB,OAAO,EAAE,GAAG,CAAC,QAAQ;QACrB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAmB;IAC/C,OAAO;QACL,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,OAAO,EAAE,IAAI,CAAC,MAAM;QACpB,WAAW,EAAE,IAAI,CAAC,MAAM;QACxB,QAAQ,EAAE,IAAI,CAAC,OAAO;QACtB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,UAAU,EAAE,IAAI,CAAC,SAAS;QAC1B,UAAU,EAAE,IAAI,CAAC,SAAS;KAC3B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ interface MdFrontmatter {
2
+ column?: string;
3
+ jiraKey?: string;
4
+ assignee?: string;
5
+ [key: string]: unknown;
6
+ }
7
+ interface ParsedMd {
8
+ frontmatter: MdFrontmatter;
9
+ title: string;
10
+ body: string;
11
+ }
12
+ export declare function parseMdFile(filePath: string): ParsedMd;
13
+ export declare function parseMdContent(content: string): ParsedMd;
14
+ export declare function updateMdFrontmatter(filePath: string, updates: Partial<MdFrontmatter>): void;
15
+ export {};
16
+ //# sourceMappingURL=md-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"md-parser.d.ts","sourceRoot":"","sources":["../../../src/adapters/board/md-parser.ts"],"names":[],"mappings":"AAEA,UAAU,aAAa;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,UAAU,QAAQ;IAChB,WAAW,EAAE,aAAa,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAGtD;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,CAcxD;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAC9B,IAAI,CAoBN"}
@@ -0,0 +1,44 @@
1
+ import { readFileSync, writeFileSync } from 'node:fs';
2
+ export function parseMdFile(filePath) {
3
+ const content = readFileSync(filePath, 'utf-8');
4
+ return parseMdContent(content);
5
+ }
6
+ export function parseMdContent(content) {
7
+ let frontmatter = {};
8
+ let body = content;
9
+ const fmMatch = /^---\s*\n([\s\S]*?)\n---\s*\n/.exec(content);
10
+ if (fmMatch?.[1]) {
11
+ frontmatter = parseYamlSimple(fmMatch[1]);
12
+ body = content.slice(fmMatch[0].length);
13
+ }
14
+ const titleMatch = /^#\s+(.+)/m.exec(body);
15
+ const title = titleMatch?.[1]?.trim() ?? 'Untitled';
16
+ return { frontmatter, title, body };
17
+ }
18
+ export function updateMdFrontmatter(filePath, updates) {
19
+ const content = readFileSync(filePath, 'utf-8');
20
+ const fmMatch = /^---\s*\n([\s\S]*?)\n---\s*\n/.exec(content);
21
+ let frontmatter = {};
22
+ let body = content;
23
+ if (fmMatch?.[1]) {
24
+ frontmatter = parseYamlSimple(fmMatch[1]);
25
+ body = content.slice(fmMatch[0].length);
26
+ }
27
+ Object.assign(frontmatter, updates);
28
+ const fmLines = Object.entries(frontmatter)
29
+ .filter(([, v]) => v != null)
30
+ .map(([k, v]) => `${k}: ${String(v)}`);
31
+ const newContent = `---\n${fmLines.join('\n')}\n---\n${body}`;
32
+ writeFileSync(filePath, newContent);
33
+ }
34
+ function parseYamlSimple(raw) {
35
+ const result = {};
36
+ for (const line of raw.split('\n')) {
37
+ const match = /^(\w+)\s*:\s*(.+)/.exec(line);
38
+ if (match?.[1] && match[2]) {
39
+ result[match[1]] = match[2].trim();
40
+ }
41
+ }
42
+ return result;
43
+ }
44
+ //# sourceMappingURL=md-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"md-parser.js","sourceRoot":"","sources":["../../../src/adapters/board/md-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAetD,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChD,OAAO,cAAc,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,IAAI,WAAW,GAAkB,EAAE,CAAC;IACpC,IAAI,IAAI,GAAG,OAAO,CAAC;IAEnB,MAAM,OAAO,GAAG,+BAA+B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9D,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjB,WAAW,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1C,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,UAAU,CAAC;IAEpD,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,OAA+B;IAE/B,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,+BAA+B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE9D,IAAI,WAAW,GAAkB,EAAE,CAAC;IACpC,IAAI,IAAI,GAAG,OAAO,CAAC;IAEnB,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjB,WAAW,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1C,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAEpC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC;SACxC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC;SAC5B,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAEzC,MAAM,UAAU,GAAG,QAAQ,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;IAC9D,aAAa,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,eAAe,CAAC,GAAW;IAClC,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACrC,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,8 @@
1
+ export interface DiscoveredSkill {
2
+ name: string;
3
+ description: string;
4
+ source: 'project' | 'personal';
5
+ path: string;
6
+ }
7
+ export declare function discoverSkills(projectDir?: string): DiscoveredSkill[];
8
+ //# sourceMappingURL=skill-discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-discovery.d.ts","sourceRoot":"","sources":["../../../src/adapters/board/skill-discovery.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,SAAS,GAAG,UAAU,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,eAAe,EAAE,CAoBrE"}
@@ -0,0 +1,60 @@
1
+ import { readdirSync, existsSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ export function discoverSkills(projectDir) {
5
+ const skills = new Map();
6
+ const personalDir = join(homedir(), '.claude', 'skills');
7
+ if (existsSync(personalDir)) {
8
+ for (const skill of scanSkillsDir(personalDir, 'personal')) {
9
+ skills.set(skill.name, skill);
10
+ }
11
+ }
12
+ if (projectDir) {
13
+ const projectSkillsDir = join(projectDir, '.claude', 'skills');
14
+ if (existsSync(projectSkillsDir)) {
15
+ for (const skill of scanSkillsDir(projectSkillsDir, 'project')) {
16
+ skills.set(skill.name, skill);
17
+ }
18
+ }
19
+ }
20
+ return Array.from(skills.values());
21
+ }
22
+ function scanSkillsDir(dir, source) {
23
+ const results = [];
24
+ let entries;
25
+ try {
26
+ entries = readdirSync(dir);
27
+ }
28
+ catch {
29
+ return results;
30
+ }
31
+ for (const entry of entries) {
32
+ const skillMdPath = join(dir, entry, 'SKILL.md');
33
+ if (!existsSync(skillMdPath)) {
34
+ continue;
35
+ }
36
+ const description = extractSkillDescription(skillMdPath);
37
+ results.push({
38
+ name: entry,
39
+ description,
40
+ source,
41
+ path: join(dir, entry),
42
+ });
43
+ }
44
+ return results;
45
+ }
46
+ function extractSkillDescription(skillMdPath) {
47
+ try {
48
+ const content = readFileSync(skillMdPath, 'utf-8');
49
+ const fmMatch = /^---\s*\n([\s\S]*?)\n---/.exec(content);
50
+ if (!fmMatch?.[1]) {
51
+ return '';
52
+ }
53
+ const descMatch = /description:\s*["']?(.+?)["']?\s*$/m.exec(fmMatch[1]);
54
+ return descMatch?.[1]?.trim() ?? '';
55
+ }
56
+ catch {
57
+ return '';
58
+ }
59
+ }
60
+ //# sourceMappingURL=skill-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-discovery.js","sourceRoot":"","sources":["../../../src/adapters/board/skill-discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AASlC,MAAM,UAAU,cAAc,CAAC,UAAmB;IAChD,MAAM,MAAM,GAAG,IAAI,GAAG,EAA2B,CAAC;IAElD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IACzD,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC5B,KAAK,MAAM,KAAK,IAAI,aAAa,CAAC,WAAW,EAAE,UAAU,CAAC,EAAE,CAAC;YAC3D,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC/D,IAAI,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACjC,KAAK,MAAM,KAAK,IAAI,aAAa,CAAC,gBAAgB,EAAE,SAAS,CAAC,EAAE,CAAC;gBAC/D,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,aAAa,CACpB,GAAW,EACX,MAA8B;IAE9B,MAAM,OAAO,GAAsB,EAAE,CAAC;IAEtC,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;QACjD,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7B,SAAS;QACX,CAAC;QAED,MAAM,WAAW,GAAG,uBAAuB,CAAC,WAAW,CAAC,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,KAAK;YACX,WAAW;YACX,MAAM;YACN,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC;SACvB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,uBAAuB,CAAC,WAAmB;IAClD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,OAAO,GAAG,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzD,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClB,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,SAAS,GAAG,qCAAqC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACzE,OAAO,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { ISkillRunner } from '../../core/ports/skill-runner.js';
2
+ export declare class ClaudeSkillRunner implements ISkillRunner {
3
+ private readonly processes;
4
+ private executionCounter;
5
+ execute(skillName: string, args: string[]): AsyncGenerator<string>;
6
+ isAvailable(): Promise<boolean>;
7
+ cancel(executionId: string): void;
8
+ private streamOutput;
9
+ }
10
+ //# sourceMappingURL=skill-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-runner.d.ts","sourceRoot":"","sources":["../../../src/adapters/board/skill-runner.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAErE,qBAAa,iBAAkB,YAAW,YAAY;IACpD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmC;IAC7D,OAAO,CAAC,gBAAgB,CAAK;IAEtB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,cAAc,CAAC,MAAM,CAAC;IAqBnE,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAUrC,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;YAQlB,YAAY;CA6B5B"}
@@ -0,0 +1,65 @@
1
+ import { spawn } from 'node:child_process';
2
+ export class ClaudeSkillRunner {
3
+ processes = new Map();
4
+ executionCounter = 0;
5
+ async *execute(skillName, args) {
6
+ const executionId = String(++this.executionCounter);
7
+ const prompt = `/${skillName} ${args.join(' ')}`;
8
+ const child = spawn('claude', ['-p', prompt], {
9
+ stdio: ['ignore', 'pipe', 'pipe'],
10
+ env: { ...process.env },
11
+ });
12
+ this.processes.set(executionId, child);
13
+ try {
14
+ const iterator = this.streamOutput(child, executionId);
15
+ for await (const chunk of iterator) {
16
+ yield chunk;
17
+ }
18
+ }
19
+ finally {
20
+ this.processes.delete(executionId);
21
+ }
22
+ }
23
+ async isAvailable() {
24
+ return new Promise((resolve) => {
25
+ const child = spawn('claude', ['--version'], {
26
+ stdio: ['ignore', 'pipe', 'pipe'],
27
+ });
28
+ child.on('close', (code) => { resolve(code === 0); });
29
+ child.on('error', () => { resolve(false); });
30
+ });
31
+ }
32
+ cancel(executionId) {
33
+ const child = this.processes.get(executionId);
34
+ if (child) {
35
+ child.kill('SIGTERM');
36
+ this.processes.delete(executionId);
37
+ }
38
+ }
39
+ async *streamOutput(child, executionId) {
40
+ const stdout = child.stdout;
41
+ const stderr = child.stderr;
42
+ if (!stdout || !stderr) {
43
+ return;
44
+ }
45
+ const chunks = [];
46
+ const state = { done: false };
47
+ stdout.setEncoding('utf-8');
48
+ stderr.setEncoding('utf-8');
49
+ stdout.on('data', (data) => { chunks.push(data); });
50
+ stderr.on('data', (data) => { chunks.push(data); });
51
+ child.on('close', () => { state.done = true; });
52
+ child.on('error', () => { state.done = true; });
53
+ while (!state.done || chunks.length > 0) {
54
+ const chunk = chunks.shift();
55
+ if (chunk !== undefined) {
56
+ yield chunk;
57
+ }
58
+ else {
59
+ await new Promise((r) => setTimeout(r, 50));
60
+ }
61
+ }
62
+ this.processes.delete(executionId);
63
+ }
64
+ }
65
+ //# sourceMappingURL=skill-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-runner.js","sourceRoot":"","sources":["../../../src/adapters/board/skill-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { IBoardStore } from '../../core/ports/board-store.js';
2
+ import type { BoardTaskData } from '../../core/types/board.js';
3
+ import type { PipelineConfig } from '../../core/board/pipeline.value-object.js';
4
+ export declare class SqlJsBoardStore implements IBoardStore {
5
+ private db;
6
+ private readonly workspaceDir;
7
+ constructor(workspaceDir: string);
8
+ initialize(): Promise<void>;
9
+ private getDb;
10
+ private queryAll;
11
+ getAllTasks(): Promise<BoardTaskData[]>;
12
+ getTasksByColumn(column: string): Promise<BoardTaskData[]>;
13
+ createTask(task: Omit<BoardTaskData, 'id'>): Promise<BoardTaskData>;
14
+ updateTask(id: string, fields: Partial<BoardTaskData>): Promise<void>;
15
+ deleteTask(id: string): Promise<void>;
16
+ syncFromFiles(tasksDir: string): Promise<void>;
17
+ loadPipeline(): Promise<PipelineConfig>;
18
+ savePipeline(config: PipelineConfig): Promise<void>;
19
+ close(): Promise<void>;
20
+ }
21
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/adapters/board/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAC;AAahF,qBAAa,eAAgB,YAAW,WAAW;IACjD,OAAO,CAAC,EAAE,CAAwB;IAClC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,YAAY,EAAE,MAAM;IAI1B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA2BjC,OAAO,CAAC,KAAK;IAOb,OAAO,CAAC,QAAQ;IAiBhB,WAAW,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IAKvC,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAW1D,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC;IAWnE,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBrE,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK/B,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA+CpD,YAAY,IAAI,OAAO,CAAC,cAAc,CAAC;IAevC,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IASnD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAKvB"}
@@ -0,0 +1,176 @@
1
+ import { rowToTaskData } from './mapper.js';
2
+ import { parseMdFile } from './md-parser.js';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { readdirSync, existsSync } from 'node:fs';
5
+ import { join, relative } from 'node:path';
6
+ export class SqlJsBoardStore {
7
+ db = null;
8
+ workspaceDir;
9
+ constructor(workspaceDir) {
10
+ this.workspaceDir = workspaceDir;
11
+ }
12
+ async initialize() {
13
+ const sqlJsModule = await import('sql.js');
14
+ const initFn = sqlJsModule.default;
15
+ const SQL = await initFn();
16
+ this.db = new SQL.Database();
17
+ this.db.run(`
18
+ CREATE TABLE IF NOT EXISTS board_tasks (
19
+ id TEXT PRIMARY KEY,
20
+ title TEXT NOT NULL,
21
+ md_path TEXT NOT NULL UNIQUE,
22
+ column_name TEXT NOT NULL DEFAULT 'backlog',
23
+ jira_key TEXT,
24
+ assignee TEXT,
25
+ created_at TEXT NOT NULL,
26
+ updated_at TEXT NOT NULL
27
+ )
28
+ `);
29
+ this.db.run(`
30
+ CREATE TABLE IF NOT EXISTS board_pipeline (
31
+ id INTEGER PRIMARY KEY CHECK (id = 1),
32
+ config_json TEXT NOT NULL
33
+ )
34
+ `);
35
+ }
36
+ getDb() {
37
+ if (!this.db) {
38
+ throw new Error('BoardStore not initialized. Call initialize() first.');
39
+ }
40
+ return this.db;
41
+ }
42
+ queryAll(sql, params) {
43
+ const db = this.getDb();
44
+ if (params?.length) {
45
+ db.run('SELECT 1', []);
46
+ }
47
+ const result = db.exec(sql);
48
+ if (!result[0]) {
49
+ return [];
50
+ }
51
+ const { columns, values } = result[0];
52
+ return values.map((row) => {
53
+ const obj = {};
54
+ columns.forEach((col, i) => { obj[col] = row[i]; });
55
+ return obj;
56
+ });
57
+ }
58
+ getAllTasks() {
59
+ const rows = this.queryAll('SELECT * FROM board_tasks ORDER BY created_at');
60
+ return Promise.resolve(rows.map(rowToTaskData));
61
+ }
62
+ getTasksByColumn(column) {
63
+ const db = this.getDb();
64
+ db.run('CREATE TEMP TABLE IF NOT EXISTS _param (v TEXT)');
65
+ db.run('DELETE FROM _param');
66
+ db.run('INSERT INTO _param VALUES (?)', [column]);
67
+ const rows = this.queryAll('SELECT bt.* FROM board_tasks bt, _param p WHERE bt.column_name = p.v ORDER BY bt.created_at');
68
+ return Promise.resolve(rows.map(rowToTaskData));
69
+ }
70
+ createTask(task) {
71
+ const id = randomUUID();
72
+ const db = this.getDb();
73
+ db.run(`INSERT INTO board_tasks (id, title, md_path, column_name, jira_key, assignee, created_at, updated_at)
74
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [id, task.title, task.mdPath, task.column, task.jiraKey, task.assignee, task.createdAt, task.updatedAt]);
75
+ return Promise.resolve({ id, ...task });
76
+ }
77
+ updateTask(id, fields) {
78
+ const sets = [];
79
+ const values = [];
80
+ if (fields.title !== undefined) {
81
+ sets.push('title = ?');
82
+ values.push(fields.title);
83
+ }
84
+ if (fields.column !== undefined) {
85
+ sets.push('column_name = ?');
86
+ values.push(fields.column);
87
+ }
88
+ if (fields.jiraKey !== undefined) {
89
+ sets.push('jira_key = ?');
90
+ values.push(fields.jiraKey);
91
+ }
92
+ if (fields.assignee !== undefined) {
93
+ sets.push('assignee = ?');
94
+ values.push(fields.assignee);
95
+ }
96
+ sets.push('updated_at = ?');
97
+ values.push(new Date().toISOString());
98
+ values.push(id);
99
+ const db = this.getDb();
100
+ db.run(`UPDATE board_tasks SET ${sets.join(', ')} WHERE id = ?`, values);
101
+ return Promise.resolve();
102
+ }
103
+ deleteTask(id) {
104
+ this.getDb().run('DELETE FROM board_tasks WHERE id = ?', [id]);
105
+ return Promise.resolve();
106
+ }
107
+ async syncFromFiles(tasksDir) {
108
+ const folders = ['Backlog', 'ToDo', 'Done'];
109
+ const folderToColumn = {
110
+ Backlog: 'backlog',
111
+ ToDo: 'backlog',
112
+ Done: 'done',
113
+ };
114
+ for (const folder of folders) {
115
+ const dir = join(tasksDir, folder);
116
+ if (!existsSync(dir)) {
117
+ continue;
118
+ }
119
+ let files;
120
+ try {
121
+ files = readdirSync(dir).filter((f) => f.endsWith('.md'));
122
+ }
123
+ catch {
124
+ continue;
125
+ }
126
+ for (const file of files) {
127
+ const filePath = join(dir, file);
128
+ const relPath = relative(this.workspaceDir, filePath);
129
+ const db = this.getDb();
130
+ db.run('CREATE TEMP TABLE IF NOT EXISTS _path_param (v TEXT)');
131
+ db.run('DELETE FROM _path_param');
132
+ db.run('INSERT INTO _path_param VALUES (?)', [relPath]);
133
+ const existing = this.queryAll('SELECT bt.* FROM board_tasks bt, _path_param p WHERE bt.md_path = p.v');
134
+ if (existing.length > 0) {
135
+ continue;
136
+ }
137
+ const parsed = parseMdFile(filePath);
138
+ const now = new Date().toISOString();
139
+ await this.createTask({
140
+ title: parsed.title,
141
+ mdPath: relPath,
142
+ column: parsed.frontmatter.column ?? folderToColumn[folder] ?? 'backlog',
143
+ jiraKey: parsed.frontmatter.jiraKey ?? null,
144
+ assignee: parsed.frontmatter.assignee ?? null,
145
+ createdAt: now,
146
+ updatedAt: now,
147
+ });
148
+ }
149
+ }
150
+ }
151
+ loadPipeline() {
152
+ const result = this.getDb().exec('SELECT config_json FROM board_pipeline WHERE id = 1');
153
+ const raw = result[0]?.values[0]?.[0];
154
+ if (typeof raw === 'string') {
155
+ return Promise.resolve(JSON.parse(raw));
156
+ }
157
+ return Promise.resolve({
158
+ columns: [
159
+ { name: 'backlog', displayName: 'Backlog', type: 'system' },
160
+ { name: 'done', displayName: 'Done', type: 'system' },
161
+ ],
162
+ port: 5002,
163
+ });
164
+ }
165
+ savePipeline(config) {
166
+ const json = JSON.stringify(config);
167
+ this.getDb().run(`INSERT OR REPLACE INTO board_pipeline (id, config_json) VALUES (1, ?)`, [json]);
168
+ return Promise.resolve();
169
+ }
170
+ close() {
171
+ this.db?.close();
172
+ this.db = null;
173
+ return Promise.resolve();
174
+ }
175
+ }
176
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/adapters/board/store.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type { IStorage, QueryResult } from '../../core/ports/storage.js';
2
- import type { IssueBatch } from '../../core/types/index.js';
2
+ import type { IssueBatch, HybridSearchResult } from '../../core/types/index.js';
3
3
  import type { CommitBatch } from '../../core/types/git.js';
4
4
  import type { GitHubBatch, Release } from '../../core/types/github.js';
5
5
  import type { DbSchemaBatch } from '../../core/types/database.js';
@@ -27,6 +27,7 @@ export declare class PostgresStorage implements IStorage {
27
27
  issueKey: string;
28
28
  similarity: number;
29
29
  }[]>;
30
+ hybridSearch(query: string, vector: number[] | null, limit: number, threshold?: number): Promise<HybridSearchResult[]>;
30
31
  query(sql: string, params: unknown[]): Promise<QueryResult>;
31
32
  saveDbSchemaBatch(batch: DbSchemaBatch, sourceName: string): Promise<void>;
32
33
  deleteDbSchema(sourceName: string): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/adapters/postgres/storage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG5D;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,QAAQ;IAC9C,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAU;gBAEnB,MAAM,EAAE,QAAQ;IAItB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAsH3C,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAyDlD,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAWzD,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAW1D,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAmHlD,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA8ChD,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAW5D,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAWxD,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAOhE,cAAc,CAClB,MAAM,EAAE,MAAM,EAAE,EAChB,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAyBhD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IAK3D,iBAAiB,CAAC,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6D1E,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/adapters/postgres/storage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG5D;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,QAAQ;IAC9C,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAU;gBAEnB,MAAM,EAAE,QAAQ;IAItB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAsH3C,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAyDlD,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAWzD,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAW1D,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAmHlD,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA8ChD,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAW5D,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAWxD,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAOhE,cAAc,CAClB,MAAM,EAAE,MAAM,EAAE,EAChB,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAyBhD,YAAY,CAChB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EACvB,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAuE1B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IAK3D,iBAAiB,CAAC,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6D1E,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
@@ -312,6 +312,61 @@ export class PostgresStorage {
312
312
  similarity: r.similarity,
313
313
  }));
314
314
  }
315
+ async hybridSearch(query, vector, limit, threshold) {
316
+ const k = 60;
317
+ const maxPerSource = limit * 2;
318
+ const minSimilarity = threshold ?? 0.5;
319
+ if (!vector) {
320
+ const result = await this.pool.query(`SELECT issue_key,
321
+ 1.0 / (${String(k)} + ROW_NUMBER() OVER (ORDER BY ts_rank_cd(search_vector, plainto_tsquery('english', $1)) DESC)) AS score,
322
+ true AS in_text,
323
+ false AS in_vector
324
+ FROM issues
325
+ WHERE search_vector @@ plainto_tsquery('english', $1)
326
+ ORDER BY score DESC
327
+ LIMIT $2`, [query, limit]);
328
+ return result.rows.map((r) => ({
329
+ issueKey: r.issue_key,
330
+ score: r.score,
331
+ source: 'text',
332
+ }));
333
+ }
334
+ const vectorStr = `[${vector.join(',')}]`;
335
+ const result = await this.pool.query(`WITH text_search AS (
336
+ SELECT issue_key, ROW_NUMBER() OVER (ORDER BY ts_rank_cd(search_vector, plainto_tsquery('english', $1)) DESC) AS rank
337
+ FROM issues
338
+ WHERE search_vector @@ plainto_tsquery('english', $1)
339
+ LIMIT $3
340
+ ),
341
+ vector_search AS (
342
+ SELECT issue_key, ROW_NUMBER() OVER (ORDER BY embedding <=> $2::vector) AS rank
343
+ FROM issues
344
+ WHERE embedding IS NOT NULL
345
+ AND 1 - (embedding <=> $2::vector) >= ${String(minSimilarity)}
346
+ LIMIT $3
347
+ )
348
+ SELECT COALESCE(t.issue_key, v.issue_key) AS issue_key,
349
+ 1.0 / (${String(k)} + COALESCE(t.rank, 1000)) + 1.0 / (${String(k)} + COALESCE(v.rank, 1000)) AS score,
350
+ t.issue_key IS NOT NULL AS in_text,
351
+ v.issue_key IS NOT NULL AS in_vector
352
+ FROM text_search t
353
+ FULL OUTER JOIN vector_search v ON t.issue_key = v.issue_key
354
+ ORDER BY score DESC
355
+ LIMIT $4`, [query, vectorStr, maxPerSource, limit]);
356
+ return result.rows.map((r) => {
357
+ let source;
358
+ if (r.in_text && r.in_vector) {
359
+ source = 'both';
360
+ }
361
+ else if (r.in_text) {
362
+ source = 'text';
363
+ }
364
+ else {
365
+ source = 'semantic';
366
+ }
367
+ return { issueKey: r.issue_key, score: r.score, source };
368
+ });
369
+ }
315
370
  async query(sql, params) {
316
371
  const result = await this.pool.query(sql, params);
317
372
  return { rows: result.rows };