@rallycry/conveyor-agent 11.0.6 → 11.0.8
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/{boot-7XH4FFLO.js → boot-ZE6BM7L2.js} +25 -335
- package/dist/{chunk-UHMCBCQL.js → chunk-43XITDZP.js} +2 -2
- package/dist/{chunk-HFUVAHII.js → chunk-APP6Y2D7.js} +2 -1
- package/dist/{chunk-D57S4UR5.js → chunk-IBAIJY7V.js} +17 -1
- package/dist/{chunk-W6VILPQE.js → chunk-JG3VMWRQ.js} +1 -1
- package/dist/{chunk-GUYMLASA.js → chunk-SKTCDL4K.js} +45 -8
- package/dist/chunk-SR66HQKB.js +464 -0
- package/dist/{chunk-EXQ6AHOY.js → chunk-TOTCEWJD.js} +18 -0
- package/dist/cli.js +9 -9
- package/dist/{client-IG6C5F2G.js → client-6AUPKKMV.js} +1 -1
- package/dist/index.d.ts +13 -0
- package/dist/index.js +5 -5
- package/dist/{serve-boot-IFUIGFEH.js → serve-boot-ESZKFN5M.js} +3 -3
- package/dist/{server-2Z5V3IPA.js → server-2IZBKD3Q.js} +2 -2
- package/package.json +2 -2
- package/dist/chunk-XORJ6SII.js +0 -46
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
startWorkbenchServer
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-IBAIJY7V.js";
|
|
4
4
|
import {
|
|
5
5
|
TOMBSTONE_MESSAGE,
|
|
6
6
|
isLegacyEntrypointLaunch
|
|
7
7
|
} from "./chunk-R3FDJQL6.js";
|
|
8
8
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
cloneReferenceRepos,
|
|
10
|
+
computeGraphifyEnv,
|
|
11
|
+
readAgentVersion,
|
|
12
|
+
refreshSkillsAfterCheckout,
|
|
13
|
+
runPreReadyBinds
|
|
14
|
+
} from "./chunk-SR66HQKB.js";
|
|
15
|
+
import "./chunk-JG3VMWRQ.js";
|
|
12
16
|
import {
|
|
13
17
|
GitPrepJob,
|
|
14
18
|
defaultGit,
|
|
15
19
|
ensureDir,
|
|
16
|
-
redactToken,
|
|
17
20
|
reportBootMilestone
|
|
18
21
|
} from "./chunk-GL2DIQEQ.js";
|
|
19
22
|
import "./chunk-W4LZ7R6Z.js";
|
|
@@ -29,7 +32,7 @@ import {
|
|
|
29
32
|
|
|
30
33
|
// src/boot/index.ts
|
|
31
34
|
import { spawn } from "child_process";
|
|
32
|
-
import { statSync as
|
|
35
|
+
import { statSync as statSync3 } from "fs";
|
|
33
36
|
import { hostname as osHostname } from "os";
|
|
34
37
|
|
|
35
38
|
// src/boot/bundle.ts
|
|
@@ -159,32 +162,6 @@ function buildChildEnv(opts) {
|
|
|
159
162
|
return child;
|
|
160
163
|
}
|
|
161
164
|
|
|
162
|
-
// src/boot/graphify.ts
|
|
163
|
-
var USER_HOME_MOUNT = "/mnt/conveyor-users";
|
|
164
|
-
function computeGraphifyEnv(env, repoName, dirExists) {
|
|
165
|
-
if (env.CONVEYOR_GRAPHIFY_DISABLE === "1") {
|
|
166
|
-
return {};
|
|
167
|
-
}
|
|
168
|
-
const slug = env.CONVEYOR_GRAPHIFY_SLUG || repoName;
|
|
169
|
-
if (!slug) {
|
|
170
|
-
return {};
|
|
171
|
-
}
|
|
172
|
-
const primaryRoot = `${USER_HOME_MOUNT}/users/_shared/graphify`;
|
|
173
|
-
const legacyRoot = `${USER_HOME_MOUNT}/_shared/graphify`;
|
|
174
|
-
let sharedRoot = env.CONVEYOR_GRAPHIFY_SHARED_ROOT;
|
|
175
|
-
if (!sharedRoot) {
|
|
176
|
-
sharedRoot = dirExists(primaryRoot) || !dirExists(legacyRoot) ? primaryRoot : legacyRoot;
|
|
177
|
-
}
|
|
178
|
-
const dir = env.CONVEYOR_GRAPHIFY_DIR || `${sharedRoot}/${slug}/latest`;
|
|
179
|
-
const graph = env.CONVEYOR_GRAPHIFY_GRAPH || `${dir}/graph.json`;
|
|
180
|
-
return {
|
|
181
|
-
CONVEYOR_GRAPHIFY_SLUG: slug,
|
|
182
|
-
CONVEYOR_GRAPHIFY_SHARED_ROOT: sharedRoot,
|
|
183
|
-
CONVEYOR_GRAPHIFY_DIR: dir,
|
|
184
|
-
CONVEYOR_GRAPHIFY_GRAPH: graph
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
|
|
188
165
|
// src/boot/logger.ts
|
|
189
166
|
import { appendFileSync } from "fs";
|
|
190
167
|
var BOOTSTRAP_LOG_PATH = "/tmp/claudespace-bootstrap.log";
|
|
@@ -605,9 +582,9 @@ var SEED_GATES = {
|
|
|
605
582
|
}
|
|
606
583
|
};
|
|
607
584
|
var SEED_FABLE_OPTION = {
|
|
608
|
-
value: "claude-fable-5[1m]",
|
|
585
|
+
value: "claude-fable-5-1[1m]",
|
|
609
586
|
label: "Fable",
|
|
610
|
-
description: "Fable 5 - most capable for your hardest and longest-running tasks"
|
|
587
|
+
description: "Fable 5.1 - most capable for your hardest and longest-running tasks"
|
|
611
588
|
};
|
|
612
589
|
function isPlainObject(value) {
|
|
613
590
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -851,306 +828,10 @@ async function startWorkspaceSshd(exec, log, port = process.env.CONVEYOR_WORKSPA
|
|
|
851
828
|
}
|
|
852
829
|
}
|
|
853
830
|
|
|
854
|
-
// src/boot/workspace-extras.ts
|
|
855
|
-
import {
|
|
856
|
-
appendFileSync as appendFileSync3,
|
|
857
|
-
cpSync,
|
|
858
|
-
existsSync as existsSync3,
|
|
859
|
-
lstatSync as lstatSync2,
|
|
860
|
-
mkdirSync as mkdirSync3,
|
|
861
|
-
readdirSync as readdirSync2,
|
|
862
|
-
readFileSync as readFileSync2,
|
|
863
|
-
readlinkSync,
|
|
864
|
-
rmSync as rmSync2,
|
|
865
|
-
statSync as statSync3,
|
|
866
|
-
symlinkSync as symlinkSync2
|
|
867
|
-
} from "fs";
|
|
868
|
-
import { dirname as dirname2, join as join5 } from "path";
|
|
869
|
-
import { fileURLToPath } from "url";
|
|
870
|
-
function errText(err) {
|
|
871
|
-
return redactToken(err instanceof Error ? err.message : String(err));
|
|
872
|
-
}
|
|
873
|
-
function isDir2(path) {
|
|
874
|
-
try {
|
|
875
|
-
return statSync3(path).isDirectory();
|
|
876
|
-
} catch {
|
|
877
|
-
return false;
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
function isSymlink(path) {
|
|
881
|
-
try {
|
|
882
|
-
return lstatSync2(path).isSymbolicLink();
|
|
883
|
-
} catch {
|
|
884
|
-
return false;
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
var GRAPHIFY_BUNDLE_FILES = [
|
|
888
|
-
"graph.json",
|
|
889
|
-
"GRAPH_REPORT.md",
|
|
890
|
-
"manifest.json",
|
|
891
|
-
".graphify_analysis.json",
|
|
892
|
-
".graphify_labels.json",
|
|
893
|
-
"publish-manifest.json",
|
|
894
|
-
"cost.json"
|
|
895
|
-
];
|
|
896
|
-
function bindGraphifyBundle(workspace, graphifyEnv, log) {
|
|
897
|
-
const slug = graphifyEnv.CONVEYOR_GRAPHIFY_SLUG;
|
|
898
|
-
const sourceDir = graphifyEnv.CONVEYOR_GRAPHIFY_DIR;
|
|
899
|
-
const graphFile = graphifyEnv.CONVEYOR_GRAPHIFY_GRAPH;
|
|
900
|
-
if (!slug || !sourceDir || !graphFile) return;
|
|
901
|
-
if (!existsSync3(graphFile)) {
|
|
902
|
-
log.info(`[boot] Graphify bundle not found for '${slug}' at ${sourceDir}`);
|
|
903
|
-
return;
|
|
904
|
-
}
|
|
905
|
-
const targetDir = join5(workspace, "graphify-out");
|
|
906
|
-
try {
|
|
907
|
-
mkdirSync3(targetDir, { recursive: true });
|
|
908
|
-
} catch {
|
|
909
|
-
log.warn(`[boot] WARN: unable to create graphify-out at ${targetDir}`);
|
|
910
|
-
return;
|
|
911
|
-
}
|
|
912
|
-
for (const rel of GRAPHIFY_BUNDLE_FILES) {
|
|
913
|
-
const source = join5(sourceDir, rel);
|
|
914
|
-
const target = join5(targetDir, rel);
|
|
915
|
-
if (!existsSync3(source)) continue;
|
|
916
|
-
if (existsSync3(target) || isSymlink(target)) continue;
|
|
917
|
-
try {
|
|
918
|
-
symlinkSync2(source, target);
|
|
919
|
-
} catch {
|
|
920
|
-
}
|
|
921
|
-
}
|
|
922
|
-
log.info(`[boot] Bound graphify bundle '${slug}' into ${targetDir}`);
|
|
923
|
-
}
|
|
924
|
-
async function ensureGrimoireSubmodule(workspace, githubToken, git, log) {
|
|
925
|
-
try {
|
|
926
|
-
if (!existsSync3(join5(workspace, ".gitmodules"))) return;
|
|
927
|
-
let paths = "";
|
|
928
|
-
try {
|
|
929
|
-
({ stdout: paths } = await git(
|
|
930
|
-
["config", "--file", ".gitmodules", "--get-regexp", String.raw`submodule\..*\.path`],
|
|
931
|
-
{ cwd: workspace, timeoutMs: 1e4 }
|
|
932
|
-
));
|
|
933
|
-
} catch {
|
|
934
|
-
return;
|
|
935
|
-
}
|
|
936
|
-
if (!paths.split("\n").some((line) => line.trim().endsWith(".claude/grimoire"))) return;
|
|
937
|
-
if (isDir2(join5(workspace, ".claude", "grimoire", "skills"))) return;
|
|
938
|
-
if (!githubToken) {
|
|
939
|
-
log.warn("[boot] WARN: grimoire submodule absent and no token to fetch it");
|
|
940
|
-
return;
|
|
941
|
-
}
|
|
942
|
-
try {
|
|
943
|
-
await git(
|
|
944
|
-
[
|
|
945
|
-
"-c",
|
|
946
|
-
`url.https://x-access-token:${githubToken}@github.com/.insteadOf=https://github.com/`,
|
|
947
|
-
"submodule",
|
|
948
|
-
"update",
|
|
949
|
-
"--init",
|
|
950
|
-
".claude/grimoire"
|
|
951
|
-
],
|
|
952
|
-
{ cwd: workspace, timeoutMs: 3e5 }
|
|
953
|
-
);
|
|
954
|
-
log.info("[boot] Initialized grimoire submodule");
|
|
955
|
-
} catch (err) {
|
|
956
|
-
log.warn(
|
|
957
|
-
`[boot] WARN: grimoire submodule init failed (baked pods may lack rc-* skills): ${errText(err)}`
|
|
958
|
-
);
|
|
959
|
-
}
|
|
960
|
-
} catch (err) {
|
|
961
|
-
log.warn(`[boot] WARN: grimoire submodule check failed: ${errText(err)}`);
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
function excludeLinkedSkills(workspace, names, log) {
|
|
965
|
-
if (names.length === 0) return;
|
|
966
|
-
const infoDir = join5(workspace, ".git", "info");
|
|
967
|
-
if (!isDir2(join5(workspace, ".git"))) return;
|
|
968
|
-
try {
|
|
969
|
-
mkdirSync3(infoDir, { recursive: true });
|
|
970
|
-
const excludePath = join5(infoDir, "exclude");
|
|
971
|
-
const existing = existsSync3(excludePath) ? readFileSync2(excludePath, "utf8") : "";
|
|
972
|
-
const missing = names.map((name) => `.claude/skills/${name}`).filter((line) => !existing.split("\n").includes(line));
|
|
973
|
-
if (missing.length === 0) return;
|
|
974
|
-
const prefix = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
|
|
975
|
-
appendFileSync3(excludePath, `${prefix}${missing.join("\n")}
|
|
976
|
-
`);
|
|
977
|
-
} catch (err) {
|
|
978
|
-
log.warn(`[boot] WARN: unable to exclude grimoire skill links: ${errText(err)}`);
|
|
979
|
-
}
|
|
980
|
-
}
|
|
981
|
-
function symlinkTargetsGrimoire(path) {
|
|
982
|
-
try {
|
|
983
|
-
return readlinkSync(path).includes(join5("grimoire", "skills"));
|
|
984
|
-
} catch {
|
|
985
|
-
return false;
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
|
-
function linkGrimoireSkills(workspace, log) {
|
|
989
|
-
const sourceDir = join5(workspace, ".claude", "grimoire", "skills");
|
|
990
|
-
const targetDir = join5(workspace, ".claude", "skills");
|
|
991
|
-
if (!isDir2(sourceDir)) return;
|
|
992
|
-
try {
|
|
993
|
-
mkdirSync3(targetDir, { recursive: true });
|
|
994
|
-
} catch {
|
|
995
|
-
log.warn(`[boot] WARN: unable to create ${targetDir}; skipping grimoire skill links`);
|
|
996
|
-
return;
|
|
997
|
-
}
|
|
998
|
-
const linkedNames = [];
|
|
999
|
-
let names = [];
|
|
1000
|
-
try {
|
|
1001
|
-
names = readdirSync2(sourceDir);
|
|
1002
|
-
} catch {
|
|
1003
|
-
return;
|
|
1004
|
-
}
|
|
1005
|
-
for (const name of names) {
|
|
1006
|
-
if (!isDir2(join5(sourceDir, name))) continue;
|
|
1007
|
-
const target = join5(targetDir, name);
|
|
1008
|
-
if (existsSync3(target) && !isSymlink(target)) {
|
|
1009
|
-
log.warn(`[boot] WARN: ${target} exists and is not a symlink; skipping`);
|
|
1010
|
-
continue;
|
|
1011
|
-
}
|
|
1012
|
-
if (isSymlink(target) && !symlinkTargetsGrimoire(target)) continue;
|
|
1013
|
-
try {
|
|
1014
|
-
rmSync2(target, { force: true });
|
|
1015
|
-
symlinkSync2(join5("..", "grimoire", "skills", name), target);
|
|
1016
|
-
linkedNames.push(name);
|
|
1017
|
-
} catch {
|
|
1018
|
-
}
|
|
1019
|
-
}
|
|
1020
|
-
excludeLinkedSkills(workspace, linkedNames, log);
|
|
1021
|
-
log.info(`[boot] Linked ${linkedNames.length} grimoire skills into ${targetDir}`);
|
|
1022
|
-
}
|
|
1023
|
-
function bundledSkillsDir(moduleUrl = import.meta.url) {
|
|
1024
|
-
try {
|
|
1025
|
-
const dir = join5(dirname2(fileURLToPath(moduleUrl)), "..", "skills");
|
|
1026
|
-
return isDir2(dir) ? dir : null;
|
|
1027
|
-
} catch {
|
|
1028
|
-
return null;
|
|
1029
|
-
}
|
|
1030
|
-
}
|
|
1031
|
-
function materializeBundledSkills(workspace, log, sourceDirOverride) {
|
|
1032
|
-
const sourceDir = sourceDirOverride === void 0 ? bundledSkillsDir() : sourceDirOverride;
|
|
1033
|
-
if (!sourceDir) {
|
|
1034
|
-
log.warn(
|
|
1035
|
-
"[boot] WARN: no bundled skills payload in this agent build. Cloud modes that invoke a skill will have no workflow to follow. This is a packaging fault (tsup copySkillsPayload did not run), not a workspace problem."
|
|
1036
|
-
);
|
|
1037
|
-
return;
|
|
1038
|
-
}
|
|
1039
|
-
const targetDir = join5(workspace, ".claude", "skills");
|
|
1040
|
-
try {
|
|
1041
|
-
mkdirSync3(targetDir, { recursive: true });
|
|
1042
|
-
} catch {
|
|
1043
|
-
log.warn(`[boot] WARN: unable to create ${targetDir}; skipping bundled skills`);
|
|
1044
|
-
return;
|
|
1045
|
-
}
|
|
1046
|
-
const copied = [];
|
|
1047
|
-
let names = [];
|
|
1048
|
-
try {
|
|
1049
|
-
names = readdirSync2(sourceDir);
|
|
1050
|
-
} catch {
|
|
1051
|
-
return;
|
|
1052
|
-
}
|
|
1053
|
-
for (const name of names) {
|
|
1054
|
-
if (!isDir2(join5(sourceDir, name))) continue;
|
|
1055
|
-
const target = join5(targetDir, name);
|
|
1056
|
-
if (existsSync3(target) || isSymlink(target)) continue;
|
|
1057
|
-
try {
|
|
1058
|
-
cpSync(join5(sourceDir, name), target, { recursive: true, dereference: true });
|
|
1059
|
-
copied.push(name);
|
|
1060
|
-
} catch {
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
excludeLinkedSkills(workspace, copied, log);
|
|
1064
|
-
log.info(`[boot] Materialized ${copied.length} bundled skills into ${targetDir}`);
|
|
1065
|
-
}
|
|
1066
|
-
async function neutralizeGrimoirePointer(workspace, git, log) {
|
|
1067
|
-
if (!existsSync3(join5(workspace, ".claude", "grimoire"))) return;
|
|
1068
|
-
try {
|
|
1069
|
-
await git(["update-index", "--assume-unchanged", ".claude/grimoire"], {
|
|
1070
|
-
cwd: workspace,
|
|
1071
|
-
timeoutMs: 1e4
|
|
1072
|
-
});
|
|
1073
|
-
log.info("[boot] Marked .claude/grimoire assume-unchanged (submodule pointer drift is noise)");
|
|
1074
|
-
} catch (err) {
|
|
1075
|
-
log.warn(`[boot] WARN: grimoire assume-unchanged failed: ${errText(err)}`);
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1078
|
-
function parseReferenceRepos(refsJson) {
|
|
1079
|
-
let parsed;
|
|
1080
|
-
try {
|
|
1081
|
-
parsed = JSON.parse(refsJson);
|
|
1082
|
-
} catch {
|
|
1083
|
-
return [];
|
|
1084
|
-
}
|
|
1085
|
-
if (!Array.isArray(parsed)) return [];
|
|
1086
|
-
const refs = [];
|
|
1087
|
-
for (const entry of parsed) {
|
|
1088
|
-
if (typeof entry !== "object" || entry === null) continue;
|
|
1089
|
-
const raw = entry;
|
|
1090
|
-
const str = (key) => typeof raw[key] === "string" ? raw[key] : "";
|
|
1091
|
-
const ref = {
|
|
1092
|
-
slug: str("slug"),
|
|
1093
|
-
owner: str("owner"),
|
|
1094
|
-
name: str("name"),
|
|
1095
|
-
branch: str("branch") || "main",
|
|
1096
|
-
token: str("token")
|
|
1097
|
-
};
|
|
1098
|
-
if (ref.token && ref.slug && ref.owner && ref.name) refs.push(ref);
|
|
1099
|
-
}
|
|
1100
|
-
return refs;
|
|
1101
|
-
}
|
|
1102
|
-
async function runPreReadyBinds(workspace, bundle, git, log) {
|
|
1103
|
-
const graphifyEnv = computeGraphifyEnv(process.env, bundle.gitPlan.repoName, isDir2);
|
|
1104
|
-
bindGraphifyBundle(workspace, graphifyEnv, log);
|
|
1105
|
-
await ensureGrimoireSubmodule(workspace, bundle.githubToken ?? "", git, log);
|
|
1106
|
-
linkGrimoireSkills(workspace, log);
|
|
1107
|
-
materializeBundledSkills(workspace, log);
|
|
1108
|
-
await neutralizeGrimoirePointer(workspace, git, log);
|
|
1109
|
-
}
|
|
1110
|
-
async function cloneReferenceRepos(refsJson, git, log, referencesDir = "/workspaces/references") {
|
|
1111
|
-
if (!refsJson) return;
|
|
1112
|
-
const refs = parseReferenceRepos(refsJson);
|
|
1113
|
-
if (refs.length === 0) return;
|
|
1114
|
-
try {
|
|
1115
|
-
mkdirSync3(referencesDir, { recursive: true });
|
|
1116
|
-
} catch {
|
|
1117
|
-
return;
|
|
1118
|
-
}
|
|
1119
|
-
for (const ref of refs) {
|
|
1120
|
-
const dest = join5(referencesDir, ref.slug);
|
|
1121
|
-
if (existsSync3(join5(dest, ".git"))) continue;
|
|
1122
|
-
try {
|
|
1123
|
-
await git(
|
|
1124
|
-
[
|
|
1125
|
-
"clone",
|
|
1126
|
-
"--depth",
|
|
1127
|
-
"1",
|
|
1128
|
-
"--single-branch",
|
|
1129
|
-
"--branch",
|
|
1130
|
-
ref.branch,
|
|
1131
|
-
`https://x-access-token:${ref.token}@github.com/${ref.owner}/${ref.name}.git`,
|
|
1132
|
-
dest
|
|
1133
|
-
],
|
|
1134
|
-
{ timeoutMs: 6e5 }
|
|
1135
|
-
);
|
|
1136
|
-
try {
|
|
1137
|
-
await git(
|
|
1138
|
-
["remote", "set-url", "origin", `https://github.com/${ref.owner}/${ref.name}.git`],
|
|
1139
|
-
{ cwd: dest, timeoutMs: 1e4 }
|
|
1140
|
-
);
|
|
1141
|
-
} catch {
|
|
1142
|
-
}
|
|
1143
|
-
log.info(`[boot] cloned reference ${ref.slug} (${ref.owner}/${ref.name}@${ref.branch})`);
|
|
1144
|
-
} catch {
|
|
1145
|
-
log.warn(`[boot] WARN: reference clone failed: ${ref.slug}`);
|
|
1146
|
-
}
|
|
1147
|
-
}
|
|
1148
|
-
}
|
|
1149
|
-
|
|
1150
831
|
// src/boot/workbench-boot-deps.ts
|
|
1151
832
|
var WORKSPACE_DIR = "/workspaces/repo";
|
|
1152
833
|
var HOME_DIR = "/home/conveyor";
|
|
1153
|
-
var
|
|
834
|
+
var USER_HOME_MOUNT = "/mnt/conveyor-users";
|
|
1154
835
|
function sleep(ms) {
|
|
1155
836
|
return new Promise((resolve) => {
|
|
1156
837
|
setTimeout(resolve, ms);
|
|
@@ -1183,6 +864,14 @@ function defaultWorkbenchBootDeps() {
|
|
|
1183
864
|
}),
|
|
1184
865
|
bindsBeforeReady: (ctx, bundle) => runPreReadyBinds(WORKSPACE_DIR, bundle, defaultGit, ctx.log),
|
|
1185
866
|
cloneReferences: (ctx, bundle) => cloneReferenceRepos(bundle.envVars?.REFERENCE_REPOS_JSON, defaultGit, ctx.log),
|
|
867
|
+
refreshSkills: async (ctx) => {
|
|
868
|
+
const { filled, shadowed, stale } = await refreshSkillsAfterCheckout(
|
|
869
|
+
WORKSPACE_DIR,
|
|
870
|
+
defaultGit,
|
|
871
|
+
ctx.log
|
|
872
|
+
);
|
|
873
|
+
return { t: "refreshSkills", filled, shadowed, stale };
|
|
874
|
+
},
|
|
1186
875
|
ensureWorkspaceDir: (ctx) => {
|
|
1187
876
|
ensureDir(WORKSPACE_DIR);
|
|
1188
877
|
ctx.log.info(`[boot] ensured workspace dir ${WORKSPACE_DIR}`);
|
|
@@ -1190,7 +879,7 @@ function defaultWorkbenchBootDeps() {
|
|
|
1190
879
|
wireHome: (ctx) => {
|
|
1191
880
|
void wireUserHome({
|
|
1192
881
|
home: HOME_DIR,
|
|
1193
|
-
userHomeMount:
|
|
882
|
+
userHomeMount: USER_HOME_MOUNT,
|
|
1194
883
|
userId: ctx.childEnv?.CONVEYOR_USER_ID,
|
|
1195
884
|
projectId: ctx.childEnv?.CONVEYOR_PROJECT_ID ?? ctx.childEnv?.PROJECT_ID,
|
|
1196
885
|
sharedDir: process.env.CONVEYOR_SHARED_DIR,
|
|
@@ -1239,6 +928,7 @@ async function runWorkbenchBoot(ctx, overrides = {}) {
|
|
|
1239
928
|
token: ctx.bootstrapToken,
|
|
1240
929
|
version: readAgentVersion() ?? "unknown",
|
|
1241
930
|
getGitStatus: () => toGitStatusFrame(job.status),
|
|
931
|
+
refreshSkills: () => deps.refreshSkills(ctx),
|
|
1242
932
|
oomWatchdog: oomWatchdogOptionsFromEnv(ctx.log)
|
|
1243
933
|
});
|
|
1244
934
|
ctx.log.info("[boot] step=startDaemon listen socket up (startupProbe gate open)");
|
|
@@ -1261,7 +951,7 @@ async function runWorkbenchBoot(ctx, overrides = {}) {
|
|
|
1261
951
|
|
|
1262
952
|
// src/boot/index.ts
|
|
1263
953
|
var HOME_DIR2 = "/home/conveyor";
|
|
1264
|
-
var
|
|
954
|
+
var USER_HOME_MOUNT2 = "/mnt/conveyor-users";
|
|
1265
955
|
function defaultBootDeps() {
|
|
1266
956
|
return {
|
|
1267
957
|
fetchFn: fetch,
|
|
@@ -1272,7 +962,7 @@ function defaultBootDeps() {
|
|
|
1272
962
|
exec: defaultExec,
|
|
1273
963
|
dirExists: (path) => {
|
|
1274
964
|
try {
|
|
1275
|
-
return
|
|
965
|
+
return statSync3(path).isDirectory();
|
|
1276
966
|
} catch {
|
|
1277
967
|
return false;
|
|
1278
968
|
}
|
|
@@ -1349,7 +1039,7 @@ function agentBootSteps(deps = defaultBootDeps(), signal = new AbortController()
|
|
|
1349
1039
|
if (ctx.bundle) {
|
|
1350
1040
|
void wireUserHome({
|
|
1351
1041
|
home: HOME_DIR2,
|
|
1352
|
-
userHomeMount:
|
|
1042
|
+
userHomeMount: USER_HOME_MOUNT2,
|
|
1353
1043
|
userId: ctx.childEnv?.CONVEYOR_USER_ID,
|
|
1354
1044
|
projectId: ctx.childEnv?.CONVEYOR_PROJECT_ID ?? ctx.childEnv?.PROJECT_ID,
|
|
1355
1045
|
sharedDir: process.env.CONVEYOR_SHARED_DIR,
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
readWorkspaceBytes,
|
|
6
6
|
statWorkspacePath,
|
|
7
7
|
workspacePathExists
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-APP6Y2D7.js";
|
|
9
9
|
import {
|
|
10
10
|
reportBootMilestone
|
|
11
11
|
} from "./chunk-GL2DIQEQ.js";
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from "./chunk-W4LZ7R6Z.js";
|
|
17
17
|
import {
|
|
18
18
|
getWorkbenchClient
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-TOTCEWJD.js";
|
|
20
20
|
import {
|
|
21
21
|
workbenchEnabled
|
|
22
22
|
} from "./chunk-KMB3BU4S.js";
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
import {
|
|
21
21
|
WorkbenchError,
|
|
22
22
|
getWorkbenchClient
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-TOTCEWJD.js";
|
|
24
24
|
import {
|
|
25
25
|
workbenchEnabled
|
|
26
26
|
} from "./chunk-KMB3BU4S.js";
|
|
@@ -2548,6 +2548,7 @@ export {
|
|
|
2548
2548
|
statWorkspacePath,
|
|
2549
2549
|
workspacePathExists,
|
|
2550
2550
|
GIT_TIMEOUT_MS,
|
|
2551
|
+
git,
|
|
2551
2552
|
updateRemoteToken,
|
|
2552
2553
|
verifyGitCredential,
|
|
2553
2554
|
forceFreshMintBlocked,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadPtySpawn
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-JG3VMWRQ.js";
|
|
4
4
|
import {
|
|
5
5
|
terminateProcessGroup
|
|
6
6
|
} from "./chunk-W4LZ7R6Z.js";
|
|
@@ -99,6 +99,19 @@ function handleConnection(socket, opts, liveOps) {
|
|
|
99
99
|
});
|
|
100
100
|
socket.on("data", (chunk) => reader.push(chunk));
|
|
101
101
|
}
|
|
102
|
+
async function runRefreshSkills(socket, opts) {
|
|
103
|
+
const empty = { t: "refreshSkills", filled: [], shadowed: [], stale: [] };
|
|
104
|
+
try {
|
|
105
|
+
writeFrame(socket, await opts.refreshSkills?.() ?? empty);
|
|
106
|
+
} catch (err) {
|
|
107
|
+
writeFrame(socket, {
|
|
108
|
+
t: "error",
|
|
109
|
+
message: err instanceof Error ? err.message : String(err),
|
|
110
|
+
code: errCode(err)
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
socket.end();
|
|
114
|
+
}
|
|
102
115
|
function dispatch(socket, req, sink, opts, liveOps) {
|
|
103
116
|
if (!req || typeof req !== "object" || !timingSafeTokenEqual(req.token ?? "", opts.token)) {
|
|
104
117
|
writeFrame(socket, { t: "error", message: "unauthorized", code: "unauthorized" });
|
|
@@ -114,6 +127,9 @@ function dispatch(socket, req, sink, opts, liveOps) {
|
|
|
114
127
|
writeFrame(socket, opts.getGitStatus?.() ?? { t: "gitStatus", state: "ready" });
|
|
115
128
|
socket.end();
|
|
116
129
|
return;
|
|
130
|
+
case "refreshSkills":
|
|
131
|
+
void runRefreshSkills(socket, opts);
|
|
132
|
+
return;
|
|
117
133
|
case "exec":
|
|
118
134
|
runExec(socket, req, sink, liveOps);
|
|
119
135
|
return;
|
|
@@ -200,7 +200,7 @@ async function loadPtySpawn() {
|
|
|
200
200
|
async function resolvePtySpawn() {
|
|
201
201
|
const { workbenchEnabled } = await import("./mode-ZJSOSLGU.js");
|
|
202
202
|
if (!workbenchEnabled()) return loadPtySpawn();
|
|
203
|
-
const { getWorkbenchClient } = await import("./client-
|
|
203
|
+
const { getWorkbenchClient } = await import("./client-6AUPKKMV.js");
|
|
204
204
|
return (file, args, options) => getWorkbenchClient().spawnPty(file, args, options);
|
|
205
205
|
}
|
|
206
206
|
function sessionTempBase() {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
mapChatHistory,
|
|
3
|
-
readAgentVersion
|
|
4
|
-
|
|
3
|
+
readAgentVersion,
|
|
4
|
+
refreshSkillsAfterCheckout
|
|
5
|
+
} from "./chunk-SR66HQKB.js";
|
|
5
6
|
import {
|
|
6
7
|
MAX_BETWEEN_TURN_BUFFER,
|
|
7
8
|
MAX_DIAGNOSTIC_OUTPUT,
|
|
@@ -28,7 +29,7 @@ import {
|
|
|
28
29
|
spawnOptionsFingerprint,
|
|
29
30
|
transcriptSize,
|
|
30
31
|
turnOptionsFrom
|
|
31
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-JG3VMWRQ.js";
|
|
32
33
|
import {
|
|
33
34
|
AgentConnection,
|
|
34
35
|
CodespacePortVisibility,
|
|
@@ -44,6 +45,7 @@ import {
|
|
|
44
45
|
forceFreshCooldownNotice,
|
|
45
46
|
forceFreshMintBlocked,
|
|
46
47
|
getCurrentBranch,
|
|
48
|
+
git,
|
|
47
49
|
hasUncommittedChanges,
|
|
48
50
|
hasUnpushedCommits,
|
|
49
51
|
pushToOrigin,
|
|
@@ -57,7 +59,7 @@ import {
|
|
|
57
59
|
statWorkspacePath,
|
|
58
60
|
updateRemoteToken,
|
|
59
61
|
verifyGitCredential
|
|
60
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-APP6Y2D7.js";
|
|
61
63
|
import {
|
|
62
64
|
registerBootMilestoneSocketFallback,
|
|
63
65
|
reportBootMilestone
|
|
@@ -78,7 +80,7 @@ import {
|
|
|
78
80
|
} from "./chunk-IA45XHOA.js";
|
|
79
81
|
import {
|
|
80
82
|
getWorkbenchClient
|
|
81
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-TOTCEWJD.js";
|
|
82
84
|
import {
|
|
83
85
|
workbenchEnabled
|
|
84
86
|
} from "./chunk-KMB3BU4S.js";
|
|
@@ -232,7 +234,7 @@ var EXTERNAL_AGENT_MESSAGE_SOURCE = "external_agent";
|
|
|
232
234
|
var DEFAULT_SONNET_MODEL = "claude-sonnet-5";
|
|
233
235
|
var DEFAULT_OPUS_MODEL = "claude-opus-5";
|
|
234
236
|
var DEFAULT_HAIKU_MODEL = "claude-haiku-4-5-20251001";
|
|
235
|
-
var FABLE_MODEL = "claude-fable-5";
|
|
237
|
+
var FABLE_MODEL = "claude-fable-5-1";
|
|
236
238
|
var PREVIOUS_SONNET_MODEL = "claude-sonnet-4-6";
|
|
237
239
|
var PREVIOUS_OPUS_MODEL = "claude-opus-4-8";
|
|
238
240
|
var PTY_STREAM_PORT_BASE = 7420;
|
|
@@ -1938,7 +1940,7 @@ var ANTHROPIC_CATALOG = [
|
|
|
1938
1940
|
anthropicEntry(PREVIOUS_SONNET_MODEL, "Sonnet 4.6", 3, 15),
|
|
1939
1941
|
// The Haiku line (4.5 and older) predates the tuning surface and 400s on it.
|
|
1940
1942
|
anthropicEntry(DEFAULT_HAIKU_MODEL, "Haiku 4.5", 1, 5, { supportsEffort: false }),
|
|
1941
|
-
anthropicEntry(FABLE_MODEL, "Fable 5
|
|
1943
|
+
anthropicEntry(FABLE_MODEL, "Fable 5.1", 10, 50)
|
|
1942
1944
|
];
|
|
1943
1945
|
var HUMAN_PROSE_WRITING_STYLE = `## Writing style for humans
|
|
1944
1946
|
When you write prose a person will read \u2014 chat messages, plan updates, PR titles and bodies, PR review guides (the \`publish_review_guide\` overview and section explanations), review comments \u2014 follow these rules (based on ASD-STE100 Simplified Technical English):
|
|
@@ -4342,7 +4344,7 @@ function seedWorkspaceTrust(config, trustCwd) {
|
|
|
4342
4344
|
var FABLE_MODEL_OPTION = {
|
|
4343
4345
|
value: `${FABLE_MODEL}[1m]`,
|
|
4344
4346
|
label: "Fable",
|
|
4345
|
-
description: "Fable 5 - most capable for your hardest and longest-running tasks"
|
|
4347
|
+
description: "Fable 5.1 - most capable for your hardest and longest-running tasks"
|
|
4346
4348
|
};
|
|
4347
4349
|
function seedFableModelOption(config) {
|
|
4348
4350
|
const cache = Array.isArray(config.additionalModelOptionsCache) ? config.additionalModelOptionsCache : [];
|
|
@@ -15188,6 +15190,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
15188
15190
|
process.stderr.write("[conveyor-agent] WARNING: task-branch checkout failed\n");
|
|
15189
15191
|
}
|
|
15190
15192
|
if (ok) void reportBootMilestone({ key: "branch_ready" });
|
|
15193
|
+
await this.refreshSkillsForCheckout();
|
|
15191
15194
|
}
|
|
15192
15195
|
if (!this.stopped) {
|
|
15193
15196
|
this.lifecycle.startGitFlush();
|
|
@@ -15247,6 +15250,40 @@ var SessionRunner = class _SessionRunner {
|
|
|
15247
15250
|
await this.run();
|
|
15248
15251
|
}
|
|
15249
15252
|
// ── Core loop ──────────────────────────────────────────────────────
|
|
15253
|
+
/**
|
|
15254
|
+
* Re-run the skill floor against the tree `ensureOnTaskBranch` just produced.
|
|
15255
|
+
*
|
|
15256
|
+
* Split-mode pods keep the repo in the WORKBENCH container, so this routes
|
|
15257
|
+
* over the launcher: running it in-process here would materialize skills into
|
|
15258
|
+
* the AGENT container's own copy of /workspaces/repo — still on the base
|
|
15259
|
+
* branch, already complete — and look like it worked while Claude spawned on
|
|
15260
|
+
* the untouched real tree. Codespaces/local (no workbench) run it directly.
|
|
15261
|
+
*
|
|
15262
|
+
* Best-effort by design: a failure warns and boot continues, exactly like the
|
|
15263
|
+
* pre-ready binds it repeats.
|
|
15264
|
+
*/
|
|
15265
|
+
async refreshSkillsForCheckout() {
|
|
15266
|
+
const write = (msg) => void process.stderr.write(`[conveyor-agent] ${msg}
|
|
15267
|
+
`);
|
|
15268
|
+
try {
|
|
15269
|
+
const result = workbenchEnabled() ? await getWorkbenchClient().refreshSkills() : await refreshSkillsAfterCheckout(
|
|
15270
|
+
this.config.workspaceDir,
|
|
15271
|
+
async (args, opts) => ({
|
|
15272
|
+
stdout: await git(opts?.cwd ?? this.config.workspaceDir, args, opts?.timeoutMs)
|
|
15273
|
+
}),
|
|
15274
|
+
{ info: write, warn: write, error: write }
|
|
15275
|
+
);
|
|
15276
|
+
const { filled, shadowed, stale } = result;
|
|
15277
|
+
if (filled.length + shadowed.length + stale.length === 0) return;
|
|
15278
|
+
write(
|
|
15279
|
+
`post-checkout skill refresh: filled=[${filled.join(", ")}] shadowed=[${shadowed.join(", ")}] unusable=[${stale.join(", ")}]`
|
|
15280
|
+
);
|
|
15281
|
+
} catch (err) {
|
|
15282
|
+
write(
|
|
15283
|
+
`WARNING: post-checkout skill refresh failed: ${err instanceof Error ? err.message : String(err)}`
|
|
15284
|
+
);
|
|
15285
|
+
}
|
|
15286
|
+
}
|
|
15250
15287
|
// oxlint-disable-next-line complexity -- dormant idle paths add branches but are tightly coupled to the loop
|
|
15251
15288
|
async coreLoop() {
|
|
15252
15289
|
while (!this.stopped) {
|
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
import {
|
|
2
|
+
redactToken
|
|
3
|
+
} from "./chunk-GL2DIQEQ.js";
|
|
4
|
+
|
|
5
|
+
// src/boot/graphify.ts
|
|
6
|
+
var USER_HOME_MOUNT = "/mnt/conveyor-users";
|
|
7
|
+
function computeGraphifyEnv(env, repoName, dirExists) {
|
|
8
|
+
if (env.CONVEYOR_GRAPHIFY_DISABLE === "1") {
|
|
9
|
+
return {};
|
|
10
|
+
}
|
|
11
|
+
const slug = env.CONVEYOR_GRAPHIFY_SLUG || repoName;
|
|
12
|
+
if (!slug) {
|
|
13
|
+
return {};
|
|
14
|
+
}
|
|
15
|
+
const primaryRoot = `${USER_HOME_MOUNT}/users/_shared/graphify`;
|
|
16
|
+
const legacyRoot = `${USER_HOME_MOUNT}/_shared/graphify`;
|
|
17
|
+
let sharedRoot = env.CONVEYOR_GRAPHIFY_SHARED_ROOT;
|
|
18
|
+
if (!sharedRoot) {
|
|
19
|
+
sharedRoot = dirExists(primaryRoot) || !dirExists(legacyRoot) ? primaryRoot : legacyRoot;
|
|
20
|
+
}
|
|
21
|
+
const dir = env.CONVEYOR_GRAPHIFY_DIR || `${sharedRoot}/${slug}/latest`;
|
|
22
|
+
const graph = env.CONVEYOR_GRAPHIFY_GRAPH || `${dir}/graph.json`;
|
|
23
|
+
return {
|
|
24
|
+
CONVEYOR_GRAPHIFY_SLUG: slug,
|
|
25
|
+
CONVEYOR_GRAPHIFY_SHARED_ROOT: sharedRoot,
|
|
26
|
+
CONVEYOR_GRAPHIFY_DIR: dir,
|
|
27
|
+
CONVEYOR_GRAPHIFY_GRAPH: graph
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// src/runner/session-runner-helpers.ts
|
|
32
|
+
import { readFileSync } from "fs";
|
|
33
|
+
import { dirname, join } from "path";
|
|
34
|
+
import { fileURLToPath } from "url";
|
|
35
|
+
function mapChatHistory(messages) {
|
|
36
|
+
if (!messages) return [];
|
|
37
|
+
return messages.map((m) => ({
|
|
38
|
+
id: m.id,
|
|
39
|
+
role: m.role ?? "user",
|
|
40
|
+
content: m.content ?? "",
|
|
41
|
+
userId: m.userId,
|
|
42
|
+
userName: m.user?.name ?? void 0,
|
|
43
|
+
createdAt: m.createdAt,
|
|
44
|
+
...m.source ? { source: m.source } : {},
|
|
45
|
+
...m.files && m.files.length > 0 ? {
|
|
46
|
+
files: m.files.map((f) => ({
|
|
47
|
+
fileId: f.id,
|
|
48
|
+
fileName: f.fileName,
|
|
49
|
+
mimeType: f.mimeType,
|
|
50
|
+
fileSize: f.fileSize,
|
|
51
|
+
downloadUrl: f.downloadUrl ?? "",
|
|
52
|
+
content: f.content,
|
|
53
|
+
contentEncoding: f.contentEncoding
|
|
54
|
+
}))
|
|
55
|
+
} : {}
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
function readAgentVersion() {
|
|
59
|
+
try {
|
|
60
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
61
|
+
for (const rel of ["../package.json", "../../package.json"]) {
|
|
62
|
+
try {
|
|
63
|
+
const pkg = JSON.parse(readFileSync(join(here, rel), "utf-8"));
|
|
64
|
+
if (pkg.version) return pkg.version;
|
|
65
|
+
} catch {
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
} catch {
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/boot/workspace-extras.ts
|
|
74
|
+
import {
|
|
75
|
+
appendFileSync,
|
|
76
|
+
cpSync,
|
|
77
|
+
existsSync,
|
|
78
|
+
lstatSync,
|
|
79
|
+
mkdirSync,
|
|
80
|
+
readdirSync,
|
|
81
|
+
readFileSync as readFileSync2,
|
|
82
|
+
readlinkSync,
|
|
83
|
+
renameSync,
|
|
84
|
+
rmSync,
|
|
85
|
+
statSync,
|
|
86
|
+
symlinkSync
|
|
87
|
+
} from "fs";
|
|
88
|
+
import { dirname as dirname2, join as join2 } from "path";
|
|
89
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
90
|
+
function errText(err) {
|
|
91
|
+
return redactToken(err instanceof Error ? err.message : String(err));
|
|
92
|
+
}
|
|
93
|
+
function isDir(path) {
|
|
94
|
+
try {
|
|
95
|
+
return statSync(path).isDirectory();
|
|
96
|
+
} catch {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function isSymlink(path) {
|
|
101
|
+
try {
|
|
102
|
+
return lstatSync(path).isSymbolicLink();
|
|
103
|
+
} catch {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function isDanglingSymlink(path) {
|
|
108
|
+
return !existsSync(path) && isSymlink(path);
|
|
109
|
+
}
|
|
110
|
+
var GRAPHIFY_BUNDLE_FILES = [
|
|
111
|
+
"graph.json",
|
|
112
|
+
"GRAPH_REPORT.md",
|
|
113
|
+
"manifest.json",
|
|
114
|
+
".graphify_analysis.json",
|
|
115
|
+
".graphify_labels.json",
|
|
116
|
+
"publish-manifest.json",
|
|
117
|
+
"cost.json"
|
|
118
|
+
];
|
|
119
|
+
function bindGraphifyBundle(workspace, graphifyEnv, log) {
|
|
120
|
+
const slug = graphifyEnv.CONVEYOR_GRAPHIFY_SLUG;
|
|
121
|
+
const sourceDir = graphifyEnv.CONVEYOR_GRAPHIFY_DIR;
|
|
122
|
+
const graphFile = graphifyEnv.CONVEYOR_GRAPHIFY_GRAPH;
|
|
123
|
+
if (!slug || !sourceDir || !graphFile) return;
|
|
124
|
+
if (!existsSync(graphFile)) {
|
|
125
|
+
log.info(`[boot] Graphify bundle not found for '${slug}' at ${sourceDir}`);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const targetDir = join2(workspace, "graphify-out");
|
|
129
|
+
try {
|
|
130
|
+
mkdirSync(targetDir, { recursive: true });
|
|
131
|
+
} catch {
|
|
132
|
+
log.warn(`[boot] WARN: unable to create graphify-out at ${targetDir}`);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
for (const rel of GRAPHIFY_BUNDLE_FILES) {
|
|
136
|
+
const source = join2(sourceDir, rel);
|
|
137
|
+
const target = join2(targetDir, rel);
|
|
138
|
+
if (!existsSync(source)) continue;
|
|
139
|
+
if (existsSync(target) || isSymlink(target)) continue;
|
|
140
|
+
try {
|
|
141
|
+
symlinkSync(source, target);
|
|
142
|
+
} catch {
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
log.info(`[boot] Bound graphify bundle '${slug}' into ${targetDir}`);
|
|
146
|
+
}
|
|
147
|
+
async function ensureGrimoireSubmodule(workspace, githubToken, git, log) {
|
|
148
|
+
try {
|
|
149
|
+
if (!existsSync(join2(workspace, ".gitmodules"))) return;
|
|
150
|
+
let paths = "";
|
|
151
|
+
try {
|
|
152
|
+
({ stdout: paths } = await git(
|
|
153
|
+
["config", "--file", ".gitmodules", "--get-regexp", String.raw`submodule\..*\.path`],
|
|
154
|
+
{ cwd: workspace, timeoutMs: 1e4 }
|
|
155
|
+
));
|
|
156
|
+
} catch {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (!paths.split("\n").some((line) => line.trim().endsWith(".claude/grimoire"))) return;
|
|
160
|
+
if (isDir(join2(workspace, ".claude", "grimoire", "skills"))) return;
|
|
161
|
+
if (!githubToken) {
|
|
162
|
+
log.warn("[boot] WARN: grimoire submodule absent and no token to fetch it");
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
try {
|
|
166
|
+
await git(
|
|
167
|
+
[
|
|
168
|
+
"-c",
|
|
169
|
+
`url.https://x-access-token:${githubToken}@github.com/.insteadOf=https://github.com/`,
|
|
170
|
+
"submodule",
|
|
171
|
+
"update",
|
|
172
|
+
"--init",
|
|
173
|
+
".claude/grimoire"
|
|
174
|
+
],
|
|
175
|
+
{ cwd: workspace, timeoutMs: 3e5 }
|
|
176
|
+
);
|
|
177
|
+
log.info("[boot] Initialized grimoire submodule");
|
|
178
|
+
} catch (err) {
|
|
179
|
+
log.warn(
|
|
180
|
+
`[boot] WARN: grimoire submodule init failed (baked pods may lack rc-* skills): ${errText(err)}`
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
} catch (err) {
|
|
184
|
+
log.warn(`[boot] WARN: grimoire submodule check failed: ${errText(err)}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
function excludeLinkedSkills(workspace, names, log) {
|
|
188
|
+
if (names.length === 0) return;
|
|
189
|
+
const infoDir = join2(workspace, ".git", "info");
|
|
190
|
+
if (!isDir(join2(workspace, ".git"))) return;
|
|
191
|
+
try {
|
|
192
|
+
mkdirSync(infoDir, { recursive: true });
|
|
193
|
+
const excludePath = join2(infoDir, "exclude");
|
|
194
|
+
const existing = existsSync(excludePath) ? readFileSync2(excludePath, "utf8") : "";
|
|
195
|
+
const missing = names.map((name) => `.claude/skills/${name}`).filter((line) => !existing.split("\n").includes(line));
|
|
196
|
+
if (missing.length === 0) return;
|
|
197
|
+
const prefix = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
|
|
198
|
+
appendFileSync(excludePath, `${prefix}${missing.join("\n")}
|
|
199
|
+
`);
|
|
200
|
+
} catch (err) {
|
|
201
|
+
log.warn(`[boot] WARN: unable to exclude grimoire skill links: ${errText(err)}`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
function symlinkTargetsGrimoire(path) {
|
|
205
|
+
try {
|
|
206
|
+
return readlinkSync(path).includes(join2("grimoire", "skills"));
|
|
207
|
+
} catch {
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
function linkGrimoireSkills(workspace, log) {
|
|
212
|
+
const sourceDir = join2(workspace, ".claude", "grimoire", "skills");
|
|
213
|
+
const targetDir = join2(workspace, ".claude", "skills");
|
|
214
|
+
if (!isDir(sourceDir)) return;
|
|
215
|
+
try {
|
|
216
|
+
mkdirSync(targetDir, { recursive: true });
|
|
217
|
+
} catch {
|
|
218
|
+
log.warn(`[boot] WARN: unable to create ${targetDir}; skipping grimoire skill links`);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
const linkedNames = [];
|
|
222
|
+
let names = [];
|
|
223
|
+
try {
|
|
224
|
+
names = readdirSync(sourceDir);
|
|
225
|
+
} catch {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
for (const name of names) {
|
|
229
|
+
if (!isDir(join2(sourceDir, name))) continue;
|
|
230
|
+
const target = join2(targetDir, name);
|
|
231
|
+
if (existsSync(target) && !isSymlink(target)) {
|
|
232
|
+
log.warn(`[boot] WARN: ${target} exists and is not a symlink; skipping`);
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
if (isSymlink(target) && !symlinkTargetsGrimoire(target)) continue;
|
|
236
|
+
try {
|
|
237
|
+
rmSync(target, { force: true });
|
|
238
|
+
symlinkSync(join2("..", "grimoire", "skills", name), target);
|
|
239
|
+
linkedNames.push(name);
|
|
240
|
+
} catch {
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
excludeLinkedSkills(workspace, linkedNames, log);
|
|
244
|
+
log.info(`[boot] Linked ${linkedNames.length} grimoire skills into ${targetDir}`);
|
|
245
|
+
}
|
|
246
|
+
function bundledSkillsDir(moduleUrl = import.meta.url) {
|
|
247
|
+
try {
|
|
248
|
+
const dir = join2(dirname2(fileURLToPath2(moduleUrl)), "..", "skills");
|
|
249
|
+
return isDir(dir) ? dir : null;
|
|
250
|
+
} catch {
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
var EMPTY_MATERIALIZE = { filled: [], shadowed: [], stale: [] };
|
|
255
|
+
async function hideShadowedPins(workspace, names, git, log) {
|
|
256
|
+
if (names.length === 0) return;
|
|
257
|
+
const paths = names.map((name) => `.claude/skills/${name}`);
|
|
258
|
+
if (!git) {
|
|
259
|
+
log.warn(
|
|
260
|
+
`[boot] WARN: replaced skill pin(s) ${names.join(", ")} stay visible to git (no git runner supplied)`
|
|
261
|
+
);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
try {
|
|
265
|
+
await git(["update-index", "--assume-unchanged", ...paths], {
|
|
266
|
+
cwd: workspace,
|
|
267
|
+
timeoutMs: 1e4
|
|
268
|
+
});
|
|
269
|
+
} catch (err) {
|
|
270
|
+
log.warn(`[boot] WARN: unable to hide replaced skill pins from git: ${errText(err)}`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
function readlinkOr(path) {
|
|
274
|
+
try {
|
|
275
|
+
return readlinkSync(path);
|
|
276
|
+
} catch {
|
|
277
|
+
return "unknown target";
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
function fillOneSkill(sourceDir, targetDir, name, log) {
|
|
281
|
+
if (!isDir(join2(sourceDir, name))) return null;
|
|
282
|
+
const target = join2(targetDir, name);
|
|
283
|
+
const dangling = isDanglingSymlink(target);
|
|
284
|
+
if (!dangling && (existsSync(target) || isSymlink(target))) return null;
|
|
285
|
+
if (!dangling) {
|
|
286
|
+
try {
|
|
287
|
+
cpSync(join2(sourceDir, name), target, { recursive: true, dereference: true });
|
|
288
|
+
return "filled";
|
|
289
|
+
} catch {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
log.warn(
|
|
294
|
+
`[boot] WARN: repo skill '${name}' pointed at a missing target (${readlinkOr(target)}); shadowing it with this agent build's bundled copy`
|
|
295
|
+
);
|
|
296
|
+
const staging = join2(targetDir, `.${name}.conveyor-staging`);
|
|
297
|
+
try {
|
|
298
|
+
rmSync(staging, { recursive: true, force: true });
|
|
299
|
+
cpSync(join2(sourceDir, name), staging, { recursive: true, dereference: true });
|
|
300
|
+
rmSync(target, { force: true });
|
|
301
|
+
renameSync(staging, target);
|
|
302
|
+
return "shadowed";
|
|
303
|
+
} catch (err) {
|
|
304
|
+
try {
|
|
305
|
+
rmSync(staging, { recursive: true, force: true });
|
|
306
|
+
} catch {
|
|
307
|
+
}
|
|
308
|
+
log.warn(
|
|
309
|
+
`[boot] WARN: could not replace dangling skill pin '${name}' (${errText(err)}) \u2014 it stays unusable in this session's skill registry`
|
|
310
|
+
);
|
|
311
|
+
return "stale";
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
function reportStalePins(targetDir, bundled, log) {
|
|
315
|
+
let present = [];
|
|
316
|
+
try {
|
|
317
|
+
present = readdirSync(targetDir);
|
|
318
|
+
} catch {
|
|
319
|
+
return [];
|
|
320
|
+
}
|
|
321
|
+
const stale = present.filter(
|
|
322
|
+
(name) => !bundled.has(name) && isDanglingSymlink(join2(targetDir, name))
|
|
323
|
+
);
|
|
324
|
+
for (const name of stale) {
|
|
325
|
+
log.warn(
|
|
326
|
+
`[boot] WARN: repo skill '${name}' is a dangling pin and this agent build has no bundled copy \u2014 it will not appear in the session's skill registry`
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
return stale;
|
|
330
|
+
}
|
|
331
|
+
async function materializeBundledSkills(workspace, log, sourceDirOverride, git) {
|
|
332
|
+
const sourceDir = sourceDirOverride === void 0 ? bundledSkillsDir() : sourceDirOverride;
|
|
333
|
+
if (!sourceDir) {
|
|
334
|
+
log.warn(
|
|
335
|
+
"[boot] WARN: no bundled skills payload in this agent build. Cloud modes that invoke a skill will have no workflow to follow. This is a packaging fault (tsup copySkillsPayload did not run), not a workspace problem."
|
|
336
|
+
);
|
|
337
|
+
return EMPTY_MATERIALIZE;
|
|
338
|
+
}
|
|
339
|
+
const targetDir = join2(workspace, ".claude", "skills");
|
|
340
|
+
try {
|
|
341
|
+
mkdirSync(targetDir, { recursive: true });
|
|
342
|
+
} catch {
|
|
343
|
+
log.warn(`[boot] WARN: unable to create ${targetDir}; skipping bundled skills`);
|
|
344
|
+
return EMPTY_MATERIALIZE;
|
|
345
|
+
}
|
|
346
|
+
const filled = [];
|
|
347
|
+
const shadowed = [];
|
|
348
|
+
const unreplaced = [];
|
|
349
|
+
let names = [];
|
|
350
|
+
try {
|
|
351
|
+
names = readdirSync(sourceDir);
|
|
352
|
+
} catch {
|
|
353
|
+
return EMPTY_MATERIALIZE;
|
|
354
|
+
}
|
|
355
|
+
for (const name of names) {
|
|
356
|
+
const outcome = fillOneSkill(sourceDir, targetDir, name, log);
|
|
357
|
+
if (outcome === "filled") filled.push(name);
|
|
358
|
+
else if (outcome === "shadowed") shadowed.push(name);
|
|
359
|
+
else if (outcome === "stale") unreplaced.push(name);
|
|
360
|
+
}
|
|
361
|
+
const stale = [...unreplaced, ...reportStalePins(targetDir, new Set(names), log)];
|
|
362
|
+
excludeLinkedSkills(workspace, [...filled, ...shadowed], log);
|
|
363
|
+
await hideShadowedPins(workspace, shadowed, git, log);
|
|
364
|
+
log.info(
|
|
365
|
+
`[boot] Materialized ${filled.length} bundled skills into ${targetDir}` + (shadowed.length > 0 ? `; replaced ${shadowed.length} dangling pin(s)` : "") + (stale.length > 0 ? `; ${stale.length} dangling pin(s) left unusable` : "")
|
|
366
|
+
);
|
|
367
|
+
return { filled, shadowed, stale };
|
|
368
|
+
}
|
|
369
|
+
function refreshSkillsAfterCheckout(workspace, git, log, sourceDirOverride) {
|
|
370
|
+
linkGrimoireSkills(workspace, log);
|
|
371
|
+
return materializeBundledSkills(workspace, log, sourceDirOverride, git);
|
|
372
|
+
}
|
|
373
|
+
async function neutralizeGrimoirePointer(workspace, git, log) {
|
|
374
|
+
if (!existsSync(join2(workspace, ".claude", "grimoire"))) return;
|
|
375
|
+
try {
|
|
376
|
+
await git(["update-index", "--assume-unchanged", ".claude/grimoire"], {
|
|
377
|
+
cwd: workspace,
|
|
378
|
+
timeoutMs: 1e4
|
|
379
|
+
});
|
|
380
|
+
log.info("[boot] Marked .claude/grimoire assume-unchanged (submodule pointer drift is noise)");
|
|
381
|
+
} catch (err) {
|
|
382
|
+
log.warn(`[boot] WARN: grimoire assume-unchanged failed: ${errText(err)}`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
function parseReferenceRepos(refsJson) {
|
|
386
|
+
let parsed;
|
|
387
|
+
try {
|
|
388
|
+
parsed = JSON.parse(refsJson);
|
|
389
|
+
} catch {
|
|
390
|
+
return [];
|
|
391
|
+
}
|
|
392
|
+
if (!Array.isArray(parsed)) return [];
|
|
393
|
+
const refs = [];
|
|
394
|
+
for (const entry of parsed) {
|
|
395
|
+
if (typeof entry !== "object" || entry === null) continue;
|
|
396
|
+
const raw = entry;
|
|
397
|
+
const str = (key) => typeof raw[key] === "string" ? raw[key] : "";
|
|
398
|
+
const ref = {
|
|
399
|
+
slug: str("slug"),
|
|
400
|
+
owner: str("owner"),
|
|
401
|
+
name: str("name"),
|
|
402
|
+
branch: str("branch") || "main",
|
|
403
|
+
token: str("token")
|
|
404
|
+
};
|
|
405
|
+
if (ref.token && ref.slug && ref.owner && ref.name) refs.push(ref);
|
|
406
|
+
}
|
|
407
|
+
return refs;
|
|
408
|
+
}
|
|
409
|
+
async function runPreReadyBinds(workspace, bundle, git, log) {
|
|
410
|
+
const graphifyEnv = computeGraphifyEnv(process.env, bundle.gitPlan.repoName, isDir);
|
|
411
|
+
bindGraphifyBundle(workspace, graphifyEnv, log);
|
|
412
|
+
await ensureGrimoireSubmodule(workspace, bundle.githubToken ?? "", git, log);
|
|
413
|
+
linkGrimoireSkills(workspace, log);
|
|
414
|
+
await materializeBundledSkills(workspace, log, void 0, git);
|
|
415
|
+
await neutralizeGrimoirePointer(workspace, git, log);
|
|
416
|
+
}
|
|
417
|
+
async function cloneReferenceRepos(refsJson, git, log, referencesDir = "/workspaces/references") {
|
|
418
|
+
if (!refsJson) return;
|
|
419
|
+
const refs = parseReferenceRepos(refsJson);
|
|
420
|
+
if (refs.length === 0) return;
|
|
421
|
+
try {
|
|
422
|
+
mkdirSync(referencesDir, { recursive: true });
|
|
423
|
+
} catch {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
for (const ref of refs) {
|
|
427
|
+
const dest = join2(referencesDir, ref.slug);
|
|
428
|
+
if (existsSync(join2(dest, ".git"))) continue;
|
|
429
|
+
try {
|
|
430
|
+
await git(
|
|
431
|
+
[
|
|
432
|
+
"clone",
|
|
433
|
+
"--depth",
|
|
434
|
+
"1",
|
|
435
|
+
"--single-branch",
|
|
436
|
+
"--branch",
|
|
437
|
+
ref.branch,
|
|
438
|
+
`https://x-access-token:${ref.token}@github.com/${ref.owner}/${ref.name}.git`,
|
|
439
|
+
dest
|
|
440
|
+
],
|
|
441
|
+
{ timeoutMs: 6e5 }
|
|
442
|
+
);
|
|
443
|
+
try {
|
|
444
|
+
await git(
|
|
445
|
+
["remote", "set-url", "origin", `https://github.com/${ref.owner}/${ref.name}.git`],
|
|
446
|
+
{ cwd: dest, timeoutMs: 1e4 }
|
|
447
|
+
);
|
|
448
|
+
} catch {
|
|
449
|
+
}
|
|
450
|
+
log.info(`[boot] cloned reference ${ref.slug} (${ref.owner}/${ref.name}@${ref.branch})`);
|
|
451
|
+
} catch {
|
|
452
|
+
log.warn(`[boot] WARN: reference clone failed: ${ref.slug}`);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export {
|
|
458
|
+
computeGraphifyEnv,
|
|
459
|
+
refreshSkillsAfterCheckout,
|
|
460
|
+
runPreReadyBinds,
|
|
461
|
+
cloneReferenceRepos,
|
|
462
|
+
mapChatHistory,
|
|
463
|
+
readAgentVersion
|
|
464
|
+
};
|
|
@@ -138,6 +138,24 @@ var WorkbenchClient = class {
|
|
|
138
138
|
);
|
|
139
139
|
});
|
|
140
140
|
}
|
|
141
|
+
/** Ask the workbench — which owns the repo filesystem in split mode — to
|
|
142
|
+
* re-run the skill floor after the agent's authoritative task-branch
|
|
143
|
+
* checkout. A daemon without a provider answers an empty result. */
|
|
144
|
+
refreshSkills() {
|
|
145
|
+
return new Promise((resolve, reject) => {
|
|
146
|
+
let result = null;
|
|
147
|
+
this.open(
|
|
148
|
+
{ op: "refreshSkills" },
|
|
149
|
+
(frame) => {
|
|
150
|
+
if (frame.t === "refreshSkills") result = frame;
|
|
151
|
+
},
|
|
152
|
+
(error) => {
|
|
153
|
+
if (result) resolve(result);
|
|
154
|
+
else reject(error ?? new WorkbenchError("connection closed before refreshSkills"));
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
141
159
|
/** Mirrors setup/commands.ts runSetupCommand (shell form, streamed output,
|
|
142
160
|
* abort → graceful term-group kill, non-zero exit rejects). */
|
|
143
161
|
runSetupCommand(cmd, cwd, onOutput, signal) {
|
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
WorkspaceCommandSupervisor,
|
|
8
8
|
startWorkspaceCommandsAfterConnect,
|
|
9
9
|
stopWorkspaceCommands
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-43XITDZP.js";
|
|
11
11
|
import {
|
|
12
12
|
DEFAULT_SONNET_MODEL,
|
|
13
13
|
PtyHarness,
|
|
@@ -27,13 +27,13 @@ import {
|
|
|
27
27
|
resolveTuiKindFromEnv,
|
|
28
28
|
runUsageProbe,
|
|
29
29
|
sampleKeyUsage
|
|
30
|
-
} from "./chunk-
|
|
31
|
-
import "./chunk-
|
|
30
|
+
} from "./chunk-SKTCDL4K.js";
|
|
31
|
+
import "./chunk-SR66HQKB.js";
|
|
32
32
|
import {
|
|
33
33
|
inheritedEnv,
|
|
34
34
|
resolvePtySpawn,
|
|
35
35
|
sessionTempBase
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-JG3VMWRQ.js";
|
|
37
37
|
import {
|
|
38
38
|
AgentConnection,
|
|
39
39
|
CodespacePortVisibility,
|
|
@@ -44,12 +44,12 @@ import {
|
|
|
44
44
|
createServiceLogger,
|
|
45
45
|
fetchBootstrap,
|
|
46
46
|
loadConveyorConfig
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-APP6Y2D7.js";
|
|
48
48
|
import "./chunk-GL2DIQEQ.js";
|
|
49
49
|
import "./chunk-W4LZ7R6Z.js";
|
|
50
50
|
import "./chunk-7P6QZHXZ.js";
|
|
51
51
|
import "./chunk-IA45XHOA.js";
|
|
52
|
-
import "./chunk-
|
|
52
|
+
import "./chunk-TOTCEWJD.js";
|
|
53
53
|
import "./chunk-KMB3BU4S.js";
|
|
54
54
|
import "./chunk-6Q6LQBWO.js";
|
|
55
55
|
|
|
@@ -1201,7 +1201,7 @@ function wireSpawnChildren(mode, connection, supervisors, logger7) {
|
|
|
1201
1201
|
|
|
1202
1202
|
// src/cli.ts
|
|
1203
1203
|
if (process.argv[2] === "boot") {
|
|
1204
|
-
const { runBoot } = await import("./boot-
|
|
1204
|
+
const { runBoot } = await import("./boot-ZE6BM7L2.js");
|
|
1205
1205
|
process.exit(await runBoot(process.argv.slice(3)));
|
|
1206
1206
|
}
|
|
1207
1207
|
if (isLegacyEntrypointLaunch(process.env)) {
|
|
@@ -1303,7 +1303,7 @@ process.on("unhandledRejection", (reason) => {
|
|
|
1303
1303
|
process.exit(1);
|
|
1304
1304
|
});
|
|
1305
1305
|
if (process.env.CONVEYOR_MODE === "workbench") {
|
|
1306
|
-
const { startWorkbenchServer } = await import("./server-
|
|
1306
|
+
const { startWorkbenchServer } = await import("./server-2IZBKD3Q.js");
|
|
1307
1307
|
const { oomWatchdogOptionsFromEnv } = await import("./oom-watchdog-PAC5OJJG.js");
|
|
1308
1308
|
const { DEFAULT_WORKBENCH_PORT } = await import("./protocol-QBCYO4GI.js");
|
|
1309
1309
|
const port = Number(process.env.CONVEYOR_WORKBENCH_PORT) || DEFAULT_WORKBENCH_PORT;
|
|
@@ -1454,7 +1454,7 @@ if (!RUNNER_MODES.includes(CONVEYOR_MODE)) {
|
|
|
1454
1454
|
process.exit(1);
|
|
1455
1455
|
}
|
|
1456
1456
|
if (CONVEYOR_MODE === "serving") {
|
|
1457
|
-
const { runServingSession } = await import("./serve-boot-
|
|
1457
|
+
const { runServingSession } = await import("./serve-boot-ESZKFN5M.js");
|
|
1458
1458
|
exitContext.runnerMode = "serving";
|
|
1459
1459
|
exitContext.sessionId = process.env.CONVEYOR_SESSION_ID ?? exitContext.sessionId;
|
|
1460
1460
|
const outcome = await runServingSession({
|
package/dist/index.d.ts
CHANGED
|
@@ -851,6 +851,19 @@ declare class SessionRunner {
|
|
|
851
851
|
run(): Promise<void>;
|
|
852
852
|
/** Convenience wrapper: connect() then run(). */
|
|
853
853
|
start(): Promise<void>;
|
|
854
|
+
/**
|
|
855
|
+
* Re-run the skill floor against the tree `ensureOnTaskBranch` just produced.
|
|
856
|
+
*
|
|
857
|
+
* Split-mode pods keep the repo in the WORKBENCH container, so this routes
|
|
858
|
+
* over the launcher: running it in-process here would materialize skills into
|
|
859
|
+
* the AGENT container's own copy of /workspaces/repo — still on the base
|
|
860
|
+
* branch, already complete — and look like it worked while Claude spawned on
|
|
861
|
+
* the untouched real tree. Codespaces/local (no workbench) run it directly.
|
|
862
|
+
*
|
|
863
|
+
* Best-effort by design: a failure warns and boot continues, exactly like the
|
|
864
|
+
* pre-ready binds it repeats.
|
|
865
|
+
*/
|
|
866
|
+
private refreshSkillsForCheckout;
|
|
854
867
|
private coreLoop;
|
|
855
868
|
/**
|
|
856
869
|
* Handle dormant-after-completed idle. Returns true if a critical message
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SessionRunner,
|
|
3
3
|
unshallowRepo
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-SKTCDL4K.js";
|
|
5
|
+
import "./chunk-SR66HQKB.js";
|
|
6
|
+
import "./chunk-JG3VMWRQ.js";
|
|
7
7
|
import {
|
|
8
8
|
AgentConnection,
|
|
9
9
|
GIT_TIMEOUT_MS,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
stageAndCommit,
|
|
18
18
|
updateRemoteToken,
|
|
19
19
|
workspacePathExists
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-APP6Y2D7.js";
|
|
21
21
|
import "./chunk-GL2DIQEQ.js";
|
|
22
22
|
import {
|
|
23
23
|
runAuthTokenCommand,
|
|
@@ -28,7 +28,7 @@ import "./chunk-7P6QZHXZ.js";
|
|
|
28
28
|
import "./chunk-IA45XHOA.js";
|
|
29
29
|
import {
|
|
30
30
|
getWorkbenchClient
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-TOTCEWJD.js";
|
|
32
32
|
import {
|
|
33
33
|
workbenchEnabled
|
|
34
34
|
} from "./chunk-KMB3BU4S.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
WorkspaceCommandSupervisor
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-43XITDZP.js";
|
|
4
4
|
import {
|
|
5
5
|
AgentConnection,
|
|
6
6
|
CodespacePortVisibility,
|
|
@@ -11,11 +11,11 @@ import {
|
|
|
11
11
|
createServiceLogger,
|
|
12
12
|
ensureOnTaskBranch,
|
|
13
13
|
loadConveyorConfig
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-APP6Y2D7.js";
|
|
15
15
|
import "./chunk-GL2DIQEQ.js";
|
|
16
16
|
import "./chunk-W4LZ7R6Z.js";
|
|
17
17
|
import "./chunk-IA45XHOA.js";
|
|
18
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-TOTCEWJD.js";
|
|
19
19
|
import "./chunk-KMB3BU4S.js";
|
|
20
20
|
import "./chunk-6Q6LQBWO.js";
|
|
21
21
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rallycry/conveyor-agent",
|
|
3
|
-
"version": "11.0.
|
|
3
|
+
"version": "11.0.8",
|
|
4
4
|
"description": "Conveyor Agent Runner v10 - PTY harness for the task chat (SDK harness for audit/project-chat). Agent-as-User architecture with BaseService patterns. Works locally too.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"typecheck": "tsgo --noEmit"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@anthropic-ai/claude-agent-sdk": "^0.3.
|
|
41
|
+
"@anthropic-ai/claude-agent-sdk": "^0.3.257",
|
|
42
42
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
43
43
|
"node-pty": "^1.0.0",
|
|
44
44
|
"socket.io-client": "^4.8.3",
|
package/dist/chunk-XORJ6SII.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
// src/runner/session-runner-helpers.ts
|
|
2
|
-
import { readFileSync } from "fs";
|
|
3
|
-
import { dirname, join } from "path";
|
|
4
|
-
import { fileURLToPath } from "url";
|
|
5
|
-
function mapChatHistory(messages) {
|
|
6
|
-
if (!messages) return [];
|
|
7
|
-
return messages.map((m) => ({
|
|
8
|
-
id: m.id,
|
|
9
|
-
role: m.role ?? "user",
|
|
10
|
-
content: m.content ?? "",
|
|
11
|
-
userId: m.userId,
|
|
12
|
-
userName: m.user?.name ?? void 0,
|
|
13
|
-
createdAt: m.createdAt,
|
|
14
|
-
...m.source ? { source: m.source } : {},
|
|
15
|
-
...m.files && m.files.length > 0 ? {
|
|
16
|
-
files: m.files.map((f) => ({
|
|
17
|
-
fileId: f.id,
|
|
18
|
-
fileName: f.fileName,
|
|
19
|
-
mimeType: f.mimeType,
|
|
20
|
-
fileSize: f.fileSize,
|
|
21
|
-
downloadUrl: f.downloadUrl ?? "",
|
|
22
|
-
content: f.content,
|
|
23
|
-
contentEncoding: f.contentEncoding
|
|
24
|
-
}))
|
|
25
|
-
} : {}
|
|
26
|
-
}));
|
|
27
|
-
}
|
|
28
|
-
function readAgentVersion() {
|
|
29
|
-
try {
|
|
30
|
-
const here = dirname(fileURLToPath(import.meta.url));
|
|
31
|
-
for (const rel of ["../package.json", "../../package.json"]) {
|
|
32
|
-
try {
|
|
33
|
-
const pkg = JSON.parse(readFileSync(join(here, rel), "utf-8"));
|
|
34
|
-
if (pkg.version) return pkg.version;
|
|
35
|
-
} catch {
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
} catch {
|
|
39
|
-
}
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export {
|
|
44
|
-
mapChatHistory,
|
|
45
|
-
readAgentVersion
|
|
46
|
-
};
|