struere 0.9.7 → 0.9.9

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 (39) hide show
  1. package/dist/bin/struere.js +235 -103
  2. package/dist/cli/commands/dev.d.ts.map +1 -1
  3. package/dist/cli/commands/init.d.ts.map +1 -1
  4. package/dist/cli/commands/org.d.ts +5 -0
  5. package/dist/cli/commands/org.d.ts.map +1 -0
  6. package/dist/cli/index.js +675 -539
  7. package/dist/cli/utils/__tests__/plugin.test.d.ts +2 -0
  8. package/dist/cli/utils/__tests__/plugin.test.d.ts.map +1 -0
  9. package/dist/cli/utils/config.d.ts +2 -2
  10. package/dist/cli/utils/config.d.ts.map +1 -1
  11. package/dist/cli/utils/convex.d.ts +6 -1
  12. package/dist/cli/utils/convex.d.ts.map +1 -1
  13. package/dist/cli/utils/entities.d.ts.map +1 -1
  14. package/dist/cli/utils/evals.d.ts.map +1 -1
  15. package/dist/cli/utils/extractor.d.ts +1 -0
  16. package/dist/cli/utils/extractor.d.ts.map +1 -1
  17. package/dist/cli/utils/integrations.d.ts.map +1 -1
  18. package/dist/cli/utils/plugin.d.ts +1 -1
  19. package/dist/cli/utils/plugin.d.ts.map +1 -1
  20. package/dist/cli/utils/whatsapp.d.ts +4 -4
  21. package/dist/cli/utils/whatsapp.d.ts.map +1 -1
  22. package/dist/define/__tests__/agent.test.d.ts +2 -0
  23. package/dist/define/__tests__/agent.test.d.ts.map +1 -0
  24. package/dist/define/__tests__/entityType.test.d.ts +2 -0
  25. package/dist/define/__tests__/entityType.test.d.ts.map +1 -0
  26. package/dist/define/__tests__/role.test.d.ts +2 -0
  27. package/dist/define/__tests__/role.test.d.ts.map +1 -0
  28. package/dist/define/__tests__/trigger.test.d.ts +2 -0
  29. package/dist/define/__tests__/trigger.test.d.ts.map +1 -0
  30. package/dist/define/index.d.ts +0 -1
  31. package/dist/define/index.d.ts.map +1 -1
  32. package/dist/define/tools.d.ts +1 -0
  33. package/dist/define/tools.d.ts.map +1 -1
  34. package/dist/index.d.ts +1 -2
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +4 -29
  37. package/dist/types.d.ts +56 -21
  38. package/dist/types.d.ts.map +1 -1
  39. package/package.json +1 -1
@@ -19463,11 +19463,13 @@ function getApiKey() {
19463
19463
  return process.env.STRUERE_API_KEY || null;
19464
19464
  }
19465
19465
 
19466
- // src/cli/utils/convex.ts
19466
+ // src/cli/utils/config.ts
19467
19467
  var CONVEX_URL = process.env.STRUERE_CONVEX_URL || "https://rapid-wildebeest-172.convex.cloud";
19468
19468
  function getSiteUrl() {
19469
19469
  return CONVEX_URL.replace(".cloud", ".site");
19470
19470
  }
19471
+
19472
+ // src/cli/utils/convex.ts
19471
19473
  async function refreshToken() {
19472
19474
  const credentials = loadCredentials();
19473
19475
  if (!credentials?.sessionId)
@@ -19492,6 +19494,38 @@ async function refreshToken() {
19492
19494
  return null;
19493
19495
  }
19494
19496
  }
19497
+ async function createOrganization(token, name, slug) {
19498
+ const response = await fetch(`${CONVEX_URL}/api/action`, {
19499
+ method: "POST",
19500
+ headers: {
19501
+ "Content-Type": "application/json",
19502
+ Authorization: `Bearer ${token}`
19503
+ },
19504
+ body: JSON.stringify({
19505
+ path: "organizations:createFromCli",
19506
+ args: { name, slug }
19507
+ }),
19508
+ signal: AbortSignal.timeout(30000)
19509
+ });
19510
+ const text = await response.text();
19511
+ let json;
19512
+ try {
19513
+ json = JSON.parse(text);
19514
+ } catch {
19515
+ return { error: text || `HTTP ${response.status}` };
19516
+ }
19517
+ if (!response.ok) {
19518
+ const msg = json.errorData?.message || json.errorMessage || text;
19519
+ return { error: msg };
19520
+ }
19521
+ if (json.status === "success" && json.value) {
19522
+ return { organization: json.value };
19523
+ }
19524
+ if (json.status === "error") {
19525
+ return { error: json.errorData?.message || json.errorMessage || "Unknown error" };
19526
+ }
19527
+ return { error: `Unexpected response: ${text}` };
19528
+ }
19495
19529
  async function listMyOrganizations(token) {
19496
19530
  const response = await fetch(`${CONVEX_URL}/api/query`, {
19497
19531
  method: "POST",
@@ -19980,7 +20014,7 @@ async function browserLoginInternal(spinner) {
19980
20014
  if (organizations.length > 0) {
19981
20015
  console.log(source_default.gray("Organizations:"), organizations.map((o) => o.name).join(", "));
19982
20016
  } else {
19983
- console.log(source_default.yellow("No organizations found. Create one in the dashboard first."));
20017
+ console.log(source_default.yellow("No organizations found. Run"), source_default.cyan("struere org create"), source_default.yellow("to create one."));
19984
20018
  }
19985
20019
  console.log();
19986
20020
  return credentials;
@@ -20292,7 +20326,7 @@ export default defineTools([
20292
20326
  },
20293
20327
  },
20294
20328
  },
20295
- handler: async (args, context, fetch) => {
20329
+ handler: async (args, context, struere, fetch) => {
20296
20330
  const timezone = (args.timezone as string) || 'UTC'
20297
20331
  const now = new Date()
20298
20332
  return {
@@ -20321,7 +20355,7 @@ export default defineTools([
20321
20355
  },
20322
20356
  required: ['message'],
20323
20357
  },
20324
- handler: async (args, context, fetch) => {
20358
+ handler: async (args, context, struere, fetch) => {
20325
20359
  const webhookUrl = process.env.SLACK_WEBHOOK_URL
20326
20360
  if (!webhookUrl) {
20327
20361
  return { success: false, error: 'SLACK_WEBHOOK_URL not configured' }
@@ -20662,6 +20696,15 @@ function defineTrigger(config) {
20662
20696
  if (!action.tool) throw new Error('Trigger action tool is required')
20663
20697
  if (!action.args || typeof action.args !== 'object') throw new Error('Trigger action args must be an object')
20664
20698
  }
20699
+ if (config.schedule) {
20700
+ if (config.schedule.delay !== undefined && config.schedule.at !== undefined) throw new Error('Trigger schedule cannot have both "delay" and "at"')
20701
+ if (config.schedule.delay !== undefined && typeof config.schedule.delay !== 'number') throw new Error('Trigger schedule.delay must be a number')
20702
+ if (config.schedule.at !== undefined && typeof config.schedule.at !== 'string') throw new Error('Trigger schedule.at must be a string')
20703
+ }
20704
+ if (config.retry) {
20705
+ if (config.retry.maxAttempts !== undefined && (typeof config.retry.maxAttempts !== 'number' || config.retry.maxAttempts < 1)) throw new Error('Trigger retry.maxAttempts must be a positive number')
20706
+ if (config.retry.backoffMs !== undefined && (typeof config.retry.backoffMs !== 'number' || config.retry.backoffMs < 0)) throw new Error('Trigger retry.backoffMs must be a non-negative number')
20707
+ }
20665
20708
  return config
20666
20709
  }
20667
20710
 
@@ -20692,24 +20735,7 @@ function defineTools(tools) {
20692
20735
  })
20693
20736
  }
20694
20737
 
20695
- function defineConfig(config) {
20696
- const defaultConfig = {
20697
- port: 3000,
20698
- host: 'localhost',
20699
- cors: { origins: ['http://localhost:3000'], credentials: true },
20700
- logging: { level: 'info', format: 'pretty' },
20701
- auth: { type: 'none' },
20702
- }
20703
- return {
20704
- ...defaultConfig,
20705
- ...config,
20706
- cors: config.cors ? { ...defaultConfig.cors, ...config.cors } : defaultConfig.cors,
20707
- logging: config.logging ? { ...defaultConfig.logging, ...config.logging } : defaultConfig.logging,
20708
- auth: config.auth ? { ...defaultConfig.auth, ...config.auth } : defaultConfig.auth,
20709
- }
20710
- }
20711
-
20712
- export { defineAgent, defineRole, defineData, defineTrigger, defineTools, defineConfig }
20738
+ export { defineAgent, defineRole, defineData, defineTrigger, defineTools }
20713
20739
  `;
20714
20740
  function registerStruerePlugin() {
20715
20741
  if (registered)
@@ -20755,11 +20781,6 @@ var TYPE_DECLARATIONS = `declare module 'struere' {
20755
20781
  export interface ToolContext {
20756
20782
  conversationId: string
20757
20783
  userId?: string
20758
- state: {
20759
- get<T>(key: string): Promise<T | undefined>
20760
- set<T>(key: string, value: T): Promise<void>
20761
- delete(key: string): Promise<void>
20762
- }
20763
20784
  }
20764
20785
 
20765
20786
  export type ToolHandler = (params: Record<string, unknown>, context: ToolContext) => Promise<unknown>
@@ -20788,6 +20809,12 @@ var TYPE_DECLARATIONS = `declare module 'struere' {
20788
20809
  model?: ModelConfig
20789
20810
  tools?: string[]
20790
20811
  firstMessageSuggestions?: string[]
20812
+ threadContextParams?: Array<{
20813
+ name: string
20814
+ type: 'string' | 'number' | 'boolean'
20815
+ required?: boolean
20816
+ description?: string
20817
+ }>
20791
20818
  }
20792
20819
 
20793
20820
  export interface JSONSchemaProperty {
@@ -20824,13 +20851,12 @@ var TYPE_DECLARATIONS = `declare module 'struere' {
20824
20851
  resource: string
20825
20852
  actions: string[]
20826
20853
  effect: 'allow' | 'deny'
20827
- priority?: number
20828
20854
  }
20829
20855
 
20830
20856
  export interface ScopeRuleConfig {
20831
20857
  entityType: string
20832
20858
  field: string
20833
- operator: 'eq' | 'ne' | 'in' | 'contains'
20859
+ operator: 'eq' | 'neq' | 'in' | 'contains'
20834
20860
  value: string
20835
20861
  }
20836
20862
 
@@ -20865,22 +20891,15 @@ var TYPE_DECLARATIONS = `declare module 'struere' {
20865
20891
  condition?: Record<string, unknown>
20866
20892
  }
20867
20893
  actions: TriggerAction[]
20868
- }
20869
-
20870
- export interface FrameworkConfig {
20871
- port?: number
20872
- host?: string
20873
- cors?: {
20874
- origins: string[]
20875
- credentials?: boolean
20876
- }
20877
- logging?: {
20878
- level: 'debug' | 'info' | 'warn' | 'error'
20879
- format?: 'json' | 'pretty'
20894
+ schedule?: {
20895
+ delay?: number
20896
+ at?: string
20897
+ offset?: number
20898
+ cancelPrevious?: boolean
20880
20899
  }
20881
- auth?: {
20882
- type: 'none' | 'api-key' | 'jwt' | 'custom'
20883
- validate?: (token: string) => Promise<boolean>
20900
+ retry?: {
20901
+ maxAttempts?: number
20902
+ backoffMs?: number
20884
20903
  }
20885
20904
  }
20886
20905
 
@@ -20889,7 +20908,6 @@ var TYPE_DECLARATIONS = `declare module 'struere' {
20889
20908
  export function defineData(config: EntityTypeConfig): EntityTypeConfig
20890
20909
  export function defineTrigger(config: TriggerConfig): TriggerConfig
20891
20910
  export function defineTools(tools: ToolDefinition[]): ToolReference[]
20892
- export function defineConfig(config?: Partial<FrameworkConfig>): FrameworkConfig
20893
20911
  }
20894
20912
  `;
20895
20913
  function generateTypeDeclarations(cwd) {
@@ -21445,6 +21463,112 @@ function isOrgAccessError(error) {
21445
21463
  return message.includes("Access denied") || message.includes("not a member") || message.includes("Organization not found");
21446
21464
  }
21447
21465
 
21466
+ // src/cli/commands/org.ts
21467
+ async function promptCreateOrg(token) {
21468
+ if (!isInteractive2()) {
21469
+ console.log(source_default.red("No organizations found. Run struere org create to create one."));
21470
+ return null;
21471
+ }
21472
+ const shouldCreate = await esm_default2({
21473
+ message: "No organizations found. Create one now?",
21474
+ default: true
21475
+ });
21476
+ if (!shouldCreate)
21477
+ return null;
21478
+ const name = await esm_default3({
21479
+ message: "Organization name:",
21480
+ validate: (v) => v.trim().length > 0 || "Name is required"
21481
+ });
21482
+ const slug = slugify(name.trim());
21483
+ const spinner = ora();
21484
+ spinner.start("Creating organization");
21485
+ const { organization, error } = await createOrganization(token, name.trim(), slug);
21486
+ if (error || !organization) {
21487
+ spinner.fail("Failed to create organization");
21488
+ console.log(source_default.red(error || "Unknown error"));
21489
+ return null;
21490
+ }
21491
+ spinner.succeed(`Created organization ${source_default.cyan(organization.name)} (${organization.slug})`);
21492
+ return organization;
21493
+ }
21494
+ var orgCommand = new Command("org").description("Manage organizations");
21495
+ orgCommand.command("list").description("List your organizations").option("--json", "Output as JSON").action(async (options) => {
21496
+ const credentials = loadCredentials();
21497
+ if (!credentials) {
21498
+ console.log(source_default.red("Not authenticated. Run struere login first."));
21499
+ process.exit(1);
21500
+ }
21501
+ await refreshToken();
21502
+ const fresh = loadCredentials();
21503
+ const token = fresh?.token || credentials.token;
21504
+ const spinner = ora();
21505
+ spinner.start("Fetching organizations");
21506
+ const { organizations, error } = await listMyOrganizations(token);
21507
+ if (error) {
21508
+ spinner.fail("Failed to fetch organizations");
21509
+ console.log(source_default.red(error));
21510
+ process.exit(1);
21511
+ }
21512
+ spinner.stop();
21513
+ if (options.json) {
21514
+ console.log(JSON.stringify(organizations, null, 2));
21515
+ return;
21516
+ }
21517
+ if (organizations.length === 0) {
21518
+ console.log(source_default.yellow("No organizations found."));
21519
+ console.log(source_default.gray("Run"), source_default.cyan("struere org create"), source_default.gray("to create one."));
21520
+ return;
21521
+ }
21522
+ console.log();
21523
+ console.log(source_default.bold("Organizations"));
21524
+ console.log();
21525
+ for (const org of organizations) {
21526
+ console.log(` ${source_default.cyan(org.name)} ${source_default.gray(`(${org.slug})`)} ${source_default.gray(`- ${org.role}`)}`);
21527
+ }
21528
+ console.log();
21529
+ });
21530
+ orgCommand.command("create").argument("[name]", "Organization name").description("Create a new organization").option("--slug <slug>", "Custom slug").option("--json", "Output as JSON").action(async (nameArg, options) => {
21531
+ const credentials = loadCredentials();
21532
+ if (!credentials) {
21533
+ console.log(source_default.red("Not authenticated. Run struere login first."));
21534
+ process.exit(1);
21535
+ }
21536
+ await refreshToken();
21537
+ const fresh = loadCredentials();
21538
+ const token = fresh?.token || credentials.token;
21539
+ let name = nameArg;
21540
+ if (!name) {
21541
+ if (!isInteractive2()) {
21542
+ console.log(source_default.red("Organization name is required in non-interactive mode."));
21543
+ process.exit(1);
21544
+ }
21545
+ name = await esm_default3({
21546
+ message: "Organization name:",
21547
+ validate: (v) => v.trim().length > 0 || "Name is required"
21548
+ });
21549
+ }
21550
+ name = name.trim();
21551
+ const slug = options.slug || slugify(name);
21552
+ const spinner = ora();
21553
+ spinner.start("Creating organization");
21554
+ const { organization, error } = await createOrganization(token, name, slug);
21555
+ if (error || !organization) {
21556
+ spinner.fail("Failed to create organization");
21557
+ console.log(source_default.red(error || "Unknown error"));
21558
+ process.exit(1);
21559
+ }
21560
+ spinner.stop();
21561
+ if (options.json) {
21562
+ console.log(JSON.stringify(organization, null, 2));
21563
+ return;
21564
+ }
21565
+ console.log(source_default.green("\u2713"), `Created organization ${source_default.cyan(organization.name)} (${organization.slug})`);
21566
+ console.log();
21567
+ console.log(source_default.gray("Next steps:"));
21568
+ console.log(source_default.gray(" \u2022"), source_default.cyan("struere init"), source_default.gray("- Initialize a project"));
21569
+ console.log();
21570
+ });
21571
+
21448
21572
  // src/cli/commands/init.ts
21449
21573
  async function runInit(cwd, selectedOrg) {
21450
21574
  const spinner = ora();
@@ -21473,10 +21597,11 @@ async function runInit(cwd, selectedOrg) {
21473
21597
  return false;
21474
21598
  }
21475
21599
  if (organizations.length === 0) {
21476
- console.log(source_default.red("No organizations found. Please create one in the dashboard first."));
21477
- return false;
21478
- }
21479
- if (organizations.length === 1) {
21600
+ const created = await promptCreateOrg(credentials.token);
21601
+ if (!created)
21602
+ return false;
21603
+ org = created;
21604
+ } else if (organizations.length === 1) {
21480
21605
  org = organizations[0];
21481
21606
  } else {
21482
21607
  org = await esm_default4({
@@ -21554,12 +21679,17 @@ var initCommand = new Command("init").description("Initialize a new Struere orga
21554
21679
  console.log(source_default.red("Failed to fetch organizations:"), error);
21555
21680
  process.exit(1);
21556
21681
  }
21557
- if (organizations.length === 0) {
21558
- console.log(source_default.red("No organizations found. Please create one in the dashboard first."));
21559
- process.exit(1);
21560
- }
21561
21682
  let selectedOrg;
21562
- if (options.org) {
21683
+ if (organizations.length === 0) {
21684
+ if (nonInteractive) {
21685
+ console.log(source_default.red("No organizations found. Run struere org create to create one."));
21686
+ process.exit(1);
21687
+ }
21688
+ const created = await promptCreateOrg(credentials?.token || "");
21689
+ if (!created)
21690
+ process.exit(1);
21691
+ selectedOrg = created;
21692
+ } else if (options.org) {
21563
21693
  const found = organizations.find((o) => o.slug === options.org);
21564
21694
  if (!found) {
21565
21695
  console.log(source_default.red(`Organization "${options.org}" not found.`));
@@ -21797,7 +21927,8 @@ function extractAgentPayload(agent, customToolsMap) {
21797
21927
  name: customTool.name,
21798
21928
  description: customTool.description,
21799
21929
  parameters: customTool.parameters || { type: "object", properties: {} },
21800
- handlerCode: extractHandlerCode(customTool._originalHandler || customTool.handler)
21930
+ handlerCode: extractHandlerCode(customTool._originalHandler || customTool.handler),
21931
+ ...customTool.templateOnly && { templateOnly: true }
21801
21932
  };
21802
21933
  });
21803
21934
  return {
@@ -22658,9 +22789,15 @@ var devCommand = new Command("dev").description("Watch files and sync to develop
22658
22789
  persistent: true,
22659
22790
  usePolling: false
22660
22791
  });
22661
- const handleFileChange = async (path, action) => {
22662
- const relativePath = path.replace(cwd, ".");
22663
- console.log(source_default.gray(`${action}: ${relativePath}`));
22792
+ let debounceTimer = null;
22793
+ let pendingChanges = [];
22794
+ const triggerSync = async () => {
22795
+ const changes = [...pendingChanges];
22796
+ pendingChanges = [];
22797
+ for (const { path, action } of changes) {
22798
+ const relativePath = path.replace(cwd, ".");
22799
+ console.log(source_default.gray(`${action}: ${relativePath}`));
22800
+ }
22664
22801
  const syncSpinner = ora("Syncing...").start();
22665
22802
  try {
22666
22803
  await performDevSync(cwd, project.organization.id);
@@ -22688,6 +22825,15 @@ var devCommand = new Command("dev").description("Watch files and sync to develop
22688
22825
  }
22689
22826
  }
22690
22827
  };
22828
+ const handleFileChange = (path, action) => {
22829
+ pendingChanges.push({ path, action });
22830
+ if (debounceTimer)
22831
+ clearTimeout(debounceTimer);
22832
+ debounceTimer = setTimeout(() => {
22833
+ debounceTimer = null;
22834
+ triggerSync();
22835
+ }, 300);
22836
+ };
22691
22837
  watcher.on("change", (path) => handleFileChange(path, "Changed"));
22692
22838
  watcher.on("add", (path) => handleFileChange(path, "Added"));
22693
22839
  watcher.on("unlink", (path) => handleFileChange(path, "Removed"));
@@ -23616,13 +23762,13 @@ export default defineTools([])
23616
23762
  ` parameters: ${stringifyValue(tool.parameters, 4)}`
23617
23763
  ];
23618
23764
  if (tool.handlerCode) {
23619
- parts.push(` handler: async (args, context, fetch) => {
23765
+ parts.push(` handler: async (args, context, struere, fetch) => {
23620
23766
  ${tool.handlerCode.split(`
23621
23767
  `).join(`
23622
23768
  `)}
23623
23769
  }`);
23624
23770
  } else {
23625
- parts.push(` handler: async (args, context, fetch) => {
23771
+ parts.push(` handler: async (args, context, struere, fetch) => {
23626
23772
  throw new Error("TODO: implement handler")
23627
23773
  }`);
23628
23774
  }
@@ -23912,7 +24058,6 @@ var pullCommand = new Command("pull").description("Pull remote resources to loca
23912
24058
  });
23913
24059
 
23914
24060
  // src/cli/utils/entities.ts
23915
- var CONVEX_URL2 = process.env.STRUERE_CONVEX_URL || "https://rapid-wildebeest-172.convex.cloud";
23916
24061
  function getToken() {
23917
24062
  const credentials = loadCredentials();
23918
24063
  const apiKey = getApiKey();
@@ -23922,7 +24067,7 @@ async function convexQuery(path, args) {
23922
24067
  const token = getToken();
23923
24068
  if (!token)
23924
24069
  return { error: "Not authenticated" };
23925
- const response = await fetch(`${CONVEX_URL2}/api/query`, {
24070
+ const response = await fetch(`${CONVEX_URL}/api/query`, {
23926
24071
  method: "POST",
23927
24072
  headers: {
23928
24073
  "Content-Type": "application/json",
@@ -23951,7 +24096,7 @@ async function convexMutation(path, args) {
23951
24096
  const token = getToken();
23952
24097
  if (!token)
23953
24098
  return { error: "Not authenticated" };
23954
- const response = await fetch(`${CONVEX_URL2}/api/mutation`, {
24099
+ const response = await fetch(`${CONVEX_URL}/api/mutation`, {
23955
24100
  method: "POST",
23956
24101
  headers: {
23957
24102
  "Content-Type": "application/json",
@@ -24481,7 +24626,6 @@ import { join as join9 } from "path";
24481
24626
  import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync6 } from "fs";
24482
24627
 
24483
24628
  // src/cli/utils/evals.ts
24484
- var CONVEX_URL3 = process.env.STRUERE_CONVEX_URL || "https://rapid-wildebeest-172.convex.cloud";
24485
24629
  function getToken2() {
24486
24630
  const credentials = loadCredentials();
24487
24631
  const apiKey = getApiKey();
@@ -24492,7 +24636,7 @@ function getToken2() {
24492
24636
  }
24493
24637
  async function convexQuery2(path, args) {
24494
24638
  const token = getToken2();
24495
- const response = await fetch(`${CONVEX_URL3}/api/query`, {
24639
+ const response = await fetch(`${CONVEX_URL}/api/query`, {
24496
24640
  method: "POST",
24497
24641
  headers: {
24498
24642
  "Content-Type": "application/json",
@@ -24517,7 +24661,7 @@ async function convexQuery2(path, args) {
24517
24661
  }
24518
24662
  async function convexMutation2(path, args) {
24519
24663
  const token = getToken2();
24520
- const response = await fetch(`${CONVEX_URL3}/api/mutation`, {
24664
+ const response = await fetch(`${CONVEX_URL}/api/mutation`, {
24521
24665
  method: "POST",
24522
24666
  headers: {
24523
24667
  "Content-Type": "application/json",
@@ -24934,10 +25078,6 @@ evalCommand.addCommand(runCommand);
24934
25078
  import { readFileSync as readFileSync4 } from "fs";
24935
25079
 
24936
25080
  // src/cli/utils/whatsapp.ts
24937
- var CONVEX_URL4 = process.env.STRUERE_CONVEX_URL || "https://rapid-wildebeest-172.convex.cloud";
24938
- function getSiteUrl2() {
24939
- return CONVEX_URL4.replace(".cloud", ".site");
24940
- }
24941
25081
  function getToken3() {
24942
25082
  const credentials = loadCredentials();
24943
25083
  const apiKey = getApiKey();
@@ -24947,7 +25087,7 @@ async function httpPost(path, body) {
24947
25087
  const apiKey = getApiKey();
24948
25088
  if (!apiKey)
24949
25089
  return { error: "Not authenticated" };
24950
- const siteUrl = getSiteUrl2();
25090
+ const siteUrl = getSiteUrl();
24951
25091
  try {
24952
25092
  const response = await fetch(`${siteUrl}${path}`, {
24953
25093
  method: "POST",
@@ -24980,7 +25120,7 @@ async function convexAction(path, args) {
24980
25120
  const token = getToken3();
24981
25121
  if (!token)
24982
25122
  return { error: "Not authenticated" };
24983
- const response = await fetch(`${CONVEX_URL4}/api/action`, {
25123
+ const response = await fetch(`${CONVEX_URL}/api/action`, {
24984
25124
  method: "POST",
24985
25125
  headers: {
24986
25126
  "Content-Type": "application/json",
@@ -25009,7 +25149,7 @@ async function convexQuery3(path, args) {
25009
25149
  const token = getToken3();
25010
25150
  if (!token)
25011
25151
  return { error: "Not authenticated" };
25012
- const response = await fetch(`${CONVEX_URL4}/api/query`, {
25152
+ const response = await fetch(`${CONVEX_URL}/api/query`, {
25013
25153
  method: "POST",
25014
25154
  headers: {
25015
25155
  "Content-Type": "application/json",
@@ -25043,16 +25183,15 @@ async function listWhatsAppConnections(env2) {
25043
25183
  }
25044
25184
  return convexQuery3("whatsapp:listConnections", { environment: env2 });
25045
25185
  }
25046
- async function listTemplates(connectionId, env2) {
25186
+ async function listTemplates(connectionId) {
25047
25187
  if (getApiKey()) {
25048
25188
  return httpPost("/v1/templates/list", { connectionId });
25049
25189
  }
25050
25190
  return convexAction("whatsappActions:listTemplates", {
25051
- connectionId,
25052
- environment: env2
25191
+ connectionId
25053
25192
  });
25054
25193
  }
25055
- async function createTemplate(connectionId, env2, name, language, category, components, allowCategoryChange) {
25194
+ async function createTemplate(connectionId, name, language, category, components, allowCategoryChange) {
25056
25195
  if (getApiKey()) {
25057
25196
  return httpPost("/v1/templates/create", {
25058
25197
  connectionId,
@@ -25065,7 +25204,6 @@ async function createTemplate(connectionId, env2, name, language, category, comp
25065
25204
  }
25066
25205
  return convexAction("whatsappActions:createTemplate", {
25067
25206
  connectionId,
25068
- environment: env2,
25069
25207
  name,
25070
25208
  language,
25071
25209
  category,
@@ -25073,23 +25211,21 @@ async function createTemplate(connectionId, env2, name, language, category, comp
25073
25211
  ...allowCategoryChange !== undefined && { allowCategoryChange }
25074
25212
  });
25075
25213
  }
25076
- async function deleteTemplate(connectionId, env2, name) {
25214
+ async function deleteTemplate(connectionId, name) {
25077
25215
  if (getApiKey()) {
25078
25216
  return httpPost("/v1/templates/delete", { connectionId, name });
25079
25217
  }
25080
25218
  return convexAction("whatsappActions:deleteTemplate", {
25081
25219
  connectionId,
25082
- environment: env2,
25083
25220
  name
25084
25221
  });
25085
25222
  }
25086
- async function getTemplateStatus(connectionId, env2, name) {
25223
+ async function getTemplateStatus(connectionId, name) {
25087
25224
  if (getApiKey()) {
25088
25225
  return httpPost("/v1/templates/status", { connectionId, name });
25089
25226
  }
25090
25227
  return convexAction("whatsappActions:getTemplateStatus", {
25091
25228
  connectionId,
25092
- environment: env2,
25093
25229
  name
25094
25230
  });
25095
25231
  }
@@ -25185,13 +25321,12 @@ function statusColor2(status) {
25185
25321
  }
25186
25322
  }
25187
25323
  var templatesCommand = new Command("templates").description("Manage WhatsApp message templates");
25188
- templatesCommand.command("list").description("List all message templates").option("--env <environment>", "Environment (development|production)", "development").option("--connection <id>", "WhatsApp connection ID").option("--json", "Output raw JSON").action(async (opts) => {
25324
+ templatesCommand.command("list").description("List all message templates").option("--connection <id>", "WhatsApp connection ID").option("--json", "Output raw JSON").action(async (opts) => {
25189
25325
  await ensureAuth2();
25190
- const env2 = opts.env;
25191
- const connectionId = await resolveConnectionId(env2, opts.connection);
25326
+ const connectionId = await resolveConnectionId("development", opts.connection);
25192
25327
  const out = createOutput();
25193
25328
  out.start("Fetching templates");
25194
- const { data, error } = await listTemplates(connectionId, env2);
25329
+ const { data, error } = await listTemplates(connectionId);
25195
25330
  if (error) {
25196
25331
  out.fail("Failed to fetch templates");
25197
25332
  out.error(error);
@@ -25223,10 +25358,9 @@ templatesCommand.command("list").description("List all message templates").optio
25223
25358
  })));
25224
25359
  console.log();
25225
25360
  });
25226
- templatesCommand.command("create <name>").description("Create a new message template").option("--env <environment>", "Environment (development|production)", "development").option("--connection <id>", "WhatsApp connection ID").option("--language <code>", "Language code", "en_US").option("--category <cat>", "Category (UTILITY|MARKETING|AUTHENTICATION)", "UTILITY").option("--components <json>", "Components as JSON string").option("--file <path>", "Read components from a JSON file").option("--allow-category-change", "Allow Meta to reassign category").option("--json", "Output raw JSON").action(async (name, opts) => {
25361
+ templatesCommand.command("create <name>").description("Create a new message template").option("--connection <id>", "WhatsApp connection ID").option("--language <code>", "Language code", "en_US").option("--category <cat>", "Category (UTILITY|MARKETING|AUTHENTICATION)", "UTILITY").option("--components <json>", "Components as JSON string").option("--file <path>", "Read components from a JSON file").option("--allow-category-change", "Allow Meta to reassign category").option("--json", "Output raw JSON").action(async (name, opts) => {
25227
25362
  await ensureAuth2();
25228
- const env2 = opts.env;
25229
- const connectionId = await resolveConnectionId(env2, opts.connection);
25363
+ const connectionId = await resolveConnectionId("development", opts.connection);
25230
25364
  let components;
25231
25365
  if (opts.file) {
25232
25366
  try {
@@ -25254,7 +25388,7 @@ templatesCommand.command("create <name>").description("Create a new message temp
25254
25388
  }
25255
25389
  const out = createOutput();
25256
25390
  out.start(`Creating template "${name}"`);
25257
- const { data, error } = await createTemplate(connectionId, env2, name, opts.language, opts.category.toUpperCase(), components, opts.allowCategoryChange);
25391
+ const { data, error } = await createTemplate(connectionId, name, opts.language, opts.category.toUpperCase(), components, opts.allowCategoryChange);
25258
25392
  if (error) {
25259
25393
  out.fail("Failed to create template");
25260
25394
  out.error(error);
@@ -25272,10 +25406,9 @@ templatesCommand.command("create <name>").description("Create a new message temp
25272
25406
  console.log();
25273
25407
  }
25274
25408
  });
25275
- templatesCommand.command("delete <name>").description("Delete a message template").option("--env <environment>", "Environment (development|production)", "development").option("--connection <id>", "WhatsApp connection ID").option("--yes", "Skip confirmation").action(async (name, opts) => {
25409
+ templatesCommand.command("delete <name>").description("Delete a message template").option("--connection <id>", "WhatsApp connection ID").option("--yes", "Skip confirmation").action(async (name, opts) => {
25276
25410
  await ensureAuth2();
25277
- const env2 = opts.env;
25278
- const connectionId = await resolveConnectionId(env2, opts.connection);
25411
+ const connectionId = await resolveConnectionId("development", opts.connection);
25279
25412
  if (!opts.yes && isInteractive2()) {
25280
25413
  const confirmed = await esm_default2({
25281
25414
  message: `Delete template "${name}"? This cannot be undone.`,
@@ -25288,7 +25421,7 @@ templatesCommand.command("delete <name>").description("Delete a message template
25288
25421
  }
25289
25422
  const out = createOutput();
25290
25423
  out.start(`Deleting template "${name}"`);
25291
- const { error } = await deleteTemplate(connectionId, env2, name);
25424
+ const { error } = await deleteTemplate(connectionId, name);
25292
25425
  if (error) {
25293
25426
  out.fail("Failed to delete template");
25294
25427
  out.error(error);
@@ -25297,13 +25430,12 @@ templatesCommand.command("delete <name>").description("Delete a message template
25297
25430
  out.succeed(`Template "${name}" deleted`);
25298
25431
  console.log();
25299
25432
  });
25300
- templatesCommand.command("status <name>").description("Check template approval status").option("--env <environment>", "Environment (development|production)", "development").option("--connection <id>", "WhatsApp connection ID").option("--json", "Output raw JSON").action(async (name, opts) => {
25433
+ templatesCommand.command("status <name>").description("Check template approval status").option("--connection <id>", "WhatsApp connection ID").option("--json", "Output raw JSON").action(async (name, opts) => {
25301
25434
  await ensureAuth2();
25302
- const env2 = opts.env;
25303
- const connectionId = await resolveConnectionId(env2, opts.connection);
25435
+ const connectionId = await resolveConnectionId("development", opts.connection);
25304
25436
  const out = createOutput();
25305
25437
  out.start(`Checking status for "${name}"`);
25306
- const { data, error } = await getTemplateStatus(connectionId, env2, name);
25438
+ const { data, error } = await getTemplateStatus(connectionId, name);
25307
25439
  if (error) {
25308
25440
  out.fail("Failed to fetch template status");
25309
25441
  out.error(error);
@@ -25336,7 +25468,6 @@ templatesCommand.command("status <name>").description("Check template approval s
25336
25468
  });
25337
25469
 
25338
25470
  // src/cli/utils/integrations.ts
25339
- var CONVEX_URL5 = process.env.STRUERE_CONVEX_URL || "https://rapid-wildebeest-172.convex.cloud";
25340
25471
  function getToken4() {
25341
25472
  const credentials = loadCredentials();
25342
25473
  const apiKey = getApiKey();
@@ -25346,7 +25477,7 @@ async function convexQuery4(path, args) {
25346
25477
  const token = getToken4();
25347
25478
  if (!token)
25348
25479
  return { error: "Not authenticated" };
25349
- const response = await fetch(`${CONVEX_URL5}/api/query`, {
25480
+ const response = await fetch(`${CONVEX_URL}/api/query`, {
25350
25481
  method: "POST",
25351
25482
  headers: {
25352
25483
  "Content-Type": "application/json",
@@ -25375,7 +25506,7 @@ async function convexMutation3(path, args) {
25375
25506
  const token = getToken4();
25376
25507
  if (!token)
25377
25508
  return { error: "Not authenticated" };
25378
- const response = await fetch(`${CONVEX_URL5}/api/mutation`, {
25509
+ const response = await fetch(`${CONVEX_URL}/api/mutation`, {
25379
25510
  method: "POST",
25380
25511
  headers: {
25381
25512
  "Content-Type": "application/json",
@@ -25404,7 +25535,7 @@ async function convexAction2(path, args) {
25404
25535
  const token = getToken4();
25405
25536
  if (!token)
25406
25537
  return { error: "Not authenticated" };
25407
- const response = await fetch(`${CONVEX_URL5}/api/action`, {
25538
+ const response = await fetch(`${CONVEX_URL}/api/action`, {
25408
25539
  method: "POST",
25409
25540
  headers: {
25410
25541
  "Content-Type": "application/json",
@@ -25869,7 +26000,7 @@ var compilePromptCommand = new Command("compile-prompt").description("Compile an
25869
26000
  // package.json
25870
26001
  var package_default = {
25871
26002
  name: "struere",
25872
- version: "0.9.7",
26003
+ version: "0.9.9",
25873
26004
  description: "Build, test, and deploy AI agents",
25874
26005
  keywords: [
25875
26006
  "ai",
@@ -25973,6 +26104,7 @@ program.addCommand(initCommand);
25973
26104
  program.addCommand(loginCommand);
25974
26105
  program.addCommand(logoutCommand);
25975
26106
  program.addCommand(whoamiCommand);
26107
+ program.addCommand(orgCommand);
25976
26108
  program.addCommand(syncCommand);
25977
26109
  program.addCommand(devCommand);
25978
26110
  program.addCommand(deployCommand);