@kaelen-ai/cli 0.1.13 → 0.1.15

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/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from 'commander';
3
- import chalk11 from 'chalk';
3
+ import chalk12 from 'chalk';
4
4
  import { writeFile, readFile, mkdtemp, rm, mkdir, stat, readdir } from 'fs/promises';
5
5
  import { join, resolve, dirname, relative, basename, extname, isAbsolute } from 'path';
6
6
  import * as acorn from 'acorn';
@@ -2387,19 +2387,26 @@ function analyzeTopLevel2(body) {
2387
2387
  const imports = [];
2388
2388
  const rootCalls = [];
2389
2389
  for (const stmt of body) {
2390
- if (stmt.type === "ExportNamedDeclaration" || stmt.type === "ExportDefaultDeclaration" || stmt.type === "ExportAllDeclaration") {
2390
+ let candidate = stmt;
2391
+ if (stmt.type === "ExportNamedDeclaration") {
2392
+ const declaration = stmt.declaration;
2393
+ if (!declaration) {
2394
+ continue;
2395
+ }
2396
+ candidate = declaration;
2397
+ } else if (stmt.type === "ExportDefaultDeclaration" || stmt.type === "ExportAllDeclaration") {
2391
2398
  continue;
2392
2399
  }
2393
- if (stmt.type === "ImportDeclaration") {
2394
- const specifiers = stmt.specifiers;
2400
+ if (candidate.type === "ImportDeclaration") {
2401
+ const specifiers = candidate.specifiers;
2395
2402
  if (specifiers.length === 0) {
2396
2403
  continue;
2397
2404
  }
2398
2405
  const info = {
2399
2406
  specifiers: [],
2400
- source: stmt.source.value,
2401
- start: stmt.start,
2402
- end: stmt.end
2407
+ source: candidate.source.value,
2408
+ start: candidate.start,
2409
+ end: candidate.end
2403
2410
  };
2404
2411
  for (const spec of specifiers) {
2405
2412
  const local = spec.local.name;
@@ -2415,20 +2422,20 @@ function analyzeTopLevel2(body) {
2415
2422
  imports.push(info);
2416
2423
  continue;
2417
2424
  }
2418
- if (isRootTargetCall(stmt)) {
2425
+ if (isRootTargetCall(candidate)) {
2419
2426
  rootCalls.push({
2420
- start: stmt.start,
2421
- end: stmt.end
2427
+ start: candidate.start,
2428
+ end: candidate.end
2422
2429
  });
2423
2430
  continue;
2424
2431
  }
2425
2432
  const names = /* @__PURE__ */ new Set();
2426
- if (stmt.type === "VariableDeclaration") {
2427
- for (const declaration of stmt.declarations) {
2433
+ if (candidate.type === "VariableDeclaration") {
2434
+ for (const declaration of candidate.declarations) {
2428
2435
  collectBindingNames2(declaration.id, names);
2429
2436
  }
2430
- } else if (stmt.type === "FunctionDeclaration" || stmt.type === "ClassDeclaration") {
2431
- const id = stmt.id;
2437
+ } else if (candidate.type === "FunctionDeclaration" || candidate.type === "ClassDeclaration") {
2438
+ const id = candidate.id;
2432
2439
  if (id?.type === "Identifier") {
2433
2440
  names.add(id.name);
2434
2441
  }
@@ -2438,7 +2445,7 @@ function analyzeTopLevel2(body) {
2438
2445
  if (names.size === 0) {
2439
2446
  continue;
2440
2447
  }
2441
- const refs = collectRefs2(stmt);
2448
+ const refs = collectRefs2(candidate);
2442
2449
  for (const name of names) {
2443
2450
  refs.delete(name);
2444
2451
  }
@@ -2769,7 +2776,7 @@ async function buildCommand(options) {
2769
2776
  const config = await loadConfig({
2770
2777
  dir: options.dir
2771
2778
  });
2772
- console.log(chalk11.gray("Validating deployment..."));
2779
+ console.log(chalk12.gray("Validating deployment..."));
2773
2780
  stagingDir = await createStagingDir();
2774
2781
  const { manifest } = await buildPipeline(
2775
2782
  config,
@@ -2799,10 +2806,10 @@ async function buildCommand(options) {
2799
2806
  `${subscriptions.length} subscription${subscriptions.length === 1 ? "" : "s"}`,
2800
2807
  `${secretBundles.length} secret bundle${secretBundles.length === 1 ? "" : "s"}`
2801
2808
  ];
2802
- console.log(chalk11.green(`\u2713 Build succeeded (${parts.join(", ")})`));
2809
+ console.log(chalk12.green(`\u2713 Build succeeded (${parts.join(", ")})`));
2803
2810
  } catch (err) {
2804
2811
  if (err instanceof CliError) {
2805
- console.error(chalk11.red(err.message));
2812
+ console.error(chalk12.red(err.message));
2806
2813
  process.exit(1);
2807
2814
  }
2808
2815
  throw err;
@@ -2989,9 +2996,9 @@ function diffManifests(local, remote) {
2989
2996
  };
2990
2997
  }
2991
2998
  var SYMBOLS = {
2992
- added: chalk11.green("+ "),
2993
- changed: chalk11.yellow("~ "),
2994
- removed: chalk11.red("- ")
2999
+ added: chalk12.green("+ "),
3000
+ changed: chalk12.yellow("~ "),
3001
+ removed: chalk12.red("- ")
2995
3002
  };
2996
3003
  var LABELS = {
2997
3004
  added: "new",
@@ -3013,11 +3020,11 @@ function formatPlan(diff) {
3013
3020
  const entries = diff[key];
3014
3021
  lines.push(` ${label}:`);
3015
3022
  if (entries.length === 0) {
3016
- lines.push(chalk11.gray(" (no changes)"));
3023
+ lines.push(chalk12.gray(" (no changes)"));
3017
3024
  } else {
3018
3025
  for (const e of entries) {
3019
3026
  lines.push(
3020
- ` ${SYMBOLS[e.kind]}${e.name} ${chalk11.gray(`(${LABELS[e.kind]})`)}`
3027
+ ` ${SYMBOLS[e.kind]}${e.name} ${chalk12.gray(`(${LABELS[e.kind]})`)}`
3021
3028
  );
3022
3029
  }
3023
3030
  }
@@ -3471,6 +3478,82 @@ function createClient(config) {
3471
3478
  );
3472
3479
  return data.createProject;
3473
3480
  }
3481
+ async function principals2(projectIdValue) {
3482
+ const data = await graphql(
3483
+ `
3484
+ query Principals($projectId: ID!) {
3485
+ principals(projectId: $projectId) {
3486
+ id
3487
+ externalId
3488
+ state
3489
+ metadata
3490
+ projectId
3491
+ insertedAt
3492
+ updatedAt
3493
+ }
3494
+ }
3495
+ `,
3496
+ { projectId: projectIdValue }
3497
+ );
3498
+ return data.principals ?? [];
3499
+ }
3500
+ async function createPrincipal(projectIdValue, input) {
3501
+ const data = await graphql(
3502
+ `
3503
+ mutation CreatePrincipal($projectId: ID!, $input: CreatePrincipalInput!) {
3504
+ createPrincipal(projectId: $projectId, input: $input) {
3505
+ id
3506
+ externalId
3507
+ state
3508
+ metadata
3509
+ projectId
3510
+ insertedAt
3511
+ updatedAt
3512
+ }
3513
+ }
3514
+ `,
3515
+ { projectId: projectIdValue, input }
3516
+ );
3517
+ return data.createPrincipal;
3518
+ }
3519
+ async function updatePrincipal(projectIdValue, id, input) {
3520
+ const data = await graphql(
3521
+ `
3522
+ mutation UpdatePrincipal($projectId: ID!, $id: ID!, $input: UpdatePrincipalInput!) {
3523
+ updatePrincipal(projectId: $projectId, id: $id, input: $input) {
3524
+ id
3525
+ externalId
3526
+ state
3527
+ metadata
3528
+ projectId
3529
+ insertedAt
3530
+ updatedAt
3531
+ }
3532
+ }
3533
+ `,
3534
+ { projectId: projectIdValue, id, input }
3535
+ );
3536
+ return data.updatePrincipal ?? null;
3537
+ }
3538
+ async function deletePrincipal(projectIdValue, id) {
3539
+ const data = await graphql(
3540
+ `
3541
+ mutation DeletePrincipal($projectId: ID!, $id: ID!) {
3542
+ deletePrincipal(projectId: $projectId, id: $id) {
3543
+ id
3544
+ externalId
3545
+ state
3546
+ metadata
3547
+ projectId
3548
+ insertedAt
3549
+ updatedAt
3550
+ }
3551
+ }
3552
+ `,
3553
+ { projectId: projectIdValue, id }
3554
+ );
3555
+ return data.deletePrincipal ?? null;
3556
+ }
3474
3557
  async function listSecrets(projectIdValue) {
3475
3558
  const data = await graphql(
3476
3559
  `
@@ -3591,6 +3674,9 @@ function createClient(config) {
3591
3674
  }
3592
3675
  async function emitSignal(input) {
3593
3676
  const projectIdValue = input.projectId ?? projectId();
3677
+ if (!input.principalId || input.principalId.trim() === "") {
3678
+ throw new ConfigError("principalId is required to emit a signal");
3679
+ }
3594
3680
  const eventName = normalizeRuntimeSignalName2(input.signal);
3595
3681
  if (!eventName) {
3596
3682
  throw new ConfigError(
@@ -3618,6 +3704,7 @@ function createClient(config) {
3618
3704
  {
3619
3705
  input: {
3620
3706
  projectId: projectIdValue,
3707
+ principalId: input.principalId,
3621
3708
  eventName,
3622
3709
  payloadJson: JSON.stringify(input.payload ?? {}),
3623
3710
  metadataJson: JSON.stringify(input.metadata ?? {}),
@@ -3694,6 +3781,10 @@ function createClient(config) {
3694
3781
  organizations,
3695
3782
  projects: projects2,
3696
3783
  createProject,
3784
+ principals: principals2,
3785
+ createPrincipal,
3786
+ updatePrincipal,
3787
+ deletePrincipal,
3697
3788
  listSecrets,
3698
3789
  putSecret,
3699
3790
  deleteSecret,
@@ -3712,7 +3803,7 @@ async function deployCommand(options) {
3712
3803
  const config = await loadConfig({
3713
3804
  dir: options.dir
3714
3805
  });
3715
- console.log(chalk11.gray("Planning deployment..."));
3806
+ console.log(chalk12.gray("Planning deployment..."));
3716
3807
  stagingDir = await createStagingDir();
3717
3808
  const { manifest } = await buildPipeline(
3718
3809
  config,
@@ -3722,7 +3813,7 @@ async function deployCommand(options) {
3722
3813
  );
3723
3814
  if (!config.apiUrl || !config.projectId) {
3724
3815
  console.log(
3725
- chalk11.yellow(
3816
+ chalk12.yellow(
3726
3817
  "\nNo apiUrl or projectId configured. Skipping upload."
3727
3818
  )
3728
3819
  );
@@ -3732,30 +3823,30 @@ async function deployCommand(options) {
3732
3823
  apiUrl: config.apiUrl,
3733
3824
  projectId: config.projectId
3734
3825
  });
3735
- console.log(chalk11.gray("\nComparing with remote..."));
3826
+ console.log(chalk12.gray("\nComparing with remote..."));
3736
3827
  const remoteManifest = await client.fetchRemoteManifest(client.projectId());
3737
3828
  const diff = diffManifests(manifest, remoteManifest);
3738
3829
  if (!diff.hasChanges) {
3739
- console.log(chalk11.green("\n\u2713 No changes to deploy."));
3830
+ console.log(chalk12.green("\n\u2713 No changes to deploy."));
3740
3831
  return;
3741
3832
  }
3742
3833
  console.log("\n" + formatPlan(diff));
3743
3834
  const confirmed = await confirmPlan(options.yes ?? false);
3744
3835
  if (!confirmed) {
3745
- console.log(chalk11.yellow("Deploy cancelled."));
3836
+ console.log(chalk12.yellow("Deploy cancelled."));
3746
3837
  return;
3747
3838
  }
3748
- console.log(chalk11.gray("\nApplying deployment..."));
3839
+ console.log(chalk12.gray("\nApplying deployment..."));
3749
3840
  const zipPath = join(stagingDir, "deploy.zip");
3750
3841
  await zipBuildOutput(stagingDir, zipPath);
3751
3842
  const revision = await client.deployBundle(zipPath, manifest);
3752
3843
  console.log(
3753
- chalk11.green(`
3844
+ chalk12.green(`
3754
3845
  \u2713 Deployment complete (revision ${revision.revision}, ${revision.status})`)
3755
3846
  );
3756
3847
  } catch (err) {
3757
3848
  if (err instanceof CliError) {
3758
- console.error(chalk11.red(err.message));
3849
+ console.error(chalk12.red(err.message));
3759
3850
  process.exit(1);
3760
3851
  }
3761
3852
  throw err;
@@ -3866,7 +3957,7 @@ async function loginCommand(options) {
3866
3957
  try {
3867
3958
  if (options.token) {
3868
3959
  await saveToken(options.token, true);
3869
- console.log(chalk11.green("\u2713 API key saved"));
3960
+ console.log(chalk12.green("\u2713 API key saved"));
3870
3961
  return;
3871
3962
  }
3872
3963
  const config = await loadConfig();
@@ -3877,7 +3968,7 @@ async function loginCommand(options) {
3877
3968
  }
3878
3969
  const existing = await loadToken();
3879
3970
  if (existing) {
3880
- console.log(chalk11.gray("Existing session found. Re-authenticating..."));
3971
+ console.log(chalk12.gray("Existing session found. Re-authenticating..."));
3881
3972
  }
3882
3973
  const callbackServer = await startCallbackServer();
3883
3974
  const pkce = generatePkcePair();
@@ -3887,12 +3978,12 @@ async function loginCommand(options) {
3887
3978
  callbackServer.state,
3888
3979
  pkce.challenge
3889
3980
  );
3890
- console.log(chalk11.gray("Opening your browser for sign-in..."));
3981
+ console.log(chalk12.gray("Opening your browser for sign-in..."));
3891
3982
  try {
3892
3983
  await open(authorizationUrl);
3893
3984
  } catch {
3894
- console.log(chalk11.yellow("Could not open the browser automatically."));
3895
- console.log(chalk11.gray(`Open this URL manually:
3985
+ console.log(chalk12.yellow("Could not open the browser automatically."));
3986
+ console.log(chalk12.gray(`Open this URL manually:
3896
3987
  ${authorizationUrl}`));
3897
3988
  }
3898
3989
  try {
@@ -3916,10 +4007,10 @@ ${authorizationUrl}`));
3916
4007
  } finally {
3917
4008
  callbackServer.close();
3918
4009
  }
3919
- console.log(chalk11.green("\n\u2713 Authenticated successfully"));
4010
+ console.log(chalk12.green("\n\u2713 Authenticated successfully"));
3920
4011
  } catch (err) {
3921
4012
  if (err instanceof CliError) {
3922
- console.error(chalk11.red(err.message));
4013
+ console.error(chalk12.red(err.message));
3923
4014
  process.exit(1);
3924
4015
  }
3925
4016
  throw err;
@@ -3929,10 +4020,10 @@ async function logoutCommand() {
3929
4020
  const creds = await loadCredentials();
3930
4021
  await clearToken();
3931
4022
  if (!creds) {
3932
- console.log(chalk11.yellow("Not logged in."));
4023
+ console.log(chalk12.yellow("Not logged in."));
3933
4024
  return;
3934
4025
  }
3935
- console.log(chalk11.green("\u2713 Logged out"));
4026
+ console.log(chalk12.green("\u2713 Logged out"));
3936
4027
  }
3937
4028
  async function hydrateIdentity() {
3938
4029
  const creds = await loadCredentials();
@@ -3976,26 +4067,26 @@ async function hydrateIdentity() {
3976
4067
  async function whoamiCommand() {
3977
4068
  const { creds, sessionName, sessionEmail } = await hydrateIdentity();
3978
4069
  if (!creds) {
3979
- console.log(chalk11.yellow("Not logged in. Run `io login` to authenticate."));
4070
+ console.log(chalk12.yellow("Not logged in. Run `io login` to authenticate."));
3980
4071
  return;
3981
4072
  }
3982
- console.log(chalk11.green("\u2713 Logged in"));
4073
+ console.log(chalk12.green("\u2713 Logged in"));
3983
4074
  const displayUser = sessionName ?? sessionEmail ?? creds.userId;
3984
4075
  if (displayUser) {
3985
- console.log(chalk11.gray(` User: ${displayUser}`));
4076
+ console.log(chalk12.gray(` User: ${displayUser}`));
3986
4077
  }
3987
4078
  if (sessionEmail && sessionEmail !== displayUser) {
3988
- console.log(chalk11.gray(` Email: ${sessionEmail}`));
4079
+ console.log(chalk12.gray(` Email: ${sessionEmail}`));
3989
4080
  }
3990
4081
  if (creds.organizationId) {
3991
- console.log(chalk11.gray(` Organization: ${creds.organizationId}`));
4082
+ console.log(chalk12.gray(` Organization: ${creds.organizationId}`));
3992
4083
  }
3993
4084
  if (creds.apiKey) {
3994
- console.log(chalk11.gray(" Session: API key"));
4085
+ console.log(chalk12.gray(" Session: API key"));
3995
4086
  } else if (creds.refreshToken) {
3996
- console.log(chalk11.gray(" Session: refresh token stored"));
4087
+ console.log(chalk12.gray(" Session: refresh token stored"));
3997
4088
  } else {
3998
- console.log(chalk11.gray(" Session: token only (no refresh)"));
4089
+ console.log(chalk12.gray(" Session: token only (no refresh)"));
3999
4090
  }
4000
4091
  }
4001
4092
  var CONFIG_FILE = "io.config.json";
@@ -4025,13 +4116,13 @@ async function selectOrganization(organizations, preferredId) {
4025
4116
  if (organizations.length === 1) {
4026
4117
  return organizations[0];
4027
4118
  }
4028
- console.log(chalk11.gray("\nAvailable organizations:"));
4119
+ console.log(chalk12.gray("\nAvailable organizations:"));
4029
4120
  organizations.forEach((organization, index2) => {
4030
4121
  console.log(
4031
- ` ${chalk11.green(String(index2 + 1))}. ${organization.name} ${chalk11.gray(organization.id)}`
4122
+ ` ${chalk12.green(String(index2 + 1))}. ${organization.name} ${chalk12.gray(organization.id)}`
4032
4123
  );
4033
4124
  });
4034
- const choice = await prompt(chalk11.gray("\nSelect an organization (number or ID): "));
4125
+ const choice = await prompt(chalk12.gray("\nSelect an organization (number or ID): "));
4035
4126
  const index = Number(choice);
4036
4127
  if (index > 0 && index <= organizations.length) {
4037
4128
  return organizations[index - 1];
@@ -4044,16 +4135,16 @@ async function initCommand(options) {
4044
4135
  const existing = await readExistingConfig(cwd);
4045
4136
  if (existing.projectId && !options.yes) {
4046
4137
  const overwrite = await prompt(
4047
- chalk11.yellow(`io.config.json already has projectId "${existing.projectId}". Overwrite? (y/n) `)
4138
+ chalk12.yellow(`io.config.json already has projectId "${existing.projectId}". Overwrite? (y/n) `)
4048
4139
  );
4049
4140
  if (overwrite.toLowerCase() !== "y") {
4050
- console.log(chalk11.gray("Cancelled."));
4141
+ console.log(chalk12.gray("Cancelled."));
4051
4142
  return;
4052
4143
  }
4053
4144
  }
4054
4145
  const config = { ...existing };
4055
4146
  if (!config.apiUrl) {
4056
- const apiUrl = await prompt(chalk11.gray("API URL (leave blank for default): "));
4147
+ const apiUrl = await prompt(chalk12.gray("API URL (leave blank for default): "));
4057
4148
  if (apiUrl) {
4058
4149
  config.apiUrl = apiUrl;
4059
4150
  }
@@ -4075,7 +4166,7 @@ async function initCommand(options) {
4075
4166
  try {
4076
4167
  organizations = await client.organizations();
4077
4168
  } catch {
4078
- console.log(chalk11.yellow("Could not fetch organizations. Enter project ID manually."));
4169
+ console.log(chalk12.yellow("Could not fetch organizations. Enter project ID manually."));
4079
4170
  }
4080
4171
  const selectedOrganization = await selectOrganization(
4081
4172
  organizations,
@@ -4084,14 +4175,14 @@ async function initCommand(options) {
4084
4175
  if (selectedOrganization) {
4085
4176
  const projects2 = await client.projects(selectedOrganization.id);
4086
4177
  if (projects2.length > 0) {
4087
- console.log(chalk11.gray("\nAvailable projects:"));
4178
+ console.log(chalk12.gray("\nAvailable projects:"));
4088
4179
  projects2.forEach((project, index2) => {
4089
4180
  console.log(
4090
- ` ${chalk11.green(String(index2 + 1))}. ${project.name} ${chalk11.gray(project.id)}`
4181
+ ` ${chalk12.green(String(index2 + 1))}. ${project.name} ${chalk12.gray(project.id)}`
4091
4182
  );
4092
4183
  });
4093
4184
  const choice = await prompt(
4094
- chalk11.gray("\nSelect a project (number) or enter a project ID: ")
4185
+ chalk12.gray("\nSelect a project (number) or enter a project ID: ")
4095
4186
  );
4096
4187
  const index = Number(choice);
4097
4188
  if (index > 0 && index <= projects2.length) {
@@ -4101,26 +4192,26 @@ async function initCommand(options) {
4101
4192
  }
4102
4193
  } else {
4103
4194
  const createNew = await prompt(
4104
- chalk11.gray("No projects found. Create one? (y/n) ")
4195
+ chalk12.gray("No projects found. Create one? (y/n) ")
4105
4196
  );
4106
4197
  if (createNew.toLowerCase() === "y") {
4107
- const name = await prompt(chalk11.gray("Project name: "));
4198
+ const name = await prompt(chalk12.gray("Project name: "));
4108
4199
  if (name) {
4109
4200
  const project = await client.createProject(selectedOrganization.id, name);
4110
4201
  config.projectId = project.id;
4111
- console.log(chalk11.green(`\u2713 Created project: ${project.name}`));
4202
+ console.log(chalk12.green(`\u2713 Created project: ${project.name}`));
4112
4203
  }
4113
4204
  }
4114
4205
  }
4115
4206
  } else {
4116
- const projectId = await prompt(chalk11.gray("Project ID (or leave blank): "));
4207
+ const projectId = await prompt(chalk12.gray("Project ID (or leave blank): "));
4117
4208
  if (projectId) {
4118
4209
  config.projectId = projectId;
4119
4210
  }
4120
4211
  }
4121
4212
  } else {
4122
- console.log(chalk11.yellow("Not logged in. Run `io login` first to select a project."));
4123
- const projectId = await prompt(chalk11.gray("Project ID (or leave blank): "));
4213
+ console.log(chalk12.yellow("Not logged in. Run `io login` first to select a project."));
4214
+ const projectId = await prompt(chalk12.gray("Project ID (or leave blank): "));
4124
4215
  if (projectId) {
4125
4216
  config.projectId = projectId;
4126
4217
  }
@@ -4130,14 +4221,14 @@ async function initCommand(options) {
4130
4221
  JSON.stringify(config, null, 2) + "\n",
4131
4222
  "utf-8"
4132
4223
  );
4133
- console.log(chalk11.green(`
4224
+ console.log(chalk12.green(`
4134
4225
  \u2713 Wrote ${CONFIG_FILE}`));
4135
4226
  if (config.projectId) {
4136
- console.log(chalk11.gray(` Project: ${config.projectId}`));
4227
+ console.log(chalk12.gray(` Project: ${config.projectId}`));
4137
4228
  }
4138
4229
  } catch (err) {
4139
4230
  if (err instanceof CliError) {
4140
- console.error(chalk11.red(err.message));
4231
+ console.error(chalk12.red(err.message));
4141
4232
  process.exit(1);
4142
4233
  }
4143
4234
  throw err;
@@ -4165,16 +4256,16 @@ async function projectsListCommand() {
4165
4256
  const organizationId = await resolveOrganizationId(client);
4166
4257
  const projects2 = await client.projects(organizationId);
4167
4258
  if (!projects2 || projects2.length === 0) {
4168
- console.log(chalk11.gray("No projects found. Create one with `io projects create <name>`."));
4259
+ console.log(chalk12.gray("No projects found. Create one with `io projects create <name>`."));
4169
4260
  return;
4170
4261
  }
4171
4262
  for (const p of projects2) {
4172
- const current = p.id === config.projectId ? chalk11.green(" (current)") : "";
4173
- console.log(` ${p.name} ${chalk11.gray(p.id)}${current}`);
4263
+ const current = p.id === config.projectId ? chalk12.green(" (current)") : "";
4264
+ console.log(` ${p.name} ${chalk12.gray(p.id)}${current}`);
4174
4265
  }
4175
4266
  } catch (err) {
4176
4267
  if (err instanceof CliError) {
4177
- console.error(chalk11.red(err.message));
4268
+ console.error(chalk12.red(err.message));
4178
4269
  process.exit(1);
4179
4270
  }
4180
4271
  throw err;
@@ -4186,10 +4277,10 @@ async function projectsCreateCommand(name) {
4186
4277
  const client = createClient(config);
4187
4278
  const organizationId = await resolveOrganizationId(client);
4188
4279
  const project = await client.createProject(organizationId, name);
4189
- console.log(chalk11.green(`\u2713 Created project: ${project.name}`));
4190
- console.log(chalk11.gray(` ID: ${project.id}`));
4280
+ console.log(chalk12.green(`\u2713 Created project: ${project.name}`));
4281
+ console.log(chalk12.gray(` ID: ${project.id}`));
4191
4282
  console.log(
4192
- chalk11.gray(
4283
+ chalk12.gray(
4193
4284
  `
4194
4285
  Add to io.config.json:
4195
4286
  { "projectId": "${project.id}" }`
@@ -4197,7 +4288,7 @@ async function projectsCreateCommand(name) {
4197
4288
  );
4198
4289
  } catch (err) {
4199
4290
  if (err instanceof CliError) {
4200
- console.error(chalk11.red(err.message));
4291
+ console.error(chalk12.red(err.message));
4201
4292
  process.exit(1);
4202
4293
  }
4203
4294
  throw err;
@@ -4209,10 +4300,10 @@ async function secretsSetCommand(name, value) {
4209
4300
  const client = createClient(config);
4210
4301
  const pid = client.projectId();
4211
4302
  await client.putSecret(pid, { name, value });
4212
- console.log(chalk11.green(`\u2713 Set secret: ${name}`));
4303
+ console.log(chalk12.green(`\u2713 Set secret: ${name}`));
4213
4304
  } catch (err) {
4214
4305
  if (err instanceof CliError) {
4215
- console.error(chalk11.red(err.message));
4306
+ console.error(chalk12.red(err.message));
4216
4307
  process.exit(1);
4217
4308
  }
4218
4309
  throw err;
@@ -4224,16 +4315,16 @@ async function secretsListCommand() {
4224
4315
  const client = createClient(config);
4225
4316
  const secrets2 = await client.listSecrets(client.projectId());
4226
4317
  if (!secrets2 || secrets2.length === 0) {
4227
- console.log(chalk11.gray("No secrets configured."));
4318
+ console.log(chalk12.gray("No secrets configured."));
4228
4319
  return;
4229
4320
  }
4230
4321
  for (const s of secrets2) {
4231
- const value = s.hasValue ? "" : chalk11.gray(" (no value)");
4322
+ const value = s.hasValue ? "" : chalk12.gray(" (no value)");
4232
4323
  console.log(` ${s.name}${value}`);
4233
4324
  }
4234
4325
  } catch (err) {
4235
4326
  if (err instanceof CliError) {
4236
- console.error(chalk11.red(err.message));
4327
+ console.error(chalk12.red(err.message));
4237
4328
  process.exit(1);
4238
4329
  }
4239
4330
  throw err;
@@ -4245,25 +4336,123 @@ async function secretsRemoveCommand(name) {
4245
4336
  const client = createClient(config);
4246
4337
  const removed = await client.deleteSecret(client.projectId(), name);
4247
4338
  if (!removed) {
4248
- console.log(chalk11.yellow(`Secret "${name}" not found.`));
4339
+ console.log(chalk12.yellow(`Secret "${name}" not found.`));
4249
4340
  return;
4250
4341
  }
4251
- console.log(chalk11.green(`\u2713 Removed secret: ${name}`));
4342
+ console.log(chalk12.green(`\u2713 Removed secret: ${name}`));
4252
4343
  } catch (err) {
4253
4344
  if (err instanceof CliError) {
4254
- console.error(chalk11.red(err.message));
4345
+ console.error(chalk12.red(err.message));
4255
4346
  process.exit(1);
4256
4347
  }
4257
4348
  throw err;
4258
4349
  }
4259
4350
  }
4351
+ function parseMetadata(input) {
4352
+ if (!input) return void 0;
4353
+ try {
4354
+ const parsed = JSON.parse(input);
4355
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
4356
+ return parsed;
4357
+ }
4358
+ } catch {
4359
+ }
4360
+ throw new ConfigError("metadata must be a JSON object");
4361
+ }
4362
+ function validateState(state) {
4363
+ if (!state) return void 0;
4364
+ if (state === "active" || state === "inactive" || state === "archived") return state;
4365
+ throw new ConfigError("state must be active, inactive, or archived");
4366
+ }
4367
+ async function withClient(options) {
4368
+ const config = await loadConfig({ projectId: options.projectId });
4369
+ const client = createClient(config);
4370
+ return { client, projectId: client.projectId() };
4371
+ }
4372
+ function handleError(err) {
4373
+ if (err instanceof CliError) {
4374
+ console.error(chalk12.red(err.message));
4375
+ process.exit(1);
4376
+ }
4377
+ throw err;
4378
+ }
4379
+ async function principalsListCommand(options) {
4380
+ try {
4381
+ const { client, projectId } = await withClient(options);
4382
+ const principals2 = await client.principals(projectId);
4383
+ if (principals2.length === 0) {
4384
+ console.log(chalk12.gray("No principals found. Create one with `io principals create <external-id>`."));
4385
+ return;
4386
+ }
4387
+ for (const principal of principals2) {
4388
+ console.log(
4389
+ ` ${principal.externalId} ${chalk12.gray(principal.id)} ${chalk12.gray(principal.state)}`
4390
+ );
4391
+ }
4392
+ } catch (err) {
4393
+ handleError(err);
4394
+ }
4395
+ }
4396
+ async function principalsCreateCommand(externalId, options) {
4397
+ try {
4398
+ const { client, projectId } = await withClient(options);
4399
+ const principal = await client.createPrincipal(projectId, {
4400
+ externalId,
4401
+ state: validateState(options.state),
4402
+ metadata: parseMetadata(options.metadata)
4403
+ });
4404
+ console.log(chalk12.green(`\u2713 Created principal: ${principal.externalId}`));
4405
+ console.log(chalk12.gray(` ID: ${principal.id}`));
4406
+ console.log(chalk12.gray(` Project: ${principal.projectId}`));
4407
+ console.log(chalk12.gray(` State: ${principal.state}`));
4408
+ } catch (err) {
4409
+ handleError(err);
4410
+ }
4411
+ }
4412
+ async function principalsUpdateCommand(id, options) {
4413
+ try {
4414
+ const { client, projectId } = await withClient(options);
4415
+ const input = {
4416
+ externalId: options.externalId,
4417
+ state: validateState(options.state),
4418
+ metadata: parseMetadata(options.metadata)
4419
+ };
4420
+ if (!input.externalId && !input.state && !input.metadata) {
4421
+ throw new ConfigError("nothing to update; pass --external-id, --state, or --metadata");
4422
+ }
4423
+ const principal = await client.updatePrincipal(projectId, id, input);
4424
+ if (!principal) {
4425
+ console.log(chalk12.yellow(`Principal "${id}" not found.`));
4426
+ return;
4427
+ }
4428
+ console.log(chalk12.green(`\u2713 Updated principal: ${principal.externalId}`));
4429
+ console.log(chalk12.gray(` ID: ${principal.id}`));
4430
+ console.log(chalk12.gray(` Project: ${principal.projectId}`));
4431
+ console.log(chalk12.gray(` State: ${principal.state}`));
4432
+ } catch (err) {
4433
+ handleError(err);
4434
+ }
4435
+ }
4436
+ async function principalsDeleteCommand(id, options) {
4437
+ try {
4438
+ const { client, projectId } = await withClient(options);
4439
+ const principal = await client.deletePrincipal(projectId, id);
4440
+ if (!principal) {
4441
+ console.log(chalk12.yellow(`Principal "${id}" not found.`));
4442
+ return;
4443
+ }
4444
+ console.log(chalk12.green(`\u2713 Deleted principal: ${principal.externalId}`));
4445
+ } catch (err) {
4446
+ handleError(err);
4447
+ }
4448
+ }
4260
4449
  function meterBar(used, limit, width = 20) {
4261
- if (limit === 0) return chalk11.gray("\u2591".repeat(width));
4450
+ if (limit === 0) return chalk12.gray("\u2591".repeat(width));
4262
4451
  const ratio = Math.min(used / limit, 1);
4263
4452
  const filled = Math.round(ratio * width);
4264
4453
  const empty = width - filled;
4265
- const color = ratio >= 0.9 ? chalk11.red : ratio >= 0.7 ? chalk11.yellow : chalk11.green;
4266
- return color("\u2588".repeat(filled)) + chalk11.gray("\u2591".repeat(empty));
4454
+ const color = ratio >= 0.9 ? chalk12.red : ratio >= 0.7 ? chalk12.yellow : chalk12.green;
4455
+ return color("\u2588".repeat(filled)) + chalk12.gray("\u2591".repeat(empty));
4267
4456
  }
4268
4457
  function formatNumber(n) {
4269
4458
  if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
@@ -4273,9 +4462,11 @@ function formatNumber(n) {
4273
4462
  var METER_LABELS = {
4274
4463
  events: "Events",
4275
4464
  ingest_tokens: "Ingest Tokens",
4465
+ query_tokens: "Query Tokens",
4276
4466
  voice_seconds: "Voice Seconds",
4277
4467
  compute_gb_sec: "Compute (GB\xB7s)",
4278
- storage_gb: "Storage (GB)"
4468
+ storage_gb: "Memory Storage (GB)",
4469
+ artifact_storage_gb: "Artifact Storage (GB)"
4279
4470
  };
4280
4471
  async function quotaCommand() {
4281
4472
  try {
@@ -4283,22 +4474,22 @@ async function quotaCommand() {
4283
4474
  const client = createClient(config);
4284
4475
  const statuses = await client.quotaStatuses();
4285
4476
  if (statuses.length === 0) {
4286
- console.log(chalk11.gray("No quota data available."));
4477
+ console.log(chalk12.gray("No quota data available."));
4287
4478
  return;
4288
4479
  }
4289
- console.log(chalk11.bold("\nQuota Usage\n"));
4480
+ console.log(chalk12.bold("\nQuota Usage\n"));
4290
4481
  for (const status of statuses) {
4291
4482
  const label = METER_LABELS[status.meter] ?? status.meter;
4292
4483
  const bar = meterBar(status.used, status.limit);
4293
4484
  const pct = status.limit > 0 ? `${status.percentageUsed.toFixed(1)}%` : "\u2014";
4294
4485
  const usage = `${formatNumber(status.used)} / ${formatNumber(status.limit)}`;
4295
- const enforcement = status.enforcement === "hard_cap" ? chalk11.red("hard") : chalk11.yellow("soft");
4296
- console.log(` ${label.padEnd(18)} ${bar} ${usage.padStart(16)} ${pct.padStart(6)} ${enforcement}`);
4486
+ const enforcement = status.enforcement === "hard_cap" ? chalk12.red("hard") : chalk12.yellow("soft");
4487
+ console.log(` ${label.padEnd(22)} ${bar} ${usage.padStart(16)} ${pct.padStart(6)} ${enforcement}`);
4297
4488
  }
4298
4489
  console.log();
4299
4490
  } catch (err) {
4300
4491
  if (err instanceof CliError) {
4301
- console.error(chalk11.red(err.message));
4492
+ console.error(chalk12.red(err.message));
4302
4493
  process.exit(1);
4303
4494
  }
4304
4495
  throw err;
@@ -4694,18 +4885,18 @@ function inferActivityPrincipalLabel(event) {
4694
4885
 
4695
4886
  // src/commands/logs.ts
4696
4887
  var LEVEL_COLORS = {
4697
- error: chalk11.red,
4698
- warning: chalk11.yellow,
4699
- info: chalk11.blue,
4700
- success: chalk11.green,
4701
- scheduled: chalk11.magenta
4888
+ error: chalk12.red,
4889
+ warning: chalk12.yellow,
4890
+ info: chalk12.blue,
4891
+ success: chalk12.green,
4892
+ scheduled: chalk12.magenta
4702
4893
  };
4703
4894
  var FOLLOW_POLL_INTERVAL_MS = 2e3;
4704
4895
  var FOLLOW_SEEN_ID_LIMIT = 1e3;
4705
4896
  var FOLLOW_BATCH_LIMIT = 200;
4706
4897
  function colorLevel(level) {
4707
- if (!level) return chalk11.gray("\u2014");
4708
- const colorFn = LEVEL_COLORS[level] ?? chalk11.gray;
4898
+ if (!level) return chalk12.gray("\u2014");
4899
+ const colorFn = LEVEL_COLORS[level] ?? chalk12.gray;
4709
4900
  return colorFn(level.padEnd(7));
4710
4901
  }
4711
4902
  function pad(value, width) {
@@ -4718,8 +4909,8 @@ function formatTime(isoString) {
4718
4909
  }
4719
4910
  function formatDuration(ms) {
4720
4911
  if (ms == null) return "";
4721
- if (ms < 1e3) return chalk11.gray(`${ms}ms`);
4722
- return chalk11.gray(`${(ms / 1e3).toFixed(1)}s`);
4912
+ if (ms < 1e3) return chalk12.gray(`${ms}ms`);
4913
+ return chalk12.gray(`${(ms / 1e3).toFixed(1)}s`);
4723
4914
  }
4724
4915
  function truncate(value, width) {
4725
4916
  if (value.length <= width) return value;
@@ -4727,19 +4918,19 @@ function truncate(value, width) {
4727
4918
  }
4728
4919
  function formatHeader() {
4729
4920
  return [
4730
- ` ${chalk11.gray(pad("TIME", 10))}`,
4731
- chalk11.gray(pad("STATUS", 9)),
4732
- chalk11.gray(pad("CATEGORY", 14)),
4733
- chalk11.gray(pad("NAME", 24)),
4734
- chalk11.gray(pad("DURATION", 10)),
4735
- chalk11.gray("DETAIL")
4921
+ ` ${chalk12.gray(pad("TIME", 10))}`,
4922
+ chalk12.gray(pad("STATUS", 9)),
4923
+ chalk12.gray(pad("CATEGORY", 14)),
4924
+ chalk12.gray(pad("NAME", 24)),
4925
+ chalk12.gray(pad("DURATION", 10)),
4926
+ chalk12.gray("DETAIL")
4736
4927
  ].join(" ");
4737
4928
  }
4738
4929
  function formatEvent(event) {
4739
- const time = chalk11.gray(formatTime(event.occurredAt));
4930
+ const time = chalk12.gray(formatTime(event.occurredAt));
4740
4931
  const statusKey = inferActivityEventStatus(event);
4741
4932
  const status = colorLevel(statusKey);
4742
- const category = chalk11.cyan(pad(inferActivityEventCategory(event), 14));
4933
+ const category = chalk12.cyan(pad(inferActivityEventCategory(event), 14));
4743
4934
  const name = pad(truncate(inferActivityEventName(event), 24), 24);
4744
4935
  const duration = formatDuration(event.durationMs);
4745
4936
  const detail = inferActivityEventDetail(event) || inferActivityPrincipalLabel(event) || "";
@@ -4749,7 +4940,7 @@ function formatEvent(event) {
4749
4940
  category,
4750
4941
  name,
4751
4942
  pad(duration || "", 10),
4752
- detail ? chalk11.gray(detail) : ""
4943
+ detail ? chalk12.gray(detail) : ""
4753
4944
  ].join(" ").trimEnd();
4754
4945
  }
4755
4946
  function latestOccurredAt(events, fallback) {
@@ -4811,7 +5002,7 @@ async function drainFollowEvents(client, projectId, input, since, seenIds, seenO
4811
5002
  }
4812
5003
  function installSigintHandler(onExit) {
4813
5004
  const handleSigint = () => {
4814
- console.log(chalk11.gray("\n Disconnected."));
5005
+ console.log(chalk12.gray("\n Disconnected."));
4815
5006
  onExit();
4816
5007
  process.exit(0);
4817
5008
  };
@@ -4837,15 +5028,15 @@ async function logsCommand(options) {
4837
5028
  }
4838
5029
  const events = await client.projectEvents(pid, input);
4839
5030
  if (events.length === 0 && !options.follow) {
4840
- console.log(chalk11.gray("No events found."));
5031
+ console.log(chalk12.gray("No events found."));
4841
5032
  return;
4842
5033
  }
4843
5034
  if (events.length > 0) {
4844
- console.log(chalk11.bold(`
5035
+ console.log(chalk12.bold(`
4845
5036
  Activity Log \u2014 ${events.length} events
4846
5037
  `));
4847
5038
  console.log(formatHeader());
4848
- console.log(chalk11.gray(` ${"\u2500".repeat(92)}`));
5039
+ console.log(chalk12.gray(` ${"\u2500".repeat(92)}`));
4849
5040
  for (const event of events) {
4850
5041
  console.log(formatEvent(event));
4851
5042
  }
@@ -4864,7 +5055,7 @@ Activity Log \u2014 ${events.length} events
4864
5055
  }
4865
5056
  } catch (err) {
4866
5057
  if (err instanceof CliError) {
4867
- console.error(chalk11.red(err.message));
5058
+ console.error(chalk12.red(err.message));
4868
5059
  process.exit(1);
4869
5060
  }
4870
5061
  throw err;
@@ -4875,7 +5066,7 @@ async function tailEvents(apiUrl, client, projectId, input, initialEvents, follo
4875
5066
  if (!creds || !creds.token) {
4876
5067
  throw new ConfigError("Not authenticated. Run `io login` first.");
4877
5068
  }
4878
- console.log(chalk11.gray("\n Waiting for events... (Ctrl+C to stop)\n"));
5069
+ console.log(chalk12.gray("\n Waiting for events... (Ctrl+C to stop)\n"));
4879
5070
  if (creds.apiKey) {
4880
5071
  return new Promise((_resolve, reject) => {
4881
5072
  let disconnect;
@@ -4899,7 +5090,7 @@ async function tailEvents(apiUrl, client, projectId, input, initialEvents, follo
4899
5090
  trimSeenIds(seenIds2, seenOrder2);
4900
5091
  },
4901
5092
  onConnected: () => {
4902
- console.log(chalk11.green(" \u25CF Connected \u2014 tailing live events\n"));
5093
+ console.log(chalk12.green(" \u25CF Connected \u2014 tailing live events\n"));
4903
5094
  void drainFollowEvents(
4904
5095
  client,
4905
5096
  projectId,
@@ -4912,7 +5103,7 @@ async function tailEvents(apiUrl, client, projectId, input, initialEvents, follo
4912
5103
  console.log(formatEvent(event));
4913
5104
  }
4914
5105
  }).catch((error) => {
4915
- console.error(chalk11.red(`
5106
+ console.error(chalk12.red(`
4916
5107
  Connection error: ${error.message}`));
4917
5108
  removeSigintHandler2();
4918
5109
  disconnect?.();
@@ -4920,7 +5111,7 @@ async function tailEvents(apiUrl, client, projectId, input, initialEvents, follo
4920
5111
  });
4921
5112
  },
4922
5113
  onError: (error) => {
4923
- console.error(chalk11.red(`
5114
+ console.error(chalk12.red(`
4924
5115
  Connection error: ${error.message}`));
4925
5116
  removeSigintHandler2();
4926
5117
  disconnect?.();
@@ -4930,7 +5121,7 @@ async function tailEvents(apiUrl, client, projectId, input, initialEvents, follo
4930
5121
  });
4931
5122
  }
4932
5123
  console.log(
4933
- chalk11.green(" \u25CF Connected \u2014 polling for live events with your authenticated session\n")
5124
+ chalk12.green(" \u25CF Connected \u2014 polling for live events with your authenticated session\n")
4934
5125
  );
4935
5126
  const seenIds = new Set(initialEvents.map((event) => event.id));
4936
5127
  const seenOrder = initialEvents.map((event) => event.id);
@@ -4996,10 +5187,14 @@ async function signalEmitCommand(name, options) {
4996
5187
  "signal name must be a bare event name like smoke.start or use the signal: namespace"
4997
5188
  );
4998
5189
  }
5190
+ if (!options.principalId || options.principalId.trim() === "") {
5191
+ throw new ConfigError("signals emit requires --principal-id <id>");
5192
+ }
4999
5193
  const payload = parseJsonObject(options.payload, "payload");
5000
5194
  const metadata = parseJsonObject(options.metadata, "metadata");
5001
5195
  const event = await client.emitSignal({
5002
5196
  signal,
5197
+ principalId: options.principalId,
5003
5198
  payload,
5004
5199
  metadata,
5005
5200
  correlationId: options.correlationId,
@@ -5011,18 +5206,18 @@ async function signalEmitCommand(name, options) {
5011
5206
  console.log(JSON.stringify(event, null, 2));
5012
5207
  return;
5013
5208
  }
5014
- console.log(chalk11.green(`\u2713 Emitted ${event.name}`));
5015
- console.log(chalk11.gray(` Event: ${event.id}`));
5016
- console.log(chalk11.gray(` Project: ${event.projectId}`));
5209
+ console.log(chalk12.green(`\u2713 Emitted ${event.name}`));
5210
+ console.log(chalk12.gray(` Event: ${event.id}`));
5211
+ console.log(chalk12.gray(` Project: ${event.projectId}`));
5017
5212
  if (event.dispatchStatus) {
5018
- console.log(chalk11.gray(` Dispatch: ${event.dispatchStatus}`));
5213
+ console.log(chalk12.gray(` Dispatch: ${event.dispatchStatus}`));
5019
5214
  }
5020
5215
  if (event.occurredAt) {
5021
- console.log(chalk11.gray(` At: ${event.occurredAt}`));
5216
+ console.log(chalk12.gray(` At: ${event.occurredAt}`));
5022
5217
  }
5023
5218
  } catch (err) {
5024
5219
  if (err instanceof CliError) {
5025
- console.error(chalk11.red(err.message));
5220
+ console.error(chalk12.red(err.message));
5026
5221
  process.exit(1);
5027
5222
  }
5028
5223
  throw err;
@@ -5031,7 +5226,7 @@ async function signalEmitCommand(name, options) {
5031
5226
 
5032
5227
  // src/index.ts
5033
5228
  var program = new Command();
5034
- program.name("io").description("IO CLI \u2014 build and deploy behaviors").version("0.1.13");
5229
+ program.name("io").description("IO CLI \u2014 build and deploy behaviors").version("0.1.15");
5035
5230
  program.command("init").description("Initialize io.config.json for the current project").option("--yes", "Overwrite existing config without prompting").action(initCommand);
5036
5231
  program.command("build").description("Build behaviors from the io/ directory").option("--dir <path>", "Source directory", "io").option("--minify", "Minify bundles", false).action(buildCommand);
5037
5232
  program.command("deploy").description("Build and package for deployment").option("--dir <path>", "Source directory", "io").option("--no-minify", "Skip minification").option("--yes", "Skip confirmation prompt").action(deployCommand);
@@ -5045,8 +5240,13 @@ var secrets = program.command("secrets").description("Manage project secrets");
5045
5240
  secrets.command("set <name> <value>").description("Set a secret value").option("--target <targets...>", "Restrict to specific targets").action(secretsSetCommand);
5046
5241
  secrets.command("list").description("List all secrets").action(secretsListCommand);
5047
5242
  secrets.command("remove <name>").description("Remove a secret").action(secretsRemoveCommand);
5243
+ var principals = program.command("principals").description("Manage project principals");
5244
+ principals.command("list").description("List principals in the active project").option("--project-id <id>", "Override the configured project ID").action(principalsListCommand);
5245
+ principals.command("create <external-id>").description("Create a principal in the active project").option("--project-id <id>", "Override the configured project ID").option("--state <state>", "Principal state: active, inactive, or archived").option("--metadata <json>", "Principal metadata as a JSON object").action(principalsCreateCommand);
5246
+ principals.command("update <id>").description("Update a principal").option("--project-id <id>", "Override the configured project ID").option("--external-id <external-id>", "Replace the external ID").option("--state <state>", "Principal state: active, inactive, or archived").option("--metadata <json>", "Replace principal metadata with a JSON object").action(principalsUpdateCommand);
5247
+ principals.command("delete <id>").description("Delete a principal").option("--project-id <id>", "Override the configured project ID").action(principalsDeleteCommand);
5048
5248
  var signals = program.command("signals").description("Emit runtime signals");
5049
- signals.command("emit <name>").description("Emit a signal into the active project's event stream").option("--payload <json>", "Signal payload as a JSON object", "{}").option("--metadata <json>", "Signal metadata as a JSON object", "{}").option("--project-id <id>", "Override the configured project ID").option("--correlation-id <id>", "Correlation ID to attach to the signal").option("--causation-id <id>", "Causation ID to attach to the signal").option("--idempotency-key <key>", "Optional idempotency key").option("--source-name <name>", "Optional source name for the emitted signal").option("--json", "Print the raw emitted event as JSON", false).action(signalEmitCommand);
5249
+ signals.command("emit <name>").description("Emit a signal into the active project's event stream").option("--payload <json>", "Signal payload as a JSON object", "{}").option("--metadata <json>", "Signal metadata as a JSON object", "{}").option("--project-id <id>", "Override the configured project ID").requiredOption("--principal-id <id>", "Project principal ID for the emitted signal").option("--correlation-id <id>", "Correlation ID to attach to the signal").option("--causation-id <id>", "Causation ID to attach to the signal").option("--idempotency-key <key>", "Optional idempotency key").option("--source-name <name>", "Optional source name for the emitted signal").option("--json", "Print the raw emitted event as JSON", false).action(signalEmitCommand);
5050
5250
  program.command("quota").description("Show current quota usage for the active organization").action(quotaCommand);
5051
5251
  program.command("logs").description("Show recent activity events").option("--limit <count>", "Number of events to show", "50").option("--type <types...>", "Filter by event types").option("--since <duration>", "Show events since (e.g. 15m, 1h, 7d)").option("--follow", "Tail events in real-time").action(logsCommand);
5052
5252
  program.parse();