opencode-gitbutler 0.1.8 → 0.1.9

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 CHANGED
@@ -16,8 +16,9 @@ This plugin bridges the gap by bringing GitButler's virtual branch power directl
16
16
  - Zero-config setup. Just add it to your plugins and go.
17
17
  - Works with GitButler virtual branches to avoid worktree overhead.
18
18
  - Impersonates Cursor for full GitButler CLI compatibility.
19
- - Unique multi-agent session mapping.
20
- - Hunk-level rub guard to skip multi-stack files.
19
+ - Session-first routing: every edit/write is assigned via `but cursor after-edit`.
20
+ - Unique multi-agent session mapping so subagents stay on the parent branch.
21
+ - Hunk-level rub guard in post-stop recovery to avoid unsafe auto-moves.
21
22
 
22
23
  ## Installation
23
24
 
@@ -46,11 +47,29 @@ See [GitButler installation docs](https://docs.gitbutler.com/installation) for o
46
47
  ### 3. Restart OpenCode
47
48
 
48
49
  The plugin automatically:
50
+ - Routes every `edit`/`write` through GitButler's `after-edit`
49
51
  - Creates and renames branches based on your prompts
50
- - Generates commit messages using Claude Haiku
51
- - Injects workspace state into agent context via `SKILL.md`
52
+ - Rewords commit messages using Claude Haiku (with deterministic fallback)
53
+ - Injects workspace state notifications into agent context
52
54
  - Checks for updates on session creation
53
55
 
56
+ ## How Branch Assignment Works
57
+
58
+ This plugin uses a session-first flow. In practice:
59
+
60
+ 1. On every `edit`/`write`, the plugin resolves your **root session** (parent session for subagents).
61
+ 2. It derives a deterministic `conversation_id` from that root session (or from `branch_target`, when configured).
62
+ 3. It always calls `but cursor after-edit` with that `conversation_id` and file path.
63
+ 4. On idle/stop, it calls `but cursor stop` for that same `conversation_id`.
64
+ 5. In post-stop processing, it may:
65
+ - sweep edited files and `but rub` unassigned changes when attribution is safe,
66
+ - reword commit message,
67
+ - rename default `ge-branch-*` names,
68
+ - sync OpenCode session title,
69
+ - clean empty default branches.
70
+
71
+ This avoids cross-session branch pollution and keeps subagent edits attached to the parent session branch.
72
+
54
73
  ## Configuration
55
74
 
56
75
  Create `.opencode/gitbutler.json` in your workspace root to override defaults:
@@ -77,7 +96,23 @@ Create `.opencode/gitbutler.json` in your workspace root to override defaults:
77
96
  "auto_update": true,
78
97
 
79
98
  // Regex pattern for default branch detection
80
- "default_branch_pattern": "^ge-branch-\\d+$"
99
+ "default_branch_pattern": "^ge-branch-\\d+$",
100
+
101
+ // Milliseconds before file lock is considered stale
102
+ "stale_lock_ms": 300000,
103
+
104
+ // Max age of pending notifications before expiry
105
+ "notification_max_age_ms": 300000,
106
+
107
+ // Enable branch inference heuristics in post-stop sweep
108
+ "inference_enabled": true,
109
+
110
+ // Optional: force all sessions onto one branch seed
111
+ "branch_target": "",
112
+
113
+ // Reserved (currently no-op)
114
+ "edit_debounce_ms": 200,
115
+ "gc_on_session_start": false
81
116
  }
82
117
  ```
83
118
 
@@ -93,6 +128,12 @@ Create `.opencode/gitbutler.json` in your workspace root to override defaults:
93
128
  | `branch_slug_max_length` | number | `50` | Max auto-generated branch name length |
94
129
  | `auto_update` | boolean | `true` | Check npm for newer versions |
95
130
  | `default_branch_pattern` | string | `"^ge-branch-\\d+$"` | Regex for default branch detection |
131
+ | `stale_lock_ms` | number | `300000` | Lock age threshold before stale cleanup |
132
+ | `notification_max_age_ms` | number | `300000` | Expiry window for queued state notifications |
133
+ | `inference_enabled` | boolean | `true` | Enable branch inference in post-stop sweep |
134
+ | `branch_target` | string | unset | Force all sessions to one branch seed (disables per-session isolation) |
135
+ | `edit_debounce_ms` | number | `200` | Reserved, currently no-op |
136
+ | `gc_on_session_start` | boolean | `false` | Reserved, currently no-op |
96
137
 
97
138
  All fields are optional. Missing fields use defaults.
98
139
 
@@ -105,7 +146,7 @@ How this plugin compares to GitButler's built-in Cursor and Claude Code integrat
105
146
  | Post-edit hook | `after-edit` | PostToolUse | `tool.execute.after` | Equal |
106
147
  | Stop/idle hook | `stop` | Stop | `session.idle` | Equal |
107
148
  | Branch creation | `get_or_create_session` | `get_or_create_session` | via `conversation_id` | Equal |
108
- | Auto-assign to existing branch | | | `but rub` via `findFileBranch()` | **Better** |
149
+ | Auto-assign to existing branch | Internal | Internal | Session-first `after-edit` + safe post-stop `but rub` sweep | **Better** |
109
150
  | Branch auto-rename (LLM) | From Cursor DB | From transcript | `but reword` + user prompt | Equal |
110
151
  | Auto-commit on stop | `handle_changes()` | `handle_changes()` | via `but cursor stop` | Equal |
111
152
  | Commit message (LLM) | OpenAI gpt-4-mini | OpenAI gpt-4-mini | Claude Haiku via OpenCode SDK | Equal |
@@ -118,6 +159,13 @@ How this plugin compares to GitButler's built-in Cursor and Claude Code integrat
118
159
 
119
160
  For the full architecture breakdown, gap analysis, and known issues, see [`docs/gitbutler-integration.md`](docs/gitbutler-integration.md).
120
161
 
162
+ ## Known Operational Limits
163
+
164
+ - The plugin only performs GitButler actions in workspace mode (`gitbutler/workspace` branch).
165
+ - If `branch_target` is set, all sessions intentionally share one branch seed.
166
+ - `edit_debounce_ms` and `gc_on_session_start` are reserved config fields and are currently no-op.
167
+ - GitButler CLI still has upstream edge cases around unapply/pull after squash-merge with deleted remote branches (see linked issues in `docs/gitbutler-integration.md`).
168
+
121
169
  ## Troubleshooting
122
170
 
123
171
  ### GitButler CLI not found
@@ -139,6 +187,15 @@ If `.opencode/gitbutler.json` is missing, the plugin uses all defaults. No error
139
187
 
140
188
  Enable `log_enabled: true` in config to write detailed logs to `.opencode/plugin/debug.log`. Useful for diagnosing branch creation, commit message generation, and state injection issues.
141
189
 
190
+ ### Wrong branch assignment
191
+
192
+ If changes still appear on an unexpected branch:
193
+
194
+ 1. Ensure `branch_target` is not set in `.opencode/gitbutler.json`.
195
+ 2. Check `.opencode/plugin/session-map.json` and confirm subagent sessions resolve to the expected parent.
196
+ 3. Inspect `.opencode/plugin/debug.log` for `after-edit`, `session-stop`, and `branch-collision` events.
197
+ 4. Run `but status --json -f` and verify where the file is currently assigned.
198
+
142
199
  ### LLM timeout
143
200
 
144
201
  If commit message generation times out, increase `llm_timeout_ms` in config:
package/dist/index.js CHANGED
@@ -101,9 +101,89 @@ async function loadConfig(cwd) {
101
101
  }
102
102
 
103
103
  // src/logger.ts
104
- import { appendFile } from "fs/promises";
104
+ import {
105
+ appendFile,
106
+ mkdir,
107
+ rename,
108
+ rm,
109
+ stat
110
+ } from "fs/promises";
111
+ import { dirname } from "path";
105
112
  var LOG_PATH_SUFFIX = ".opencode/plugin/debug.log";
106
- function createLogger(logEnabled, cwd) {
113
+ var DEFAULT_MAX_FILE_BYTES = 5 * 1024 * 1024;
114
+ function createLogger(logEnabled, cwd, options = {}) {
115
+ const maxFileBytes = options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES;
116
+ const logPath = `${cwd}/${LOG_PATH_SUFFIX}`;
117
+ const logDir = dirname(logPath);
118
+ const rotatedPath = `${logPath}.1`;
119
+ const warned = new Set;
120
+ let writeQueue = Promise.resolve();
121
+ function toErrorMessage(err) {
122
+ if (err instanceof Error)
123
+ return err.message;
124
+ return String(err);
125
+ }
126
+ function warnOnce(key, message, err) {
127
+ if (warned.has(key))
128
+ return;
129
+ warned.add(key);
130
+ const suffix = err ? `: ${toErrorMessage(err)}` : "";
131
+ console.warn(`[opencode-gitbutler] ${message}${suffix}`);
132
+ }
133
+ function getErrCode(err) {
134
+ if (typeof err === "object" && err !== null && "code" in err && typeof err.code === "string") {
135
+ return err.code;
136
+ }
137
+ return;
138
+ }
139
+ async function ensureLogDirectory() {
140
+ try {
141
+ await mkdir(logDir, { recursive: true });
142
+ return true;
143
+ } catch (err) {
144
+ warnOnce("mkdir", `Logger failed to create log directory at ${logDir}`, err);
145
+ return false;
146
+ }
147
+ }
148
+ async function rotateIfNeeded() {
149
+ if (maxFileBytes <= 0)
150
+ return;
151
+ let fileSize = 0;
152
+ try {
153
+ const fileInfo = await stat(logPath);
154
+ fileSize = fileInfo.size;
155
+ } catch (err) {
156
+ if (getErrCode(err) === "ENOENT")
157
+ return;
158
+ warnOnce("rotate-stat", `Logger failed to read log file size at ${logPath}`, err);
159
+ return;
160
+ }
161
+ if (fileSize < maxFileBytes)
162
+ return;
163
+ try {
164
+ await rm(rotatedPath, { force: true });
165
+ await rename(logPath, rotatedPath);
166
+ } catch (err) {
167
+ if (getErrCode(err) === "ENOENT")
168
+ return;
169
+ warnOnce("rotate", `Logger failed to rotate log file at ${logPath}`, err);
170
+ }
171
+ }
172
+ function enqueue(line) {
173
+ writeQueue = writeQueue.then(async () => {
174
+ const ready = await ensureLogDirectory();
175
+ if (!ready)
176
+ return;
177
+ await rotateIfNeeded();
178
+ try {
179
+ await appendFile(logPath, line);
180
+ } catch (err) {
181
+ warnOnce("write", `Logger failed to append to ${logPath}`, err);
182
+ }
183
+ }).catch((err) => {
184
+ warnOnce("pipeline", "Logger pipeline failure", err);
185
+ });
186
+ }
107
187
  function write(level, cat, data = {}) {
108
188
  if (!logEnabled)
109
189
  return;
@@ -113,13 +193,14 @@ function createLogger(logEnabled, cwd) {
113
193
  cat,
114
194
  ...data
115
195
  };
116
- appendFile(`${cwd}/${LOG_PATH_SUFFIX}`, JSON.stringify(entry) + `
117
- `).catch(() => {});
196
+ enqueue(JSON.stringify(entry) + `
197
+ `);
118
198
  }
119
199
  return {
120
200
  info: (cat, data) => write("info", cat, data ?? {}),
121
201
  warn: (cat, data) => write("warn", cat, data ?? {}),
122
- error: (cat, data) => write("error", cat, data ?? {})
202
+ error: (cat, data) => write("error", cat, data ?? {}),
203
+ flush: () => writeQueue
123
204
  };
124
205
  }
125
206
 
@@ -823,6 +904,9 @@ function classifyRewordFailure(stderr) {
823
904
  return "not-workspace";
824
905
  return "unknown";
825
906
  }
907
+ function rewordTrackingKey(branchCliId, commitId) {
908
+ return `${branchCliId}\x00${commitId}`;
909
+ }
826
910
  function createRewordManager(deps) {
827
911
  const {
828
912
  cwd,
@@ -1136,11 +1220,12 @@ function createRewordManager(deps) {
1136
1220
  continue;
1137
1221
  if (branch.commits.length === 0)
1138
1222
  continue;
1139
- if (rewordedBranches.has(branch.cliId))
1140
- continue;
1141
1223
  const commit = branch.commits[0];
1142
1224
  if (!commit)
1143
1225
  continue;
1226
+ const trackingKey = rewordTrackingKey(branch.cliId, commit.commitId);
1227
+ if (rewordedBranches.has(trackingKey))
1228
+ continue;
1144
1229
  try {
1145
1230
  const VALID_CONVENTIONAL = /^(feat|fix|refactor|test|docs|style|perf|chore|ci|build)(\(.+?\))?:\s/;
1146
1231
  const DEFAULT_PLACEHOLDERS = [
@@ -1156,7 +1241,7 @@ function createRewordManager(deps) {
1156
1241
  commit: commit.cliId,
1157
1242
  existingMessage: existingMsg
1158
1243
  });
1159
- rewordedBranches.add(branch.cliId);
1244
+ rewordedBranches.add(trackingKey);
1160
1245
  rewordCount++;
1161
1246
  } else {
1162
1247
  const llmMessage = await generateLLMCommitMessage(commit.commitId, prompt);
@@ -1181,7 +1266,7 @@ function createRewordManager(deps) {
1181
1266
  failCount++;
1182
1267
  continue;
1183
1268
  }
1184
- rewordedBranches.add(branch.cliId);
1269
+ rewordedBranches.add(trackingKey);
1185
1270
  savePluginState(conversationsWithEdits, rewordedBranches, branchOwnership).catch(() => {});
1186
1271
  addNotification(sessionID, `Commit on branch \`${branch.name}\` reworded to: "${commitMsg}"`);
1187
1272
  log.info("reword", {
@@ -1242,6 +1327,25 @@ function createRewordManager(deps) {
1242
1327
  }))
1243
1328
  });
1244
1329
  }
1330
+ if (candidateBranches.length === 1) {
1331
+ const branch = candidateBranches[0];
1332
+ const syncedBranchName = latestBranchName ?? branch.name;
1333
+ const current = branchOwnership.get(conversationId);
1334
+ const branchChanged = !current || current.rootSessionID !== rootSessionID || current.branchName !== syncedBranchName;
1335
+ if (branchChanged) {
1336
+ branchOwnership.set(conversationId, {
1337
+ rootSessionID,
1338
+ branchName: syncedBranchName,
1339
+ firstSeen: current?.firstSeen ?? Date.now()
1340
+ });
1341
+ savePluginState(conversationsWithEdits, rewordedBranches, branchOwnership).catch(() => {});
1342
+ log.info("branch-ownership-updated", {
1343
+ conversationId,
1344
+ rootSessionID,
1345
+ branchName: syncedBranchName
1346
+ });
1347
+ }
1348
+ }
1245
1349
  if (shouldSetTitle) {
1246
1350
  const singleBranch = candidateBranches[0];
1247
1351
  const titleToSet = latestBranchName ?? singleBranch.name;
@@ -1313,9 +1417,25 @@ function createGitButlerPlugin(config = { ...DEFAULT_CONFIG }) {
1313
1417
  const persistedState = await state.loadPluginState();
1314
1418
  const conversationsWithEdits = new Set(persistedState.conversationsWithEdits);
1315
1419
  const rewordedBranches = new Set(persistedState.rewordedBranches);
1420
+ const MAX_TRACKED_REWORD_KEYS = 2000;
1421
+ while (rewordedBranches.size > MAX_TRACKED_REWORD_KEYS) {
1422
+ const oldest = rewordedBranches.values().next().value;
1423
+ if (!oldest)
1424
+ break;
1425
+ rewordedBranches.delete(oldest);
1426
+ }
1316
1427
  for (const [convId, ownership] of Object.entries(persistedState.branchOwnership ?? {})) {
1317
1428
  branchOwnership.set(convId, ownership);
1318
1429
  }
1430
+ async function persistPluginState() {
1431
+ while (rewordedBranches.size > MAX_TRACKED_REWORD_KEYS) {
1432
+ const oldest = rewordedBranches.values().next().value;
1433
+ if (!oldest)
1434
+ break;
1435
+ rewordedBranches.delete(oldest);
1436
+ }
1437
+ await state.savePluginState(conversationsWithEdits, rewordedBranches, branchOwnership);
1438
+ }
1319
1439
  log.info("state-loaded", {
1320
1440
  conversations: conversationsWithEdits.size,
1321
1441
  reworded: rewordedBranches.size,
@@ -1369,7 +1489,9 @@ function createGitButlerPlugin(config = { ...DEFAULT_CONFIG }) {
1369
1489
  rewordedBranches,
1370
1490
  branchOwnership,
1371
1491
  editedFilesPerConversation,
1372
- savePluginState: state.savePluginState,
1492
+ savePluginState: async () => {
1493
+ await persistPluginState();
1494
+ },
1373
1495
  internalSessionIds,
1374
1496
  reapStaleLocks,
1375
1497
  client
@@ -1544,7 +1666,7 @@ function createGitButlerPlugin(config = { ...DEFAULT_CONFIG }) {
1544
1666
  firstSeen: Date.now()
1545
1667
  });
1546
1668
  }
1547
- state.savePluginState(conversationsWithEdits, rewordedBranches, branchOwnership).catch(() => {});
1669
+ persistPluginState().catch(() => {});
1548
1670
  } finally {
1549
1671
  const releasedLock = fileLocks.get(relativePath);
1550
1672
  fileLocks.delete(relativePath);
@@ -1604,7 +1726,21 @@ function createGitButlerPlugin(config = { ...DEFAULT_CONFIG }) {
1604
1726
  error: err instanceof Error ? err.message : String(err)
1605
1727
  });
1606
1728
  }
1607
- await reword.postStopProcessing(props?.sessionID, conversationId, stopFailed);
1729
+ let postStopSucceeded = false;
1730
+ try {
1731
+ await reword.postStopProcessing(props?.sessionID, conversationId, stopFailed);
1732
+ postStopSucceeded = true;
1733
+ } catch (err) {
1734
+ log.error("post-stop-error", {
1735
+ conversationId,
1736
+ error: err instanceof Error ? err.message : String(err)
1737
+ });
1738
+ }
1739
+ if (!stopFailed && postStopSucceeded) {
1740
+ conversationsWithEdits.delete(conversationId);
1741
+ editedFilesPerConversation.delete(conversationId);
1742
+ persistPluginState().catch(() => {});
1743
+ }
1608
1744
  assignmentCache.clear();
1609
1745
  cachedStatus = null;
1610
1746
  } finally {
@@ -1666,7 +1802,7 @@ ${branchList}`);
1666
1802
  }
1667
1803
  }
1668
1804
  if (rewordedBranches.size > 0) {
1669
- contextParts.push(`Reworded branches (commit messages updated): ${rewordedBranches.size} branches`);
1805
+ contextParts.push(`Tracked reworded commits: ${rewordedBranches.size}`);
1670
1806
  }
1671
1807
  if (conversationsWithEdits.has(conversationId)) {
1672
1808
  contextParts.push(`This session has active edits tracked in GitButler (conversation: ${conversationId.slice(0, 8)})`);
package/dist/logger.d.ts CHANGED
@@ -1,8 +1,12 @@
1
1
  export type LogLevel = "info" | "warn" | "error";
2
+ export type LoggerOptions = {
3
+ maxFileBytes?: number;
4
+ };
2
5
  export type Logger = {
3
6
  info: (cat: string, data?: Record<string, unknown>) => void;
4
7
  warn: (cat: string, data?: Record<string, unknown>) => void;
5
8
  error: (cat: string, data?: Record<string, unknown>) => void;
9
+ flush?: () => Promise<void>;
6
10
  };
7
11
  /**
8
12
  * Structured NDJSON logger with explicit levels.
@@ -17,5 +21,5 @@ export type Logger = {
17
21
  * jq 'select(.cat == "cursor-ok")'
18
22
  * grep '"cat":"llm-' debug.log | jq .
19
23
  */
20
- export declare function createLogger(logEnabled: boolean, cwd: string): Logger;
24
+ export declare function createLogger(logEnabled: boolean, cwd: string, options?: LoggerOptions): Logger;
21
25
  //# sourceMappingURL=logger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEjD,MAAM,MAAM,MAAM,GAAG;IACnB,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC5D,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC5D,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CAC9D,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAwBrE"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEjD,MAAM,MAAM,aAAa,GAAG;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC5D,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC5D,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC7D,KAAK,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,OAAO,EACnB,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,aAAkB,GAC1B,MAAM,CA0HR"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAUzD,wBAAsB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAa3D;AAED,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE/E;AAED,wBAAgB,qBAAqB,CACnC,MAAM,GAAE,qBAA6C,GACpD,MAAM,CAskBR"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAUzD,wBAAsB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAa3D;AAED,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE/E;AAED,wBAAgB,qBAAqB,CACnC,MAAM,GAAE,qBAA6C,GACpD,MAAM,CAumBR"}
package/dist/reword.d.ts CHANGED
@@ -100,5 +100,6 @@ export type RewordManager = {
100
100
  postStopProcessing: (sessionID: string | undefined, conversationId: string, stopFailed?: boolean) => Promise<void>;
101
101
  };
102
102
  export declare function classifyRewordFailure(stderr: string): string;
103
+ export declare function rewordTrackingKey(branchCliId: string, commitId: string): string;
103
104
  export declare function createRewordManager(deps: RewordDeps): RewordManager;
104
105
  //# sourceMappingURL=reword.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reword.d.ts","sourceRoot":"","sources":["../src/reword.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"reword.d.ts","sourceRoot":"","sources":["../src/reword.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,GAAG,EAAiB,MAAM,UAAU,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,GAAG,CAAC;IACT,MAAM,EAAE,qBAAqB,CAAC;IAC9B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,eAAe,EAAE,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;IACxD,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,CAAC;IAC9D,sBAAsB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACpC,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC9C,0BAA0B,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACrD,eAAe,EAAE,CACf,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,EAC1B,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,EACrB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,KACpC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAChC,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,MAAM,EAAE;QACN,OAAO,EAAE;YACP,QAAQ,EAAE,CAAC,IAAI,EAAE;gBACf,IAAI,EAAE;oBAAE,EAAE,EAAE,MAAM,CAAA;iBAAE,CAAC;gBACrB,KAAK,EAAE;oBAAE,KAAK,EAAE,MAAM,CAAA;iBAAE,CAAC;aAC1B,KAAK,OAAO,CAAC;gBACZ,IAAI,CAAC,EAAE,KAAK,CAAC;oBACX,IAAI,EAAE;wBAAE,IAAI,EAAE,MAAM,CAAA;qBAAE,CAAC;oBACvB,KAAK,EAAE,KAAK,CAAC;wBAAE,IAAI,EAAE,MAAM,CAAC;wBAAC,IAAI,CAAC,EAAE,MAAM,CAAA;qBAAE,CAAC,CAAC;iBAC/C,CAAC,CAAC;aACJ,CAAC,CAAC;YACH,MAAM,EAAE,CAAC,IAAI,EAAE;gBACb,IAAI,EAAE;oBAAE,KAAK,EAAE,MAAM,CAAA;iBAAE,CAAC;aACzB,KAAK,OAAO,CAAC;gBAAE,IAAI,CAAC,EAAE;oBAAE,EAAE,EAAE,MAAM,CAAA;iBAAE,CAAA;aAAE,CAAC,CAAC;YACzC,MAAM,EAAE,CAAC,IAAI,EAAE;gBACb,IAAI,EAAE;oBAAE,EAAE,EAAE,MAAM,CAAA;iBAAE,CAAC;gBACrB,IAAI,EAAE;oBACJ,KAAK,EAAE;wBAAE,UAAU,EAAE,MAAM,CAAC;wBAAC,OAAO,EAAE,MAAM,CAAA;qBAAE,CAAC;oBAC/C,MAAM,EAAE,MAAM,CAAC;oBACf,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;oBAC7B,KAAK,EAAE,KAAK,CAAC;wBAAE,IAAI,EAAE,MAAM,CAAC;wBAAC,IAAI,EAAE,MAAM,CAAA;qBAAE,CAAC,CAAC;iBAC9C,CAAC;aACH,KAAK,OAAO,CAAC;gBACZ,IAAI,CAAC,EAAE;oBACL,KAAK,EAAE,KAAK,CAAC;wBAAE,IAAI,EAAE,MAAM,CAAC;wBAAC,IAAI,CAAC,EAAE,MAAM,CAAA;qBAAE,CAAC,CAAC;iBAC/C,CAAC;aACH,CAAC,CAAC;YACH,MAAM,EAAE,CAAC,IAAI,EAAE;gBACb,IAAI,EAAE;oBAAE,EAAE,EAAE,MAAM,CAAA;iBAAE,CAAC;aACtB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;YACvB,MAAM,EAAE,CAAC,IAAI,EAAE;gBACb,IAAI,EAAE;oBAAE,EAAE,EAAE,MAAM,CAAA;iBAAE,CAAC;gBACrB,IAAI,EAAE;oBAAE,KAAK,EAAE,MAAM,CAAA;iBAAE,CAAC;aACzB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;SACxB,CAAC;KACH,CAAC;CACH,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB,CA8BA,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQvD;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAiBtD;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAStE;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/D,wBAAwB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC3F,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,cAAc,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACpH,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAU5D;AAED,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,MAAM,CAER;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,GAAG,aAAa,CA0mBnE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-gitbutler",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for GitButler integration",
6
6
  "main": "dist/index.js",