@sudocode-ai/integration-beads 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.
@@ -0,0 +1,192 @@
1
+ /**
2
+ * JSONL utilities for Beads plugin
3
+ *
4
+ * Provides atomic read/write operations for .beads/issues.jsonl files.
5
+ * Used as fallback when Beads CLI is not available.
6
+ */
7
+ import { existsSync, readFileSync, writeFileSync, renameSync } from "fs";
8
+ import * as path from "path";
9
+ import { randomBytes } from "crypto";
10
+ /**
11
+ * Read all issues from a beads JSONL file
12
+ *
13
+ * @param filePath - Path to issues.jsonl
14
+ * @param options - Read options
15
+ * @returns Array of parsed issues
16
+ */
17
+ export function readBeadsJSONL(filePath, options = {}) {
18
+ if (!existsSync(filePath)) {
19
+ return [];
20
+ }
21
+ try {
22
+ const content = readFileSync(filePath, "utf-8");
23
+ const lines = content.split("\n").filter((line) => line.trim());
24
+ const issues = [];
25
+ for (const line of lines) {
26
+ try {
27
+ const issue = JSON.parse(line);
28
+ issues.push(issue);
29
+ }
30
+ catch (parseError) {
31
+ if (!options.skipErrors) {
32
+ throw parseError;
33
+ }
34
+ // Skip malformed lines when skipErrors is true
35
+ }
36
+ }
37
+ return issues;
38
+ }
39
+ catch (error) {
40
+ if (options.skipErrors) {
41
+ return [];
42
+ }
43
+ throw error;
44
+ }
45
+ }
46
+ /**
47
+ * Write issues to a beads JSONL file atomically
48
+ *
49
+ * Features:
50
+ * - Atomic write (temp file + rename)
51
+ * - Sorted by created_at to minimize git merge conflicts
52
+ * - Skips write if content unchanged (prevents watcher loops)
53
+ *
54
+ * @param filePath - Path to issues.jsonl
55
+ * @param issues - Array of issues to write
56
+ */
57
+ export function writeBeadsJSONL(filePath, issues) {
58
+ console.log(`[beads-jsonl] writeBeadsJSONL called with ${issues.length} issue(s)`);
59
+ // Sort by created_at for consistent ordering (minimizes merge conflicts)
60
+ const sortedIssues = [...issues].sort((a, b) => {
61
+ const aDate = a.created_at || "";
62
+ const bDate = b.created_at || "";
63
+ if (aDate < bDate)
64
+ return -1;
65
+ if (aDate > bDate)
66
+ return 1;
67
+ // Fallback to ID comparison
68
+ return (a.id || "").localeCompare(b.id || "");
69
+ });
70
+ // Build content
71
+ const content = sortedIssues.map((issue) => JSON.stringify(issue)).join("\n");
72
+ // Skip write if content unchanged (prevents watcher loops)
73
+ if (existsSync(filePath)) {
74
+ const existingContent = readFileSync(filePath, "utf-8");
75
+ if (existingContent.trim() === content.trim()) {
76
+ console.log(`[beads-jsonl] Content unchanged, skipping write`);
77
+ return; // No changes
78
+ }
79
+ console.log(`[beads-jsonl] Content changed, proceeding with write`);
80
+ }
81
+ else {
82
+ console.log(`[beads-jsonl] File doesn't exist, creating new file`);
83
+ }
84
+ // Atomic write: write to temp file, then rename
85
+ const tempPath = `${filePath}.tmp`;
86
+ writeFileSync(tempPath, content + "\n", "utf-8");
87
+ renameSync(tempPath, filePath);
88
+ console.log(`[beads-jsonl] Successfully wrote to ${filePath}`);
89
+ }
90
+ /**
91
+ * Generate a beads-style ID
92
+ *
93
+ * Beads uses IDs like "beads-a1b2c3d4"
94
+ *
95
+ * @param prefix - ID prefix (default: "beads")
96
+ * @returns Generated ID
97
+ */
98
+ export function generateBeadsId(prefix = "beads") {
99
+ const random = randomBytes(4).toString("hex");
100
+ return `${prefix}-${random}`;
101
+ }
102
+ /**
103
+ * Create a new issue in the JSONL file
104
+ *
105
+ * @param beadsDir - Path to .beads directory
106
+ * @param issue - Issue data to create
107
+ * @param idPrefix - Prefix for generated ID
108
+ * @returns The created issue with generated ID
109
+ */
110
+ export function createIssueViaJSONL(beadsDir, issue, idPrefix = "beads") {
111
+ const issuesPath = path.join(beadsDir, "issues.jsonl");
112
+ const issues = readBeadsJSONL(issuesPath, { skipErrors: true });
113
+ const now = new Date().toISOString();
114
+ const newIssue = {
115
+ id: generateBeadsId(idPrefix),
116
+ title: issue.title || "Untitled",
117
+ description: issue.description || "",
118
+ status: issue.status || "open",
119
+ priority: issue.priority ?? 2,
120
+ created_at: issue.created_at || now,
121
+ updated_at: issue.updated_at || now,
122
+ ...issue, // Allow additional fields to pass through
123
+ };
124
+ // Ensure ID is from our generator, not passed in
125
+ newIssue.id = generateBeadsId(idPrefix);
126
+ issues.push(newIssue);
127
+ writeBeadsJSONL(issuesPath, issues);
128
+ return newIssue;
129
+ }
130
+ /**
131
+ * Update an existing issue in the JSONL file
132
+ *
133
+ * @param beadsDir - Path to .beads directory
134
+ * @param issueId - ID of issue to update
135
+ * @param updates - Fields to update
136
+ * @returns The updated issue
137
+ * @throws Error if issue not found
138
+ */
139
+ export function updateIssueViaJSONL(beadsDir, issueId, updates) {
140
+ console.log(`[beads-jsonl] updateIssueViaJSONL called for ${issueId} with updates:`, JSON.stringify(updates));
141
+ const issuesPath = path.join(beadsDir, "issues.jsonl");
142
+ const issues = readBeadsJSONL(issuesPath, { skipErrors: true });
143
+ const index = issues.findIndex((i) => i.id === issueId);
144
+ if (index === -1) {
145
+ console.error(`[beads-jsonl] Issue not found: ${issueId}`);
146
+ throw new Error(`Beads issue not found: ${issueId}`);
147
+ }
148
+ console.log(`[beads-jsonl] Found issue at index ${index}, current status: ${issues[index].status}`);
149
+ // Merge updates, preserving beads-specific fields
150
+ const updatedIssue = {
151
+ ...issues[index],
152
+ ...updates,
153
+ id: issueId, // Preserve original ID
154
+ updated_at: new Date().toISOString(),
155
+ };
156
+ console.log(`[beads-jsonl] Merged issue, new status: ${updatedIssue.status}`);
157
+ issues[index] = updatedIssue;
158
+ writeBeadsJSONL(issuesPath, issues);
159
+ console.log(`[beads-jsonl] Wrote issues back to ${issuesPath}`);
160
+ return updatedIssue;
161
+ }
162
+ /**
163
+ * Delete an issue from the JSONL file
164
+ *
165
+ * @param beadsDir - Path to .beads directory
166
+ * @param issueId - ID of issue to delete
167
+ * @returns True if deleted, false if not found
168
+ */
169
+ export function deleteIssueViaJSONL(beadsDir, issueId) {
170
+ const issuesPath = path.join(beadsDir, "issues.jsonl");
171
+ const issues = readBeadsJSONL(issuesPath, { skipErrors: true });
172
+ const originalLength = issues.length;
173
+ const filtered = issues.filter((i) => i.id !== issueId);
174
+ if (filtered.length === originalLength) {
175
+ return false; // Not found
176
+ }
177
+ writeBeadsJSONL(issuesPath, filtered);
178
+ return true;
179
+ }
180
+ /**
181
+ * Get a single issue by ID
182
+ *
183
+ * @param beadsDir - Path to .beads directory
184
+ * @param issueId - ID of issue to find
185
+ * @returns The issue or null if not found
186
+ */
187
+ export function getIssueById(beadsDir, issueId) {
188
+ const issuesPath = path.join(beadsDir, "issues.jsonl");
189
+ const issues = readBeadsJSONL(issuesPath, { skipErrors: true });
190
+ return issues.find((i) => i.id === issueId) || null;
191
+ }
192
+ //# sourceMappingURL=jsonl-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonl-utils.js","sourceRoot":"","sources":["../src/jsonl-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * File watcher for Beads integration
3
+ *
4
+ * Watches the .beads/issues.jsonl file for changes and detects
5
+ * which entities were created, updated, or deleted.
6
+ */
7
+ import type { ExternalChange } from "@sudocode-ai/types";
8
+ import { type BeadsIssue } from "./jsonl-utils.js";
9
+ /**
10
+ * Callback type for change notifications
11
+ */
12
+ export type ChangeCallback = (changes: ExternalChange[]) => void;
13
+ /**
14
+ * BeadsWatcher monitors .beads/issues.jsonl for changes
15
+ *
16
+ * Uses content hashing to detect actual changes vs just file touches.
17
+ * This prevents false positives from atomic writes and other file operations.
18
+ */
19
+ export declare class BeadsWatcher {
20
+ private watcher;
21
+ private entityHashes;
22
+ private beadsDir;
23
+ private callback;
24
+ private isProcessing;
25
+ constructor(beadsDir: string);
26
+ /**
27
+ * Update the cached hash for a specific entity after we wrote to it.
28
+ * This prevents the watcher from detecting our own writes as changes.
29
+ */
30
+ updateEntityHash(entityId: string, entity: BeadsIssue): void;
31
+ /**
32
+ * Remove an entity from the hash cache (after deletion)
33
+ */
34
+ removeEntityHash(entityId: string): void;
35
+ /**
36
+ * Start watching for changes
37
+ *
38
+ * @param callback - Function to call when changes are detected
39
+ */
40
+ start(callback: ChangeCallback): void;
41
+ /**
42
+ * Stop watching for changes
43
+ */
44
+ stop(): void;
45
+ /**
46
+ * Check if watcher is active
47
+ */
48
+ isWatching(): boolean;
49
+ /**
50
+ * Capture current state (entity hashes) for comparison
51
+ */
52
+ private captureState;
53
+ /**
54
+ * Handle file change event
55
+ */
56
+ private handleFileChange;
57
+ /**
58
+ * Handle file deleted event
59
+ */
60
+ private handleFileDeleted;
61
+ /**
62
+ * Detect changes by comparing current state to cached state
63
+ *
64
+ * @returns Array of detected changes
65
+ */
66
+ private detectChanges;
67
+ /**
68
+ * Convert BeadsIssue to ExternalEntity format
69
+ * Note: Beads uses 'description', which maps to ExternalEntity.description
70
+ */
71
+ private issueToExternalEntity;
72
+ /**
73
+ * Get current cached hashes (for testing/debugging)
74
+ */
75
+ getEntityHashes(): Map<string, string>;
76
+ /**
77
+ * Force refresh of cached state (useful after external sync)
78
+ */
79
+ refreshState(): void;
80
+ }
81
+ //# sourceMappingURL=watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnE;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;AAEjE;;;;;GAKG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,YAAY,CAAS;gBAEjB,QAAQ,EAAE,MAAM;IAI5B;;;OAGG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAM5D;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKxC;;;;OAIG;IACH,KAAK,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAgCrC;;OAEG;IACH,IAAI,IAAI,IAAI;IASZ;;OAEG;IACH,UAAU,IAAI,OAAO;IAIrB;;OAEG;IACH,OAAO,CAAC,YAAY;IAapB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAkCxB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAiCzB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAwDrB;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAc7B;;OAEG;IACH,eAAe,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAItC;;OAEG;IACH,YAAY,IAAI,IAAI;CAGrB"}
@@ -0,0 +1,252 @@
1
+ /**
2
+ * File watcher for Beads integration
3
+ *
4
+ * Watches the .beads/issues.jsonl file for changes and detects
5
+ * which entities were created, updated, or deleted.
6
+ */
7
+ import chokidar from "chokidar";
8
+ import * as path from "path";
9
+ import { computeCanonicalHash } from "./hash-utils.js";
10
+ import { readBeadsJSONL } from "./jsonl-utils.js";
11
+ /**
12
+ * BeadsWatcher monitors .beads/issues.jsonl for changes
13
+ *
14
+ * Uses content hashing to detect actual changes vs just file touches.
15
+ * This prevents false positives from atomic writes and other file operations.
16
+ */
17
+ export class BeadsWatcher {
18
+ watcher = null;
19
+ entityHashes = new Map();
20
+ beadsDir;
21
+ callback = null;
22
+ isProcessing = false;
23
+ constructor(beadsDir) {
24
+ this.beadsDir = beadsDir;
25
+ }
26
+ /**
27
+ * Update the cached hash for a specific entity after we wrote to it.
28
+ * This prevents the watcher from detecting our own writes as changes.
29
+ */
30
+ updateEntityHash(entityId, entity) {
31
+ const hash = computeCanonicalHash(entity);
32
+ console.log(`[beads-watcher] Updated hash for ${entityId} after outbound write`);
33
+ this.entityHashes.set(entityId, hash);
34
+ }
35
+ /**
36
+ * Remove an entity from the hash cache (after deletion)
37
+ */
38
+ removeEntityHash(entityId) {
39
+ console.log(`[beads-watcher] Removed hash for ${entityId} after outbound delete`);
40
+ this.entityHashes.delete(entityId);
41
+ }
42
+ /**
43
+ * Start watching for changes
44
+ *
45
+ * @param callback - Function to call when changes are detected
46
+ */
47
+ start(callback) {
48
+ if (this.watcher) {
49
+ console.warn("[beads-watcher] Already watching");
50
+ return;
51
+ }
52
+ this.callback = callback;
53
+ const issuesPath = path.join(this.beadsDir, "issues.jsonl");
54
+ // Capture initial state
55
+ this.captureState();
56
+ this.watcher = chokidar.watch(issuesPath, {
57
+ persistent: true,
58
+ ignoreInitial: true,
59
+ awaitWriteFinish: {
60
+ stabilityThreshold: 100, // Wait 100ms for writes to settle
61
+ pollInterval: 50,
62
+ },
63
+ });
64
+ this.watcher.on("change", () => this.handleFileChange());
65
+ this.watcher.on("add", () => this.handleFileChange());
66
+ this.watcher.on("unlink", () => this.handleFileDeleted());
67
+ this.watcher.on("error", (error) => {
68
+ console.error("[beads-watcher] Error:", error);
69
+ });
70
+ console.log(`[beads-watcher] Started watching ${issuesPath}`);
71
+ }
72
+ /**
73
+ * Stop watching for changes
74
+ */
75
+ stop() {
76
+ if (this.watcher) {
77
+ this.watcher.close();
78
+ this.watcher = null;
79
+ this.callback = null;
80
+ console.log("[beads-watcher] Stopped");
81
+ }
82
+ }
83
+ /**
84
+ * Check if watcher is active
85
+ */
86
+ isWatching() {
87
+ return this.watcher !== null;
88
+ }
89
+ /**
90
+ * Capture current state (entity hashes) for comparison
91
+ */
92
+ captureState() {
93
+ const issues = readBeadsJSONL(path.join(this.beadsDir, "issues.jsonl"), { skipErrors: true });
94
+ this.entityHashes.clear();
95
+ for (const issue of issues) {
96
+ const hash = computeCanonicalHash(issue);
97
+ this.entityHashes.set(issue.id, hash);
98
+ }
99
+ }
100
+ /**
101
+ * Handle file change event
102
+ */
103
+ handleFileChange() {
104
+ console.log("[beads-watcher] File change detected");
105
+ // Prevent concurrent processing
106
+ if (this.isProcessing) {
107
+ console.log("[beads-watcher] Already processing, skipping");
108
+ return;
109
+ }
110
+ this.isProcessing = true;
111
+ try {
112
+ const changes = this.detectChanges();
113
+ console.log(`[beads-watcher] Detected ${changes.length} change(s) (content-based comparison)`);
114
+ if (changes.length > 0) {
115
+ for (const change of changes) {
116
+ console.log(`[beads-watcher] - ${change.change_type}: ${change.entity_id}`);
117
+ }
118
+ if (this.callback) {
119
+ console.log("[beads-watcher] Invoking callback");
120
+ this.callback(changes);
121
+ }
122
+ else {
123
+ console.log("[beads-watcher] No callback registered!");
124
+ }
125
+ }
126
+ else {
127
+ console.log("[beads-watcher] No actual content changes (hashes match)");
128
+ }
129
+ }
130
+ catch (error) {
131
+ console.error("[beads-watcher] Error processing changes:", error);
132
+ }
133
+ finally {
134
+ this.isProcessing = false;
135
+ }
136
+ }
137
+ /**
138
+ * Handle file deleted event
139
+ */
140
+ handleFileDeleted() {
141
+ if (this.isProcessing) {
142
+ return;
143
+ }
144
+ this.isProcessing = true;
145
+ try {
146
+ // All entities are deleted
147
+ const changes = [];
148
+ const now = new Date().toISOString();
149
+ for (const [id] of this.entityHashes) {
150
+ changes.push({
151
+ entity_id: id,
152
+ entity_type: "issue",
153
+ change_type: "deleted",
154
+ timestamp: now,
155
+ });
156
+ }
157
+ this.entityHashes.clear();
158
+ if (changes.length > 0 && this.callback) {
159
+ this.callback(changes);
160
+ }
161
+ }
162
+ catch (error) {
163
+ console.error("[beads-watcher] Error processing deletion:", error);
164
+ }
165
+ finally {
166
+ this.isProcessing = false;
167
+ }
168
+ }
169
+ /**
170
+ * Detect changes by comparing current state to cached state
171
+ *
172
+ * @returns Array of detected changes
173
+ */
174
+ detectChanges() {
175
+ const issues = readBeadsJSONL(path.join(this.beadsDir, "issues.jsonl"), { skipErrors: true });
176
+ const changes = [];
177
+ const now = new Date().toISOString();
178
+ const currentIds = new Set();
179
+ // Check for created and updated entities
180
+ for (const issue of issues) {
181
+ currentIds.add(issue.id);
182
+ const newHash = computeCanonicalHash(issue);
183
+ const cachedHash = this.entityHashes.get(issue.id);
184
+ if (!cachedHash) {
185
+ // New entity
186
+ changes.push({
187
+ entity_id: issue.id,
188
+ entity_type: "issue",
189
+ change_type: "created",
190
+ timestamp: issue.created_at || now,
191
+ data: this.issueToExternalEntity(issue),
192
+ });
193
+ this.entityHashes.set(issue.id, newHash);
194
+ }
195
+ else if (newHash !== cachedHash) {
196
+ // Updated entity
197
+ changes.push({
198
+ entity_id: issue.id,
199
+ entity_type: "issue",
200
+ change_type: "updated",
201
+ timestamp: issue.updated_at || now,
202
+ data: this.issueToExternalEntity(issue),
203
+ });
204
+ this.entityHashes.set(issue.id, newHash);
205
+ }
206
+ // If hashes match, no change
207
+ }
208
+ // Check for deleted entities
209
+ for (const [id] of this.entityHashes) {
210
+ if (!currentIds.has(id)) {
211
+ changes.push({
212
+ entity_id: id,
213
+ entity_type: "issue",
214
+ change_type: "deleted",
215
+ timestamp: now,
216
+ });
217
+ this.entityHashes.delete(id);
218
+ }
219
+ }
220
+ return changes;
221
+ }
222
+ /**
223
+ * Convert BeadsIssue to ExternalEntity format
224
+ * Note: Beads uses 'description', which maps to ExternalEntity.description
225
+ */
226
+ issueToExternalEntity(issue) {
227
+ return {
228
+ id: issue.id,
229
+ type: "issue",
230
+ title: issue.title || "",
231
+ description: issue.description || "", // Beads uses 'description'
232
+ status: issue.status,
233
+ priority: issue.priority,
234
+ created_at: issue.created_at,
235
+ updated_at: issue.updated_at,
236
+ raw: issue,
237
+ };
238
+ }
239
+ /**
240
+ * Get current cached hashes (for testing/debugging)
241
+ */
242
+ getEntityHashes() {
243
+ return new Map(this.entityHashes);
244
+ }
245
+ /**
246
+ * Force refresh of cached state (useful after external sync)
247
+ */
248
+ refreshState() {
249
+ this.captureState();
250
+ }
251
+ }
252
+ //# sourceMappingURL=watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@sudocode-ai/integration-beads",
3
+ "version": "0.1.13",
4
+ "description": "Beads integration plugin for sudocode",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "test": "vitest --run",
20
+ "test:cli": "RUN_CLI_TESTS=true vitest --run",
21
+ "clean": "rm -rf dist"
22
+ },
23
+ "keywords": [
24
+ "sudocode",
25
+ "integration",
26
+ "beads",
27
+ "plugin"
28
+ ],
29
+ "author": "sudocode-ai",
30
+ "license": "MIT",
31
+ "dependencies": {
32
+ "chokidar": "^4.0.3"
33
+ },
34
+ "peerDependencies": {
35
+ "@sudocode-ai/types": "^0.1.13"
36
+ },
37
+ "devDependencies": {
38
+ "@beads/bd": "^0.29.0",
39
+ "@sudocode-ai/types": "^0.1.13",
40
+ "@types/node": "^22.10.2",
41
+ "typescript": "^5.8.3",
42
+ "vitest": "^3.2.4"
43
+ }
44
+ }