@factiii/runner 0.11.0 → 0.11.1
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/cli.js +102 -8
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -13465,10 +13465,12 @@ function execLogin(command, opts) {
|
|
|
13465
13465
|
let output = "";
|
|
13466
13466
|
let settled = false;
|
|
13467
13467
|
let timer;
|
|
13468
|
+
let idleTimer;
|
|
13468
13469
|
const done = (code, extra = "") => {
|
|
13469
13470
|
if (settled) return;
|
|
13470
13471
|
settled = true;
|
|
13471
13472
|
if (timer) clearTimeout(timer);
|
|
13473
|
+
if (idleTimer) clearTimeout(idleTimer);
|
|
13472
13474
|
resolve2({ code, output: (output + extra).slice(-cap) });
|
|
13473
13475
|
};
|
|
13474
13476
|
let proc;
|
|
@@ -13490,9 +13492,22 @@ function execLogin(command, opts) {
|
|
|
13490
13492
|
done(-1, `
|
|
13491
13493
|
[timed out after ${Math.round(opts.timeout / 1e3)}s]`);
|
|
13492
13494
|
}, opts.timeout);
|
|
13495
|
+
const idleMs = opts.idleTimeout;
|
|
13496
|
+
const bumpIdle = () => {
|
|
13497
|
+
if (!idleMs) return;
|
|
13498
|
+
if (idleTimer) clearTimeout(idleTimer);
|
|
13499
|
+
idleTimer = setTimeout(() => {
|
|
13500
|
+
killTree(proc);
|
|
13501
|
+
const secs = Math.round(idleMs / 1e3);
|
|
13502
|
+
done(-1, `
|
|
13503
|
+
[no output for ${secs}s - timed out]`);
|
|
13504
|
+
}, idleMs);
|
|
13505
|
+
};
|
|
13506
|
+
bumpIdle();
|
|
13493
13507
|
const collect = (chunk) => {
|
|
13494
13508
|
output += chunk.toString("utf-8");
|
|
13495
13509
|
if (output.length > cap * 2) output = output.slice(-cap);
|
|
13510
|
+
bumpIdle();
|
|
13496
13511
|
opts.onOutput?.(output);
|
|
13497
13512
|
};
|
|
13498
13513
|
proc.stdout.on("data", collect);
|
|
@@ -14639,6 +14654,60 @@ async function checkDeployStatus(opts) {
|
|
|
14639
14654
|
variables
|
|
14640
14655
|
};
|
|
14641
14656
|
}
|
|
14657
|
+
var RELEASE_BRANCH_LIMIT = 25;
|
|
14658
|
+
var BRANCH_FIELDS = "%(refname:short)%09%(committerdate:unix)";
|
|
14659
|
+
async function listReleaseBranches(opts) {
|
|
14660
|
+
const { workspace, branch } = await ensureWorkspaceClone(opts);
|
|
14661
|
+
await hostGit(workspace, "fetch", "origin", "--prune");
|
|
14662
|
+
let counted = true;
|
|
14663
|
+
let raw = "";
|
|
14664
|
+
try {
|
|
14665
|
+
raw = await hostGit(
|
|
14666
|
+
workspace,
|
|
14667
|
+
"for-each-ref",
|
|
14668
|
+
"--sort=-committerdate",
|
|
14669
|
+
`--format=${BRANCH_FIELDS}%09%(ahead-behind:refs/remotes/origin/${branch})%09%(contents:subject)`,
|
|
14670
|
+
"refs/remotes/origin"
|
|
14671
|
+
);
|
|
14672
|
+
} catch {
|
|
14673
|
+
counted = false;
|
|
14674
|
+
raw = await hostGit(
|
|
14675
|
+
workspace,
|
|
14676
|
+
"for-each-ref",
|
|
14677
|
+
"--sort=-committerdate",
|
|
14678
|
+
`--format=${BRANCH_FIELDS}%09%(contents:subject)`,
|
|
14679
|
+
"refs/remotes/origin"
|
|
14680
|
+
);
|
|
14681
|
+
}
|
|
14682
|
+
const branches = [];
|
|
14683
|
+
for (const row of raw.split("\n")) {
|
|
14684
|
+
if (branches.length >= RELEASE_BRANCH_LIMIT) break;
|
|
14685
|
+
const [ref = "", unix = "", ...rest] = row.split(" ");
|
|
14686
|
+
if (!ref.startsWith("origin/")) continue;
|
|
14687
|
+
const name = ref.slice("origin/".length);
|
|
14688
|
+
if (name === "HEAD" || name === branch) continue;
|
|
14689
|
+
let ahead = counted ? Number(rest.shift()?.split(" ")[0]) || 0 : 0;
|
|
14690
|
+
if (!counted) {
|
|
14691
|
+
try {
|
|
14692
|
+
const count = await hostGit(
|
|
14693
|
+
workspace,
|
|
14694
|
+
"rev-list",
|
|
14695
|
+
"--count",
|
|
14696
|
+
`origin/${branch}..${ref}`
|
|
14697
|
+
);
|
|
14698
|
+
ahead = Number(count.trim()) || 0;
|
|
14699
|
+
} catch {
|
|
14700
|
+
}
|
|
14701
|
+
}
|
|
14702
|
+
branches.push({
|
|
14703
|
+
name,
|
|
14704
|
+
ahead,
|
|
14705
|
+
updated: Number(unix) || 0,
|
|
14706
|
+
subject: rest.join(" ").trim()
|
|
14707
|
+
});
|
|
14708
|
+
}
|
|
14709
|
+
return branches;
|
|
14710
|
+
}
|
|
14642
14711
|
var requiredVariableSchema = external_exports.object({
|
|
14643
14712
|
key: external_exports.string().min(1),
|
|
14644
14713
|
title: external_exports.string().catch(""),
|
|
@@ -18578,7 +18647,8 @@ var SECRETS_MARKER = "NEED_SECRETS:";
|
|
|
18578
18647
|
var COMPLETE_MARKER = "DEPLOY_COMPLETE:";
|
|
18579
18648
|
var FAILED_MARKER = "DEPLOY_FAILED:";
|
|
18580
18649
|
var MAX_MARKERLESS_TURNS = 3;
|
|
18581
|
-
var
|
|
18650
|
+
var COMMAND_IDLE_TIMEOUT_MS = 45 * 6e4;
|
|
18651
|
+
var COMMAND_TIMEOUT_MS = 6 * 60 * 6e4;
|
|
18582
18652
|
var tail = (s, max = 8e3) => s.length > max ? s.slice(-max) : s;
|
|
18583
18653
|
function tailMarker(text) {
|
|
18584
18654
|
const zone = text.slice(-2e3);
|
|
@@ -18631,6 +18701,7 @@ async function authorizeAndRun(opts) {
|
|
|
18631
18701
|
cwd: opts.cwd,
|
|
18632
18702
|
env: { ...process.env, ...spaceEnv(opts.spaceDir), ...secrets },
|
|
18633
18703
|
timeout: COMMAND_TIMEOUT_MS,
|
|
18704
|
+
idleTimeout: COMMAND_IDLE_TIMEOUT_MS,
|
|
18634
18705
|
maxBuffer: 32 * 1024 * 1024
|
|
18635
18706
|
});
|
|
18636
18707
|
const output = redact(res.output);
|
|
@@ -18661,13 +18732,18 @@ async function startDeployRun(opts) {
|
|
|
18661
18732
|
);
|
|
18662
18733
|
await hostGit(workspace, "clean", "-fd");
|
|
18663
18734
|
await ensureClaudeSkillLink(workspace);
|
|
18735
|
+
const release = (opts.releaseBranch || "").replace(/[^\w./-]/g, "");
|
|
18736
|
+
const releaseNote = release && release !== status.branch ? `The release branch for this run is \`${release}\` - it was chosen in the Deploy modal, so do not ask which branch to ship. Check it out as your first step.` : "";
|
|
18737
|
+
if (releaseNote) {
|
|
18738
|
+
hooks.sendLog({
|
|
18739
|
+
type: "system",
|
|
18740
|
+
content: `Release branch: ${release}`
|
|
18741
|
+
});
|
|
18742
|
+
}
|
|
18664
18743
|
const contract = prompts_default.deployRun.join("\n");
|
|
18665
18744
|
const reminder = "Reminder: every declared deploy variable is intentionally unset in your shell. Never check for them or abort over them - prefix any command that needs one with `factiii-secrets run --` and the runner injects the values.";
|
|
18666
|
-
|
|
18667
|
-
|
|
18668
|
-
${reminder}` : `/deploy
|
|
18669
|
-
|
|
18670
|
-
${reminder}`;
|
|
18745
|
+
const opening = opts.provider === "codex" ? 'Use the "deploy" skill: load it and execute it step by step.' : "/deploy";
|
|
18746
|
+
let prompt2 = [opening, releaseNote, reminder].filter(Boolean).join("\n\n");
|
|
18671
18747
|
let sessionId = "";
|
|
18672
18748
|
let markerless = 0;
|
|
18673
18749
|
let todos = [];
|
|
@@ -19713,6 +19789,20 @@ var BoardAgentEngine = class _BoardAgentEngine {
|
|
|
19713
19789
|
githubToken: config.githubToken
|
|
19714
19790
|
});
|
|
19715
19791
|
}
|
|
19792
|
+
// What the Deploy modal's release picker offers: branches on origin that
|
|
19793
|
+
// could ship, newest first. See listReleaseBranches.
|
|
19794
|
+
async deployBranches() {
|
|
19795
|
+
const config = this.core.readConfig();
|
|
19796
|
+
if (!config.repoUrl || !config.githubToken) {
|
|
19797
|
+
throw new Error("Set the repository URL and GitHub token first.");
|
|
19798
|
+
}
|
|
19799
|
+
return listReleaseBranches({
|
|
19800
|
+
spaceDir: this.core.spaceDir(),
|
|
19801
|
+
repoUrl: config.repoUrl,
|
|
19802
|
+
mainBranch: config.mainBranch,
|
|
19803
|
+
githubToken: config.githubToken
|
|
19804
|
+
});
|
|
19805
|
+
}
|
|
19716
19806
|
// ── Agent skills (SKILL.md) ──
|
|
19717
19807
|
// Repo opts are optional here, unlike deploy: the global roots are readable
|
|
19718
19808
|
// with no repo configured, and listSkills reports repoAvailable: false.
|
|
@@ -19874,7 +19964,7 @@ var BoardAgentEngine = class _BoardAgentEngine {
|
|
|
19874
19964
|
return this.activity.clear("deploy-run");
|
|
19875
19965
|
}
|
|
19876
19966
|
}
|
|
19877
|
-
deployRunStart(sendLog, provider) {
|
|
19967
|
+
deployRunStart(sendLog, provider, releaseBranch) {
|
|
19878
19968
|
if (this.runState.phase === "running" || this.runState.phase === "awaiting-input" || this.runState.phase === "awaiting-auth") {
|
|
19879
19969
|
throw new Error("A deploy run is already in progress.");
|
|
19880
19970
|
}
|
|
@@ -19917,6 +20007,7 @@ var BoardAgentEngine = class _BoardAgentEngine {
|
|
|
19917
20007
|
mainBranch: opts.mainBranch,
|
|
19918
20008
|
githubToken: opts.githubToken,
|
|
19919
20009
|
provider: opts.provider,
|
|
20010
|
+
releaseBranch,
|
|
19920
20011
|
hooks: {
|
|
19921
20012
|
sendLog: bufferLog,
|
|
19922
20013
|
onTodos: (todos) => this.setRun({ todos }),
|
|
@@ -20964,6 +21055,8 @@ ${c.content.trim() || "(no description)"}`
|
|
|
20964
21055
|
return await this.bareWorkNames();
|
|
20965
21056
|
case "deployStatus":
|
|
20966
21057
|
return await this.deployStatus();
|
|
21058
|
+
case "deployBranches":
|
|
21059
|
+
return await this.deployBranches();
|
|
20967
21060
|
case "skillsList":
|
|
20968
21061
|
return await this.skillsList();
|
|
20969
21062
|
case "skillRead":
|
|
@@ -21018,7 +21111,8 @@ ${c.content.trim() || "(no description)"}`
|
|
|
21018
21111
|
return this.deployRunStart(
|
|
21019
21112
|
askLogSender ?? (() => {
|
|
21020
21113
|
}),
|
|
21021
|
-
payload?.provider
|
|
21114
|
+
payload?.provider,
|
|
21115
|
+
payload?.branch
|
|
21022
21116
|
);
|
|
21023
21117
|
case "deployRunState":
|
|
21024
21118
|
return this.deployRunState();
|
package/package.json
CHANGED