dahrk-node 0.1.1 → 0.1.2
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/main.js +151 -69
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -1269,6 +1269,25 @@ function createGitService(opts = {}) {
|
|
|
1269
1269
|
log2.warn(`could not set worktree scratch exclude at ${worktreePath}: ${e.message}`);
|
|
1270
1270
|
}
|
|
1271
1271
|
};
|
|
1272
|
+
const commitPending = (worktreePath, message) => {
|
|
1273
|
+
const SCRATCH = ".skakel/scratch";
|
|
1274
|
+
excludeScratchLocally(worktreePath);
|
|
1275
|
+
git(worktreePath, ["rm", "-r", "--cached", "--ignore-unmatch", "--quiet", SCRATCH]);
|
|
1276
|
+
git(worktreePath, ["add", "-A", "--", "."]);
|
|
1277
|
+
const dirty = !gitOk(worktreePath, ["diff", "--cached", "--quiet"]);
|
|
1278
|
+
if (dirty) {
|
|
1279
|
+
git(worktreePath, [
|
|
1280
|
+
"-c",
|
|
1281
|
+
`user.name=${authorName}`,
|
|
1282
|
+
"-c",
|
|
1283
|
+
`user.email=${authorEmail}`,
|
|
1284
|
+
"commit",
|
|
1285
|
+
"-m",
|
|
1286
|
+
message
|
|
1287
|
+
]);
|
|
1288
|
+
}
|
|
1289
|
+
return { headSha: git(worktreePath, ["rev-parse", "HEAD"]).trim(), dirty };
|
|
1290
|
+
};
|
|
1272
1291
|
const setupAuth = (token) => {
|
|
1273
1292
|
const dir = mkdtempSync(join2(tmpdir(), "dahrk-cred-"));
|
|
1274
1293
|
const script = join2(dir, "askpass.sh");
|
|
@@ -1334,6 +1353,9 @@ function createGitService(opts = {}) {
|
|
|
1334
1353
|
} finally {
|
|
1335
1354
|
auth?.cleanup();
|
|
1336
1355
|
}
|
|
1356
|
+
if (!gitOk(worktreePath, ["rev-parse", "--verify", "-q", "HEAD"])) {
|
|
1357
|
+
throw new Error(`base '${baseBranch}' did not materialise into ${worktreePath} (unborn HEAD)`);
|
|
1358
|
+
}
|
|
1337
1359
|
mkdirSync(join2(worktreePath, ".skakel", "scratch"), { recursive: true });
|
|
1338
1360
|
return refFor(spec, worktreePath);
|
|
1339
1361
|
},
|
|
@@ -1343,24 +1365,8 @@ function createGitService(opts = {}) {
|
|
|
1343
1365
|
throw new Error(`worktree missing for push: ${worktreePath}`);
|
|
1344
1366
|
}
|
|
1345
1367
|
const branch = sanitizeBranchName(opts2.branch);
|
|
1346
|
-
const
|
|
1347
|
-
|
|
1348
|
-
git(worktreePath, ["rm", "-r", "--cached", "--ignore-unmatch", "--quiet", SCRATCH]);
|
|
1349
|
-
git(worktreePath, ["add", "-A", "--", "."]);
|
|
1350
|
-
const hasStaged = !gitOk(worktreePath, ["diff", "--cached", "--quiet"]);
|
|
1351
|
-
if (hasStaged) {
|
|
1352
|
-
git(worktreePath, [
|
|
1353
|
-
"-c",
|
|
1354
|
-
`user.name=${authorName}`,
|
|
1355
|
-
"-c",
|
|
1356
|
-
`user.email=${authorEmail}`,
|
|
1357
|
-
"commit",
|
|
1358
|
-
"-m",
|
|
1359
|
-
opts2.message
|
|
1360
|
-
]);
|
|
1361
|
-
}
|
|
1362
|
-
const dirty = hasStaged;
|
|
1363
|
-
let headSha = git(worktreePath, ["rev-parse", "HEAD"]).trim();
|
|
1368
|
+
const { headSha: committedSha, dirty } = commitPending(worktreePath, opts2.message);
|
|
1369
|
+
let headSha = committedSha;
|
|
1364
1370
|
let commitsAhead = 0;
|
|
1365
1371
|
for (const baseRef of [opts2.base, `origin/${opts2.base}`, `refs/heads/${opts2.base}`]) {
|
|
1366
1372
|
if (!baseRef) continue;
|
|
@@ -1385,6 +1391,9 @@ function createGitService(opts = {}) {
|
|
|
1385
1391
|
}
|
|
1386
1392
|
}
|
|
1387
1393
|
if (fetched) {
|
|
1394
|
+
if (!gitOk(worktreePath, ["merge-base", "HEAD", "FETCH_HEAD"])) {
|
|
1395
|
+
return { headSha, pushed: false, nothingToCommit: !dirty, commitsAhead, integration: "diverged" };
|
|
1396
|
+
}
|
|
1388
1397
|
try {
|
|
1389
1398
|
git(worktreePath, [
|
|
1390
1399
|
"-c",
|
|
@@ -1397,10 +1406,18 @@ function createGitService(opts = {}) {
|
|
|
1397
1406
|
], auth?.env);
|
|
1398
1407
|
integration = "clean";
|
|
1399
1408
|
headSha = git(worktreePath, ["rev-parse", "HEAD"]).trim();
|
|
1400
|
-
} catch {
|
|
1401
|
-
const
|
|
1402
|
-
|
|
1403
|
-
|
|
1409
|
+
} catch (mergeErr) {
|
|
1410
|
+
const inMerge = gitOk(worktreePath, ["rev-parse", "--verify", "-q", "MERGE_HEAD"]);
|
|
1411
|
+
if (inMerge) {
|
|
1412
|
+
const conflictFiles = git(worktreePath, ["diff", "--name-only", "--diff-filter=U"]).split("\n").map((l) => l.trim()).filter(Boolean);
|
|
1413
|
+
git(worktreePath, ["merge", "--abort"]);
|
|
1414
|
+
return { headSha, pushed: false, nothingToCommit: !dirty, commitsAhead, integration: "conflict", conflictFiles };
|
|
1415
|
+
}
|
|
1416
|
+
const msg = mergeErr.message;
|
|
1417
|
+
if (/unrelated histories|refusing to merge/i.test(msg)) {
|
|
1418
|
+
return { headSha, pushed: false, nothingToCommit: !dirty, commitsAhead, integration: "diverged" };
|
|
1419
|
+
}
|
|
1420
|
+
throw mergeErr;
|
|
1404
1421
|
}
|
|
1405
1422
|
}
|
|
1406
1423
|
git(worktreePath, ["push", remote, `HEAD:refs/heads/${branch}`], netEnv(auth?.env));
|
|
@@ -1410,6 +1427,22 @@ function createGitService(opts = {}) {
|
|
|
1410
1427
|
}
|
|
1411
1428
|
return { headSha, pushed, nothingToCommit: !dirty, commitsAhead, ...integration ? { integration } : {} };
|
|
1412
1429
|
},
|
|
1430
|
+
async backupPush(ref, opts2) {
|
|
1431
|
+
const { worktreePath } = ref;
|
|
1432
|
+
if (!existsSync(worktreePath) || !gitOk(worktreePath, ["rev-parse", "--git-dir"])) {
|
|
1433
|
+
throw new Error(`worktree missing for backup push: ${worktreePath}`);
|
|
1434
|
+
}
|
|
1435
|
+
const wipRef = sanitizeBranchName(opts2.branch);
|
|
1436
|
+
const { headSha, dirty } = commitPending(worktreePath, opts2.message);
|
|
1437
|
+
const auth = opts2.credentialToken ? setupAuth(opts2.credentialToken) : void 0;
|
|
1438
|
+
const remote = opts2.credentialToken ? withTokenUser(ref.gitUrl) : ref.gitUrl;
|
|
1439
|
+
try {
|
|
1440
|
+
git(worktreePath, ["push", "--force", remote, `HEAD:refs/heads/${wipRef}`], netEnv(auth?.env));
|
|
1441
|
+
} finally {
|
|
1442
|
+
auth?.cleanup();
|
|
1443
|
+
}
|
|
1444
|
+
return { headSha, pushed: true, nothingToCommit: !dirty, wipRef };
|
|
1445
|
+
},
|
|
1413
1446
|
async openPrAmbient(ref, opts2) {
|
|
1414
1447
|
const ownerRepo = parseOwnerRepo(ref.gitUrl);
|
|
1415
1448
|
if (!ownerRepo) return { prError: `cannot derive owner/repo from ${ref.gitUrl}` };
|
|
@@ -2277,62 +2310,111 @@ function createStageRunner(deps) {
|
|
|
2277
2310
|
return { jobId, status: "fail", summary: `edge does not serve repo "${job.workspaceRef.repoId}"` };
|
|
2278
2311
|
}
|
|
2279
2312
|
lastUsed.set(runId, Date.now());
|
|
2280
|
-
|
|
2281
|
-
if (!ref) {
|
|
2282
|
-
ref = await deps.gitService.createWorktree({
|
|
2283
|
-
repoId: job.workspaceRef.repoId,
|
|
2284
|
-
gitUrl: job.workspaceRef.gitUrl,
|
|
2285
|
-
baseBranch: job.workspaceRef.baseBranch,
|
|
2286
|
-
runId,
|
|
2287
|
-
repo: job.workspaceRef.repo,
|
|
2288
|
-
branch: job.branch,
|
|
2289
|
-
...job.workspaceRef.credentialToken ? { credentialToken: job.workspaceRef.credentialToken } : {}
|
|
2290
|
-
});
|
|
2291
|
-
worktrees.set(runId, ref);
|
|
2292
|
-
}
|
|
2313
|
+
inFlight.set(runId, (inFlight.get(runId) ?? 0) + 1);
|
|
2293
2314
|
try {
|
|
2294
|
-
const
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2315
|
+
const mode = job.mode ?? "deliver";
|
|
2316
|
+
if (mode === "backup") {
|
|
2317
|
+
const ref2 = worktrees.get(runId);
|
|
2318
|
+
if (!ref2) {
|
|
2319
|
+
return {
|
|
2320
|
+
jobId,
|
|
2321
|
+
status: "fail",
|
|
2322
|
+
branch: job.branch,
|
|
2323
|
+
summary: `backup push: run ${runId} has no live worktree; committed HEAD cannot be preserved`
|
|
2324
|
+
};
|
|
2325
|
+
}
|
|
2326
|
+
try {
|
|
2327
|
+
const r = await deps.gitService.backupPush(ref2, {
|
|
2328
|
+
message: job.message,
|
|
2329
|
+
branch: job.branch,
|
|
2330
|
+
...job.workspaceRef.credentialToken ? { credentialToken: job.workspaceRef.credentialToken } : {}
|
|
2331
|
+
});
|
|
2332
|
+
const result = {
|
|
2333
|
+
jobId,
|
|
2334
|
+
status: "ok",
|
|
2335
|
+
branch: job.branch,
|
|
2336
|
+
headSha: r.headSha,
|
|
2337
|
+
pushed: r.pushed,
|
|
2338
|
+
nothingToCommit: r.nothingToCommit,
|
|
2339
|
+
wipRef: r.wipRef,
|
|
2340
|
+
summary: `backup: preserved ${r.headSha.slice(0, 7)} on ${r.wipRef} (no base merge, no PR)`
|
|
2341
|
+
};
|
|
2342
|
+
return result;
|
|
2343
|
+
} catch (e) {
|
|
2344
|
+
return { jobId, status: "fail", branch: job.branch, summary: `backup push failed: ${e.message}` };
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
let ref = worktrees.get(runId);
|
|
2348
|
+
if (!ref) {
|
|
2349
|
+
ref = await deps.gitService.createWorktree({
|
|
2350
|
+
repoId: job.workspaceRef.repoId,
|
|
2351
|
+
gitUrl: job.workspaceRef.gitUrl,
|
|
2352
|
+
baseBranch: job.workspaceRef.baseBranch,
|
|
2353
|
+
runId,
|
|
2354
|
+
repo: job.workspaceRef.repo,
|
|
2355
|
+
branch: job.branch,
|
|
2356
|
+
...job.workspaceRef.credentialToken ? { credentialToken: job.workspaceRef.credentialToken } : {}
|
|
2357
|
+
});
|
|
2358
|
+
worktrees.set(runId, ref);
|
|
2359
|
+
}
|
|
2360
|
+
try {
|
|
2361
|
+
const r = await deps.gitService.commitAndPush(ref, {
|
|
2362
|
+
message: job.message,
|
|
2363
|
+
branch: job.branch,
|
|
2364
|
+
base: job.base,
|
|
2365
|
+
...job.workspaceRef.credentialToken ? { credentialToken: job.workspaceRef.credentialToken } : {}
|
|
2366
|
+
});
|
|
2367
|
+
if (r.integration === "conflict") {
|
|
2368
|
+
return {
|
|
2369
|
+
jobId,
|
|
2370
|
+
status: "ok",
|
|
2371
|
+
branch: job.branch,
|
|
2372
|
+
headSha: r.headSha,
|
|
2373
|
+
pushed: false,
|
|
2374
|
+
nothingToCommit: r.nothingToCommit,
|
|
2375
|
+
commitsAhead: r.commitsAhead,
|
|
2376
|
+
integration: "conflict",
|
|
2377
|
+
...r.conflictFiles ? { conflictFiles: r.conflictFiles } : {},
|
|
2378
|
+
summary: `base advanced; merge conflict on ${job.branch} (manual merge needed)`
|
|
2379
|
+
};
|
|
2380
|
+
}
|
|
2381
|
+
if (r.integration === "diverged") {
|
|
2382
|
+
return {
|
|
2383
|
+
jobId,
|
|
2384
|
+
status: "fail",
|
|
2385
|
+
branch: job.branch,
|
|
2386
|
+
headSha: r.headSha,
|
|
2387
|
+
pushed: false,
|
|
2388
|
+
nothingToCommit: r.nothingToCommit,
|
|
2389
|
+
commitsAhead: r.commitsAhead,
|
|
2390
|
+
summary: `branch history diverged from ${job.base}; cannot auto-integrate on ${job.branch} (the branch likely needs rebuilding from ${job.base})`
|
|
2391
|
+
};
|
|
2392
|
+
}
|
|
2393
|
+
const pr = job.openPr && r.pushed ? await deps.gitService.openPrAmbient(ref, {
|
|
2394
|
+
branch: job.branch,
|
|
2395
|
+
base: job.base,
|
|
2396
|
+
title: job.openPr.title,
|
|
2397
|
+
body: job.openPr.body
|
|
2398
|
+
}) : void 0;
|
|
2301
2399
|
return {
|
|
2302
2400
|
jobId,
|
|
2303
2401
|
status: "ok",
|
|
2304
2402
|
branch: job.branch,
|
|
2305
2403
|
headSha: r.headSha,
|
|
2306
|
-
pushed:
|
|
2404
|
+
pushed: r.pushed,
|
|
2307
2405
|
nothingToCommit: r.nothingToCommit,
|
|
2308
2406
|
commitsAhead: r.commitsAhead,
|
|
2309
|
-
integration:
|
|
2310
|
-
...
|
|
2311
|
-
|
|
2407
|
+
...r.integration ? { integration: r.integration } : {},
|
|
2408
|
+
...pr?.prUrl ? { prUrl: pr.prUrl } : {},
|
|
2409
|
+
...pr?.prNumber !== void 0 ? { prNumber: pr.prNumber } : {},
|
|
2410
|
+
...pr?.prError ? { prError: pr.prError } : {},
|
|
2411
|
+
summary: r.nothingToCommit ? `no changes to commit; ${r.pushed ? "branch pushed" : "nothing pushed"}` : `committed ${r.headSha.slice(0, 7)} and pushed ${job.branch}`
|
|
2312
2412
|
};
|
|
2413
|
+
} catch (e) {
|
|
2414
|
+
return { jobId, status: "fail", summary: `push failed: ${e.message}` };
|
|
2313
2415
|
}
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
base: job.base,
|
|
2317
|
-
title: job.openPr.title,
|
|
2318
|
-
body: job.openPr.body
|
|
2319
|
-
}) : void 0;
|
|
2320
|
-
return {
|
|
2321
|
-
jobId,
|
|
2322
|
-
status: "ok",
|
|
2323
|
-
branch: job.branch,
|
|
2324
|
-
headSha: r.headSha,
|
|
2325
|
-
pushed: r.pushed,
|
|
2326
|
-
nothingToCommit: r.nothingToCommit,
|
|
2327
|
-
commitsAhead: r.commitsAhead,
|
|
2328
|
-
...r.integration ? { integration: r.integration } : {},
|
|
2329
|
-
...pr?.prUrl ? { prUrl: pr.prUrl } : {},
|
|
2330
|
-
...pr?.prNumber !== void 0 ? { prNumber: pr.prNumber } : {},
|
|
2331
|
-
...pr?.prError ? { prError: pr.prError } : {},
|
|
2332
|
-
summary: r.nothingToCommit ? `no changes to commit; ${r.pushed ? "branch pushed" : "nothing pushed"}` : `committed ${r.headSha.slice(0, 7)} and pushed ${job.branch}`
|
|
2333
|
-
};
|
|
2334
|
-
} catch (e) {
|
|
2335
|
-
return { jobId, status: "fail", summary: `push failed: ${e.message}` };
|
|
2416
|
+
} finally {
|
|
2417
|
+
inFlight.set(runId, Math.max(0, (inFlight.get(runId) ?? 1) - 1));
|
|
2336
2418
|
}
|
|
2337
2419
|
},
|
|
2338
2420
|
cancel(jobId) {
|
|
@@ -2882,7 +2964,7 @@ async function runDoctor(inputs, deps = {}) {
|
|
|
2882
2964
|
}
|
|
2883
2965
|
|
|
2884
2966
|
// src/main.ts
|
|
2885
|
-
var CLIENT_VERSION = "0.1.
|
|
2967
|
+
var CLIENT_VERSION = "0.1.2";
|
|
2886
2968
|
var DEFAULT_HUB_URL = "wss://api.dahrk.ai";
|
|
2887
2969
|
var list = (v) => (v ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
2888
2970
|
var RUNTIMES = ["claude-code", "codex", "pi"];
|