@openape/apes 1.4.0 → 1.5.0
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
|
@@ -63,7 +63,7 @@ import {
|
|
|
63
63
|
} from "./chunk-OBF7IMQ2.js";
|
|
64
64
|
|
|
65
65
|
// src/cli.ts
|
|
66
|
-
import
|
|
66
|
+
import consola43 from "consola";
|
|
67
67
|
|
|
68
68
|
// src/ape-shell.ts
|
|
69
69
|
import path from "path";
|
|
@@ -93,7 +93,7 @@ function rewriteApeShellArgs(argv, argv0) {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
// src/cli.ts
|
|
96
|
-
import { defineCommand as
|
|
96
|
+
import { defineCommand as defineCommand53, runMain } from "citty";
|
|
97
97
|
|
|
98
98
|
// src/commands/auth/login.ts
|
|
99
99
|
import { Buffer as Buffer2 } from "buffer";
|
|
@@ -3918,15 +3918,135 @@ var agentsCommand = defineCommand28({
|
|
|
3918
3918
|
});
|
|
3919
3919
|
|
|
3920
3920
|
// src/commands/nest/index.ts
|
|
3921
|
-
import { defineCommand as
|
|
3921
|
+
import { defineCommand as defineCommand33 } from "citty";
|
|
3922
3922
|
|
|
3923
|
-
// src/commands/nest/
|
|
3923
|
+
// src/commands/nest/authorize.ts
|
|
3924
3924
|
import { execFileSync as execFileSync9 } from "child_process";
|
|
3925
|
-
import { existsSync as existsSync10, mkdirSync as mkdirSync4, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
|
|
3926
|
-
import { homedir as homedir10, userInfo as userInfo2 } from "os";
|
|
3927
|
-
import { join as join8 } from "path";
|
|
3928
3925
|
import { defineCommand as defineCommand29 } from "citty";
|
|
3929
3926
|
import consola25 from "consola";
|
|
3927
|
+
var authorizeNestCommand = defineCommand29({
|
|
3928
|
+
meta: {
|
|
3929
|
+
name: "authorize",
|
|
3930
|
+
description: "Request the always-capability-grant the nest needs for zero-prompt spawn/destroy"
|
|
3931
|
+
},
|
|
3932
|
+
args: {
|
|
3933
|
+
"reason": {
|
|
3934
|
+
type: "string",
|
|
3935
|
+
description: "Reason shown in the DDISA approval UI"
|
|
3936
|
+
},
|
|
3937
|
+
"wait": {
|
|
3938
|
+
type: "boolean",
|
|
3939
|
+
description: "Block until the grant is approved (default: print URL + exit 0)"
|
|
3940
|
+
}
|
|
3941
|
+
},
|
|
3942
|
+
async run({ args }) {
|
|
3943
|
+
const reason = args.reason ?? "nest-managed agent lifecycle (spawn / destroy / sync) \u2014 approve as Always";
|
|
3944
|
+
consola25.info("Requesting capability-grant for `apes-agents` (selector name=* covers all agent names)...");
|
|
3945
|
+
consola25.info("");
|
|
3946
|
+
consola25.info("When the IdP approval page opens, choose **Always** so the nest can re-use the grant on every spawn.");
|
|
3947
|
+
consola25.info("");
|
|
3948
|
+
const cmdArgs = [
|
|
3949
|
+
"grants",
|
|
3950
|
+
"request-capability",
|
|
3951
|
+
"apes-agents",
|
|
3952
|
+
"--resource",
|
|
3953
|
+
"agents:*",
|
|
3954
|
+
"--selector",
|
|
3955
|
+
"name=*",
|
|
3956
|
+
"--action",
|
|
3957
|
+
"create",
|
|
3958
|
+
"--action",
|
|
3959
|
+
"delete",
|
|
3960
|
+
"--action",
|
|
3961
|
+
"edit",
|
|
3962
|
+
"--action",
|
|
3963
|
+
"list",
|
|
3964
|
+
"--approval=always",
|
|
3965
|
+
"--reason",
|
|
3966
|
+
reason,
|
|
3967
|
+
"--run-as",
|
|
3968
|
+
"root"
|
|
3969
|
+
];
|
|
3970
|
+
if (args.wait) cmdArgs.push("--wait");
|
|
3971
|
+
try {
|
|
3972
|
+
execFileSync9("apes", cmdArgs, { stdio: "inherit" });
|
|
3973
|
+
} catch (err) {
|
|
3974
|
+
throw new Error(err instanceof Error ? err.message : String(err));
|
|
3975
|
+
}
|
|
3976
|
+
}
|
|
3977
|
+
});
|
|
3978
|
+
|
|
3979
|
+
// src/commands/nest/install.ts
|
|
3980
|
+
import { execFileSync as execFileSync10 } from "child_process";
|
|
3981
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync4, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
|
|
3982
|
+
import { homedir as homedir10, userInfo as userInfo2 } from "os";
|
|
3983
|
+
import { dirname as dirname3, join as join8 } from "path";
|
|
3984
|
+
import { defineCommand as defineCommand30 } from "citty";
|
|
3985
|
+
import consola26 from "consola";
|
|
3986
|
+
|
|
3987
|
+
// src/commands/nest/apes-agents-adapter.ts
|
|
3988
|
+
var APES_AGENTS_ADAPTER_TOML = `schema = "openape-shapes/v1"
|
|
3989
|
+
|
|
3990
|
+
# Adapter for the \`apes agents\` subtree \u2014 written by \`apes nest install\`.
|
|
3991
|
+
# A capability-grant with selector \`name=*\` covers any agent name
|
|
3992
|
+
# (selectorValueMatches treats '*' as a glob), letting the nest spawn
|
|
3993
|
+
# and destroy without per-agent DDISA prompts.
|
|
3994
|
+
|
|
3995
|
+
[cli]
|
|
3996
|
+
id = "apes-agents"
|
|
3997
|
+
executable = "apes"
|
|
3998
|
+
audience = "shapes"
|
|
3999
|
+
version = "1"
|
|
4000
|
+
|
|
4001
|
+
# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
4002
|
+
# AGENT LIFECYCLE \u2014 spawn / destroy / sync
|
|
4003
|
+
# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
4004
|
+
|
|
4005
|
+
[[operation]]
|
|
4006
|
+
id = "agents.spawn"
|
|
4007
|
+
command = ["agents", "spawn"]
|
|
4008
|
+
positionals = ["name"]
|
|
4009
|
+
display = "Spawn agent {name}"
|
|
4010
|
+
action = "create"
|
|
4011
|
+
risk = "high"
|
|
4012
|
+
resource_chain = ["agents:name={name}"]
|
|
4013
|
+
|
|
4014
|
+
[[operation]]
|
|
4015
|
+
id = "agents.destroy"
|
|
4016
|
+
command = ["agents", "destroy"]
|
|
4017
|
+
positionals = ["name"]
|
|
4018
|
+
display = "Destroy agent {name}"
|
|
4019
|
+
action = "delete"
|
|
4020
|
+
risk = "critical"
|
|
4021
|
+
resource_chain = ["agents:name={name}"]
|
|
4022
|
+
|
|
4023
|
+
[[operation]]
|
|
4024
|
+
id = "agents.sync"
|
|
4025
|
+
command = ["agents", "sync"]
|
|
4026
|
+
display = "Sync agent state with troop"
|
|
4027
|
+
action = "edit"
|
|
4028
|
+
risk = "low"
|
|
4029
|
+
resource_chain = ["agents:*"]
|
|
4030
|
+
|
|
4031
|
+
[[operation]]
|
|
4032
|
+
id = "agents.list"
|
|
4033
|
+
command = ["agents", "list"]
|
|
4034
|
+
display = "List agents"
|
|
4035
|
+
action = "list"
|
|
4036
|
+
risk = "low"
|
|
4037
|
+
resource_chain = ["agents:*"]
|
|
4038
|
+
|
|
4039
|
+
[[operation]]
|
|
4040
|
+
id = "agents.allow"
|
|
4041
|
+
command = ["agents", "allow"]
|
|
4042
|
+
positionals = ["name", "peer_email"]
|
|
4043
|
+
display = "Allow agent {name} to accept contact requests from {peer_email}"
|
|
4044
|
+
action = "edit"
|
|
4045
|
+
risk = "medium"
|
|
4046
|
+
resource_chain = ["agents:name={name}", "allowlist:email={peer_email}"]
|
|
4047
|
+
`;
|
|
4048
|
+
|
|
4049
|
+
// src/commands/nest/install.ts
|
|
3930
4050
|
var PLIST_LABEL = "ai.openape.nest";
|
|
3931
4051
|
function plistPath() {
|
|
3932
4052
|
return join8(homedir10(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
@@ -3969,6 +4089,19 @@ function buildPlist(args) {
|
|
|
3969
4089
|
</plist>
|
|
3970
4090
|
`;
|
|
3971
4091
|
}
|
|
4092
|
+
function installAdapter2() {
|
|
4093
|
+
const target = join8(homedir10(), ".openape", "shapes", "adapters", "apes-agents.toml");
|
|
4094
|
+
mkdirSync4(dirname3(target), { recursive: true });
|
|
4095
|
+
let existing = "";
|
|
4096
|
+
try {
|
|
4097
|
+
existing = readFileSync10(target, "utf8");
|
|
4098
|
+
} catch {
|
|
4099
|
+
}
|
|
4100
|
+
if (existing === APES_AGENTS_ADAPTER_TOML) return false;
|
|
4101
|
+
writeFileSync6(target, APES_AGENTS_ADAPTER_TOML, { mode: 420 });
|
|
4102
|
+
consola26.success(`Wrote shapes adapter ${target}`);
|
|
4103
|
+
return true;
|
|
4104
|
+
}
|
|
3972
4105
|
function findBinary(name) {
|
|
3973
4106
|
for (const dir of [
|
|
3974
4107
|
join8(homedir10(), ".bun", "bin"),
|
|
@@ -3981,7 +4114,7 @@ function findBinary(name) {
|
|
|
3981
4114
|
}
|
|
3982
4115
|
throw new Error(`could not locate ${name} on PATH; install it first`);
|
|
3983
4116
|
}
|
|
3984
|
-
var installNestCommand =
|
|
4117
|
+
var installNestCommand = defineCommand30({
|
|
3985
4118
|
meta: {
|
|
3986
4119
|
name: "install",
|
|
3987
4120
|
description: "Install + start the local nest-daemon (idempotent \u2014 re-running just restarts)"
|
|
@@ -4000,10 +4133,11 @@ var installNestCommand = defineCommand29({
|
|
|
4000
4133
|
}
|
|
4001
4134
|
const nestBin = findBinary("openape-nest");
|
|
4002
4135
|
const apesBin = findBinary("apes");
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4136
|
+
consola26.info(`Installing nest at ${plistPath()}`);
|
|
4137
|
+
consola26.info(` nest binary: ${nestBin}`);
|
|
4138
|
+
consola26.info(` apes binary: ${apesBin}`);
|
|
4139
|
+
consola26.info(` HTTP port: ${port}`);
|
|
4140
|
+
installAdapter2();
|
|
4007
4141
|
mkdirSync4(join8(homeDir, "Library", "LaunchAgents"), { recursive: true });
|
|
4008
4142
|
const desired = buildPlist({ nestBin, apesBin, homeDir, port });
|
|
4009
4143
|
let existing = "";
|
|
@@ -4013,35 +4147,33 @@ var installNestCommand = defineCommand29({
|
|
|
4013
4147
|
}
|
|
4014
4148
|
if (existing !== desired) {
|
|
4015
4149
|
writeFileSync6(plistPath(), desired, { mode: 420 });
|
|
4016
|
-
|
|
4150
|
+
consola26.success("Wrote launchd plist");
|
|
4017
4151
|
} else {
|
|
4018
|
-
|
|
4152
|
+
consola26.info("plist already up to date");
|
|
4019
4153
|
}
|
|
4020
4154
|
const uid = userInfo2().uid;
|
|
4021
4155
|
try {
|
|
4022
|
-
|
|
4156
|
+
execFileSync10("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL}`], { stdio: "ignore" });
|
|
4023
4157
|
} catch {
|
|
4024
4158
|
}
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
consola25.info('(The seed-spawn will fail because "_grant_pattern_seed_" is not a valid');
|
|
4035
|
-
consola25.info("agent name \u2014 that's expected. The grant just needs to be approved-as-always.)");
|
|
4159
|
+
execFileSync10("/bin/launchctl", ["bootstrap", `gui/${uid}`, plistPath()], { stdio: "inherit" });
|
|
4160
|
+
consola26.success(`Nest daemon bootstrapped \u2014 http://127.0.0.1:${port}`);
|
|
4161
|
+
consola26.info("");
|
|
4162
|
+
consola26.info("Next: request the capability-grant that lets the nest spawn/destroy any agent without per-call approval:");
|
|
4163
|
+
consola26.info("");
|
|
4164
|
+
consola26.info(" apes nest authorize");
|
|
4165
|
+
consola26.info("");
|
|
4166
|
+
consola26.info("That requests an `apes-agents` capability-grant covering all agent names (selector glob `name=*`)");
|
|
4167
|
+
consola26.info("from your DDISA inbox; approve it once as `always` and the nest API runs silently from then on.");
|
|
4036
4168
|
}
|
|
4037
4169
|
});
|
|
4038
4170
|
|
|
4039
4171
|
// src/commands/nest/status.ts
|
|
4040
4172
|
import process2 from "process";
|
|
4041
|
-
import { defineCommand as
|
|
4042
|
-
import
|
|
4173
|
+
import { defineCommand as defineCommand31 } from "citty";
|
|
4174
|
+
import consola27 from "consola";
|
|
4043
4175
|
var DEFAULT_PORT = 9091;
|
|
4044
|
-
var statusNestCommand =
|
|
4176
|
+
var statusNestCommand = defineCommand31({
|
|
4045
4177
|
meta: {
|
|
4046
4178
|
name: "status",
|
|
4047
4179
|
description: "Print state of the local nest-daemon (agents registered, processes supervised)"
|
|
@@ -4061,8 +4193,8 @@ var statusNestCommand = defineCommand30({
|
|
|
4061
4193
|
} catch (err) {
|
|
4062
4194
|
const msg = err instanceof Error ? err.message : String(err);
|
|
4063
4195
|
if (msg.includes("ECONNREFUSED") || msg.includes("fetch failed")) {
|
|
4064
|
-
|
|
4065
|
-
|
|
4196
|
+
consola27.error(`Nest daemon is not running at http://127.0.0.1:${port}`);
|
|
4197
|
+
consola27.info(" Run: apes nest install");
|
|
4066
4198
|
process2.exit(2);
|
|
4067
4199
|
}
|
|
4068
4200
|
throw err;
|
|
@@ -4071,15 +4203,15 @@ var statusNestCommand = defineCommand30({
|
|
|
4071
4203
|
console.log(JSON.stringify(status, null, 2));
|
|
4072
4204
|
return;
|
|
4073
4205
|
}
|
|
4074
|
-
|
|
4206
|
+
consola27.info(`Nest at http://127.0.0.1:${port} \u2014 ${status.agents} agent(s) registered, ${status.processes.length} supervised`);
|
|
4075
4207
|
if (status.processes.length === 0) {
|
|
4076
|
-
|
|
4208
|
+
consola27.info(" (no processes running)");
|
|
4077
4209
|
return;
|
|
4078
4210
|
}
|
|
4079
4211
|
for (const p of status.processes) {
|
|
4080
4212
|
const uptime = humanDuration(p.uptimeSec);
|
|
4081
4213
|
const crashTag = p.consecutiveCrashes > 0 ? ` \u26A0 ${p.consecutiveCrashes} crash(es)` : "";
|
|
4082
|
-
|
|
4214
|
+
consola27.info(` ${p.name.padEnd(16)} pid=${String(p.pid).padEnd(6)} up=${uptime}${crashTag}`);
|
|
4083
4215
|
}
|
|
4084
4216
|
}
|
|
4085
4217
|
});
|
|
@@ -4091,14 +4223,14 @@ function humanDuration(sec) {
|
|
|
4091
4223
|
}
|
|
4092
4224
|
|
|
4093
4225
|
// src/commands/nest/uninstall.ts
|
|
4094
|
-
import { execFileSync as
|
|
4226
|
+
import { execFileSync as execFileSync11 } from "child_process";
|
|
4095
4227
|
import { existsSync as existsSync11, unlinkSync } from "fs";
|
|
4096
4228
|
import { homedir as homedir11, userInfo as userInfo3 } from "os";
|
|
4097
4229
|
import { join as join9 } from "path";
|
|
4098
|
-
import { defineCommand as
|
|
4099
|
-
import
|
|
4230
|
+
import { defineCommand as defineCommand32 } from "citty";
|
|
4231
|
+
import consola28 from "consola";
|
|
4100
4232
|
var PLIST_LABEL2 = "ai.openape.nest";
|
|
4101
|
-
var uninstallNestCommand =
|
|
4233
|
+
var uninstallNestCommand = defineCommand32({
|
|
4102
4234
|
meta: {
|
|
4103
4235
|
name: "uninstall",
|
|
4104
4236
|
description: "Stop + remove the local nest-daemon (registry + agents preserved)"
|
|
@@ -4107,42 +4239,43 @@ var uninstallNestCommand = defineCommand31({
|
|
|
4107
4239
|
const uid = userInfo3().uid;
|
|
4108
4240
|
const path2 = join9(homedir11(), "Library", "LaunchAgents", `${PLIST_LABEL2}.plist`);
|
|
4109
4241
|
try {
|
|
4110
|
-
|
|
4111
|
-
|
|
4242
|
+
execFileSync11("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL2}`], { stdio: "ignore" });
|
|
4243
|
+
consola28.success("Nest daemon stopped");
|
|
4112
4244
|
} catch {
|
|
4113
|
-
|
|
4245
|
+
consola28.info("Nest daemon was not loaded");
|
|
4114
4246
|
}
|
|
4115
4247
|
if (existsSync11(path2)) {
|
|
4116
4248
|
unlinkSync(path2);
|
|
4117
|
-
|
|
4249
|
+
consola28.success(`Removed ${path2}`);
|
|
4118
4250
|
}
|
|
4119
|
-
|
|
4251
|
+
consola28.info("Registry at ~/.openape/nest/agents.json kept \u2014 re-run `apes nest install` to resume supervision.");
|
|
4120
4252
|
}
|
|
4121
4253
|
});
|
|
4122
4254
|
|
|
4123
4255
|
// src/commands/nest/index.ts
|
|
4124
|
-
var nestCommand =
|
|
4256
|
+
var nestCommand = defineCommand33({
|
|
4125
4257
|
meta: {
|
|
4126
4258
|
name: "nest",
|
|
4127
|
-
description: "Manage the local Nest control-plane daemon (install, status, uninstall). The Nest hosts agents on this computer \u2014 once installed, `apes agents spawn` is fast (no per-spawn DDISA approvals) and per-agent launchd plists are replaced by a single supervised process tree."
|
|
4259
|
+
description: "Manage the local Nest control-plane daemon (install, authorize, status, uninstall). The Nest hosts agents on this computer \u2014 once installed + authorized, `apes agents spawn` is fast (no per-spawn DDISA approvals) and per-agent launchd plists are replaced by a single supervised process tree."
|
|
4128
4260
|
},
|
|
4129
4261
|
subCommands: {
|
|
4130
4262
|
install: installNestCommand,
|
|
4263
|
+
authorize: authorizeNestCommand,
|
|
4131
4264
|
status: statusNestCommand,
|
|
4132
4265
|
uninstall: uninstallNestCommand
|
|
4133
4266
|
}
|
|
4134
4267
|
});
|
|
4135
4268
|
|
|
4136
4269
|
// src/commands/adapter/index.ts
|
|
4137
|
-
import { defineCommand as
|
|
4138
|
-
import
|
|
4139
|
-
var adapterCommand =
|
|
4270
|
+
import { defineCommand as defineCommand34 } from "citty";
|
|
4271
|
+
import consola29 from "consola";
|
|
4272
|
+
var adapterCommand = defineCommand34({
|
|
4140
4273
|
meta: {
|
|
4141
4274
|
name: "adapter",
|
|
4142
4275
|
description: "Manage CLI adapters"
|
|
4143
4276
|
},
|
|
4144
4277
|
subCommands: {
|
|
4145
|
-
list:
|
|
4278
|
+
list: defineCommand34({
|
|
4146
4279
|
meta: {
|
|
4147
4280
|
name: "list",
|
|
4148
4281
|
description: "List available adapters"
|
|
@@ -4173,7 +4306,7 @@ var adapterCommand = defineCommand33({
|
|
|
4173
4306
|
`);
|
|
4174
4307
|
return;
|
|
4175
4308
|
}
|
|
4176
|
-
|
|
4309
|
+
consola29.info(`Registry: ${index2.adapters.length} adapters (${index2.generated_at})`);
|
|
4177
4310
|
for (const a of index2.adapters) {
|
|
4178
4311
|
const installed = isInstalled(a.id, false) ? " [installed]" : "";
|
|
4179
4312
|
console.log(` ${a.id.padEnd(12)} ${a.name.padEnd(24)} ${a.category}${installed}`);
|
|
@@ -4195,7 +4328,7 @@ var adapterCommand = defineCommand33({
|
|
|
4195
4328
|
return;
|
|
4196
4329
|
}
|
|
4197
4330
|
if (local.length === 0) {
|
|
4198
|
-
|
|
4331
|
+
consola29.info("No adapters installed. Use `apes adapter list --remote` to see available adapters.");
|
|
4199
4332
|
return;
|
|
4200
4333
|
}
|
|
4201
4334
|
for (const a of local) {
|
|
@@ -4203,7 +4336,7 @@ var adapterCommand = defineCommand33({
|
|
|
4203
4336
|
}
|
|
4204
4337
|
}
|
|
4205
4338
|
}),
|
|
4206
|
-
install:
|
|
4339
|
+
install: defineCommand34({
|
|
4207
4340
|
meta: {
|
|
4208
4341
|
name: "install",
|
|
4209
4342
|
description: "Install an adapter from the registry"
|
|
@@ -4232,24 +4365,24 @@ var adapterCommand = defineCommand33({
|
|
|
4232
4365
|
for (const id of ids) {
|
|
4233
4366
|
const entry = findAdapter(index, id);
|
|
4234
4367
|
if (!entry) {
|
|
4235
|
-
|
|
4368
|
+
consola29.error(`Adapter "${id}" not found in registry. Use \`apes adapter search ${id}\` to search.`);
|
|
4236
4369
|
continue;
|
|
4237
4370
|
}
|
|
4238
4371
|
const conflicts = findConflictingAdapters(entry.executable, id);
|
|
4239
4372
|
if (conflicts.length > 0) {
|
|
4240
4373
|
for (const c of conflicts) {
|
|
4241
|
-
|
|
4242
|
-
|
|
4374
|
+
consola29.warn(`Conflicting adapter found: ${c.path} (id: ${c.adapterId}, executable: ${c.executable})`);
|
|
4375
|
+
consola29.warn(` Remove it with: apes adapter remove ${c.adapterId}`);
|
|
4243
4376
|
}
|
|
4244
4377
|
}
|
|
4245
4378
|
const result = await installAdapter(entry, { local });
|
|
4246
4379
|
const verb = result.updated ? "Updated" : "Installed";
|
|
4247
|
-
|
|
4248
|
-
|
|
4380
|
+
consola29.success(`${verb} ${result.id} \u2192 ${result.path}`);
|
|
4381
|
+
consola29.info(`Digest: ${result.digest}`);
|
|
4249
4382
|
}
|
|
4250
4383
|
}
|
|
4251
4384
|
}),
|
|
4252
|
-
remove:
|
|
4385
|
+
remove: defineCommand34({
|
|
4253
4386
|
meta: {
|
|
4254
4387
|
name: "remove",
|
|
4255
4388
|
description: "Remove an installed adapter"
|
|
@@ -4272,9 +4405,9 @@ var adapterCommand = defineCommand33({
|
|
|
4272
4405
|
let failed = false;
|
|
4273
4406
|
for (const id of ids) {
|
|
4274
4407
|
if (removeAdapter(id, local)) {
|
|
4275
|
-
|
|
4408
|
+
consola29.success(`Removed adapter: ${id}`);
|
|
4276
4409
|
} else {
|
|
4277
|
-
|
|
4410
|
+
consola29.error(`Adapter "${id}" is not installed${local ? " locally" : ""}`);
|
|
4278
4411
|
failed = true;
|
|
4279
4412
|
}
|
|
4280
4413
|
}
|
|
@@ -4282,7 +4415,7 @@ var adapterCommand = defineCommand33({
|
|
|
4282
4415
|
throw new CliError("Some adapters could not be removed");
|
|
4283
4416
|
}
|
|
4284
4417
|
}),
|
|
4285
|
-
info:
|
|
4418
|
+
info: defineCommand34({
|
|
4286
4419
|
meta: {
|
|
4287
4420
|
name: "info",
|
|
4288
4421
|
description: "Show detailed adapter information"
|
|
@@ -4324,7 +4457,7 @@ var adapterCommand = defineCommand33({
|
|
|
4324
4457
|
}
|
|
4325
4458
|
}
|
|
4326
4459
|
}),
|
|
4327
|
-
search:
|
|
4460
|
+
search: defineCommand34({
|
|
4328
4461
|
meta: {
|
|
4329
4462
|
name: "search",
|
|
4330
4463
|
description: "Search adapters in the registry"
|
|
@@ -4356,7 +4489,7 @@ var adapterCommand = defineCommand33({
|
|
|
4356
4489
|
return;
|
|
4357
4490
|
}
|
|
4358
4491
|
if (results.length === 0) {
|
|
4359
|
-
|
|
4492
|
+
consola29.info(`No adapters matching "${query}"`);
|
|
4360
4493
|
return;
|
|
4361
4494
|
}
|
|
4362
4495
|
for (const a of results) {
|
|
@@ -4365,7 +4498,7 @@ var adapterCommand = defineCommand33({
|
|
|
4365
4498
|
}
|
|
4366
4499
|
}
|
|
4367
4500
|
}),
|
|
4368
|
-
update:
|
|
4501
|
+
update: defineCommand34({
|
|
4369
4502
|
meta: {
|
|
4370
4503
|
name: "update",
|
|
4371
4504
|
description: "Update installed adapters"
|
|
@@ -4391,33 +4524,33 @@ var adapterCommand = defineCommand33({
|
|
|
4391
4524
|
const targetId = args.id ? String(args.id) : void 0;
|
|
4392
4525
|
const targets = targetId ? [targetId] : index.adapters.map((a) => a.id).filter((id) => isInstalled(id, false));
|
|
4393
4526
|
if (targets.length === 0) {
|
|
4394
|
-
|
|
4527
|
+
consola29.info("No adapters installed to update.");
|
|
4395
4528
|
return;
|
|
4396
4529
|
}
|
|
4397
4530
|
for (const id of targets) {
|
|
4398
4531
|
const entry = findAdapter(index, id);
|
|
4399
4532
|
if (!entry) {
|
|
4400
|
-
|
|
4533
|
+
consola29.warn(`${id}: not found in registry, skipping`);
|
|
4401
4534
|
continue;
|
|
4402
4535
|
}
|
|
4403
4536
|
const localDigest = getInstalledDigest(id, false);
|
|
4404
4537
|
if (localDigest === entry.digest) {
|
|
4405
|
-
|
|
4538
|
+
consola29.info(`${id}: already up to date`);
|
|
4406
4539
|
continue;
|
|
4407
4540
|
}
|
|
4408
4541
|
if (localDigest && !args.yes) {
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4542
|
+
consola29.warn(`${id}: digest will change \u2014 existing grants for this adapter will be invalidated`);
|
|
4543
|
+
consola29.info(` Old: ${localDigest}`);
|
|
4544
|
+
consola29.info(` New: ${entry.digest}`);
|
|
4545
|
+
consola29.info(" Use --yes to confirm");
|
|
4413
4546
|
continue;
|
|
4414
4547
|
}
|
|
4415
4548
|
const result = await installAdapter(entry);
|
|
4416
|
-
|
|
4549
|
+
consola29.success(`Updated ${result.id} \u2192 ${result.path}`);
|
|
4417
4550
|
}
|
|
4418
4551
|
}
|
|
4419
4552
|
}),
|
|
4420
|
-
verify:
|
|
4553
|
+
verify: defineCommand34({
|
|
4421
4554
|
meta: {
|
|
4422
4555
|
name: "verify",
|
|
4423
4556
|
description: "Verify installed adapter against registry digest"
|
|
@@ -4450,7 +4583,7 @@ var adapterCommand = defineCommand33({
|
|
|
4450
4583
|
if (!localDigest)
|
|
4451
4584
|
throw new Error(`Adapter "${id}" is not installed${local ? " locally" : ""}`);
|
|
4452
4585
|
if (localDigest === entry.digest) {
|
|
4453
|
-
|
|
4586
|
+
consola29.success(`${id}: digest matches registry`);
|
|
4454
4587
|
} else {
|
|
4455
4588
|
console.log(` Local: ${localDigest}`);
|
|
4456
4589
|
console.log(` Registry: ${entry.digest}`);
|
|
@@ -4462,11 +4595,11 @@ var adapterCommand = defineCommand33({
|
|
|
4462
4595
|
});
|
|
4463
4596
|
|
|
4464
4597
|
// src/commands/run.ts
|
|
4465
|
-
import { execFileSync as
|
|
4598
|
+
import { execFileSync as execFileSync12 } from "child_process";
|
|
4466
4599
|
import { hostname as hostname4 } from "os";
|
|
4467
4600
|
import { basename } from "path";
|
|
4468
|
-
import { defineCommand as
|
|
4469
|
-
import
|
|
4601
|
+
import { defineCommand as defineCommand35 } from "citty";
|
|
4602
|
+
import consola30 from "consola";
|
|
4470
4603
|
function shouldWaitForGrant(args) {
|
|
4471
4604
|
return args.wait === true || process.env.APE_WAIT === "1";
|
|
4472
4605
|
}
|
|
@@ -4503,7 +4636,7 @@ function printPendingGrantInfo(grant, idp) {
|
|
|
4503
4636
|
const statusCmd = `apes grants status ${grant.id}`;
|
|
4504
4637
|
const executeCmd = `apes grants run ${grant.id}`;
|
|
4505
4638
|
if (mode === "human") {
|
|
4506
|
-
|
|
4639
|
+
consola30.success(`Grant ${grant.id} created \u2014 awaiting your approval`);
|
|
4507
4640
|
console.log(` Approve in browser: ${approveUrl}`);
|
|
4508
4641
|
console.log(` Check status: ${statusCmd}`);
|
|
4509
4642
|
console.log(` Run after approval: ${executeCmd}`);
|
|
@@ -4513,7 +4646,7 @@ function printPendingGrantInfo(grant, idp) {
|
|
|
4513
4646
|
return;
|
|
4514
4647
|
}
|
|
4515
4648
|
const maxMin = getPollMaxMinutes();
|
|
4516
|
-
|
|
4649
|
+
consola30.success(`Grant ${grant.id} created (pending approval)`);
|
|
4517
4650
|
console.log(` Approve: ${approveUrl}`);
|
|
4518
4651
|
console.log(` Status: ${statusCmd} [--json]`);
|
|
4519
4652
|
console.log(` Execute: ${executeCmd} --wait`);
|
|
@@ -4535,7 +4668,7 @@ function printPendingGrantInfo(grant, idp) {
|
|
|
4535
4668
|
console.log(' Tip: Approve as "timed" or "always" in the browser to let this');
|
|
4536
4669
|
console.log(" grant be reused on subsequent invocations without re-approval.");
|
|
4537
4670
|
}
|
|
4538
|
-
var runCommand =
|
|
4671
|
+
var runCommand = defineCommand35({
|
|
4539
4672
|
meta: {
|
|
4540
4673
|
name: "run",
|
|
4541
4674
|
description: "Execute a grant-secured command"
|
|
@@ -4638,7 +4771,7 @@ async function runShellMode(command, args) {
|
|
|
4638
4771
|
}
|
|
4639
4772
|
} catch {
|
|
4640
4773
|
}
|
|
4641
|
-
|
|
4774
|
+
consola30.info(`Requesting ape-shell session grant on ${targetHost}`);
|
|
4642
4775
|
const grant = await apiFetch(grantsUrl, {
|
|
4643
4776
|
method: "POST",
|
|
4644
4777
|
body: {
|
|
@@ -4658,8 +4791,8 @@ async function runShellMode(command, args) {
|
|
|
4658
4791
|
host: targetHost
|
|
4659
4792
|
});
|
|
4660
4793
|
if (shouldWaitForGrant(args)) {
|
|
4661
|
-
|
|
4662
|
-
|
|
4794
|
+
consola30.info(`Grant requested: ${grant.id}`);
|
|
4795
|
+
consola30.info("Waiting for approval...");
|
|
4663
4796
|
const maxWait = 3e5;
|
|
4664
4797
|
const interval = 3e3;
|
|
4665
4798
|
const start = Date.now();
|
|
@@ -4690,13 +4823,13 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
4690
4823
|
try {
|
|
4691
4824
|
resolved = await resolveCommand(loaded, [normalizedExecutable, ...parsed.argv]);
|
|
4692
4825
|
} catch (err) {
|
|
4693
|
-
|
|
4826
|
+
consola30.debug(`ape-shell: adapter resolve failed for "${parsed.raw}":`, err);
|
|
4694
4827
|
return false;
|
|
4695
4828
|
}
|
|
4696
4829
|
try {
|
|
4697
4830
|
const existingGrantId = await findExistingGrant(resolved, idp);
|
|
4698
4831
|
if (existingGrantId) {
|
|
4699
|
-
|
|
4832
|
+
consola30.info(`Reusing grant ${existingGrantId} for: ${resolved.detail.display}`);
|
|
4700
4833
|
const token = await fetchGrantToken(idp, existingGrantId);
|
|
4701
4834
|
await verifyAndExecute(token, resolved, existingGrantId);
|
|
4702
4835
|
return true;
|
|
@@ -4704,7 +4837,7 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
4704
4837
|
} catch {
|
|
4705
4838
|
}
|
|
4706
4839
|
const approval = args.approval ?? "once";
|
|
4707
|
-
|
|
4840
|
+
consola30.info(`Requesting grant for: ${resolved.detail.display}`);
|
|
4708
4841
|
const grant = await createShapesGrant(resolved, {
|
|
4709
4842
|
idp,
|
|
4710
4843
|
approval,
|
|
@@ -4712,8 +4845,8 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
4712
4845
|
});
|
|
4713
4846
|
if (grant.similar_grants?.similar_grants?.length) {
|
|
4714
4847
|
const n = grant.similar_grants.similar_grants.length;
|
|
4715
|
-
|
|
4716
|
-
|
|
4848
|
+
consola30.info("");
|
|
4849
|
+
consola30.info(` Similar grant(s) found (${n}). Your approver can extend an existing grant to cover this request.`);
|
|
4717
4850
|
}
|
|
4718
4851
|
notifyGrantPending({
|
|
4719
4852
|
grantId: grant.id,
|
|
@@ -4723,8 +4856,8 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
4723
4856
|
host: args.host || hostname4()
|
|
4724
4857
|
});
|
|
4725
4858
|
if (shouldWaitForGrant(args)) {
|
|
4726
|
-
|
|
4727
|
-
|
|
4859
|
+
consola30.info(`Grant requested: ${grant.id}`);
|
|
4860
|
+
consola30.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
4728
4861
|
const status = await waitForGrantStatus(idp, grant.id);
|
|
4729
4862
|
if (status !== "approved")
|
|
4730
4863
|
throw new CliError(`Grant ${status}`);
|
|
@@ -4740,7 +4873,7 @@ function execShellCommand(command) {
|
|
|
4740
4873
|
throw new CliError("No command to execute");
|
|
4741
4874
|
try {
|
|
4742
4875
|
const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
|
|
4743
|
-
|
|
4876
|
+
execFileSync12(command[0], command.slice(1), {
|
|
4744
4877
|
stdio: "inherit",
|
|
4745
4878
|
env: inheritedEnv
|
|
4746
4879
|
});
|
|
@@ -4798,7 +4931,7 @@ async function runAdapterMode(command, rawArgs, args) {
|
|
|
4798
4931
|
try {
|
|
4799
4932
|
const existingGrantId = await findExistingGrant(resolved, idp);
|
|
4800
4933
|
if (existingGrantId) {
|
|
4801
|
-
|
|
4934
|
+
consola30.info(`Reusing existing grant: ${existingGrantId}`);
|
|
4802
4935
|
const token = await fetchGrantToken(idp, existingGrantId);
|
|
4803
4936
|
await verifyAndExecute(token, resolved, existingGrantId);
|
|
4804
4937
|
return;
|
|
@@ -4812,17 +4945,17 @@ async function runAdapterMode(command, rawArgs, args) {
|
|
|
4812
4945
|
});
|
|
4813
4946
|
if (grant.similar_grants?.similar_grants?.length) {
|
|
4814
4947
|
const n = grant.similar_grants.similar_grants.length;
|
|
4815
|
-
|
|
4816
|
-
|
|
4948
|
+
consola30.info("");
|
|
4949
|
+
consola30.info(` Similar grant(s) found (${n}). Your approver can extend an existing grant to cover this request.`);
|
|
4817
4950
|
if (grant.similar_grants.widened_details?.length) {
|
|
4818
4951
|
const wider = grant.similar_grants.widened_details.map((d) => d.permission).join(", ");
|
|
4819
|
-
|
|
4952
|
+
consola30.info(` Broader scope: ${wider}`);
|
|
4820
4953
|
}
|
|
4821
|
-
|
|
4954
|
+
consola30.info("");
|
|
4822
4955
|
}
|
|
4823
4956
|
if (shouldWaitForGrant(args)) {
|
|
4824
|
-
|
|
4825
|
-
|
|
4957
|
+
consola30.info(`Grant requested: ${grant.id}`);
|
|
4958
|
+
consola30.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
4826
4959
|
const status = await waitForGrantStatus(idp, grant.id);
|
|
4827
4960
|
if (status !== "approved")
|
|
4828
4961
|
throw new Error(`Grant ${status}`);
|
|
@@ -4842,7 +4975,7 @@ async function runAudienceMode(audience, action, args) {
|
|
|
4842
4975
|
const grantsUrl = await getGrantsEndpoint(idp);
|
|
4843
4976
|
const command = action.split(" ");
|
|
4844
4977
|
const targetHost = args.host || hostname4();
|
|
4845
|
-
|
|
4978
|
+
consola30.info(`Requesting ${audience} grant on ${targetHost}: ${command.join(" ")}`);
|
|
4846
4979
|
const grant = await apiFetch(grantsUrl, {
|
|
4847
4980
|
method: "POST",
|
|
4848
4981
|
body: {
|
|
@@ -4859,9 +4992,9 @@ async function runAudienceMode(audience, action, args) {
|
|
|
4859
4992
|
printPendingGrantInfo(grant, idp);
|
|
4860
4993
|
throw new CliExit(getAsyncExitCode());
|
|
4861
4994
|
}
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4995
|
+
consola30.success(`Grant requested: ${grant.id}`);
|
|
4996
|
+
consola30.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
4997
|
+
consola30.info("Waiting for approval...");
|
|
4865
4998
|
const maxWait = 15 * 60 * 1e3;
|
|
4866
4999
|
const interval = 3e3;
|
|
4867
5000
|
const start = Date.now();
|
|
@@ -4869,7 +5002,7 @@ async function runAudienceMode(audience, action, args) {
|
|
|
4869
5002
|
while (Date.now() - start < maxWait) {
|
|
4870
5003
|
const status = await apiFetch(`${grantsUrl}/${grant.id}`);
|
|
4871
5004
|
if (status.status === "approved") {
|
|
4872
|
-
|
|
5005
|
+
consola30.success("Grant approved!");
|
|
4873
5006
|
approved = true;
|
|
4874
5007
|
break;
|
|
4875
5008
|
}
|
|
@@ -4884,15 +5017,15 @@ async function runAudienceMode(audience, action, args) {
|
|
|
4884
5017
|
`Grant approval timed out after ${minutes} min (still pending). Check your DDISA inbox at ${idp}/grant-approval?grant_id=${grant.id} \u2014 if approved later, re-run the same \`apes run\` command and it will reuse the grant.`
|
|
4885
5018
|
);
|
|
4886
5019
|
}
|
|
4887
|
-
|
|
5020
|
+
consola30.info("Fetching grant token...");
|
|
4888
5021
|
const { authz_jwt } = await apiFetch(`${grantsUrl}/${grant.id}/token`, {
|
|
4889
5022
|
method: "POST"
|
|
4890
5023
|
});
|
|
4891
5024
|
if (audience === "escapes") {
|
|
4892
|
-
|
|
5025
|
+
consola30.info(`Executing: ${command.join(" ")}`);
|
|
4893
5026
|
try {
|
|
4894
5027
|
const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
|
|
4895
|
-
|
|
5028
|
+
execFileSync12(args["escapes-path"] || "escapes", ["--grant", authz_jwt, "--", ...command], {
|
|
4896
5029
|
stdio: "inherit",
|
|
4897
5030
|
env: inheritedEnv
|
|
4898
5031
|
});
|
|
@@ -4907,8 +5040,8 @@ async function runAudienceMode(audience, action, args) {
|
|
|
4907
5040
|
|
|
4908
5041
|
// src/commands/proxy.ts
|
|
4909
5042
|
import { spawn as spawn2 } from "child_process";
|
|
4910
|
-
import { defineCommand as
|
|
4911
|
-
import
|
|
5043
|
+
import { defineCommand as defineCommand36 } from "citty";
|
|
5044
|
+
import consola31 from "consola";
|
|
4912
5045
|
|
|
4913
5046
|
// src/proxy/config.ts
|
|
4914
5047
|
function buildDefaultProxyConfigToml(opts) {
|
|
@@ -4945,7 +5078,7 @@ import { spawn } from "child_process";
|
|
|
4945
5078
|
import { mkdtempSync as mkdtempSync3, rmSync as rmSync3, writeFileSync as writeFileSync7 } from "fs";
|
|
4946
5079
|
import { createRequire } from "module";
|
|
4947
5080
|
import { tmpdir as tmpdir3 } from "os";
|
|
4948
|
-
import { dirname as
|
|
5081
|
+
import { dirname as dirname4, join as join10, resolve as resolve4 } from "path";
|
|
4949
5082
|
var require2 = createRequire(import.meta.url);
|
|
4950
5083
|
function findProxyBin() {
|
|
4951
5084
|
const pkgPath = require2.resolve("@openape/proxy/package.json");
|
|
@@ -4954,7 +5087,7 @@ function findProxyBin() {
|
|
|
4954
5087
|
if (!binRel) {
|
|
4955
5088
|
throw new Error("@openape/proxy is missing the openape-proxy bin entry");
|
|
4956
5089
|
}
|
|
4957
|
-
return resolve4(
|
|
5090
|
+
return resolve4(dirname4(pkgPath), binRel);
|
|
4958
5091
|
}
|
|
4959
5092
|
async function startEphemeralProxy(configToml) {
|
|
4960
5093
|
const tmpDir = mkdtempSync3(join10(tmpdir3(), "openape-proxy-"));
|
|
@@ -5051,10 +5184,10 @@ function resolveProxyConfigOptions() {
|
|
|
5051
5184
|
77
|
|
5052
5185
|
);
|
|
5053
5186
|
}
|
|
5054
|
-
|
|
5187
|
+
consola31.info(`[apes proxy] IdP-mediated mode \u2014 agent=${auth.email}, idp=${auth.idp}`);
|
|
5055
5188
|
return { agentEmail: auth.email, idpUrl: auth.idp, mediated: true };
|
|
5056
5189
|
}
|
|
5057
|
-
var proxyCommand =
|
|
5190
|
+
var proxyCommand = defineCommand36({
|
|
5058
5191
|
meta: {
|
|
5059
5192
|
name: "proxy",
|
|
5060
5193
|
description: "Run a command with HTTPS_PROXY routed through the OpenApe egress proxy."
|
|
@@ -5076,12 +5209,12 @@ var proxyCommand = defineCommand35({
|
|
|
5076
5209
|
let close = null;
|
|
5077
5210
|
if (reuseUrl) {
|
|
5078
5211
|
proxyUrl = reuseUrl;
|
|
5079
|
-
|
|
5212
|
+
consola31.info(`[apes proxy] reusing existing proxy at ${proxyUrl}`);
|
|
5080
5213
|
} else {
|
|
5081
5214
|
const ephemeral = await startEphemeralProxy(buildDefaultProxyConfigToml(resolveProxyConfigOptions()));
|
|
5082
5215
|
proxyUrl = ephemeral.url;
|
|
5083
5216
|
close = ephemeral.close;
|
|
5084
|
-
|
|
5217
|
+
consola31.info(`[apes proxy] started ephemeral proxy at ${proxyUrl}`);
|
|
5085
5218
|
}
|
|
5086
5219
|
const noProxy = process.env.NO_PROXY ?? process.env.no_proxy ?? "127.0.0.1,localhost";
|
|
5087
5220
|
const childEnv = {
|
|
@@ -5113,7 +5246,7 @@ var proxyCommand = defineCommand35({
|
|
|
5113
5246
|
else resolveExit(code ?? 0);
|
|
5114
5247
|
});
|
|
5115
5248
|
child.once("error", (err) => {
|
|
5116
|
-
|
|
5249
|
+
consola31.error(`[apes proxy] failed to spawn '${wrapped[0]}':`, err.message);
|
|
5117
5250
|
resolveExit(127);
|
|
5118
5251
|
});
|
|
5119
5252
|
});
|
|
@@ -5127,8 +5260,8 @@ function signalNumber(signal) {
|
|
|
5127
5260
|
}
|
|
5128
5261
|
|
|
5129
5262
|
// src/commands/explain.ts
|
|
5130
|
-
import { defineCommand as
|
|
5131
|
-
var explainCommand =
|
|
5263
|
+
import { defineCommand as defineCommand37 } from "citty";
|
|
5264
|
+
var explainCommand = defineCommand37({
|
|
5132
5265
|
meta: {
|
|
5133
5266
|
name: "explain",
|
|
5134
5267
|
description: "Show what permission a command would need"
|
|
@@ -5166,9 +5299,9 @@ var explainCommand = defineCommand36({
|
|
|
5166
5299
|
});
|
|
5167
5300
|
|
|
5168
5301
|
// src/commands/config/get.ts
|
|
5169
|
-
import { defineCommand as
|
|
5170
|
-
import
|
|
5171
|
-
var configGetCommand =
|
|
5302
|
+
import { defineCommand as defineCommand38 } from "citty";
|
|
5303
|
+
import consola32 from "consola";
|
|
5304
|
+
var configGetCommand = defineCommand38({
|
|
5172
5305
|
meta: {
|
|
5173
5306
|
name: "get",
|
|
5174
5307
|
description: "Get a configuration value"
|
|
@@ -5188,7 +5321,7 @@ var configGetCommand = defineCommand37({
|
|
|
5188
5321
|
if (idp)
|
|
5189
5322
|
console.log(idp);
|
|
5190
5323
|
else
|
|
5191
|
-
|
|
5324
|
+
consola32.info("No IdP configured.");
|
|
5192
5325
|
break;
|
|
5193
5326
|
}
|
|
5194
5327
|
case "email": {
|
|
@@ -5196,7 +5329,7 @@ var configGetCommand = defineCommand37({
|
|
|
5196
5329
|
if (auth?.email)
|
|
5197
5330
|
console.log(auth.email);
|
|
5198
5331
|
else
|
|
5199
|
-
|
|
5332
|
+
consola32.info("Not logged in.");
|
|
5200
5333
|
break;
|
|
5201
5334
|
}
|
|
5202
5335
|
default: {
|
|
@@ -5209,7 +5342,7 @@ var configGetCommand = defineCommand37({
|
|
|
5209
5342
|
if (sectionObj && field in sectionObj) {
|
|
5210
5343
|
console.log(sectionObj[field]);
|
|
5211
5344
|
} else {
|
|
5212
|
-
|
|
5345
|
+
consola32.info(`Key "${key}" not set.`);
|
|
5213
5346
|
}
|
|
5214
5347
|
} else {
|
|
5215
5348
|
throw new CliError(`Unknown key: "${key}". Use: idp, email, defaults.idp, defaults.approval, agent.key, agent.email`);
|
|
@@ -5220,9 +5353,9 @@ var configGetCommand = defineCommand37({
|
|
|
5220
5353
|
});
|
|
5221
5354
|
|
|
5222
5355
|
// src/commands/config/set.ts
|
|
5223
|
-
import { defineCommand as
|
|
5224
|
-
import
|
|
5225
|
-
var configSetCommand =
|
|
5356
|
+
import { defineCommand as defineCommand39 } from "citty";
|
|
5357
|
+
import consola33 from "consola";
|
|
5358
|
+
var configSetCommand = defineCommand39({
|
|
5226
5359
|
meta: {
|
|
5227
5360
|
name: "set",
|
|
5228
5361
|
description: "Set a configuration value"
|
|
@@ -5258,12 +5391,12 @@ var configSetCommand = defineCommand38({
|
|
|
5258
5391
|
throw new CliError(`Unknown section: "${section}". Use: defaults, agent`);
|
|
5259
5392
|
}
|
|
5260
5393
|
saveConfig(config);
|
|
5261
|
-
|
|
5394
|
+
consola33.success(`Set ${key} = ${value}`);
|
|
5262
5395
|
}
|
|
5263
5396
|
});
|
|
5264
5397
|
|
|
5265
5398
|
// src/commands/fetch/index.ts
|
|
5266
|
-
import { defineCommand as
|
|
5399
|
+
import { defineCommand as defineCommand40 } from "citty";
|
|
5267
5400
|
async function doRequest(method, url, body, contentType, raw, showHeaders) {
|
|
5268
5401
|
const token = getAuthToken();
|
|
5269
5402
|
if (!token) {
|
|
@@ -5299,13 +5432,13 @@ async function doRequest(method, url, body, contentType, raw, showHeaders) {
|
|
|
5299
5432
|
throw new CliError(`HTTP ${response.status} ${response.statusText}`);
|
|
5300
5433
|
}
|
|
5301
5434
|
}
|
|
5302
|
-
var fetchCommand =
|
|
5435
|
+
var fetchCommand = defineCommand40({
|
|
5303
5436
|
meta: {
|
|
5304
5437
|
name: "fetch",
|
|
5305
5438
|
description: "Make authenticated HTTP requests"
|
|
5306
5439
|
},
|
|
5307
5440
|
subCommands: {
|
|
5308
|
-
get:
|
|
5441
|
+
get: defineCommand40({
|
|
5309
5442
|
meta: {
|
|
5310
5443
|
name: "get",
|
|
5311
5444
|
description: "GET request with auth token"
|
|
@@ -5331,7 +5464,7 @@ var fetchCommand = defineCommand39({
|
|
|
5331
5464
|
await doRequest("GET", String(args.url), void 0, "application/json", Boolean(args.raw), Boolean(args.headers));
|
|
5332
5465
|
}
|
|
5333
5466
|
}),
|
|
5334
|
-
post:
|
|
5467
|
+
post: defineCommand40({
|
|
5335
5468
|
meta: {
|
|
5336
5469
|
name: "post",
|
|
5337
5470
|
description: "POST request with auth token"
|
|
@@ -5370,8 +5503,8 @@ var fetchCommand = defineCommand39({
|
|
|
5370
5503
|
});
|
|
5371
5504
|
|
|
5372
5505
|
// src/commands/mcp/index.ts
|
|
5373
|
-
import { defineCommand as
|
|
5374
|
-
var mcpCommand =
|
|
5506
|
+
import { defineCommand as defineCommand41 } from "citty";
|
|
5507
|
+
var mcpCommand = defineCommand41({
|
|
5375
5508
|
meta: {
|
|
5376
5509
|
name: "mcp",
|
|
5377
5510
|
description: "Start MCP server for AI agents"
|
|
@@ -5394,7 +5527,7 @@ var mcpCommand = defineCommand40({
|
|
|
5394
5527
|
if (transport !== "stdio" && transport !== "sse") {
|
|
5395
5528
|
throw new Error('Transport must be "stdio" or "sse"');
|
|
5396
5529
|
}
|
|
5397
|
-
const { startMcpServer } = await import("./server-
|
|
5530
|
+
const { startMcpServer } = await import("./server-AK2JBMJD.js");
|
|
5398
5531
|
await startMcpServer(transport, port);
|
|
5399
5532
|
}
|
|
5400
5533
|
});
|
|
@@ -5402,10 +5535,10 @@ var mcpCommand = defineCommand40({
|
|
|
5402
5535
|
// src/commands/init/index.ts
|
|
5403
5536
|
import { existsSync as existsSync12, copyFileSync, writeFileSync as writeFileSync8 } from "fs";
|
|
5404
5537
|
import { randomBytes } from "crypto";
|
|
5405
|
-
import { execFileSync as
|
|
5538
|
+
import { execFileSync as execFileSync13 } from "child_process";
|
|
5406
5539
|
import { join as join11 } from "path";
|
|
5407
|
-
import { defineCommand as
|
|
5408
|
-
import
|
|
5540
|
+
import { defineCommand as defineCommand42 } from "citty";
|
|
5541
|
+
import consola34 from "consola";
|
|
5409
5542
|
var DEFAULT_IDP_URL = "https://id.openape.at";
|
|
5410
5543
|
async function downloadTemplate(repo, targetDir) {
|
|
5411
5544
|
const { downloadTemplate: gigetDownload } = await import("giget");
|
|
@@ -5414,28 +5547,28 @@ async function downloadTemplate(repo, targetDir) {
|
|
|
5414
5547
|
function installDeps(dir) {
|
|
5415
5548
|
const hasLockFile = (name) => existsSync12(join11(dir, name));
|
|
5416
5549
|
if (hasLockFile("pnpm-lock.yaml")) {
|
|
5417
|
-
|
|
5550
|
+
execFileSync13("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
|
|
5418
5551
|
} else if (hasLockFile("bun.lockb")) {
|
|
5419
|
-
|
|
5552
|
+
execFileSync13("bun", ["install"], { cwd: dir, stdio: "inherit" });
|
|
5420
5553
|
} else {
|
|
5421
|
-
|
|
5554
|
+
execFileSync13("npm", ["install"], { cwd: dir, stdio: "inherit" });
|
|
5422
5555
|
}
|
|
5423
5556
|
}
|
|
5424
5557
|
async function promptChoice(message, choices) {
|
|
5425
|
-
const result = await
|
|
5558
|
+
const result = await consola34.prompt(message, { type: "select", options: choices });
|
|
5426
5559
|
if (typeof result === "symbol") {
|
|
5427
5560
|
throw new CliExit(0);
|
|
5428
5561
|
}
|
|
5429
5562
|
return result;
|
|
5430
5563
|
}
|
|
5431
5564
|
async function promptText(message, defaultValue) {
|
|
5432
|
-
const result = await
|
|
5565
|
+
const result = await consola34.prompt(message, { type: "text", default: defaultValue, placeholder: defaultValue });
|
|
5433
5566
|
if (typeof result === "symbol") {
|
|
5434
5567
|
throw new CliExit(0);
|
|
5435
5568
|
}
|
|
5436
5569
|
return result || defaultValue || "";
|
|
5437
5570
|
}
|
|
5438
|
-
var initCommand =
|
|
5571
|
+
var initCommand = defineCommand42({
|
|
5439
5572
|
meta: {
|
|
5440
5573
|
name: "init",
|
|
5441
5574
|
description: "Scaffold a new OpenApe project"
|
|
@@ -5480,20 +5613,20 @@ async function initSP(targetDir) {
|
|
|
5480
5613
|
if (existsSync12(join11(dir, "package.json"))) {
|
|
5481
5614
|
throw new CliError(`Directory "${dir}" already contains a project.`);
|
|
5482
5615
|
}
|
|
5483
|
-
|
|
5616
|
+
consola34.start("Scaffolding SP starter...");
|
|
5484
5617
|
await downloadTemplate("openape-ai/openape-sp-starter", dir);
|
|
5485
|
-
|
|
5486
|
-
|
|
5618
|
+
consola34.success("Scaffolded from openape-sp-starter");
|
|
5619
|
+
consola34.start("Installing dependencies...");
|
|
5487
5620
|
installDeps(dir);
|
|
5488
|
-
|
|
5621
|
+
consola34.success("Dependencies installed");
|
|
5489
5622
|
const envExample = join11(dir, ".env.example");
|
|
5490
5623
|
const envFile = join11(dir, ".env");
|
|
5491
5624
|
if (existsSync12(envExample) && !existsSync12(envFile)) {
|
|
5492
5625
|
copyFileSync(envExample, envFile);
|
|
5493
|
-
|
|
5626
|
+
consola34.success(`\`.env\` created (using Free IdP at ${DEFAULT_IDP_URL})`);
|
|
5494
5627
|
}
|
|
5495
5628
|
console.log("");
|
|
5496
|
-
|
|
5629
|
+
consola34.box([
|
|
5497
5630
|
`cd ${dir}`,
|
|
5498
5631
|
"npm run dev",
|
|
5499
5632
|
"",
|
|
@@ -5512,15 +5645,15 @@ async function initIdP(targetDir) {
|
|
|
5512
5645
|
"s3 (S3-compatible)"
|
|
5513
5646
|
]);
|
|
5514
5647
|
const adminEmail = await promptText("Admin email");
|
|
5515
|
-
|
|
5648
|
+
consola34.start("Scaffolding IdP starter...");
|
|
5516
5649
|
await downloadTemplate("openape-ai/openape-idp-starter", dir);
|
|
5517
|
-
|
|
5518
|
-
|
|
5650
|
+
consola34.success("Scaffolded from openape-idp-starter");
|
|
5651
|
+
consola34.start("Installing dependencies...");
|
|
5519
5652
|
installDeps(dir);
|
|
5520
|
-
|
|
5653
|
+
consola34.success("Dependencies installed");
|
|
5521
5654
|
const sessionSecret = randomBytes(32).toString("hex");
|
|
5522
5655
|
const managementToken = randomBytes(32).toString("hex");
|
|
5523
|
-
|
|
5656
|
+
consola34.success("Secrets generated");
|
|
5524
5657
|
const isLocalhost = domain === "localhost";
|
|
5525
5658
|
const origin = isLocalhost ? "http://localhost:3000" : `https://${domain}`;
|
|
5526
5659
|
const envContent = [
|
|
@@ -5536,9 +5669,9 @@ async function initIdP(targetDir) {
|
|
|
5536
5669
|
].join("\n");
|
|
5537
5670
|
writeFileSync8(join11(dir, ".env"), `${envContent}
|
|
5538
5671
|
`, { mode: 384 });
|
|
5539
|
-
|
|
5672
|
+
consola34.success(".env created");
|
|
5540
5673
|
console.log("");
|
|
5541
|
-
|
|
5674
|
+
consola34.box([
|
|
5542
5675
|
`cd ${dir}`,
|
|
5543
5676
|
"npm run dev",
|
|
5544
5677
|
"",
|
|
@@ -5558,8 +5691,8 @@ import { Buffer as Buffer5 } from "buffer";
|
|
|
5558
5691
|
import { existsSync as existsSync13, readFileSync as readFileSync11 } from "fs";
|
|
5559
5692
|
import { execFile as execFile2 } from "child_process";
|
|
5560
5693
|
import { sign as sign2 } from "crypto";
|
|
5561
|
-
import { defineCommand as
|
|
5562
|
-
import
|
|
5694
|
+
import { defineCommand as defineCommand43 } from "citty";
|
|
5695
|
+
import consola35 from "consola";
|
|
5563
5696
|
var DEFAULT_IDP_URL2 = "https://id.openape.at";
|
|
5564
5697
|
var DEFAULT_KEY_PATH = "~/.ssh/id_ed25519";
|
|
5565
5698
|
var POLL_INTERVAL = 3e3;
|
|
@@ -5602,7 +5735,7 @@ async function pollForEnrollment(idp, agentEmail, keyPath) {
|
|
|
5602
5735
|
}
|
|
5603
5736
|
throw new Error("Enrollment timed out. Please check the browser and try again.");
|
|
5604
5737
|
}
|
|
5605
|
-
var enrollCommand =
|
|
5738
|
+
var enrollCommand = defineCommand43({
|
|
5606
5739
|
meta: {
|
|
5607
5740
|
name: "enroll",
|
|
5608
5741
|
description: "Enroll an agent with an Identity Provider"
|
|
@@ -5622,18 +5755,18 @@ var enrollCommand = defineCommand42({
|
|
|
5622
5755
|
}
|
|
5623
5756
|
},
|
|
5624
5757
|
async run({ args }) {
|
|
5625
|
-
const idp = args.idp || await
|
|
5758
|
+
const idp = args.idp || await consola35.prompt("IdP URL", { type: "text", default: DEFAULT_IDP_URL2, placeholder: DEFAULT_IDP_URL2 }).then((r) => {
|
|
5626
5759
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
5627
5760
|
return r;
|
|
5628
5761
|
}) || DEFAULT_IDP_URL2;
|
|
5629
|
-
const agentName = args.name || await
|
|
5762
|
+
const agentName = args.name || await consola35.prompt("Agent name", { type: "text", placeholder: "deploy-bot" }).then((r) => {
|
|
5630
5763
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
5631
5764
|
return r;
|
|
5632
5765
|
});
|
|
5633
5766
|
if (!agentName) {
|
|
5634
5767
|
throw new CliError("Agent name is required.");
|
|
5635
5768
|
}
|
|
5636
|
-
const keyPath = args.key || await
|
|
5769
|
+
const keyPath = args.key || await consola35.prompt("Ed25519 key", { type: "text", default: DEFAULT_KEY_PATH, placeholder: DEFAULT_KEY_PATH }).then((r) => {
|
|
5637
5770
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
5638
5771
|
return r;
|
|
5639
5772
|
}) || DEFAULT_KEY_PATH;
|
|
@@ -5641,19 +5774,19 @@ var enrollCommand = defineCommand42({
|
|
|
5641
5774
|
let publicKey;
|
|
5642
5775
|
if (existsSync13(resolvedKey)) {
|
|
5643
5776
|
publicKey = readPublicKey(resolvedKey);
|
|
5644
|
-
|
|
5777
|
+
consola35.success(`Using existing key ${keyPath}`);
|
|
5645
5778
|
} else {
|
|
5646
|
-
|
|
5779
|
+
consola35.start(`Generating Ed25519 key pair at ${keyPath}...`);
|
|
5647
5780
|
publicKey = generateAndSaveKey(keyPath);
|
|
5648
|
-
|
|
5781
|
+
consola35.success(`Key pair generated at ${keyPath}`);
|
|
5649
5782
|
}
|
|
5650
5783
|
const encodedKey = encodeURIComponent(publicKey);
|
|
5651
5784
|
const enrollUrl = `${idp}/enroll?name=${encodeURIComponent(agentName)}&key=${encodedKey}`;
|
|
5652
|
-
|
|
5653
|
-
|
|
5785
|
+
consola35.info("Opening browser for enrollment...");
|
|
5786
|
+
consola35.info(`\u2192 ${idp}/enroll`);
|
|
5654
5787
|
openBrowser2(enrollUrl);
|
|
5655
5788
|
console.log("");
|
|
5656
|
-
const agentEmail = await
|
|
5789
|
+
const agentEmail = await consola35.prompt(
|
|
5657
5790
|
"Agent email (shown in browser after enrollment)",
|
|
5658
5791
|
{ type: "text", placeholder: `agent+${agentName}@...` }
|
|
5659
5792
|
).then((r) => {
|
|
@@ -5663,7 +5796,7 @@ var enrollCommand = defineCommand42({
|
|
|
5663
5796
|
if (!agentEmail) {
|
|
5664
5797
|
throw new CliError("Agent email is required to verify enrollment.");
|
|
5665
5798
|
}
|
|
5666
|
-
|
|
5799
|
+
consola35.start("Verifying enrollment...");
|
|
5667
5800
|
const { token, expiresIn } = await pollForEnrollment(idp, agentEmail, keyPath);
|
|
5668
5801
|
saveAuth({
|
|
5669
5802
|
idp,
|
|
@@ -5675,18 +5808,18 @@ var enrollCommand = defineCommand42({
|
|
|
5675
5808
|
config.defaults = { ...config.defaults, idp };
|
|
5676
5809
|
config.agent = { key: keyPath, email: agentEmail };
|
|
5677
5810
|
saveConfig(config);
|
|
5678
|
-
|
|
5679
|
-
|
|
5811
|
+
consola35.success(`Agent enrolled as ${agentEmail}`);
|
|
5812
|
+
consola35.success("Config saved to ~/.config/apes/");
|
|
5680
5813
|
console.log("");
|
|
5681
|
-
|
|
5814
|
+
consola35.info("Verify with: apes whoami");
|
|
5682
5815
|
}
|
|
5683
5816
|
});
|
|
5684
5817
|
|
|
5685
5818
|
// src/commands/register-user.ts
|
|
5686
5819
|
import { existsSync as existsSync14, readFileSync as readFileSync12 } from "fs";
|
|
5687
|
-
import { defineCommand as
|
|
5688
|
-
import
|
|
5689
|
-
var registerUserCommand =
|
|
5820
|
+
import { defineCommand as defineCommand44 } from "citty";
|
|
5821
|
+
import consola36 from "consola";
|
|
5822
|
+
var registerUserCommand = defineCommand44({
|
|
5690
5823
|
meta: {
|
|
5691
5824
|
name: "register-user",
|
|
5692
5825
|
description: "Register a sub-user with SSH key"
|
|
@@ -5741,18 +5874,18 @@ var registerUserCommand = defineCommand43({
|
|
|
5741
5874
|
...userType ? { type: userType } : {}
|
|
5742
5875
|
}
|
|
5743
5876
|
});
|
|
5744
|
-
|
|
5877
|
+
consola36.success(`User registered: ${result.email} (type: ${result.type}, owner: ${result.owner})`);
|
|
5745
5878
|
}
|
|
5746
5879
|
});
|
|
5747
5880
|
|
|
5748
5881
|
// src/commands/utils/index.ts
|
|
5749
|
-
import { defineCommand as
|
|
5882
|
+
import { defineCommand as defineCommand46 } from "citty";
|
|
5750
5883
|
|
|
5751
5884
|
// src/commands/utils/dig.ts
|
|
5752
|
-
import { defineCommand as
|
|
5753
|
-
import
|
|
5885
|
+
import { defineCommand as defineCommand45 } from "citty";
|
|
5886
|
+
import consola37 from "consola";
|
|
5754
5887
|
import { resolveDDISA as resolveDDISA2 } from "@openape/core";
|
|
5755
|
-
var digCommand =
|
|
5888
|
+
var digCommand = defineCommand45({
|
|
5756
5889
|
meta: {
|
|
5757
5890
|
name: "dig",
|
|
5758
5891
|
description: "Resolve DDISA IdP for a domain or email (admin/diag tool)"
|
|
@@ -5825,12 +5958,12 @@ var digCommand = defineCommand44({
|
|
|
5825
5958
|
console.log(` domain: ${domain}`);
|
|
5826
5959
|
console.log("");
|
|
5827
5960
|
if (!result.ddisa.found) {
|
|
5828
|
-
|
|
5961
|
+
consola37.warn(`No DDISA record at _ddisa.${domain}`);
|
|
5829
5962
|
if (result.hint) console.log(`
|
|
5830
5963
|
${result.hint}`);
|
|
5831
5964
|
throw new CliError(`No DDISA record found for ${domain}`);
|
|
5832
5965
|
}
|
|
5833
|
-
|
|
5966
|
+
consola37.success(`_ddisa.${domain} \u2192 ${result.ddisa.idp}`);
|
|
5834
5967
|
console.log(` Version: ${result.ddisa.version || "ddisa1"}`);
|
|
5835
5968
|
console.log(` IdP URL: ${result.ddisa.idp}`);
|
|
5836
5969
|
if (result.ddisa.mode) console.log(` Mode: ${result.ddisa.mode}`);
|
|
@@ -5840,13 +5973,13 @@ ${result.hint}`);
|
|
|
5840
5973
|
return;
|
|
5841
5974
|
}
|
|
5842
5975
|
if (result.idpDiscovery.ok) {
|
|
5843
|
-
|
|
5976
|
+
consola37.success(`IdP reachable (${result.idpDiscovery.status ?? 200})`);
|
|
5844
5977
|
if (result.idpDiscovery.issuer) console.log(` Issuer: ${result.idpDiscovery.issuer}`);
|
|
5845
5978
|
if (result.idpDiscovery.ddisaVersion) console.log(` DDISA: v${result.idpDiscovery.ddisaVersion}`);
|
|
5846
5979
|
if (result.idpDiscovery.authMethods?.length) console.log(` Auth: ${result.idpDiscovery.authMethods.join(", ")}`);
|
|
5847
5980
|
if (result.idpDiscovery.grantTypes?.length) console.log(` Grants: ${result.idpDiscovery.grantTypes.join(", ")}`);
|
|
5848
5981
|
} else {
|
|
5849
|
-
|
|
5982
|
+
consola37.warn(`IdP discovery failed${result.idpDiscovery.status ? ` (HTTP ${result.idpDiscovery.status})` : ""}`);
|
|
5850
5983
|
if (result.hint) console.log(`
|
|
5851
5984
|
${result.hint}`);
|
|
5852
5985
|
throw new CliError(`IdP at ${result.ddisa.idp} not reachable`);
|
|
@@ -5855,7 +5988,7 @@ ${result.hint}`);
|
|
|
5855
5988
|
});
|
|
5856
5989
|
|
|
5857
5990
|
// src/commands/utils/index.ts
|
|
5858
|
-
var utilsCommand =
|
|
5991
|
+
var utilsCommand = defineCommand46({
|
|
5859
5992
|
meta: {
|
|
5860
5993
|
name: "utils",
|
|
5861
5994
|
description: "Admin/diagnostic utilities (dig, \u2026)"
|
|
@@ -5866,12 +5999,12 @@ var utilsCommand = defineCommand45({
|
|
|
5866
5999
|
});
|
|
5867
6000
|
|
|
5868
6001
|
// src/commands/sessions/index.ts
|
|
5869
|
-
import { defineCommand as
|
|
6002
|
+
import { defineCommand as defineCommand49 } from "citty";
|
|
5870
6003
|
|
|
5871
6004
|
// src/commands/sessions/list.ts
|
|
5872
|
-
import { defineCommand as
|
|
5873
|
-
import
|
|
5874
|
-
var sessionsListCommand =
|
|
6005
|
+
import { defineCommand as defineCommand47 } from "citty";
|
|
6006
|
+
import consola38 from "consola";
|
|
6007
|
+
var sessionsListCommand = defineCommand47({
|
|
5875
6008
|
meta: {
|
|
5876
6009
|
name: "list",
|
|
5877
6010
|
description: "List your active refresh-token families (one per logged-in device)."
|
|
@@ -5889,7 +6022,7 @@ var sessionsListCommand = defineCommand46({
|
|
|
5889
6022
|
return;
|
|
5890
6023
|
}
|
|
5891
6024
|
if (result.data.length === 0) {
|
|
5892
|
-
|
|
6025
|
+
consola38.info("No active sessions.");
|
|
5893
6026
|
return;
|
|
5894
6027
|
}
|
|
5895
6028
|
for (const f of result.data) {
|
|
@@ -5901,9 +6034,9 @@ var sessionsListCommand = defineCommand46({
|
|
|
5901
6034
|
});
|
|
5902
6035
|
|
|
5903
6036
|
// src/commands/sessions/remove.ts
|
|
5904
|
-
import { defineCommand as
|
|
5905
|
-
import
|
|
5906
|
-
var sessionsRemoveCommand =
|
|
6037
|
+
import { defineCommand as defineCommand48 } from "citty";
|
|
6038
|
+
import consola39 from "consola";
|
|
6039
|
+
var sessionsRemoveCommand = defineCommand48({
|
|
5907
6040
|
meta: {
|
|
5908
6041
|
name: "remove",
|
|
5909
6042
|
description: "Revoke one of your active refresh-token families by id."
|
|
@@ -5919,12 +6052,12 @@ var sessionsRemoveCommand = defineCommand47({
|
|
|
5919
6052
|
const id = String(args.familyId).trim();
|
|
5920
6053
|
if (!id) throw new CliError("familyId required");
|
|
5921
6054
|
await apiFetch(`/api/me/sessions/${encodeURIComponent(id)}`, { method: "DELETE" });
|
|
5922
|
-
|
|
6055
|
+
consola39.success(`Session ${id} revoked. The device using it will need to \`apes login\` again on its next refresh.`);
|
|
5923
6056
|
}
|
|
5924
6057
|
});
|
|
5925
6058
|
|
|
5926
6059
|
// src/commands/sessions/index.ts
|
|
5927
|
-
var sessionsCommand =
|
|
6060
|
+
var sessionsCommand = defineCommand49({
|
|
5928
6061
|
meta: {
|
|
5929
6062
|
name: "sessions",
|
|
5930
6063
|
description: "Manage your active refresh-token sessions across devices"
|
|
@@ -5936,10 +6069,10 @@ var sessionsCommand = defineCommand48({
|
|
|
5936
6069
|
});
|
|
5937
6070
|
|
|
5938
6071
|
// src/commands/dns-check.ts
|
|
5939
|
-
import { defineCommand as
|
|
5940
|
-
import
|
|
6072
|
+
import { defineCommand as defineCommand50 } from "citty";
|
|
6073
|
+
import consola40 from "consola";
|
|
5941
6074
|
import { resolveDDISA as resolveDDISA3 } from "@openape/core";
|
|
5942
|
-
var dnsCheckCommand =
|
|
6075
|
+
var dnsCheckCommand = defineCommand50({
|
|
5943
6076
|
meta: {
|
|
5944
6077
|
name: "dns-check",
|
|
5945
6078
|
description: "Validate DDISA DNS TXT records for a domain"
|
|
@@ -5953,7 +6086,7 @@ var dnsCheckCommand = defineCommand49({
|
|
|
5953
6086
|
},
|
|
5954
6087
|
async run({ args }) {
|
|
5955
6088
|
const domain = args.domain;
|
|
5956
|
-
|
|
6089
|
+
consola40.start(`Checking _ddisa.${domain}...`);
|
|
5957
6090
|
try {
|
|
5958
6091
|
const result = await resolveDDISA3(domain);
|
|
5959
6092
|
if (!result) {
|
|
@@ -5962,7 +6095,7 @@ var dnsCheckCommand = defineCommand49({
|
|
|
5962
6095
|
console.log(` _ddisa.${domain} TXT "v=ddisa1 idp=https://id.${domain}"`);
|
|
5963
6096
|
throw new CliError(`No DDISA record found for ${domain}`);
|
|
5964
6097
|
}
|
|
5965
|
-
|
|
6098
|
+
consola40.success(`_ddisa.${domain} \u2192 ${result.idp}`);
|
|
5966
6099
|
console.log("");
|
|
5967
6100
|
console.log(` Version: ${result.version || "ddisa1"}`);
|
|
5968
6101
|
console.log(` IdP URL: ${result.idp}`);
|
|
@@ -5971,14 +6104,14 @@ var dnsCheckCommand = defineCommand49({
|
|
|
5971
6104
|
if (result.priority !== void 0)
|
|
5972
6105
|
console.log(` Priority: ${result.priority}`);
|
|
5973
6106
|
console.log("");
|
|
5974
|
-
|
|
6107
|
+
consola40.start(`Verifying IdP at ${result.idp}...`);
|
|
5975
6108
|
const discoResp = await fetch(`${result.idp}/.well-known/openid-configuration`);
|
|
5976
6109
|
if (!discoResp.ok) {
|
|
5977
|
-
|
|
6110
|
+
consola40.warn(`IdP discovery failed (${discoResp.status}). Is the IdP running at ${result.idp}?`);
|
|
5978
6111
|
return;
|
|
5979
6112
|
}
|
|
5980
6113
|
const disco = await discoResp.json();
|
|
5981
|
-
|
|
6114
|
+
consola40.success(`IdP is reachable`);
|
|
5982
6115
|
console.log(` Issuer: ${disco.issuer}`);
|
|
5983
6116
|
console.log(` DDISA: v${disco.ddisa_version || "?"}`);
|
|
5984
6117
|
if (disco.ddisa_auth_methods_supported) {
|
|
@@ -5996,7 +6129,7 @@ var dnsCheckCommand = defineCommand49({
|
|
|
5996
6129
|
// src/commands/health.ts
|
|
5997
6130
|
import { exec } from "child_process";
|
|
5998
6131
|
import { promisify } from "util";
|
|
5999
|
-
import { defineCommand as
|
|
6132
|
+
import { defineCommand as defineCommand51 } from "citty";
|
|
6000
6133
|
var execAsync = promisify(exec);
|
|
6001
6134
|
async function resolveApeShellPath() {
|
|
6002
6135
|
try {
|
|
@@ -6032,7 +6165,7 @@ async function bestEffortGrantCount(idp) {
|
|
|
6032
6165
|
}
|
|
6033
6166
|
}
|
|
6034
6167
|
async function runHealth(args) {
|
|
6035
|
-
const version = true ? "1.
|
|
6168
|
+
const version = true ? "1.5.0" : "0.0.0";
|
|
6036
6169
|
const auth = loadAuth();
|
|
6037
6170
|
if (!auth) {
|
|
6038
6171
|
throw new CliError("Not logged in. Run `apes login` first.", 1);
|
|
@@ -6095,7 +6228,7 @@ async function runHealth(args) {
|
|
|
6095
6228
|
throw new CliError(`IdP ${auth.idp} unreachable: ${idpProbe.error}`, 1);
|
|
6096
6229
|
}
|
|
6097
6230
|
}
|
|
6098
|
-
var healthCommand =
|
|
6231
|
+
var healthCommand = defineCommand51({
|
|
6099
6232
|
meta: {
|
|
6100
6233
|
name: "health",
|
|
6101
6234
|
description: "Report CLI diagnostic state (auth, IdP, grants, binaries)"
|
|
@@ -6113,8 +6246,8 @@ var healthCommand = defineCommand50({
|
|
|
6113
6246
|
});
|
|
6114
6247
|
|
|
6115
6248
|
// src/commands/workflows.ts
|
|
6116
|
-
import { defineCommand as
|
|
6117
|
-
import
|
|
6249
|
+
import { defineCommand as defineCommand52 } from "citty";
|
|
6250
|
+
import consola41 from "consola";
|
|
6118
6251
|
|
|
6119
6252
|
// src/guides/index.ts
|
|
6120
6253
|
var guides = [
|
|
@@ -6164,7 +6297,7 @@ var guides = [
|
|
|
6164
6297
|
];
|
|
6165
6298
|
|
|
6166
6299
|
// src/commands/workflows.ts
|
|
6167
|
-
var workflowsCommand =
|
|
6300
|
+
var workflowsCommand = defineCommand52({
|
|
6168
6301
|
meta: {
|
|
6169
6302
|
name: "workflows",
|
|
6170
6303
|
description: "Discover workflow guides"
|
|
@@ -6185,7 +6318,7 @@ var workflowsCommand = defineCommand51({
|
|
|
6185
6318
|
if (args.id) {
|
|
6186
6319
|
const guide = guides.find((g) => g.id === String(args.id));
|
|
6187
6320
|
if (!guide) {
|
|
6188
|
-
|
|
6321
|
+
consola41.info(`Available: ${guides.map((g) => g.id).join(", ")}`);
|
|
6189
6322
|
throw new CliError(`Guide not found: ${args.id}`);
|
|
6190
6323
|
}
|
|
6191
6324
|
if (args.json) {
|
|
@@ -6228,7 +6361,7 @@ var workflowsCommand = defineCommand51({
|
|
|
6228
6361
|
import { existsSync as existsSync15, mkdirSync as mkdirSync5, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "fs";
|
|
6229
6362
|
import { homedir as homedir12 } from "os";
|
|
6230
6363
|
import { join as join12 } from "path";
|
|
6231
|
-
import
|
|
6364
|
+
import consola42 from "consola";
|
|
6232
6365
|
var PACKAGE_NAME = "@openape/apes";
|
|
6233
6366
|
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
6234
6367
|
var CACHE_FILE = join12(homedir12(), ".config", "apes", ".version-check.json");
|
|
@@ -6273,7 +6406,7 @@ async function fetchLatestVersion() {
|
|
|
6273
6406
|
}
|
|
6274
6407
|
function warnIfBehind(currentVersion, latest) {
|
|
6275
6408
|
if (compareSemver(currentVersion, latest) < 0) {
|
|
6276
|
-
|
|
6409
|
+
consola42.warn(
|
|
6277
6410
|
`apes ${currentVersion} is behind latest @openape/apes@${latest}. Run \`npm i -g @openape/apes@latest\` to update. (Suppress with APES_NO_UPDATE_CHECK=1.)`
|
|
6278
6411
|
);
|
|
6279
6412
|
}
|
|
@@ -6305,10 +6438,10 @@ if (shellRewrite) {
|
|
|
6305
6438
|
if (shellRewrite.action === "rewrite") {
|
|
6306
6439
|
process.argv = shellRewrite.argv;
|
|
6307
6440
|
} else if (shellRewrite.action === "version") {
|
|
6308
|
-
console.log(`ape-shell ${"1.
|
|
6441
|
+
console.log(`ape-shell ${"1.5.0"} (OpenApe DDISA shell wrapper)`);
|
|
6309
6442
|
process.exit(0);
|
|
6310
6443
|
} else if (shellRewrite.action === "help") {
|
|
6311
|
-
console.log(`ape-shell ${"1.
|
|
6444
|
+
console.log(`ape-shell ${"1.5.0"} \u2014 OpenApe DDISA shell wrapper`);
|
|
6312
6445
|
console.log("");
|
|
6313
6446
|
console.log("Usage:");
|
|
6314
6447
|
console.log(" ape-shell Start interactive grant-mediated REPL");
|
|
@@ -6332,7 +6465,7 @@ if (shellRewrite) {
|
|
|
6332
6465
|
}
|
|
6333
6466
|
}
|
|
6334
6467
|
var debug = process.argv.includes("--debug");
|
|
6335
|
-
var grantsCommand =
|
|
6468
|
+
var grantsCommand = defineCommand53({
|
|
6336
6469
|
meta: {
|
|
6337
6470
|
name: "grants",
|
|
6338
6471
|
description: "Grant management"
|
|
@@ -6353,7 +6486,7 @@ var grantsCommand = defineCommand52({
|
|
|
6353
6486
|
"delegation-revoke": delegationRevokeCommand
|
|
6354
6487
|
}
|
|
6355
6488
|
});
|
|
6356
|
-
var configCommand =
|
|
6489
|
+
var configCommand = defineCommand53({
|
|
6357
6490
|
meta: {
|
|
6358
6491
|
name: "config",
|
|
6359
6492
|
description: "Configuration management"
|
|
@@ -6363,10 +6496,10 @@ var configCommand = defineCommand52({
|
|
|
6363
6496
|
set: configSetCommand
|
|
6364
6497
|
}
|
|
6365
6498
|
});
|
|
6366
|
-
var main =
|
|
6499
|
+
var main = defineCommand53({
|
|
6367
6500
|
meta: {
|
|
6368
6501
|
name: "apes",
|
|
6369
|
-
version: "1.
|
|
6502
|
+
version: "1.5.0",
|
|
6370
6503
|
description: "Unified CLI for OpenApe"
|
|
6371
6504
|
},
|
|
6372
6505
|
subCommands: {
|
|
@@ -6422,20 +6555,20 @@ async function maybeRefreshAuth() {
|
|
|
6422
6555
|
}
|
|
6423
6556
|
}
|
|
6424
6557
|
await maybeRefreshAuth();
|
|
6425
|
-
await maybeWarnStaleVersion("1.
|
|
6558
|
+
await maybeWarnStaleVersion("1.5.0").catch(() => {
|
|
6426
6559
|
});
|
|
6427
6560
|
runMain(main).catch((err) => {
|
|
6428
6561
|
if (err instanceof CliExit) {
|
|
6429
6562
|
process.exit(err.exitCode);
|
|
6430
6563
|
}
|
|
6431
6564
|
if (err instanceof CliError) {
|
|
6432
|
-
|
|
6565
|
+
consola43.error(err.message);
|
|
6433
6566
|
process.exit(err.exitCode);
|
|
6434
6567
|
}
|
|
6435
6568
|
if (debug) {
|
|
6436
|
-
|
|
6569
|
+
consola43.error(err);
|
|
6437
6570
|
} else {
|
|
6438
|
-
|
|
6571
|
+
consola43.error(err instanceof ApiError ? err.message : err instanceof Error ? err.message : String(err));
|
|
6439
6572
|
}
|
|
6440
6573
|
process.exit(1);
|
|
6441
6574
|
});
|