struere 0.14.1 → 0.14.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/bin/struere.js +495 -69
  2. package/dist/cli/commands/deploy.d.ts.map +1 -1
  3. package/dist/cli/commands/dev.d.ts.map +1 -1
  4. package/dist/cli/commands/doctor.d.ts.map +1 -1
  5. package/dist/cli/commands/keys.d.ts +3 -0
  6. package/dist/cli/commands/keys.d.ts.map +1 -0
  7. package/dist/cli/commands/sync.d.ts +6 -1
  8. package/dist/cli/commands/sync.d.ts.map +1 -1
  9. package/dist/cli/commands/triggers.d.ts.map +1 -1
  10. package/dist/cli/index.js +495 -69
  11. package/dist/cli/utils/apiKeys.d.ts +31 -0
  12. package/dist/cli/utils/apiKeys.d.ts.map +1 -0
  13. package/dist/cli/utils/convex.d.ts +7 -0
  14. package/dist/cli/utils/convex.d.ts.map +1 -1
  15. package/dist/cli/utils/extractor.d.ts +11 -1
  16. package/dist/cli/utils/extractor.d.ts.map +1 -1
  17. package/dist/cli/utils/logs.d.ts +4 -3
  18. package/dist/cli/utils/logs.d.ts.map +1 -1
  19. package/dist/cli/utils/threads.d.ts +1 -0
  20. package/dist/cli/utils/threads.d.ts.map +1 -1
  21. package/dist/cli/utils/triggers.d.ts +12 -10
  22. package/dist/cli/utils/triggers.d.ts.map +1 -1
  23. package/dist/client/chatClient.d.ts +8 -0
  24. package/dist/client/chatClient.d.ts.map +1 -0
  25. package/dist/client/dataClient.d.ts +21 -0
  26. package/dist/client/dataClient.d.ts.map +1 -0
  27. package/dist/client/index.d.ts +13 -0
  28. package/dist/client/index.d.ts.map +1 -0
  29. package/dist/client/index.js +245 -0
  30. package/dist/client/transport.d.ts +35 -0
  31. package/dist/client/transport.d.ts.map +1 -0
  32. package/dist/client/types.d.ts +130 -0
  33. package/dist/client/types.d.ts.map +1 -0
  34. package/dist/index.js +2 -2
  35. package/dist/types.d.ts +11 -1
  36. package/dist/types.d.ts.map +1 -1
  37. package/package.json +6 -2
@@ -680,7 +680,8 @@ async function _fireTrigger(options) {
680
680
  slug: options.slug,
681
681
  environment: options.environment,
682
682
  entityId: options.entityId,
683
- data: options.data
683
+ data: options.data,
684
+ ...options.organizationId && { organizationId: options.organizationId }
684
685
  }
685
686
  }),
686
687
  signal: AbortSignal.timeout(60000)
@@ -3226,6 +3227,42 @@ function validateResources(payload, resources) {
3226
3227
  }
3227
3228
 
3228
3229
  // src/cli/commands/sync.ts
3230
+ class SyncValidationFailureError extends Error {
3231
+ validationErrors;
3232
+ constructor(validationErrors) {
3233
+ super("Server-side validation failed for one or more resources");
3234
+ this.name = "SyncValidationFailureError";
3235
+ this.validationErrors = validationErrors;
3236
+ }
3237
+ }
3238
+ function renderValidationErrors(errors) {
3239
+ console.log();
3240
+ console.log(chalk6.red.bold("Validation failed \u2014 no changes were applied."));
3241
+ console.log();
3242
+ const labels = {
3243
+ agents: "agent",
3244
+ entityTypes: "entity type",
3245
+ roles: "role",
3246
+ evalSuites: "eval suite",
3247
+ triggers: "trigger",
3248
+ fixtures: "fixture",
3249
+ routers: "router",
3250
+ tools: "tool"
3251
+ };
3252
+ const order = ["agents", "entityTypes", "roles", "evalSuites", "triggers", "fixtures", "routers", "tools"];
3253
+ for (const key of order) {
3254
+ const items = errors[key];
3255
+ if (!items || items.length === 0)
3256
+ continue;
3257
+ const label = labels[key] || key;
3258
+ console.log(chalk6.red.bold(` ${key}:`), chalk6.red(`${items.length} invalid ${label}${items.length === 1 ? "" : "s"}`));
3259
+ for (const item of items) {
3260
+ const id = item.slug || item.name || "(unidentified)";
3261
+ console.log(chalk6.red(` - ${id}: ${item.error}`));
3262
+ }
3263
+ }
3264
+ console.log();
3265
+ }
3229
3266
  async function performDevSync(cwd, organizationId) {
3230
3267
  generateTypeDeclarations(cwd);
3231
3268
  const resources = await loadAllResources(cwd);
@@ -3256,6 +3293,8 @@ ${resources.errors.join(`
3256
3293
  environment: "development"
3257
3294
  });
3258
3295
  if (!devResult.success) {
3296
+ if (devResult.validationErrors)
3297
+ throw new SyncValidationFailureError(devResult.validationErrors);
3259
3298
  throw new Error(devResult.error || "Dev sync failed");
3260
3299
  }
3261
3300
  const hasEvalContent = payload.evalSuites && payload.evalSuites.length > 0 || payload.fixtures && payload.fixtures.length > 0;
@@ -3271,6 +3310,8 @@ ${resources.errors.join(`
3271
3310
  environment: "eval"
3272
3311
  });
3273
3312
  if (!evalResult.success) {
3313
+ if (evalResult.validationErrors)
3314
+ throw new SyncValidationFailureError(evalResult.validationErrors);
3274
3315
  throw new Error(evalResult.error || "Eval sync failed");
3275
3316
  }
3276
3317
  }
@@ -3343,8 +3384,11 @@ ${resources.errors.join(`
3343
3384
  organizationId,
3344
3385
  environment: "eval"
3345
3386
  });
3346
- if (!result.success)
3387
+ if (!result.success) {
3388
+ if (result.validationErrors)
3389
+ throw new SyncValidationFailureError(result.validationErrors);
3347
3390
  throw new Error(result.error || "Eval sync failed");
3391
+ }
3348
3392
  return result;
3349
3393
  }
3350
3394
  if (environment === "production") {
@@ -3353,8 +3397,11 @@ ${resources.errors.join(`
3353
3397
  organizationId,
3354
3398
  environment: "production"
3355
3399
  });
3356
- if (!result.success)
3400
+ if (!result.success) {
3401
+ if (result.validationErrors)
3402
+ throw new SyncValidationFailureError(result.validationErrors);
3357
3403
  throw new Error(result.error || "Production sync failed");
3404
+ }
3358
3405
  return result;
3359
3406
  }
3360
3407
  return performDevSync(cwd, organizationId);
@@ -3560,6 +3607,15 @@ var syncCommand = new Command5("sync").description("Sync resources to Convex and
3560
3607
  }));
3561
3608
  }
3562
3609
  } catch (error) {
3610
+ if (error instanceof SyncValidationFailureError) {
3611
+ if (jsonMode) {
3612
+ console.log(JSON.stringify({ success: false, validationErrors: error.validationErrors }));
3613
+ } else {
3614
+ output.fail("Sync failed");
3615
+ renderValidationErrors(error.validationErrors);
3616
+ }
3617
+ process.exit(1);
3618
+ }
3563
3619
  if (jsonMode) {
3564
3620
  console.log(JSON.stringify({ success: false, error: error instanceof Error ? error.message : String(error) }));
3565
3621
  } else {
@@ -3578,7 +3634,10 @@ var devCommand = new Command6("dev").description("Watch files and sync to develo
3578
3634
  const apiKey = getApiKey();
3579
3635
  const nonInteractive = !isInteractive();
3580
3636
  if (nonInteractive) {
3581
- console.error("Error: struere dev is a long-running watch process. Use struere sync instead.");
3637
+ console.error(chalk7.red("Error:"), "`struere dev` requires an interactive terminal (TTY) to render its watch UI.");
3638
+ console.error(chalk7.gray(" - For a one-shot sync, use:"), chalk7.cyan("struere sync [--env development]"));
3639
+ console.error(chalk7.gray(" - For continuous deployment in CI/CD, use:"), chalk7.cyan("struere deploy"));
3640
+ console.error(chalk7.gray(" - To run dev in the foreground, attach a TTY (avoid backgrounding with `&` or piping output)."));
3582
3641
  process.exit(1);
3583
3642
  }
3584
3643
  console.log();
@@ -3690,6 +3749,9 @@ var devCommand = new Command6("dev").description("Watch files and sync to develo
3690
3749
  console.log(chalk7.gray(" 2."), "Or run", chalk7.cyan("struere init"), "to select a different organization");
3691
3750
  console.log();
3692
3751
  process.exit(1);
3752
+ } else if (error instanceof SyncValidationFailureError) {
3753
+ spinner.fail("Sync failed");
3754
+ renderValidationErrors(error.validationErrors);
3693
3755
  } else {
3694
3756
  spinner.fail("Sync failed");
3695
3757
  console.log(chalk7.red("Error:"), error instanceof Error ? error.message : String(error));
@@ -3730,8 +3792,13 @@ var devCommand = new Command6("dev").description("Watch files and sync to develo
3730
3792
  await performDevSync(cwd, project.organization.id);
3731
3793
  syncSpinner.succeed("Synced");
3732
3794
  } catch (error) {
3733
- syncSpinner.fail("Sync failed");
3734
- console.log(chalk7.red("Error:"), error instanceof Error ? error.message : String(error));
3795
+ if (error instanceof SyncValidationFailureError) {
3796
+ syncSpinner.fail("Sync failed");
3797
+ renderValidationErrors(error.validationErrors);
3798
+ } else {
3799
+ syncSpinner.fail("Sync failed");
3800
+ console.log(chalk7.red("Error:"), error instanceof Error ? error.message : String(error));
3801
+ }
3735
3802
  }
3736
3803
  };
3737
3804
  const handleFileChange = (path, action) => {
@@ -3998,6 +4065,8 @@ var deployCommand = new Command7("deploy").description("Deploy all resources to
3998
4065
  environment: "production"
3999
4066
  });
4000
4067
  if (!syncResult.success) {
4068
+ if (syncResult.validationErrors)
4069
+ throw new SyncValidationFailureError(syncResult.validationErrors);
4001
4070
  throw new Error(syncResult.error || "Deploy failed");
4002
4071
  }
4003
4072
  const elapsed = Date.now() - startTime;
@@ -4107,6 +4176,14 @@ var deployCommand = new Command7("deploy").description("Deploy all resources to
4107
4176
  console.log();
4108
4177
  }
4109
4178
  process.exit(1);
4179
+ } else if (error instanceof SyncValidationFailureError) {
4180
+ if (jsonMode) {
4181
+ console.log(JSON.stringify({ success: false, validationErrors: error.validationErrors }));
4182
+ } else {
4183
+ spinner.fail("Deployment failed");
4184
+ renderValidationErrors(error.validationErrors);
4185
+ }
4186
+ process.exit(1);
4110
4187
  } else {
4111
4188
  if (jsonMode) {
4112
4189
  console.log(JSON.stringify({ success: false, error: error instanceof Error ? error.message : String(error) }));
@@ -5776,7 +5853,8 @@ async function queryThreads(options) {
5776
5853
  environment: options.environment,
5777
5854
  ...options.agentId && { agentId: options.agentId },
5778
5855
  ...options.channel && { channel: options.channel },
5779
- ...options.limit && { limit: options.limit }
5856
+ ...options.limit && { limit: options.limit },
5857
+ ...options.organizationId && { organizationId: options.organizationId }
5780
5858
  });
5781
5859
  if (result.error || !result.data)
5782
5860
  return result;
@@ -5792,20 +5870,21 @@ async function queryThreads(options) {
5792
5870
  }
5793
5871
  return result;
5794
5872
  }
5795
- async function queryThreadDetail(threadId, messageLimit) {
5873
+ async function queryThreadDetail(threadId, messageLimit, organizationId) {
5796
5874
  return convexQuery2("threads:getWithMessages", {
5797
5875
  id: threadId,
5798
- ...messageLimit && { messageLimit }
5876
+ ...messageLimit && { messageLimit },
5877
+ ...organizationId && { organizationId }
5799
5878
  });
5800
5879
  }
5801
- async function queryThreadExecutions(threadId) {
5802
- return convexQuery2("executions:getByThread", { threadId });
5880
+ async function queryThreadExecutions(threadId, organizationId) {
5881
+ return convexQuery2("executions:getByThread", { threadId, ...organizationId && { organizationId } });
5803
5882
  }
5804
- async function resolveThreadId(shortId, environment) {
5883
+ async function resolveThreadId(shortId, environment, organizationId) {
5805
5884
  if (shortId.includes("|") || shortId.length > 20) {
5806
5885
  return { data: shortId };
5807
5886
  }
5808
- const result = await queryThreads({ environment: environment ?? "development", limit: 100 });
5887
+ const result = await queryThreads({ environment: environment ?? "development", limit: 100, organizationId });
5809
5888
  if (result.error || !result.data)
5810
5889
  return { error: result.error ?? "Could not fetch threads" };
5811
5890
  const threads = result.data;
@@ -5814,7 +5893,7 @@ async function resolveThreadId(shortId, environment) {
5814
5893
  for (const env of ["production", "development", "eval"]) {
5815
5894
  if (env === (environment ?? "development"))
5816
5895
  continue;
5817
- const envResult = await queryThreads({ environment: env, limit: 100 });
5896
+ const envResult = await queryThreads({ environment: env, limit: 100, organizationId });
5818
5897
  if (envResult.data) {
5819
5898
  const envThreads = envResult.data;
5820
5899
  const envMatch = envThreads.find((t) => t._id.endsWith(shortId));
@@ -5916,7 +5995,8 @@ logsCommand.command("list", { isDefault: true }).description("List recent conver
5916
5995
  agentId,
5917
5996
  channel: opts.channel,
5918
5997
  phone: opts.phone,
5919
- limit: parseInt(opts.limit, 10)
5998
+ limit: parseInt(opts.limit, 10),
5999
+ organizationId: orgId
5920
6000
  });
5921
6001
  if (error || !data) {
5922
6002
  spinner?.fail("Failed to fetch conversations");
@@ -5953,8 +6033,9 @@ logsCommand.command("list", { isDefault: true }).description("List recent conver
5953
6033
  logsCommand.command("view <thread-id>").description("View conversation messages").option("--env <environment>", "Environment hint for resolving short IDs").option("--exec", "Include execution details").option("--verbose", "Show full tool call arguments and results").option("--tail", "Show most recent messages (use with --limit)").option("--json", "Output raw JSON").option("--limit <n>", "Message limit", "100").action(async (rawThreadId, opts) => {
5954
6034
  await ensureAuth2();
5955
6035
  const spinner = opts.json ? null : ora12();
6036
+ const orgId = getOrgId2();
5956
6037
  spinner?.start("Resolving thread");
5957
- const resolved = await resolveThreadId(rawThreadId, opts.env);
6038
+ const resolved = await resolveThreadId(rawThreadId, opts.env, orgId);
5958
6039
  if (resolved.error || !resolved.data) {
5959
6040
  spinner?.fail("Thread not found");
5960
6041
  console.log(chalk16.red("Error:"), resolved.error || `No thread matched "${rawThreadId}"`);
@@ -5964,7 +6045,7 @@ logsCommand.command("view <thread-id>").description("View conversation messages"
5964
6045
  spinner?.stop();
5965
6046
  spinner?.start("Fetching conversation");
5966
6047
  const fetchLimit = opts.tail ? 1000 : parseInt(opts.limit, 10);
5967
- const { data, error } = await queryThreadDetail(threadId, fetchLimit);
6048
+ const { data, error } = await queryThreadDetail(threadId, fetchLimit, orgId);
5968
6049
  if (error || !data) {
5969
6050
  spinner?.fail("Failed to fetch conversation");
5970
6051
  console.log(chalk16.red("Error:"), error || "Thread not found");
@@ -5974,7 +6055,7 @@ logsCommand.command("view <thread-id>").description("View conversation messages"
5974
6055
  const result = data;
5975
6056
  let executions = [];
5976
6057
  if (opts.exec) {
5977
- const execResult = await queryThreadExecutions(threadId);
6058
+ const execResult = await queryThreadExecutions(threadId, orgId);
5978
6059
  if (execResult.data) {
5979
6060
  executions = execResult.data;
5980
6061
  }
@@ -7593,51 +7674,54 @@ async function convexMutation5(path, args) {
7593
7674
  }
7594
7675
  return json.value;
7595
7676
  }
7596
- async function listTriggers(environment) {
7597
- return convexQuery6("triggers:list", { environment });
7677
+ async function listTriggers(environment, organizationId) {
7678
+ return convexQuery6("triggers:list", { environment, ...organizationId && { organizationId } });
7598
7679
  }
7599
- async function getTrigger(slug, environment) {
7600
- return convexQuery6("triggers:getBySlug", { slug, environment });
7680
+ async function getTrigger(slug, environment, organizationId) {
7681
+ return convexQuery6("triggers:getBySlug", { slug, environment, ...organizationId && { organizationId } });
7601
7682
  }
7602
7683
  async function listTriggerRuns(options) {
7603
7684
  return convexQuery6("triggers:listRuns", {
7604
7685
  environment: options.environment,
7605
7686
  ...options.status && { status: options.status },
7606
7687
  ...options.triggerSlug && { triggerSlug: options.triggerSlug },
7607
- ...options.limit && { limit: options.limit }
7688
+ ...options.limit && { limit: options.limit },
7689
+ ...options.organizationId && { organizationId: options.organizationId }
7608
7690
  });
7609
7691
  }
7610
- async function getTriggerRunDetail(runId, environment) {
7692
+ async function getTriggerRunDetail(runId, environment, organizationId) {
7611
7693
  return convexQuery6("triggers:getRunDetail", {
7612
7694
  runId,
7613
- ...environment && { environment }
7695
+ ...environment && { environment },
7696
+ ...organizationId && { organizationId }
7614
7697
  });
7615
7698
  }
7616
- async function getTriggerRunStats(environment) {
7617
- return convexQuery6("triggers:getRunStats", { environment });
7699
+ async function getTriggerRunStats(environment, organizationId) {
7700
+ return convexQuery6("triggers:getRunStats", { environment, ...organizationId && { organizationId } });
7618
7701
  }
7619
- async function getLastRunStatuses(environment) {
7620
- return convexQuery6("triggers:getLastRunStatuses", { environment });
7702
+ async function getLastRunStatuses(environment, organizationId) {
7703
+ return convexQuery6("triggers:getLastRunStatuses", { environment, ...organizationId && { organizationId } });
7621
7704
  }
7622
- async function cancelTriggerRun(runId, environment) {
7623
- return convexMutation5("triggers:cancelRun", { runId, environment });
7705
+ async function cancelTriggerRun(runId, environment, organizationId) {
7706
+ return convexMutation5("triggers:cancelRun", { runId, environment, ...organizationId && { organizationId } });
7624
7707
  }
7625
- async function retryTriggerRun(runId, environment) {
7626
- return convexMutation5("triggers:retryRun", { runId, environment });
7708
+ async function retryTriggerRun(runId, environment, organizationId) {
7709
+ return convexMutation5("triggers:retryRun", { runId, environment, ...organizationId && { organizationId } });
7627
7710
  }
7628
- async function toggleTrigger(slug, enabled, environment) {
7711
+ async function toggleTrigger(slug, enabled, environment, organizationId) {
7629
7712
  const path = enabled ? "triggers:enable" : "triggers:disable";
7630
- return convexMutation5(path, { slug, environment });
7713
+ return convexMutation5(path, { slug, environment, ...organizationId && { organizationId } });
7631
7714
  }
7632
7715
  async function listTriggerExecutions(options) {
7633
7716
  return convexQuery6("triggers:listExecutions", {
7634
7717
  environment: options.environment,
7635
7718
  ...options.triggerSlug && { triggerSlug: options.triggerSlug },
7636
- ...options.limit && { limit: options.limit }
7719
+ ...options.limit && { limit: options.limit },
7720
+ ...options.organizationId && { organizationId: options.organizationId }
7637
7721
  });
7638
7722
  }
7639
- async function getTriggerExecutionDetail(eventId, environment) {
7640
- return convexQuery6("triggers:getExecutionDetail", { eventId, ...environment && { environment } });
7723
+ async function getTriggerExecutionDetail(eventId, environment, organizationId) {
7724
+ return convexQuery6("triggers:getExecutionDetail", { eventId, ...environment && { environment }, ...organizationId && { organizationId } });
7641
7725
  }
7642
7726
  async function convexAction3(path, args) {
7643
7727
  const token = getToken3();
@@ -7664,11 +7748,15 @@ async function convexAction3(path, args) {
7664
7748
  }
7665
7749
  return json.value;
7666
7750
  }
7667
- async function retryImmediateExecution(eventId, environment) {
7668
- return convexAction3("triggers:retryImmediateExecution", { eventId, environment });
7751
+ async function retryImmediateExecution(eventId, environment, organizationId) {
7752
+ return convexAction3("triggers:retryImmediateExecution", { eventId, environment, ...organizationId && { organizationId } });
7669
7753
  }
7670
7754
 
7671
7755
  // src/cli/commands/triggers.ts
7756
+ function getOrgId3() {
7757
+ const project = loadProject(process.cwd());
7758
+ return project?.organization.id;
7759
+ }
7672
7760
  async function withTriggerAuthRetry(fn) {
7673
7761
  try {
7674
7762
  return await fn();
@@ -7836,10 +7924,11 @@ triggersCommand.command("list", { isDefault: true }).description("List all trigg
7836
7924
  await ensureAuth5();
7837
7925
  const spinner = opts.json ? null : ora14();
7838
7926
  try {
7927
+ const orgId = getOrgId3();
7839
7928
  spinner?.start("Fetching triggers");
7840
7929
  const [triggers, statuses] = await Promise.all([
7841
- listTriggers(opts.env),
7842
- getLastRunStatuses(opts.env)
7930
+ listTriggers(opts.env, orgId),
7931
+ getLastRunStatuses(opts.env, orgId)
7843
7932
  ]);
7844
7933
  let filtered = triggers;
7845
7934
  if (opts.failed) {
@@ -7885,7 +7974,7 @@ triggersCommand.command("get <slug>").description("View trigger details").option
7885
7974
  const spinner = opts.json ? null : ora14();
7886
7975
  try {
7887
7976
  spinner?.start("Fetching trigger");
7888
- const trigger = await getTrigger(slug, opts.env);
7977
+ const trigger = await getTrigger(slug, opts.env, getOrgId3());
7889
7978
  if (!trigger) {
7890
7979
  spinner?.fail("Trigger not found");
7891
7980
  if (opts.json) {
@@ -7968,7 +8057,8 @@ triggersCommand.command("runs [slug]").description("List trigger runs").option("
7968
8057
  environment: opts.env,
7969
8058
  status: opts.status,
7970
8059
  triggerSlug: slug,
7971
- limit: parseInt(opts.limit, 10)
8060
+ limit: parseInt(opts.limit, 10),
8061
+ organizationId: getOrgId3()
7972
8062
  });
7973
8063
  spinner?.succeed(`Found ${runs.length} runs`);
7974
8064
  if (opts.json) {
@@ -8010,7 +8100,7 @@ triggersCommand.command("run <run-id>").description("View trigger run details").
8010
8100
  const spinner = opts.json ? null : ora14();
8011
8101
  try {
8012
8102
  spinner?.start("Fetching run");
8013
- const run = await getTriggerRunDetail(runId, opts.env);
8103
+ const run = await getTriggerRunDetail(runId, opts.env, getOrgId3());
8014
8104
  if (!run) {
8015
8105
  spinner?.fail("Run not found");
8016
8106
  if (opts.json) {
@@ -8054,8 +8144,9 @@ triggersCommand.command("stats").description("Show trigger run statistics").opti
8054
8144
  await ensureAuth5();
8055
8145
  const spinner = opts.json ? null : ora14();
8056
8146
  try {
8147
+ const orgId = getOrgId3();
8057
8148
  spinner?.start("Fetching statistics");
8058
- const stats = await getTriggerRunStats(opts.env);
8149
+ const stats = await getTriggerRunStats(opts.env, orgId);
8059
8150
  spinner?.succeed("Run statistics");
8060
8151
  if (opts.json) {
8061
8152
  console.log(JSON.stringify(stats, null, 2));
@@ -8080,7 +8171,7 @@ triggersCommand.command("stats").description("Show trigger run statistics").opti
8080
8171
  console.log(` ${chalk20.gray("\u2500".repeat(18))}`);
8081
8172
  console.log(` ${chalk20.bold("Total".padEnd(12))} ${chalk20.bold(String(total).padStart(6))}`);
8082
8173
  console.log();
8083
- const executions = await listTriggerExecutions({ environment: opts.env, limit: 50 });
8174
+ const executions = await listTriggerExecutions({ environment: opts.env, limit: 50, organizationId: orgId });
8084
8175
  const recentFailures = executions.filter((e) => e.eventType === "trigger.failed");
8085
8176
  const recentSuccesses = executions.length - recentFailures.length;
8086
8177
  console.log(chalk20.bold(` Recent Executions`));
@@ -8112,7 +8203,8 @@ triggersCommand.command("logs [slug]").description("View trigger execution histo
8112
8203
  const executions = await withTriggerAuthRetry(() => listTriggerExecutions({
8113
8204
  environment: opts.env,
8114
8205
  triggerSlug: slug,
8115
- limit: parseInt(opts.limit, 10)
8206
+ limit: parseInt(opts.limit, 10),
8207
+ organizationId: getOrgId3()
8116
8208
  }));
8117
8209
  spinner?.succeed(`Found ${executions.length} executions`);
8118
8210
  if (opts.json) {
@@ -8172,6 +8264,7 @@ triggersCommand.command("log <identifier>").description("View detailed trigger e
8172
8264
  await ensureAuth5();
8173
8265
  const spinner = opts.json ? null : ora14();
8174
8266
  try {
8267
+ const orgId = getOrgId3();
8175
8268
  const nth = parseInt(opts.nth, 10);
8176
8269
  if (isNaN(nth) || nth < 1) {
8177
8270
  console.error(chalk20.red("Error:"), "--nth must be a positive integer (e.g., --nth 1 for most recent)");
@@ -8184,7 +8277,8 @@ triggersCommand.command("log <identifier>").description("View detailed trigger e
8184
8277
  const executions = await withTriggerAuthRetry(() => listTriggerExecutions({
8185
8278
  environment: opts.env,
8186
8279
  triggerSlug: identifier,
8187
- limit: nth
8280
+ limit: nth,
8281
+ organizationId: orgId
8188
8282
  }));
8189
8283
  if (!executions.length) {
8190
8284
  spinner?.fail(`No executions found for trigger "${identifier}" in ${opts.env}`);
@@ -8202,7 +8296,7 @@ triggersCommand.command("log <identifier>").description("View detailed trigger e
8202
8296
  spinner?.succeed(`Found execution for "${identifier}"`);
8203
8297
  }
8204
8298
  spinner?.start("Fetching execution detail");
8205
- const event = await withTriggerAuthRetry(() => getTriggerExecutionDetail(eventId, opts.env));
8299
+ const event = await withTriggerAuthRetry(() => getTriggerExecutionDetail(eventId, opts.env, orgId));
8206
8300
  if (!event) {
8207
8301
  spinner?.fail("Execution not found");
8208
8302
  if (opts.json) {
@@ -8264,7 +8358,7 @@ triggersCommand.command("retry <run-id>").description("Retry a failed or dead ru
8264
8358
  }
8265
8359
  try {
8266
8360
  spinner?.start("Retrying run...");
8267
- await retryTriggerRun(runId, environment);
8361
+ await retryTriggerRun(runId, environment, getOrgId3());
8268
8362
  spinner?.succeed(chalk20.green(`Run ${runId} queued for retry`));
8269
8363
  if (opts.json) {
8270
8364
  console.log(JSON.stringify({ success: true, runId }));
@@ -8295,7 +8389,7 @@ triggersCommand.command("cancel <run-id>").description("Cancel a pending run").o
8295
8389
  }
8296
8390
  try {
8297
8391
  spinner?.start("Cancelling run...");
8298
- await cancelTriggerRun(runId, environment);
8392
+ await cancelTriggerRun(runId, environment, getOrgId3());
8299
8393
  spinner?.succeed(chalk20.green(`Run ${runId} cancelled`));
8300
8394
  if (opts.json) {
8301
8395
  console.log(JSON.stringify({ success: true, runId }));
@@ -8326,7 +8420,7 @@ triggersCommand.command("enable <slug>").description("Enable a trigger").option(
8326
8420
  }
8327
8421
  try {
8328
8422
  spinner?.start("Enabling trigger...");
8329
- await toggleTrigger(slug, true, environment);
8423
+ await toggleTrigger(slug, true, environment, getOrgId3());
8330
8424
  spinner?.succeed(chalk20.green(`Trigger ${slug} enabled`));
8331
8425
  if (opts.json) {
8332
8426
  console.log(JSON.stringify({ success: true, slug }));
@@ -8357,7 +8451,7 @@ triggersCommand.command("disable <slug>").description("Disable a trigger").optio
8357
8451
  }
8358
8452
  try {
8359
8453
  spinner?.start("Disabling trigger...");
8360
- await toggleTrigger(slug, false, environment);
8454
+ await toggleTrigger(slug, false, environment, getOrgId3());
8361
8455
  spinner?.succeed(chalk20.green(`Trigger ${slug} disabled`));
8362
8456
  if (opts.json) {
8363
8457
  console.log(JSON.stringify({ success: true, slug }));
@@ -8388,7 +8482,7 @@ triggersCommand.command("retry-event <event-id>").description("Retry a failed im
8388
8482
  }
8389
8483
  try {
8390
8484
  spinner?.start("Retrying failed execution...");
8391
- const result = await retryImmediateExecution(eventId, environment);
8485
+ const result = await retryImmediateExecution(eventId, environment, getOrgId3());
8392
8486
  if (result.success) {
8393
8487
  spinner?.succeed(chalk20.green(`Execution retried successfully`));
8394
8488
  } else {
@@ -8436,7 +8530,8 @@ triggersCommand.command("fire <slug>").description("Manually fire a trigger").op
8436
8530
  slug,
8437
8531
  environment,
8438
8532
  entityId: opts.entity,
8439
- data
8533
+ data,
8534
+ organizationId: getOrgId3()
8440
8535
  });
8441
8536
  if (error) {
8442
8537
  spinner?.fail("Trigger execution failed");
@@ -8594,12 +8689,14 @@ async function listThreads(options) {
8594
8689
  return convexQuery7("threads:listWithPreviews", {
8595
8690
  environment: options.environment,
8596
8691
  channel: options.channel,
8597
- limit: options.limit
8692
+ limit: options.limit,
8693
+ ...options.organizationId && { organizationId: options.organizationId }
8598
8694
  });
8599
8695
  }
8600
8696
  async function getThreadWithMessages(options) {
8601
8697
  return convexQuery7("threads:getWithMessages", {
8602
- id: options.threadId
8698
+ id: options.threadId,
8699
+ ...options.organizationId && { organizationId: options.organizationId }
8603
8700
  });
8604
8701
  }
8605
8702
  async function archiveThread(options) {
@@ -10377,8 +10474,8 @@ function checkModelConfig(resources) {
10377
10474
  hint: "Check agent model config - temperature should be 0-2"
10378
10475
  };
10379
10476
  }
10380
- async function checkStuckThreads(environment) {
10381
- const threads = await withAuthRetry2(() => listThreads({ environment, limit: 100 }));
10477
+ async function checkStuckThreads(environment, organizationId) {
10478
+ const threads = await withAuthRetry2(() => listThreads({ environment, limit: 100, organizationId }));
10382
10479
  const issues = [];
10383
10480
  const now = Date.now();
10384
10481
  const fiveMinutes = 5 * 60 * 1000;
@@ -10407,8 +10504,8 @@ async function checkStuckThreads(environment) {
10407
10504
  hint: "Run `struere threads archive <id>` to archive stuck threads"
10408
10505
  };
10409
10506
  }
10410
- async function checkTriggerHealth(environment) {
10411
- const executions = await withAuthRetry2(() => listTriggerExecutions({ environment, limit: 100 }));
10507
+ async function checkTriggerHealth(environment, organizationId) {
10508
+ const executions = await withAuthRetry2(() => listTriggerExecutions({ environment, limit: 100, organizationId }));
10412
10509
  if (executions.length === 0) {
10413
10510
  return {
10414
10511
  id: "trigger-health",
@@ -10455,8 +10552,8 @@ async function checkTriggerHealth(environment) {
10455
10552
  hint: "Run `struere triggers logs <slug>` to investigate failures"
10456
10553
  };
10457
10554
  }
10458
- async function checkSyncDrift(resources, environment) {
10459
- const { state, error } = await withAuthRetry2(() => getSyncState(undefined, environment));
10555
+ async function checkSyncDrift(resources, environment, organizationId) {
10556
+ const { state, error } = await withAuthRetry2(() => getSyncState(organizationId, environment));
10460
10557
  if (error || !state) {
10461
10558
  return {
10462
10559
  id: "sync-drift",
@@ -10565,6 +10662,8 @@ var doctorCommand = new Command25("doctor").description("Run diagnostic checks o
10565
10662
  const spinner = opts.json ? null : ora20();
10566
10663
  const cwd = process.cwd();
10567
10664
  const environment = opts.env;
10665
+ const project = loadProject(cwd);
10666
+ const organizationId = project?.organization.id;
10568
10667
  try {
10569
10668
  spinner?.start("Loading resources...");
10570
10669
  const resources = await loadAllResources(cwd);
@@ -10575,9 +10674,9 @@ var doctorCommand = new Command25("doctor").description("Run diagnostic checks o
10575
10674
  runCheck(() => checkTemplateApprovals(resources)),
10576
10675
  runCheck(() => checkEntityTypeReferences(resources)),
10577
10676
  runCheck(() => checkModelConfig(resources)),
10578
- runCheck(() => checkStuckThreads(environment)),
10579
- runCheck(() => checkTriggerHealth(environment)),
10580
- runCheck(() => checkSyncDrift(resources, environment))
10677
+ runCheck(() => checkStuckThreads(environment, organizationId)),
10678
+ runCheck(() => checkTriggerHealth(environment, organizationId)),
10679
+ runCheck(() => checkSyncDrift(resources, environment, organizationId))
10581
10680
  ]);
10582
10681
  spinner?.stop();
10583
10682
  const checks = results.map((r) => r.status === "fulfilled" ? r.value : { id: "unknown", label: "Unknown", status: "warn", message: `Check failed: ${r.reason}` });
@@ -10631,10 +10730,332 @@ var doctorCommand = new Command25("doctor").description("Run diagnostic checks o
10631
10730
  process.exit(1);
10632
10731
  }
10633
10732
  });
10733
+
10734
+ // src/cli/commands/keys.ts
10735
+ init_credentials();
10736
+ import { Command as Command26 } from "commander";
10737
+ import chalk29 from "chalk";
10738
+ import ora21 from "ora";
10739
+ import { input as input3, confirm as confirm8 } from "@inquirer/prompts";
10740
+ init_convex();
10741
+
10742
+ // src/cli/utils/apiKeys.ts
10743
+ init_credentials();
10744
+ init_config();
10745
+ function getToken5() {
10746
+ const credentials = loadCredentials();
10747
+ const apiKey = getApiKey();
10748
+ const token = apiKey || credentials?.token;
10749
+ if (!token)
10750
+ throw new Error("Not authenticated");
10751
+ return token;
10752
+ }
10753
+ async function convexQuery8(path, args) {
10754
+ const token = getToken5();
10755
+ const response = await fetch(`${CONVEX_URL}/api/query`, {
10756
+ method: "POST",
10757
+ headers: {
10758
+ "Content-Type": "application/json",
10759
+ Authorization: `Bearer ${token}`
10760
+ },
10761
+ body: JSON.stringify({ path, args })
10762
+ });
10763
+ const text = await response.text();
10764
+ let json;
10765
+ try {
10766
+ json = JSON.parse(text);
10767
+ } catch {
10768
+ throw new Error(text || `HTTP ${response.status}`);
10769
+ }
10770
+ if (!response.ok) {
10771
+ throw new Error(json.errorData?.message || json.errorMessage || text);
10772
+ }
10773
+ if (json.status === "error") {
10774
+ throw new Error(json.errorMessage || "Unknown error from Convex");
10775
+ }
10776
+ return json.value;
10777
+ }
10778
+ async function convexMutation6(path, args) {
10779
+ const token = getToken5();
10780
+ const response = await fetch(`${CONVEX_URL}/api/mutation`, {
10781
+ method: "POST",
10782
+ headers: {
10783
+ "Content-Type": "application/json",
10784
+ Authorization: `Bearer ${token}`
10785
+ },
10786
+ body: JSON.stringify({ path, args })
10787
+ });
10788
+ const text = await response.text();
10789
+ let json;
10790
+ try {
10791
+ json = JSON.parse(text);
10792
+ } catch {
10793
+ throw new Error(text || `HTTP ${response.status}`);
10794
+ }
10795
+ if (!response.ok) {
10796
+ throw new Error(json.errorData?.message || json.errorMessage || text);
10797
+ }
10798
+ if (json.status === "error") {
10799
+ throw new Error(json.errorMessage || "Unknown error from Convex");
10800
+ }
10801
+ return json.value;
10802
+ }
10803
+ async function listApiKeys() {
10804
+ return convexQuery8("apiKeys:list", {});
10805
+ }
10806
+ async function createApiKey(args) {
10807
+ return convexMutation6("apiKeys:create", {
10808
+ name: args.name,
10809
+ environment: args.environment,
10810
+ permissions: args.permissions ?? ["*"]
10811
+ });
10812
+ }
10813
+ async function removeApiKey(id) {
10814
+ return convexMutation6("apiKeys:remove", { id });
10815
+ }
10816
+
10817
+ // src/cli/commands/keys.ts
10818
+ async function withKeyAuthRetry(fn) {
10819
+ try {
10820
+ return await fn();
10821
+ } catch (err) {
10822
+ const msg = err instanceof Error ? err.message : String(err);
10823
+ if (msg.includes("Unauthenticated") || msg.includes("OIDC") || msg.includes("token") || msg.includes("expired")) {
10824
+ const refreshed = await refreshToken();
10825
+ if (!refreshed)
10826
+ throw err;
10827
+ return fn();
10828
+ }
10829
+ throw err;
10830
+ }
10831
+ }
10832
+ async function ensureAuth9() {
10833
+ const cwd = process.cwd();
10834
+ const nonInteractive = !isInteractive();
10835
+ if (!hasProject(cwd)) {
10836
+ if (nonInteractive) {
10837
+ console.error(chalk29.red("No struere.json found. Run struere init first."));
10838
+ process.exit(1);
10839
+ }
10840
+ console.log(chalk29.yellow("No struere.json found - initializing project..."));
10841
+ console.log();
10842
+ const success = await runInit(cwd);
10843
+ if (!success) {
10844
+ process.exit(1);
10845
+ }
10846
+ console.log();
10847
+ }
10848
+ let credentials = loadCredentials();
10849
+ const apiKey = getApiKey();
10850
+ if (!credentials && !apiKey) {
10851
+ if (nonInteractive) {
10852
+ console.error(chalk29.red("Not authenticated. Set STRUERE_API_KEY or run struere login."));
10853
+ process.exit(1);
10854
+ }
10855
+ console.log(chalk29.yellow("Not logged in - authenticating..."));
10856
+ console.log();
10857
+ credentials = await performLogin();
10858
+ if (!credentials) {
10859
+ console.log(chalk29.red("Authentication failed"));
10860
+ process.exit(1);
10861
+ }
10862
+ console.log();
10863
+ }
10864
+ return true;
10865
+ }
10866
+ function relativeTime4(ts) {
10867
+ const diff = Date.now() - ts;
10868
+ const seconds = Math.floor(diff / 1000);
10869
+ if (seconds < 60)
10870
+ return `${seconds}s ago`;
10871
+ const minutes = Math.floor(seconds / 60);
10872
+ if (minutes < 60)
10873
+ return `${minutes}m ago`;
10874
+ const hours = Math.floor(minutes / 60);
10875
+ if (hours < 24)
10876
+ return `${hours}h ago`;
10877
+ const days = Math.floor(hours / 24);
10878
+ return `${days}d ago`;
10879
+ }
10880
+ function maskedPrefix(prefix) {
10881
+ return `${prefix}****`;
10882
+ }
10883
+ function isValidEnvironment(value) {
10884
+ return value === "development" || value === "production" || value === "eval";
10885
+ }
10886
+ var keysCommand = new Command26("keys").description("Manage API keys");
10887
+ keysCommand.command("list", { isDefault: true }).description("List API keys").option("--env <environment>", "Filter by environment (development|production|eval)").option("--json", "Output raw JSON").action(async (opts) => {
10888
+ await ensureAuth9();
10889
+ const spinner = opts.json ? null : ora21();
10890
+ try {
10891
+ spinner?.start("Fetching API keys");
10892
+ let keys = await withKeyAuthRetry(() => listApiKeys());
10893
+ if (opts.env) {
10894
+ if (!isValidEnvironment(opts.env)) {
10895
+ spinner?.fail(`Invalid environment: ${opts.env}`);
10896
+ process.exit(1);
10897
+ }
10898
+ keys = keys.filter((k) => k.environment === opts.env);
10899
+ }
10900
+ spinner?.succeed(`Found ${keys.length} API key${keys.length === 1 ? "" : "s"}${opts.env ? ` (${opts.env})` : ""}`);
10901
+ if (opts.json) {
10902
+ console.log(JSON.stringify(keys, null, 2));
10903
+ return;
10904
+ }
10905
+ console.log();
10906
+ renderTable([
10907
+ { key: "id", label: "ID", width: 14 },
10908
+ { key: "name", label: "Name", width: 24 },
10909
+ { key: "prefix", label: "Prefix", width: 22 },
10910
+ { key: "environment", label: "Env", width: 12 },
10911
+ { key: "created", label: "Created", width: 12 },
10912
+ { key: "lastUsed", label: "Last Used", width: 12 }
10913
+ ], keys.map((k) => ({
10914
+ id: k.id.slice(-12),
10915
+ name: k.name,
10916
+ prefix: maskedPrefix(k.keyPrefix),
10917
+ environment: k.environment,
10918
+ created: relativeTime4(k.createdAt),
10919
+ lastUsed: k.lastUsedAt ? relativeTime4(k.lastUsedAt) : chalk29.gray("-")
10920
+ })));
10921
+ console.log();
10922
+ } catch (err) {
10923
+ const message = err instanceof Error ? err.message : String(err);
10924
+ spinner?.fail("Failed to fetch API keys");
10925
+ if (opts.json) {
10926
+ console.log(JSON.stringify({ success: false, error: message }));
10927
+ } else {
10928
+ console.log(chalk29.red("Error:"), message);
10929
+ }
10930
+ process.exit(1);
10931
+ }
10932
+ });
10933
+ keysCommand.command("create").description("Create a new API key").option("--name <name>", "Key name").option("--env <environment>", "Environment (development|production|eval)", "development").option("--json", "Output raw JSON").option("--confirm", "Skip production confirmation").action(async (opts) => {
10934
+ await ensureAuth9();
10935
+ if (!isValidEnvironment(opts.env)) {
10936
+ const message = `Invalid environment: ${opts.env}`;
10937
+ if (opts.json) {
10938
+ console.log(JSON.stringify({ success: false, error: message }));
10939
+ } else {
10940
+ console.log(chalk29.red("Error:"), message);
10941
+ }
10942
+ process.exit(1);
10943
+ }
10944
+ const environment = opts.env;
10945
+ let name = opts.name;
10946
+ if (!name || !name.trim()) {
10947
+ if (!isInteractive()) {
10948
+ const message = "--name is required in non-interactive mode";
10949
+ if (opts.json) {
10950
+ console.log(JSON.stringify({ success: false, error: message }));
10951
+ } else {
10952
+ console.log(chalk29.red("Error:"), message);
10953
+ }
10954
+ process.exit(1);
10955
+ }
10956
+ name = await input3({
10957
+ message: "API key name:",
10958
+ validate: (v) => v.trim().length > 0 || "Name is required"
10959
+ });
10960
+ }
10961
+ name = name.trim();
10962
+ if (environment === "production" && !opts.confirm && !opts.json && isInteractive()) {
10963
+ const ok = await confirm8({
10964
+ message: chalk29.yellow("Create API key in PRODUCTION environment?"),
10965
+ default: false
10966
+ });
10967
+ if (!ok) {
10968
+ console.log(chalk29.gray("Cancelled"));
10969
+ process.exit(0);
10970
+ }
10971
+ }
10972
+ const spinner = opts.json ? null : ora21();
10973
+ try {
10974
+ spinner?.start("Creating API key");
10975
+ const result = await withKeyAuthRetry(() => createApiKey({ name, environment }));
10976
+ spinner?.succeed(chalk29.green(`Created API key ${chalk29.cyan(result.name)}`));
10977
+ if (opts.json) {
10978
+ console.log(JSON.stringify({
10979
+ id: result.id,
10980
+ name: result.name,
10981
+ prefix: result.keyPrefix,
10982
+ key: result.key,
10983
+ environment,
10984
+ createdAt: result.createdAt
10985
+ }, null, 2));
10986
+ return;
10987
+ }
10988
+ console.log();
10989
+ console.log(chalk29.bold(" " + chalk29.yellow("Save this key now \u2014 it will not be shown again.")));
10990
+ console.log();
10991
+ console.log(` ${chalk29.gray("Key:")} ${chalk29.cyan(result.key)}`);
10992
+ console.log(` ${chalk29.gray("Name:")} ${result.name}`);
10993
+ console.log(` ${chalk29.gray("Prefix:")} ${result.keyPrefix}`);
10994
+ console.log(` ${chalk29.gray("Environment:")} ${environment}`);
10995
+ console.log(` ${chalk29.gray("ID:")} ${result.id}`);
10996
+ console.log();
10997
+ } catch (err) {
10998
+ const message = err instanceof Error ? err.message : String(err);
10999
+ spinner?.fail("Failed to create API key");
11000
+ if (opts.json) {
11001
+ console.log(JSON.stringify({ success: false, error: message }));
11002
+ } else {
11003
+ console.log(chalk29.red("Error:"), message);
11004
+ }
11005
+ process.exit(1);
11006
+ }
11007
+ });
11008
+ keysCommand.command("revoke <id-or-prefix>").description("Revoke an API key (delete)").option("--confirm", "Skip confirmation prompt").option("--json", "Output raw JSON").action(async (idOrPrefix, opts) => {
11009
+ await ensureAuth9();
11010
+ const spinner = opts.json ? null : ora21();
11011
+ try {
11012
+ spinner?.start("Looking up API key");
11013
+ const keys = await withKeyAuthRetry(() => listApiKeys());
11014
+ const target = keys.find((k) => k.id === idOrPrefix) ?? keys.find((k) => k.id.endsWith(idOrPrefix)) ?? keys.find((k) => k.keyPrefix === idOrPrefix) ?? keys.find((k) => k.keyPrefix.startsWith(idOrPrefix));
11015
+ if (!target) {
11016
+ spinner?.fail(`API key not found: ${idOrPrefix}`);
11017
+ if (opts.json) {
11018
+ console.log(JSON.stringify({ success: false, error: "API key not found" }));
11019
+ }
11020
+ process.exit(1);
11021
+ }
11022
+ spinner?.succeed(`Found ${chalk29.cyan(target.name)} (${maskedPrefix(target.keyPrefix)}, ${target.environment})`);
11023
+ if (!opts.confirm && !opts.json) {
11024
+ if (!isInteractive()) {
11025
+ console.log(chalk29.red("Error:"), "Use --confirm to revoke in non-interactive mode");
11026
+ process.exit(1);
11027
+ }
11028
+ const ok = await confirm8({
11029
+ message: `Revoke this key? This cannot be undone.`,
11030
+ default: false
11031
+ });
11032
+ if (!ok) {
11033
+ console.log(chalk29.gray("Cancelled"));
11034
+ process.exit(0);
11035
+ }
11036
+ }
11037
+ const revokeSpinner = opts.json ? null : ora21();
11038
+ revokeSpinner?.start("Revoking API key");
11039
+ await withKeyAuthRetry(() => removeApiKey(target.id));
11040
+ revokeSpinner?.succeed(chalk29.green(`Revoked ${chalk29.cyan(target.name)}`));
11041
+ if (opts.json) {
11042
+ console.log(JSON.stringify({ success: true, id: target.id, name: target.name }));
11043
+ }
11044
+ } catch (err) {
11045
+ const message = err instanceof Error ? err.message : String(err);
11046
+ spinner?.fail("Failed to revoke API key");
11047
+ if (opts.json) {
11048
+ console.log(JSON.stringify({ success: false, error: message }));
11049
+ } else {
11050
+ console.log(chalk29.red("Error:"), message);
11051
+ }
11052
+ process.exit(1);
11053
+ }
11054
+ });
10634
11055
  // package.json
10635
11056
  var package_default = {
10636
11057
  name: "struere",
10637
- version: "0.14.1",
11058
+ version: "0.14.3",
10638
11059
  description: "Build, test, and deploy AI agents",
10639
11060
  keywords: [
10640
11061
  "ai",
@@ -10669,13 +11090,17 @@ var package_default = {
10669
11090
  ".": {
10670
11091
  import: "./dist/index.js",
10671
11092
  types: "./dist/index.d.ts"
11093
+ },
11094
+ "./client": {
11095
+ import: "./dist/client/index.js",
11096
+ types: "./dist/client/index.d.ts"
10672
11097
  }
10673
11098
  },
10674
11099
  files: [
10675
11100
  "dist"
10676
11101
  ],
10677
11102
  scripts: {
10678
- build: "bun build ./src/cli/index.ts --outdir ./dist/cli --target bun --external commander --external chalk --external ora --external chokidar --external yaml --external @inquirer/prompts && bun build ./src/index.ts --outdir ./dist --target node && bun build ./src/bin/struere.ts --outdir ./dist/bin --target bun --external commander --external chalk --external ora --external chokidar --external yaml --external @inquirer/prompts && tsc --emitDeclarationOnly && chmod +x ./dist/bin/struere.js",
11103
+ build: "bun build ./src/cli/index.ts --outdir ./dist/cli --target bun --external commander --external chalk --external ora --external chokidar --external yaml --external @inquirer/prompts && bun build ./src/index.ts --outdir ./dist --target node && bun build ./src/client/index.ts --outdir ./dist/client --target browser && bun build ./src/bin/struere.ts --outdir ./dist/bin --target bun --external commander --external chalk --external ora --external chokidar --external yaml --external @inquirer/prompts && tsc --emitDeclarationOnly && chmod +x ./dist/bin/struere.js",
10679
11104
  dev: "tsc --watch",
10680
11105
  test: "bun test",
10681
11106
  prepublishOnly: "bun run build"
@@ -10759,4 +11184,5 @@ program.addCommand(chatCommand);
10759
11184
  program.addCommand(whatsappCommand);
10760
11185
  program.addCommand(diffCommand);
10761
11186
  program.addCommand(doctorCommand);
11187
+ program.addCommand(keysCommand);
10762
11188
  program.parse();