agent-conveyor 0.1.19 → 0.1.20
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/README.md +21 -3
- package/dist/cli/typescript-runtime.js +202 -2
- package/dist/cli/typescript-runtime.js.map +1 -1
- package/package.json +2 -1
- package/plugin/agent-conveyor/plugin.json +15 -0
- package/plugin/agent-conveyor/skills/conveyor-check-status/SKILL.md +38 -0
- package/plugin/agent-conveyor/skills/conveyor-create-pair/SKILL.md +43 -0
- package/plugin/agent-conveyor/skills/conveyor-create-worker-set/SKILL.md +55 -0
package/README.md
CHANGED
|
@@ -154,18 +154,36 @@ The GitHub Pages version lives at
|
|
|
154
154
|
Use `node scripts/check-landing-page.mjs` for a docs-only desktop/mobile
|
|
155
155
|
screenshot gate; this does not run the full package release smoke.
|
|
156
156
|
|
|
157
|
+
### Codex Operator Plugin
|
|
158
|
+
|
|
159
|
+
Agent Conveyor also ships Codex-app-only operator scaffolding for visible
|
|
160
|
+
manager/worker sessions from any project. Install the package, then install
|
|
161
|
+
and inspect the plugin:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
npm install -g agent-conveyor
|
|
165
|
+
conveyor install-plugin
|
|
166
|
+
conveyor plugin-status
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
The per-project default ledger for operator sessions is
|
|
170
|
+
`.codex-workers/workerctl.db`. The initial included skills are
|
|
171
|
+
`conveyor-create-pair`, `conveyor-create-worker-set`, and
|
|
172
|
+
`conveyor-check-status`.
|
|
173
|
+
|
|
157
174
|
After install, the intended Codex app entry point is natural language. Open a
|
|
158
175
|
new Codex app session in the target repo and say:
|
|
159
176
|
|
|
160
177
|
```text
|
|
161
|
-
Use the
|
|
178
|
+
Use the conveyor-create-pair skill.
|
|
162
179
|
|
|
163
180
|
Set up a Codex app Ralph loop for issue CTL.
|
|
164
181
|
Require adversarial proof before another worker iteration.
|
|
165
182
|
```
|
|
166
183
|
|
|
167
|
-
|
|
168
|
-
|
|
184
|
+
For multiple workers, start with `Use the conveyor-create-worker-set skill`.
|
|
185
|
+
The installed plugin skill should call the `conveyor` CLI, choose names, create
|
|
186
|
+
the no-tmux binding with `create-disposable-binding`, point the worker at
|
|
169
187
|
`worker-inbox`, and use `loop-status` plus telemetry receipts before reporting
|
|
170
188
|
that the loop is ready. When the manager is itself running in the Codex app and
|
|
171
189
|
thread tools are available, the skill should first call `create_thread` for a
|
|
@@ -171,6 +171,15 @@ export function runTypescriptRuntimeCommand(options) {
|
|
|
171
171
|
if (parsed.command === "install-skills") {
|
|
172
172
|
return runInstallSkillsCommand(parsed, options);
|
|
173
173
|
}
|
|
174
|
+
if (parsed.command === "plugin-path") {
|
|
175
|
+
return runPluginPathCommand(parsed, options);
|
|
176
|
+
}
|
|
177
|
+
if (parsed.command === "plugin-status") {
|
|
178
|
+
return runPluginStatusCommand(parsed, options);
|
|
179
|
+
}
|
|
180
|
+
if (parsed.command === "install-plugin") {
|
|
181
|
+
return runInstallPluginCommand(parsed, options);
|
|
182
|
+
}
|
|
174
183
|
if (parsed.command === "bind") {
|
|
175
184
|
return runBindCommand(parsed, options);
|
|
176
185
|
}
|
|
@@ -1086,7 +1095,7 @@ function parseRuntimeArgs(args, env) {
|
|
|
1086
1095
|
index += 1;
|
|
1087
1096
|
}
|
|
1088
1097
|
else if (arg === "--codex-home") {
|
|
1089
|
-
if (command !== "install-skills") {
|
|
1098
|
+
if (command !== "install-skills" && command !== "install-plugin" && command !== "plugin-status" && command !== "plugin-path") {
|
|
1090
1099
|
return { command, enabled, error: "Unsupported TypeScript runtime option: --codex-home", explicit, flags, task };
|
|
1091
1100
|
}
|
|
1092
1101
|
const value = valueAfter(queue, index, arg);
|
|
@@ -6655,7 +6664,7 @@ function runInstallSkillsCommand(parsed, options) {
|
|
|
6655
6664
|
if (unsupported) {
|
|
6656
6665
|
return unsupportedRuntimeResult(parsed, unsupported);
|
|
6657
6666
|
}
|
|
6658
|
-
const codexHome =
|
|
6667
|
+
const codexHome = resolveCodexHome(parsed, options);
|
|
6659
6668
|
const skills = installableSkillSources();
|
|
6660
6669
|
const targets = skills.map((skill) => ({
|
|
6661
6670
|
name: skill.name,
|
|
@@ -6687,6 +6696,194 @@ function runInstallSkillsCommand(parsed, options) {
|
|
|
6687
6696
|
const lines = targets.map((target) => `${parsed.flags.dryRun ? "would install" : "installed"} ${target.name} skill in ${target.target}`);
|
|
6688
6697
|
return { exitCode: 0, handled: true, stdout: `${lines.join("\n")}\n` };
|
|
6689
6698
|
}
|
|
6699
|
+
const AGENT_CONVEYOR_PLUGIN_NAME = "agent-conveyor";
|
|
6700
|
+
const AGENT_CONVEYOR_PLUGIN_SKILLS = ["conveyor-create-pair", "conveyor-create-worker-set", "conveyor-check-status"];
|
|
6701
|
+
function resolveCodexHome(parsed, options) {
|
|
6702
|
+
return resolve(expandUserPath(parsed.flags.codexHome ?? options.env?.CODEX_HOME ?? join(homedir(), ".codex")));
|
|
6703
|
+
}
|
|
6704
|
+
function packageVersionFromRoot(packageRoot) {
|
|
6705
|
+
const packageJsonPath = join(packageRoot, "package.json");
|
|
6706
|
+
const parsed = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
6707
|
+
if (!isPlainRecord(parsed) || typeof parsed.version !== "string" || parsed.version.length === 0) {
|
|
6708
|
+
throw new Error(`Package version not found in ${packageJsonPath}.`);
|
|
6709
|
+
}
|
|
6710
|
+
return parsed.version;
|
|
6711
|
+
}
|
|
6712
|
+
function pluginPaths(parsed, options) {
|
|
6713
|
+
const codexHome = resolveCodexHome(parsed, options);
|
|
6714
|
+
const packageRoot = packageRootFromRuntimeModule();
|
|
6715
|
+
const packageVersion = packageVersionFromRoot(packageRoot);
|
|
6716
|
+
const pluginCacheRoot = join(codexHome, "plugins", "cache", AGENT_CONVEYOR_PLUGIN_NAME, AGENT_CONVEYOR_PLUGIN_NAME);
|
|
6717
|
+
return {
|
|
6718
|
+
codex_home: codexHome,
|
|
6719
|
+
package_root: packageRoot,
|
|
6720
|
+
plugin_cache_root: pluginCacheRoot,
|
|
6721
|
+
plugin_install_root: join(pluginCacheRoot, packageVersion),
|
|
6722
|
+
plugin_source: join(packageRoot, "plugin", AGENT_CONVEYOR_PLUGIN_NAME),
|
|
6723
|
+
skills_install_root: join(codexHome, "skills"),
|
|
6724
|
+
};
|
|
6725
|
+
}
|
|
6726
|
+
function readAgentConveyorPluginManifest(source) {
|
|
6727
|
+
const manifestPath = join(source, "plugin.json");
|
|
6728
|
+
const parsed = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
6729
|
+
if (!isPlainRecord(parsed)) {
|
|
6730
|
+
throw new Error(`Agent Conveyor plugin manifest must be a JSON object: ${manifestPath}`);
|
|
6731
|
+
}
|
|
6732
|
+
if (parsed.name !== AGENT_CONVEYOR_PLUGIN_NAME) {
|
|
6733
|
+
throw new Error(`Agent Conveyor plugin manifest name must be "${AGENT_CONVEYOR_PLUGIN_NAME}": ${manifestPath}`);
|
|
6734
|
+
}
|
|
6735
|
+
if (typeof parsed.version !== "string") {
|
|
6736
|
+
throw new Error(`Agent Conveyor plugin manifest is missing a string version: ${manifestPath}`);
|
|
6737
|
+
}
|
|
6738
|
+
return {
|
|
6739
|
+
name: parsed.name,
|
|
6740
|
+
version: parsed.version,
|
|
6741
|
+
skills: Array.isArray(parsed.skills) ? parsed.skills.filter((skill) => typeof skill === "string") : undefined,
|
|
6742
|
+
};
|
|
6743
|
+
}
|
|
6744
|
+
function assertPluginVersionMatchesPackage(manifest, packageVersion) {
|
|
6745
|
+
if (manifest.version !== packageVersion) {
|
|
6746
|
+
throw new Error(`Agent Conveyor plugin version ${manifest.version} does not match package version ${packageVersion}.`);
|
|
6747
|
+
}
|
|
6748
|
+
}
|
|
6749
|
+
function pluginSkillTargets(paths) {
|
|
6750
|
+
return AGENT_CONVEYOR_PLUGIN_SKILLS.map((name) => {
|
|
6751
|
+
const target = join(paths.skills_install_root, name);
|
|
6752
|
+
return {
|
|
6753
|
+
installed: existsSync(join(target, "SKILL.md")),
|
|
6754
|
+
name,
|
|
6755
|
+
source: join(paths.plugin_source, "skills", name),
|
|
6756
|
+
target,
|
|
6757
|
+
};
|
|
6758
|
+
});
|
|
6759
|
+
}
|
|
6760
|
+
function installedAgentConveyorPluginManifest(paths) {
|
|
6761
|
+
const manifestPath = join(paths.plugin_install_root, "plugin.json");
|
|
6762
|
+
if (!existsSync(manifestPath)) {
|
|
6763
|
+
return null;
|
|
6764
|
+
}
|
|
6765
|
+
const parsed = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
6766
|
+
if (!isPlainRecord(parsed) || parsed.name !== AGENT_CONVEYOR_PLUGIN_NAME || typeof parsed.version !== "string") {
|
|
6767
|
+
return null;
|
|
6768
|
+
}
|
|
6769
|
+
return {
|
|
6770
|
+
name: parsed.name,
|
|
6771
|
+
version: parsed.version,
|
|
6772
|
+
skills: Array.isArray(parsed.skills) ? parsed.skills.filter((skill) => typeof skill === "string") : undefined,
|
|
6773
|
+
};
|
|
6774
|
+
}
|
|
6775
|
+
function agentConveyorPluginStatus(parsed, options) {
|
|
6776
|
+
const paths = pluginPaths(parsed, options);
|
|
6777
|
+
const packageVersion = packageVersionFromRoot(paths.package_root);
|
|
6778
|
+
const manifest = readAgentConveyorPluginManifest(paths.plugin_source);
|
|
6779
|
+
const installedManifest = installedAgentConveyorPluginManifest(paths);
|
|
6780
|
+
const installedVersion = installedManifest?.version ?? null;
|
|
6781
|
+
const skills = pluginSkillTargets(paths);
|
|
6782
|
+
const installed = installedManifest !== null && skills.every((skill) => skill.installed);
|
|
6783
|
+
return {
|
|
6784
|
+
installed,
|
|
6785
|
+
installed_version: installedVersion,
|
|
6786
|
+
package_version: packageVersion,
|
|
6787
|
+
paths,
|
|
6788
|
+
plugin_version: manifest.version,
|
|
6789
|
+
skills,
|
|
6790
|
+
version_matches: installed && installedVersion === packageVersion && manifest.version === packageVersion,
|
|
6791
|
+
};
|
|
6792
|
+
}
|
|
6793
|
+
function unsupportedPluginOptions(parsed) {
|
|
6794
|
+
if (parsed.task !== null) {
|
|
6795
|
+
return `Unexpected argument: ${parsed.task}`;
|
|
6796
|
+
}
|
|
6797
|
+
return null;
|
|
6798
|
+
}
|
|
6799
|
+
function runPluginPathCommand(parsed, options) {
|
|
6800
|
+
const unsupported = unsupportedPluginOptions(parsed);
|
|
6801
|
+
if (unsupported) {
|
|
6802
|
+
return unsupportedRuntimeResult(parsed, unsupported);
|
|
6803
|
+
}
|
|
6804
|
+
const paths = pluginPaths(parsed, options);
|
|
6805
|
+
if (parsed.flags.json) {
|
|
6806
|
+
return jsonResult(paths);
|
|
6807
|
+
}
|
|
6808
|
+
return {
|
|
6809
|
+
exitCode: 0,
|
|
6810
|
+
handled: true,
|
|
6811
|
+
stdout: [
|
|
6812
|
+
`codex_home: ${paths.codex_home}`,
|
|
6813
|
+
`package_root: ${paths.package_root}`,
|
|
6814
|
+
`plugin_cache_root: ${paths.plugin_cache_root}`,
|
|
6815
|
+
`plugin_install_root: ${paths.plugin_install_root}`,
|
|
6816
|
+
`plugin_source: ${paths.plugin_source}`,
|
|
6817
|
+
`skills_install_root: ${paths.skills_install_root}`,
|
|
6818
|
+
"",
|
|
6819
|
+
].join("\n"),
|
|
6820
|
+
};
|
|
6821
|
+
}
|
|
6822
|
+
function runPluginStatusCommand(parsed, options) {
|
|
6823
|
+
const unsupported = unsupportedPluginOptions(parsed);
|
|
6824
|
+
if (unsupported) {
|
|
6825
|
+
return unsupportedRuntimeResult(parsed, unsupported);
|
|
6826
|
+
}
|
|
6827
|
+
const status = agentConveyorPluginStatus(parsed, options);
|
|
6828
|
+
if (parsed.flags.json) {
|
|
6829
|
+
return jsonResult(status);
|
|
6830
|
+
}
|
|
6831
|
+
const skillLines = status.skills.map((skill) => `skill ${skill.name}: ${skill.installed ? "installed" : "missing"}`);
|
|
6832
|
+
return {
|
|
6833
|
+
exitCode: 0,
|
|
6834
|
+
handled: true,
|
|
6835
|
+
stdout: [
|
|
6836
|
+
`installed: ${status.installed}`,
|
|
6837
|
+
`installed_version: ${status.installed_version ?? "none"}`,
|
|
6838
|
+
`package_version: ${status.package_version}`,
|
|
6839
|
+
`plugin_version: ${status.plugin_version}`,
|
|
6840
|
+
`version_matches: ${status.version_matches}`,
|
|
6841
|
+
...skillLines,
|
|
6842
|
+
"",
|
|
6843
|
+
].join("\n"),
|
|
6844
|
+
};
|
|
6845
|
+
}
|
|
6846
|
+
function runInstallPluginCommand(parsed, options) {
|
|
6847
|
+
const unsupported = unsupportedPluginOptions(parsed);
|
|
6848
|
+
if (unsupported) {
|
|
6849
|
+
return unsupportedRuntimeResult(parsed, unsupported);
|
|
6850
|
+
}
|
|
6851
|
+
const paths = pluginPaths(parsed, options);
|
|
6852
|
+
const packageVersion = packageVersionFromRoot(paths.package_root);
|
|
6853
|
+
const manifest = readAgentConveyorPluginManifest(paths.plugin_source);
|
|
6854
|
+
assertPluginVersionMatchesPackage(manifest, packageVersion);
|
|
6855
|
+
const skillTargets = pluginSkillTargets(paths);
|
|
6856
|
+
for (const target of skillTargets) {
|
|
6857
|
+
if (!existsSync(join(target.source, "SKILL.md"))) {
|
|
6858
|
+
throw new Error(`Agent Conveyor plugin skill not found: ${target.source}`);
|
|
6859
|
+
}
|
|
6860
|
+
}
|
|
6861
|
+
if (!parsed.flags.dryRun) {
|
|
6862
|
+
rmSync(paths.plugin_install_root, { force: true, recursive: true });
|
|
6863
|
+
mkdirSync(dirname(paths.plugin_install_root), { recursive: true });
|
|
6864
|
+
cpSync(paths.plugin_source, paths.plugin_install_root, { recursive: true });
|
|
6865
|
+
for (const target of skillTargets) {
|
|
6866
|
+
rmSync(target.target, { force: true, recursive: true });
|
|
6867
|
+
mkdirSync(dirname(target.target), { recursive: true });
|
|
6868
|
+
cpSync(target.source, target.target, { recursive: true });
|
|
6869
|
+
}
|
|
6870
|
+
}
|
|
6871
|
+
const status = agentConveyorPluginStatus(parsed, options);
|
|
6872
|
+
const payload = {
|
|
6873
|
+
...status,
|
|
6874
|
+
dry_run: parsed.flags.dryRun,
|
|
6875
|
+
installed: status.installed,
|
|
6876
|
+
installed_skills: parsed.flags.dryRun ? [] : skillTargets.map((target) => target.name),
|
|
6877
|
+
};
|
|
6878
|
+
if (parsed.flags.json) {
|
|
6879
|
+
return jsonResult(payload);
|
|
6880
|
+
}
|
|
6881
|
+
const lines = [
|
|
6882
|
+
`${parsed.flags.dryRun ? "would install" : "installed"} ${AGENT_CONVEYOR_PLUGIN_NAME} plugin in ${paths.plugin_install_root}`,
|
|
6883
|
+
...skillTargets.map((target) => `${parsed.flags.dryRun ? "would install" : "installed"} ${target.name} skill in ${target.target}`),
|
|
6884
|
+
];
|
|
6885
|
+
return { exitCode: 0, handled: true, stdout: `${lines.join("\n")}\n` };
|
|
6886
|
+
}
|
|
6690
6887
|
function dashboardLaunchPayload(parsed) {
|
|
6691
6888
|
const queryParams = new URLSearchParams();
|
|
6692
6889
|
if (parsed.flags.taskName) {
|
|
@@ -15486,6 +15683,9 @@ function isDefaultRuntimeCommand(command) {
|
|
|
15486
15683
|
|| command === "start-test"
|
|
15487
15684
|
|| command === "dashboard"
|
|
15488
15685
|
|| command === "install-skills"
|
|
15686
|
+
|| command === "install-plugin"
|
|
15687
|
+
|| command === "plugin-status"
|
|
15688
|
+
|| command === "plugin-path"
|
|
15489
15689
|
|| command === "replay"
|
|
15490
15690
|
|| command === "export-task"
|
|
15491
15691
|
|| command === "tasks"
|