@consiliency/agent-board-cli 1.2.0 → 1.4.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.d.ts +26 -2
- package/dist/cli.js +113 -4
- package/package.json +11 -10
package/dist/cli.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
+
import { type EnrollmentIntent, type PendingEnrollmentStore } from "@consiliency/agent-board-client";
|
|
2
3
|
type JsonObject = Record<string, unknown>;
|
|
3
4
|
export interface CliIo {
|
|
4
5
|
writeStdout(message: string): void;
|
|
@@ -100,6 +101,29 @@ export declare function signingStatusFromEnv(env?: NodeJS.ProcessEnv): {
|
|
|
100
101
|
redacted: boolean;
|
|
101
102
|
};
|
|
102
103
|
};
|
|
103
|
-
export
|
|
104
|
-
|
|
104
|
+
export interface EnrollmentCommandRunner {
|
|
105
|
+
run(input: {
|
|
106
|
+
slug: string;
|
|
107
|
+
intent: EnrollmentIntent;
|
|
108
|
+
agentKind?: string;
|
|
109
|
+
requestedScopes?: string[];
|
|
110
|
+
requestedBoardScopes?: string[];
|
|
111
|
+
}): Promise<unknown>;
|
|
112
|
+
begin(input: {
|
|
113
|
+
slug: string;
|
|
114
|
+
intent: EnrollmentIntent;
|
|
115
|
+
agentKind?: string;
|
|
116
|
+
requestedScopes?: string[];
|
|
117
|
+
oob?: boolean;
|
|
118
|
+
}): Promise<unknown>;
|
|
119
|
+
complete(input: {
|
|
120
|
+
enrollmentId: string;
|
|
121
|
+
code?: string;
|
|
122
|
+
redirectResponse?: string;
|
|
123
|
+
slug?: string;
|
|
124
|
+
}): Promise<unknown>;
|
|
125
|
+
}
|
|
126
|
+
export declare function defaultEnrollmentRunner(env?: NodeJS.ProcessEnv, store?: PendingEnrollmentStore): EnrollmentCommandRunner;
|
|
127
|
+
export declare function createProgram(client: ClientLike, io: CliIo, enrollment?: EnrollmentCommandRunner): Command;
|
|
128
|
+
export declare function runCli(argv: string[], io?: CliIo, client?: ClientLike, enrollment?: EnrollmentCommandRunner): Promise<void>;
|
|
105
129
|
export {};
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Command, Option } from "commander";
|
|
2
|
-
import { createAgentBoardClient, toOperationFailure, } from "@consiliency/agent-board-client";
|
|
2
|
+
import { createAgentBoardClient, toOperationFailure, beginEnrollment, completeEnrollment, runEnrollment, resolveEnrollmentDescriptor, InMemoryPendingEnrollmentStore, } from "@consiliency/agent-board-client";
|
|
3
3
|
function isRuntimeStatus(value) {
|
|
4
4
|
return Boolean(value && typeof value === "object" && "runtime" in value);
|
|
5
5
|
}
|
|
@@ -1207,7 +1207,115 @@ function addReadCommands(program, client, io) {
|
|
|
1207
1207
|
limit: options.limit,
|
|
1208
1208
|
})));
|
|
1209
1209
|
}
|
|
1210
|
-
|
|
1210
|
+
// The default runner resolves the env descriptor (proving configuration) and then
|
|
1211
|
+
// requires a host-provided keystore integration. Live enrollment (generating the
|
|
1212
|
+
// agent key in an OS keychain/TPM/HSM and opening the browser) is gated on the
|
|
1213
|
+
// external Portal integration (E1/E2); the command + wiring exist here.
|
|
1214
|
+
export function defaultEnrollmentRunner(env = process.env, store = new InMemoryPendingEnrollmentStore()) {
|
|
1215
|
+
const notConfigured = () => {
|
|
1216
|
+
throw new Error("live enrollment requires a configured keystore backend (os_keychain/tpm/agent_socket/hsm) " +
|
|
1217
|
+
"and browser opener; the environment descriptor resolved but no keystore integration is wired");
|
|
1218
|
+
};
|
|
1219
|
+
return {
|
|
1220
|
+
async run(input) {
|
|
1221
|
+
resolveEnrollmentDescriptor(env);
|
|
1222
|
+
void beginEnrollment;
|
|
1223
|
+
void completeEnrollment;
|
|
1224
|
+
void runEnrollment;
|
|
1225
|
+
void store;
|
|
1226
|
+
void input;
|
|
1227
|
+
return notConfigured();
|
|
1228
|
+
},
|
|
1229
|
+
async begin(input) {
|
|
1230
|
+
resolveEnrollmentDescriptor(env);
|
|
1231
|
+
void input;
|
|
1232
|
+
return notConfigured();
|
|
1233
|
+
},
|
|
1234
|
+
async complete(input) {
|
|
1235
|
+
void input;
|
|
1236
|
+
return notConfigured();
|
|
1237
|
+
},
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
function intentFromOptions(options) {
|
|
1241
|
+
if (options.joinBoard) {
|
|
1242
|
+
return { kind: "join_board", boardId: options.joinBoard };
|
|
1243
|
+
}
|
|
1244
|
+
const slug = options.createBoard ?? options.slug ?? "";
|
|
1245
|
+
return {
|
|
1246
|
+
kind: "create_board",
|
|
1247
|
+
slug,
|
|
1248
|
+
name: options.boardName ?? slug,
|
|
1249
|
+
description: options.boardDescription,
|
|
1250
|
+
visibility: options.visibility,
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
function csv(value) {
|
|
1254
|
+
return value
|
|
1255
|
+
? String(value)
|
|
1256
|
+
.split(",")
|
|
1257
|
+
.map((v) => v.trim())
|
|
1258
|
+
.filter(Boolean)
|
|
1259
|
+
: undefined;
|
|
1260
|
+
}
|
|
1261
|
+
function addEnrollCommands(program, io, enrollment) {
|
|
1262
|
+
const enroll = program
|
|
1263
|
+
.command("enroll")
|
|
1264
|
+
.description("enroll this agent via OAuth auth-code+PKCE and provision a board");
|
|
1265
|
+
// One-shot loopback flow. It is a DEFAULT subcommand (isDefault) so bare
|
|
1266
|
+
// `enroll ...` runs it, while keeping its options off the parent — otherwise a
|
|
1267
|
+
// parent-level --slug shadows the begin/complete subcommands' own --slug.
|
|
1268
|
+
enroll
|
|
1269
|
+
.command("run", { isDefault: true })
|
|
1270
|
+
.description("one-shot enrollment over an RFC 8252 loopback receiver")
|
|
1271
|
+
.requiredOption("--slug <slug>", "desired agent slug")
|
|
1272
|
+
.option("--agent-kind <kind>", "agent kind (default 'agent')")
|
|
1273
|
+
.option("--create-board <slug>", "create-board intent slug")
|
|
1274
|
+
.option("--board-name <name>", "board name for create-board")
|
|
1275
|
+
.option("--board-description <description>", "board description")
|
|
1276
|
+
.option("--visibility <visibility>", "board visibility")
|
|
1277
|
+
.option("--join-board <boardId>", "join-board intent board id")
|
|
1278
|
+
.option("--requested-scopes <csv>", "requested scopes (comma-separated)")
|
|
1279
|
+
.option("--requested-board-scopes <csv>", "requested board scopes (comma-separated)")
|
|
1280
|
+
.action((options) => runHandler(io, "agent_board.enroll", () => enrollment.run({
|
|
1281
|
+
slug: options.slug,
|
|
1282
|
+
agentKind: options.agentKind,
|
|
1283
|
+
intent: intentFromOptions(options),
|
|
1284
|
+
requestedScopes: csv(options.requestedScopes),
|
|
1285
|
+
requestedBoardScopes: csv(options.requestedBoardScopes),
|
|
1286
|
+
})));
|
|
1287
|
+
enroll
|
|
1288
|
+
.command("begin")
|
|
1289
|
+
.description("begin an enrollment; prints the authorization URL (no code_verifier/state)")
|
|
1290
|
+
.requiredOption("--slug <slug>", "desired agent slug")
|
|
1291
|
+
.option("--agent-kind <kind>", "agent kind")
|
|
1292
|
+
.option("--create-board <slug>", "create-board intent slug")
|
|
1293
|
+
.option("--board-name <name>", "board name for create-board")
|
|
1294
|
+
.option("--join-board <boardId>", "join-board intent board id")
|
|
1295
|
+
.option("--requested-scopes <csv>", "requested scopes (comma-separated)")
|
|
1296
|
+
.option("--oob", "use the out-of-band paste flow instead of loopback")
|
|
1297
|
+
.action((options) => runHandler(io, "agent_board.begin_enrollment", () => enrollment.begin({
|
|
1298
|
+
slug: options.slug,
|
|
1299
|
+
agentKind: options.agentKind,
|
|
1300
|
+
intent: intentFromOptions(options),
|
|
1301
|
+
requestedScopes: csv(options.requestedScopes),
|
|
1302
|
+
oob: Boolean(options.oob),
|
|
1303
|
+
})));
|
|
1304
|
+
enroll
|
|
1305
|
+
.command("complete")
|
|
1306
|
+
.description("complete an enrollment with the authorization code")
|
|
1307
|
+
.requiredOption("--enrollment-id <id>", "the enrollment id from begin")
|
|
1308
|
+
.option("--code <code>", "the authorization code (OOB paste)")
|
|
1309
|
+
.option("--redirect-response <url>", "the full redirect response URL")
|
|
1310
|
+
.option("--slug <slug>", "override the agent slug")
|
|
1311
|
+
.action((options) => runHandler(io, "agent_board.complete_enrollment", () => enrollment.complete({
|
|
1312
|
+
enrollmentId: options.enrollmentId,
|
|
1313
|
+
code: options.code,
|
|
1314
|
+
redirectResponse: options.redirectResponse,
|
|
1315
|
+
slug: options.slug,
|
|
1316
|
+
})));
|
|
1317
|
+
}
|
|
1318
|
+
export function createProgram(client, io, enrollment = defaultEnrollmentRunner()) {
|
|
1211
1319
|
const program = new Command()
|
|
1212
1320
|
.name("agent-board")
|
|
1213
1321
|
.description("Thin CLI surface for the agent_board RPC and canonical read contracts")
|
|
@@ -1228,12 +1336,13 @@ export function createProgram(client, io) {
|
|
|
1228
1336
|
.action((options) => runRuntimeDoctor(io, client, Boolean(options.requireRuntime)));
|
|
1229
1337
|
addWriteCommands(program, client, io);
|
|
1230
1338
|
addReadCommands(program, client, io);
|
|
1339
|
+
addEnrollCommands(program, io, enrollment);
|
|
1231
1340
|
return program;
|
|
1232
1341
|
}
|
|
1233
1342
|
export async function runCli(argv, io = {
|
|
1234
1343
|
writeStdout: (message) => process.stdout.write(message),
|
|
1235
1344
|
writeStderr: (message) => process.stderr.write(message),
|
|
1236
|
-
}, client = createAgentBoardClient()) {
|
|
1237
|
-
const program = createProgram(client, io);
|
|
1345
|
+
}, client = createAgentBoardClient(), enrollment = defaultEnrollmentRunner()) {
|
|
1346
|
+
const program = createProgram(client, io, enrollment);
|
|
1238
1347
|
await program.parseAsync(argv, { from: "user" });
|
|
1239
1348
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@consiliency/agent-board-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"repository": "https://github.com/Consiliency/message-board.git",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -20,18 +20,19 @@
|
|
|
20
20
|
"LICENSE",
|
|
21
21
|
"NOTICE"
|
|
22
22
|
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\" && tsc -p tsconfig.build.json",
|
|
25
|
+
"prepack": "pnpm run build",
|
|
26
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
27
|
+
"test": "vitest run"
|
|
28
|
+
},
|
|
23
29
|
"publishConfig": {
|
|
24
30
|
"access": "public",
|
|
25
31
|
"registry": "https://registry.npmjs.org"
|
|
26
32
|
},
|
|
27
33
|
"dependencies": {
|
|
28
|
-
"
|
|
29
|
-
"
|
|
34
|
+
"@consiliency/agent-board-client": "1.6.0",
|
|
35
|
+
"commander": "^14.0.1"
|
|
30
36
|
},
|
|
31
|
-
"license": "Apache-2.0"
|
|
32
|
-
|
|
33
|
-
"build": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\" && tsc -p tsconfig.build.json",
|
|
34
|
-
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
35
|
-
"test": "vitest run"
|
|
36
|
-
}
|
|
37
|
-
}
|
|
37
|
+
"license": "Apache-2.0"
|
|
38
|
+
}
|