@eide/foir-cli 0.22.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -469,7 +469,7 @@ import { StorageService as StorageService2 } from "@eide/foir-proto-ts/storage/v
469
469
  import { OperationsService as OperationsService2 } from "@eide/foir-proto-ts/operations/v1/operations_pb";
470
470
  import { HooksService as HooksService2 } from "@eide/foir-proto-ts/hooks/v1/hooks_pb";
471
471
  import { NotificationsService as NotificationsService2 } from "@eide/foir-proto-ts/notifications/v1/notifications_pb";
472
- import { SchedulesService as SchedulesService2 } from "@eide/foir-proto-ts/schedules/v1/schedules_pb";
472
+ import { SchedulesService as SchedulesService3 } from "@eide/foir-proto-ts/schedules/v1/schedules_pb";
473
473
  import { AppsService as AppsService2 } from "@eide/foir-proto-ts/apps/v1/apps_service_pb";
474
474
  import { SecretsService as SecretsService2 } from "@eide/foir-proto-ts/secrets/v1/secrets_pb";
475
475
 
@@ -1464,7 +1464,10 @@ import {
1464
1464
  GlobalSearchRequestSchema,
1465
1465
  GetEmbeddingStatsRequestSchema,
1466
1466
  GetRecordEmbeddingsRequestSchema,
1467
- FindSimilarRecordsRequestSchema
1467
+ FindSimilarRecordsRequestSchema,
1468
+ WriteEmbeddingsRequestSchema,
1469
+ DeleteEmbeddingsRequestSchema,
1470
+ SearchEmbeddingsRequestSchema
1468
1471
  } from "@eide/foir-proto-ts/records/v1/records_pb";
1469
1472
  import { RecordType } from "@eide/foir-proto-ts/records/v1/records_pb";
1470
1473
  function sanitizeData(obj) {
@@ -1812,6 +1815,34 @@ function createRecordsMethods(client) {
1812
1815
  })
1813
1816
  );
1814
1817
  return resp.records ?? [];
1818
+ },
1819
+ async writeEmbeddings(params) {
1820
+ const resp = await client.writeEmbeddings(
1821
+ create4(WriteEmbeddingsRequestSchema, {
1822
+ recordId: params.recordId,
1823
+ vector: params.vector,
1824
+ dimensions: params.dimensions,
1825
+ provider: params.provider,
1826
+ modelName: params.modelName
1827
+ })
1828
+ );
1829
+ return resp.success;
1830
+ },
1831
+ async deleteEmbeddings(recordId) {
1832
+ const resp = await client.deleteEmbeddings(
1833
+ create4(DeleteEmbeddingsRequestSchema, { recordId })
1834
+ );
1835
+ return resp.success;
1836
+ },
1837
+ async searchEmbeddings(params) {
1838
+ const resp = await client.searchEmbeddings(
1839
+ create4(SearchEmbeddingsRequestSchema, {
1840
+ queryVector: params.queryVector,
1841
+ modelKey: params.modelKey,
1842
+ limit: params.limit ?? 10
1843
+ })
1844
+ );
1845
+ return resp.results ?? [];
1815
1846
  }
1816
1847
  };
1817
1848
  }
@@ -3032,8 +3063,144 @@ function createCronSchedulesMethods(client) {
3032
3063
  };
3033
3064
  }
3034
3065
 
3035
- // src/lib/rpc/secrets.ts
3066
+ // src/lib/rpc/publish-batches.ts
3036
3067
  import { create as create13 } from "@bufbuild/protobuf";
3068
+ import { timestampFromDate } from "@bufbuild/protobuf/wkt";
3069
+ import {
3070
+ ListPublishBatchesRequestSchema,
3071
+ GetPublishBatchRequestSchema,
3072
+ CreatePublishBatchRequestSchema,
3073
+ UpdatePublishBatchRequestSchema,
3074
+ DeletePublishBatchRequestSchema,
3075
+ TriggerPublishBatchRequestSchema,
3076
+ PausePublishBatchRequestSchema,
3077
+ ResumePublishBatchRequestSchema,
3078
+ PreviewRollbackBatchRequestSchema,
3079
+ RollbackPublishBatchRequestSchema,
3080
+ RetryFailedBatchItemsRequestSchema,
3081
+ AddItemsToPublishBatchRequestSchema,
3082
+ RemoveItemsFromPublishBatchRequestSchema
3083
+ } from "@eide/foir-proto-ts/schedules/v1/schedules_pb";
3084
+ function createPublishBatchesMethods(client) {
3085
+ return {
3086
+ async listPublishBatches(params = {}) {
3087
+ const resp = await client.listPublishBatches(
3088
+ create13(ListPublishBatchesRequestSchema, {
3089
+ status: params.status,
3090
+ limit: params.limit ?? 50,
3091
+ offset: params.offset ?? 0
3092
+ })
3093
+ );
3094
+ return { batches: resp.batches ?? [], total: resp.total };
3095
+ },
3096
+ async getPublishBatch(id) {
3097
+ const resp = await client.getPublishBatch(
3098
+ create13(GetPublishBatchRequestSchema, { id })
3099
+ );
3100
+ return { batch: resp.batch ?? null, items: resp.items ?? [] };
3101
+ },
3102
+ async createPublishBatch(input) {
3103
+ const resp = await client.createPublishBatch(
3104
+ create13(CreatePublishBatchRequestSchema, {
3105
+ name: input.name,
3106
+ description: input.description,
3107
+ scheduledAt: timestampFromDate(input.scheduledAt),
3108
+ versionIds: input.versionIds ?? [],
3109
+ modelIds: input.modelIds ?? [],
3110
+ operationIds: input.operationIds ?? [],
3111
+ contextDimensionIds: input.contextDimensionIds ?? [],
3112
+ authProviderIds: input.authProviderIds ?? [],
3113
+ includeProfileSchema: input.includeProfileSchema ?? false
3114
+ })
3115
+ );
3116
+ return resp.batch ?? null;
3117
+ },
3118
+ async updatePublishBatch(input) {
3119
+ const resp = await client.updatePublishBatch(
3120
+ create13(UpdatePublishBatchRequestSchema, {
3121
+ id: input.id,
3122
+ name: input.name,
3123
+ description: input.description,
3124
+ scheduledAt: input.scheduledAt ? timestampFromDate(input.scheduledAt) : void 0
3125
+ })
3126
+ );
3127
+ return resp.batch ?? null;
3128
+ },
3129
+ async deletePublishBatch(id) {
3130
+ const resp = await client.deletePublishBatch(
3131
+ create13(DeletePublishBatchRequestSchema, { id })
3132
+ );
3133
+ return resp.success;
3134
+ },
3135
+ async triggerPublishBatch(id) {
3136
+ const resp = await client.triggerPublishBatch(
3137
+ create13(TriggerPublishBatchRequestSchema, { id })
3138
+ );
3139
+ return resp.batch ?? null;
3140
+ },
3141
+ async pausePublishBatch(id) {
3142
+ const resp = await client.pausePublishBatch(
3143
+ create13(PausePublishBatchRequestSchema, { id })
3144
+ );
3145
+ return resp.batch ?? null;
3146
+ },
3147
+ async resumePublishBatch(id) {
3148
+ const resp = await client.resumePublishBatch(
3149
+ create13(ResumePublishBatchRequestSchema, { id })
3150
+ );
3151
+ return resp.batch ?? null;
3152
+ },
3153
+ async previewRollback(batchId) {
3154
+ const resp = await client.previewRollbackBatch(
3155
+ create13(PreviewRollbackBatchRequestSchema, { batchId })
3156
+ );
3157
+ return resp;
3158
+ },
3159
+ async rollbackPublishBatch(batchId) {
3160
+ const resp = await client.rollbackPublishBatch(
3161
+ create13(RollbackPublishBatchRequestSchema, { batchId })
3162
+ );
3163
+ return resp.batch ?? null;
3164
+ },
3165
+ async retryFailedItems(batchId) {
3166
+ const resp = await client.retryFailedBatchItems(
3167
+ create13(RetryFailedBatchItemsRequestSchema, { batchId })
3168
+ );
3169
+ return resp.batch ?? null;
3170
+ },
3171
+ async addItems(input) {
3172
+ const resp = await client.addItemsToPublishBatch(
3173
+ create13(AddItemsToPublishBatchRequestSchema, {
3174
+ batchId: input.batchId,
3175
+ versionIds: input.versionIds ?? [],
3176
+ modelIds: input.modelIds ?? [],
3177
+ operationIds: input.operationIds ?? [],
3178
+ contextDimensionIds: input.contextDimensionIds ?? [],
3179
+ authProviderIds: input.authProviderIds ?? [],
3180
+ includeProfileSchema: input.includeProfileSchema ?? false
3181
+ })
3182
+ );
3183
+ return resp.batch ?? null;
3184
+ },
3185
+ async removeItems(input) {
3186
+ const resp = await client.removeItemsFromPublishBatch(
3187
+ create13(RemoveItemsFromPublishBatchRequestSchema, {
3188
+ batchId: input.batchId,
3189
+ versionIds: input.versionIds ?? [],
3190
+ modelIds: input.modelIds ?? [],
3191
+ operationIds: input.operationIds ?? [],
3192
+ contextDimensionIds: input.contextDimensionIds ?? [],
3193
+ authProviderIds: input.authProviderIds ?? [],
3194
+ excludeProfileSchema: input.excludeProfileSchema ?? false
3195
+ })
3196
+ );
3197
+ return resp.batch ?? null;
3198
+ }
3199
+ };
3200
+ }
3201
+
3202
+ // src/lib/rpc/secrets.ts
3203
+ import { create as create14 } from "@bufbuild/protobuf";
3037
3204
  import {
3038
3205
  PutSecretRequestSchema,
3039
3206
  GetSecretRequestSchema,
@@ -3048,7 +3215,7 @@ function createSecretsMethods(client) {
3048
3215
  return {
3049
3216
  async put(args) {
3050
3217
  const resp = await client.putSecret(
3051
- create13(PutSecretRequestSchema, {
3218
+ create14(PutSecretRequestSchema, {
3052
3219
  tenantId: args.tenantId,
3053
3220
  projectId: args.projectId,
3054
3221
  ownerKind: args.ownerKind,
@@ -3061,12 +3228,12 @@ function createSecretsMethods(client) {
3061
3228
  },
3062
3229
  async get(ref, purpose) {
3063
3230
  return client.getSecret(
3064
- create13(GetSecretRequestSchema, { ref, purpose: purpose ?? "" })
3231
+ create14(GetSecretRequestSchema, { ref, purpose: purpose ?? "" })
3065
3232
  );
3066
3233
  },
3067
3234
  async list(args) {
3068
3235
  const resp = await client.listSecrets(
3069
- create13(ListSecretsRequestSchema, {
3236
+ create14(ListSecretsRequestSchema, {
3070
3237
  tenantId: args.tenantId,
3071
3238
  projectId: args.projectId,
3072
3239
  ownerKind: args.ownerKind ?? OwnerKind.UNSPECIFIED,
@@ -3078,19 +3245,19 @@ function createSecretsMethods(client) {
3078
3245
  },
3079
3246
  async rotate(ref, plaintext) {
3080
3247
  const resp = await client.rotateSecret(
3081
- create13(RotateSecretRequestSchema, { ref, plaintext })
3248
+ create14(RotateSecretRequestSchema, { ref, plaintext })
3082
3249
  );
3083
3250
  return resp.newRef;
3084
3251
  },
3085
3252
  async delete(ref) {
3086
- await client.deleteSecret(create13(DeleteSecretRequestSchema, { ref }));
3253
+ await client.deleteSecret(create14(DeleteSecretRequestSchema, { ref }));
3087
3254
  },
3088
3255
  async restore(ref) {
3089
- await client.restoreSecret(create13(RestoreSecretRequestSchema, { ref }));
3256
+ await client.restoreSecret(create14(RestoreSecretRequestSchema, { ref }));
3090
3257
  },
3091
3258
  async purge(args = {}) {
3092
3259
  const resp = await client.purgeSoftDeleted(
3093
- create13(PurgeSoftDeletedRequestSchema, {
3260
+ create14(PurgeSoftDeletedRequestSchema, {
3094
3261
  tenantId: args.tenantId ?? "",
3095
3262
  projectId: args.projectId ?? ""
3096
3263
  })
@@ -3154,7 +3321,10 @@ async function createPlatformClient(options) {
3154
3321
  createRpcClient(NotificationsService2, transport)
3155
3322
  ),
3156
3323
  cronSchedules: createCronSchedulesMethods(
3157
- createRpcClient(SchedulesService2, transport)
3324
+ createRpcClient(SchedulesService3, transport)
3325
+ ),
3326
+ publishBatches: createPublishBatchesMethods(
3327
+ createRpcClient(SchedulesService3, transport)
3158
3328
  ),
3159
3329
  apps: createAppsMethods(createRpcClient(AppsService2, transport)),
3160
3330
  secrets: createSecretsMethods(createRpcClient(SecretsService2, transport))
@@ -3188,7 +3358,10 @@ function createPlatformClientWithHeaders(apiUrl, headers) {
3188
3358
  createRpcClient(NotificationsService2, transport)
3189
3359
  ),
3190
3360
  cronSchedules: createCronSchedulesMethods(
3191
- createRpcClient(SchedulesService2, transport)
3361
+ createRpcClient(SchedulesService3, transport)
3362
+ ),
3363
+ publishBatches: createPublishBatchesMethods(
3364
+ createRpcClient(SchedulesService3, transport)
3192
3365
  ),
3193
3366
  apps: createAppsMethods(createRpcClient(AppsService2, transport)),
3194
3367
  secrets: createSecretsMethods(createRpcClient(SecretsService2, transport))
@@ -5627,11 +5800,7 @@ function registerPushCommand(program2, globalOpts) {
5627
5800
  false
5628
5801
  ).option(
5629
5802
  "--publish",
5630
- "Promote updated models, operations, auth providers, and profile schema to the published channel after the push. New resources auto-publish; this flag covers updates, which are otherwise left as drafts.",
5631
- false
5632
- ).option(
5633
- "--publish-tokens",
5634
- "Promote applied design tokens to the published channel after the push. Without this flag, tokens land on the draft channel and the storefront keeps serving the last published snapshot.",
5803
+ "Promote updated models, operations, auth providers, profile schema, and design tokens to the published channel after the push. New resources auto-publish; this flag covers updates, which are otherwise left as drafts.",
5635
5804
  false
5636
5805
  ).option("--env <path>", "Path to .env file (default: .env)").action(
5637
5806
  withErrorHandler(
@@ -5693,7 +5862,7 @@ function registerPushCommand(program2, globalOpts) {
5693
5862
  tenantId: resolved?.project.tenantId,
5694
5863
  projectId: resolved?.project.id,
5695
5864
  force: opts.force ?? false,
5696
- publishDesignTokens: opts.publishTokens ?? false
5865
+ publishDesignTokens: opts.publish ?? false
5697
5866
  });
5698
5867
  } catch (e) {
5699
5868
  if (e instanceof PushConflictError) {
@@ -5756,6 +5925,7 @@ function registerPushCommand(program2, globalOpts) {
5756
5925
  if (publishCounts.authProviders)
5757
5926
  lines.push(`${publishCounts.authProviders} auth providers`);
5758
5927
  if (publishCounts.profileSchema) lines.push("profile schema");
5928
+ if (summary.designTokensPublished) lines.push("design tokens");
5759
5929
  console.log();
5760
5930
  if (lines.length > 0) {
5761
5931
  console.log(
@@ -5766,7 +5936,7 @@ function registerPushCommand(program2, globalOpts) {
5766
5936
  chalk6.dim(" Nothing to publish (no resources were updated).")
5767
5937
  );
5768
5938
  }
5769
- } else if (summary.updatedModelIds.length + summary.updatedOperationIds.length + summary.updatedAuthProviderIds.length > 0 || summary.profileSchemaUpdated) {
5939
+ } else if (summary.updatedModelIds.length + summary.updatedOperationIds.length + summary.updatedAuthProviderIds.length > 0 || summary.profileSchemaUpdated || summary.designTokensUpdated) {
5770
5940
  console.log();
5771
5941
  console.log(
5772
5942
  chalk6.dim(
@@ -7504,8 +7674,61 @@ function registerApiKeysCommands(program2, globalOpts) {
7504
7674
  );
7505
7675
  }
7506
7676
 
7507
- // src/commands/auth-providers.ts
7677
+ // src/commands/auth.ts
7508
7678
  import chalk11 from "chalk";
7679
+ import { CustomerAuthConfigSchema } from "@eide/foir-proto-ts/identity/v1/identity_pb";
7680
+ import { timestampDate } from "@bufbuild/protobuf/wkt";
7681
+ function registerAuthCommands(program2, globalOpts) {
7682
+ const auth = program2.command("auth").description("Inspect customer auth configuration and verify customer tokens");
7683
+ auth.command("config").description("Print the project's customer-auth configuration").action(
7684
+ withErrorHandler(globalOpts, async () => {
7685
+ const opts = globalOpts();
7686
+ const client = await createPlatformClient(opts);
7687
+ const config2 = await client.identity.getCustomerAuthConfig();
7688
+ if (!config2) {
7689
+ throw new Error("No customer auth configuration found for this project.");
7690
+ }
7691
+ formatOutputProto(CustomerAuthConfigSchema, config2, opts);
7692
+ })
7693
+ );
7694
+ auth.command("verify-token <token>").description("Verify a customer JWT and print its claims").action(
7695
+ withErrorHandler(globalOpts, async (token) => {
7696
+ const opts = globalOpts();
7697
+ const client = await createPlatformClient(opts);
7698
+ const resp = await client.identity.verifyCustomerToken(token);
7699
+ const expiresAtIso = resp.expiresAt ? timestampDate(resp.expiresAt).toISOString() : null;
7700
+ if (opts.json || opts.jsonl) {
7701
+ formatOutput(
7702
+ {
7703
+ valid: resp.valid,
7704
+ customerId: resp.customerId ?? null,
7705
+ email: resp.email ?? null,
7706
+ roles: resp.roles ?? [],
7707
+ expiresAt: expiresAtIso,
7708
+ error: resp.error ?? null
7709
+ },
7710
+ opts
7711
+ );
7712
+ return;
7713
+ }
7714
+ if (!resp.valid) {
7715
+ throw new Error(
7716
+ `Token invalid: ${resp.error ?? "no further detail"}`
7717
+ );
7718
+ }
7719
+ console.log(chalk11.green("\u25CF Valid"));
7720
+ if (resp.customerId)
7721
+ console.log(` Customer: ${chalk11.cyan(resp.customerId)}`);
7722
+ if (resp.email) console.log(` Email: ${resp.email}`);
7723
+ if (resp.roles && resp.roles.length > 0)
7724
+ console.log(` Roles: ${resp.roles.join(", ")}`);
7725
+ if (expiresAtIso) console.log(` Expires: ${expiresAtIso}`);
7726
+ })
7727
+ );
7728
+ }
7729
+
7730
+ // src/commands/auth-providers.ts
7731
+ import chalk12 from "chalk";
7509
7732
  import { AuthProviderSchema } from "@eide/foir-proto-ts/identity/v1/identity_pb";
7510
7733
  var VALID_TYPES = [
7511
7734
  "OAUTH2",
@@ -7559,7 +7782,7 @@ function registerAuthProvidersCommands(program2, globalOpts) {
7559
7782
  formatOutputProto(AuthProviderSchema, provider, opts);
7560
7783
  } else {
7561
7784
  const p = provider;
7562
- console.log(chalk11.bold(`${p.name}`) + chalk11.gray(` (${p.key})`));
7785
+ console.log(chalk12.bold(`${p.name}`) + chalk12.gray(` (${p.key})`));
7563
7786
  console.log(` Type: ${p.type}`);
7564
7787
  console.log(` Enabled: ${p.enabled ? "yes" : "no"}`);
7565
7788
  console.log(` Default: ${p.isDefault ? "yes" : "no"}`);
@@ -7573,13 +7796,13 @@ function registerAuthProvidersCommands(program2, globalOpts) {
7573
7796
  if (p.configDisplay) {
7574
7797
  console.log(` Config:`);
7575
7798
  console.log(
7576
- chalk11.gray(
7799
+ chalk12.gray(
7577
7800
  JSON.stringify(p.configDisplay, null, 2).replace(/^/gm, " ")
7578
7801
  )
7579
7802
  );
7580
7803
  }
7581
- console.log(chalk11.gray(` Created: ${p.createdAt}`));
7582
- console.log(chalk11.gray(` Updated: ${p.updatedAt}`));
7804
+ console.log(chalk12.gray(` Created: ${p.createdAt}`));
7805
+ console.log(chalk12.gray(` Updated: ${p.updatedAt}`));
7583
7806
  }
7584
7807
  })
7585
7808
  );
@@ -7689,6 +7912,637 @@ function registerAuthProvidersCommands(program2, globalOpts) {
7689
7912
  );
7690
7913
  }
7691
7914
 
7915
+ // src/commands/embeddings.ts
7916
+ import chalk13 from "chalk";
7917
+ function registerEmbeddingsCommands(program2, globalOpts) {
7918
+ const embeddings = program2.command("embeddings").description("Manage vector embeddings for semantic search");
7919
+ embeddings.command("write").description("Write an embedding vector for a record").option("-d, --data <json>", "Embedding input as JSON string").option("--file <path>", "Embedding input from JSON file").action(
7920
+ withErrorHandler(globalOpts, async (cmdOpts) => {
7921
+ const opts = globalOpts();
7922
+ const input = await parseInputData({
7923
+ data: cmdOpts.data,
7924
+ file: cmdOpts.file
7925
+ });
7926
+ if (!input?.recordId) {
7927
+ throw new Error("Embedding input missing required field: recordId");
7928
+ }
7929
+ if (!Array.isArray(input.vector) || input.vector.length === 0) {
7930
+ throw new Error(
7931
+ "Embedding input missing required field: vector (non-empty number[])"
7932
+ );
7933
+ }
7934
+ const dimensions = input.dimensions ?? input.vector.length;
7935
+ const client = await createPlatformClient(opts);
7936
+ const ok = await client.records.writeEmbeddings({
7937
+ recordId: input.recordId,
7938
+ vector: input.vector,
7939
+ dimensions,
7940
+ provider: input.provider,
7941
+ modelName: input.modelName
7942
+ });
7943
+ if (opts.json || opts.jsonl) {
7944
+ formatOutput({ written: ok, recordId: input.recordId, dimensions }, opts);
7945
+ } else if (ok) {
7946
+ success(
7947
+ `Wrote ${dimensions}-dim embedding for ${input.recordId}`
7948
+ );
7949
+ } else {
7950
+ throw new Error(`Write failed for ${input.recordId}`);
7951
+ }
7952
+ })
7953
+ );
7954
+ embeddings.command("delete <recordId>").description("Delete the embedding for a record").option("--confirm", "Skip confirmation prompt").action(
7955
+ withErrorHandler(
7956
+ globalOpts,
7957
+ async (recordId, cmdOpts) => {
7958
+ const opts = globalOpts();
7959
+ const confirmed = await confirmAction(
7960
+ `Delete embedding for ${recordId}?`,
7961
+ { confirm: !!cmdOpts.confirm }
7962
+ );
7963
+ if (!confirmed) {
7964
+ console.log("Aborted.");
7965
+ return;
7966
+ }
7967
+ const client = await createPlatformClient(opts);
7968
+ const ok = await client.records.deleteEmbeddings(recordId);
7969
+ if (opts.json || opts.jsonl) {
7970
+ formatOutput({ deleted: ok, recordId }, opts);
7971
+ } else {
7972
+ success(`Deleted embedding for ${recordId}`);
7973
+ }
7974
+ }
7975
+ )
7976
+ );
7977
+ embeddings.command("search").description("Search by vector similarity").requiredOption(
7978
+ "-d, --data <json>",
7979
+ 'Search input as JSON: {"queryVector":[\u2026],"modelKey":"\u2026","limit":10}'
7980
+ ).action(
7981
+ withErrorHandler(globalOpts, async (cmdOpts) => {
7982
+ const opts = globalOpts();
7983
+ const input = await parseInputData({
7984
+ data: cmdOpts.data
7985
+ });
7986
+ if (!Array.isArray(input.queryVector) || input.queryVector.length === 0) {
7987
+ throw new Error(
7988
+ "Search input missing required field: queryVector (non-empty number[])"
7989
+ );
7990
+ }
7991
+ const client = await createPlatformClient(opts);
7992
+ const results = await client.records.searchEmbeddings({
7993
+ queryVector: input.queryVector,
7994
+ modelKey: input.modelKey,
7995
+ limit: input.limit
7996
+ });
7997
+ if (opts.json || opts.jsonl) {
7998
+ formatOutput(results, opts);
7999
+ return;
8000
+ }
8001
+ if (results.length === 0) {
8002
+ console.log(chalk13.dim("No matches."));
8003
+ return;
8004
+ }
8005
+ for (const r of results) {
8006
+ const score = typeof r.similarity === "number" ? r.similarity.toFixed(4) : "\u2014";
8007
+ console.log(
8008
+ ` ${chalk13.cyan(r.id)} ${chalk13.dim(r.modelKey ?? "")} ${chalk13.gray(`sim=${score}`)}`
8009
+ );
8010
+ }
8011
+ })
8012
+ );
8013
+ embeddings.command("list <recordId>").description("List embeddings stored for a record").action(
8014
+ withErrorHandler(globalOpts, async (recordId) => {
8015
+ const opts = globalOpts();
8016
+ const client = await createPlatformClient(opts);
8017
+ const items = await client.records.getRecordEmbeddings(recordId);
8018
+ formatOutput(items, opts);
8019
+ })
8020
+ );
8021
+ embeddings.command("stats [modelKey]").description("Embedding statistics, optionally scoped to a model").action(
8022
+ withErrorHandler(globalOpts, async (modelKey) => {
8023
+ const opts = globalOpts();
8024
+ const client = await createPlatformClient(opts);
8025
+ const stats = await client.records.getEmbeddingStats(modelKey);
8026
+ if (opts.json || opts.jsonl) {
8027
+ formatOutput(stats, opts);
8028
+ return;
8029
+ }
8030
+ if (stats.length === 0) {
8031
+ console.log(chalk13.dim("No embeddings yet."));
8032
+ return;
8033
+ }
8034
+ for (const s of stats) {
8035
+ console.log(
8036
+ ` ${chalk13.cyan(s.modelKey)} ${chalk13.dim(`embedded=${s.embeddedRecords}/${s.totalRecords} pending=${s.pendingRecords}`)}`
8037
+ );
8038
+ }
8039
+ })
8040
+ );
8041
+ embeddings.command("similar <recordId>").description("Find records similar to the given record").option("--model-key <key>", "Limit matches to a specific model").option("--limit <n>", "Maximum results (default: 10)").action(
8042
+ withErrorHandler(
8043
+ globalOpts,
8044
+ async (recordId, cmdOpts) => {
8045
+ const opts = globalOpts();
8046
+ const client = await createPlatformClient(opts);
8047
+ const results = await client.records.findSimilarRecords({
8048
+ recordId,
8049
+ modelKey: cmdOpts.modelKey,
8050
+ limit: cmdOpts.limit ? parseInt(String(cmdOpts.limit), 10) : void 0
8051
+ });
8052
+ if (opts.json || opts.jsonl) {
8053
+ formatOutput(results, opts);
8054
+ return;
8055
+ }
8056
+ if (results.length === 0) {
8057
+ console.log(chalk13.dim("No similar records."));
8058
+ return;
8059
+ }
8060
+ for (const r of results) {
8061
+ const score = typeof r.similarity === "number" ? r.similarity.toFixed(4) : "\u2014";
8062
+ console.log(
8063
+ ` ${chalk13.cyan(r.id)} ${chalk13.dim(r.modelKey ?? "")} ${chalk13.gray(`sim=${score}`)}`
8064
+ );
8065
+ }
8066
+ }
8067
+ )
8068
+ );
8069
+ }
8070
+
8071
+ // src/commands/hooks.ts
8072
+ import {
8073
+ HookSchema,
8074
+ HookDeliverySchema
8075
+ } from "@eide/foir-proto-ts/hooks/v1/hooks_pb";
8076
+ function registerHooksCommands(program2, globalOpts) {
8077
+ const hooks = program2.command("hooks").description("Manage lifecycle hooks (event-driven webhooks)");
8078
+ hooks.command("list").description("List hooks").option("--event <event>", "Filter by event name").option("--active", "Show only active hooks").option("--inactive", "Show only inactive hooks").option("--limit <n>", "Maximum results (default: 50)").option("--offset <n>", "Pagination offset").action(
8079
+ withErrorHandler(globalOpts, async (cmdOpts) => {
8080
+ const opts = globalOpts();
8081
+ const client = await createPlatformClient(opts);
8082
+ let isActive;
8083
+ if (cmdOpts.active) isActive = true;
8084
+ else if (cmdOpts.inactive) isActive = false;
8085
+ const resp = await client.hooks.listHooks({
8086
+ event: cmdOpts.event,
8087
+ isActive,
8088
+ limit: cmdOpts.limit ? parseInt(String(cmdOpts.limit), 10) : void 0,
8089
+ offset: cmdOpts.offset ? parseInt(String(cmdOpts.offset), 10) : void 0
8090
+ });
8091
+ formatListProto(HookSchema, resp.hooks ?? [], opts, {
8092
+ columns: [
8093
+ { key: "id", header: "ID", width: 28 },
8094
+ { key: "key", header: "Key", width: 24 },
8095
+ { key: "name", header: "Name", width: 24 },
8096
+ { key: "event", header: "Event", width: 22 },
8097
+ { key: "targetType", header: "Target", width: 14 },
8098
+ {
8099
+ key: "isActive",
8100
+ header: "Active",
8101
+ width: 7,
8102
+ format: (v) => v ? "yes" : "no"
8103
+ }
8104
+ ]
8105
+ });
8106
+ })
8107
+ );
8108
+ hooks.command("get <keyOrId>").description("Get a hook by key or ID").action(
8109
+ withErrorHandler(globalOpts, async (keyOrId) => {
8110
+ const opts = globalOpts();
8111
+ const client = await createPlatformClient(opts);
8112
+ const hook = keyOrId.includes("-") || keyOrId.length > 20 ? await client.hooks.getHook(keyOrId) : await client.hooks.getHookByKey(keyOrId);
8113
+ if (!hook) {
8114
+ throw new Error(`Hook not found: ${keyOrId}`);
8115
+ }
8116
+ formatOutputProto(HookSchema, hook, opts);
8117
+ })
8118
+ );
8119
+ hooks.command("create").description("Create a hook").option("-d, --data <json>", "Hook definition as JSON string").option("--file <path>", "Hook definition from JSON file").action(
8120
+ withErrorHandler(globalOpts, async (cmdOpts) => {
8121
+ const opts = globalOpts();
8122
+ const input = await parseInputData({
8123
+ data: cmdOpts.data,
8124
+ file: cmdOpts.file
8125
+ });
8126
+ for (const required of ["key", "name", "event", "targetType"]) {
8127
+ if (!input[required]) {
8128
+ throw new Error(`Hook input missing required field: ${required}`);
8129
+ }
8130
+ }
8131
+ const client = await createPlatformClient(opts);
8132
+ const hook = await client.hooks.createHook({
8133
+ key: input.key,
8134
+ name: input.name,
8135
+ event: input.event,
8136
+ targetType: input.targetType,
8137
+ description: input.description,
8138
+ operationKey: input.operationKey,
8139
+ notificationConfig: input.notificationConfig,
8140
+ filter: input.filter,
8141
+ configId: input.configId
8142
+ });
8143
+ if (opts.json || opts.jsonl) {
8144
+ formatOutputProto(HookSchema, hook, opts);
8145
+ } else {
8146
+ success(`Created hook ${hook?.key} (${hook?.id})`);
8147
+ }
8148
+ })
8149
+ );
8150
+ hooks.command("update <id>").description("Update a hook").option("-d, --data <json>", "Patch fields as JSON string").option("--file <path>", "Patch fields from JSON file").option("--active", "Activate the hook").option("--no-active", "Deactivate the hook").action(
8151
+ withErrorHandler(
8152
+ globalOpts,
8153
+ async (id, cmdOpts) => {
8154
+ const opts = globalOpts();
8155
+ const patch = cmdOpts.data || cmdOpts.file ? await parseInputData({
8156
+ data: cmdOpts.data,
8157
+ file: cmdOpts.file
8158
+ }) : {};
8159
+ const update = {
8160
+ id,
8161
+ name: patch.name,
8162
+ description: patch.description,
8163
+ operationKey: patch.operationKey,
8164
+ notificationConfig: patch.notificationConfig,
8165
+ filter: patch.filter
8166
+ };
8167
+ if (cmdOpts.active !== void 0) {
8168
+ update.isActive = !!cmdOpts.active;
8169
+ }
8170
+ const client = await createPlatformClient(opts);
8171
+ const hook = await client.hooks.updateHook(update);
8172
+ if (opts.json || opts.jsonl) {
8173
+ formatOutputProto(HookSchema, hook, opts);
8174
+ } else {
8175
+ success(`Updated hook ${hook?.key} (${hook?.id})`);
8176
+ }
8177
+ }
8178
+ )
8179
+ );
8180
+ hooks.command("delete <id>").description("Delete a hook").option("--confirm", "Skip confirmation prompt").action(
8181
+ withErrorHandler(
8182
+ globalOpts,
8183
+ async (id, cmdOpts) => {
8184
+ const opts = globalOpts();
8185
+ const confirmed = await confirmAction(
8186
+ `Delete hook ${id}? This also removes its delivery history.`,
8187
+ { confirm: !!cmdOpts.confirm }
8188
+ );
8189
+ if (!confirmed) {
8190
+ console.log("Aborted.");
8191
+ return;
8192
+ }
8193
+ const client = await createPlatformClient(opts);
8194
+ const deleted = await client.hooks.deleteHook(id);
8195
+ if (opts.json || opts.jsonl) {
8196
+ formatOutput({ deleted, id }, opts);
8197
+ } else {
8198
+ success(`Deleted hook ${id}`);
8199
+ }
8200
+ }
8201
+ )
8202
+ );
8203
+ hooks.command("deliveries <hookId>").description("List recent deliveries for a hook").option("--status <status>", "Filter by status (success / failed / pending)").option("--limit <n>", "Maximum results (default: 50)").option("--offset <n>", "Pagination offset").action(
8204
+ withErrorHandler(
8205
+ globalOpts,
8206
+ async (hookId, cmdOpts) => {
8207
+ const opts = globalOpts();
8208
+ const client = await createPlatformClient(opts);
8209
+ const resp = await client.hooks.listHookDeliveries({
8210
+ hookId,
8211
+ status: cmdOpts.status,
8212
+ limit: cmdOpts.limit ? parseInt(String(cmdOpts.limit), 10) : void 0,
8213
+ offset: cmdOpts.offset ? parseInt(String(cmdOpts.offset), 10) : void 0
8214
+ });
8215
+ formatListProto(HookDeliverySchema, resp.deliveries ?? [], opts, {
8216
+ columns: [
8217
+ { key: "id", header: "ID", width: 28 },
8218
+ { key: "event", header: "Event", width: 22 },
8219
+ { key: "status", header: "Status", width: 10 },
8220
+ { key: "attempts", header: "Tries", width: 6 },
8221
+ {
8222
+ key: "durationMs",
8223
+ header: "Duration",
8224
+ width: 10,
8225
+ format: (v) => typeof v === "number" ? `${v}ms` : "\u2014"
8226
+ },
8227
+ { key: "deliveredAt", header: "Delivered", width: 24 }
8228
+ ]
8229
+ });
8230
+ }
8231
+ )
8232
+ );
8233
+ hooks.command("retry-delivery <deliveryId>").description("Retry a failed delivery").action(
8234
+ withErrorHandler(globalOpts, async (deliveryId) => {
8235
+ const opts = globalOpts();
8236
+ const client = await createPlatformClient(opts);
8237
+ const ok = await client.hooks.retryHookDelivery(deliveryId);
8238
+ if (opts.json || opts.jsonl) {
8239
+ formatOutput({ retried: ok, deliveryId }, opts);
8240
+ } else if (ok) {
8241
+ success(`Re-queued delivery ${deliveryId}`);
8242
+ } else {
8243
+ throw new Error(`Retry failed for delivery ${deliveryId}`);
8244
+ }
8245
+ })
8246
+ );
8247
+ hooks.command("test <hookId>").description("Send a test delivery against the hook").option("-d, --data <json>", "Test payload as JSON string").option("--file <path>", "Test payload from JSON file").action(
8248
+ withErrorHandler(
8249
+ globalOpts,
8250
+ async (hookId, cmdOpts) => {
8251
+ const opts = globalOpts();
8252
+ const testPayload = cmdOpts.data || cmdOpts.file ? await parseInputData({
8253
+ data: cmdOpts.data,
8254
+ file: cmdOpts.file
8255
+ }) : void 0;
8256
+ const client = await createPlatformClient(opts);
8257
+ const result = await client.hooks.testHook({ hookId, testPayload });
8258
+ if (opts.json || opts.jsonl) {
8259
+ formatOutput(result, opts);
8260
+ } else if (result.success) {
8261
+ success(`Test delivery succeeded for hook ${hookId}`);
8262
+ } else {
8263
+ throw new Error(
8264
+ `Test delivery failed: ${result.error ?? "unknown error"}`
8265
+ );
8266
+ }
8267
+ }
8268
+ )
8269
+ );
8270
+ }
8271
+
8272
+ // src/commands/rollouts.ts
8273
+ import chalk14 from "chalk";
8274
+ import { PublishBatchSchema } from "@eide/foir-proto-ts/schedules/v1/schedules_pb";
8275
+ function parseScheduledAt(value) {
8276
+ const date = new Date(value);
8277
+ if (Number.isNaN(date.getTime())) {
8278
+ throw new Error(
8279
+ `Invalid scheduledAt "${value}". Expected an ISO-8601 timestamp.`
8280
+ );
8281
+ }
8282
+ return date;
8283
+ }
8284
+ function registerRolloutsCommands(program2, globalOpts) {
8285
+ const rollouts = program2.command("rollouts").description("Manage bulk scheduled publishing rollouts");
8286
+ rollouts.command("list").description("List rollouts").option("--status <status>", "Filter by status").option("--limit <n>", "Maximum results (default: 50)").option("--offset <n>", "Pagination offset").action(
8287
+ withErrorHandler(globalOpts, async (cmdOpts) => {
8288
+ const opts = globalOpts();
8289
+ const client = await createPlatformClient(opts);
8290
+ const { batches } = await client.publishBatches.listPublishBatches({
8291
+ status: cmdOpts.status,
8292
+ limit: cmdOpts.limit ? parseInt(String(cmdOpts.limit), 10) : void 0,
8293
+ offset: cmdOpts.offset ? parseInt(String(cmdOpts.offset), 10) : void 0
8294
+ });
8295
+ formatListProto(PublishBatchSchema, batches, opts, {
8296
+ columns: [
8297
+ { key: "id", header: "ID", width: 28 },
8298
+ { key: "name", header: "Name", width: 28 },
8299
+ { key: "status", header: "Status", width: 12 },
8300
+ { key: "itemCount", header: "Items", width: 6 },
8301
+ { key: "completedCount", header: "Done", width: 6 },
8302
+ { key: "failedCount", header: "Failed", width: 7 },
8303
+ { key: "scheduledAt", header: "Scheduled", width: 24 }
8304
+ ]
8305
+ });
8306
+ })
8307
+ );
8308
+ rollouts.command("get <id>").description("Get a rollout (with its items)").action(
8309
+ withErrorHandler(globalOpts, async (id) => {
8310
+ const opts = globalOpts();
8311
+ const client = await createPlatformClient(opts);
8312
+ const { batch, items } = await client.publishBatches.getPublishBatch(id);
8313
+ if (!batch) throw new Error(`Rollout not found: ${id}`);
8314
+ if (opts.json || opts.jsonl) {
8315
+ formatOutput({ rollout: batch, items }, opts);
8316
+ return;
8317
+ }
8318
+ formatOutputProto(PublishBatchSchema, batch, opts);
8319
+ if (items.length > 0) {
8320
+ console.log();
8321
+ console.log(chalk14.bold(`Items (${items.length}):`));
8322
+ for (const it of items) {
8323
+ console.log(
8324
+ ` ${chalk14.cyan(it.id)} ${chalk14.dim(it.targetKind)} ${chalk14.gray(it.status ?? "")}`
8325
+ );
8326
+ }
8327
+ }
8328
+ })
8329
+ );
8330
+ rollouts.command("create").description("Create a rollout").option("-d, --data <json>", "Rollout definition as JSON string").option("--file <path>", "Rollout definition from JSON file").action(
8331
+ withErrorHandler(globalOpts, async (cmdOpts) => {
8332
+ const opts = globalOpts();
8333
+ const input = await parseInputData({
8334
+ data: cmdOpts.data,
8335
+ file: cmdOpts.file
8336
+ });
8337
+ if (!input?.name) {
8338
+ throw new Error("Rollout input missing required field: name");
8339
+ }
8340
+ if (!input.scheduledAt) {
8341
+ throw new Error("Rollout input missing required field: scheduledAt");
8342
+ }
8343
+ const scheduledAt = parseScheduledAt(input.scheduledAt);
8344
+ const client = await createPlatformClient(opts);
8345
+ const batch = await client.publishBatches.createPublishBatch({
8346
+ name: input.name,
8347
+ description: input.description,
8348
+ scheduledAt,
8349
+ versionIds: input.versionIds,
8350
+ modelIds: input.modelIds,
8351
+ operationIds: input.operationIds,
8352
+ contextDimensionIds: input.contextDimensionIds,
8353
+ authProviderIds: input.authProviderIds,
8354
+ includeProfileSchema: input.includeProfileSchema
8355
+ });
8356
+ if (opts.json || opts.jsonl) {
8357
+ formatOutputProto(PublishBatchSchema, batch, opts);
8358
+ } else {
8359
+ success(`Created rollout ${batch?.name} (${batch?.id})`);
8360
+ }
8361
+ })
8362
+ );
8363
+ rollouts.command("update <id>").description("Update a rollout (name, description, scheduledAt)").option("-d, --data <json>", "Patch fields as JSON string").option("--file <path>", "Patch fields from JSON file").action(
8364
+ withErrorHandler(
8365
+ globalOpts,
8366
+ async (id, cmdOpts) => {
8367
+ const opts = globalOpts();
8368
+ const patch = await parseInputData({
8369
+ data: cmdOpts.data,
8370
+ file: cmdOpts.file
8371
+ });
8372
+ const client = await createPlatformClient(opts);
8373
+ const batch = await client.publishBatches.updatePublishBatch({
8374
+ id,
8375
+ name: patch.name,
8376
+ description: patch.description,
8377
+ scheduledAt: patch.scheduledAt ? parseScheduledAt(patch.scheduledAt) : void 0
8378
+ });
8379
+ if (opts.json || opts.jsonl) {
8380
+ formatOutputProto(PublishBatchSchema, batch, opts);
8381
+ } else {
8382
+ success(`Updated rollout ${batch?.name} (${batch?.id})`);
8383
+ }
8384
+ }
8385
+ )
8386
+ );
8387
+ rollouts.command("delete <id>").description("Delete a rollout before it runs").option("--confirm", "Skip confirmation prompt").action(
8388
+ withErrorHandler(
8389
+ globalOpts,
8390
+ async (id, cmdOpts) => {
8391
+ const opts = globalOpts();
8392
+ const confirmed = await confirmAction(
8393
+ `Delete rollout ${id}? This cannot be undone.`,
8394
+ { confirm: !!cmdOpts.confirm }
8395
+ );
8396
+ if (!confirmed) {
8397
+ console.log("Aborted.");
8398
+ return;
8399
+ }
8400
+ const client = await createPlatformClient(opts);
8401
+ const ok = await client.publishBatches.deletePublishBatch(id);
8402
+ if (opts.json || opts.jsonl) {
8403
+ formatOutput({ deleted: ok, id }, opts);
8404
+ } else {
8405
+ success(`Deleted rollout ${id}`);
8406
+ }
8407
+ }
8408
+ )
8409
+ );
8410
+ rollouts.command("trigger <id>").description("Trigger a rollout immediately (ignore its scheduled time)").action(
8411
+ withErrorHandler(globalOpts, async (id) => {
8412
+ const opts = globalOpts();
8413
+ const client = await createPlatformClient(opts);
8414
+ const batch = await client.publishBatches.triggerPublishBatch(id);
8415
+ if (opts.json || opts.jsonl) {
8416
+ formatOutputProto(PublishBatchSchema, batch, opts);
8417
+ } else {
8418
+ success(`Triggered rollout ${batch?.name} (${batch?.id})`);
8419
+ }
8420
+ })
8421
+ );
8422
+ rollouts.command("pause <id>").description("Pause an in-flight rollout").action(
8423
+ withErrorHandler(globalOpts, async (id) => {
8424
+ const opts = globalOpts();
8425
+ const client = await createPlatformClient(opts);
8426
+ const batch = await client.publishBatches.pausePublishBatch(id);
8427
+ if (opts.json || opts.jsonl) {
8428
+ formatOutputProto(PublishBatchSchema, batch, opts);
8429
+ } else {
8430
+ success(`Paused rollout ${batch?.id}`);
8431
+ }
8432
+ })
8433
+ );
8434
+ rollouts.command("resume <id>").description("Resume a paused rollout").action(
8435
+ withErrorHandler(globalOpts, async (id) => {
8436
+ const opts = globalOpts();
8437
+ const client = await createPlatformClient(opts);
8438
+ const batch = await client.publishBatches.resumePublishBatch(id);
8439
+ if (opts.json || opts.jsonl) {
8440
+ formatOutputProto(PublishBatchSchema, batch, opts);
8441
+ } else {
8442
+ success(`Resumed rollout ${batch?.id}`);
8443
+ }
8444
+ })
8445
+ );
8446
+ rollouts.command("retry <id>").description("Retry failed items in a rollout").action(
8447
+ withErrorHandler(globalOpts, async (id) => {
8448
+ const opts = globalOpts();
8449
+ const client = await createPlatformClient(opts);
8450
+ const batch = await client.publishBatches.retryFailedItems(id);
8451
+ if (opts.json || opts.jsonl) {
8452
+ formatOutputProto(PublishBatchSchema, batch, opts);
8453
+ } else {
8454
+ success(`Re-queued failed items for rollout ${batch?.id}`);
8455
+ }
8456
+ })
8457
+ );
8458
+ rollouts.command("rollback <id>").description(
8459
+ "Roll back a completed rollout (use --preview to dry-run first)"
8460
+ ).option("--preview", "Preview the rollback without executing").option("--confirm", "Skip confirmation prompt").action(
8461
+ withErrorHandler(
8462
+ globalOpts,
8463
+ async (id, cmdOpts) => {
8464
+ const opts = globalOpts();
8465
+ const client = await createPlatformClient(opts);
8466
+ if (cmdOpts.preview) {
8467
+ const preview = await client.publishBatches.previewRollback(id);
8468
+ formatOutput(preview, opts);
8469
+ return;
8470
+ }
8471
+ const confirmed = await confirmAction(
8472
+ `Roll back rollout ${id}? This creates a new inverse rollout that reverts published changes.`,
8473
+ { confirm: !!cmdOpts.confirm }
8474
+ );
8475
+ if (!confirmed) {
8476
+ console.log("Aborted.");
8477
+ return;
8478
+ }
8479
+ const rollback = await client.publishBatches.rollbackPublishBatch(id);
8480
+ if (opts.json || opts.jsonl) {
8481
+ formatOutputProto(PublishBatchSchema, rollback, opts);
8482
+ } else {
8483
+ success(
8484
+ `Rollback rollout ${rollback?.id} created for ${id}`
8485
+ );
8486
+ }
8487
+ }
8488
+ )
8489
+ );
8490
+ rollouts.command("add-items <id>").description("Add items (records / models / operations / etc.) to a rollout").option("-d, --data <json>", "Items as JSON string").option("--file <path>", "Items from JSON file").action(
8491
+ withErrorHandler(
8492
+ globalOpts,
8493
+ async (id, cmdOpts) => {
8494
+ const opts = globalOpts();
8495
+ const items = await parseInputData({
8496
+ data: cmdOpts.data,
8497
+ file: cmdOpts.file
8498
+ });
8499
+ const client = await createPlatformClient(opts);
8500
+ const batch = await client.publishBatches.addItems({
8501
+ batchId: id,
8502
+ versionIds: items.versionIds,
8503
+ modelIds: items.modelIds,
8504
+ operationIds: items.operationIds,
8505
+ contextDimensionIds: items.contextDimensionIds,
8506
+ authProviderIds: items.authProviderIds,
8507
+ includeProfileSchema: items.includeProfileSchema
8508
+ });
8509
+ if (opts.json || opts.jsonl) {
8510
+ formatOutputProto(PublishBatchSchema, batch, opts);
8511
+ } else {
8512
+ success(`Added items to rollout ${batch?.id}`);
8513
+ }
8514
+ }
8515
+ )
8516
+ );
8517
+ rollouts.command("remove-items <id>").description("Remove items from a rollout").option("-d, --data <json>", "Items to remove as JSON string").option("--file <path>", "Items to remove from JSON file").action(
8518
+ withErrorHandler(
8519
+ globalOpts,
8520
+ async (id, cmdOpts) => {
8521
+ const opts = globalOpts();
8522
+ const items = await parseInputData({
8523
+ data: cmdOpts.data,
8524
+ file: cmdOpts.file
8525
+ });
8526
+ const client = await createPlatformClient(opts);
8527
+ const batch = await client.publishBatches.removeItems({
8528
+ batchId: id,
8529
+ versionIds: items.versionIds,
8530
+ modelIds: items.modelIds,
8531
+ operationIds: items.operationIds,
8532
+ contextDimensionIds: items.contextDimensionIds,
8533
+ authProviderIds: items.authProviderIds,
8534
+ excludeProfileSchema: items.excludeProfileSchema
8535
+ });
8536
+ if (opts.json || opts.jsonl) {
8537
+ formatOutputProto(PublishBatchSchema, batch, opts);
8538
+ } else {
8539
+ success(`Removed items from rollout ${batch?.id}`);
8540
+ }
8541
+ }
8542
+ )
8543
+ );
8544
+ }
8545
+
7692
8546
  // src/commands/locales.ts
7693
8547
  import { LocaleSchema } from "@eide/foir-proto-ts/settings/v1/settings_pb";
7694
8548
  function registerLocalesCommands(program2, globalOpts) {
@@ -7893,7 +8747,7 @@ function registerSettingsCommands(program2, globalOpts) {
7893
8747
  // src/commands/design-tokens.ts
7894
8748
  import { existsSync as existsSync6, readFileSync as readFileSync2 } from "fs";
7895
8749
  import { resolve as resolve6 } from "path";
7896
- import chalk12 from "chalk";
8750
+ import chalk15 from "chalk";
7897
8751
  function registerDesignTokensCommands(program2, globalOpts) {
7898
8752
  const tokens = program2.command("design-tokens").description("Manage project design tokens (W3C-formatted)");
7899
8753
  tokens.command("get").description("Print the current design tokens document").option("--channel <channel>", "draft | published", "draft").option(
@@ -7941,7 +8795,7 @@ function registerDesignTokensCommands(program2, globalOpts) {
7941
8795
  const resp = await client.settings.publishDesignTokens();
7942
8796
  success("Design tokens published");
7943
8797
  if (resp.breakingChanges && resp.breakingChanges.length > 0) {
7944
- console.log(chalk12.yellow("\nBreaking changes:"));
8798
+ console.log(chalk15.yellow("\nBreaking changes:"));
7945
8799
  for (const c of resp.breakingChanges) {
7946
8800
  console.log(` ${c.severity} ${c.path}: ${c.description}`);
7947
8801
  }
@@ -7957,7 +8811,7 @@ function registerDesignTokensCommands(program2, globalOpts) {
7957
8811
  const resp = await client.settings.publishDesignTokens();
7958
8812
  success("Design tokens published");
7959
8813
  if (resp.breakingChanges && resp.breakingChanges.length > 0) {
7960
- console.log(chalk12.yellow("\nBreaking changes:"));
8814
+ console.log(chalk15.yellow("\nBreaking changes:"));
7961
8815
  for (const c of resp.breakingChanges) {
7962
8816
  console.log(` ${c.severity} ${c.path}: ${c.description}`);
7963
8817
  }
@@ -7982,12 +8836,12 @@ function registerDesignTokensCommands(program2, globalOpts) {
7982
8836
  return;
7983
8837
  }
7984
8838
  if (status.hasPendingChanges) {
7985
- console.log(chalk12.yellow("\u25CF Pending changes"));
8839
+ console.log(chalk15.yellow("\u25CF Pending changes"));
7986
8840
  } else {
7987
- console.log(chalk12.green("\u25CF Up to date"));
8841
+ console.log(chalk15.green("\u25CF Up to date"));
7988
8842
  }
7989
8843
  if (status.breakingChanges && status.breakingChanges.length > 0) {
7990
- console.log(chalk12.yellow("\nPending changes:"));
8844
+ console.log(chalk15.yellow("\nPending changes:"));
7991
8845
  for (const c of status.breakingChanges) {
7992
8846
  console.log(` ${c.severity} ${c.path}: ${c.description}`);
7993
8847
  }
@@ -9159,7 +10013,11 @@ registerOperationsCommands(program, getGlobalOpts);
9159
10013
  registerSegmentsCommands(program, getGlobalOpts);
9160
10014
  registerSchedulesCommands(program, getGlobalOpts);
9161
10015
  registerApiKeysCommands(program, getGlobalOpts);
10016
+ registerAuthCommands(program, getGlobalOpts);
9162
10017
  registerAuthProvidersCommands(program, getGlobalOpts);
10018
+ registerEmbeddingsCommands(program, getGlobalOpts);
10019
+ registerHooksCommands(program, getGlobalOpts);
10020
+ registerRolloutsCommands(program, getGlobalOpts);
9163
10021
  registerLocalesCommands(program, getGlobalOpts);
9164
10022
  registerSettingsCommands(program, getGlobalOpts);
9165
10023
  registerDesignTokensCommands(program, getGlobalOpts);
@@ -385,7 +385,7 @@ interface ApplyConfigInput {
385
385
  /**
386
386
  * W3C-formatted design tokens document for this project. Reconciled by
387
387
  * `foir push` — the document is applied verbatim to the draft channel.
388
- * Add `--publish-tokens` to promote draft → published in the same push.
388
+ * Add `--publish` to promote draft → published in the same push.
389
389
  */
390
390
  designTokens?: ApplyConfigDesignTokensInput;
391
391
  [key: string]: unknown;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eide/foir-cli",
3
- "version": "0.22.0",
3
+ "version": "0.24.0",
4
4
  "description": "Universal platform CLI for Foir platform",
5
5
  "type": "module",
6
6
  "publishConfig": {