argustack 0.1.10 → 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.
- package/README.md +5 -2
- package/dist/adapters/board/index.d.ts +6 -0
- package/dist/adapters/board/index.d.ts.map +1 -0
- package/dist/adapters/board/index.js +6 -0
- package/dist/adapters/board/index.js.map +1 -0
- package/dist/adapters/board/mapper.d.ts +14 -0
- package/dist/adapters/board/mapper.d.ts.map +1 -0
- package/dist/adapters/board/mapper.js +25 -0
- package/dist/adapters/board/mapper.js.map +1 -0
- package/dist/adapters/board/md-parser.d.ts +16 -0
- package/dist/adapters/board/md-parser.d.ts.map +1 -0
- package/dist/adapters/board/md-parser.js +44 -0
- package/dist/adapters/board/md-parser.js.map +1 -0
- package/dist/adapters/board/skill-discovery.d.ts +8 -0
- package/dist/adapters/board/skill-discovery.d.ts.map +1 -0
- package/dist/adapters/board/skill-discovery.js +60 -0
- package/dist/adapters/board/skill-discovery.js.map +1 -0
- package/dist/adapters/board/skill-runner.d.ts +10 -0
- package/dist/adapters/board/skill-runner.d.ts.map +1 -0
- package/dist/adapters/board/skill-runner.js +65 -0
- package/dist/adapters/board/skill-runner.js.map +1 -0
- package/dist/adapters/board/store.d.ts +21 -0
- package/dist/adapters/board/store.d.ts.map +1 -0
- package/dist/adapters/board/store.js +176 -0
- package/dist/adapters/board/store.js.map +1 -0
- package/dist/adapters/postgres/storage.d.ts +2 -1
- package/dist/adapters/postgres/storage.d.ts.map +1 -1
- package/dist/adapters/postgres/storage.js +55 -0
- package/dist/adapters/postgres/storage.js.map +1 -1
- package/dist/board/assets/index-Bnh8GW_4.css +1 -0
- package/dist/board/assets/index-CEXc5QXH.js +68 -0
- package/dist/board/favicon.png +0 -0
- package/dist/board/index.html +14 -0
- package/dist/cli/board-server.d.ts +2 -0
- package/dist/cli/board-server.d.ts.map +1 -0
- package/dist/cli/board-server.js +124 -0
- package/dist/cli/board-server.js.map +1 -0
- package/dist/cli/board.d.ts +3 -0
- package/dist/cli/board.d.ts.map +1 -0
- package/dist/cli/board.js +26 -0
- package/dist/cli/board.js.map +1 -0
- package/dist/cli/index.js +9 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init/generators.d.ts +2 -2
- package/dist/cli/init/generators.d.ts.map +1 -1
- package/dist/cli/init/generators.js +14 -12
- package/dist/cli/init/generators.js.map +1 -1
- package/dist/cli/init/index.d.ts +10 -0
- package/dist/cli/init/index.d.ts.map +1 -1
- package/dist/cli/init/index.js +205 -72
- package/dist/cli/init/index.js.map +1 -1
- package/dist/cli/init/setup-db.d.ts.map +1 -1
- package/dist/cli/init/setup-db.js +5 -3
- package/dist/cli/init/setup-db.js.map +1 -1
- package/dist/cli/init/setup-git.d.ts.map +1 -1
- package/dist/cli/init/setup-git.js +10 -4
- package/dist/cli/init/setup-git.js.map +1 -1
- package/dist/cli/init/setup-github.js +5 -5
- package/dist/cli/init/setup-github.js.map +1 -1
- package/dist/cli/init/setup-jira.d.ts.map +1 -1
- package/dist/cli/init/setup-jira.js +5 -3
- package/dist/cli/init/setup-jira.js.map +1 -1
- package/dist/cli/init/types.d.ts +9 -1
- package/dist/cli/init/types.d.ts.map +1 -1
- package/dist/cli/init/types.js +54 -0
- package/dist/cli/init/types.js.map +1 -1
- package/dist/cli/mcp-install.d.ts +9 -0
- package/dist/cli/mcp-install.d.ts.map +1 -1
- package/dist/cli/mcp-install.js +3 -3
- package/dist/cli/mcp-install.js.map +1 -1
- package/dist/cli/sync.d.ts.map +1 -1
- package/dist/cli/sync.js +2 -1
- package/dist/cli/sync.js.map +1 -1
- package/dist/core/board/board-column.value-object.d.ts +14 -0
- package/dist/core/board/board-column.value-object.d.ts.map +1 -0
- package/dist/core/board/board-column.value-object.js +36 -0
- package/dist/core/board/board-column.value-object.js.map +1 -0
- package/dist/core/board/board-task.entity.d.ts +20 -0
- package/dist/core/board/board-task.entity.d.ts.map +1 -0
- package/dist/core/board/board-task.entity.js +51 -0
- package/dist/core/board/board-task.entity.js.map +1 -0
- package/dist/core/board/index.d.ts +6 -0
- package/dist/core/board/index.d.ts.map +1 -0
- package/dist/core/board/index.js +6 -0
- package/dist/core/board/index.js.map +1 -0
- package/dist/core/board/pipeline.value-object.d.ts +22 -0
- package/dist/core/board/pipeline.value-object.d.ts.map +1 -0
- package/dist/core/board/pipeline.value-object.js +50 -0
- package/dist/core/board/pipeline.value-object.js.map +1 -0
- package/dist/core/board/skill-execution.entity.d.ts +18 -0
- package/dist/core/board/skill-execution.entity.d.ts.map +1 -0
- package/dist/core/board/skill-execution.entity.js +57 -0
- package/dist/core/board/skill-execution.entity.js.map +1 -0
- package/dist/core/board/task-title.value-object.d.ts +7 -0
- package/dist/core/board/task-title.value-object.d.ts.map +1 -0
- package/dist/core/board/task-title.value-object.js +20 -0
- package/dist/core/board/task-title.value-object.js.map +1 -0
- package/dist/core/ports/board-store.d.ts +15 -0
- package/dist/core/ports/board-store.d.ts.map +1 -0
- package/dist/core/ports/board-store.js +2 -0
- package/dist/core/ports/board-store.js.map +1 -0
- package/dist/core/ports/skill-runner.d.ts +6 -0
- package/dist/core/ports/skill-runner.d.ts.map +1 -0
- package/dist/core/ports/skill-runner.js +2 -0
- package/dist/core/ports/skill-runner.js.map +1 -0
- package/dist/core/ports/storage.d.ts +9 -1
- package/dist/core/ports/storage.d.ts.map +1 -1
- package/dist/core/types/board.d.ts +21 -0
- package/dist/core/types/board.d.ts.map +1 -0
- package/dist/core/types/board.js +2 -0
- package/dist/core/types/board.js.map +1 -0
- package/dist/core/types/config.d.ts +2 -0
- package/dist/core/types/config.d.ts.map +1 -1
- package/dist/core/types/config.js.map +1 -1
- package/dist/core/types/index.d.ts +1 -1
- package/dist/core/types/index.d.ts.map +1 -1
- package/dist/core/types/index.js.map +1 -1
- package/dist/core/types/issue.d.ts +5 -0
- package/dist/core/types/issue.d.ts.map +1 -1
- package/dist/mcp/helpers.d.ts +18 -1
- package/dist/mcp/helpers.d.ts.map +1 -1
- package/dist/mcp/helpers.js +92 -0
- package/dist/mcp/helpers.js.map +1 -1
- package/dist/mcp/tools/search.d.ts.map +1 -1
- package/dist/mcp/tools/search.js +17 -20
- package/dist/mcp/tools/search.js.map +1 -1
- package/dist/mcp/tools/workspace.d.ts.map +1 -1
- package/dist/mcp/tools/workspace.js +35 -2
- package/dist/mcp/tools/workspace.js.map +1 -1
- package/dist/use-cases/move-task.d.ts +18 -0
- package/dist/use-cases/move-task.d.ts.map +1 -0
- package/dist/use-cases/move-task.js +45 -0
- package/dist/use-cases/move-task.js.map +1 -0
- package/dist/use-cases/sync-board.d.ts +13 -0
- package/dist/use-cases/sync-board.d.ts.map +1 -0
- package/dist/use-cases/sync-board.js +20 -0
- package/dist/use-cases/sync-board.js.map +1 -0
- package/dist/workspace/config.d.ts +1 -1
- package/dist/workspace/config.d.ts.map +1 -1
- package/dist/workspace/config.js +2 -1
- package/dist/workspace/config.js.map +1 -1
- package/package.json +13 -3
package/README.md
CHANGED
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/argustack)
|
|
4
4
|
[](https://www.npmjs.com/package/argustack)
|
|
5
5
|
[](LICENSE)
|
|
6
|
+
[](https://app.paperlink.online/s/0aa7d2d6/argustack)
|
|
6
7
|
|
|
7
8
|
**Ask AI about your Jira, Git, and GitHub — powered by local data, not cloud APIs.**
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
[**Documentation & Examples →**](https://app.paperlink.online/s/0aa7d2d6/argustack)
|
|
11
|
+
|
|
12
|
+
Argustack downloads your project data into local PostgreSQL, cross-references everything, and gives Claude direct access via 20 MCP tools. All data stays on your machine.
|
|
10
13
|
|
|
11
14
|
> *Was ticket PROJ-123 implemented as described?*
|
|
12
15
|
> *Who reviewed the PR and what was the feedback?*
|
|
@@ -21,7 +24,7 @@ Argustack downloads your project data into local PostgreSQL, cross-references ev
|
|
|
21
24
|
- **Cross-source timeline** — Jira + Git + GitHub events in chronological order
|
|
22
25
|
- **Semantic search** — find issues by meaning, not just keywords (pgvector)
|
|
23
26
|
- **Task estimation** — predict duration per developer based on actual history
|
|
24
|
-
- **
|
|
27
|
+
- **20 MCP tools** — Claude queries your data directly via SQL
|
|
25
28
|
- **100% local** — no cloud, no accounts, no telemetry
|
|
26
29
|
|
|
27
30
|
## Quick Start
|
|
@@ -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 @@
|
|
|
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;
|
|
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 };
|