@kaelen-ai/cli 0.1.14 → 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';
@@ -2776,7 +2776,7 @@ async function buildCommand(options) {
2776
2776
  const config = await loadConfig({
2777
2777
  dir: options.dir
2778
2778
  });
2779
- console.log(chalk11.gray("Validating deployment..."));
2779
+ console.log(chalk12.gray("Validating deployment..."));
2780
2780
  stagingDir = await createStagingDir();
2781
2781
  const { manifest } = await buildPipeline(
2782
2782
  config,
@@ -2806,10 +2806,10 @@ async function buildCommand(options) {
2806
2806
  `${subscriptions.length} subscription${subscriptions.length === 1 ? "" : "s"}`,
2807
2807
  `${secretBundles.length} secret bundle${secretBundles.length === 1 ? "" : "s"}`
2808
2808
  ];
2809
- console.log(chalk11.green(`\u2713 Build succeeded (${parts.join(", ")})`));
2809
+ console.log(chalk12.green(`\u2713 Build succeeded (${parts.join(", ")})`));
2810
2810
  } catch (err) {
2811
2811
  if (err instanceof CliError) {
2812
- console.error(chalk11.red(err.message));
2812
+ console.error(chalk12.red(err.message));
2813
2813
  process.exit(1);
2814
2814
  }
2815
2815
  throw err;
@@ -2996,9 +2996,9 @@ function diffManifests(local, remote) {
2996
2996
  };
2997
2997
  }
2998
2998
  var SYMBOLS = {
2999
- added: chalk11.green("+ "),
3000
- changed: chalk11.yellow("~ "),
3001
- removed: chalk11.red("- ")
2999
+ added: chalk12.green("+ "),
3000
+ changed: chalk12.yellow("~ "),
3001
+ removed: chalk12.red("- ")
3002
3002
  };
3003
3003
  var LABELS = {
3004
3004
  added: "new",
@@ -3020,11 +3020,11 @@ function formatPlan(diff) {
3020
3020
  const entries = diff[key];
3021
3021
  lines.push(` ${label}:`);
3022
3022
  if (entries.length === 0) {
3023
- lines.push(chalk11.gray(" (no changes)"));
3023
+ lines.push(chalk12.gray(" (no changes)"));
3024
3024
  } else {
3025
3025
  for (const e of entries) {
3026
3026
  lines.push(
3027
- ` ${SYMBOLS[e.kind]}${e.name} ${chalk11.gray(`(${LABELS[e.kind]})`)}`
3027
+ ` ${SYMBOLS[e.kind]}${e.name} ${chalk12.gray(`(${LABELS[e.kind]})`)}`
3028
3028
  );
3029
3029
  }
3030
3030
  }
@@ -3478,6 +3478,82 @@ function createClient(config) {
3478
3478
  );
3479
3479
  return data.createProject;
3480
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
+ }
3481
3557
  async function listSecrets(projectIdValue) {
3482
3558
  const data = await graphql(
3483
3559
  `
@@ -3598,6 +3674,9 @@ function createClient(config) {
3598
3674
  }
3599
3675
  async function emitSignal(input) {
3600
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
+ }
3601
3680
  const eventName = normalizeRuntimeSignalName2(input.signal);
3602
3681
  if (!eventName) {
3603
3682
  throw new ConfigError(
@@ -3625,6 +3704,7 @@ function createClient(config) {
3625
3704
  {
3626
3705
  input: {
3627
3706
  projectId: projectIdValue,
3707
+ principalId: input.principalId,
3628
3708
  eventName,
3629
3709
  payloadJson: JSON.stringify(input.payload ?? {}),
3630
3710
  metadataJson: JSON.stringify(input.metadata ?? {}),
@@ -3701,6 +3781,10 @@ function createClient(config) {
3701
3781
  organizations,
3702
3782
  projects: projects2,
3703
3783
  createProject,
3784
+ principals: principals2,
3785
+ createPrincipal,
3786
+ updatePrincipal,
3787
+ deletePrincipal,
3704
3788
  listSecrets,
3705
3789
  putSecret,
3706
3790
  deleteSecret,
@@ -3719,7 +3803,7 @@ async function deployCommand(options) {
3719
3803
  const config = await loadConfig({
3720
3804
  dir: options.dir
3721
3805
  });
3722
- console.log(chalk11.gray("Planning deployment..."));
3806
+ console.log(chalk12.gray("Planning deployment..."));
3723
3807
  stagingDir = await createStagingDir();
3724
3808
  const { manifest } = await buildPipeline(
3725
3809
  config,
@@ -3729,7 +3813,7 @@ async function deployCommand(options) {
3729
3813
  );
3730
3814
  if (!config.apiUrl || !config.projectId) {
3731
3815
  console.log(
3732
- chalk11.yellow(
3816
+ chalk12.yellow(
3733
3817
  "\nNo apiUrl or projectId configured. Skipping upload."
3734
3818
  )
3735
3819
  );
@@ -3739,30 +3823,30 @@ async function deployCommand(options) {
3739
3823
  apiUrl: config.apiUrl,
3740
3824
  projectId: config.projectId
3741
3825
  });
3742
- console.log(chalk11.gray("\nComparing with remote..."));
3826
+ console.log(chalk12.gray("\nComparing with remote..."));
3743
3827
  const remoteManifest = await client.fetchRemoteManifest(client.projectId());
3744
3828
  const diff = diffManifests(manifest, remoteManifest);
3745
3829
  if (!diff.hasChanges) {
3746
- console.log(chalk11.green("\n\u2713 No changes to deploy."));
3830
+ console.log(chalk12.green("\n\u2713 No changes to deploy."));
3747
3831
  return;
3748
3832
  }
3749
3833
  console.log("\n" + formatPlan(diff));
3750
3834
  const confirmed = await confirmPlan(options.yes ?? false);
3751
3835
  if (!confirmed) {
3752
- console.log(chalk11.yellow("Deploy cancelled."));
3836
+ console.log(chalk12.yellow("Deploy cancelled."));
3753
3837
  return;
3754
3838
  }
3755
- console.log(chalk11.gray("\nApplying deployment..."));
3839
+ console.log(chalk12.gray("\nApplying deployment..."));
3756
3840
  const zipPath = join(stagingDir, "deploy.zip");
3757
3841
  await zipBuildOutput(stagingDir, zipPath);
3758
3842
  const revision = await client.deployBundle(zipPath, manifest);
3759
3843
  console.log(
3760
- chalk11.green(`
3844
+ chalk12.green(`
3761
3845
  \u2713 Deployment complete (revision ${revision.revision}, ${revision.status})`)
3762
3846
  );
3763
3847
  } catch (err) {
3764
3848
  if (err instanceof CliError) {
3765
- console.error(chalk11.red(err.message));
3849
+ console.error(chalk12.red(err.message));
3766
3850
  process.exit(1);
3767
3851
  }
3768
3852
  throw err;
@@ -3873,7 +3957,7 @@ async function loginCommand(options) {
3873
3957
  try {
3874
3958
  if (options.token) {
3875
3959
  await saveToken(options.token, true);
3876
- console.log(chalk11.green("\u2713 API key saved"));
3960
+ console.log(chalk12.green("\u2713 API key saved"));
3877
3961
  return;
3878
3962
  }
3879
3963
  const config = await loadConfig();
@@ -3884,7 +3968,7 @@ async function loginCommand(options) {
3884
3968
  }
3885
3969
  const existing = await loadToken();
3886
3970
  if (existing) {
3887
- console.log(chalk11.gray("Existing session found. Re-authenticating..."));
3971
+ console.log(chalk12.gray("Existing session found. Re-authenticating..."));
3888
3972
  }
3889
3973
  const callbackServer = await startCallbackServer();
3890
3974
  const pkce = generatePkcePair();
@@ -3894,12 +3978,12 @@ async function loginCommand(options) {
3894
3978
  callbackServer.state,
3895
3979
  pkce.challenge
3896
3980
  );
3897
- console.log(chalk11.gray("Opening your browser for sign-in..."));
3981
+ console.log(chalk12.gray("Opening your browser for sign-in..."));
3898
3982
  try {
3899
3983
  await open(authorizationUrl);
3900
3984
  } catch {
3901
- console.log(chalk11.yellow("Could not open the browser automatically."));
3902
- 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:
3903
3987
  ${authorizationUrl}`));
3904
3988
  }
3905
3989
  try {
@@ -3923,10 +4007,10 @@ ${authorizationUrl}`));
3923
4007
  } finally {
3924
4008
  callbackServer.close();
3925
4009
  }
3926
- console.log(chalk11.green("\n\u2713 Authenticated successfully"));
4010
+ console.log(chalk12.green("\n\u2713 Authenticated successfully"));
3927
4011
  } catch (err) {
3928
4012
  if (err instanceof CliError) {
3929
- console.error(chalk11.red(err.message));
4013
+ console.error(chalk12.red(err.message));
3930
4014
  process.exit(1);
3931
4015
  }
3932
4016
  throw err;
@@ -3936,10 +4020,10 @@ async function logoutCommand() {
3936
4020
  const creds = await loadCredentials();
3937
4021
  await clearToken();
3938
4022
  if (!creds) {
3939
- console.log(chalk11.yellow("Not logged in."));
4023
+ console.log(chalk12.yellow("Not logged in."));
3940
4024
  return;
3941
4025
  }
3942
- console.log(chalk11.green("\u2713 Logged out"));
4026
+ console.log(chalk12.green("\u2713 Logged out"));
3943
4027
  }
3944
4028
  async function hydrateIdentity() {
3945
4029
  const creds = await loadCredentials();
@@ -3983,26 +4067,26 @@ async function hydrateIdentity() {
3983
4067
  async function whoamiCommand() {
3984
4068
  const { creds, sessionName, sessionEmail } = await hydrateIdentity();
3985
4069
  if (!creds) {
3986
- 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."));
3987
4071
  return;
3988
4072
  }
3989
- console.log(chalk11.green("\u2713 Logged in"));
4073
+ console.log(chalk12.green("\u2713 Logged in"));
3990
4074
  const displayUser = sessionName ?? sessionEmail ?? creds.userId;
3991
4075
  if (displayUser) {
3992
- console.log(chalk11.gray(` User: ${displayUser}`));
4076
+ console.log(chalk12.gray(` User: ${displayUser}`));
3993
4077
  }
3994
4078
  if (sessionEmail && sessionEmail !== displayUser) {
3995
- console.log(chalk11.gray(` Email: ${sessionEmail}`));
4079
+ console.log(chalk12.gray(` Email: ${sessionEmail}`));
3996
4080
  }
3997
4081
  if (creds.organizationId) {
3998
- console.log(chalk11.gray(` Organization: ${creds.organizationId}`));
4082
+ console.log(chalk12.gray(` Organization: ${creds.organizationId}`));
3999
4083
  }
4000
4084
  if (creds.apiKey) {
4001
- console.log(chalk11.gray(" Session: API key"));
4085
+ console.log(chalk12.gray(" Session: API key"));
4002
4086
  } else if (creds.refreshToken) {
4003
- console.log(chalk11.gray(" Session: refresh token stored"));
4087
+ console.log(chalk12.gray(" Session: refresh token stored"));
4004
4088
  } else {
4005
- console.log(chalk11.gray(" Session: token only (no refresh)"));
4089
+ console.log(chalk12.gray(" Session: token only (no refresh)"));
4006
4090
  }
4007
4091
  }
4008
4092
  var CONFIG_FILE = "io.config.json";
@@ -4032,13 +4116,13 @@ async function selectOrganization(organizations, preferredId) {
4032
4116
  if (organizations.length === 1) {
4033
4117
  return organizations[0];
4034
4118
  }
4035
- console.log(chalk11.gray("\nAvailable organizations:"));
4119
+ console.log(chalk12.gray("\nAvailable organizations:"));
4036
4120
  organizations.forEach((organization, index2) => {
4037
4121
  console.log(
4038
- ` ${chalk11.green(String(index2 + 1))}. ${organization.name} ${chalk11.gray(organization.id)}`
4122
+ ` ${chalk12.green(String(index2 + 1))}. ${organization.name} ${chalk12.gray(organization.id)}`
4039
4123
  );
4040
4124
  });
4041
- 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): "));
4042
4126
  const index = Number(choice);
4043
4127
  if (index > 0 && index <= organizations.length) {
4044
4128
  return organizations[index - 1];
@@ -4051,16 +4135,16 @@ async function initCommand(options) {
4051
4135
  const existing = await readExistingConfig(cwd);
4052
4136
  if (existing.projectId && !options.yes) {
4053
4137
  const overwrite = await prompt(
4054
- 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) `)
4055
4139
  );
4056
4140
  if (overwrite.toLowerCase() !== "y") {
4057
- console.log(chalk11.gray("Cancelled."));
4141
+ console.log(chalk12.gray("Cancelled."));
4058
4142
  return;
4059
4143
  }
4060
4144
  }
4061
4145
  const config = { ...existing };
4062
4146
  if (!config.apiUrl) {
4063
- 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): "));
4064
4148
  if (apiUrl) {
4065
4149
  config.apiUrl = apiUrl;
4066
4150
  }
@@ -4082,7 +4166,7 @@ async function initCommand(options) {
4082
4166
  try {
4083
4167
  organizations = await client.organizations();
4084
4168
  } catch {
4085
- 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."));
4086
4170
  }
4087
4171
  const selectedOrganization = await selectOrganization(
4088
4172
  organizations,
@@ -4091,14 +4175,14 @@ async function initCommand(options) {
4091
4175
  if (selectedOrganization) {
4092
4176
  const projects2 = await client.projects(selectedOrganization.id);
4093
4177
  if (projects2.length > 0) {
4094
- console.log(chalk11.gray("\nAvailable projects:"));
4178
+ console.log(chalk12.gray("\nAvailable projects:"));
4095
4179
  projects2.forEach((project, index2) => {
4096
4180
  console.log(
4097
- ` ${chalk11.green(String(index2 + 1))}. ${project.name} ${chalk11.gray(project.id)}`
4181
+ ` ${chalk12.green(String(index2 + 1))}. ${project.name} ${chalk12.gray(project.id)}`
4098
4182
  );
4099
4183
  });
4100
4184
  const choice = await prompt(
4101
- chalk11.gray("\nSelect a project (number) or enter a project ID: ")
4185
+ chalk12.gray("\nSelect a project (number) or enter a project ID: ")
4102
4186
  );
4103
4187
  const index = Number(choice);
4104
4188
  if (index > 0 && index <= projects2.length) {
@@ -4108,26 +4192,26 @@ async function initCommand(options) {
4108
4192
  }
4109
4193
  } else {
4110
4194
  const createNew = await prompt(
4111
- chalk11.gray("No projects found. Create one? (y/n) ")
4195
+ chalk12.gray("No projects found. Create one? (y/n) ")
4112
4196
  );
4113
4197
  if (createNew.toLowerCase() === "y") {
4114
- const name = await prompt(chalk11.gray("Project name: "));
4198
+ const name = await prompt(chalk12.gray("Project name: "));
4115
4199
  if (name) {
4116
4200
  const project = await client.createProject(selectedOrganization.id, name);
4117
4201
  config.projectId = project.id;
4118
- console.log(chalk11.green(`\u2713 Created project: ${project.name}`));
4202
+ console.log(chalk12.green(`\u2713 Created project: ${project.name}`));
4119
4203
  }
4120
4204
  }
4121
4205
  }
4122
4206
  } else {
4123
- const projectId = await prompt(chalk11.gray("Project ID (or leave blank): "));
4207
+ const projectId = await prompt(chalk12.gray("Project ID (or leave blank): "));
4124
4208
  if (projectId) {
4125
4209
  config.projectId = projectId;
4126
4210
  }
4127
4211
  }
4128
4212
  } else {
4129
- console.log(chalk11.yellow("Not logged in. Run `io login` first to select a project."));
4130
- 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): "));
4131
4215
  if (projectId) {
4132
4216
  config.projectId = projectId;
4133
4217
  }
@@ -4137,14 +4221,14 @@ async function initCommand(options) {
4137
4221
  JSON.stringify(config, null, 2) + "\n",
4138
4222
  "utf-8"
4139
4223
  );
4140
- console.log(chalk11.green(`
4224
+ console.log(chalk12.green(`
4141
4225
  \u2713 Wrote ${CONFIG_FILE}`));
4142
4226
  if (config.projectId) {
4143
- console.log(chalk11.gray(` Project: ${config.projectId}`));
4227
+ console.log(chalk12.gray(` Project: ${config.projectId}`));
4144
4228
  }
4145
4229
  } catch (err) {
4146
4230
  if (err instanceof CliError) {
4147
- console.error(chalk11.red(err.message));
4231
+ console.error(chalk12.red(err.message));
4148
4232
  process.exit(1);
4149
4233
  }
4150
4234
  throw err;
@@ -4172,16 +4256,16 @@ async function projectsListCommand() {
4172
4256
  const organizationId = await resolveOrganizationId(client);
4173
4257
  const projects2 = await client.projects(organizationId);
4174
4258
  if (!projects2 || projects2.length === 0) {
4175
- 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>`."));
4176
4260
  return;
4177
4261
  }
4178
4262
  for (const p of projects2) {
4179
- const current = p.id === config.projectId ? chalk11.green(" (current)") : "";
4180
- 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}`);
4181
4265
  }
4182
4266
  } catch (err) {
4183
4267
  if (err instanceof CliError) {
4184
- console.error(chalk11.red(err.message));
4268
+ console.error(chalk12.red(err.message));
4185
4269
  process.exit(1);
4186
4270
  }
4187
4271
  throw err;
@@ -4193,10 +4277,10 @@ async function projectsCreateCommand(name) {
4193
4277
  const client = createClient(config);
4194
4278
  const organizationId = await resolveOrganizationId(client);
4195
4279
  const project = await client.createProject(organizationId, name);
4196
- console.log(chalk11.green(`\u2713 Created project: ${project.name}`));
4197
- 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}`));
4198
4282
  console.log(
4199
- chalk11.gray(
4283
+ chalk12.gray(
4200
4284
  `
4201
4285
  Add to io.config.json:
4202
4286
  { "projectId": "${project.id}" }`
@@ -4204,7 +4288,7 @@ async function projectsCreateCommand(name) {
4204
4288
  );
4205
4289
  } catch (err) {
4206
4290
  if (err instanceof CliError) {
4207
- console.error(chalk11.red(err.message));
4291
+ console.error(chalk12.red(err.message));
4208
4292
  process.exit(1);
4209
4293
  }
4210
4294
  throw err;
@@ -4216,10 +4300,10 @@ async function secretsSetCommand(name, value) {
4216
4300
  const client = createClient(config);
4217
4301
  const pid = client.projectId();
4218
4302
  await client.putSecret(pid, { name, value });
4219
- console.log(chalk11.green(`\u2713 Set secret: ${name}`));
4303
+ console.log(chalk12.green(`\u2713 Set secret: ${name}`));
4220
4304
  } catch (err) {
4221
4305
  if (err instanceof CliError) {
4222
- console.error(chalk11.red(err.message));
4306
+ console.error(chalk12.red(err.message));
4223
4307
  process.exit(1);
4224
4308
  }
4225
4309
  throw err;
@@ -4231,16 +4315,16 @@ async function secretsListCommand() {
4231
4315
  const client = createClient(config);
4232
4316
  const secrets2 = await client.listSecrets(client.projectId());
4233
4317
  if (!secrets2 || secrets2.length === 0) {
4234
- console.log(chalk11.gray("No secrets configured."));
4318
+ console.log(chalk12.gray("No secrets configured."));
4235
4319
  return;
4236
4320
  }
4237
4321
  for (const s of secrets2) {
4238
- const value = s.hasValue ? "" : chalk11.gray(" (no value)");
4322
+ const value = s.hasValue ? "" : chalk12.gray(" (no value)");
4239
4323
  console.log(` ${s.name}${value}`);
4240
4324
  }
4241
4325
  } catch (err) {
4242
4326
  if (err instanceof CliError) {
4243
- console.error(chalk11.red(err.message));
4327
+ console.error(chalk12.red(err.message));
4244
4328
  process.exit(1);
4245
4329
  }
4246
4330
  throw err;
@@ -4252,25 +4336,123 @@ async function secretsRemoveCommand(name) {
4252
4336
  const client = createClient(config);
4253
4337
  const removed = await client.deleteSecret(client.projectId(), name);
4254
4338
  if (!removed) {
4255
- console.log(chalk11.yellow(`Secret "${name}" not found.`));
4339
+ console.log(chalk12.yellow(`Secret "${name}" not found.`));
4256
4340
  return;
4257
4341
  }
4258
- console.log(chalk11.green(`\u2713 Removed secret: ${name}`));
4342
+ console.log(chalk12.green(`\u2713 Removed secret: ${name}`));
4259
4343
  } catch (err) {
4260
4344
  if (err instanceof CliError) {
4261
- console.error(chalk11.red(err.message));
4345
+ console.error(chalk12.red(err.message));
4262
4346
  process.exit(1);
4263
4347
  }
4264
4348
  throw err;
4265
4349
  }
4266
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
+ }
4267
4449
  function meterBar(used, limit, width = 20) {
4268
- if (limit === 0) return chalk11.gray("\u2591".repeat(width));
4450
+ if (limit === 0) return chalk12.gray("\u2591".repeat(width));
4269
4451
  const ratio = Math.min(used / limit, 1);
4270
4452
  const filled = Math.round(ratio * width);
4271
4453
  const empty = width - filled;
4272
- const color = ratio >= 0.9 ? chalk11.red : ratio >= 0.7 ? chalk11.yellow : chalk11.green;
4273
- 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));
4274
4456
  }
4275
4457
  function formatNumber(n) {
4276
4458
  if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
@@ -4280,9 +4462,11 @@ function formatNumber(n) {
4280
4462
  var METER_LABELS = {
4281
4463
  events: "Events",
4282
4464
  ingest_tokens: "Ingest Tokens",
4465
+ query_tokens: "Query Tokens",
4283
4466
  voice_seconds: "Voice Seconds",
4284
4467
  compute_gb_sec: "Compute (GB\xB7s)",
4285
- storage_gb: "Storage (GB)"
4468
+ storage_gb: "Memory Storage (GB)",
4469
+ artifact_storage_gb: "Artifact Storage (GB)"
4286
4470
  };
4287
4471
  async function quotaCommand() {
4288
4472
  try {
@@ -4290,22 +4474,22 @@ async function quotaCommand() {
4290
4474
  const client = createClient(config);
4291
4475
  const statuses = await client.quotaStatuses();
4292
4476
  if (statuses.length === 0) {
4293
- console.log(chalk11.gray("No quota data available."));
4477
+ console.log(chalk12.gray("No quota data available."));
4294
4478
  return;
4295
4479
  }
4296
- console.log(chalk11.bold("\nQuota Usage\n"));
4480
+ console.log(chalk12.bold("\nQuota Usage\n"));
4297
4481
  for (const status of statuses) {
4298
4482
  const label = METER_LABELS[status.meter] ?? status.meter;
4299
4483
  const bar = meterBar(status.used, status.limit);
4300
4484
  const pct = status.limit > 0 ? `${status.percentageUsed.toFixed(1)}%` : "\u2014";
4301
4485
  const usage = `${formatNumber(status.used)} / ${formatNumber(status.limit)}`;
4302
- const enforcement = status.enforcement === "hard_cap" ? chalk11.red("hard") : chalk11.yellow("soft");
4303
- 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}`);
4304
4488
  }
4305
4489
  console.log();
4306
4490
  } catch (err) {
4307
4491
  if (err instanceof CliError) {
4308
- console.error(chalk11.red(err.message));
4492
+ console.error(chalk12.red(err.message));
4309
4493
  process.exit(1);
4310
4494
  }
4311
4495
  throw err;
@@ -4701,18 +4885,18 @@ function inferActivityPrincipalLabel(event) {
4701
4885
 
4702
4886
  // src/commands/logs.ts
4703
4887
  var LEVEL_COLORS = {
4704
- error: chalk11.red,
4705
- warning: chalk11.yellow,
4706
- info: chalk11.blue,
4707
- success: chalk11.green,
4708
- scheduled: chalk11.magenta
4888
+ error: chalk12.red,
4889
+ warning: chalk12.yellow,
4890
+ info: chalk12.blue,
4891
+ success: chalk12.green,
4892
+ scheduled: chalk12.magenta
4709
4893
  };
4710
4894
  var FOLLOW_POLL_INTERVAL_MS = 2e3;
4711
4895
  var FOLLOW_SEEN_ID_LIMIT = 1e3;
4712
4896
  var FOLLOW_BATCH_LIMIT = 200;
4713
4897
  function colorLevel(level) {
4714
- if (!level) return chalk11.gray("\u2014");
4715
- const colorFn = LEVEL_COLORS[level] ?? chalk11.gray;
4898
+ if (!level) return chalk12.gray("\u2014");
4899
+ const colorFn = LEVEL_COLORS[level] ?? chalk12.gray;
4716
4900
  return colorFn(level.padEnd(7));
4717
4901
  }
4718
4902
  function pad(value, width) {
@@ -4725,8 +4909,8 @@ function formatTime(isoString) {
4725
4909
  }
4726
4910
  function formatDuration(ms) {
4727
4911
  if (ms == null) return "";
4728
- if (ms < 1e3) return chalk11.gray(`${ms}ms`);
4729
- 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`);
4730
4914
  }
4731
4915
  function truncate(value, width) {
4732
4916
  if (value.length <= width) return value;
@@ -4734,19 +4918,19 @@ function truncate(value, width) {
4734
4918
  }
4735
4919
  function formatHeader() {
4736
4920
  return [
4737
- ` ${chalk11.gray(pad("TIME", 10))}`,
4738
- chalk11.gray(pad("STATUS", 9)),
4739
- chalk11.gray(pad("CATEGORY", 14)),
4740
- chalk11.gray(pad("NAME", 24)),
4741
- chalk11.gray(pad("DURATION", 10)),
4742
- 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")
4743
4927
  ].join(" ");
4744
4928
  }
4745
4929
  function formatEvent(event) {
4746
- const time = chalk11.gray(formatTime(event.occurredAt));
4930
+ const time = chalk12.gray(formatTime(event.occurredAt));
4747
4931
  const statusKey = inferActivityEventStatus(event);
4748
4932
  const status = colorLevel(statusKey);
4749
- const category = chalk11.cyan(pad(inferActivityEventCategory(event), 14));
4933
+ const category = chalk12.cyan(pad(inferActivityEventCategory(event), 14));
4750
4934
  const name = pad(truncate(inferActivityEventName(event), 24), 24);
4751
4935
  const duration = formatDuration(event.durationMs);
4752
4936
  const detail = inferActivityEventDetail(event) || inferActivityPrincipalLabel(event) || "";
@@ -4756,7 +4940,7 @@ function formatEvent(event) {
4756
4940
  category,
4757
4941
  name,
4758
4942
  pad(duration || "", 10),
4759
- detail ? chalk11.gray(detail) : ""
4943
+ detail ? chalk12.gray(detail) : ""
4760
4944
  ].join(" ").trimEnd();
4761
4945
  }
4762
4946
  function latestOccurredAt(events, fallback) {
@@ -4818,7 +5002,7 @@ async function drainFollowEvents(client, projectId, input, since, seenIds, seenO
4818
5002
  }
4819
5003
  function installSigintHandler(onExit) {
4820
5004
  const handleSigint = () => {
4821
- console.log(chalk11.gray("\n Disconnected."));
5005
+ console.log(chalk12.gray("\n Disconnected."));
4822
5006
  onExit();
4823
5007
  process.exit(0);
4824
5008
  };
@@ -4844,15 +5028,15 @@ async function logsCommand(options) {
4844
5028
  }
4845
5029
  const events = await client.projectEvents(pid, input);
4846
5030
  if (events.length === 0 && !options.follow) {
4847
- console.log(chalk11.gray("No events found."));
5031
+ console.log(chalk12.gray("No events found."));
4848
5032
  return;
4849
5033
  }
4850
5034
  if (events.length > 0) {
4851
- console.log(chalk11.bold(`
5035
+ console.log(chalk12.bold(`
4852
5036
  Activity Log \u2014 ${events.length} events
4853
5037
  `));
4854
5038
  console.log(formatHeader());
4855
- console.log(chalk11.gray(` ${"\u2500".repeat(92)}`));
5039
+ console.log(chalk12.gray(` ${"\u2500".repeat(92)}`));
4856
5040
  for (const event of events) {
4857
5041
  console.log(formatEvent(event));
4858
5042
  }
@@ -4871,7 +5055,7 @@ Activity Log \u2014 ${events.length} events
4871
5055
  }
4872
5056
  } catch (err) {
4873
5057
  if (err instanceof CliError) {
4874
- console.error(chalk11.red(err.message));
5058
+ console.error(chalk12.red(err.message));
4875
5059
  process.exit(1);
4876
5060
  }
4877
5061
  throw err;
@@ -4882,7 +5066,7 @@ async function tailEvents(apiUrl, client, projectId, input, initialEvents, follo
4882
5066
  if (!creds || !creds.token) {
4883
5067
  throw new ConfigError("Not authenticated. Run `io login` first.");
4884
5068
  }
4885
- 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"));
4886
5070
  if (creds.apiKey) {
4887
5071
  return new Promise((_resolve, reject) => {
4888
5072
  let disconnect;
@@ -4906,7 +5090,7 @@ async function tailEvents(apiUrl, client, projectId, input, initialEvents, follo
4906
5090
  trimSeenIds(seenIds2, seenOrder2);
4907
5091
  },
4908
5092
  onConnected: () => {
4909
- console.log(chalk11.green(" \u25CF Connected \u2014 tailing live events\n"));
5093
+ console.log(chalk12.green(" \u25CF Connected \u2014 tailing live events\n"));
4910
5094
  void drainFollowEvents(
4911
5095
  client,
4912
5096
  projectId,
@@ -4919,7 +5103,7 @@ async function tailEvents(apiUrl, client, projectId, input, initialEvents, follo
4919
5103
  console.log(formatEvent(event));
4920
5104
  }
4921
5105
  }).catch((error) => {
4922
- console.error(chalk11.red(`
5106
+ console.error(chalk12.red(`
4923
5107
  Connection error: ${error.message}`));
4924
5108
  removeSigintHandler2();
4925
5109
  disconnect?.();
@@ -4927,7 +5111,7 @@ async function tailEvents(apiUrl, client, projectId, input, initialEvents, follo
4927
5111
  });
4928
5112
  },
4929
5113
  onError: (error) => {
4930
- console.error(chalk11.red(`
5114
+ console.error(chalk12.red(`
4931
5115
  Connection error: ${error.message}`));
4932
5116
  removeSigintHandler2();
4933
5117
  disconnect?.();
@@ -4937,7 +5121,7 @@ async function tailEvents(apiUrl, client, projectId, input, initialEvents, follo
4937
5121
  });
4938
5122
  }
4939
5123
  console.log(
4940
- 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")
4941
5125
  );
4942
5126
  const seenIds = new Set(initialEvents.map((event) => event.id));
4943
5127
  const seenOrder = initialEvents.map((event) => event.id);
@@ -5003,10 +5187,14 @@ async function signalEmitCommand(name, options) {
5003
5187
  "signal name must be a bare event name like smoke.start or use the signal: namespace"
5004
5188
  );
5005
5189
  }
5190
+ if (!options.principalId || options.principalId.trim() === "") {
5191
+ throw new ConfigError("signals emit requires --principal-id <id>");
5192
+ }
5006
5193
  const payload = parseJsonObject(options.payload, "payload");
5007
5194
  const metadata = parseJsonObject(options.metadata, "metadata");
5008
5195
  const event = await client.emitSignal({
5009
5196
  signal,
5197
+ principalId: options.principalId,
5010
5198
  payload,
5011
5199
  metadata,
5012
5200
  correlationId: options.correlationId,
@@ -5018,18 +5206,18 @@ async function signalEmitCommand(name, options) {
5018
5206
  console.log(JSON.stringify(event, null, 2));
5019
5207
  return;
5020
5208
  }
5021
- console.log(chalk11.green(`\u2713 Emitted ${event.name}`));
5022
- console.log(chalk11.gray(` Event: ${event.id}`));
5023
- 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}`));
5024
5212
  if (event.dispatchStatus) {
5025
- console.log(chalk11.gray(` Dispatch: ${event.dispatchStatus}`));
5213
+ console.log(chalk12.gray(` Dispatch: ${event.dispatchStatus}`));
5026
5214
  }
5027
5215
  if (event.occurredAt) {
5028
- console.log(chalk11.gray(` At: ${event.occurredAt}`));
5216
+ console.log(chalk12.gray(` At: ${event.occurredAt}`));
5029
5217
  }
5030
5218
  } catch (err) {
5031
5219
  if (err instanceof CliError) {
5032
- console.error(chalk11.red(err.message));
5220
+ console.error(chalk12.red(err.message));
5033
5221
  process.exit(1);
5034
5222
  }
5035
5223
  throw err;
@@ -5038,7 +5226,7 @@ async function signalEmitCommand(name, options) {
5038
5226
 
5039
5227
  // src/index.ts
5040
5228
  var program = new Command();
5041
- program.name("io").description("IO CLI \u2014 build and deploy behaviors").version("0.1.14");
5229
+ program.name("io").description("IO CLI \u2014 build and deploy behaviors").version("0.1.15");
5042
5230
  program.command("init").description("Initialize io.config.json for the current project").option("--yes", "Overwrite existing config without prompting").action(initCommand);
5043
5231
  program.command("build").description("Build behaviors from the io/ directory").option("--dir <path>", "Source directory", "io").option("--minify", "Minify bundles", false).action(buildCommand);
5044
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);
@@ -5052,8 +5240,13 @@ var secrets = program.command("secrets").description("Manage project secrets");
5052
5240
  secrets.command("set <name> <value>").description("Set a secret value").option("--target <targets...>", "Restrict to specific targets").action(secretsSetCommand);
5053
5241
  secrets.command("list").description("List all secrets").action(secretsListCommand);
5054
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);
5055
5248
  var signals = program.command("signals").description("Emit runtime signals");
5056
- 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);
5057
5250
  program.command("quota").description("Show current quota usage for the active organization").action(quotaCommand);
5058
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);
5059
5252
  program.parse();