@openape/apes 0.32.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js
CHANGED
|
@@ -1871,7 +1871,7 @@ mkdir -p "$HOME_DIR/.ssh" "$HOME_DIR/.config/apes"
|
|
|
1871
1871
|
cat > "$HOME_DIR/.ssh/id_ed25519" ${shHeredoc(privatePemForHeredoc.trimEnd())}
|
|
1872
1872
|
cat > "$HOME_DIR/.ssh/id_ed25519.pub" ${shHeredoc(`${input.publicKeySshLine}`)}
|
|
1873
1873
|
cat > "$HOME_DIR/.config/apes/auth.json" ${shHeredoc(input.authJson)}
|
|
1874
|
-
${claudeBlock}${claudeTokenBlock}${buildBridgeBlock(input.bridge)}${
|
|
1874
|
+
${claudeBlock}${claudeTokenBlock}${buildBridgeBlock(input.bridge)}${buildTroopBlock(input.troop)}
|
|
1875
1875
|
chown -R "$NAME:staff" "$HOME_DIR"
|
|
1876
1876
|
chmod 700 "$HOME_DIR/.ssh"
|
|
1877
1877
|
chmod 700 "$HOME_DIR/.config"
|
|
@@ -1884,7 +1884,7 @@ if [ -f "$HOME_DIR/.config/openape/claude-token.env" ]; then
|
|
|
1884
1884
|
fi
|
|
1885
1885
|
|
|
1886
1886
|
echo "OK $NAME uid=$NEXT_UID home=$HOME_DIR"
|
|
1887
|
-
${buildBridgeBootstrapBlock(input.bridge)}${
|
|
1887
|
+
${buildBridgeBootstrapBlock(input.bridge)}${buildTroopBootstrapBlock(input.troop)}`;
|
|
1888
1888
|
}
|
|
1889
1889
|
function buildBridgeBlock(bridge) {
|
|
1890
1890
|
if (!bridge) return "";
|
|
@@ -1906,7 +1906,7 @@ chmod 644 ${shQuote(bridge.plistPath)}
|
|
|
1906
1906
|
function buildBridgeBootstrapBlock(bridge) {
|
|
1907
1907
|
if (!bridge) return "";
|
|
1908
1908
|
return `
|
|
1909
|
-
echo "==> Installing bridge stack as
|
|
1909
|
+
echo "==> Installing bridge stack as \${NAME} via bun (one-time)\u2026"
|
|
1910
1910
|
su - "$NAME" -c '
|
|
1911
1911
|
set -euo pipefail
|
|
1912
1912
|
export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:$HOME/.bun/install/global/bin"
|
|
@@ -1921,28 +1921,28 @@ launchctl bootstrap system ${shQuote(bridge.plistPath)} || \\
|
|
|
1921
1921
|
echo "warn: bridge bootstrap into system domain failed; check ${bridge.plistPath}"
|
|
1922
1922
|
`;
|
|
1923
1923
|
}
|
|
1924
|
-
function
|
|
1925
|
-
if (!
|
|
1924
|
+
function buildTroopBlock(troop) {
|
|
1925
|
+
if (!troop) return "";
|
|
1926
1926
|
return `
|
|
1927
1927
|
mkdir -p "$HOME_DIR/Library/LaunchAgents" "$HOME_DIR/Library/Logs" "$HOME_DIR/.openape/agent/tasks"
|
|
1928
|
-
cat > ${shQuote(
|
|
1929
|
-
chmod 644 ${shQuote(
|
|
1928
|
+
cat > ${shQuote(troop.plistPath)} ${shHeredoc(troop.plistContent)}
|
|
1929
|
+
chmod 644 ${shQuote(troop.plistPath)}
|
|
1930
1930
|
`;
|
|
1931
1931
|
}
|
|
1932
|
-
function
|
|
1933
|
-
if (!
|
|
1932
|
+
function buildTroopBootstrapBlock(troop) {
|
|
1933
|
+
if (!troop) return "";
|
|
1934
1934
|
return `
|
|
1935
|
-
# Bootstrap the
|
|
1935
|
+
# Bootstrap the troop sync launchd into the agent's GUI domain so it
|
|
1936
1936
|
# starts firing every 5 minutes. RunAtLoad in the plist also kicks
|
|
1937
1937
|
# off an immediate first sync so the agent registers + appears in
|
|
1938
|
-
# the
|
|
1939
|
-
echo "==> Installing
|
|
1938
|
+
# the troop SP within seconds of spawn finishing.
|
|
1939
|
+
echo "==> Installing troop sync launchd as \${NAME}\u2026"
|
|
1940
1940
|
su - "$NAME" -c '
|
|
1941
1941
|
set -euo pipefail
|
|
1942
1942
|
NAME_UID="$(id -u)"
|
|
1943
|
-
launchctl bootout "gui/$NAME_UID/${
|
|
1944
|
-
launchctl bootstrap "gui/$NAME_UID" ${shQuote(
|
|
1945
|
-
echo "warn:
|
|
1943
|
+
launchctl bootout "gui/$NAME_UID/${troop.plistLabel}" 2>/dev/null || true
|
|
1944
|
+
launchctl bootstrap "gui/$NAME_UID" ${shQuote(troop.plistPath)} || \\
|
|
1945
|
+
echo "warn: troop sync bootstrap failed; run \\\`apes agents sync\\\` manually as $NAME to register at troop.openape.ai"
|
|
1946
1946
|
'
|
|
1947
1947
|
`;
|
|
1948
1948
|
}
|
|
@@ -2982,15 +2982,15 @@ var RpcSessionMap = class {
|
|
|
2982
2982
|
}
|
|
2983
2983
|
};
|
|
2984
2984
|
|
|
2985
|
-
// src/lib/
|
|
2986
|
-
var
|
|
2987
|
-
var
|
|
2988
|
-
constructor(
|
|
2989
|
-
this.
|
|
2985
|
+
// src/lib/troop-client.ts
|
|
2986
|
+
var DEFAULT_TROOP_URL = "https://troop.openape.ai";
|
|
2987
|
+
var TroopClient = class {
|
|
2988
|
+
constructor(troopUrl, agentJwt) {
|
|
2989
|
+
this.troopUrl = troopUrl;
|
|
2990
2990
|
this.agentJwt = agentJwt;
|
|
2991
2991
|
}
|
|
2992
2992
|
async request(path2, init) {
|
|
2993
|
-
const res = await fetch(`${this.
|
|
2993
|
+
const res = await fetch(`${this.troopUrl}${path2}`, {
|
|
2994
2994
|
...init,
|
|
2995
2995
|
headers: {
|
|
2996
2996
|
...init?.headers ?? {},
|
|
@@ -3000,7 +3000,7 @@ var TribeClient = class {
|
|
|
3000
3000
|
});
|
|
3001
3001
|
if (!res.ok) {
|
|
3002
3002
|
const text = await res.text().catch(() => "");
|
|
3003
|
-
throw new Error(`
|
|
3003
|
+
throw new Error(`troop ${init?.method ?? "GET"} ${path2} failed: ${res.status} ${text}`);
|
|
3004
3004
|
}
|
|
3005
3005
|
if (res.status === 204) return void 0;
|
|
3006
3006
|
return await res.json();
|
|
@@ -3032,11 +3032,11 @@ var TribeClient = class {
|
|
|
3032
3032
|
});
|
|
3033
3033
|
}
|
|
3034
3034
|
};
|
|
3035
|
-
function
|
|
3035
|
+
function resolveTroopUrl(override) {
|
|
3036
3036
|
if (override) return override.replace(/\/$/, "");
|
|
3037
|
-
const fromEnv = process.env.
|
|
3037
|
+
const fromEnv = process.env.OPENAPE_TROOP_URL;
|
|
3038
3038
|
if (fromEnv) return fromEnv.replace(/\/$/, "");
|
|
3039
|
-
return
|
|
3039
|
+
return DEFAULT_TROOP_URL;
|
|
3040
3040
|
}
|
|
3041
3041
|
|
|
3042
3042
|
// src/commands/agents/run.ts
|
|
@@ -3053,7 +3053,7 @@ function readAuth() {
|
|
|
3053
3053
|
function readTaskSpec(taskId) {
|
|
3054
3054
|
const path2 = join3(TASK_CACHE_DIR, `${taskId}.json`);
|
|
3055
3055
|
if (!existsSync5(path2)) {
|
|
3056
|
-
throw new CliError(`No cached task spec at ${path2}. Run \`apes agents sync\` first to pull the task list from
|
|
3056
|
+
throw new CliError(`No cached task spec at ${path2}. Run \`apes agents sync\` first to pull the task list from troop.`);
|
|
3057
3057
|
}
|
|
3058
3058
|
return JSON.parse(readFileSync5(path2, "utf8"));
|
|
3059
3059
|
}
|
|
@@ -3079,7 +3079,7 @@ function readLitellmConfig(model) {
|
|
|
3079
3079
|
var runAgentCommand = defineCommand24({
|
|
3080
3080
|
meta: {
|
|
3081
3081
|
name: "run",
|
|
3082
|
-
description: "Execute one task (typically launchd-invoked). Reports the run record to
|
|
3082
|
+
description: "Execute one task (typically launchd-invoked). Reports the run record to troop."
|
|
3083
3083
|
},
|
|
3084
3084
|
args: {
|
|
3085
3085
|
"task-id": {
|
|
@@ -3087,9 +3087,9 @@ var runAgentCommand = defineCommand24({
|
|
|
3087
3087
|
description: "Task ID (slug) to run. The cached spec at ~/.openape/agent/tasks/<id>.json is used.",
|
|
3088
3088
|
required: true
|
|
3089
3089
|
},
|
|
3090
|
-
"
|
|
3090
|
+
"troop-url": {
|
|
3091
3091
|
type: "string",
|
|
3092
|
-
description: "Override
|
|
3092
|
+
description: "Override troop SP base URL."
|
|
3093
3093
|
},
|
|
3094
3094
|
"model": {
|
|
3095
3095
|
type: "string",
|
|
@@ -3107,8 +3107,8 @@ var runAgentCommand = defineCommand24({
|
|
|
3107
3107
|
} catch (err) {
|
|
3108
3108
|
throw new CliError(`task ${taskId}: ${err.message}`);
|
|
3109
3109
|
}
|
|
3110
|
-
const
|
|
3111
|
-
const { id: runId } = await
|
|
3110
|
+
const troop = new TroopClient(resolveTroopUrl(args["troop-url"]), auth.access_token);
|
|
3111
|
+
const { id: runId } = await troop.startRun(taskId);
|
|
3112
3112
|
consola22.info(`Run ${runId} started for task ${taskId}`);
|
|
3113
3113
|
try {
|
|
3114
3114
|
const result = await runLoop({
|
|
@@ -3121,7 +3121,7 @@ var runAgentCommand = defineCommand24({
|
|
|
3121
3121
|
tools,
|
|
3122
3122
|
maxSteps: spec.maxSteps
|
|
3123
3123
|
});
|
|
3124
|
-
await
|
|
3124
|
+
await troop.finaliseRun(runId, {
|
|
3125
3125
|
status: result.status,
|
|
3126
3126
|
final_message: result.finalMessage,
|
|
3127
3127
|
step_count: result.stepCount,
|
|
@@ -3131,7 +3131,7 @@ var runAgentCommand = defineCommand24({
|
|
|
3131
3131
|
if (result.status === "error") process.exit(1);
|
|
3132
3132
|
} catch (err) {
|
|
3133
3133
|
const message = err?.message ?? String(err);
|
|
3134
|
-
await
|
|
3134
|
+
await troop.finaliseRun(runId, {
|
|
3135
3135
|
status: "error",
|
|
3136
3136
|
final_message: message.slice(0, 4e3),
|
|
3137
3137
|
step_count: 0,
|
|
@@ -3270,8 +3270,8 @@ import { join as join6 } from "path";
|
|
|
3270
3270
|
import { defineCommand as defineCommand26 } from "citty";
|
|
3271
3271
|
import consola23 from "consola";
|
|
3272
3272
|
|
|
3273
|
-
// src/lib/
|
|
3274
|
-
var SYNC_LABEL_PREFIX = "openape.
|
|
3273
|
+
// src/lib/troop-bootstrap.ts
|
|
3274
|
+
var SYNC_LABEL_PREFIX = "openape.troop.sync";
|
|
3275
3275
|
var SYNC_INTERVAL_SECONDS = 300;
|
|
3276
3276
|
function syncPlistLabel(agentName) {
|
|
3277
3277
|
return `${SYNC_LABEL_PREFIX}.${agentName}`;
|
|
@@ -3280,10 +3280,10 @@ function escape(s) {
|
|
|
3280
3280
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
3281
3281
|
}
|
|
3282
3282
|
function buildSyncPlist(input) {
|
|
3283
|
-
const envBlock = input.
|
|
3283
|
+
const envBlock = input.troopUrl ? ` <key>EnvironmentVariables</key>
|
|
3284
3284
|
<dict>
|
|
3285
3285
|
<key>HOME</key><string>${escape(input.homeDir)}</string>
|
|
3286
|
-
<key>
|
|
3286
|
+
<key>OPENAPE_TROOP_URL</key><string>${escape(input.troopUrl)}</string>
|
|
3287
3287
|
</dict>
|
|
3288
3288
|
` : ` <key>EnvironmentVariables</key>
|
|
3289
3289
|
<dict>
|
|
@@ -3309,9 +3309,9 @@ ${envBlock} <key>StartInterval</key>
|
|
|
3309
3309
|
<key>RunAtLoad</key>
|
|
3310
3310
|
<true/>
|
|
3311
3311
|
<key>StandardOutPath</key>
|
|
3312
|
-
<string>${escape(input.homeDir)}/Library/Logs/openape-
|
|
3312
|
+
<string>${escape(input.homeDir)}/Library/Logs/openape-troop-sync.log</string>
|
|
3313
3313
|
<key>StandardErrorPath</key>
|
|
3314
|
-
<string>${escape(input.homeDir)}/Library/Logs/openape-
|
|
3314
|
+
<string>${escape(input.homeDir)}/Library/Logs/openape-troop-sync.log</string>
|
|
3315
3315
|
</dict>
|
|
3316
3316
|
</plist>
|
|
3317
3317
|
`;
|
|
@@ -3613,11 +3613,11 @@ and try again.`
|
|
|
3613
3613
|
envFile: buildBridgeEnvFile(cfg)
|
|
3614
3614
|
};
|
|
3615
3615
|
})() : null;
|
|
3616
|
-
const
|
|
3617
|
-
const
|
|
3618
|
-
const
|
|
3619
|
-
plistLabel:
|
|
3620
|
-
plistPath:
|
|
3616
|
+
const troopPlistLabel = `openape.troop.sync.${name}`;
|
|
3617
|
+
const troopPlistPath = `${homeDir}/Library/LaunchAgents/${troopPlistLabel}.plist`;
|
|
3618
|
+
const troop = {
|
|
3619
|
+
plistLabel: troopPlistLabel,
|
|
3620
|
+
plistPath: troopPlistPath,
|
|
3621
3621
|
plistContent: buildSyncPlist({ agentName: name, apesBin: apes, homeDir })
|
|
3622
3622
|
};
|
|
3623
3623
|
const script = buildSpawnSetupScript({
|
|
@@ -3631,14 +3631,14 @@ and try again.`
|
|
|
3631
3631
|
hookScriptSource: includeClaudeHook ? BASH_VIA_APE_SHELL_HOOK_SOURCE : null,
|
|
3632
3632
|
claudeOauthToken,
|
|
3633
3633
|
bridge,
|
|
3634
|
-
|
|
3634
|
+
troop
|
|
3635
3635
|
});
|
|
3636
3636
|
writeFileSync4(scriptPath, script, { mode: 448 });
|
|
3637
3637
|
consola23.start("Running privileged setup as root via `apes run --as root --wait`\u2026");
|
|
3638
3638
|
consola23.info("You will be asked to approve the as=root grant in your DDISA inbox; this command blocks until you do.");
|
|
3639
3639
|
execFileSync7(apes, ["run", "--as", "root", "--wait", "--", "bash", scriptPath], { stdio: "inherit" });
|
|
3640
3640
|
consola23.success(`Agent ${name} spawned.`);
|
|
3641
|
-
consola23.info(`\u{1F517}
|
|
3641
|
+
consola23.info(`\u{1F517} Troop: https://troop.openape.ai/agents/${name}`);
|
|
3642
3642
|
if (args.bridge) {
|
|
3643
3643
|
consola23.info(`On first boot, the bridge will send you a contact request from ${registration.email}.`);
|
|
3644
3644
|
consola23.info("Open chat.openape.ai and accept it to start chatting with the agent.");
|
|
@@ -3686,7 +3686,7 @@ import { execFileSync as execFileSync8 } from "child_process";
|
|
|
3686
3686
|
import { mkdirSync as mkdirSync3, readdirSync, readFileSync as readFileSync9, unlinkSync, writeFileSync as writeFileSync5 } from "fs";
|
|
3687
3687
|
import { homedir as homedir9, userInfo as userInfo2 } from "os";
|
|
3688
3688
|
import { join as join7 } from "path";
|
|
3689
|
-
var PLIST_PREFIX = "openape.
|
|
3689
|
+
var PLIST_PREFIX = "openape.troop.";
|
|
3690
3690
|
function plistDir() {
|
|
3691
3691
|
return join7(homedir9(), "Library", "LaunchAgents");
|
|
3692
3692
|
}
|
|
@@ -3789,9 +3789,9 @@ ${calendarBlocks}
|
|
|
3789
3789
|
</dict>
|
|
3790
3790
|
${calendarKey}
|
|
3791
3791
|
<key>StandardOutPath</key>
|
|
3792
|
-
<string>${escape2(input.homeDir)}/Library/Logs/openape-
|
|
3792
|
+
<string>${escape2(input.homeDir)}/Library/Logs/openape-troop-${escape2(input.taskId)}.log</string>
|
|
3793
3793
|
<key>StandardErrorPath</key>
|
|
3794
|
-
<string>${escape2(input.homeDir)}/Library/Logs/openape-
|
|
3794
|
+
<string>${escape2(input.homeDir)}/Library/Logs/openape-troop-${escape2(input.taskId)}.log</string>
|
|
3795
3795
|
</dict>
|
|
3796
3796
|
</plist>
|
|
3797
3797
|
`;
|
|
@@ -3933,28 +3933,28 @@ function findApesBin() {
|
|
|
3933
3933
|
var syncAgentCommand = defineCommand27({
|
|
3934
3934
|
meta: {
|
|
3935
3935
|
name: "sync",
|
|
3936
|
-
description: "Pull this agent's task list from
|
|
3936
|
+
description: "Pull this agent's task list from troop.openape.ai and reconcile launchd plists"
|
|
3937
3937
|
},
|
|
3938
3938
|
args: {
|
|
3939
|
-
"
|
|
3939
|
+
"troop-url": {
|
|
3940
3940
|
type: "string",
|
|
3941
|
-
description: "Override
|
|
3941
|
+
description: "Override troop SP base URL (default: $OPENAPE_TROOP_URL or https://troop.openape.ai)"
|
|
3942
3942
|
}
|
|
3943
3943
|
},
|
|
3944
3944
|
async run({ args }) {
|
|
3945
3945
|
const auth = readAuthJson();
|
|
3946
3946
|
const agentName = agentNameFromEmail(auth.email);
|
|
3947
|
-
const
|
|
3948
|
-
const client = new
|
|
3947
|
+
const troopUrl = resolveTroopUrl(args["troop-url"]);
|
|
3948
|
+
const client = new TroopClient(troopUrl, auth.access_token);
|
|
3949
3949
|
const hostId = getHostId();
|
|
3950
3950
|
const host = getHostname();
|
|
3951
3951
|
if (!hostId) {
|
|
3952
|
-
throw new CliError("Could not read IOPlatformUUID \u2014 is this macOS?
|
|
3952
|
+
throw new CliError("Could not read IOPlatformUUID \u2014 is this macOS? Troop sync only works on macOS for v1.");
|
|
3953
3953
|
}
|
|
3954
3954
|
if (!auth.owner_email) {
|
|
3955
3955
|
throw new CliError(`${AUTH_PATH3} is missing owner_email \u2014 re-run \`apes agents spawn\` to update.`);
|
|
3956
3956
|
}
|
|
3957
|
-
consola24.start(`Syncing ${agentName} (${host}, hostId ${hostId.slice(0, 8)}\u2026) with ${
|
|
3957
|
+
consola24.start(`Syncing ${agentName} (${host}, hostId ${hostId.slice(0, 8)}\u2026) with ${troopUrl}`);
|
|
3958
3958
|
const sync = await client.sync({
|
|
3959
3959
|
hostname: host,
|
|
3960
3960
|
hostId,
|
|
@@ -5263,7 +5263,7 @@ var mcpCommand = defineCommand36({
|
|
|
5263
5263
|
if (transport !== "stdio" && transport !== "sse") {
|
|
5264
5264
|
throw new Error('Transport must be "stdio" or "sse"');
|
|
5265
5265
|
}
|
|
5266
|
-
const { startMcpServer } = await import("./server-
|
|
5266
|
+
const { startMcpServer } = await import("./server-F6CJ5B5O.js");
|
|
5267
5267
|
await startMcpServer(transport, port);
|
|
5268
5268
|
}
|
|
5269
5269
|
});
|
|
@@ -5901,7 +5901,7 @@ async function bestEffortGrantCount(idp) {
|
|
|
5901
5901
|
}
|
|
5902
5902
|
}
|
|
5903
5903
|
async function runHealth(args) {
|
|
5904
|
-
const version = true ? "0.
|
|
5904
|
+
const version = true ? "1.0.1" : "0.0.0";
|
|
5905
5905
|
const auth = loadAuth();
|
|
5906
5906
|
if (!auth) {
|
|
5907
5907
|
throw new CliError("Not logged in. Run `apes login` first.", 1);
|
|
@@ -6174,10 +6174,10 @@ if (shellRewrite) {
|
|
|
6174
6174
|
if (shellRewrite.action === "rewrite") {
|
|
6175
6175
|
process.argv = shellRewrite.argv;
|
|
6176
6176
|
} else if (shellRewrite.action === "version") {
|
|
6177
|
-
console.log(`ape-shell ${"0.
|
|
6177
|
+
console.log(`ape-shell ${"1.0.1"} (OpenApe DDISA shell wrapper)`);
|
|
6178
6178
|
process.exit(0);
|
|
6179
6179
|
} else if (shellRewrite.action === "help") {
|
|
6180
|
-
console.log(`ape-shell ${"0.
|
|
6180
|
+
console.log(`ape-shell ${"1.0.1"} \u2014 OpenApe DDISA shell wrapper`);
|
|
6181
6181
|
console.log("");
|
|
6182
6182
|
console.log("Usage:");
|
|
6183
6183
|
console.log(" ape-shell Start interactive grant-mediated REPL");
|
|
@@ -6235,7 +6235,7 @@ var configCommand = defineCommand48({
|
|
|
6235
6235
|
var main = defineCommand48({
|
|
6236
6236
|
meta: {
|
|
6237
6237
|
name: "apes",
|
|
6238
|
-
version: "0.
|
|
6238
|
+
version: "1.0.1",
|
|
6239
6239
|
description: "Unified CLI for OpenApe"
|
|
6240
6240
|
},
|
|
6241
6241
|
subCommands: {
|
|
@@ -6290,7 +6290,7 @@ async function maybeRefreshAuth() {
|
|
|
6290
6290
|
}
|
|
6291
6291
|
}
|
|
6292
6292
|
await maybeRefreshAuth();
|
|
6293
|
-
await maybeWarnStaleVersion("0.
|
|
6293
|
+
await maybeWarnStaleVersion("1.0.1").catch(() => {
|
|
6294
6294
|
});
|
|
6295
6295
|
runMain(main).catch((err) => {
|
|
6296
6296
|
if (err instanceof CliExit) {
|