@codions/portta 0.0.0-develop.159.sha-0da77d5 → 0.0.0-develop.166.sha-d31f10f
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/assets/skills/portta-workflows/SKILL.md +11 -6
- package/dist/cli.js +1462 -1258
- package/dist/documentation.json +1 -1
- package/dist/host.js +566 -361
- package/dist/runtime/VERSION +1 -1
- package/package.json +1 -1
package/dist/host.js
CHANGED
|
@@ -33142,7 +33142,7 @@ var require_compile = __commonJS({
|
|
|
33142
33142
|
const schOrFunc = root.refs[ref];
|
|
33143
33143
|
if (schOrFunc)
|
|
33144
33144
|
return schOrFunc;
|
|
33145
|
-
let _sch =
|
|
33145
|
+
let _sch = resolve22.call(this, root, ref);
|
|
33146
33146
|
if (_sch === void 0) {
|
|
33147
33147
|
const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
|
|
33148
33148
|
const { schemaId } = this.opts;
|
|
@@ -33169,7 +33169,7 @@ var require_compile = __commonJS({
|
|
|
33169
33169
|
function sameSchemaEnv(s1, s2) {
|
|
33170
33170
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
33171
33171
|
}
|
|
33172
|
-
function
|
|
33172
|
+
function resolve22(root, ref) {
|
|
33173
33173
|
let sch;
|
|
33174
33174
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
33175
33175
|
ref = sch;
|
|
@@ -33994,7 +33994,7 @@ var require_fast_uri = __commonJS({
|
|
|
33994
33994
|
}
|
|
33995
33995
|
return uri;
|
|
33996
33996
|
}
|
|
33997
|
-
function
|
|
33997
|
+
function resolve22(baseURI, relativeURI, options) {
|
|
33998
33998
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
33999
33999
|
const {
|
|
34000
34000
|
parsed: baseParsed,
|
|
@@ -34027,49 +34027,49 @@ var require_fast_uri = __commonJS({
|
|
|
34027
34027
|
schemelessOptions.skipEscape = true;
|
|
34028
34028
|
return serialize2(resolved2, schemelessOptions);
|
|
34029
34029
|
}
|
|
34030
|
-
function resolveComponent(base,
|
|
34030
|
+
function resolveComponent(base, relative6, options, skipNormalization) {
|
|
34031
34031
|
const target = {};
|
|
34032
34032
|
if (!skipNormalization) {
|
|
34033
34033
|
base = parse4(serialize2(base, options), options);
|
|
34034
|
-
|
|
34034
|
+
relative6 = parse4(serialize2(relative6, options), options);
|
|
34035
34035
|
}
|
|
34036
34036
|
options = options || {};
|
|
34037
|
-
if (!options.tolerant &&
|
|
34038
|
-
target.scheme =
|
|
34039
|
-
target.userinfo =
|
|
34040
|
-
target.host =
|
|
34041
|
-
target.port =
|
|
34042
|
-
target.path = removeDotSegments(
|
|
34043
|
-
target.query =
|
|
34037
|
+
if (!options.tolerant && relative6.scheme) {
|
|
34038
|
+
target.scheme = relative6.scheme;
|
|
34039
|
+
target.userinfo = relative6.userinfo;
|
|
34040
|
+
target.host = relative6.host;
|
|
34041
|
+
target.port = relative6.port;
|
|
34042
|
+
target.path = removeDotSegments(relative6.path || "");
|
|
34043
|
+
target.query = relative6.query;
|
|
34044
34044
|
} else {
|
|
34045
|
-
if (
|
|
34046
|
-
target.userinfo =
|
|
34047
|
-
target.host =
|
|
34048
|
-
target.port =
|
|
34049
|
-
target.path = removeDotSegments(
|
|
34050
|
-
target.query =
|
|
34045
|
+
if (relative6.userinfo !== void 0 || relative6.host !== void 0 || relative6.port !== void 0) {
|
|
34046
|
+
target.userinfo = relative6.userinfo;
|
|
34047
|
+
target.host = relative6.host;
|
|
34048
|
+
target.port = relative6.port;
|
|
34049
|
+
target.path = removeDotSegments(relative6.path || "");
|
|
34050
|
+
target.query = relative6.query;
|
|
34051
34051
|
} else {
|
|
34052
|
-
if (!
|
|
34052
|
+
if (!relative6.path) {
|
|
34053
34053
|
target.path = base.path;
|
|
34054
|
-
if (
|
|
34055
|
-
target.query =
|
|
34054
|
+
if (relative6.query !== void 0) {
|
|
34055
|
+
target.query = relative6.query;
|
|
34056
34056
|
} else {
|
|
34057
34057
|
target.query = base.query;
|
|
34058
34058
|
}
|
|
34059
34059
|
} else {
|
|
34060
|
-
if (
|
|
34061
|
-
target.path = removeDotSegments(
|
|
34060
|
+
if (relative6.path[0] === "/") {
|
|
34061
|
+
target.path = removeDotSegments(relative6.path);
|
|
34062
34062
|
} else {
|
|
34063
34063
|
if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
|
|
34064
|
-
target.path = "/" +
|
|
34064
|
+
target.path = "/" + relative6.path;
|
|
34065
34065
|
} else if (!base.path) {
|
|
34066
|
-
target.path =
|
|
34066
|
+
target.path = relative6.path;
|
|
34067
34067
|
} else {
|
|
34068
|
-
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) +
|
|
34068
|
+
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative6.path;
|
|
34069
34069
|
}
|
|
34070
34070
|
target.path = removeDotSegments(target.path);
|
|
34071
34071
|
}
|
|
34072
|
-
target.query =
|
|
34072
|
+
target.query = relative6.query;
|
|
34073
34073
|
}
|
|
34074
34074
|
target.userinfo = base.userinfo;
|
|
34075
34075
|
target.host = base.host;
|
|
@@ -34077,7 +34077,7 @@ var require_fast_uri = __commonJS({
|
|
|
34077
34077
|
}
|
|
34078
34078
|
target.scheme = base.scheme;
|
|
34079
34079
|
}
|
|
34080
|
-
target.fragment =
|
|
34080
|
+
target.fragment = relative6.fragment;
|
|
34081
34081
|
return target;
|
|
34082
34082
|
}
|
|
34083
34083
|
function equal(uriA, uriB, options) {
|
|
@@ -34356,7 +34356,7 @@ var require_fast_uri = __commonJS({
|
|
|
34356
34356
|
var fastUri = {
|
|
34357
34357
|
SCHEMES,
|
|
34358
34358
|
normalize: normalize2,
|
|
34359
|
-
resolve:
|
|
34359
|
+
resolve: resolve22,
|
|
34360
34360
|
resolveComponent,
|
|
34361
34361
|
equal,
|
|
34362
34362
|
serialize: serialize2,
|
|
@@ -41506,10 +41506,9 @@ function expandTemplate(template, env2) {
|
|
|
41506
41506
|
|
|
41507
41507
|
// ../host/src/modules/taskflow/adapters/devcontainer-environment.ts
|
|
41508
41508
|
import { createHash as createHash3 } from "node:crypto";
|
|
41509
|
-
import {
|
|
41510
|
-
import { access, readdir, readFile } from "node:fs/promises";
|
|
41509
|
+
import { access as access2, readdir, readFile as readFile2 } from "node:fs/promises";
|
|
41511
41510
|
import { createRequire } from "node:module";
|
|
41512
|
-
import { dirname as dirname4,
|
|
41511
|
+
import { dirname as dirname4, join as join5, relative as relative2, resolve as resolve3 } from "node:path";
|
|
41513
41512
|
|
|
41514
41513
|
// ../../node_modules/zod/v4/classic/external.js
|
|
41515
41514
|
var external_exports = {};
|
|
@@ -44775,16 +44774,16 @@ function hostToolInvocation(tool, options) {
|
|
|
44775
44774
|
return /[\s'"\\]/.test(resolved2) ? `'${resolved2.replaceAll("'", "'\\''")}'` : resolved2;
|
|
44776
44775
|
}
|
|
44777
44776
|
function resolveWorkerBins(env2 = process.env) {
|
|
44778
|
-
const
|
|
44777
|
+
const resolve22 = (name, override) => {
|
|
44779
44778
|
const explicit = override?.trim();
|
|
44780
44779
|
if (explicit) return resolveHostTool(explicit, { env: env2 }) ?? explicit;
|
|
44781
44780
|
return resolveHostTool(name, { env: env2 }) ?? void 0;
|
|
44782
44781
|
};
|
|
44783
44782
|
return {
|
|
44784
|
-
codexBin:
|
|
44785
|
-
opencodeBin:
|
|
44786
|
-
pathToClaudeCodeExecutable:
|
|
44787
|
-
piBin:
|
|
44783
|
+
codexBin: resolve22("codex", env2.CODEX_BIN),
|
|
44784
|
+
opencodeBin: resolve22("opencode", env2.OPENCODE_BIN),
|
|
44785
|
+
pathToClaudeCodeExecutable: resolve22("claude"),
|
|
44786
|
+
piBin: resolve22("pi", env2.PI_BIN)
|
|
44788
44787
|
};
|
|
44789
44788
|
}
|
|
44790
44789
|
|
|
@@ -44822,10 +44821,10 @@ function webStream(stream) {
|
|
|
44822
44821
|
};
|
|
44823
44822
|
}
|
|
44824
44823
|
function writeToStdin(stream, input2) {
|
|
44825
|
-
return new Promise((
|
|
44824
|
+
return new Promise((resolve22, reject2) => {
|
|
44826
44825
|
stream.write(input2, (error61) => {
|
|
44827
44826
|
if (error61) reject2(error61);
|
|
44828
|
-
else
|
|
44827
|
+
else resolve22();
|
|
44829
44828
|
});
|
|
44830
44829
|
});
|
|
44831
44830
|
}
|
|
@@ -44847,8 +44846,8 @@ var NodeProcessRunner = class {
|
|
|
44847
44846
|
let settled = false;
|
|
44848
44847
|
let resolveExit = () => {
|
|
44849
44848
|
};
|
|
44850
|
-
const exited = new Promise((
|
|
44851
|
-
resolveExit =
|
|
44849
|
+
const exited = new Promise((resolve22) => {
|
|
44850
|
+
resolveExit = resolve22;
|
|
44852
44851
|
});
|
|
44853
44852
|
const finish = (code, signal, closeOutputs = false) => {
|
|
44854
44853
|
if (settled) return;
|
|
@@ -44926,6 +44925,177 @@ async function runCaptured(runner, spec) {
|
|
|
44926
44925
|
return { stdout, stderr, exit };
|
|
44927
44926
|
}
|
|
44928
44927
|
|
|
44928
|
+
// ../host/src/modules/taskflow/adapters/worktree-git-mount.ts
|
|
44929
|
+
import { access, readFile, realpath, rename, unlink, writeFile as writeFile2 } from "node:fs/promises";
|
|
44930
|
+
import { basename as basename2, isAbsolute as isAbsolute2, join as join4, posix, relative, resolve as resolve2, sep } from "node:path";
|
|
44931
|
+
var PREFLIGHT = "Dev Container preflight";
|
|
44932
|
+
var BACK_LINK = "gitdir";
|
|
44933
|
+
function repairCommand(workspacePath) {
|
|
44934
|
+
return `git -C ${workspacePath} worktree repair --relative-paths`;
|
|
44935
|
+
}
|
|
44936
|
+
function toPosix(value) {
|
|
44937
|
+
return sep === "/" ? value : value.replaceAll(sep, "/");
|
|
44938
|
+
}
|
|
44939
|
+
async function exists(path) {
|
|
44940
|
+
try {
|
|
44941
|
+
await access(path);
|
|
44942
|
+
return true;
|
|
44943
|
+
} catch {
|
|
44944
|
+
return false;
|
|
44945
|
+
}
|
|
44946
|
+
}
|
|
44947
|
+
async function readRaw(path) {
|
|
44948
|
+
try {
|
|
44949
|
+
return await readFile(path, "utf8");
|
|
44950
|
+
} catch {
|
|
44951
|
+
return null;
|
|
44952
|
+
}
|
|
44953
|
+
}
|
|
44954
|
+
async function writeAtomic(path, content) {
|
|
44955
|
+
const temporary = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
44956
|
+
try {
|
|
44957
|
+
await writeFile2(temporary, content, "utf8");
|
|
44958
|
+
await rename(temporary, path);
|
|
44959
|
+
} catch (error61) {
|
|
44960
|
+
await unlink(temporary).catch(() => {
|
|
44961
|
+
});
|
|
44962
|
+
throw error61;
|
|
44963
|
+
}
|
|
44964
|
+
}
|
|
44965
|
+
async function gitDirs(runner, cwd) {
|
|
44966
|
+
const result = await runCaptured(runner, {
|
|
44967
|
+
command: "git",
|
|
44968
|
+
args: ["rev-parse", "--path-format=absolute", "--git-dir", "--git-common-dir"],
|
|
44969
|
+
cwd
|
|
44970
|
+
});
|
|
44971
|
+
if (result.exit.code !== 0) return null;
|
|
44972
|
+
const [gitDir, commonDir] = result.stdout.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
44973
|
+
return gitDir && commonDir ? { gitDir, commonDir } : null;
|
|
44974
|
+
}
|
|
44975
|
+
function linkTarget(content) {
|
|
44976
|
+
const value = content.trim();
|
|
44977
|
+
if (!value.startsWith("gitdir:")) return null;
|
|
44978
|
+
const target = value.slice("gitdir:".length).trim();
|
|
44979
|
+
return target.length > 0 ? target : null;
|
|
44980
|
+
}
|
|
44981
|
+
async function worktreeLink(workspacePath) {
|
|
44982
|
+
const content = await readRaw(join4(workspacePath, ".git"));
|
|
44983
|
+
return content === null ? null : linkTarget(content);
|
|
44984
|
+
}
|
|
44985
|
+
async function porttaOwned(runner, workspacePath, gitDir) {
|
|
44986
|
+
if (await exists(gitRuntimePaths(gitDir).meta)) return true;
|
|
44987
|
+
const result = await runCaptured(runner, {
|
|
44988
|
+
command: "git",
|
|
44989
|
+
args: ["config", "--get", RUNTIME_IDENTITY.gitBaseConfigKey],
|
|
44990
|
+
cwd: workspacePath
|
|
44991
|
+
});
|
|
44992
|
+
return result.exit.code === 0 && result.stdout.trim().length > 0;
|
|
44993
|
+
}
|
|
44994
|
+
async function planRelativeRelink(workspacePath, dirs) {
|
|
44995
|
+
const forwardPath = join4(workspacePath, ".git");
|
|
44996
|
+
const backPath = join4(dirs.gitDir, BACK_LINK);
|
|
44997
|
+
if (join4(dirs.commonDir, "worktrees", basename2(dirs.gitDir)) !== dirs.gitDir)
|
|
44998
|
+
return {
|
|
44999
|
+
ok: false,
|
|
45000
|
+
reason: `its Git dir ${dirs.gitDir} is not <common dir>/worktrees/<id> under ${dirs.commonDir}`
|
|
45001
|
+
};
|
|
45002
|
+
const forward = await readRaw(forwardPath);
|
|
45003
|
+
if (forward === null) return { ok: false, reason: `${forwardPath} could not be read` };
|
|
45004
|
+
const target = linkTarget(forward);
|
|
45005
|
+
if (target === null) return { ok: false, reason: `${forwardPath} does not record a gitdir link` };
|
|
45006
|
+
if (resolve2(workspacePath, target) !== dirs.gitDir)
|
|
45007
|
+
return { ok: false, reason: `${forwardPath} points at ${resolve2(workspacePath, target)}, not at ${dirs.gitDir}` };
|
|
45008
|
+
const back = await readRaw(backPath);
|
|
45009
|
+
if (back === null) return { ok: false, reason: `${backPath} could not be read` };
|
|
45010
|
+
if (resolve2(dirs.gitDir, back.trim()) !== forwardPath)
|
|
45011
|
+
return { ok: false, reason: `${backPath} points at ${resolve2(dirs.gitDir, back.trim())}, not at ${forwardPath}` };
|
|
45012
|
+
return {
|
|
45013
|
+
ok: true,
|
|
45014
|
+
writes: [
|
|
45015
|
+
{ path: forwardPath, previous: forward, next: `gitdir: ${toPosix(relative(workspacePath, dirs.gitDir))}
|
|
45016
|
+
` },
|
|
45017
|
+
{ path: backPath, previous: back, next: `${toPosix(relative(dirs.gitDir, forwardPath))}
|
|
45018
|
+
` }
|
|
45019
|
+
]
|
|
45020
|
+
};
|
|
45021
|
+
}
|
|
45022
|
+
async function relinkRelative(runner, workspacePath, dirs) {
|
|
45023
|
+
const plan = await planRelativeRelink(workspacePath, dirs);
|
|
45024
|
+
if (!plan.ok) return plan.reason;
|
|
45025
|
+
const written = [];
|
|
45026
|
+
const restore = async () => {
|
|
45027
|
+
for (const write2 of written) await writeAtomic(write2.path, write2.previous).catch(() => {
|
|
45028
|
+
});
|
|
45029
|
+
};
|
|
45030
|
+
for (const write2 of plan.writes) {
|
|
45031
|
+
try {
|
|
45032
|
+
await writeAtomic(write2.path, write2.next);
|
|
45033
|
+
written.push(write2);
|
|
45034
|
+
} catch (error61) {
|
|
45035
|
+
await restore();
|
|
45036
|
+
return `${write2.path} could not be rewritten: ${error61 instanceof Error ? error61.message : String(error61)}`;
|
|
45037
|
+
}
|
|
45038
|
+
}
|
|
45039
|
+
const after = await gitDirs(runner, workspacePath);
|
|
45040
|
+
if (!after || after.gitDir !== dirs.gitDir || after.commonDir !== dirs.commonDir) {
|
|
45041
|
+
await restore();
|
|
45042
|
+
return "the rewritten links did not resolve back to the same repository, so they were reverted";
|
|
45043
|
+
}
|
|
45044
|
+
return null;
|
|
45045
|
+
}
|
|
45046
|
+
async function worktreeGitMountArgs(input2) {
|
|
45047
|
+
const { runner } = input2;
|
|
45048
|
+
const workspacePath = await realpath(input2.workspacePath).catch(() => input2.workspacePath);
|
|
45049
|
+
const dirs = await gitDirs(runner, workspacePath);
|
|
45050
|
+
if (!dirs || dirs.gitDir === dirs.commonDir) return [];
|
|
45051
|
+
const where = input2.configRef ? `${workspacePath} (${input2.configRef})` : workspacePath;
|
|
45052
|
+
if (input2.workspaceMount) {
|
|
45053
|
+
throw new Error(
|
|
45054
|
+
`${PREFLIGHT}: ${where} is a linked Git worktree and the configuration sets a custom workspaceMount. The Dev Containers CLI then ignores --mount-git-worktree-common-dir (devcontainers/cli#1243), so the Git common dir cannot be mounted and Git would not work inside the container. Remove workspaceMount from the Dev Container configuration, or open this configuration from the main checkout.`
|
|
45055
|
+
);
|
|
45056
|
+
}
|
|
45057
|
+
let link = await worktreeLink(workspacePath);
|
|
45058
|
+
const backLink = await readRaw(join4(dirs.gitDir, BACK_LINK));
|
|
45059
|
+
if (link !== null && isAbsolute2(link) || backLink !== null && isAbsolute2(backLink.trim())) {
|
|
45060
|
+
if (!await porttaOwned(runner, workspacePath, dirs.gitDir)) {
|
|
45061
|
+
throw new Error(
|
|
45062
|
+
`${PREFLIGHT}: the Git worktree at ${where} is linked with an absolute gitdir, which does not exist inside a container. Portta did not create this worktree and will not rewrite its links. Migrate it explicitly with: ${repairCommand(workspacePath)}`
|
|
45063
|
+
);
|
|
45064
|
+
}
|
|
45065
|
+
const failure = await relinkRelative(runner, workspacePath, dirs);
|
|
45066
|
+
if (failure !== null) {
|
|
45067
|
+
throw new Error(
|
|
45068
|
+
`${PREFLIGHT}: the Git worktree at ${where} is linked with an absolute gitdir and could not be migrated to relative links: ${failure}. Run: ${repairCommand(workspacePath)}`
|
|
45069
|
+
);
|
|
45070
|
+
}
|
|
45071
|
+
link = await worktreeLink(workspacePath);
|
|
45072
|
+
}
|
|
45073
|
+
if (link === null || isAbsolute2(link)) {
|
|
45074
|
+
throw new Error(
|
|
45075
|
+
`${PREFLIGHT}: the Git worktree at ${where} has no relative gitdir link, so the Git common dir cannot be mounted into the container. Run: ${repairCommand(workspacePath)}`
|
|
45076
|
+
);
|
|
45077
|
+
}
|
|
45078
|
+
const containerWorkspacePath = input2.containerWorkspacePath;
|
|
45079
|
+
if (!containerWorkspacePath) {
|
|
45080
|
+
throw new Error(
|
|
45081
|
+
`${PREFLIGHT}: the container workspace folder for ${where} is unknown, so the Git common dir of this linked worktree cannot be mounted into the container.`
|
|
45082
|
+
);
|
|
45083
|
+
}
|
|
45084
|
+
const up = toPosix(relative(dirs.gitDir, dirs.commonDir));
|
|
45085
|
+
if (up.length === 0 || up.split("/").some((segment) => segment !== "..")) {
|
|
45086
|
+
throw new Error(
|
|
45087
|
+
`${PREFLIGHT}: the Git common dir ${dirs.commonDir} does not contain the worktree Git dir ${dirs.gitDir}, so it cannot be mapped into the container for ${where}.`
|
|
45088
|
+
);
|
|
45089
|
+
}
|
|
45090
|
+
const containerGitDir = posix.resolve(containerWorkspacePath, toPosix(link));
|
|
45091
|
+
const containerCommonDir = posix.resolve(containerGitDir, up);
|
|
45092
|
+
return [
|
|
45093
|
+
"--mount-git-worktree-common-dir",
|
|
45094
|
+
"--mount",
|
|
45095
|
+
`type=bind,source=${dirs.commonDir},target=${containerCommonDir}`
|
|
45096
|
+
];
|
|
45097
|
+
}
|
|
45098
|
+
|
|
44929
45099
|
// ../host/src/modules/taskflow/adapters/devcontainer-environment.ts
|
|
44930
45100
|
var cliOutputSchema = external_exports.object({
|
|
44931
45101
|
containerId: external_exports.string(),
|
|
@@ -44947,47 +45117,26 @@ function hash2(value) {
|
|
|
44947
45117
|
function quoteShell(value) {
|
|
44948
45118
|
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
44949
45119
|
}
|
|
44950
|
-
function
|
|
45120
|
+
async function exists2(path) {
|
|
44951
45121
|
try {
|
|
44952
|
-
|
|
44953
|
-
const gitDir = value.startsWith("gitdir: ") ? value.slice("gitdir: ".length).trim() : "";
|
|
44954
|
-
return gitDir.length > 0 && !isAbsolute2(gitDir) ? gitDir : null;
|
|
44955
|
-
} catch {
|
|
44956
|
-
return null;
|
|
44957
|
-
}
|
|
44958
|
-
}
|
|
44959
|
-
function commonGitDir(path, separator) {
|
|
44960
|
-
const marker = `${separator}worktrees${separator}`;
|
|
44961
|
-
const index = path.lastIndexOf(marker);
|
|
44962
|
-
return index > 0 ? path.slice(0, index) : null;
|
|
44963
|
-
}
|
|
44964
|
-
function worktreeGitMount(workspacePath, containerWorkspacePath) {
|
|
44965
|
-
const gitDir = relativeWorktreeGitDir(workspacePath);
|
|
44966
|
-
if (!gitDir || !containerWorkspacePath) return null;
|
|
44967
|
-
const source = commonGitDir(resolve2(workspacePath, gitDir), sep);
|
|
44968
|
-
const target = commonGitDir(posix.resolve(containerWorkspacePath, gitDir.replaceAll(sep, "/")), "/");
|
|
44969
|
-
return source && target ? `type=bind,source=${source},target=${target}` : null;
|
|
44970
|
-
}
|
|
44971
|
-
async function exists(path) {
|
|
44972
|
-
try {
|
|
44973
|
-
await access(path);
|
|
45122
|
+
await access2(path);
|
|
44974
45123
|
return true;
|
|
44975
45124
|
} catch {
|
|
44976
45125
|
return false;
|
|
44977
45126
|
}
|
|
44978
45127
|
}
|
|
44979
45128
|
async function findDevcontainerConfigs(workspacePath) {
|
|
44980
|
-
const rootConfig =
|
|
44981
|
-
const directory =
|
|
45129
|
+
const rootConfig = join5(workspacePath, ".devcontainer.json");
|
|
45130
|
+
const directory = join5(workspacePath, ".devcontainer");
|
|
44982
45131
|
const configs = [];
|
|
44983
|
-
if (await
|
|
44984
|
-
if (await
|
|
44985
|
-
if (await
|
|
45132
|
+
if (await exists2(rootConfig)) configs.push(rootConfig);
|
|
45133
|
+
if (await exists2(join5(directory, "devcontainer.json"))) configs.push(join5(directory, "devcontainer.json"));
|
|
45134
|
+
if (await exists2(directory)) {
|
|
44986
45135
|
const entries = await readdir(directory, { withFileTypes: true });
|
|
44987
45136
|
for (const entry of entries) {
|
|
44988
45137
|
if (!entry.isDirectory()) continue;
|
|
44989
|
-
const candidate =
|
|
44990
|
-
if (await
|
|
45138
|
+
const candidate = join5(directory, entry.name, "devcontainer.json");
|
|
45139
|
+
if (await exists2(candidate)) configs.push(candidate);
|
|
44991
45140
|
}
|
|
44992
45141
|
}
|
|
44993
45142
|
return [...new Set(configs)].sort();
|
|
@@ -45082,7 +45231,7 @@ async function resolveComposeConfiguration(runner, config2, merged) {
|
|
|
45082
45231
|
if (files.length === 0) return { hashMaterial: "", risks: [] };
|
|
45083
45232
|
const args = [
|
|
45084
45233
|
"compose",
|
|
45085
|
-
...files.flatMap((file2) => ["-f",
|
|
45234
|
+
...files.flatMap((file2) => ["-f", resolve3(dirname4(config2), file2)]),
|
|
45086
45235
|
"config",
|
|
45087
45236
|
"--format",
|
|
45088
45237
|
"json"
|
|
@@ -45106,6 +45255,7 @@ var DevContainerProvider = class {
|
|
|
45106
45255
|
cli;
|
|
45107
45256
|
cliPrefix;
|
|
45108
45257
|
workspaceFolders = /* @__PURE__ */ new Map();
|
|
45258
|
+
workspaceMounts = /* @__PURE__ */ new Map();
|
|
45109
45259
|
runner;
|
|
45110
45260
|
constructor(runner = new NodeProcessRunner(), cli) {
|
|
45111
45261
|
this.runner = runner;
|
|
@@ -45116,7 +45266,7 @@ var DevContainerProvider = class {
|
|
|
45116
45266
|
}
|
|
45117
45267
|
const packagePath = createRequire(import.meta.url).resolve("@devcontainers/cli/package.json");
|
|
45118
45268
|
this.cli = process.execPath;
|
|
45119
|
-
this.cliPrefix = [
|
|
45269
|
+
this.cliPrefix = [join5(dirname4(packagePath), "devcontainer.js")];
|
|
45120
45270
|
}
|
|
45121
45271
|
args(args) {
|
|
45122
45272
|
return [...this.cliPrefix, ...args];
|
|
@@ -45138,7 +45288,7 @@ var DevContainerProvider = class {
|
|
|
45138
45288
|
return {
|
|
45139
45289
|
provider: this.id,
|
|
45140
45290
|
available: version2.supported,
|
|
45141
|
-
configRefs: configs.map((config2) =>
|
|
45291
|
+
configRefs: configs.map((config2) => relative2(context.workspacePath, config2)),
|
|
45142
45292
|
...version2.version ? { version: version2.version } : {},
|
|
45143
45293
|
diagnostics: version2.diagnostic ? [version2.diagnostic] : []
|
|
45144
45294
|
};
|
|
@@ -45146,7 +45296,7 @@ var DevContainerProvider = class {
|
|
|
45146
45296
|
async configFor(context) {
|
|
45147
45297
|
const configs = await findDevcontainerConfigs(context.workspacePath);
|
|
45148
45298
|
if (context.configRef) {
|
|
45149
|
-
const selected2 =
|
|
45299
|
+
const selected2 = resolve3(context.workspacePath, context.configRef);
|
|
45150
45300
|
if (!configs.includes(selected2)) throw new Error(`Dev Container config was not found: ${context.configRef}`);
|
|
45151
45301
|
return selected2;
|
|
45152
45302
|
}
|
|
@@ -45176,16 +45326,19 @@ var DevContainerProvider = class {
|
|
|
45176
45326
|
});
|
|
45177
45327
|
if (result.exit.code !== 0) throw new Error(`devcontainer read-configuration failed: ${result.stderr.trim()}`);
|
|
45178
45328
|
const raw2 = readOutputSchema.parse(JSON.parse(result.stdout));
|
|
45179
|
-
const rawConfig = await
|
|
45329
|
+
const rawConfig = await readFile2(config2, "utf8");
|
|
45180
45330
|
const merged = record2(raw2.mergedConfiguration ?? raw2.configuration);
|
|
45181
45331
|
if (typeof merged.workspaceFolder === "string") this.workspaceFolders.set(config2, merged.workspaceFolder);
|
|
45332
|
+
if (typeof merged.workspaceMount === "string" && merged.workspaceMount.trim().length > 0)
|
|
45333
|
+
this.workspaceMounts.set(config2, merged.workspaceMount);
|
|
45334
|
+
else this.workspaceMounts.delete(config2);
|
|
45182
45335
|
const compose2 = await resolveComposeConfiguration(this.runner, config2, merged);
|
|
45183
|
-
const lockfile =
|
|
45184
|
-
const lockfileExists = await
|
|
45185
|
-
const lockfileContents = lockfileExists ? await
|
|
45336
|
+
const lockfile = join5(dirname4(config2), "devcontainer-lock.json");
|
|
45337
|
+
const lockfileExists = await exists2(lockfile);
|
|
45338
|
+
const lockfileContents = lockfileExists ? await readFile2(lockfile, "utf8") : "";
|
|
45186
45339
|
return {
|
|
45187
45340
|
provider: this.id,
|
|
45188
|
-
configRef:
|
|
45341
|
+
configRef: relative2(context.workspacePath, config2),
|
|
45189
45342
|
configHash: hash2(`${rawConfig}\0${result.stdout}\0${compose2.hashMaterial}\0${lockfileContents}`),
|
|
45190
45343
|
workspace: { hostPath: context.workspacePath },
|
|
45191
45344
|
capabilities: {
|
|
@@ -45203,10 +45356,16 @@ var DevContainerProvider = class {
|
|
|
45203
45356
|
}
|
|
45204
45357
|
async up(environment, scope, removeExisting) {
|
|
45205
45358
|
if (!environment.configRef) throw new Error("Dev Container environment requires configRef");
|
|
45206
|
-
const config2 =
|
|
45359
|
+
const config2 = resolve3(environment.workspace.hostPath, environment.configRef);
|
|
45207
45360
|
const id = environmentIdFor(scope, "devcontainer", environment.configRef);
|
|
45208
45361
|
const composeName = `tf_${id.slice(4)}`;
|
|
45209
|
-
const
|
|
45362
|
+
const gitArgs = await worktreeGitMountArgs({
|
|
45363
|
+
runner: this.runner,
|
|
45364
|
+
workspacePath: environment.workspace.hostPath,
|
|
45365
|
+
containerWorkspacePath: this.workspaceFolders.get(config2),
|
|
45366
|
+
workspaceMount: this.workspaceMounts.get(config2),
|
|
45367
|
+
configRef: environment.configRef
|
|
45368
|
+
});
|
|
45210
45369
|
const result = await runCaptured(this.runner, {
|
|
45211
45370
|
command: this.cli,
|
|
45212
45371
|
args: this.args([
|
|
@@ -45219,8 +45378,7 @@ var DevContainerProvider = class {
|
|
|
45219
45378
|
`taskflow.environment.id=${id}`,
|
|
45220
45379
|
"--include-configuration",
|
|
45221
45380
|
"--include-merged-configuration",
|
|
45222
|
-
...
|
|
45223
|
-
...gitMount ? ["--mount", gitMount] : [],
|
|
45381
|
+
...gitArgs,
|
|
45224
45382
|
...removeExisting ? ["--remove-existing-container"] : []
|
|
45225
45383
|
]),
|
|
45226
45384
|
cwd: dirname4(config2),
|
|
@@ -45414,14 +45572,14 @@ exec ${argv.join(" ")} "$cwd" ${quoteShell(executable)} "$@"
|
|
|
45414
45572
|
const configuredFiles = configuration.dockerComposeFile;
|
|
45415
45573
|
const files = Array.isArray(configuredFiles) ? configuredFiles.filter((value) => typeof value === "string") : typeof configuredFiles === "string" ? [configuredFiles] : [];
|
|
45416
45574
|
if (project && typeof configRef === "string" && files.length > 0) {
|
|
45417
|
-
const configDirectory = dirname4(
|
|
45575
|
+
const configDirectory = dirname4(resolve3(handle.workspace.hostPath, configRef));
|
|
45418
45576
|
return {
|
|
45419
45577
|
command: "docker",
|
|
45420
45578
|
args: [
|
|
45421
45579
|
"compose",
|
|
45422
45580
|
"--project-name",
|
|
45423
45581
|
project,
|
|
45424
|
-
...files.flatMap((file2) => ["-f",
|
|
45582
|
+
...files.flatMap((file2) => ["-f", resolve3(configDirectory, file2)]),
|
|
45425
45583
|
"logs",
|
|
45426
45584
|
"--follow",
|
|
45427
45585
|
"--tail",
|
|
@@ -45440,10 +45598,10 @@ exec ${argv.join(" ")} "$cwd" ${quoteShell(executable)} "$@"
|
|
|
45440
45598
|
|
|
45441
45599
|
// ../host/src/modules/taskflow/adapters/dockerfile-environment.ts
|
|
45442
45600
|
import { createHash as createHash4 } from "node:crypto";
|
|
45443
|
-
import { existsSync, readFileSync as
|
|
45444
|
-
import { resolve as
|
|
45601
|
+
import { existsSync, readFileSync as readFileSync3 } from "node:fs";
|
|
45602
|
+
import { resolve as resolve4 } from "node:path";
|
|
45445
45603
|
function dockerfileFor(context) {
|
|
45446
|
-
const dockerfile =
|
|
45604
|
+
const dockerfile = resolve4(context.workspacePath, context.configRef ?? "Dockerfile");
|
|
45447
45605
|
if (!existsSync(dockerfile)) throw new Error(`Dockerfile does not exist: ${context.configRef ?? "Dockerfile"}`);
|
|
45448
45606
|
return dockerfile;
|
|
45449
45607
|
}
|
|
@@ -45470,7 +45628,7 @@ var DockerfileEnvironmentProvider = class {
|
|
|
45470
45628
|
command: "docker",
|
|
45471
45629
|
args: ["version", "--format", "{{.Client.Version}}"]
|
|
45472
45630
|
});
|
|
45473
|
-
const dockerfile =
|
|
45631
|
+
const dockerfile = resolve4(context.workspacePath, "Dockerfile");
|
|
45474
45632
|
return {
|
|
45475
45633
|
provider: this.id,
|
|
45476
45634
|
available: version2.exit.code === 0 && existsSync(dockerfile),
|
|
@@ -45481,7 +45639,7 @@ var DockerfileEnvironmentProvider = class {
|
|
|
45481
45639
|
}
|
|
45482
45640
|
async resolve(context) {
|
|
45483
45641
|
const dockerfile = dockerfileFor(context);
|
|
45484
|
-
const source =
|
|
45642
|
+
const source = readFileSync3(dockerfile, "utf8");
|
|
45485
45643
|
return {
|
|
45486
45644
|
provider: this.id,
|
|
45487
45645
|
configRef: dockerfile,
|
|
@@ -45765,8 +45923,8 @@ function sanitizeProjectPrefix(raw2) {
|
|
|
45765
45923
|
return raw2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").replace(/-{2,}/g, "-");
|
|
45766
45924
|
}
|
|
45767
45925
|
function deriveProjectPrefix(projectDir, takenPrefixes) {
|
|
45768
|
-
const
|
|
45769
|
-
const base = sanitizeProjectPrefix(
|
|
45926
|
+
const basename12 = projectDir.replace(/\/+$/, "").split("/").pop() ?? APP_SLUG;
|
|
45927
|
+
const base = sanitizeProjectPrefix(basename12) || APP_SLUG;
|
|
45770
45928
|
const taken = /* @__PURE__ */ new Set([...takenPrefixes, ...RESERVED_PROJECT_PREFIXES]);
|
|
45771
45929
|
if (!taken.has(base)) return base;
|
|
45772
45930
|
for (let n = 2; n < 1e3; n++) {
|
|
@@ -46312,6 +46470,9 @@ var AvailableBranchSchema = external_exports.object({
|
|
|
46312
46470
|
var AvailableBranchesQuerySchema = external_exports.object({
|
|
46313
46471
|
includeRemote: BooleanLikeSchema.optional()
|
|
46314
46472
|
});
|
|
46473
|
+
var RemoveWorktreeQuerySchema = external_exports.object({
|
|
46474
|
+
force: BooleanLikeSchema.optional()
|
|
46475
|
+
});
|
|
46315
46476
|
var NumberLikePathParamSchema = external_exports.union([
|
|
46316
46477
|
external_exports.number().int().nonnegative(),
|
|
46317
46478
|
external_exports.string().regex(/^\d+$/).transform((value) => Number(value))
|
|
@@ -47245,6 +47406,7 @@ var apiContract = defineRoutes({
|
|
|
47245
47406
|
summary: "Remove a worktree",
|
|
47246
47407
|
path: apiPaths.removeWorktree,
|
|
47247
47408
|
pathParams: WorktreeNameParamsSchema,
|
|
47409
|
+
query: RemoveWorktreeQuerySchema,
|
|
47248
47410
|
responses: {
|
|
47249
47411
|
200: OkResponseSchema,
|
|
47250
47412
|
...commonErrorResponses
|
|
@@ -47841,7 +48003,7 @@ exec ${JSON.stringify(executable)} "$@"
|
|
|
47841
48003
|
};
|
|
47842
48004
|
|
|
47843
48005
|
// ../host/src/modules/taskflow/adapters/projects-registry.ts
|
|
47844
|
-
import { mkdirSync as mkdirSync3, readFileSync as
|
|
48006
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
47845
48007
|
import { dirname as dirname6 } from "node:path";
|
|
47846
48008
|
function defaultRegistryFile() {
|
|
47847
48009
|
return globalPaths().projectsRegistry;
|
|
@@ -47850,7 +48012,7 @@ function createProjectsRegistry(file2 = defaultRegistryFile()) {
|
|
|
47850
48012
|
function read() {
|
|
47851
48013
|
let raw2;
|
|
47852
48014
|
try {
|
|
47853
|
-
raw2 =
|
|
48015
|
+
raw2 = readFileSync4(file2, "utf8");
|
|
47854
48016
|
} catch {
|
|
47855
48017
|
return [];
|
|
47856
48018
|
}
|
|
@@ -48271,15 +48433,15 @@ import { spawnSync as spawnSync3 } from "node:child_process";
|
|
|
48271
48433
|
|
|
48272
48434
|
// ../host/src/modules/taskflow/adapters/session-gateway.ts
|
|
48273
48435
|
import { createHash as createHash5 } from "node:crypto";
|
|
48274
|
-
import { basename as
|
|
48436
|
+
import { basename as basename3, resolve as resolve5 } from "node:path";
|
|
48275
48437
|
function sanitizeNameSegment(value, maxLength = 24) {
|
|
48276
48438
|
const sanitized = value.toLowerCase().replace(/[^a-z0-9_.-]+/g, "-").replace(/-{2,}/g, "-").replace(/^[.-]+|[.-]+$/g, "");
|
|
48277
48439
|
const trimmed = sanitized.slice(0, maxLength);
|
|
48278
48440
|
return trimmed || "x";
|
|
48279
48441
|
}
|
|
48280
48442
|
function buildProjectSessionName(projectRoot2) {
|
|
48281
|
-
const resolved2 =
|
|
48282
|
-
const base = sanitizeNameSegment(
|
|
48443
|
+
const resolved2 = resolve5(projectRoot2);
|
|
48444
|
+
const base = sanitizeNameSegment(basename3(resolved2), 18);
|
|
48283
48445
|
const hash4 = createHash5("sha1").update(resolved2).digest("hex").slice(0, 8);
|
|
48284
48446
|
return `${RUNTIME_IDENTITY.tmuxPrefix}-${base}-${hash4}`;
|
|
48285
48447
|
}
|
|
@@ -48546,19 +48708,19 @@ var TmuxGateway = class {
|
|
|
48546
48708
|
|
|
48547
48709
|
// ../host/src/modules/taskflow/assets.ts
|
|
48548
48710
|
import { existsSync as existsSync2 } from "node:fs";
|
|
48549
|
-
import { join as
|
|
48711
|
+
import { join as join6, resolve as resolve6 } from "node:path";
|
|
48550
48712
|
function taskflowAssets(env2 = process.env, directory = import.meta.dirname) {
|
|
48551
|
-
const bundled =
|
|
48552
|
-
if (existsSync2(
|
|
48713
|
+
const bundled = join6(directory, "assets");
|
|
48714
|
+
if (existsSync2(join6(bundled, "workflows"))) {
|
|
48553
48715
|
return {
|
|
48554
|
-
workflowBuiltinsDir: env2[ENV_NAMES.workflowBuiltinsDir] ||
|
|
48555
|
-
workflowSkill:
|
|
48716
|
+
workflowBuiltinsDir: env2[ENV_NAMES.workflowBuiltinsDir] || join6(bundled, "workflows"),
|
|
48717
|
+
workflowSkill: join6(bundled, "skills", "portta-workflows", "SKILL.md")
|
|
48556
48718
|
};
|
|
48557
48719
|
}
|
|
48558
|
-
const repository =
|
|
48720
|
+
const repository = resolve6(directory, "../../../../..");
|
|
48559
48721
|
return {
|
|
48560
|
-
workflowBuiltinsDir: env2[ENV_NAMES.workflowBuiltinsDir] ||
|
|
48561
|
-
workflowSkill:
|
|
48722
|
+
workflowBuiltinsDir: env2[ENV_NAMES.workflowBuiltinsDir] || join6(repository, "packages", "host", "workflows"),
|
|
48723
|
+
workflowSkill: join6(repository, "skills", "portta-workflows", "SKILL.md")
|
|
48562
48724
|
};
|
|
48563
48725
|
}
|
|
48564
48726
|
|
|
@@ -48766,19 +48928,19 @@ import { homedir as homedir2 } from "node:os";
|
|
|
48766
48928
|
// ../host/src/modules/taskflow/adapters/git.ts
|
|
48767
48929
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
48768
48930
|
import { readdirSync, realpathSync, rmSync, statSync as statSync3 } from "node:fs";
|
|
48769
|
-
import { basename as
|
|
48931
|
+
import { basename as basename4, dirname as dirname7, join as join7, resolve as resolve7 } from "node:path";
|
|
48770
48932
|
function canonicalizeFsPath(input2) {
|
|
48771
|
-
const resolved2 =
|
|
48933
|
+
const resolved2 = resolve7(input2);
|
|
48772
48934
|
try {
|
|
48773
48935
|
return realpathSync(resolved2);
|
|
48774
48936
|
} catch {
|
|
48775
48937
|
const missing = [];
|
|
48776
48938
|
let current = resolved2;
|
|
48777
48939
|
while (current !== dirname7(current)) {
|
|
48778
|
-
missing.unshift(
|
|
48940
|
+
missing.unshift(basename4(current));
|
|
48779
48941
|
current = dirname7(current);
|
|
48780
48942
|
try {
|
|
48781
|
-
return
|
|
48943
|
+
return join7(realpathSync(current), ...missing);
|
|
48782
48944
|
} catch {
|
|
48783
48945
|
}
|
|
48784
48946
|
}
|
|
@@ -48862,7 +49024,7 @@ function currentCheckoutRef(cwd) {
|
|
|
48862
49024
|
}
|
|
48863
49025
|
function resolveRepoRoot(dir) {
|
|
48864
49026
|
const direct = tryRunGit(["rev-parse", "--show-toplevel"], dir);
|
|
48865
|
-
if (direct.ok) return
|
|
49027
|
+
if (direct.ok) return resolve7(dir, direct.stdout);
|
|
48866
49028
|
let entries;
|
|
48867
49029
|
try {
|
|
48868
49030
|
entries = readdirSync(dir);
|
|
@@ -48870,24 +49032,24 @@ function resolveRepoRoot(dir) {
|
|
|
48870
49032
|
return null;
|
|
48871
49033
|
}
|
|
48872
49034
|
for (const entry of entries) {
|
|
48873
|
-
const child =
|
|
49035
|
+
const child = join7(dir, entry);
|
|
48874
49036
|
try {
|
|
48875
49037
|
if (!statSync3(child).isDirectory()) continue;
|
|
48876
49038
|
} catch {
|
|
48877
49039
|
continue;
|
|
48878
49040
|
}
|
|
48879
49041
|
const childResult = tryRunGit(["rev-parse", "--show-toplevel"], child);
|
|
48880
|
-
if (childResult.ok) return
|
|
49042
|
+
if (childResult.ok) return resolve7(child, childResult.stdout);
|
|
48881
49043
|
}
|
|
48882
49044
|
return null;
|
|
48883
49045
|
}
|
|
48884
49046
|
function resolveWorktreeRoot(cwd) {
|
|
48885
49047
|
const output2 = runGit(["rev-parse", "--show-toplevel"], cwd);
|
|
48886
|
-
return
|
|
49048
|
+
return resolve7(cwd, output2);
|
|
48887
49049
|
}
|
|
48888
49050
|
function resolveWorktreeGitDir(cwd) {
|
|
48889
49051
|
const output2 = runGit(["rev-parse", "--git-dir"], cwd);
|
|
48890
|
-
return
|
|
49052
|
+
return resolve7(cwd, output2);
|
|
48891
49053
|
}
|
|
48892
49054
|
function parseGitWorktreePorcelain(output2) {
|
|
48893
49055
|
const entries = [];
|
|
@@ -49084,6 +49246,21 @@ var NodeGitGateway = class {
|
|
|
49084
49246
|
const result = tryRunGit(["diff", "HEAD", "--no-color"], cwd);
|
|
49085
49247
|
return result.ok ? result.stdout : "";
|
|
49086
49248
|
}
|
|
49249
|
+
/**
|
|
49250
|
+
* Commits reachable from HEAD and from nothing else that would survive this
|
|
49251
|
+
* worktree: not on an origin branch, not on the project's main branch. It
|
|
49252
|
+
* answers "would deleting this branch lose work", which `aheadCount` cannot:
|
|
49253
|
+
* with no upstream and no remote at all, every commit counts as ahead.
|
|
49254
|
+
*/
|
|
49255
|
+
countUnsavedCommits(cwd, baseBranch) {
|
|
49256
|
+
const count = (args) => {
|
|
49257
|
+
const result = tryRunGit(args, cwd);
|
|
49258
|
+
return result.ok ? parseInt(result.stdout, 10) || 0 : null;
|
|
49259
|
+
};
|
|
49260
|
+
const excludingBase = baseBranch ? count(["rev-list", "--count", "HEAD", "--not", "--remotes=origin", baseBranch]) : null;
|
|
49261
|
+
if (excludingBase !== null) return excludingBase;
|
|
49262
|
+
return count(["rev-list", "--count", "HEAD", "--not", "--remotes=origin"]) ?? 0;
|
|
49263
|
+
}
|
|
49087
49264
|
listUnpushedCommits(cwd) {
|
|
49088
49265
|
let result = tryRunGit(["log", "--oneline", "@{upstream}..HEAD"], cwd);
|
|
49089
49266
|
if (!result.ok) {
|
|
@@ -49434,7 +49611,7 @@ function resolveSocketPath(env2) {
|
|
|
49434
49611
|
return session ? `${home2}/.config/herdr/sessions/${session}/herdr.sock` : `${home2}/.config/herdr/herdr.sock`;
|
|
49435
49612
|
}
|
|
49436
49613
|
async function request(socketPath, method, params) {
|
|
49437
|
-
return await new Promise((
|
|
49614
|
+
return await new Promise((resolve22, reject2) => {
|
|
49438
49615
|
let buffer = "";
|
|
49439
49616
|
let settled = false;
|
|
49440
49617
|
const settle = (fn) => {
|
|
@@ -49458,7 +49635,7 @@ async function request(socketPath, method, params) {
|
|
|
49458
49635
|
const line = buffer.slice(0, newline);
|
|
49459
49636
|
clearTimeout(timer);
|
|
49460
49637
|
try {
|
|
49461
|
-
settle(() =>
|
|
49638
|
+
settle(() => resolve22(parseHerdrResponse(JSON.parse(line))));
|
|
49462
49639
|
} catch {
|
|
49463
49640
|
settle(() => reject2(new HerdrRequestError(method, "invalid_response", line.slice(0, 200))));
|
|
49464
49641
|
}
|
|
@@ -49758,8 +49935,8 @@ var HerdrGateway = class {
|
|
|
49758
49935
|
};
|
|
49759
49936
|
|
|
49760
49937
|
// ../host/src/modules/taskflow/adapters/hooks.ts
|
|
49761
|
-
import { access as
|
|
49762
|
-
import { join as
|
|
49938
|
+
import { access as access3 } from "node:fs/promises";
|
|
49939
|
+
import { join as join8 } from "node:path";
|
|
49763
49940
|
function buildErrorMessage(name, exitCode, stdout, stderr) {
|
|
49764
49941
|
const output2 = stderr.trim() || stdout.trim();
|
|
49765
49942
|
if (output2) {
|
|
@@ -49804,7 +49981,7 @@ var NodeLifecycleHookRunner = class {
|
|
|
49804
49981
|
}
|
|
49805
49982
|
async hasEnvrc(cwd) {
|
|
49806
49983
|
try {
|
|
49807
|
-
await
|
|
49984
|
+
await access3(join8(cwd, ".envrc"));
|
|
49808
49985
|
return true;
|
|
49809
49986
|
} catch {
|
|
49810
49987
|
return false;
|
|
@@ -49839,7 +50016,7 @@ var NodePortProbe = class {
|
|
|
49839
50016
|
this.hostnames = hostnames;
|
|
49840
50017
|
}
|
|
49841
50018
|
isListening(port) {
|
|
49842
|
-
return new Promise((
|
|
50019
|
+
return new Promise((resolve22) => {
|
|
49843
50020
|
let settled = false;
|
|
49844
50021
|
let pending = this.hostnames.length;
|
|
49845
50022
|
const settle = (result) => {
|
|
@@ -49847,20 +50024,20 @@ var NodePortProbe = class {
|
|
|
49847
50024
|
if (result) {
|
|
49848
50025
|
settled = true;
|
|
49849
50026
|
clearTimeout(timer);
|
|
49850
|
-
|
|
50027
|
+
resolve22(true);
|
|
49851
50028
|
return;
|
|
49852
50029
|
}
|
|
49853
50030
|
pending--;
|
|
49854
50031
|
if (pending === 0) {
|
|
49855
50032
|
settled = true;
|
|
49856
50033
|
clearTimeout(timer);
|
|
49857
|
-
|
|
50034
|
+
resolve22(false);
|
|
49858
50035
|
}
|
|
49859
50036
|
};
|
|
49860
50037
|
const timer = setTimeout(() => {
|
|
49861
50038
|
if (!settled) {
|
|
49862
50039
|
settled = true;
|
|
49863
|
-
|
|
50040
|
+
resolve22(false);
|
|
49864
50041
|
}
|
|
49865
50042
|
}, this.timeoutMs);
|
|
49866
50043
|
for (const hostname3 of this.hostnames) {
|
|
@@ -49882,7 +50059,7 @@ var NodePortProbe = class {
|
|
|
49882
50059
|
|
|
49883
50060
|
// ../host/src/modules/taskflow/adapters/session-discovery.ts
|
|
49884
50061
|
import { open as open2, readdir as readdir3, stat as stat3 } from "node:fs/promises";
|
|
49885
|
-
import { basename as
|
|
50062
|
+
import { basename as basename6, join as join10 } from "node:path";
|
|
49886
50063
|
import { setTimeout as sleep3 } from "node:timers/promises";
|
|
49887
50064
|
|
|
49888
50065
|
// ../host/src/modules/taskflow/lib/type-guards.ts
|
|
@@ -49894,8 +50071,8 @@ function isStringArray2(raw2) {
|
|
|
49894
50071
|
}
|
|
49895
50072
|
|
|
49896
50073
|
// ../host/src/modules/taskflow/adapters/claude-cli.ts
|
|
49897
|
-
import { readdir as readdir2, readFile as
|
|
49898
|
-
import { basename as
|
|
50074
|
+
import { readdir as readdir2, readFile as readFile3, stat as stat2 } from "node:fs/promises";
|
|
50075
|
+
import { basename as basename5, join as join9 } from "node:path";
|
|
49899
50076
|
function isRecord4(raw2) {
|
|
49900
50077
|
return typeof raw2 === "object" && raw2 !== null && !Array.isArray(raw2);
|
|
49901
50078
|
}
|
|
@@ -50079,19 +50256,19 @@ function readClaudeProjectsRoot() {
|
|
|
50079
50256
|
if (!home2) {
|
|
50080
50257
|
throw new Error("HOME is required to resolve Claude sessions");
|
|
50081
50258
|
}
|
|
50082
|
-
return
|
|
50259
|
+
return join9(home2, ".claude", "projects");
|
|
50083
50260
|
}
|
|
50084
50261
|
async function listJsonlFiles(dir) {
|
|
50085
50262
|
try {
|
|
50086
50263
|
const entries = await readdir2(dir, { withFileTypes: true });
|
|
50087
|
-
return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map((entry) =>
|
|
50264
|
+
return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map((entry) => join9(dir, entry.name));
|
|
50088
50265
|
} catch {
|
|
50089
50266
|
return [];
|
|
50090
50267
|
}
|
|
50091
50268
|
}
|
|
50092
50269
|
async function findClaudeSessionPath(sessionId, cwd) {
|
|
50093
50270
|
const projectsRoot = readClaudeProjectsRoot();
|
|
50094
|
-
const primaryPath =
|
|
50271
|
+
const primaryPath = join9(projectsRoot, encodeClaudeProjectDir(cwd), `${sessionId}.jsonl`);
|
|
50095
50272
|
try {
|
|
50096
50273
|
await stat2(primaryPath);
|
|
50097
50274
|
return primaryPath;
|
|
@@ -50100,7 +50277,7 @@ async function findClaudeSessionPath(sessionId, cwd) {
|
|
|
50100
50277
|
const projectDirs = await readdir2(projectsRoot, { withFileTypes: true }).catch(() => []);
|
|
50101
50278
|
for (const entry of projectDirs) {
|
|
50102
50279
|
if (!entry.isDirectory()) continue;
|
|
50103
|
-
const candidate =
|
|
50280
|
+
const candidate = join9(projectsRoot, entry.name, `${sessionId}.jsonl`);
|
|
50104
50281
|
try {
|
|
50105
50282
|
await stat2(candidate);
|
|
50106
50283
|
return candidate;
|
|
@@ -50224,7 +50401,7 @@ var ClaudeCliClient = class {
|
|
|
50224
50401
|
}
|
|
50225
50402
|
async listSessions(cwd) {
|
|
50226
50403
|
const projectsRoot = readClaudeProjectsRoot();
|
|
50227
|
-
const primaryDir =
|
|
50404
|
+
const primaryDir = join9(projectsRoot, encodeClaudeProjectDir(cwd));
|
|
50228
50405
|
const primaryFiles = await listJsonlFiles(primaryDir);
|
|
50229
50406
|
if (primaryFiles.length > 0) {
|
|
50230
50407
|
return await this.summarizeSessionFiles(primaryFiles, cwd);
|
|
@@ -50233,7 +50410,7 @@ var ClaudeCliClient = class {
|
|
|
50233
50410
|
const matchedFiles = [];
|
|
50234
50411
|
for (const entry of projectDirs) {
|
|
50235
50412
|
if (!entry.isDirectory()) continue;
|
|
50236
|
-
const files = await listJsonlFiles(
|
|
50413
|
+
const files = await listJsonlFiles(join9(projectsRoot, entry.name));
|
|
50237
50414
|
for (const filePath of files) {
|
|
50238
50415
|
const session = await this.readSessionFile(filePath);
|
|
50239
50416
|
if (session?.cwd === cwd) {
|
|
@@ -50281,8 +50458,8 @@ var ClaudeCliClient = class {
|
|
|
50281
50458
|
let sessionIdResolve = null;
|
|
50282
50459
|
let sessionIdReject = null;
|
|
50283
50460
|
let interrupted = false;
|
|
50284
|
-
const sessionId = new Promise((
|
|
50285
|
-
sessionIdResolve =
|
|
50461
|
+
const sessionId = new Promise((resolve22, reject2) => {
|
|
50462
|
+
sessionIdResolve = resolve22;
|
|
50286
50463
|
sessionIdReject = reject2;
|
|
50287
50464
|
});
|
|
50288
50465
|
const resolveSessionId = (value) => {
|
|
@@ -50353,7 +50530,7 @@ var ClaudeCliClient = class {
|
|
|
50353
50530
|
const info = await stat2(filePath).catch(() => null);
|
|
50354
50531
|
if (!info) return null;
|
|
50355
50532
|
return {
|
|
50356
|
-
sessionId:
|
|
50533
|
+
sessionId: basename5(filePath, ".jsonl"),
|
|
50357
50534
|
cwd,
|
|
50358
50535
|
path: filePath,
|
|
50359
50536
|
lastSeenAt: info.mtime.toISOString()
|
|
@@ -50364,10 +50541,10 @@ var ClaudeCliClient = class {
|
|
|
50364
50541
|
}
|
|
50365
50542
|
async readSessionFile(filePath) {
|
|
50366
50543
|
try {
|
|
50367
|
-
const text = await
|
|
50544
|
+
const text = await readFile3(filePath, "utf8");
|
|
50368
50545
|
return buildClaudeSessionFromText({
|
|
50369
50546
|
path: filePath,
|
|
50370
|
-
sessionId:
|
|
50547
|
+
sessionId: basename5(filePath, ".jsonl"),
|
|
50371
50548
|
text
|
|
50372
50549
|
});
|
|
50373
50550
|
} catch {
|
|
@@ -50430,12 +50607,12 @@ function newestFirst(sessions2) {
|
|
|
50430
50607
|
return sessions2.sort((left, right) => right.mtimeMs - left.mtimeMs).map((entry) => entry.sessionId);
|
|
50431
50608
|
}
|
|
50432
50609
|
async function listClaudeSessionIds(cwd) {
|
|
50433
|
-
const dir =
|
|
50610
|
+
const dir = join10(home(), ".claude", "projects", encodeClaudeProjectDir(cwd));
|
|
50434
50611
|
const names = await readdir3(dir).catch(() => []);
|
|
50435
50612
|
const stamped = await Promise.all(
|
|
50436
50613
|
names.filter((name) => name.endsWith(".jsonl")).map(async (name) => {
|
|
50437
|
-
const info = await stat3(
|
|
50438
|
-
return info ? { sessionId:
|
|
50614
|
+
const info = await stat3(join10(dir, name)).catch(() => null);
|
|
50615
|
+
return info ? { sessionId: basename6(name, ".jsonl"), mtimeMs: info.mtimeMs } : null;
|
|
50439
50616
|
})
|
|
50440
50617
|
);
|
|
50441
50618
|
return newestFirst(stamped.filter((entry) => entry !== null));
|
|
@@ -50470,15 +50647,15 @@ async function readCodexSessionCwdId(path) {
|
|
|
50470
50647
|
}
|
|
50471
50648
|
}
|
|
50472
50649
|
async function listCodexSessionIds(cwd) {
|
|
50473
|
-
const root =
|
|
50650
|
+
const root = join10(home(), ".codex", "sessions");
|
|
50474
50651
|
const relPaths = await readdir3(root, { recursive: true }).catch(() => []);
|
|
50475
50652
|
const rollouts = relPaths.filter((rel) => {
|
|
50476
|
-
const name =
|
|
50653
|
+
const name = basename6(rel);
|
|
50477
50654
|
return name.startsWith("rollout-") && name.endsWith(".jsonl");
|
|
50478
50655
|
});
|
|
50479
50656
|
const stamped = await Promise.all(
|
|
50480
50657
|
rollouts.map(async (rel) => {
|
|
50481
|
-
const path =
|
|
50658
|
+
const path = join10(root, rel);
|
|
50482
50659
|
const meta3 = await readCodexSessionCwdId(path);
|
|
50483
50660
|
if (!meta3 || meta3.cwd !== cwd) return null;
|
|
50484
50661
|
const info = await stat3(path).catch(() => null);
|
|
@@ -50488,11 +50665,11 @@ async function listCodexSessionIds(cwd) {
|
|
|
50488
50665
|
return newestFirst(stamped.filter((entry) => entry !== null));
|
|
50489
50666
|
}
|
|
50490
50667
|
async function findCodexSessionPath(sessionId, cwd) {
|
|
50491
|
-
const root =
|
|
50668
|
+
const root = join10(home(), ".codex", "sessions");
|
|
50492
50669
|
const relPaths = await readdir3(root, { recursive: true }).catch(() => []);
|
|
50493
50670
|
for (const rel of relPaths) {
|
|
50494
|
-
if (!
|
|
50495
|
-
const path =
|
|
50671
|
+
if (!basename6(rel).endsWith(`${sessionId}.jsonl`)) continue;
|
|
50672
|
+
const path = join10(root, rel);
|
|
50496
50673
|
const meta3 = await readCodexSessionCwdId(path);
|
|
50497
50674
|
if (meta3?.id === sessionId && meta3.cwd === cwd) return path;
|
|
50498
50675
|
}
|
|
@@ -50573,8 +50750,8 @@ async function captureNewSessionId(discovery, agent, cwd, before, options = {})
|
|
|
50573
50750
|
}
|
|
50574
50751
|
|
|
50575
50752
|
// ../host/src/modules/taskflow/adapters/fs.ts
|
|
50576
|
-
import { mkdir as mkdir2, readFile as
|
|
50577
|
-
import { join as
|
|
50753
|
+
import { mkdir as mkdir2, readFile as readFile4, writeFile as writeFile3 } from "node:fs/promises";
|
|
50754
|
+
import { join as join11 } from "node:path";
|
|
50578
50755
|
var SAFE_ENV_VALUE_RE = /^[A-Za-z0-9_./:@%+=,-]+$/;
|
|
50579
50756
|
var DOTENV_LINE_RE = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)/;
|
|
50580
50757
|
function stringifyAllocatedPorts(ports) {
|
|
@@ -50605,7 +50782,7 @@ function parseDotenv(content) {
|
|
|
50605
50782
|
}
|
|
50606
50783
|
async function loadDotenvLocal(worktreePath) {
|
|
50607
50784
|
try {
|
|
50608
|
-
const content = await
|
|
50785
|
+
const content = await readFile4(join11(worktreePath, ".env.local"), "utf8");
|
|
50609
50786
|
return parseDotenv(content);
|
|
50610
50787
|
} catch {
|
|
50611
50788
|
return {};
|
|
@@ -50636,7 +50813,7 @@ async function ensureWorktreeStorageDirs(gitDir) {
|
|
|
50636
50813
|
async function readWorktreeMeta(gitDir) {
|
|
50637
50814
|
const { metaPath } = getWorktreeStoragePaths(gitDir);
|
|
50638
50815
|
try {
|
|
50639
|
-
const raw2 = JSON.parse(await
|
|
50816
|
+
const raw2 = JSON.parse(await readFile4(metaPath, "utf8"));
|
|
50640
50817
|
return normalizeWorktreeMeta(raw2);
|
|
50641
50818
|
} catch {
|
|
50642
50819
|
return null;
|
|
@@ -50644,7 +50821,7 @@ async function readWorktreeMeta(gitDir) {
|
|
|
50644
50821
|
}
|
|
50645
50822
|
async function writeWorktreeMeta(gitDir, meta3) {
|
|
50646
50823
|
const { metaPath } = await ensureWorktreeStorageDirs(gitDir);
|
|
50647
|
-
await
|
|
50824
|
+
await writeFile3(metaPath, `${JSON.stringify(meta3, null, 2)}
|
|
50648
50825
|
`);
|
|
50649
50826
|
}
|
|
50650
50827
|
function isArchivedWorktreeEntry(raw2) {
|
|
@@ -50662,7 +50839,7 @@ function isWorktreeArchiveState(raw2) {
|
|
|
50662
50839
|
async function readWorktreeArchiveState(gitDir) {
|
|
50663
50840
|
const archivePath = getProjectArchiveStatePath(gitDir);
|
|
50664
50841
|
try {
|
|
50665
|
-
const raw2 = JSON.parse(await
|
|
50842
|
+
const raw2 = JSON.parse(await readFile4(archivePath, "utf8"));
|
|
50666
50843
|
return isWorktreeArchiveState(raw2) ? {
|
|
50667
50844
|
schemaVersion: raw2.schemaVersion,
|
|
50668
50845
|
entries: raw2.entries.map((entry) => ({ ...entry }))
|
|
@@ -50674,13 +50851,13 @@ async function readWorktreeArchiveState(gitDir) {
|
|
|
50674
50851
|
async function writeWorktreeArchiveState(gitDir, state) {
|
|
50675
50852
|
const archivePath = getProjectArchiveStatePath(gitDir);
|
|
50676
50853
|
await ensureWorktreeStorageDirs(gitDir);
|
|
50677
|
-
await
|
|
50854
|
+
await writeFile3(archivePath, `${JSON.stringify(state, null, 2)}
|
|
50678
50855
|
`);
|
|
50679
50856
|
}
|
|
50680
50857
|
async function writeOpenSessionsState(gitDir, state) {
|
|
50681
50858
|
const statePath = getProjectOpenSessionsStatePath(gitDir);
|
|
50682
50859
|
await ensureWorktreeStorageDirs(gitDir);
|
|
50683
|
-
await
|
|
50860
|
+
await writeFile3(statePath, `${JSON.stringify(state, null, 2)}
|
|
50684
50861
|
`);
|
|
50685
50862
|
}
|
|
50686
50863
|
function buildRuntimeEnvMap(meta3, extraEnv = {}, dotenvValues = {}) {
|
|
@@ -50711,11 +50888,11 @@ function renderEnvFile(env2) {
|
|
|
50711
50888
|
}
|
|
50712
50889
|
async function writeRuntimeEnv(gitDir, env2) {
|
|
50713
50890
|
const { runtimeEnvPath } = await ensureWorktreeStorageDirs(gitDir);
|
|
50714
|
-
await
|
|
50891
|
+
await writeFile3(runtimeEnvPath, renderEnvFile(env2));
|
|
50715
50892
|
}
|
|
50716
50893
|
async function writeControlEnv(gitDir, env2) {
|
|
50717
50894
|
const { controlEnvPath } = await ensureWorktreeStorageDirs(gitDir);
|
|
50718
|
-
await
|
|
50895
|
+
await writeFile3(controlEnvPath, renderEnvFile(env2));
|
|
50719
50896
|
}
|
|
50720
50897
|
function isRecord5(raw2) {
|
|
50721
50898
|
return typeof raw2 === "object" && raw2 !== null && !Array.isArray(raw2);
|
|
@@ -50800,7 +50977,7 @@ function isPrEntry(raw2) {
|
|
|
50800
50977
|
async function readWorktreePrs(gitDir) {
|
|
50801
50978
|
const { prsPath } = getWorktreeStoragePaths(gitDir);
|
|
50802
50979
|
try {
|
|
50803
|
-
const raw2 = JSON.parse(await
|
|
50980
|
+
const raw2 = JSON.parse(await readFile4(prsPath, "utf8"));
|
|
50804
50981
|
if (!Array.isArray(raw2) || !raw2.every((entry) => isPrEntry(entry))) return [];
|
|
50805
50982
|
return raw2.map((entry) => ({ ...entry, isDraft: entry.isDraft ?? false }));
|
|
50806
50983
|
} catch {
|
|
@@ -50809,12 +50986,12 @@ async function readWorktreePrs(gitDir) {
|
|
|
50809
50986
|
}
|
|
50810
50987
|
async function writeWorktreePrs(gitDir, prs) {
|
|
50811
50988
|
const { prsPath } = await ensureWorktreeStorageDirs(gitDir);
|
|
50812
|
-
await
|
|
50989
|
+
await writeFile3(prsPath, `${JSON.stringify(prs, null, 2)}
|
|
50813
50990
|
`);
|
|
50814
50991
|
}
|
|
50815
50992
|
|
|
50816
50993
|
// ../host/src/modules/taskflow/services/archive-service.ts
|
|
50817
|
-
import { resolve as
|
|
50994
|
+
import { resolve as resolve8 } from "node:path";
|
|
50818
50995
|
function createArchiveState(entries) {
|
|
50819
50996
|
return {
|
|
50820
50997
|
schemaVersion: WORKTREE_ARCHIVE_STATE_VERSION,
|
|
@@ -50822,7 +50999,7 @@ function createArchiveState(entries) {
|
|
|
50822
50999
|
};
|
|
50823
51000
|
}
|
|
50824
51001
|
function normalizeArchivePath(path) {
|
|
50825
|
-
return
|
|
51002
|
+
return resolve8(path);
|
|
50826
51003
|
}
|
|
50827
51004
|
function buildArchivedWorktreePathSet(state) {
|
|
50828
51005
|
return new Set(state.entries.map((entry) => normalizeArchivePath(entry.path)));
|
|
@@ -50896,8 +51073,8 @@ var ArchiveStateService = class {
|
|
|
50896
51073
|
const previous = this.mutationQueue;
|
|
50897
51074
|
let release = () => {
|
|
50898
51075
|
};
|
|
50899
|
-
this.mutationQueue = new Promise((
|
|
50900
|
-
release =
|
|
51076
|
+
this.mutationQueue = new Promise((resolve22) => {
|
|
51077
|
+
release = resolve22;
|
|
50901
51078
|
});
|
|
50902
51079
|
await previous.catch(() => {
|
|
50903
51080
|
});
|
|
@@ -51075,8 +51252,8 @@ var AutoNameService = class {
|
|
|
51075
51252
|
|
|
51076
51253
|
// ../host/src/modules/taskflow/services/lifecycle-service.ts
|
|
51077
51254
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
51078
|
-
import { mkdir as mkdir4, readFile as
|
|
51079
|
-
import { dirname as dirname10, relative as
|
|
51255
|
+
import { mkdir as mkdir4, readFile as readFile6, writeFile as writeFile5 } from "node:fs/promises";
|
|
51256
|
+
import { dirname as dirname10, relative as relative3, resolve as resolve11 } from "node:path";
|
|
51080
51257
|
|
|
51081
51258
|
// ../host/src/modules/taskflow/adapters/agent-capabilities.ts
|
|
51082
51259
|
var CAPABILITY_TIMEOUT_MS = 15e3;
|
|
@@ -51121,8 +51298,8 @@ ${stderr}`;
|
|
|
51121
51298
|
};
|
|
51122
51299
|
|
|
51123
51300
|
// ../host/src/modules/taskflow/adapters/agent-runtime.ts
|
|
51124
|
-
import { chmod, mkdir as mkdir3, readFile as
|
|
51125
|
-
import { dirname as dirname8, join as
|
|
51301
|
+
import { chmod, mkdir as mkdir3, readFile as readFile5, writeFile as writeFile4 } from "node:fs/promises";
|
|
51302
|
+
import { dirname as dirname8, join as join12, resolve as resolve9 } from "node:path";
|
|
51126
51303
|
var GENERATED_AGENT_FILES_EXCLUDES = [".claude/settings.local.json", ".codex/hooks.json"];
|
|
51127
51304
|
function shellQuote(value) {
|
|
51128
51305
|
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
@@ -51132,7 +51309,7 @@ function isRecord6(value) {
|
|
|
51132
51309
|
}
|
|
51133
51310
|
async function readJsonRecord(path) {
|
|
51134
51311
|
try {
|
|
51135
|
-
const parsed = JSON.parse(await
|
|
51312
|
+
const parsed = JSON.parse(await readFile5(path, "utf8"));
|
|
51136
51313
|
return isRecord6(parsed) ? parsed : {};
|
|
51137
51314
|
} catch {
|
|
51138
51315
|
return {};
|
|
@@ -51548,7 +51725,7 @@ async function mergeClaudeSettings(settingsPath, hookSettings) {
|
|
|
51548
51725
|
const existingHooks = existing.hooks;
|
|
51549
51726
|
const mergedHooks = existingHooks && typeof existingHooks === "object" && !Array.isArray(existingHooks) ? { ...existingHooks, ...hookSettings } : hookSettings;
|
|
51550
51727
|
const merged = { ...existing, hooks: mergedHooks };
|
|
51551
|
-
await
|
|
51728
|
+
await writeFile4(settingsPath, `${JSON.stringify(merged, null, 2)}
|
|
51552
51729
|
`);
|
|
51553
51730
|
}
|
|
51554
51731
|
function commandStartsWithAgentCtl(command, agentCtlPath) {
|
|
@@ -51571,24 +51748,24 @@ async function mergeCodexHooksFile(hooksPath, hookSettings, agentCtlPath) {
|
|
|
51571
51748
|
const preservedGroups = Array.isArray(eventGroups) ? eventGroups.filter((group) => !isTaskflowHookGroup(group, agentCtlPath)) : [];
|
|
51572
51749
|
mergedHooks[eventName] = [...preservedGroups, ...groups];
|
|
51573
51750
|
}
|
|
51574
|
-
await
|
|
51751
|
+
await writeFile4(hooksPath, `${JSON.stringify({ ...existing, hooks: mergedHooks }, null, 2)}
|
|
51575
51752
|
`);
|
|
51576
51753
|
}
|
|
51577
51754
|
async function resolveGitCommonDir(gitDir) {
|
|
51578
51755
|
try {
|
|
51579
|
-
const commonDir = (await
|
|
51756
|
+
const commonDir = (await readFile5(join12(gitDir, "commondir"), "utf8")).trim();
|
|
51580
51757
|
if (!commonDir) return gitDir;
|
|
51581
|
-
return commonDir.startsWith("/") ? commonDir :
|
|
51758
|
+
return commonDir.startsWith("/") ? commonDir : resolve9(gitDir, commonDir);
|
|
51582
51759
|
} catch {
|
|
51583
51760
|
return gitDir;
|
|
51584
51761
|
}
|
|
51585
51762
|
}
|
|
51586
51763
|
async function ensureGeneratedAgentFilesIgnored(gitDir) {
|
|
51587
51764
|
const commonDir = await resolveGitCommonDir(gitDir);
|
|
51588
|
-
const excludePath =
|
|
51765
|
+
const excludePath = join12(commonDir, "info", "exclude");
|
|
51589
51766
|
let existing = "";
|
|
51590
51767
|
try {
|
|
51591
|
-
existing = await
|
|
51768
|
+
existing = await readFile5(excludePath, "utf8");
|
|
51592
51769
|
} catch {
|
|
51593
51770
|
existing = "";
|
|
51594
51771
|
}
|
|
@@ -51597,19 +51774,19 @@ async function ensureGeneratedAgentFilesIgnored(gitDir) {
|
|
|
51597
51774
|
if (missing.length === 0) return;
|
|
51598
51775
|
await mkdir3(dirname8(excludePath), { recursive: true });
|
|
51599
51776
|
const separator = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
|
|
51600
|
-
await
|
|
51777
|
+
await writeFile4(excludePath, `${existing}${separator}${missing.join("\n")}
|
|
51601
51778
|
`);
|
|
51602
51779
|
}
|
|
51603
51780
|
async function ensureAgentRuntimeArtifacts(input2) {
|
|
51604
51781
|
const storagePaths = getWorktreeStoragePaths(input2.gitDir);
|
|
51605
51782
|
const artifacts = {
|
|
51606
|
-
agentCtlPath:
|
|
51607
|
-
claudeSettingsPath:
|
|
51608
|
-
codexHooksPath:
|
|
51783
|
+
agentCtlPath: join12(storagePaths.taskflowDir, RUNTIME_IDENTITY.agentControlBinary),
|
|
51784
|
+
claudeSettingsPath: join12(input2.worktreePath, ".claude", "settings.local.json"),
|
|
51785
|
+
codexHooksPath: join12(input2.worktreePath, ".codex", "hooks.json")
|
|
51609
51786
|
};
|
|
51610
51787
|
await mkdir3(dirname8(artifacts.claudeSettingsPath), { recursive: true });
|
|
51611
51788
|
await mkdir3(dirname8(artifacts.codexHooksPath), { recursive: true });
|
|
51612
|
-
await
|
|
51789
|
+
await writeFile4(artifacts.agentCtlPath, buildAgentCtlScript());
|
|
51613
51790
|
await chmod(artifacts.agentCtlPath, 493);
|
|
51614
51791
|
const hookSettings = buildClaudeHookSettings(artifacts);
|
|
51615
51792
|
const hooks = hookSettings.hooks;
|
|
@@ -51734,7 +51911,7 @@ function listAgentDetails(config2) {
|
|
|
51734
51911
|
}
|
|
51735
51912
|
|
|
51736
51913
|
// ../host/src/modules/taskflow/services/agent-service.ts
|
|
51737
|
-
import { dirname as dirname9, join as
|
|
51914
|
+
import { dirname as dirname9, join as join13 } from "node:path";
|
|
51738
51915
|
var DOCKER_PATH_FALLBACK = "/root/.local/bin:/usr/local/bin:/root/.bun/bin:/root/.cargo/bin";
|
|
51739
51916
|
var CUSTOM_AGENT_TEMPLATE_VARS = {
|
|
51740
51917
|
PROMPT: ENV_NAMES.agentPrompt,
|
|
@@ -51755,7 +51932,7 @@ function buildDockerRuntimeBootstrap(runtimeEnvPath) {
|
|
|
51755
51932
|
}
|
|
51756
51933
|
function buildCodexNotifyFlag(runtimeEnvPath) {
|
|
51757
51934
|
if (!runtimeEnvPath) return "";
|
|
51758
|
-
const agentCtlPath =
|
|
51935
|
+
const agentCtlPath = join13(dirname9(runtimeEnvPath), RUNTIME_IDENTITY.agentControlBinary);
|
|
51759
51936
|
return ` -c ${quoteShell3(`notify=${JSON.stringify([agentCtlPath, "codex-notify"])}`)}`;
|
|
51760
51937
|
}
|
|
51761
51938
|
function buildBuiltInAgentInvocation(input2) {
|
|
@@ -51881,7 +52058,7 @@ function buildDockerAgentPaneCommand(input2) {
|
|
|
51881
52058
|
}
|
|
51882
52059
|
|
|
51883
52060
|
// ../host/src/modules/taskflow/services/session-service.ts
|
|
51884
|
-
import { resolve as
|
|
52061
|
+
import { resolve as resolve10 } from "node:path";
|
|
51885
52062
|
function quoteShell4(value) {
|
|
51886
52063
|
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
51887
52064
|
}
|
|
@@ -51895,7 +52072,7 @@ function buildCommandPaneStartupCommand(template, ctx) {
|
|
|
51895
52072
|
if (!template.workingDir) {
|
|
51896
52073
|
return template.command;
|
|
51897
52074
|
}
|
|
51898
|
-
const workingDir =
|
|
52075
|
+
const workingDir = resolve10(resolvePaneCwd(template, ctx), template.workingDir);
|
|
51899
52076
|
return `cd -- ${quoteShell4(workingDir)} && ${template.command}`;
|
|
51900
52077
|
}
|
|
51901
52078
|
function resolvePaneStartupCommand(template, ctx) {
|
|
@@ -52196,7 +52373,7 @@ function trimTrailingSlashes(value) {
|
|
|
52196
52373
|
return value.replace(/\/+$/, "");
|
|
52197
52374
|
}
|
|
52198
52375
|
function isPathWithin(parent, child) {
|
|
52199
|
-
const path =
|
|
52376
|
+
const path = relative3(parent, child);
|
|
52200
52377
|
return path !== "" && !path.startsWith("..") && !path.includes(`..${process.platform === "win32" ? "\\" : "/"}`);
|
|
52201
52378
|
}
|
|
52202
52379
|
function normalizeWorktreeLabel(label) {
|
|
@@ -52664,9 +52841,23 @@ var LifecycleService = class {
|
|
|
52664
52841
|
throw this.wrapOperationError(error61);
|
|
52665
52842
|
}
|
|
52666
52843
|
}
|
|
52667
|
-
|
|
52844
|
+
/**
|
|
52845
|
+
* Removing a worktree deletes its branch with `--force`, so anything living
|
|
52846
|
+
* only there is gone. Uncommitted changes and unpushed commits therefore
|
|
52847
|
+
* refuse the removal unless the caller says to discard them.
|
|
52848
|
+
*/
|
|
52849
|
+
async removeWorktree(branch, options = {}) {
|
|
52668
52850
|
try {
|
|
52669
52851
|
const resolved2 = await this.resolveExistingWorktree(branch);
|
|
52852
|
+
if (!options.force) {
|
|
52853
|
+
const unsaved = this.describeUnsavedWork(resolved2.entry);
|
|
52854
|
+
if (unsaved) {
|
|
52855
|
+
throw new LifecycleError(
|
|
52856
|
+
`Worktree has ${unsaved}: ${branch}. Commit or push them, or remove with --force to discard them.`,
|
|
52857
|
+
409
|
|
52858
|
+
);
|
|
52859
|
+
}
|
|
52860
|
+
}
|
|
52670
52861
|
await this.removeResolvedWorktree(resolved2);
|
|
52671
52862
|
} catch (error61) {
|
|
52672
52863
|
throw this.wrapOperationError(error61);
|
|
@@ -52677,15 +52868,21 @@ var LifecycleService = class {
|
|
|
52677
52868
|
const resolvedWorktrees = await this.resolveAllWorktrees();
|
|
52678
52869
|
const sessionName = buildProjectSessionName(this.deps.projectRoot);
|
|
52679
52870
|
const removedBranches = [];
|
|
52871
|
+
const keptBranches = [];
|
|
52680
52872
|
for (const resolved2 of resolvedWorktrees) {
|
|
52681
52873
|
const branch = resolved2.entry.branch ?? resolved2.entry.path;
|
|
52682
52874
|
if (await this.deps.sessions.hasWindow(sessionName, buildWorktreeWindowName(branch))) {
|
|
52683
52875
|
continue;
|
|
52684
52876
|
}
|
|
52877
|
+
const unsaved = this.describeUnsavedWork(resolved2.entry);
|
|
52878
|
+
if (unsaved) {
|
|
52879
|
+
keptBranches.push({ branch, reason: unsaved });
|
|
52880
|
+
continue;
|
|
52881
|
+
}
|
|
52685
52882
|
await this.removeResolvedWorktree(resolved2);
|
|
52686
52883
|
removedBranches.push(branch);
|
|
52687
52884
|
}
|
|
52688
|
-
return { removedBranches };
|
|
52885
|
+
return { removedBranches, keptBranches };
|
|
52689
52886
|
} catch (error61) {
|
|
52690
52887
|
throw this.wrapOperationError(error61);
|
|
52691
52888
|
}
|
|
@@ -52871,7 +53068,7 @@ var LifecycleService = class {
|
|
|
52871
53068
|
return allocateServicePorts(metas, this.deps.config.services);
|
|
52872
53069
|
}
|
|
52873
53070
|
resolveWorktreePath(branch) {
|
|
52874
|
-
return
|
|
53071
|
+
return resolve11(this.deps.projectRoot, this.deps.config.workspace.worktreeRoot, branch);
|
|
52875
53072
|
}
|
|
52876
53073
|
/**
|
|
52877
53074
|
* A worktree root below the repository is intentionally kept out of the
|
|
@@ -52880,36 +53077,36 @@ var LifecycleService = class {
|
|
|
52880
53077
|
* tracked project files or leaking the choice to other contributors.
|
|
52881
53078
|
*/
|
|
52882
53079
|
async excludeInternalWorktreeRoot(worktreePath) {
|
|
52883
|
-
const projectRoot2 =
|
|
52884
|
-
const worktreeRoot =
|
|
53080
|
+
const projectRoot2 = resolve11(this.deps.projectRoot);
|
|
53081
|
+
const worktreeRoot = resolve11(projectRoot2, this.deps.config.workspace.worktreeRoot);
|
|
52885
53082
|
if (!isPathWithin(projectRoot2, worktreeRoot) || !isPathWithin(worktreeRoot, worktreePath)) return;
|
|
52886
|
-
const relativeRoot =
|
|
53083
|
+
const relativeRoot = relative3(projectRoot2, worktreeRoot).split("\\").join("/");
|
|
52887
53084
|
const rule = `/${relativeRoot}/`;
|
|
52888
53085
|
const gitDir = this.deps.git.resolveWorktreeGitDir(projectRoot2);
|
|
52889
|
-
const excludePath =
|
|
53086
|
+
const excludePath = resolve11(gitDir, "info", "exclude");
|
|
52890
53087
|
await mkdir4(dirname10(excludePath), { recursive: true });
|
|
52891
53088
|
let existing = "";
|
|
52892
53089
|
try {
|
|
52893
|
-
existing = await
|
|
53090
|
+
existing = await readFile6(excludePath, "utf8");
|
|
52894
53091
|
} catch {
|
|
52895
53092
|
}
|
|
52896
53093
|
if (existing.split(/\r?\n/).some((line) => line.trim() === rule)) return;
|
|
52897
|
-
await
|
|
53094
|
+
await writeFile5(excludePath, `${existing}${existing && !existing.endsWith("\n") ? "\n" : ""}${rule}
|
|
52898
53095
|
`);
|
|
52899
53096
|
}
|
|
52900
53097
|
listLocalBranches() {
|
|
52901
|
-
return this.deps.git.listLocalBranches(
|
|
53098
|
+
return this.deps.git.listLocalBranches(resolve11(this.deps.projectRoot));
|
|
52902
53099
|
}
|
|
52903
53100
|
listRemoteBranches() {
|
|
52904
|
-
return this.deps.git.listRemoteBranches(
|
|
53101
|
+
return this.deps.git.listRemoteBranches(resolve11(this.deps.projectRoot));
|
|
52905
53102
|
}
|
|
52906
53103
|
listCheckedOutBranches() {
|
|
52907
53104
|
return new Set(
|
|
52908
|
-
this.deps.git.listWorktrees(
|
|
53105
|
+
this.deps.git.listWorktrees(resolve11(this.deps.projectRoot)).filter((entry) => !entry.bare && entry.branch !== null).map((entry) => entry.branch)
|
|
52909
53106
|
);
|
|
52910
53107
|
}
|
|
52911
53108
|
listProjectWorktrees() {
|
|
52912
|
-
const projectRoot2 =
|
|
53109
|
+
const projectRoot2 = resolve11(this.deps.projectRoot);
|
|
52913
53110
|
return this.deps.git.listLiveWorktrees(projectRoot2).filter((entry) => !entry.bare && !sameFsPath(entry.path, projectRoot2));
|
|
52914
53111
|
}
|
|
52915
53112
|
async readManagedMetas() {
|
|
@@ -53182,6 +53379,14 @@ ${oneshotPrompt}` : oneshotPrompt ?? baseSystemPrompt;
|
|
|
53182
53379
|
}
|
|
53183
53380
|
return cleanupErrors.length > 0 ? cleanupErrors.join("; ") : null;
|
|
53184
53381
|
}
|
|
53382
|
+
/** What this worktree holds that exists nowhere else, or null when it is safe to delete. */
|
|
53383
|
+
describeUnsavedWork(entry) {
|
|
53384
|
+
const status = this.deps.git.readWorktreeStatus(entry.path);
|
|
53385
|
+
if (status.dirty) return "uncommitted changes";
|
|
53386
|
+
const commits = this.deps.git.countUnsavedCommits(entry.path, this.deps.config.workspace.mainBranch);
|
|
53387
|
+
if (commits > 0) return `${commits} commit${commits === 1 ? "" : "s"} that are only here`;
|
|
53388
|
+
return null;
|
|
53389
|
+
}
|
|
53185
53390
|
ensureNoUncommittedChanges(entry) {
|
|
53186
53391
|
const status = this.deps.git.readWorktreeStatus(entry.path);
|
|
53187
53392
|
if (status.dirty) {
|
|
@@ -53278,7 +53483,7 @@ ${oneshotPrompt}` : oneshotPrompt ?? baseSystemPrompt;
|
|
|
53278
53483
|
const cleanupErrors = [];
|
|
53279
53484
|
for (const branch of [...branches].reverse()) {
|
|
53280
53485
|
try {
|
|
53281
|
-
await this.removeWorktree(branch);
|
|
53486
|
+
await this.removeWorktree(branch, { force: true });
|
|
53282
53487
|
} catch (error61) {
|
|
53283
53488
|
cleanupErrors.push(`rollback failed for ${branch}: ${toErrorMessage2(error61)}`);
|
|
53284
53489
|
}
|
|
@@ -53705,7 +53910,7 @@ var ProjectRuntime = class {
|
|
|
53705
53910
|
};
|
|
53706
53911
|
|
|
53707
53912
|
// ../host/src/modules/taskflow/services/reconciliation-service.ts
|
|
53708
|
-
import { basename as
|
|
53913
|
+
import { basename as basename7, resolve as resolve12 } from "node:path";
|
|
53709
53914
|
|
|
53710
53915
|
// ../host/src/modules/taskflow/lib/async.ts
|
|
53711
53916
|
async function mapWithConcurrency(items, limit, fn) {
|
|
@@ -53751,7 +53956,7 @@ function startSerializedInterval(run, intervalMs, deps = {}) {
|
|
|
53751
53956
|
|
|
53752
53957
|
// ../host/src/modules/taskflow/services/reconciliation-service.ts
|
|
53753
53958
|
function makeUnmanagedWorktreeId(path) {
|
|
53754
|
-
return `unmanaged:${
|
|
53959
|
+
return `unmanaged:${resolve12(path)}`;
|
|
53755
53960
|
}
|
|
53756
53961
|
function isValidPort2(port) {
|
|
53757
53962
|
return port !== null && Number.isInteger(port) && port >= 1 && port <= 65535;
|
|
@@ -53786,7 +53991,7 @@ function findWindow(windows, sessionName, branch) {
|
|
|
53786
53991
|
return windows.find((window) => window.sessionName === sessionName && window.windowName === windowName) ?? null;
|
|
53787
53992
|
}
|
|
53788
53993
|
function resolveBranch(entry, metaBranch) {
|
|
53789
|
-
const fallback =
|
|
53994
|
+
const fallback = basename7(entry.path);
|
|
53790
53995
|
return entry.branch ?? metaBranch ?? (fallback.length > 0 ? fallback : "unknown");
|
|
53791
53996
|
}
|
|
53792
53997
|
var ReconciliationService = class {
|
|
@@ -53809,7 +54014,7 @@ var ReconciliationService = class {
|
|
|
53809
54014
|
if (!options.force && this.now() - this.lastReconciledAt < this.freshnessMs) {
|
|
53810
54015
|
return;
|
|
53811
54016
|
}
|
|
53812
|
-
const normalizedRepoRoot =
|
|
54017
|
+
const normalizedRepoRoot = resolve12(repoRoot);
|
|
53813
54018
|
const reconcilePromise = this.runReconcile(normalizedRepoRoot).then(() => {
|
|
53814
54019
|
this.lastReconciledAt = this.now();
|
|
53815
54020
|
});
|
|
@@ -56862,7 +57067,7 @@ function environmentRoutes(deps) {
|
|
|
56862
57067
|
}
|
|
56863
57068
|
|
|
56864
57069
|
// ../host/src/modules/taskflow/server/routes/github.ts
|
|
56865
|
-
import { resolve as
|
|
57070
|
+
import { resolve as resolve13 } from "node:path";
|
|
56866
57071
|
|
|
56867
57072
|
// ../host/src/modules/taskflow/services/auto-pull-service.ts
|
|
56868
57073
|
function pullMainBranch(deps) {
|
|
@@ -57323,7 +57528,7 @@ function githubRoutes(deps) {
|
|
|
57323
57528
|
const linkedRepo = config2.integrations.github.linkedRepos.find((lr) => lr.alias === repo);
|
|
57324
57529
|
if (!linkedRepo) return errorResponse(`Unknown linked repo: ${repo}`, 404);
|
|
57325
57530
|
if (!linkedRepo.dir) return errorResponse(`Linked repo "${repo}" has no dir configured`, 400);
|
|
57326
|
-
const resolvedDir =
|
|
57531
|
+
const resolvedDir = resolve13(projectDir, linkedRepo.dir);
|
|
57327
57532
|
const repoRoot = git2.resolveRepoRoot(resolvedDir);
|
|
57328
57533
|
if (!repoRoot) return errorResponse(`Linked repo "${repo}" dir is not a git repository: ${resolvedDir}`, 400);
|
|
57329
57534
|
projectRoot2 = repoRoot;
|
|
@@ -57369,7 +57574,7 @@ function hasHeader(headers, name) {
|
|
|
57369
57574
|
return getHeader(headers, name) !== void 0;
|
|
57370
57575
|
}
|
|
57371
57576
|
function putViaNodeHttps(url2, headers, body) {
|
|
57372
|
-
return new Promise((
|
|
57577
|
+
return new Promise((resolve22, reject2) => {
|
|
57373
57578
|
const parsed = new URL(url2);
|
|
57374
57579
|
const req = httpsRequest(
|
|
57375
57580
|
{
|
|
@@ -57386,7 +57591,7 @@ function putViaNodeHttps(url2, headers, body) {
|
|
|
57386
57591
|
const chunks = [];
|
|
57387
57592
|
res.on("data", (chunk) => chunks.push(chunk));
|
|
57388
57593
|
res.on("end", () => {
|
|
57389
|
-
|
|
57594
|
+
resolve22({
|
|
57390
57595
|
status: res.statusCode ?? 0,
|
|
57391
57596
|
body: Buffer.concat(chunks).toString("utf8")
|
|
57392
57597
|
});
|
|
@@ -58126,7 +58331,7 @@ function projectsRoutes(deps) {
|
|
|
58126
58331
|
|
|
58127
58332
|
// ../host/src/modules/taskflow/server/routes/runs.ts
|
|
58128
58333
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
58129
|
-
import { resolve as
|
|
58334
|
+
import { resolve as resolve14 } from "node:path";
|
|
58130
58335
|
import { setTimeout as delay } from "node:timers/promises";
|
|
58131
58336
|
var CONFLICT_REASONS = [
|
|
58132
58337
|
"branch_conflict",
|
|
@@ -58263,7 +58468,7 @@ async function apiCreateProjectRun(project, body) {
|
|
|
58263
58468
|
permissionMode: body.permissionMode ?? "interactive",
|
|
58264
58469
|
mcpServers: body.mcpServers ?? [],
|
|
58265
58470
|
projectRoot: projectDir,
|
|
58266
|
-
workspaceRoot:
|
|
58471
|
+
workspaceRoot: resolve14(projectDir, config2.workspace.worktreeRoot),
|
|
58267
58472
|
baseBranch: config2.workspace.mainBranch,
|
|
58268
58473
|
baseCommit: git2.currentBranch(projectDir),
|
|
58269
58474
|
agent: config2.workspace.defaultAgent,
|
|
@@ -58299,7 +58504,7 @@ async function apiCreateProjectRun(project, body) {
|
|
|
58299
58504
|
snapshot: snapshot.snapshot,
|
|
58300
58505
|
dataRoot: project.runs.dataRoot,
|
|
58301
58506
|
projectRoot: projectDir,
|
|
58302
|
-
workspaceRoot:
|
|
58507
|
+
workspaceRoot: resolve14(projectDir, config2.workspace.worktreeRoot),
|
|
58303
58508
|
baseBranch: config2.workspace.mainBranch,
|
|
58304
58509
|
baseCommit: git2.currentBranch(projectDir),
|
|
58305
58510
|
profile,
|
|
@@ -58423,9 +58628,9 @@ function runRoutes(deps) {
|
|
|
58423
58628
|
|
|
58424
58629
|
// ../host/src/modules/taskflow/server/routes/worktrees.ts
|
|
58425
58630
|
import { mkdirSync as mkdirSync4 } from "node:fs";
|
|
58426
|
-
import { writeFile as
|
|
58631
|
+
import { writeFile as writeFile6 } from "node:fs/promises";
|
|
58427
58632
|
import { tmpdir } from "node:os";
|
|
58428
|
-
import { join as
|
|
58633
|
+
import { join as join14, resolve as resolve15 } from "node:path";
|
|
58429
58634
|
|
|
58430
58635
|
// ../host/src/modules/taskflow/services/conversation-export-service.ts
|
|
58431
58636
|
var TaskflowConversationAttachmentMessageSchema = AgentsUiConversationMessageSchema.extend({
|
|
@@ -58969,14 +59174,14 @@ ${resolvedPrompt}` : conversationContext;
|
|
|
58969
59174
|
201
|
|
58970
59175
|
);
|
|
58971
59176
|
}
|
|
58972
|
-
async function apiDeleteWorktree(project, name) {
|
|
59177
|
+
async function apiDeleteWorktree(project, name, force) {
|
|
58973
59178
|
return project.withRemovingBranch(name, async () => {
|
|
58974
59179
|
log.info(`[worktree:rm] name=${name}`);
|
|
58975
59180
|
const worktree = project.runtime.projectRuntime.getWorktreeByBranch(name);
|
|
58976
59181
|
const environmentId = worktree ? environmentIdForWorkspace(project.environments.projectEnvironments(), worktree.worktreeId) : null;
|
|
58977
59182
|
const environment = environmentId ? project.environments.environmentForProject(environmentId) : null;
|
|
58978
59183
|
if (environment) await project.environments.destroyEnvironmentRecord(environment);
|
|
58979
|
-
await project.runtime.lifecycleService.removeWorktree(name);
|
|
59184
|
+
await project.runtime.lifecycleService.removeWorktree(name, { force });
|
|
58980
59185
|
log.debug(`[worktree:rm] done name=${name}`);
|
|
58981
59186
|
return jsonResponse({ ok: true });
|
|
58982
59187
|
});
|
|
@@ -59130,7 +59335,7 @@ async function apiUploadFiles(project, name, req) {
|
|
|
59130
59335
|
}
|
|
59131
59336
|
const entries = formData.getAll("files");
|
|
59132
59337
|
if (entries.length === 0) return errorResponse("No files provided", 400);
|
|
59133
|
-
const uploadDir =
|
|
59338
|
+
const uploadDir = join14(tmpdir(), RUNTIME_IDENTITY.tempUploadDir, sanitizeFilename(name));
|
|
59134
59339
|
mkdirSync4(uploadDir, { recursive: true });
|
|
59135
59340
|
const results = [];
|
|
59136
59341
|
for (const entry of entries) {
|
|
@@ -59142,11 +59347,11 @@ async function apiUploadFiles(project, name, req) {
|
|
|
59142
59347
|
return errorResponse(`File too large: ${entry.name} (max 10MB)`, 400);
|
|
59143
59348
|
}
|
|
59144
59349
|
const safeName = `${Date.now()}_${sanitizeFilename(entry.name)}`;
|
|
59145
|
-
const destPath =
|
|
59146
|
-
if (!
|
|
59350
|
+
const destPath = join14(uploadDir, safeName);
|
|
59351
|
+
if (!resolve15(destPath).startsWith(`${uploadDir}/`)) {
|
|
59147
59352
|
return errorResponse("Invalid filename", 400);
|
|
59148
59353
|
}
|
|
59149
|
-
await
|
|
59354
|
+
await writeFile6(destPath, new Uint8Array(await entry.arrayBuffer()));
|
|
59150
59355
|
results.push({ path: destPath });
|
|
59151
59356
|
}
|
|
59152
59357
|
log.info(`[upload] branch=${name} files=${results.length}`);
|
|
@@ -59163,9 +59368,9 @@ function worktreeRoutes(deps) {
|
|
|
59163
59368
|
const app = projectRouter();
|
|
59164
59369
|
projectRoute(app, deps, "fetchWorktrees", "Worktrees", (project) => apiGetWorktrees(project));
|
|
59165
59370
|
projectRoute(app, deps, "createWorktree", "Worktrees", (project, { body }) => apiCreateWorktree(project, body));
|
|
59166
|
-
projectRoute(app, deps, "removeWorktree", "Worktrees", (project, { params }) => {
|
|
59371
|
+
projectRoute(app, deps, "removeWorktree", "Worktrees", (project, { params, query: query2 }) => {
|
|
59167
59372
|
const name = worktreeName(params.name);
|
|
59168
|
-
return name instanceof Response ? name : apiDeleteWorktree(project, name);
|
|
59373
|
+
return name instanceof Response ? name : apiDeleteWorktree(project, name, query2.force === true);
|
|
59169
59374
|
});
|
|
59170
59375
|
projectRoute(app, deps, "openWorktree", "Worktrees", (project, { params, body }) => {
|
|
59171
59376
|
const name = worktreeName(params.name);
|
|
@@ -59320,7 +59525,7 @@ function createHostProjects(deps) {
|
|
|
59320
59525
|
import { spawn as spawn6 } from "node:child_process";
|
|
59321
59526
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
59322
59527
|
import { existsSync as existsSync6 } from "node:fs";
|
|
59323
|
-
import { dirname as dirname15, join as
|
|
59528
|
+
import { dirname as dirname15, join as join29, resolve as resolve21 } from "node:path";
|
|
59324
59529
|
import { fileURLToPath } from "node:url";
|
|
59325
59530
|
|
|
59326
59531
|
// ../host/src/modules/taskflow/adapters/codex-app-server.ts
|
|
@@ -59767,8 +59972,8 @@ var CodexAppServerClient = class {
|
|
|
59767
59972
|
}
|
|
59768
59973
|
const id = this.nextId;
|
|
59769
59974
|
this.nextId += 1;
|
|
59770
|
-
const result = await new Promise((
|
|
59771
|
-
this.pending.set(id, { resolve:
|
|
59975
|
+
const result = await new Promise((resolve22, reject2) => {
|
|
59976
|
+
this.pending.set(id, { resolve: resolve22, reject: reject2 });
|
|
59772
59977
|
try {
|
|
59773
59978
|
this.send({
|
|
59774
59979
|
id,
|
|
@@ -60431,7 +60636,7 @@ function createRunStore(path = defaultRunStorePath()) {
|
|
|
60431
60636
|
},
|
|
60432
60637
|
reserveWorkspace(input2) {
|
|
60433
60638
|
const strategy = input2.strategy ?? "isolated_worktree";
|
|
60434
|
-
const
|
|
60639
|
+
const access4 = input2.access ?? "exclusive_write";
|
|
60435
60640
|
const current = selectRun.get(input2.runId);
|
|
60436
60641
|
if (!current) return { ok: false, reason: "not_found" };
|
|
60437
60642
|
const run = toRunRecord(current);
|
|
@@ -60446,7 +60651,7 @@ function createRunStore(path = defaultRunStorePath()) {
|
|
|
60446
60651
|
reserveWorkspace.run({
|
|
60447
60652
|
...input2,
|
|
60448
60653
|
strategy,
|
|
60449
|
-
access:
|
|
60654
|
+
access: access4,
|
|
60450
60655
|
canonicalWorkspacePath: strategy === "isolated_worktree" ? input2.canonicalWorkspacePath : null,
|
|
60451
60656
|
branch: strategy === "isolated_worktree" ? input2.branch : null,
|
|
60452
60657
|
checkoutCanonicalPath: strategy === "isolated_worktree" ? null : input2.canonicalWorkspacePath,
|
|
@@ -60747,16 +60952,16 @@ var DEFAULTS = {
|
|
|
60747
60952
|
};
|
|
60748
60953
|
|
|
60749
60954
|
// ../host/src/modules/taskflow/workflows/runtime/journal.ts
|
|
60750
|
-
import { appendFileSync, existsSync as existsSync3, mkdirSync as mkdirSync6, readdirSync as readdirSync2, readFileSync as
|
|
60751
|
-
import { dirname as dirname12, join as
|
|
60955
|
+
import { appendFileSync, existsSync as existsSync3, mkdirSync as mkdirSync6, readdirSync as readdirSync2, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "node:fs";
|
|
60956
|
+
import { dirname as dirname12, join as join15 } from "node:path";
|
|
60752
60957
|
function dataRoot(roots = {}) {
|
|
60753
60958
|
return roots.dataRoot ?? globalPaths().root;
|
|
60754
60959
|
}
|
|
60755
60960
|
function runDir(runId, roots = {}) {
|
|
60756
|
-
return
|
|
60961
|
+
return join15(dataRoot(roots), "runs", runId);
|
|
60757
60962
|
}
|
|
60758
60963
|
function journalPath(runId, roots = {}) {
|
|
60759
|
-
return
|
|
60964
|
+
return join15(runDir(runId, roots), "journal.jsonl");
|
|
60760
60965
|
}
|
|
60761
60966
|
function ensureRunDir(runId, roots = {}) {
|
|
60762
60967
|
const dir = runDir(runId, roots);
|
|
@@ -60764,9 +60969,9 @@ function ensureRunDir(runId, roots = {}) {
|
|
|
60764
60969
|
return dir;
|
|
60765
60970
|
}
|
|
60766
60971
|
function listRunIds(roots = {}) {
|
|
60767
|
-
const dir =
|
|
60972
|
+
const dir = join15(dataRoot(roots), "runs");
|
|
60768
60973
|
if (!existsSync3(dir)) return [];
|
|
60769
|
-
return readdirSync2(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync3(
|
|
60974
|
+
return readdirSync2(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync3(join15(dir, e.name, "journal.jsonl"))).map((e) => e.name).sort().reverse();
|
|
60770
60975
|
}
|
|
60771
60976
|
var JournalNotFoundError = class extends Error {
|
|
60772
60977
|
runId;
|
|
@@ -60803,7 +61008,7 @@ var Journal = class {
|
|
|
60803
61008
|
const path = journalPath(runId, roots);
|
|
60804
61009
|
const out = { results: /* @__PURE__ */ new Map(), indexByKey: /* @__PURE__ */ new Map() };
|
|
60805
61010
|
if (!existsSync3(path)) return out;
|
|
60806
|
-
const text =
|
|
61011
|
+
const text = readFileSync5(path, "utf8");
|
|
60807
61012
|
for (const line of text.split("\n")) {
|
|
60808
61013
|
const trimmed = line.trim();
|
|
60809
61014
|
if (!trimmed) continue;
|
|
@@ -60846,7 +61051,7 @@ function canonicalArgs(value) {
|
|
|
60846
61051
|
}
|
|
60847
61052
|
function writeResult(runId, value, roots = {}) {
|
|
60848
61053
|
const dir = ensureRunDir(runId, roots);
|
|
60849
|
-
writeFileSync3(
|
|
61054
|
+
writeFileSync3(join15(dir, "result.json"), JSON.stringify(value, null, 2), "utf8");
|
|
60850
61055
|
}
|
|
60851
61056
|
|
|
60852
61057
|
// ../host/src/modules/taskflow/workflows/runtime/keys.ts
|
|
@@ -61179,7 +61384,7 @@ async function runInSandbox(opts) {
|
|
|
61179
61384
|
}
|
|
61180
61385
|
function raceLifecycle(work, signal, execTimeoutMs) {
|
|
61181
61386
|
if (!signal && !execTimeoutMs) return work;
|
|
61182
|
-
return new Promise((
|
|
61387
|
+
return new Promise((resolve22, reject2) => {
|
|
61183
61388
|
let settled = false;
|
|
61184
61389
|
let timer;
|
|
61185
61390
|
const cleanup = () => {
|
|
@@ -61210,7 +61415,7 @@ function raceLifecycle(work, signal, execTimeoutMs) {
|
|
|
61210
61415
|
timer.unref?.();
|
|
61211
61416
|
}
|
|
61212
61417
|
work.then(
|
|
61213
|
-
(v) => finish(() =>
|
|
61418
|
+
(v) => finish(() => resolve22(v)),
|
|
61214
61419
|
(e) => finish(() => reject2(e))
|
|
61215
61420
|
);
|
|
61216
61421
|
});
|
|
@@ -61218,13 +61423,13 @@ function raceLifecycle(work, signal, execTimeoutMs) {
|
|
|
61218
61423
|
|
|
61219
61424
|
// ../host/src/modules/taskflow/workflows/runtime/run.ts
|
|
61220
61425
|
import { createHash as createHash8, randomBytes as randomBytes2 } from "node:crypto";
|
|
61221
|
-
import { readFileSync as
|
|
61222
|
-
import { join as
|
|
61426
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "node:fs";
|
|
61427
|
+
import { join as join22, resolve as resolve17 } from "node:path";
|
|
61223
61428
|
|
|
61224
61429
|
// ../host/src/modules/taskflow/workflows/worker/claude.ts
|
|
61225
61430
|
import { readlinkSync, realpathSync as realpathSync2 } from "node:fs";
|
|
61226
61431
|
import { homedir as homedir3 } from "node:os";
|
|
61227
|
-
import { basename as
|
|
61432
|
+
import { basename as basename8, dirname as dirname13, isAbsolute as isAbsolute3, join as join16, relative as relative4, resolve as resolve16 } from "node:path";
|
|
61228
61433
|
|
|
61229
61434
|
// ../host/src/modules/taskflow/workflows/worker/index.ts
|
|
61230
61435
|
var AgentError = class extends Error {
|
|
@@ -61616,10 +61821,10 @@ function checkTool(sandbox, cwd, toolName2, input2) {
|
|
|
61616
61821
|
return void 0;
|
|
61617
61822
|
}
|
|
61618
61823
|
function withinCwd(cwd, candidate) {
|
|
61619
|
-
const base = realpathUpward(
|
|
61620
|
-
const target = realpathUpward(isAbsolute3(candidate) ?
|
|
61824
|
+
const base = realpathUpward(resolve16(cwd));
|
|
61825
|
+
const target = realpathUpward(isAbsolute3(candidate) ? resolve16(candidate) : resolve16(resolve16(cwd), candidate));
|
|
61621
61826
|
if (target === base) return true;
|
|
61622
|
-
const rel =
|
|
61827
|
+
const rel = relative4(base, target);
|
|
61623
61828
|
return rel !== "" && !rel.startsWith("..") && !isAbsolute3(rel);
|
|
61624
61829
|
}
|
|
61625
61830
|
function realpathUpward(p) {
|
|
@@ -61628,18 +61833,18 @@ function realpathUpward(p) {
|
|
|
61628
61833
|
for (let hops = 0; hops < 40; hops++) {
|
|
61629
61834
|
try {
|
|
61630
61835
|
const real = realpathSync2(existing);
|
|
61631
|
-
return suffix ?
|
|
61836
|
+
return suffix ? join16(real, suffix) : real;
|
|
61632
61837
|
} catch {
|
|
61633
61838
|
}
|
|
61634
61839
|
try {
|
|
61635
61840
|
const link = readlinkSync(existing);
|
|
61636
|
-
existing = isAbsolute3(link) ?
|
|
61841
|
+
existing = isAbsolute3(link) ? resolve16(link) : resolve16(dirname13(existing), link);
|
|
61637
61842
|
continue;
|
|
61638
61843
|
} catch {
|
|
61639
61844
|
}
|
|
61640
61845
|
const parent = dirname13(existing);
|
|
61641
61846
|
if (parent === existing) return p;
|
|
61642
|
-
suffix = suffix ?
|
|
61847
|
+
suffix = suffix ? join16(basename8(existing), suffix) : basename8(existing);
|
|
61643
61848
|
existing = parent;
|
|
61644
61849
|
}
|
|
61645
61850
|
return p;
|
|
@@ -61749,7 +61954,7 @@ function unquote(s) {
|
|
|
61749
61954
|
}
|
|
61750
61955
|
function expandHome(p) {
|
|
61751
61956
|
if (p === "~") return homedir3();
|
|
61752
|
-
if (p.startsWith("~/")) return
|
|
61957
|
+
if (p.startsWith("~/")) return join16(homedir3(), p.slice(2));
|
|
61753
61958
|
return p;
|
|
61754
61959
|
}
|
|
61755
61960
|
function usageFromResult(last) {
|
|
@@ -61770,8 +61975,8 @@ function numOr(v) {
|
|
|
61770
61975
|
}
|
|
61771
61976
|
|
|
61772
61977
|
// ../host/src/modules/taskflow/workflows/worker/codex.ts
|
|
61773
|
-
import { copyFile, writeFile as
|
|
61774
|
-
import { basename as
|
|
61978
|
+
import { copyFile, writeFile as writeFile7 } from "node:fs/promises";
|
|
61979
|
+
import { basename as basename9, join as join17 } from "node:path";
|
|
61775
61980
|
|
|
61776
61981
|
// ../host/src/modules/taskflow/workflows/worker/codex-protocol.ts
|
|
61777
61982
|
function isObject2(value) {
|
|
@@ -62024,13 +62229,13 @@ var JsonRpcStdioClient = class {
|
|
|
62024
62229
|
* error member, and rejects with a timeout if no response arrives in time.
|
|
62025
62230
|
*/
|
|
62026
62231
|
request(method, params) {
|
|
62027
|
-
return new Promise((
|
|
62232
|
+
return new Promise((resolve22, reject2) => {
|
|
62028
62233
|
if (this.dead || !this.child) {
|
|
62029
62234
|
reject2(new StdioTransportError("not_writable", "child is not running"));
|
|
62030
62235
|
return;
|
|
62031
62236
|
}
|
|
62032
62237
|
const id = this.allocId();
|
|
62033
|
-
const entry = { resolve:
|
|
62238
|
+
const entry = { resolve: resolve22, reject: reject2 };
|
|
62034
62239
|
this.pending.set(id, entry);
|
|
62035
62240
|
if (this.requestTimeoutMs > 0) {
|
|
62036
62241
|
entry.timer = setTimeout(() => {
|
|
@@ -62243,12 +62448,12 @@ var CodexWorker = class {
|
|
|
62243
62448
|
runTurn(ctx, sandbox, cwd, turnParams, forwardProgress, seedUsage) {
|
|
62244
62449
|
const { threadId } = turnParams;
|
|
62245
62450
|
let onAbort;
|
|
62246
|
-
const p = new Promise((
|
|
62451
|
+
const p = new Promise((resolve22, reject2) => {
|
|
62247
62452
|
const state = {
|
|
62248
62453
|
threadId,
|
|
62249
62454
|
deltaText: "",
|
|
62250
62455
|
usage: seedUsage ?? emptyUsage(),
|
|
62251
|
-
resolve:
|
|
62456
|
+
resolve: resolve22,
|
|
62252
62457
|
reject: reject2,
|
|
62253
62458
|
settled: false,
|
|
62254
62459
|
ctx,
|
|
@@ -62519,14 +62724,14 @@ var CodexWorker = class {
|
|
|
62519
62724
|
handleImageGeneration(state, item) {
|
|
62520
62725
|
if (state.sandbox === "read-only") return;
|
|
62521
62726
|
const rawId = typeof item.id === "string" && item.id.length > 0 ? item.id : "image";
|
|
62522
|
-
const id =
|
|
62727
|
+
const id = basename9(rawId) || "image";
|
|
62523
62728
|
const savedPath = typeof item.savedPath === "string" ? item.savedPath : void 0;
|
|
62524
62729
|
const b64 = typeof item.result === "string" ? item.result : void 0;
|
|
62525
|
-
const dest =
|
|
62730
|
+
const dest = join17(state.cwd, `${id}.png`);
|
|
62526
62731
|
const write2 = (async () => {
|
|
62527
62732
|
try {
|
|
62528
62733
|
if (savedPath) await copyFile(savedPath, dest);
|
|
62529
|
-
else if (b64) await
|
|
62734
|
+
else if (b64) await writeFile7(dest, Buffer.from(b64, "base64"));
|
|
62530
62735
|
else return;
|
|
62531
62736
|
if (state.forwardProgress)
|
|
62532
62737
|
state.ctx.onProgress({ kind: "tool-result", id, name: "image_generation", output: `saved image \u2192 ${dest}` });
|
|
@@ -62832,7 +63037,7 @@ var DEFAULT_STALL_TIMEOUT_MS = 30 * 6e4;
|
|
|
62832
63037
|
var DEFAULT_KILL_GRACE_MS = 5e3;
|
|
62833
63038
|
var DEFAULT_STDERR_LIMIT2 = 16 * 1024;
|
|
62834
63039
|
function runJsonlSubprocess(o) {
|
|
62835
|
-
return new Promise((
|
|
63040
|
+
return new Promise((resolve22, reject2) => {
|
|
62836
63041
|
if (o.signal.aborted) {
|
|
62837
63042
|
reject2(new AgentInterrupted());
|
|
62838
63043
|
return;
|
|
@@ -62944,7 +63149,7 @@ function runJsonlSubprocess(o) {
|
|
|
62944
63149
|
stdoutBuf = "";
|
|
62945
63150
|
deliver(rest);
|
|
62946
63151
|
}
|
|
62947
|
-
settle(() =>
|
|
63152
|
+
settle(() => resolve22({ code, signal: signal ?? null, stderrTail: stderrBuf.trim() }));
|
|
62948
63153
|
});
|
|
62949
63154
|
o.signal.addEventListener("abort", onAbort, { once: true });
|
|
62950
63155
|
touch();
|
|
@@ -63290,7 +63495,7 @@ function numOf(v) {
|
|
|
63290
63495
|
// ../host/src/modules/taskflow/workflows/worker/pi.ts
|
|
63291
63496
|
import { mkdtempSync, rmSync as rmSync2 } from "node:fs";
|
|
63292
63497
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
63293
|
-
import { join as
|
|
63498
|
+
import { join as join18 } from "node:path";
|
|
63294
63499
|
var PROVIDER3 = "pi";
|
|
63295
63500
|
var PI_MIN_VERSION = "0.79.1";
|
|
63296
63501
|
var EFFORT_TO_THINKING = {
|
|
@@ -63405,7 +63610,7 @@ var PiWorker = class {
|
|
|
63405
63610
|
return this.versionCheck;
|
|
63406
63611
|
}
|
|
63407
63612
|
async checkVersion() {
|
|
63408
|
-
const scratch = mkdtempSync(
|
|
63613
|
+
const scratch = mkdtempSync(join18(tmpdir2(), `${APP_SLUG}-pi-version-`));
|
|
63409
63614
|
let out;
|
|
63410
63615
|
try {
|
|
63411
63616
|
out = await captureStdout({
|
|
@@ -63638,7 +63843,7 @@ var DefaultWorkerFactory = class {
|
|
|
63638
63843
|
};
|
|
63639
63844
|
|
|
63640
63845
|
// ../host/src/modules/taskflow/workflows/runtime/event-sink.ts
|
|
63641
|
-
import { join as
|
|
63846
|
+
import { join as join19 } from "node:path";
|
|
63642
63847
|
|
|
63643
63848
|
// ../host/src/modules/taskflow/workflows/runtime/jsonl-writer.ts
|
|
63644
63849
|
import { createWriteStream, mkdirSync as mkdirSync7 } from "node:fs";
|
|
@@ -63674,12 +63879,12 @@ var JsonlWriter = class {
|
|
|
63674
63879
|
}
|
|
63675
63880
|
}
|
|
63676
63881
|
close() {
|
|
63677
|
-
return new Promise((
|
|
63882
|
+
return new Promise((resolve22) => {
|
|
63678
63883
|
if (this.dead) {
|
|
63679
|
-
|
|
63884
|
+
resolve22();
|
|
63680
63885
|
return;
|
|
63681
63886
|
}
|
|
63682
|
-
this.stream.end(() =>
|
|
63887
|
+
this.stream.end(() => resolve22());
|
|
63683
63888
|
});
|
|
63684
63889
|
}
|
|
63685
63890
|
};
|
|
@@ -63694,7 +63899,7 @@ var FileEventSink = class {
|
|
|
63694
63899
|
listeners;
|
|
63695
63900
|
clock;
|
|
63696
63901
|
constructor(runId, opts = {}) {
|
|
63697
|
-
this.writer = new JsonlWriter(
|
|
63902
|
+
this.writer = new JsonlWriter(join19(runDir(runId, opts.roots), "events.jsonl"), { flags: "a" });
|
|
63698
63903
|
this.listeners = opts.listeners ?? [];
|
|
63699
63904
|
this.clock = opts.clock ?? (() => globalThis.Date.now());
|
|
63700
63905
|
}
|
|
@@ -63758,7 +63963,7 @@ var Semaphore = class {
|
|
|
63758
63963
|
this.active++;
|
|
63759
63964
|
return this.makeRelease();
|
|
63760
63965
|
}
|
|
63761
|
-
await new Promise((
|
|
63966
|
+
await new Promise((resolve22) => this.queue.push(resolve22));
|
|
63762
63967
|
return this.makeRelease();
|
|
63763
63968
|
}
|
|
63764
63969
|
makeRelease() {
|
|
@@ -63785,15 +63990,15 @@ var Semaphore = class {
|
|
|
63785
63990
|
};
|
|
63786
63991
|
|
|
63787
63992
|
// ../host/src/modules/taskflow/workflows/runtime/transcript.ts
|
|
63788
|
-
import { join as
|
|
63993
|
+
import { join as join20 } from "node:path";
|
|
63789
63994
|
function agentsDir(runId, roots = {}) {
|
|
63790
|
-
return
|
|
63995
|
+
return join20(runDir(runId, roots), "agents");
|
|
63791
63996
|
}
|
|
63792
63997
|
function agentTranscriptPath(runId, index, roots = {}) {
|
|
63793
|
-
return
|
|
63998
|
+
return join20(agentsDir(runId, roots), `${index}.jsonl`);
|
|
63794
63999
|
}
|
|
63795
64000
|
function agentTranscriptPathByName(runId, name, roots = {}) {
|
|
63796
|
-
return
|
|
64001
|
+
return join20(agentsDir(runId, roots), `${sanitizeName(name)}.jsonl`);
|
|
63797
64002
|
}
|
|
63798
64003
|
var TEXT_FLUSH_MS = 120;
|
|
63799
64004
|
var TEXT_FLUSH_BYTES = 2048;
|
|
@@ -63875,7 +64080,7 @@ function sanitizeName(name) {
|
|
|
63875
64080
|
// ../host/src/modules/taskflow/workflows/runtime/worktree.ts
|
|
63876
64081
|
import { execFile } from "node:child_process";
|
|
63877
64082
|
import { existsSync as existsSync4, rmSync as rmSync3 } from "node:fs";
|
|
63878
|
-
import { join as
|
|
64083
|
+
import { join as join21 } from "node:path";
|
|
63879
64084
|
import { promisify } from "node:util";
|
|
63880
64085
|
var exec = promisify(execFile);
|
|
63881
64086
|
var BASE_CONFIG_KEY = RUNTIME_IDENTITY.gitBaseConfigKey;
|
|
@@ -63893,10 +64098,10 @@ async function findGitRoot(cwd) {
|
|
|
63893
64098
|
async function createWorktree(args) {
|
|
63894
64099
|
const name = `${args.runId}-${args.index}`;
|
|
63895
64100
|
const branch = args.branch ?? `aw/${name}`;
|
|
63896
|
-
const path =
|
|
64101
|
+
const path = join21(projectPaths(args.gitRoot).worktrees, name);
|
|
63897
64102
|
const base = await git(args.gitRoot, ["rev-parse", "HEAD"]);
|
|
63898
64103
|
await pruneStaleWorktree(args.gitRoot, path);
|
|
63899
|
-
await git(args.gitRoot, ["worktree", "add", "--detach", path, base]);
|
|
64104
|
+
await git(args.gitRoot, ["worktree", "add", "--relative-paths", "--detach", path, base]);
|
|
63900
64105
|
await git(path, ["checkout", "-B", branch]);
|
|
63901
64106
|
try {
|
|
63902
64107
|
await git(path, ["config", BASE_CONFIG_KEY, base]);
|
|
@@ -64616,8 +64821,8 @@ function fmtDur(ms) {
|
|
|
64616
64821
|
// ../host/src/modules/taskflow/workflows/runtime/run.ts
|
|
64617
64822
|
var HEARTBEAT_MS = 5e3;
|
|
64618
64823
|
async function runWorkflow(opts) {
|
|
64619
|
-
const filePath =
|
|
64620
|
-
const source =
|
|
64824
|
+
const filePath = resolve17(opts.file);
|
|
64825
|
+
const source = readFileSync6(filePath, "utf8");
|
|
64621
64826
|
const fileHash = sha2562(source);
|
|
64622
64827
|
const findings = determinismLint(source);
|
|
64623
64828
|
if (findings.length > 0) {
|
|
@@ -64674,7 +64879,7 @@ async function runWorkflow(opts) {
|
|
|
64674
64879
|
if (opts.signal?.aborted) ac.abort();
|
|
64675
64880
|
else opts.signal?.addEventListener("abort", onSig, { once: true });
|
|
64676
64881
|
events.emit({ type: "run", status: "started", runId, workflowFile: filePath });
|
|
64677
|
-
const heartbeatFile =
|
|
64882
|
+
const heartbeatFile = join22(runDir(runId, opts.roots), ".heartbeat");
|
|
64678
64883
|
const beat = () => {
|
|
64679
64884
|
try {
|
|
64680
64885
|
writeFileSync4(heartbeatFile, String(Date.now()));
|
|
@@ -64753,7 +64958,7 @@ function resolveDefaults(meta3, opts) {
|
|
|
64753
64958
|
effort: o.effort,
|
|
64754
64959
|
sandbox,
|
|
64755
64960
|
approval: DEFAULTS.approval,
|
|
64756
|
-
cwd:
|
|
64961
|
+
cwd: resolve17(configuredCwd ?? process.cwd()),
|
|
64757
64962
|
concurrency,
|
|
64758
64963
|
maxAgents: DEFAULTS.maxAgents,
|
|
64759
64964
|
maxFanout: DEFAULTS.maxFanout,
|
|
@@ -65020,7 +65225,7 @@ var AgentSupervisorClient = class {
|
|
|
65020
65225
|
throw new Error("Taskflow runtime supervisor did not become available");
|
|
65021
65226
|
}
|
|
65022
65227
|
send(request2) {
|
|
65023
|
-
return new Promise((
|
|
65228
|
+
return new Promise((resolve22, reject2) => {
|
|
65024
65229
|
const socket = createConnection2(this.deps.socketPath);
|
|
65025
65230
|
let data = "";
|
|
65026
65231
|
socket.setEncoding("utf8");
|
|
@@ -65041,7 +65246,7 @@ var AgentSupervisorClient = class {
|
|
|
65041
65246
|
}
|
|
65042
65247
|
try {
|
|
65043
65248
|
const response = responseResult(JSON.parse(line));
|
|
65044
|
-
|
|
65249
|
+
resolve22(response.result);
|
|
65045
65250
|
} catch (error61) {
|
|
65046
65251
|
reject2(error61);
|
|
65047
65252
|
}
|
|
@@ -65664,8 +65869,8 @@ var EnvironmentDiagnosticsService = class {
|
|
|
65664
65869
|
return check2("github", "GitHub", "error", true, "GitHub CLI is not authenticated", "Run gh auth login");
|
|
65665
65870
|
}
|
|
65666
65871
|
for (const linked of this.deps.config.integrations.github.linkedRepos) {
|
|
65667
|
-
const
|
|
65668
|
-
if (!
|
|
65872
|
+
const access4 = await this.runCommand(gh, ["repo", "view", linked.repo, "--json", "nameWithOwner"]);
|
|
65873
|
+
if (!access4.ok) {
|
|
65669
65874
|
return check2(
|
|
65670
65875
|
"github",
|
|
65671
65876
|
"GitHub",
|
|
@@ -65762,7 +65967,7 @@ var EnvironmentDiagnosticsService = class {
|
|
|
65762
65967
|
// ../host/src/modules/taskflow/services/environment-worker-factory.ts
|
|
65763
65968
|
import { chmodSync as chmodSync2, mkdtempSync as mkdtempSync2, rmSync as rmSync4, writeFileSync as writeFileSync5 } from "node:fs";
|
|
65764
65969
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
65765
|
-
import { join as
|
|
65970
|
+
import { join as join23, posix as posix2, relative as relative5 } from "node:path";
|
|
65766
65971
|
var executableByProvider = {
|
|
65767
65972
|
codex: "codex",
|
|
65768
65973
|
"claude-code": "claude",
|
|
@@ -65789,7 +65994,7 @@ var MappedWorkspaceWorker = class {
|
|
|
65789
65994
|
}
|
|
65790
65995
|
};
|
|
65791
65996
|
function mapAgentSpecToEnvironment(spec, hostWorkspace, containerWorkspace) {
|
|
65792
|
-
const suffix =
|
|
65997
|
+
const suffix = relative5(hostWorkspace, spec.cwd);
|
|
65793
65998
|
if (suffix.startsWith("..")) {
|
|
65794
65999
|
throw new Error(`Execution workspace is outside the environment mount: ${spec.cwd}`);
|
|
65795
66000
|
}
|
|
@@ -65810,10 +66015,10 @@ var EnvironmentWorkerFactory = class {
|
|
|
65810
66015
|
this.handle = handle;
|
|
65811
66016
|
const containerWorkspace = handle.workspace.containerPath;
|
|
65812
66017
|
if (!containerWorkspace) throw new Error(`Environment has no container workspace: ${handle.id}`);
|
|
65813
|
-
this.directory = mkdtempSync2(
|
|
66018
|
+
this.directory = mkdtempSync2(join23(tmpdir3(), "taskflow-environment-workers-"));
|
|
65814
66019
|
const paths = Object.fromEntries(
|
|
65815
66020
|
Object.entries(executableByProvider).map(([provider, executable]) => {
|
|
65816
|
-
const path =
|
|
66021
|
+
const path = join23(this.directory, provider);
|
|
65817
66022
|
writeFileSync5(path, transport.executableShim(handle, executable), { encoding: "utf8", mode: 448 });
|
|
65818
66023
|
chmodSync2(path, 448);
|
|
65819
66024
|
return [provider, path];
|
|
@@ -65845,8 +66050,8 @@ var RoutingEnvironmentWorker = class {
|
|
|
65845
66050
|
id;
|
|
65846
66051
|
resolve;
|
|
65847
66052
|
factoryFor;
|
|
65848
|
-
constructor(id,
|
|
65849
|
-
this.resolve =
|
|
66053
|
+
constructor(id, resolve22, factoryFor) {
|
|
66054
|
+
this.resolve = resolve22;
|
|
65850
66055
|
this.factoryFor = factoryFor;
|
|
65851
66056
|
this.id = id;
|
|
65852
66057
|
}
|
|
@@ -65863,8 +66068,8 @@ var RoutingEnvironmentWorkerFactory = class {
|
|
|
65863
66068
|
workers = /* @__PURE__ */ new Map();
|
|
65864
66069
|
resolve;
|
|
65865
66070
|
onShutdown;
|
|
65866
|
-
constructor(
|
|
65867
|
-
this.resolve =
|
|
66071
|
+
constructor(resolve22, onShutdown) {
|
|
66072
|
+
this.resolve = resolve22;
|
|
65868
66073
|
this.onShutdown = onShutdown;
|
|
65869
66074
|
}
|
|
65870
66075
|
get(id) {
|
|
@@ -65890,11 +66095,11 @@ var RoutingEnvironmentWorkerFactory = class {
|
|
|
65890
66095
|
};
|
|
65891
66096
|
|
|
65892
66097
|
// ../host/src/modules/taskflow/services/execution-transcript-service.ts
|
|
65893
|
-
import { readFile as
|
|
65894
|
-
import { basename as
|
|
66098
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
66099
|
+
import { basename as basename10, dirname as dirname14, isAbsolute as isAbsolute4, normalize } from "node:path";
|
|
65895
66100
|
|
|
65896
66101
|
// ../host/src/modules/taskflow/services/codex-session-log-service.ts
|
|
65897
|
-
import { readFile as
|
|
66102
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
65898
66103
|
var TOOL_OUTPUT_TRUNCATE_LIMIT = 12e3;
|
|
65899
66104
|
function readString3(raw2) {
|
|
65900
66105
|
return typeof raw2 === "string" && raw2.length > 0 ? raw2 : null;
|
|
@@ -66155,7 +66360,7 @@ function parseCodexSessionMessages(text) {
|
|
|
66155
66360
|
async function readCodexSessionMessages(thread) {
|
|
66156
66361
|
if (!thread.path) return [];
|
|
66157
66362
|
try {
|
|
66158
|
-
return parseCodexSessionMessages(await
|
|
66363
|
+
return parseCodexSessionMessages(await readFile7(thread.path, "utf8"));
|
|
66159
66364
|
} catch {
|
|
66160
66365
|
return [];
|
|
66161
66366
|
}
|
|
@@ -66171,7 +66376,7 @@ function transcriptPath(value, engineRunId) {
|
|
|
66171
66376
|
const path = normalize(candidate);
|
|
66172
66377
|
const agents = dirname14(path);
|
|
66173
66378
|
const run = dirname14(agents);
|
|
66174
|
-
if (
|
|
66379
|
+
if (basename10(agents) !== "agents" || basename10(run) !== engineRunId || basename10(dirname14(run)) !== "runs" || !basename10(path).endsWith(".jsonl"))
|
|
66175
66380
|
return null;
|
|
66176
66381
|
return path;
|
|
66177
66382
|
}
|
|
@@ -66225,7 +66430,7 @@ var ExecutionTranscriptService = class {
|
|
|
66225
66430
|
if (path === null) return { ok: false, reason: "unavailable" };
|
|
66226
66431
|
let bytes;
|
|
66227
66432
|
try {
|
|
66228
|
-
bytes = await
|
|
66433
|
+
bytes = await readFile8(path);
|
|
66229
66434
|
} catch (error61) {
|
|
66230
66435
|
if (error61.code !== "ENOENT") return { ok: false, reason: "unavailable" };
|
|
66231
66436
|
return { ok: true, response: { executionId, entries: [], nextCursor: 0 } };
|
|
@@ -66259,7 +66464,7 @@ var ExecutionTranscriptService = class {
|
|
|
66259
66464
|
if (!path) return { ok: false, reason: "unavailable" };
|
|
66260
66465
|
let text;
|
|
66261
66466
|
try {
|
|
66262
|
-
text = await
|
|
66467
|
+
text = await readFile8(path, "utf8");
|
|
66263
66468
|
} catch {
|
|
66264
66469
|
return { ok: false, reason: "unavailable" };
|
|
66265
66470
|
}
|
|
@@ -66845,12 +67050,12 @@ var RunPresentationService = class {
|
|
|
66845
67050
|
};
|
|
66846
67051
|
|
|
66847
67052
|
// ../host/src/modules/taskflow/services/run-service.ts
|
|
66848
|
-
import { readFile as
|
|
66849
|
-
import { join as
|
|
67053
|
+
import { readFile as readFile9 } from "node:fs/promises";
|
|
67054
|
+
import { join as join25 } from "node:path";
|
|
66850
67055
|
|
|
66851
67056
|
// ../host/src/modules/taskflow/services/workspace-facade.ts
|
|
66852
|
-
import { join as
|
|
66853
|
-
function workspaceBindingFor(runId, projectRoot2, workspaceRoot, baseBranch, baseCommit, workspace,
|
|
67057
|
+
import { join as join24 } from "node:path";
|
|
67058
|
+
function workspaceBindingFor(runId, projectRoot2, workspaceRoot, baseBranch, baseCommit, workspace, access4) {
|
|
66854
67059
|
const segment = runId.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "run";
|
|
66855
67060
|
if (workspace.strategy !== "isolated_worktree") {
|
|
66856
67061
|
const branch = workspace.strategy === "current_branch" ? "" : workspace.branch?.trim() || `${APP_SLUG}/run-${segment}`;
|
|
@@ -66862,11 +67067,11 @@ function workspaceBindingFor(runId, projectRoot2, workspaceRoot, baseBranch, bas
|
|
|
66862
67067
|
baseBranch: workspace.strategy === "new_branch" ? workspace.baseBranch?.trim() || baseBranch : baseBranch,
|
|
66863
67068
|
baseCommit,
|
|
66864
67069
|
strategy: workspace.strategy,
|
|
66865
|
-
access:
|
|
67070
|
+
access: access4
|
|
66866
67071
|
};
|
|
66867
67072
|
}
|
|
66868
67073
|
const name = `${APP_SLUG}-run-${segment}`;
|
|
66869
|
-
const path =
|
|
67074
|
+
const path = join24(workspaceRoot, name);
|
|
66870
67075
|
return {
|
|
66871
67076
|
workspaceId: `workspace_${runId}`,
|
|
66872
67077
|
path,
|
|
@@ -66875,7 +67080,7 @@ function workspaceBindingFor(runId, projectRoot2, workspaceRoot, baseBranch, bas
|
|
|
66875
67080
|
baseBranch: workspace.baseBranch?.trim() || baseBranch,
|
|
66876
67081
|
baseCommit,
|
|
66877
67082
|
strategy: workspace.strategy,
|
|
66878
|
-
access:
|
|
67083
|
+
access: access4
|
|
66879
67084
|
};
|
|
66880
67085
|
}
|
|
66881
67086
|
function slugSegment(value, fallback) {
|
|
@@ -66884,7 +67089,7 @@ function slugSegment(value, fallback) {
|
|
|
66884
67089
|
function forkBindingFor(run, workspaceRoot, slug2) {
|
|
66885
67090
|
const runSegment = slugSegment(run.id, "run");
|
|
66886
67091
|
const forkSegment = slugSegment(slug2, "fork");
|
|
66887
|
-
const path =
|
|
67092
|
+
const path = join24(workspaceRoot, `${APP_SLUG}-run-${runSegment}-fork-${forkSegment}`);
|
|
66888
67093
|
return {
|
|
66889
67094
|
workspaceId: `workspace_lease_${run.id}_${forkSegment}`,
|
|
66890
67095
|
path,
|
|
@@ -66936,7 +67141,7 @@ var WorkspaceFacade = class {
|
|
|
66936
67141
|
if (run === null) return { ok: false, reason: "not_found" };
|
|
66937
67142
|
if (run.workspacePolicy === "none") return { ok: true, run, workspace: null, replayed: true };
|
|
66938
67143
|
const workspace = input2.workspace ?? { strategy: "isolated_worktree" };
|
|
66939
|
-
const
|
|
67144
|
+
const access4 = input2.access ?? "exclusive_write";
|
|
66940
67145
|
const currentBranch = this.deps.git.currentBranch(input2.projectRoot);
|
|
66941
67146
|
if (workspace.strategy === "current_branch" && currentBranch.length === 0)
|
|
66942
67147
|
return { ok: false, reason: "detached_head" };
|
|
@@ -66952,7 +67157,7 @@ var WorkspaceFacade = class {
|
|
|
66952
67157
|
effectiveBase,
|
|
66953
67158
|
baseCommit,
|
|
66954
67159
|
workspace,
|
|
66955
|
-
|
|
67160
|
+
access4
|
|
66956
67161
|
);
|
|
66957
67162
|
if (workspace.strategy === "current_branch") binding.branch = currentBranch;
|
|
66958
67163
|
if (workspace.strategy !== "isolated_worktree") {
|
|
@@ -66960,7 +67165,7 @@ var WorkspaceFacade = class {
|
|
|
66960
67165
|
runId: input2.runId,
|
|
66961
67166
|
projectId: run.projectId,
|
|
66962
67167
|
canonicalPath: binding.canonicalPath,
|
|
66963
|
-
access:
|
|
67168
|
+
access: access4,
|
|
66964
67169
|
createdAt: this.now().toISOString()
|
|
66965
67170
|
});
|
|
66966
67171
|
if (!claim2.ok) return { ok: false, reason: "checkout_busy" };
|
|
@@ -67827,7 +68032,7 @@ var RunService = class {
|
|
|
67827
68032
|
root,
|
|
67828
68033
|
terminal.cursor,
|
|
67829
68034
|
terminal.type === "completed" ? "completed" : active.cancelling ? "cancelled" : "failed",
|
|
67830
|
-
terminal.type === "completed" ? { resultPath:
|
|
68035
|
+
terminal.type === "completed" ? { resultPath: join25(root.dataRoot, "runs", engineRunId, "result.json") } : null
|
|
67831
68036
|
);
|
|
67832
68037
|
const completedAt = this.now().toISOString();
|
|
67833
68038
|
if (terminal.type === "completed") {
|
|
@@ -67939,7 +68144,7 @@ var RunService = class {
|
|
|
67939
68144
|
async completedResult(engineRunId, dataRoot2) {
|
|
67940
68145
|
try {
|
|
67941
68146
|
const result = JsonValueSchema.safeParse(
|
|
67942
|
-
JSON.parse(await
|
|
68147
|
+
JSON.parse(await readFile9(join25(dataRoot2, "runs", engineRunId, "result.json"), "utf8"))
|
|
67943
68148
|
);
|
|
67944
68149
|
return result.success ? result.data : null;
|
|
67945
68150
|
} catch {
|
|
@@ -67986,12 +68191,12 @@ var RunService = class {
|
|
|
67986
68191
|
};
|
|
67987
68192
|
|
|
67988
68193
|
// ../host/src/modules/taskflow/services/session-restore-service.ts
|
|
67989
|
-
import { basename as
|
|
68194
|
+
import { basename as basename11, resolve as resolve18 } from "node:path";
|
|
67990
68195
|
function entryBranch(entry) {
|
|
67991
|
-
return entry.branch ??
|
|
68196
|
+
return entry.branch ?? basename11(entry.path);
|
|
67992
68197
|
}
|
|
67993
68198
|
function computeOpenBranches(input2) {
|
|
67994
|
-
const resolvedProjectDir =
|
|
68199
|
+
const resolvedProjectDir = resolve18(input2.projectDir);
|
|
67995
68200
|
const openWindowNames = new Set(
|
|
67996
68201
|
input2.windows.filter((window) => window.sessionName === input2.sessionName).map((window) => window.windowName)
|
|
67997
68202
|
);
|
|
@@ -68006,7 +68211,7 @@ function buildOpenSessionsState(branches, savedAt) {
|
|
|
68006
68211
|
}
|
|
68007
68212
|
var DEFAULT_SESSION_SNAPSHOT_INTERVAL_MS = 3e4;
|
|
68008
68213
|
async function saveOpenSessionsSnapshot(deps) {
|
|
68009
|
-
const projectRoot2 =
|
|
68214
|
+
const projectRoot2 = resolve18(deps.projectRoot);
|
|
68010
68215
|
const sessionName = buildProjectSessionName(projectRoot2);
|
|
68011
68216
|
let windows = [];
|
|
68012
68217
|
try {
|
|
@@ -68313,8 +68518,8 @@ var TaskflowDirectSessionService = class {
|
|
|
68313
68518
|
|
|
68314
68519
|
// ../host/src/modules/taskflow/services/workflow-catalog-service.ts
|
|
68315
68520
|
import { createHash as createHash9 } from "node:crypto";
|
|
68316
|
-
import { readdir as readdir4, readFile as
|
|
68317
|
-
import { join as
|
|
68521
|
+
import { readdir as readdir4, readFile as readFile10, stat as stat4 } from "node:fs/promises";
|
|
68522
|
+
import { join as join26, resolve as resolve19 } from "node:path";
|
|
68318
68523
|
var MAX_WORKFLOW_BYTES = 524288;
|
|
68319
68524
|
function hash3(value) {
|
|
68320
68525
|
return `sha256:${createHash9("sha256").update(value).digest("hex")}`;
|
|
@@ -68358,9 +68563,9 @@ function duplicateDiagnostic(name, origin) {
|
|
|
68358
68563
|
}
|
|
68359
68564
|
function rootsFor(config2) {
|
|
68360
68565
|
return [
|
|
68361
|
-
{ origin: "project", directory: projectPaths(
|
|
68362
|
-
{ origin: "global", directory:
|
|
68363
|
-
{ origin: "builtin", directory:
|
|
68566
|
+
{ origin: "project", directory: projectPaths(resolve19(config2.projectRoot)).workflows, priority: 0 },
|
|
68567
|
+
{ origin: "global", directory: join26(resolve19(config2.taskflowHome), PATH_NAMES.workflows), priority: 1 },
|
|
68568
|
+
{ origin: "builtin", directory: resolve19(config2.builtinRoot), priority: 2 }
|
|
68364
68569
|
];
|
|
68365
68570
|
}
|
|
68366
68571
|
var WorkflowCatalogService = class {
|
|
@@ -68465,7 +68670,7 @@ var WorkflowCatalogService = class {
|
|
|
68465
68670
|
return { candidates, diagnostics, invalidEntries };
|
|
68466
68671
|
}
|
|
68467
68672
|
for (const name of names) {
|
|
68468
|
-
const path =
|
|
68673
|
+
const path = join26(root.directory, name);
|
|
68469
68674
|
try {
|
|
68470
68675
|
if ((await stat4(path)).size > MAX_WORKFLOW_BYTES) {
|
|
68471
68676
|
const diagnostic = {
|
|
@@ -68478,14 +68683,14 @@ var WorkflowCatalogService = class {
|
|
|
68478
68683
|
invalidEntries.push({ status: "invalid", origin: root.origin, path, diagnostic });
|
|
68479
68684
|
continue;
|
|
68480
68685
|
}
|
|
68481
|
-
const source = await
|
|
68686
|
+
const source = await readFile10(path, "utf8");
|
|
68482
68687
|
const parsed = parseWorkflow(source);
|
|
68483
68688
|
const definition = {
|
|
68484
|
-
id: `${root.origin}:${hash3(
|
|
68689
|
+
id: `${root.origin}:${hash3(resolve19(path))}`,
|
|
68485
68690
|
name: parsed.meta.name,
|
|
68486
68691
|
description: parsed.meta.description,
|
|
68487
68692
|
origin: root.origin,
|
|
68488
|
-
path:
|
|
68693
|
+
path: resolve19(path),
|
|
68489
68694
|
contentHash: hash3(source),
|
|
68490
68695
|
source,
|
|
68491
68696
|
metadata: metadataFor(parsed.meta, this.keyVersion),
|
|
@@ -68508,7 +68713,7 @@ var WorkflowCatalogService = class {
|
|
|
68508
68713
|
};
|
|
68509
68714
|
|
|
68510
68715
|
// ../host/src/modules/taskflow/services/workflow-event-bridge.ts
|
|
68511
|
-
import { join as
|
|
68716
|
+
import { join as join27 } from "node:path";
|
|
68512
68717
|
function record4(value) {
|
|
68513
68718
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
|
|
68514
68719
|
const output2 = {};
|
|
@@ -68598,7 +68803,7 @@ function executionFor(run, existing, details, context) {
|
|
|
68598
68803
|
key: details.key,
|
|
68599
68804
|
index: details.index,
|
|
68600
68805
|
phaseIndex: details.phaseIndex,
|
|
68601
|
-
transcriptPath: context ?
|
|
68806
|
+
transcriptPath: context ? join27(context.dataRoot, "runs", context.engineRunId, "agents", `${details.index}.jsonl`) : null
|
|
68602
68807
|
},
|
|
68603
68808
|
workspaceId: run.workspaceId,
|
|
68604
68809
|
input: existing?.input ?? null,
|
|
@@ -68658,8 +68863,8 @@ var WorkflowEventBridge = class {
|
|
|
68658
68863
|
};
|
|
68659
68864
|
|
|
68660
68865
|
// ../host/src/modules/taskflow/services/workflow-runner.ts
|
|
68661
|
-
import { mkdir as mkdir5, writeFile as
|
|
68662
|
-
import { join as
|
|
68866
|
+
import { mkdir as mkdir5, writeFile as writeFile8 } from "node:fs/promises";
|
|
68867
|
+
import { join as join28 } from "node:path";
|
|
68663
68868
|
function envelope(spec, message) {
|
|
68664
68869
|
return {
|
|
68665
68870
|
...message,
|
|
@@ -68693,10 +68898,10 @@ var NodeWorkflowRunner = class {
|
|
|
68693
68898
|
const pid = process.pid;
|
|
68694
68899
|
let heartbeat;
|
|
68695
68900
|
const done = (async () => {
|
|
68696
|
-
const runDirectory =
|
|
68901
|
+
const runDirectory = join28(spec.spec.dataRoot, "runs", spec.engineRunId);
|
|
68697
68902
|
await mkdir5(runDirectory, { recursive: true });
|
|
68698
|
-
const snapshotPath =
|
|
68699
|
-
await
|
|
68903
|
+
const snapshotPath = join28(runDirectory, "workflow.js");
|
|
68904
|
+
await writeFile8(snapshotPath, spec.spec.source, "utf8");
|
|
68700
68905
|
emit(envelope(spec, { type: "started", pid }));
|
|
68701
68906
|
heartbeat = setInterval(() => {
|
|
68702
68907
|
emit(envelope(spec, { type: "heartbeat", cursor }));
|
|
@@ -69368,16 +69573,16 @@ var WorktreeConversationService = class {
|
|
|
69368
69573
|
|
|
69369
69574
|
// ../host/src/modules/taskflow/adapters/docker-compose-environment.ts
|
|
69370
69575
|
import { createHash as createHash10 } from "node:crypto";
|
|
69371
|
-
import { existsSync as existsSync5, readFileSync as
|
|
69372
|
-
import { resolve as
|
|
69576
|
+
import { existsSync as existsSync5, readFileSync as readFileSync7 } from "node:fs";
|
|
69577
|
+
import { resolve as resolve20 } from "node:path";
|
|
69373
69578
|
var COMPOSE_FILENAMES = ["compose.yaml", "compose.yml", "docker-compose.yaml", "docker-compose.yml"];
|
|
69374
69579
|
function composeFile(workspacePath, configured) {
|
|
69375
69580
|
if (configured) {
|
|
69376
|
-
const candidate =
|
|
69581
|
+
const candidate = resolve20(workspacePath, configured);
|
|
69377
69582
|
if (existsSync5(candidate)) return candidate;
|
|
69378
69583
|
throw new Error(`Docker Compose file does not exist: ${configured}`);
|
|
69379
69584
|
}
|
|
69380
|
-
const found = COMPOSE_FILENAMES.map((file2) =>
|
|
69585
|
+
const found = COMPOSE_FILENAMES.map((file2) => resolve20(workspacePath, file2)).find(existsSync5);
|
|
69381
69586
|
if (!found) throw new Error("No Docker Compose file was found");
|
|
69382
69587
|
return found;
|
|
69383
69588
|
}
|
|
@@ -69398,7 +69603,7 @@ var DockerComposeEnvironmentProvider = class {
|
|
|
69398
69603
|
}
|
|
69399
69604
|
async probe(context) {
|
|
69400
69605
|
const version2 = await runCaptured(this.runner, { command: "docker", args: ["compose", "version", "--short"] });
|
|
69401
|
-
const configs = COMPOSE_FILENAMES.map((file2) =>
|
|
69606
|
+
const configs = COMPOSE_FILENAMES.map((file2) => resolve20(context.workspacePath, file2)).filter(existsSync5);
|
|
69402
69607
|
return {
|
|
69403
69608
|
provider: this.id,
|
|
69404
69609
|
available: version2.exit.code === 0 && configs.length > 0,
|
|
@@ -69409,7 +69614,7 @@ var DockerComposeEnvironmentProvider = class {
|
|
|
69409
69614
|
}
|
|
69410
69615
|
async resolve(context) {
|
|
69411
69616
|
const file2 = composeFile(context.workspacePath, context.configRef);
|
|
69412
|
-
const source =
|
|
69617
|
+
const source = readFileSync7(file2, "utf8");
|
|
69413
69618
|
return {
|
|
69414
69619
|
provider: this.id,
|
|
69415
69620
|
configRef: file2,
|
|
@@ -70021,11 +70226,11 @@ var LocalDatagramForwardProvider = class {
|
|
|
70021
70226
|
void this.pipeResponse(command.stdout, socket, remote);
|
|
70022
70227
|
void command.exited.finally(() => commands.delete(command));
|
|
70023
70228
|
});
|
|
70024
|
-
await new Promise((
|
|
70229
|
+
await new Promise((resolve22, reject2) => {
|
|
70025
70230
|
socket.once("error", reject2);
|
|
70026
70231
|
socket.bind(0, "127.0.0.1", () => {
|
|
70027
70232
|
socket.off("error", reject2);
|
|
70028
|
-
|
|
70233
|
+
resolve22();
|
|
70029
70234
|
});
|
|
70030
70235
|
});
|
|
70031
70236
|
const address = socket.address();
|
|
@@ -70049,8 +70254,8 @@ var LocalDatagramForwardProvider = class {
|
|
|
70049
70254
|
if (!active) return;
|
|
70050
70255
|
this.active.delete(endpointId);
|
|
70051
70256
|
await Promise.all(Array.from(active.commands, (command) => command.kill()));
|
|
70052
|
-
await new Promise((
|
|
70053
|
-
active.socket.close(() =>
|
|
70257
|
+
await new Promise((resolve22) => {
|
|
70258
|
+
active.socket.close(() => resolve22());
|
|
70054
70259
|
});
|
|
70055
70260
|
}
|
|
70056
70261
|
async close() {
|
|
@@ -70127,11 +70332,11 @@ var LocalForwardProvider = class {
|
|
|
70127
70332
|
}
|
|
70128
70333
|
});
|
|
70129
70334
|
});
|
|
70130
|
-
await new Promise((
|
|
70335
|
+
await new Promise((resolve22, reject2) => {
|
|
70131
70336
|
server.once("error", reject2);
|
|
70132
70337
|
server.listen(0, "127.0.0.1", () => {
|
|
70133
70338
|
server.off("error", reject2);
|
|
70134
|
-
|
|
70339
|
+
resolve22();
|
|
70135
70340
|
});
|
|
70136
70341
|
});
|
|
70137
70342
|
const address = server.address();
|
|
@@ -70157,8 +70362,8 @@ var LocalForwardProvider = class {
|
|
|
70157
70362
|
if (!active) return;
|
|
70158
70363
|
this.active.delete(endpointId);
|
|
70159
70364
|
for (const socket of active.sockets) socket.destroy();
|
|
70160
|
-
await new Promise((
|
|
70161
|
-
active.server.close(() =>
|
|
70365
|
+
await new Promise((resolve22) => {
|
|
70366
|
+
active.server.close(() => resolve22());
|
|
70162
70367
|
});
|
|
70163
70368
|
}
|
|
70164
70369
|
async close() {
|
|
@@ -70775,13 +70980,13 @@ function createProjectApp(runtime, instancePrefix, host) {
|
|
|
70775
70980
|
const workflowEvents = new WorkflowEventBridge({ store: runStore, publisher: runEventPublisher });
|
|
70776
70981
|
const workspaces = new WorkspaceFacade({ store: runStore, git: git2 });
|
|
70777
70982
|
const workflowDataRoot = globalPaths().root;
|
|
70778
|
-
const supervisorSocket =
|
|
70983
|
+
const supervisorSocket = join29(workflowDataRoot, "runtime", "supervisor.sock");
|
|
70779
70984
|
const supervisor = new AgentSupervisorClient({
|
|
70780
70985
|
socketPath: supervisorSocket,
|
|
70781
70986
|
startDaemon: () => {
|
|
70782
70987
|
const directory = dirname15(fileURLToPath(import.meta.url));
|
|
70783
|
-
const builtEntry =
|
|
70784
|
-
const sourceEntry =
|
|
70988
|
+
const builtEntry = join29(directory, "supervisor.js");
|
|
70989
|
+
const sourceEntry = join29(directory, "supervisor.ts");
|
|
70785
70990
|
const child = existsSync6(builtEntry) ? spawn6(process.execPath, [builtEntry], { detached: true, stdio: "ignore" }) : spawn6(process.execPath, ["--import", "tsx", sourceEntry], { detached: true, stdio: "ignore" });
|
|
70786
70991
|
child.unref();
|
|
70787
70992
|
}
|
|
@@ -71067,7 +71272,7 @@ function createProjectApp(runtime, instancePrefix, host) {
|
|
|
71067
71272
|
startupEnvs: config2.startupEnvs,
|
|
71068
71273
|
linkedRepos: config2.integrations.github.linkedRepos.map((lr) => ({
|
|
71069
71274
|
alias: lr.alias,
|
|
71070
|
-
...lr.dir ? { dir:
|
|
71275
|
+
...lr.dir ? { dir: resolve21(PROJECT_DIR, lr.dir) } : {}
|
|
71071
71276
|
})),
|
|
71072
71277
|
linearAutoCreateWorktrees: linearAutoCreateEnabled,
|
|
71073
71278
|
autoRemoveOnMerge: autoRemoveOnMergeEnabled,
|
|
@@ -71153,13 +71358,13 @@ function createProjectApp(runtime, instancePrefix, host) {
|
|
|
71153
71358
|
}
|
|
71154
71359
|
}
|
|
71155
71360
|
async function getWorktreeGitDirs() {
|
|
71156
|
-
const
|
|
71157
|
-
const projectRoot2 =
|
|
71361
|
+
const gitDirs2 = /* @__PURE__ */ new Map();
|
|
71362
|
+
const projectRoot2 = resolve21(PROJECT_DIR);
|
|
71158
71363
|
for (const entry of git2.listLiveWorktrees(projectRoot2)) {
|
|
71159
71364
|
if (entry.bare || sameFsPath(entry.path, projectRoot2) || !entry.branch) continue;
|
|
71160
|
-
|
|
71365
|
+
gitDirs2.set(entry.branch, git2.resolveWorktreeGitDir(entry.path));
|
|
71161
71366
|
}
|
|
71162
|
-
return
|
|
71367
|
+
return gitDirs2;
|
|
71163
71368
|
}
|
|
71164
71369
|
async function readProjectSnapshot() {
|
|
71165
71370
|
const linearApiKey = process.env.LINEAR_API_KEY;
|
|
@@ -72223,7 +72428,7 @@ function createDaemonTaskflowHost(context) {
|
|
|
72223
72428
|
port: hostListen(env2).port,
|
|
72224
72429
|
workflowBuiltinsDir: taskflowAssets(env2).workflowBuiltinsDir,
|
|
72225
72430
|
version: env2.PORTTA_VERSION || "0.0.0-local",
|
|
72226
|
-
buildDate: true ? "2026-09-
|
|
72431
|
+
buildDate: true ? "2026-09-18T00:00:48Z" : (/* @__PURE__ */ new Date()).toISOString(),
|
|
72227
72432
|
environmentStore: createEnvironmentStore(paths.database),
|
|
72228
72433
|
hostEnvironmentProvider: new HostEnvironmentProvider(),
|
|
72229
72434
|
devContainerProvider: new DevContainerProvider(),
|
|
@@ -72702,7 +72907,7 @@ var readBodyDirect = (request2) => {
|
|
|
72702
72907
|
request2[bodyBufferKey] = buffered;
|
|
72703
72908
|
return Promise.resolve(buffered);
|
|
72704
72909
|
}
|
|
72705
|
-
const promise2 = new Promise((
|
|
72910
|
+
const promise2 = new Promise((resolve22, reject2) => {
|
|
72706
72911
|
const chunks = [];
|
|
72707
72912
|
let settled = false;
|
|
72708
72913
|
const finish = (callback) => {
|
|
@@ -72720,7 +72925,7 @@ var readBodyDirect = (request2) => {
|
|
|
72720
72925
|
else if (recovered === void 0) reject2(error61 ?? normalizeAbortError(request2, incoming));
|
|
72721
72926
|
else {
|
|
72722
72927
|
request2[bodyBufferKey] = recovered;
|
|
72723
|
-
|
|
72928
|
+
resolve22(recovered);
|
|
72724
72929
|
}
|
|
72725
72930
|
});
|
|
72726
72931
|
return true;
|
|
@@ -72732,7 +72937,7 @@ var readBodyDirect = (request2) => {
|
|
|
72732
72937
|
finish(() => {
|
|
72733
72938
|
const buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks);
|
|
72734
72939
|
request2[bodyBufferKey] = buffer;
|
|
72735
|
-
|
|
72940
|
+
resolve22(buffer);
|
|
72736
72941
|
});
|
|
72737
72942
|
};
|
|
72738
72943
|
const onError = (error61) => {
|
|
@@ -73257,7 +73462,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
|
|
|
73257
73462
|
});
|
|
73258
73463
|
if (!chunk) {
|
|
73259
73464
|
if (i === 1) {
|
|
73260
|
-
await new Promise((
|
|
73465
|
+
await new Promise((resolve22) => setTimeout(resolve22));
|
|
73261
73466
|
maxReadCount = 3;
|
|
73262
73467
|
continue;
|
|
73263
73468
|
}
|
|
@@ -73554,8 +73759,8 @@ var SESSION_ABANDON_AFTER_SECONDS = 6 * 60 * 60;
|
|
|
73554
73759
|
var INSTRUCTION_MAX_BYTES = 64 * 1024;
|
|
73555
73760
|
|
|
73556
73761
|
// ../core/src/database-config.ts
|
|
73557
|
-
import { join as
|
|
73558
|
-
var DATABASE_RELATIVE_PATH =
|
|
73762
|
+
import { join as join30 } from "node:path";
|
|
73763
|
+
var DATABASE_RELATIVE_PATH = join30("state", "panel", "portta.db");
|
|
73559
73764
|
|
|
73560
73765
|
// ../../node_modules/ws/wrapper.mjs
|
|
73561
73766
|
var import_stream = __toESM(require_stream(), 1);
|
|
@@ -73611,7 +73816,7 @@ function ghPath() {
|
|
|
73611
73816
|
}
|
|
73612
73817
|
function runGh2(args, options = {}) {
|
|
73613
73818
|
const binary = ghPath();
|
|
73614
|
-
return new Promise((
|
|
73819
|
+
return new Promise((resolve22, reject2) => {
|
|
73615
73820
|
const child = execFile2(
|
|
73616
73821
|
binary,
|
|
73617
73822
|
args,
|
|
@@ -73624,7 +73829,7 @@ function runGh2(args, options = {}) {
|
|
|
73624
73829
|
env: { ...process.env, GH_PAGER: "cat", NO_COLOR: "1", GH_PROMPT_DISABLED: "1" }
|
|
73625
73830
|
},
|
|
73626
73831
|
(error61, stdout, stderr) => {
|
|
73627
|
-
if (!error61) return
|
|
73832
|
+
if (!error61) return resolve22(stdout);
|
|
73628
73833
|
if (error61.killed) {
|
|
73629
73834
|
return reject2(new ForgeError("timeout", `gh ${args[0]} ${args[1] ?? ""} took longer than ${TIMEOUT_MS / 1e3}s`));
|
|
73630
73835
|
}
|
|
@@ -74087,11 +74292,11 @@ async function startHost(options) {
|
|
|
74087
74292
|
const sockets = new import_websocket_server.default({ noServer: true });
|
|
74088
74293
|
const server = createServer2(getRequestListener(app.fetch));
|
|
74089
74294
|
server.on("upgrade", createHostUpgrade(options, sockets));
|
|
74090
|
-
await new Promise((
|
|
74295
|
+
await new Promise((resolve22, reject2) => {
|
|
74091
74296
|
server.once("error", reject2);
|
|
74092
74297
|
server.listen(options.port, options.host, () => {
|
|
74093
74298
|
server.off("error", reject2);
|
|
74094
|
-
|
|
74299
|
+
resolve22();
|
|
74095
74300
|
});
|
|
74096
74301
|
});
|
|
74097
74302
|
const address = server.address();
|
|
@@ -74102,8 +74307,8 @@ async function startHost(options) {
|
|
|
74102
74307
|
close: async () => {
|
|
74103
74308
|
for (const socket of sockets.clients) socket.close(1001, "the host daemon is shutting down");
|
|
74104
74309
|
sockets.close();
|
|
74105
|
-
await new Promise((
|
|
74106
|
-
server.close(() =>
|
|
74310
|
+
await new Promise((resolve22) => {
|
|
74311
|
+
server.close(() => resolve22());
|
|
74107
74312
|
server.closeAllConnections();
|
|
74108
74313
|
});
|
|
74109
74314
|
for (const module of options.modules) await module.close?.();
|