opencode-immune 1.0.30 → 1.0.32
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/dist/plugin.js +46 -99
- package/package.json +1 -1
package/dist/plugin.js
CHANGED
|
@@ -615,10 +615,12 @@ async function fetchLatestHarnessRelease(repo, token) {
|
|
|
615
615
|
const tagName = data.tag_name;
|
|
616
616
|
if (!tagName)
|
|
617
617
|
return null;
|
|
618
|
-
// Find the harness
|
|
619
|
-
const
|
|
618
|
+
// Find the correct harness asset based on OS
|
|
619
|
+
const isWindows = process.platform === "win32";
|
|
620
|
+
const assetName = isWindows ? "harness-windows.tar.gz" : "harness.tar.gz";
|
|
621
|
+
const asset = data.assets?.find((a) => a.name === assetName);
|
|
620
622
|
if (!asset) {
|
|
621
|
-
console.warn(`[opencode-immune] Harness sync: release ${tagName} has no
|
|
623
|
+
console.warn(`[opencode-immune] Harness sync: release ${tagName} has no ${assetName} asset`);
|
|
622
624
|
return null;
|
|
623
625
|
}
|
|
624
626
|
return {
|
|
@@ -684,17 +686,22 @@ function extractTarGz(archivePath, destDir) {
|
|
|
684
686
|
/**
|
|
685
687
|
* Recursively copy all files from src to dest, creating directories as needed.
|
|
686
688
|
* Overwrites existing files.
|
|
689
|
+
* skipRootFiles: file names to skip ONLY when dest === rootDest (top-level copy target).
|
|
687
690
|
*/
|
|
688
|
-
async function copyDirRecursive(src, dest,
|
|
691
|
+
async function copyDirRecursive(src, dest, skipRootFiles, rootDest) {
|
|
692
|
+
const effectiveRoot = rootDest ?? dest;
|
|
689
693
|
const entries = await (0, promises_1.readdir)(src, { withFileTypes: true });
|
|
690
694
|
await (0, promises_1.mkdir)(dest, { recursive: true });
|
|
691
695
|
for (const entry of entries) {
|
|
692
|
-
|
|
696
|
+
// Skip files only at the root destination level
|
|
697
|
+
if (skipRootFiles && dest === effectiveRoot && entry.name === ".gitignore") {
|
|
698
|
+
console.log(`[opencode-immune] Harness sync: skipping root .gitignore`);
|
|
693
699
|
continue;
|
|
700
|
+
}
|
|
694
701
|
const srcPath = (0, path_1.join)(src, entry.name);
|
|
695
702
|
const destPath = (0, path_1.join)(dest, entry.name);
|
|
696
703
|
if (entry.isDirectory()) {
|
|
697
|
-
await copyDirRecursive(srcPath, destPath);
|
|
704
|
+
await copyDirRecursive(srcPath, destPath, skipRootFiles, effectiveRoot);
|
|
698
705
|
}
|
|
699
706
|
else {
|
|
700
707
|
await (0, promises_1.mkdir)((0, path_1.dirname)(destPath), { recursive: true });
|
|
@@ -1277,92 +1284,40 @@ const PRE_COMMIT_MARKER = "0-ULTRAWORK: PRE_COMMIT";
|
|
|
1277
1284
|
const CYCLE_COMPLETE_MARKER = "0-ULTRAWORK: CYCLE_COMPLETE";
|
|
1278
1285
|
const NEXT_TASK_PATTERN = /Next task:\s*(.+)/;
|
|
1279
1286
|
const ALL_CYCLES_COMPLETE_MARKER = "0-ULTRAWORK: ALL_CYCLES_COMPLETE";
|
|
1280
|
-
// Default commit prompt — used when user's /commit command file is not found
|
|
1281
|
-
const DEFAULT_COMMIT_PROMPT = `Review the staged changes using \`git diff --cached\` and create a commit.
|
|
1282
|
-
|
|
1283
|
-
If there are no staged changes, check \`git status\` for unstaged changes and stage the relevant files first.
|
|
1284
|
-
|
|
1285
|
-
The commit message MUST follow this structure:
|
|
1286
|
-
1. First line: short description (<50 chars) prefixed with feat:/fix:/refactor:
|
|
1287
|
-
2. Second line: empty
|
|
1288
|
-
3. Body: concise bullet points describing significant changes
|
|
1289
|
-
|
|
1290
|
-
Create the commit using \`git commit -m\` with the properly formatted message.`;
|
|
1291
|
-
/**
|
|
1292
|
-
* Load the /commit command prompt from user's global config.
|
|
1293
|
-
* Falls back to DEFAULT_COMMIT_PROMPT if file doesn't exist.
|
|
1294
|
-
*/
|
|
1295
|
-
async function loadCommitPrompt() {
|
|
1296
|
-
try {
|
|
1297
|
-
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
1298
|
-
const commandPath = (0, path_1.join)(home, ".config", "opencode", "commands", "commit.md");
|
|
1299
|
-
const content = await (0, promises_1.readFile)(commandPath, "utf-8");
|
|
1300
|
-
// Strip YAML frontmatter (--- ... ---)
|
|
1301
|
-
const stripped = content.replace(/^---[\s\S]*?---\s*/, "").trim();
|
|
1302
|
-
return stripped || DEFAULT_COMMIT_PROMPT;
|
|
1303
|
-
}
|
|
1304
|
-
catch {
|
|
1305
|
-
return DEFAULT_COMMIT_PROMPT;
|
|
1306
|
-
}
|
|
1307
|
-
}
|
|
1308
|
-
/**
|
|
1309
|
-
* Execute a commit by sending the /commit prompt to the current session.
|
|
1310
|
-
* The agent will analyze the diff and create a proper commit message.
|
|
1311
|
-
* Returns true if the prompt was sent successfully.
|
|
1312
|
-
*/
|
|
1313
|
-
async function runSmartCommit(state, sessionID) {
|
|
1314
|
-
try {
|
|
1315
|
-
const commitPrompt = await loadCommitPrompt();
|
|
1316
|
-
console.log(`[opencode-immune] Smart commit: sending commit prompt to session ${sessionID}...`);
|
|
1317
|
-
// Send commit prompt to the SAME session (ultrawork already finished, session is free)
|
|
1318
|
-
await state.input.client.session.prompt({
|
|
1319
|
-
body: {
|
|
1320
|
-
parts: [
|
|
1321
|
-
{
|
|
1322
|
-
type: "text",
|
|
1323
|
-
text: commitPrompt,
|
|
1324
|
-
},
|
|
1325
|
-
],
|
|
1326
|
-
},
|
|
1327
|
-
path: { id: sessionID },
|
|
1328
|
-
});
|
|
1329
|
-
console.log("[opencode-immune] Smart commit: completed.");
|
|
1330
|
-
return true;
|
|
1331
|
-
}
|
|
1332
|
-
catch (err) {
|
|
1333
|
-
console.error("[opencode-immune] Smart commit failed:", err);
|
|
1334
|
-
return false;
|
|
1335
|
-
}
|
|
1336
|
-
}
|
|
1337
1287
|
/**
|
|
1338
|
-
* Helper: run git
|
|
1339
|
-
*
|
|
1340
|
-
*
|
|
1288
|
+
* Helper: run git add + diff-stat + commit with descriptive message.
|
|
1289
|
+
* Builds commit body from `git diff --cached --stat` so the commit
|
|
1290
|
+
* is not an opaque "auto-commit" but shows what changed.
|
|
1291
|
+
* Returns true if commit succeeded (or nothing to commit), false on error.
|
|
1341
1292
|
*/
|
|
1342
|
-
function runGitCommit(directory
|
|
1293
|
+
function runGitCommit(directory) {
|
|
1343
1294
|
return new Promise((resolve) => {
|
|
1344
|
-
// Stage all changes
|
|
1295
|
+
// Stage all changes
|
|
1345
1296
|
(0, child_process_1.execFile)("git", ["add", "-A"], { cwd: directory }, (addErr) => {
|
|
1346
1297
|
if (addErr) {
|
|
1347
1298
|
console.error("[opencode-immune] git add failed:", addErr.message);
|
|
1348
1299
|
resolve(false);
|
|
1349
1300
|
return;
|
|
1350
1301
|
}
|
|
1351
|
-
//
|
|
1352
|
-
(0, child_process_1.execFile)("git", ["
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1302
|
+
// Get diff stat for commit body
|
|
1303
|
+
(0, child_process_1.execFile)("git", ["diff", "--cached", "--stat"], { cwd: directory }, (_diffErr, diffOut) => {
|
|
1304
|
+
const stat = (diffOut ?? "").trim();
|
|
1305
|
+
const body = stat ? `\n\n${stat}` : "";
|
|
1306
|
+
const message = `chore: ultrawork cycle auto-commit${body}`;
|
|
1307
|
+
(0, child_process_1.execFile)("git", ["commit", "-m", message], { cwd: directory }, (commitErr, stdout, stderr) => {
|
|
1308
|
+
if (commitErr) {
|
|
1309
|
+
if (stderr?.includes("nothing to commit") || stdout?.includes("nothing to commit")) {
|
|
1310
|
+
console.log("[opencode-immune] git commit: nothing to commit (clean tree).");
|
|
1311
|
+
resolve(true);
|
|
1312
|
+
return;
|
|
1313
|
+
}
|
|
1314
|
+
console.error("[opencode-immune] git commit failed:", commitErr.message, stderr);
|
|
1315
|
+
resolve(false);
|
|
1358
1316
|
return;
|
|
1359
1317
|
}
|
|
1360
|
-
console.
|
|
1361
|
-
resolve(
|
|
1362
|
-
|
|
1363
|
-
}
|
|
1364
|
-
console.log("[opencode-immune] git commit succeeded:", stdout?.trim());
|
|
1365
|
-
resolve(true);
|
|
1318
|
+
console.log("[opencode-immune] git commit succeeded:", stdout?.trim());
|
|
1319
|
+
resolve(true);
|
|
1320
|
+
});
|
|
1366
1321
|
});
|
|
1367
1322
|
});
|
|
1368
1323
|
});
|
|
@@ -1391,18 +1346,14 @@ function createTextCompleteHandler(state) {
|
|
|
1391
1346
|
}
|
|
1392
1347
|
// ── PRE_COMMIT only (without CYCLE_COMPLETE in same part): run commit ──
|
|
1393
1348
|
if (text.includes(PRE_COMMIT_MARKER) && !text.includes(CYCLE_COMPLETE_MARKER)) {
|
|
1394
|
-
if (!state.commitPending
|
|
1349
|
+
if (!state.commitPending) {
|
|
1395
1350
|
state.commitPending = true;
|
|
1396
|
-
console.log("[opencode-immune] Multi-Cycle: PRE_COMMIT detected (standalone), running
|
|
1351
|
+
console.log("[opencode-immune] Multi-Cycle: PRE_COMMIT detected (standalone), running git commit...");
|
|
1397
1352
|
try {
|
|
1398
|
-
|
|
1399
|
-
if (!ok) {
|
|
1400
|
-
console.log("[opencode-immune] Multi-Cycle: smart commit failed, falling back to git commit...");
|
|
1401
|
-
await runGitCommit(state.input.directory, "chore: ultrawork cycle auto-commit");
|
|
1402
|
-
}
|
|
1353
|
+
await runGitCommit(state.input.directory);
|
|
1403
1354
|
}
|
|
1404
1355
|
catch (err) {
|
|
1405
|
-
console.error("[opencode-immune] Multi-Cycle: commit failed (standalone):", err);
|
|
1356
|
+
console.error("[opencode-immune] Multi-Cycle: git commit failed (standalone):", err);
|
|
1406
1357
|
}
|
|
1407
1358
|
finally {
|
|
1408
1359
|
state.commitPending = false;
|
|
@@ -1412,20 +1363,16 @@ function createTextCompleteHandler(state) {
|
|
|
1412
1363
|
}
|
|
1413
1364
|
// ── CYCLE_COMPLETE: self-contained sequence: commit → new session ──
|
|
1414
1365
|
if (text.includes(CYCLE_COMPLETE_MARKER)) {
|
|
1415
|
-
// Step 1: Always commit first
|
|
1416
|
-
if (!state.commitPending
|
|
1366
|
+
// Step 1: Always commit first
|
|
1367
|
+
if (!state.commitPending) {
|
|
1417
1368
|
state.commitPending = true;
|
|
1418
|
-
console.log("[opencode-immune] Multi-Cycle: CYCLE_COMPLETE detected, running
|
|
1369
|
+
console.log("[opencode-immune] Multi-Cycle: CYCLE_COMPLETE detected, running git commit first...");
|
|
1419
1370
|
try {
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
console.log("[opencode-immune] Multi-Cycle: smart commit failed, falling back to git commit...");
|
|
1423
|
-
await runGitCommit(state.input.directory, "chore: ultrawork cycle auto-commit");
|
|
1424
|
-
}
|
|
1425
|
-
console.log("[opencode-immune] Multi-Cycle: commit completed before new cycle.");
|
|
1371
|
+
await runGitCommit(state.input.directory);
|
|
1372
|
+
console.log("[opencode-immune] Multi-Cycle: git commit completed before new cycle.");
|
|
1426
1373
|
}
|
|
1427
1374
|
catch (err) {
|
|
1428
|
-
console.error("[opencode-immune] Multi-Cycle: commit failed (continuing anyway):", err);
|
|
1375
|
+
console.error("[opencode-immune] Multi-Cycle: git commit failed (continuing anyway):", err);
|
|
1429
1376
|
}
|
|
1430
1377
|
finally {
|
|
1431
1378
|
state.commitPending = false;
|