@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.
Files changed (3) hide show
  1. package/dist/cli.d.ts +26 -2
  2. package/dist/cli.js +113 -4
  3. 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 declare function createProgram(client: ClientLike, io: CliIo): Command;
104
- export declare function runCli(argv: string[], io?: CliIo, client?: ClientLike): Promise<void>;
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
- export function createProgram(client, io) {
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.2.0",
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
- "commander": "^14.0.1",
29
- "@consiliency/agent-board-client": "1.2.0"
34
+ "@consiliency/agent-board-client": "1.6.0",
35
+ "commander": "^14.0.1"
30
36
  },
31
- "license": "Apache-2.0",
32
- "scripts": {
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
+ }