struere 0.9.5 → 0.9.7

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.
@@ -19710,6 +19710,115 @@ async function getSyncState(organizationId, environment) {
19710
19710
  }
19711
19711
  return { error: `Unexpected response: ${JSON.stringify(result)}` };
19712
19712
  }
19713
+ async function compilePrompt(options) {
19714
+ const credentials = loadCredentials();
19715
+ const apiKey = getApiKey();
19716
+ if (apiKey && !credentials?.token) {
19717
+ const siteUrl = getSiteUrl();
19718
+ try {
19719
+ const response2 = await fetch(`${siteUrl}/v1/compile-prompt`, {
19720
+ method: "POST",
19721
+ headers: {
19722
+ "Content-Type": "application/json",
19723
+ Authorization: `Bearer ${apiKey}`
19724
+ },
19725
+ body: JSON.stringify({
19726
+ slug: options.slug,
19727
+ message: options.message,
19728
+ channel: options.channel,
19729
+ threadMetadata: options.threadMetadata
19730
+ }),
19731
+ signal: AbortSignal.timeout(30000)
19732
+ });
19733
+ const text2 = await response2.text();
19734
+ let json2;
19735
+ try {
19736
+ json2 = JSON.parse(text2);
19737
+ } catch {
19738
+ return { error: text2 || `HTTP ${response2.status}` };
19739
+ }
19740
+ if (!response2.ok) {
19741
+ return { error: json2.error || text2 };
19742
+ }
19743
+ return { result: json2 };
19744
+ } catch (err) {
19745
+ if (err instanceof DOMException && err.name === "TimeoutError") {
19746
+ return { error: "Request timed out after 30s" };
19747
+ }
19748
+ return { error: `Network error: ${err instanceof Error ? err.message : String(err)}` };
19749
+ }
19750
+ }
19751
+ if (credentials?.sessionId) {
19752
+ await refreshToken();
19753
+ }
19754
+ const freshCredentials = loadCredentials();
19755
+ const token = apiKey || freshCredentials?.token;
19756
+ if (!token) {
19757
+ return { error: "Not authenticated" };
19758
+ }
19759
+ const agentResponse = await fetch(`${CONVEX_URL}/api/query`, {
19760
+ method: "POST",
19761
+ headers: {
19762
+ "Content-Type": "application/json",
19763
+ Authorization: `Bearer ${token}`
19764
+ },
19765
+ body: JSON.stringify({
19766
+ path: "agents:getBySlug",
19767
+ args: { slug: options.slug }
19768
+ })
19769
+ });
19770
+ if (!agentResponse.ok) {
19771
+ return { error: await agentResponse.text() };
19772
+ }
19773
+ const agentResult = await agentResponse.json();
19774
+ if (agentResult.status === "error") {
19775
+ return { error: agentResult.errorMessage || "Failed to look up agent" };
19776
+ }
19777
+ if (!agentResult.value) {
19778
+ return { error: `Agent not found: ${options.slug}` };
19779
+ }
19780
+ const response = await fetch(`${CONVEX_URL}/api/action`, {
19781
+ method: "POST",
19782
+ headers: {
19783
+ "Content-Type": "application/json",
19784
+ Authorization: `Bearer ${token}`
19785
+ },
19786
+ body: JSON.stringify({
19787
+ path: "agents:compileSystemPrompt",
19788
+ args: {
19789
+ agentId: agentResult.value._id,
19790
+ environment: options.environment,
19791
+ sampleContext: {
19792
+ message: options.message,
19793
+ channel: options.channel,
19794
+ threadMetadata: options.threadMetadata
19795
+ }
19796
+ }
19797
+ }),
19798
+ signal: AbortSignal.timeout(30000)
19799
+ });
19800
+ const text = await response.text();
19801
+ let json;
19802
+ try {
19803
+ json = JSON.parse(text);
19804
+ } catch {
19805
+ return { error: text || `HTTP ${response.status}` };
19806
+ }
19807
+ if (!response.ok) {
19808
+ const msg = json.errorData?.message || json.errorMessage || text;
19809
+ return { error: msg };
19810
+ }
19811
+ if (json.status === "success" && json.value) {
19812
+ return { result: json.value };
19813
+ }
19814
+ if (json.status === "success" && json.value === null) {
19815
+ return { error: `Agent not found or no config for environment: ${options.environment}` };
19816
+ }
19817
+ if (json.status === "error") {
19818
+ return { error: json.errorData?.message || json.errorMessage || "Unknown error from Convex" };
19819
+ }
19820
+ return { error: `Unexpected response: ${text}` };
19821
+ }
19713
19822
  async function getPullState(organizationId, environment = "development") {
19714
19823
  const credentials = loadCredentials();
19715
19824
  const apiKey = getApiKey();
@@ -19802,6 +19911,7 @@ async function browserLoginInternal(spinner) {
19802
19911
  const authPromise = new Promise((resolve, reject) => {
19803
19912
  const server = Bun.serve({
19804
19913
  port: AUTH_CALLBACK_PORT,
19914
+ hostname: "127.0.0.1",
19805
19915
  async fetch(req) {
19806
19916
  const url = new URL(req.url);
19807
19917
  if (url.pathname === "/callback") {
@@ -20102,9 +20212,9 @@ logs/
20102
20212
  }
20103
20213
  function getEntityTypeTs(name, slug) {
20104
20214
  const displayName = name.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
20105
- return `import { defineEntityType } from 'struere'
20215
+ return `import { defineData } from 'struere'
20106
20216
 
20107
- export default defineEntityType({
20217
+ export default defineData({
20108
20218
  name: "${displayName}",
20109
20219
  slug: "${slug}",
20110
20220
  schema: {
@@ -20520,11 +20630,11 @@ function validateObjectProperties(schema, path) {
20520
20630
  }
20521
20631
  }
20522
20632
 
20523
- function defineEntityType(config) {
20524
- if (!config.name) throw new Error('Entity type name is required')
20525
- if (!config.slug) throw new Error('Entity type slug is required')
20526
- if (!config.schema) throw new Error('Entity type schema is required')
20527
- if (config.schema.type !== 'object') throw new Error('Entity type schema must be an object type')
20633
+ function defineData(config) {
20634
+ if (!config.name) throw new Error('Data type name is required')
20635
+ if (!config.slug) throw new Error('Data type slug is required')
20636
+ if (!config.schema) throw new Error('Data type schema is required')
20637
+ if (config.schema.type !== 'object') throw new Error('Data type schema must be an object type')
20528
20638
  if (config.schema.properties) {
20529
20639
  for (const [key, value] of Object.entries(config.schema.properties)) {
20530
20640
  validateObjectProperties(value, key)
@@ -20599,7 +20709,7 @@ function defineConfig(config) {
20599
20709
  }
20600
20710
  }
20601
20711
 
20602
- export { defineAgent, defineRole, defineEntityType, defineTrigger, defineTools, defineConfig }
20712
+ export { defineAgent, defineRole, defineData, defineTrigger, defineTools, defineConfig }
20603
20713
  `;
20604
20714
  function registerStruerePlugin() {
20605
20715
  if (registered)
@@ -20776,7 +20886,7 @@ var TYPE_DECLARATIONS = `declare module 'struere' {
20776
20886
 
20777
20887
  export function defineAgent(config: AgentConfig): AgentConfig
20778
20888
  export function defineRole(config: RoleConfig): RoleConfig
20779
- export function defineEntityType(config: EntityTypeConfig): EntityTypeConfig
20889
+ export function defineData(config: EntityTypeConfig): EntityTypeConfig
20780
20890
  export function defineTrigger(config: TriggerConfig): TriggerConfig
20781
20891
  export function defineTools(tools: ToolDefinition[]): ToolReference[]
20782
20892
  export function defineConfig(config?: Partial<FrameworkConfig>): FrameworkConfig
@@ -20950,7 +21060,7 @@ function buildProjectContext(orgName, resources) {
20950
21060
  }
20951
21061
  if (resources.entityTypes.length > 0) {
20952
21062
  lines.push("");
20953
- lines.push(`### Entity Types (${resources.entityTypes.length})`);
21063
+ lines.push(`### Data Types (${resources.entityTypes.length})`);
20954
21064
  for (const et of resources.entityTypes) {
20955
21065
  const fields = et.schema?.properties ? Object.keys(et.schema.properties).join(", ") : "";
20956
21066
  const fieldStr = fields ? ` \u2014 fields: ${fields}` : "";
@@ -20986,7 +21096,7 @@ function buildDocument(projectContext) {
20986
21096
  const lines = [];
20987
21097
  lines.push(`# Struere Workspace`);
20988
21098
  lines.push("");
20989
- lines.push(`> This is a Struere workspace project. You define agents, entity types, roles, triggers, and custom tools here. The CLI syncs them to the Convex backend.`);
21099
+ lines.push(`> This is a Struere workspace project. You define agents, data types, roles, triggers, and custom tools here. The CLI syncs them to the Convex backend.`);
20990
21100
  lines.push("");
20991
21101
  lines.push(`## Agent Usage`);
20992
21102
  lines.push("");
@@ -21006,7 +21116,7 @@ function buildDocument(projectContext) {
21006
21116
  lines.push("");
21007
21117
  lines.push("**JSON output**: Most commands support `--json` for structured output:");
21008
21118
  lines.push("```bash");
21009
- lines.push("struere entities list <type> --json");
21119
+ lines.push("struere data list <type> --json");
21010
21120
  lines.push("struere status --json");
21011
21121
  lines.push("struere deploy --json --force");
21012
21122
  lines.push("```");
@@ -21023,7 +21133,7 @@ function buildDocument(projectContext) {
21023
21133
  lines.push("");
21024
21134
  lines.push("```");
21025
21135
  lines.push("agents/ # Agent definitions (one file per agent)");
21026
- lines.push("entity-types/ # Entity type schemas (like DB tables)");
21136
+ lines.push("entity-types/ # Data type schemas (like DB tables)");
21027
21137
  lines.push("roles/ # RBAC roles with policies, scope rules, field masks");
21028
21138
  lines.push("triggers/ # Automation rules (react to entity changes)");
21029
21139
  lines.push("tools/index.ts # Custom tools shared by all agents");
@@ -21039,16 +21149,16 @@ function buildDocument(projectContext) {
21039
21149
  lines.push("| `struere sync` | One-shot sync to Convex and exit (agent-friendly) |");
21040
21150
  lines.push("| `struere dev` | Watch files and sync to Convex on save |");
21041
21151
  lines.push("| `struere deploy` | Push development config to production |");
21042
- lines.push("| `struere add agent\\|entity-type\\|role\\|trigger\\|eval\\|fixture <name>` | Scaffold a new resource |");
21152
+ lines.push("| `struere add agent\\|data-type\\|role\\|trigger\\|eval\\|fixture <name>` | Scaffold a new resource |");
21043
21153
  lines.push("| `struere status` | Compare local vs remote state |");
21044
21154
  lines.push("| `struere pull` | Download remote resources to local files |");
21045
- lines.push("| `struere entities types` | List entity types in an environment |");
21046
- lines.push("| `struere entities list <type>` | List entities (supports `--status`, `--limit`, `--json`) |");
21047
- lines.push("| `struere entities get <id>` | Get entity details |");
21048
- lines.push("| `struere entities create <type>` | Create entity (interactive or `--data <json>`) |");
21049
- lines.push("| `struere entities update <id>` | Update entity (`--data <json>`, `--status`) |");
21050
- lines.push("| `struere entities delete <id>` | Delete entity (with confirmation) |");
21051
- lines.push("| `struere entities search <type> <query>` | Search entities by text |");
21155
+ lines.push("| `struere data types` | List data types in an environment |");
21156
+ lines.push("| `struere data list <type>` | List records (supports `--status`, `--limit`, `--json`) |");
21157
+ lines.push("| `struere data get <id>` | Get record details |");
21158
+ lines.push("| `struere data create <type>` | Create record (interactive or `--data <json>`) |");
21159
+ lines.push("| `struere data update <id>` | Update record (`--data <json>`, `--status`) |");
21160
+ lines.push("| `struere data delete <id>` | Delete record (with confirmation) |");
21161
+ lines.push("| `struere data search <type> <query>` | Search records by text |");
21052
21162
  lines.push("| `struere eval run <suite>` | Run an eval suite and write Markdown results |");
21053
21163
  lines.push("| `struere eval run <suite> --case <name>` | Run specific case(s) by name |");
21054
21164
  lines.push("| `struere eval run <suite> --tag <tag>` | Run cases matching a tag |");
@@ -21060,7 +21170,7 @@ function buildDocument(projectContext) {
21060
21170
  lines.push("");
21061
21171
  lines.push(`## Key Patterns`);
21062
21172
  lines.push("");
21063
- lines.push("- **Imports**: `import { defineAgent, defineEntityType, defineRole, defineTrigger, defineTools } from 'struere'`");
21173
+ lines.push("- **Imports**: `import { defineAgent, defineData, defineRole, defineTrigger, defineTools } from 'struere'`");
21064
21174
  lines.push("- **Default model**: `grok-4-1-fast` (provider: `xai`). Also supports `anthropic`, `openai` and `google`");
21065
21175
  lines.push("- **Scope rule values**: `actor.userId`, `actor.entityId`, `actor.organizationId`, `actor.relatedIds:TYPE`, `literal:VALUE`");
21066
21176
  lines.push("- **Policy actions**: `create`, `read`, `update`, `delete`, `list` (deny overrides allow)");
@@ -21157,7 +21267,7 @@ function buildDocument(projectContext) {
21157
21267
  lines.push("### SDK");
21158
21268
  lines.push(`- [SDK Overview](${DOCS_BASE}/sdk/overview.md)`);
21159
21269
  lines.push(`- [defineAgent](${DOCS_BASE}/sdk/define-agent.md)`);
21160
- lines.push(`- [defineEntityType](${DOCS_BASE}/sdk/define-entity-type.md)`);
21270
+ lines.push(`- [defineData](${DOCS_BASE}/sdk/define-data.md)`);
21161
21271
  lines.push(`- [defineRole](${DOCS_BASE}/sdk/define-role.md)`);
21162
21272
  lines.push(`- [defineTrigger](${DOCS_BASE}/sdk/define-trigger.md)`);
21163
21273
  lines.push(`- [defineTools](${DOCS_BASE}/sdk/define-tools.md)`);
@@ -21168,7 +21278,7 @@ function buildDocument(projectContext) {
21168
21278
  lines.push(`- [System Prompt Templates](${DOCS_BASE}/tools/system-prompt-templates.md)`);
21169
21279
  lines.push("");
21170
21280
  lines.push("### Platform");
21171
- lines.push(`- [Entities](${DOCS_BASE}/platform/entities.md)`);
21281
+ lines.push(`- [Data](${DOCS_BASE}/platform/data.md)`);
21172
21282
  lines.push(`- [Permissions](${DOCS_BASE}/platform/permissions.md)`);
21173
21283
  lines.push(`- [Agents](${DOCS_BASE}/platform/agents.md)`);
21174
21284
  lines.push(`- [Events](${DOCS_BASE}/platform/events.md)`);
@@ -21505,7 +21615,7 @@ var initCommand = new Command("init").description("Initialize a new Struere orga
21505
21615
  console.log();
21506
21616
  console.log(source_default.gray("Project structure:"));
21507
21617
  console.log(source_default.gray(" agents/ "), source_default.cyan("Agent definitions"));
21508
- console.log(source_default.gray(" entity-types/ "), source_default.cyan("Entity type schemas"));
21618
+ console.log(source_default.gray(" entity-types/ "), source_default.cyan("Data type schemas"));
21509
21619
  console.log(source_default.gray(" roles/ "), source_default.cyan("Role + permission definitions"));
21510
21620
  console.log(source_default.gray(" tools/ "), source_default.cyan("Shared custom tools"));
21511
21621
  console.log();
@@ -21563,7 +21673,9 @@ var BUILTIN_TOOLS = [
21563
21673
  "airtable.createRecords",
21564
21674
  "airtable.updateRecords",
21565
21675
  "airtable.deleteRecords",
21566
- "email.send"
21676
+ "email.send",
21677
+ "payment.create",
21678
+ "payment.getStatus"
21567
21679
  ];
21568
21680
  function extractSyncPayload(resources) {
21569
21681
  const customToolsMap = new Map;
@@ -21618,7 +21730,9 @@ function extractSyncPayload(resources) {
21618
21730
  userMessage: t.user,
21619
21731
  assertions: t.assertions
21620
21732
  })),
21621
- finalAssertions: c.finalAssertions
21733
+ finalAssertions: c.finalAssertions,
21734
+ channel: c.channel,
21735
+ contextParams: c.contextParams
21622
21736
  }))
21623
21737
  })) : undefined;
21624
21738
  const triggers = resources.triggers.length > 0 ? resources.triggers.map((t) => ({
@@ -21734,7 +21848,9 @@ function getBuiltinToolDescription(name) {
21734
21848
  "airtable.createRecords": "Create up to 10 records in an Airtable table",
21735
21849
  "airtable.updateRecords": "Update up to 10 records in an Airtable table",
21736
21850
  "airtable.deleteRecords": "Delete up to 10 records from an Airtable table",
21737
- "email.send": "Send an email via Resend"
21851
+ "email.send": "Send an email via Resend",
21852
+ "payment.create": "Create a payment link via Flow.cl and return the URL",
21853
+ "payment.getStatus": "Check the current status of a payment"
21738
21854
  };
21739
21855
  return descriptions[name] || name;
21740
21856
  }
@@ -22042,6 +22158,24 @@ function getBuiltinToolParameters(name) {
22042
22158
  replyTo: { type: "string", description: "Reply-to email address" }
22043
22159
  },
22044
22160
  required: ["to", "subject"]
22161
+ },
22162
+ "payment.create": {
22163
+ type: "object",
22164
+ properties: {
22165
+ amount: { type: "number", description: "Payment amount in the smallest currency unit" },
22166
+ description: { type: "string", description: "Description of the payment" },
22167
+ currency: { type: "string", description: "Currency code (defaults to CLP)" },
22168
+ customerEmail: { type: "string", description: "Customer email address" },
22169
+ entityId: { type: "string", description: "Optional entity ID to link the payment to" }
22170
+ },
22171
+ required: ["amount", "description"]
22172
+ },
22173
+ "payment.getStatus": {
22174
+ type: "object",
22175
+ properties: {
22176
+ entityId: { type: "string", description: "Payment entity ID to check status for" }
22177
+ },
22178
+ required: ["entityId"]
22045
22179
  }
22046
22180
  };
22047
22181
  return schemas[name] || { type: "object", properties: {} };
@@ -22118,7 +22252,7 @@ async function checkForDeletions(resources, organizationId, environment) {
22118
22252
  deletions.push({ type: "Agents", remote: remoteState.agents.length, local: payload.agents.length, deleted: deletedAgents });
22119
22253
  const deletedEntityTypes = remoteState.entityTypes.filter((et) => !localSlugs.entityTypes.has(et.slug)).map((et) => et.name);
22120
22254
  if (deletedEntityTypes.length > 0)
22121
- deletions.push({ type: "Entity types", remote: remoteState.entityTypes.length, local: payload.entityTypes.length, deleted: deletedEntityTypes });
22255
+ deletions.push({ type: "Data types", remote: remoteState.entityTypes.length, local: payload.entityTypes.length, deleted: deletedEntityTypes });
22122
22256
  const deletedRoles = remoteState.roles.filter((r) => !localSlugs.roles.has(r.name)).map((r) => r.name);
22123
22257
  if (deletedRoles.length > 0)
22124
22258
  deletions.push({ type: "Roles", remote: remoteState.roles.length, local: payload.roles.length, deleted: deletedRoles });
@@ -22223,7 +22357,7 @@ var syncCommand = new Command("sync").description("Sync resources to Convex and
22223
22357
  process.exit(1);
22224
22358
  }
22225
22359
  if (!jsonMode && !options.dryRun)
22226
- output.succeed(`Loaded ${resources.agents.length} agents, ${resources.entityTypes.length} entity types, ${resources.roles.length} roles`);
22360
+ output.succeed(`Loaded ${resources.agents.length} agents, ${resources.entityTypes.length} data types, ${resources.roles.length} roles`);
22227
22361
  } catch (error) {
22228
22362
  if (jsonMode) {
22229
22363
  console.log(JSON.stringify({ success: false, error: error instanceof Error ? error.message : String(error) }));
@@ -22255,7 +22389,7 @@ var syncCommand = new Command("sync").description("Sync resources to Convex and
22255
22389
  console.log(source_default.bold("Dry run \u2014 nothing will be synced"));
22256
22390
  console.log();
22257
22391
  console.log(source_default.gray(" Agents:"), payload.agents.map((a) => a.slug).join(", ") || "none");
22258
- console.log(source_default.gray(" Entity types:"), payload.entityTypes.map((et) => et.slug).join(", ") || "none");
22392
+ console.log(source_default.gray(" Data types:"), payload.entityTypes.map((et) => et.slug).join(", ") || "none");
22259
22393
  console.log(source_default.gray(" Roles:"), payload.roles.map((r) => r.name).join(", ") || "none");
22260
22394
  console.log(source_default.gray(" Triggers:"), (payload.triggers || []).map((t) => t.slug).join(", ") || "none");
22261
22395
  if (deletions.length > 0) {
@@ -22421,7 +22555,7 @@ var devCommand = new Command("dev").description("Watch files and sync to develop
22421
22555
  spinner.start("Loading resources");
22422
22556
  try {
22423
22557
  loadedResources = await loadAllResources(cwd);
22424
- spinner.succeed(`Loaded ${loadedResources.agents.length} agents, ${loadedResources.entityTypes.length} entity types, ${loadedResources.roles.length} roles, ${loadedResources.customTools.length} custom tools, ${loadedResources.evalSuites.length} eval suites, ${loadedResources.triggers.length} triggers, ${loadedResources.fixtures.length} fixtures`);
22558
+ spinner.succeed(`Loaded ${loadedResources.agents.length} agents, ${loadedResources.entityTypes.length} data types, ${loadedResources.roles.length} roles, ${loadedResources.customTools.length} custom tools, ${loadedResources.evalSuites.length} eval suites, ${loadedResources.triggers.length} triggers, ${loadedResources.fixtures.length} fixtures`);
22425
22559
  for (const err of loadedResources.errors) {
22426
22560
  console.log(source_default.red(" \u2716"), err);
22427
22561
  }
@@ -22634,7 +22768,7 @@ var deployCommand = new Command("deploy").description("Deploy all resources to p
22634
22768
  try {
22635
22769
  resources = await loadAllResources(cwd);
22636
22770
  if (!jsonMode)
22637
- spinner.succeed(`Loaded ${resources.agents.length} agents, ${resources.entityTypes.length} entity types, ${resources.roles.length} roles, ${resources.customTools.length} custom tools, ${resources.evalSuites.length} eval suites`);
22771
+ spinner.succeed(`Loaded ${resources.agents.length} agents, ${resources.entityTypes.length} data types, ${resources.roles.length} roles, ${resources.customTools.length} custom tools, ${resources.evalSuites.length} eval suites`);
22638
22772
  for (const err of resources.errors) {
22639
22773
  if (!jsonMode)
22640
22774
  console.log(source_default.red(" \u2716"), err);
@@ -22698,7 +22832,7 @@ var deployCommand = new Command("deploy").description("Deploy all resources to p
22698
22832
  console.log(source_default.gray(" -"), `${source_default.cyan(agent.name)} (${agent.slug}) v${agent.version}`);
22699
22833
  }
22700
22834
  console.log();
22701
- console.log("Entity types:");
22835
+ console.log("Data types:");
22702
22836
  for (const et of resources.entityTypes) {
22703
22837
  console.log(source_default.gray(" -"), source_default.cyan(et.name), `(${et.slug})`);
22704
22838
  }
@@ -22976,7 +23110,7 @@ var whoamiCommand = new Command("whoami").description("Show current logged in us
22976
23110
  });
22977
23111
 
22978
23112
  // src/cli/commands/add.ts
22979
- var addCommand = new Command("add").description("Scaffold a new resource").argument("<type>", "Resource type: agent, entity-type, role, eval, trigger, or fixture").argument("<name>", "Resource name").action(async (type, name) => {
23113
+ var addCommand = new Command("add").description("Scaffold a new resource").argument("<type>", "Resource type: agent, data-type, role, eval, trigger, or fixture").argument("<name>", "Resource name").action(async (type, name) => {
22980
23114
  const cwd = process.cwd();
22981
23115
  console.log();
22982
23116
  if (!hasProject(cwd)) {
@@ -23003,17 +23137,19 @@ var addCommand = new Command("add").description("Scaffold a new resource").argum
23003
23137
  console.log(source_default.yellow("Agent already exists:"), `agents/${slug}.ts`);
23004
23138
  }
23005
23139
  break;
23140
+ case "data-type":
23141
+ case "datatype":
23006
23142
  case "entity-type":
23007
23143
  case "entitytype":
23008
23144
  case "type":
23009
23145
  result = scaffoldEntityType(cwd, displayName, slug);
23010
23146
  if (result.createdFiles.length > 0) {
23011
- console.log(source_default.green("\u2713"), `Created entity type "${displayName}"`);
23147
+ console.log(source_default.green("\u2713"), `Created data type "${displayName}"`);
23012
23148
  for (const file of result.createdFiles) {
23013
23149
  console.log(source_default.gray(" \u2192"), file);
23014
23150
  }
23015
23151
  } else {
23016
- console.log(source_default.yellow("Entity type already exists:"), `entity-types/${slug}.ts`);
23152
+ console.log(source_default.yellow("Data type already exists:"), `entity-types/${slug}.ts`);
23017
23153
  }
23018
23154
  break;
23019
23155
  case "role":
@@ -23070,10 +23206,10 @@ var addCommand = new Command("add").description("Scaffold a new resource").argum
23070
23206
  console.log();
23071
23207
  console.log("Available types:");
23072
23208
  console.log(source_default.gray(" -"), source_default.cyan("agent"), "- Create an AI agent");
23073
- console.log(source_default.gray(" -"), source_default.cyan("entity-type"), "- Create an entity type schema");
23209
+ console.log(source_default.gray(" -"), source_default.cyan("data-type"), "- Create a data type schema");
23074
23210
  console.log(source_default.gray(" -"), source_default.cyan("role"), "- Create a role with permissions");
23075
23211
  console.log(source_default.gray(" -"), source_default.cyan("eval"), "- Create an eval suite (YAML)");
23076
- console.log(source_default.gray(" -"), source_default.cyan("trigger"), "- Create an entity trigger");
23212
+ console.log(source_default.gray(" -"), source_default.cyan("trigger"), "- Create a data trigger");
23077
23213
  console.log(source_default.gray(" -"), source_default.cyan("fixture"), "- Create a test data fixture (YAML)");
23078
23214
  console.log();
23079
23215
  process.exit(1);
@@ -23153,7 +23289,7 @@ var statusCommand = new Command("status").description("Compare local vs remote s
23153
23289
  try {
23154
23290
  localResources = await loadAllResources(cwd);
23155
23291
  if (!jsonMode) {
23156
- spinner.succeed(`Loaded ${localResources.agents.length} agents, ${localResources.entityTypes.length} entity types, ${localResources.roles.length} roles, ${localResources.customTools.length} custom tools, ${localResources.evalSuites.length} eval suites`);
23292
+ spinner.succeed(`Loaded ${localResources.agents.length} agents, ${localResources.entityTypes.length} data types, ${localResources.roles.length} roles, ${localResources.customTools.length} custom tools, ${localResources.evalSuites.length} eval suites`);
23157
23293
  for (const err of localResources.errors) {
23158
23294
  console.log(source_default.red(" \u2716"), err);
23159
23295
  }
@@ -23176,8 +23312,8 @@ var statusCommand = new Command("status").description("Compare local vs remote s
23176
23312
  if (!jsonMode)
23177
23313
  spinner.start("Fetching remote state");
23178
23314
  const [devResult, prodResult] = await Promise.all([
23179
- getSyncState(undefined, "development"),
23180
- getSyncState(undefined, "production")
23315
+ getSyncState(project.organization.id, "development"),
23316
+ getSyncState(project.organization.id, "production")
23181
23317
  ]);
23182
23318
  if (devResult.error || !devResult.state) {
23183
23319
  if (jsonMode) {
@@ -23241,10 +23377,10 @@ var statusCommand = new Command("status").description("Compare local vs remote s
23241
23377
  }
23242
23378
  }
23243
23379
  console.log();
23244
- console.log(source_default.bold("Entity Types"));
23380
+ console.log(source_default.bold("Data Types"));
23245
23381
  console.log(source_default.gray("\u2500".repeat(60)));
23246
23382
  if (localResources.entityTypes.length === 0 && devState.entityTypes.length === 0) {
23247
- console.log(source_default.gray(" No entity types"));
23383
+ console.log(source_default.gray(" No data types"));
23248
23384
  } else {
23249
23385
  for (const et of localResources.entityTypes) {
23250
23386
  const remote = devState.entityTypes.find((r) => r.slug === et.slug);
@@ -23390,9 +23526,9 @@ function generateEntityTypeFile(entityType) {
23390
23526
  if (entityType.displayConfig) {
23391
23527
  parts.push(` displayConfig: ${stringifyValue(entityType.displayConfig, 2)}`);
23392
23528
  }
23393
- return `import { defineEntityType } from 'struere'
23529
+ return `import { defineData } from 'struere'
23394
23530
 
23395
- export default defineEntityType({
23531
+ export default defineData({
23396
23532
  ${parts.join(`,
23397
23533
  `)},
23398
23534
  })
@@ -23840,57 +23976,61 @@ async function convexMutation(path, args) {
23840
23976
  return { error: String(json.errorMessage || "Unknown error") };
23841
23977
  return { error: `Unexpected response: ${text}` };
23842
23978
  }
23843
- async function queryEntityTypes(env2) {
23844
- return convexQuery("entityTypes:list", { environment: env2 });
23979
+ async function queryEntityTypes(env2, organizationId) {
23980
+ return convexQuery("entityTypes:list", { environment: env2, ...organizationId && { organizationId } });
23845
23981
  }
23846
- async function queryEntityTypeBySlug(slug, env2) {
23847
- return convexQuery("entityTypes:getBySlug", { slug, environment: env2 });
23982
+ async function queryEntityTypeBySlug(slug, env2, organizationId) {
23983
+ return convexQuery("entityTypes:getBySlug", { slug, environment: env2, ...organizationId && { organizationId } });
23848
23984
  }
23849
- async function queryEntities(slug, env2, opts) {
23985
+ async function queryEntities(slug, env2, opts, organizationId) {
23850
23986
  return convexQuery("entities:list", {
23851
23987
  entityTypeSlug: slug,
23852
23988
  environment: env2,
23853
23989
  ...opts?.status && { status: opts.status },
23854
- ...opts?.limit && { limit: opts.limit }
23990
+ ...opts?.limit && { limit: opts.limit },
23991
+ ...organizationId && { organizationId }
23855
23992
  });
23856
23993
  }
23857
- async function resolveEntityId(partialId, env2) {
23858
- const result = await convexQuery("entities:resolvePartialId", { partialId, environment: env2 });
23994
+ async function resolveEntityId(partialId, env2, organizationId) {
23995
+ const result = await convexQuery("entities:resolvePartialId", { partialId, environment: env2, ...organizationId && { organizationId } });
23859
23996
  if (result.error)
23860
23997
  return { error: result.error };
23861
23998
  if (!result.data)
23862
23999
  return { error: `No entity found matching ID "${partialId}"` };
23863
24000
  return { data: result.data };
23864
24001
  }
23865
- async function queryEntity(id, env2) {
23866
- return convexQuery("entities:getWithType", { id, environment: env2 });
24002
+ async function queryEntity(id, env2, organizationId) {
24003
+ return convexQuery("entities:getWithType", { id, environment: env2, ...organizationId && { organizationId } });
23867
24004
  }
23868
- async function searchEntities(slug, query, env2, limit) {
24005
+ async function searchEntities(slug, query, env2, limit, organizationId) {
23869
24006
  return convexQuery("entities:search", {
23870
24007
  entityTypeSlug: slug,
23871
24008
  environment: env2,
23872
24009
  query,
23873
- ...limit && { limit }
24010
+ ...limit && { limit },
24011
+ ...organizationId && { organizationId }
23874
24012
  });
23875
24013
  }
23876
- async function createEntity(slug, data, env2, status) {
24014
+ async function createEntity(slug, data, env2, status, organizationId) {
23877
24015
  return convexMutation("entities:create", {
23878
24016
  entityTypeSlug: slug,
23879
24017
  environment: env2,
23880
24018
  data,
23881
- ...status && { status }
24019
+ ...status && { status },
24020
+ ...organizationId && { organizationId }
23882
24021
  });
23883
24022
  }
23884
- async function updateEntity(id, data, env2, status) {
24023
+ async function updateEntity(id, data, env2, status, organizationId) {
23885
24024
  return convexMutation("entities:update", {
23886
24025
  id,
23887
24026
  environment: env2,
23888
24027
  data,
23889
- ...status && { status }
24028
+ ...status && { status },
24029
+ ...organizationId && { organizationId }
23890
24030
  });
23891
24031
  }
23892
- async function removeEntity(id, env2) {
23893
- return convexMutation("entities:remove", { id, environment: env2 });
24032
+ async function removeEntity(id, env2, organizationId) {
24033
+ return convexMutation("entities:remove", { id, environment: env2, ...organizationId && { organizationId } });
23894
24034
  }
23895
24035
 
23896
24036
  // src/cli/utils/table.ts
@@ -23951,6 +24091,10 @@ function deriveColumnsFromSchema(schema, displayConfig) {
23951
24091
  }
23952
24092
 
23953
24093
  // src/cli/commands/entities.ts
24094
+ function getOrgId() {
24095
+ const project = loadProject(process.cwd());
24096
+ return project?.organization.id;
24097
+ }
23954
24098
  async function ensureAuth() {
23955
24099
  const cwd = process.cwd();
23956
24100
  const nonInteractive = !isInteractive2();
@@ -23993,19 +24137,20 @@ function flattenEntityForTable(entity) {
23993
24137
  status: entity.status
23994
24138
  };
23995
24139
  }
23996
- var entitiesCommand = new Command("entities").description("Manage entity data");
23997
- entitiesCommand.command("types").description("List available entity types").option("--env <environment>", "Environment (development|production)", "development").option("--json", "Output raw JSON").action(async (opts) => {
24140
+ var entitiesCommand = new Command("data").description("Manage data records");
24141
+ entitiesCommand.command("types").description("List available data types").option("--env <environment>", "Environment (development|production)", "development").option("--json", "Output raw JSON").action(async (opts) => {
23998
24142
  await ensureAuth();
23999
24143
  const spinner = ora();
24000
24144
  const env2 = opts.env;
24001
- spinner.start("Fetching entity types");
24002
- const { data, error } = await queryEntityTypes(env2);
24145
+ const orgId = getOrgId();
24146
+ spinner.start("Fetching data types");
24147
+ const { data, error } = await queryEntityTypes(env2, orgId);
24003
24148
  if (error || !data) {
24004
- spinner.fail("Failed to fetch entity types");
24149
+ spinner.fail("Failed to fetch data types");
24005
24150
  console.log(source_default.red("Error:"), error);
24006
24151
  process.exit(1);
24007
24152
  }
24008
- spinner.succeed("Entity types loaded");
24153
+ spinner.succeed("Data types loaded");
24009
24154
  const types = data;
24010
24155
  if (opts.json) {
24011
24156
  console.log(JSON.stringify(types, null, 2));
@@ -24028,25 +24173,26 @@ entitiesCommand.command("types").description("List available entity types").opti
24028
24173
  }));
24029
24174
  console.log();
24030
24175
  });
24031
- entitiesCommand.command("list <type>").description("List entities of a type").option("--env <environment>", "Environment (development|production)", "development").option("--status <status>", "Filter by status").option("--limit <n>", "Maximum results", "50").option("--json", "Output raw JSON").action(async (type, opts) => {
24176
+ entitiesCommand.command("list <type>").description("List records of a type").option("--env <environment>", "Environment (development|production)", "development").option("--status <status>", "Filter by status").option("--limit <n>", "Maximum results", "50").option("--json", "Output raw JSON").action(async (type, opts) => {
24032
24177
  await ensureAuth();
24033
24178
  const spinner = ora();
24034
24179
  const env2 = opts.env;
24035
- spinner.start(`Fetching ${type} entities`);
24180
+ const orgId = getOrgId();
24181
+ spinner.start(`Fetching ${type} records`);
24036
24182
  const [entitiesResult, typeResult] = await Promise.all([
24037
24183
  queryEntities(type, env2, {
24038
24184
  status: opts.status,
24039
24185
  limit: parseInt(opts.limit, 10)
24040
- }),
24041
- queryEntityTypeBySlug(type, env2)
24186
+ }, orgId),
24187
+ queryEntityTypeBySlug(type, env2, orgId)
24042
24188
  ]);
24043
24189
  if (entitiesResult.error || !entitiesResult.data) {
24044
- spinner.fail(`Failed to fetch ${type} entities`);
24190
+ spinner.fail(`Failed to fetch ${type} records`);
24045
24191
  console.log(source_default.red("Error:"), entitiesResult.error);
24046
24192
  process.exit(1);
24047
24193
  }
24048
24194
  const entities = entitiesResult.data;
24049
- spinner.succeed(`Found ${entities.length} ${type} entities`);
24195
+ spinner.succeed(`Found ${entities.length} ${type} records`);
24050
24196
  if (opts.json) {
24051
24197
  console.log(JSON.stringify(entities, null, 2));
24052
24198
  return;
@@ -24059,26 +24205,27 @@ entitiesCommand.command("list <type>").description("List entities of a type").op
24059
24205
  renderTable(columns, entities.map(flattenEntityForTable));
24060
24206
  console.log();
24061
24207
  });
24062
- entitiesCommand.command("get <id>").description("Get entity details").option("--env <environment>", "Environment (development|production)", "development").option("--json", "Output raw JSON").action(async (rawId, opts) => {
24208
+ entitiesCommand.command("get <id>").description("Get record details").option("--env <environment>", "Environment (development|production)", "development").option("--json", "Output raw JSON").action(async (rawId, opts) => {
24063
24209
  await ensureAuth();
24064
24210
  const spinner = ora();
24065
24211
  const env2 = opts.env;
24066
- spinner.start("Resolving entity ID");
24067
- const resolved = await resolveEntityId(rawId, env2);
24212
+ const orgId = getOrgId();
24213
+ spinner.start("Resolving record ID");
24214
+ const resolved = await resolveEntityId(rawId, env2, orgId);
24068
24215
  if (resolved.error || !resolved.data) {
24069
- spinner.fail("Entity not found");
24070
- console.log(source_default.red("Error:"), resolved.error || `No entity matched "${rawId}"`);
24216
+ spinner.fail("Record not found");
24217
+ console.log(source_default.red("Error:"), resolved.error || `No record matched "${rawId}"`);
24071
24218
  process.exit(1);
24072
24219
  }
24073
24220
  const id = resolved.data;
24074
- spinner.text = "Fetching entity";
24075
- const { data, error } = await queryEntity(id, env2);
24221
+ spinner.text = "Fetching record";
24222
+ const { data, error } = await queryEntity(id, env2, orgId);
24076
24223
  if (error || !data) {
24077
- spinner.fail("Failed to fetch entity");
24078
- console.log(source_default.red("Error:"), error || "Entity not found");
24224
+ spinner.fail("Failed to fetch record");
24225
+ console.log(source_default.red("Error:"), error || "Record not found");
24079
24226
  process.exit(1);
24080
24227
  }
24081
- spinner.succeed("Entity loaded");
24228
+ spinner.succeed("Record loaded");
24082
24229
  const result = data;
24083
24230
  if (opts.json) {
24084
24231
  console.log(JSON.stringify(result, null, 2));
@@ -24106,10 +24253,11 @@ entitiesCommand.command("get <id>").description("Get entity details").option("--
24106
24253
  }
24107
24254
  console.log();
24108
24255
  });
24109
- entitiesCommand.command("create <type>").description("Create a new entity").option("--env <environment>", "Environment (development|production)", "development").option("--data <json>", "Entity data as JSON").option("--status <status>", "Initial status").option("--json", "Output raw JSON").action(async (type, opts) => {
24256
+ entitiesCommand.command("create <type>").description("Create a new record").option("--env <environment>", "Environment (development|production)", "development").option("--data <json>", "Record data as JSON").option("--status <status>", "Initial status").option("--json", "Output raw JSON").action(async (type, opts) => {
24110
24257
  await ensureAuth();
24111
24258
  const spinner = ora();
24112
24259
  const env2 = opts.env;
24260
+ const orgId = getOrgId();
24113
24261
  let data;
24114
24262
  if (opts.data) {
24115
24263
  try {
@@ -24123,9 +24271,9 @@ entitiesCommand.command("create <type>").description("Create a new entity").opti
24123
24271
  process.exit(1);
24124
24272
  } else {
24125
24273
  spinner.start(`Fetching ${type} schema`);
24126
- const { data: typeData, error: error2 } = await queryEntityTypeBySlug(type, env2);
24274
+ const { data: typeData, error: error2 } = await queryEntityTypeBySlug(type, env2, orgId);
24127
24275
  if (error2 || !typeData) {
24128
- spinner.fail(`Entity type not found: ${type}`);
24276
+ spinner.fail(`Data type not found: ${type}`);
24129
24277
  console.log(source_default.red("Error:"), error2 || "Not found");
24130
24278
  process.exit(1);
24131
24279
  }
@@ -24134,7 +24282,7 @@ entitiesCommand.command("create <type>").description("Create a new entity").opti
24134
24282
  const entityType = typeData;
24135
24283
  const schema = entityType.schema;
24136
24284
  if (!schema?.properties) {
24137
- console.log(source_default.red("Entity type has no schema properties defined"));
24285
+ console.log(source_default.red("Data type has no schema properties defined"));
24138
24286
  process.exit(1);
24139
24287
  }
24140
24288
  data = {};
@@ -24163,14 +24311,14 @@ entitiesCommand.command("create <type>").description("Create a new entity").opti
24163
24311
  }
24164
24312
  console.log();
24165
24313
  }
24166
- spinner.start(`Creating ${type} entity`);
24167
- const { data: result, error } = await createEntity(type, data, env2, opts.status);
24314
+ spinner.start(`Creating ${type} record`);
24315
+ const { data: result, error } = await createEntity(type, data, env2, opts.status, orgId);
24168
24316
  if (error) {
24169
- spinner.fail("Failed to create entity");
24317
+ spinner.fail("Failed to create record");
24170
24318
  console.log(source_default.red("Error:"), error);
24171
24319
  process.exit(1);
24172
24320
  }
24173
- spinner.succeed(`Entity created`);
24321
+ spinner.succeed(`Record created`);
24174
24322
  if (opts.json) {
24175
24323
  console.log(JSON.stringify({ id: result }, null, 2));
24176
24324
  } else {
@@ -24179,10 +24327,11 @@ entitiesCommand.command("create <type>").description("Create a new entity").opti
24179
24327
  console.log();
24180
24328
  }
24181
24329
  });
24182
- entitiesCommand.command("update <id>").description("Update an entity").option("--env <environment>", "Environment (development|production)", "development").option("--data <json>", "Update data as JSON").option("--status <status>", "New status").option("--json", "Output raw JSON").action(async (rawId, opts) => {
24330
+ entitiesCommand.command("update <id>").description("Update a record").option("--env <environment>", "Environment (development|production)", "development").option("--data <json>", "Update data as JSON").option("--status <status>", "New status").option("--json", "Output raw JSON").action(async (rawId, opts) => {
24183
24331
  await ensureAuth();
24184
24332
  const spinner = ora();
24185
24333
  const env2 = opts.env;
24334
+ const orgId = getOrgId();
24186
24335
  if (!opts.data && !opts.status) {
24187
24336
  console.log(source_default.red("Provide --data and/or --status"));
24188
24337
  process.exit(1);
@@ -24196,62 +24345,63 @@ entitiesCommand.command("update <id>").description("Update an entity").option("-
24196
24345
  process.exit(1);
24197
24346
  }
24198
24347
  }
24199
- spinner.start("Resolving entity ID");
24200
- const resolved = await resolveEntityId(rawId, env2);
24348
+ spinner.start("Resolving record ID");
24349
+ const resolved = await resolveEntityId(rawId, env2, orgId);
24201
24350
  if (resolved.error || !resolved.data) {
24202
- spinner.fail("Entity not found");
24203
- console.log(source_default.red("Error:"), resolved.error || `No entity matched "${rawId}"`);
24351
+ spinner.fail("Record not found");
24352
+ console.log(source_default.red("Error:"), resolved.error || `No record matched "${rawId}"`);
24204
24353
  process.exit(1);
24205
24354
  }
24206
24355
  const id = resolved.data;
24207
- spinner.text = "Updating entity";
24208
- const { data: result, error } = await updateEntity(id, data, env2, opts.status);
24356
+ spinner.text = "Updating record";
24357
+ const { data: result, error } = await updateEntity(id, data, env2, opts.status, orgId);
24209
24358
  if (error) {
24210
- spinner.fail("Failed to update entity");
24359
+ spinner.fail("Failed to update record");
24211
24360
  console.log(source_default.red("Error:"), error);
24212
24361
  process.exit(1);
24213
24362
  }
24214
- spinner.succeed("Entity updated");
24363
+ spinner.succeed("Record updated");
24215
24364
  if (opts.json) {
24216
24365
  console.log(JSON.stringify(result, null, 2));
24217
24366
  } else {
24218
24367
  console.log();
24219
- console.log(source_default.green(" Entity updated successfully"));
24368
+ console.log(source_default.green(" Record updated successfully"));
24220
24369
  console.log();
24221
24370
  }
24222
24371
  });
24223
- entitiesCommand.command("delete <id>").description("Delete an entity").option("--env <environment>", "Environment (development|production)", "development").option("--yes", "Skip confirmation").option("--json", "Output raw JSON").action(async (rawId, opts) => {
24372
+ entitiesCommand.command("delete <id>").description("Delete a record").option("--env <environment>", "Environment (development|production)", "development").option("--yes", "Skip confirmation").option("--json", "Output raw JSON").action(async (rawId, opts) => {
24224
24373
  await ensureAuth();
24225
24374
  const spinner = ora();
24226
24375
  const env2 = opts.env;
24376
+ const orgId = getOrgId();
24227
24377
  const jsonMode = !!opts.json;
24228
24378
  if (!jsonMode)
24229
- spinner.start("Resolving entity ID");
24230
- const resolved = await resolveEntityId(rawId, env2);
24379
+ spinner.start("Resolving record ID");
24380
+ const resolved = await resolveEntityId(rawId, env2, orgId);
24231
24381
  if (resolved.error || !resolved.data) {
24232
24382
  if (jsonMode) {
24233
- console.log(JSON.stringify({ success: false, error: resolved.error || `No entity matched "${rawId}"` }));
24383
+ console.log(JSON.stringify({ success: false, error: resolved.error || `No record matched "${rawId}"` }));
24234
24384
  } else {
24235
- spinner.fail("Entity not found");
24236
- console.log(source_default.red("Error:"), resolved.error || `No entity matched "${rawId}"`);
24385
+ spinner.fail("Record not found");
24386
+ console.log(source_default.red("Error:"), resolved.error || `No record matched "${rawId}"`);
24237
24387
  }
24238
24388
  process.exit(1);
24239
24389
  }
24240
24390
  const id = resolved.data;
24241
24391
  if (!jsonMode)
24242
- spinner.text = "Fetching entity";
24243
- const { data, error: fetchError } = await queryEntity(id, env2);
24392
+ spinner.text = "Fetching record";
24393
+ const { data, error: fetchError } = await queryEntity(id, env2, orgId);
24244
24394
  if (fetchError || !data) {
24245
24395
  if (jsonMode) {
24246
- console.log(JSON.stringify({ success: false, error: fetchError || "Entity not found" }));
24396
+ console.log(JSON.stringify({ success: false, error: fetchError || "Record not found" }));
24247
24397
  } else {
24248
- spinner.fail("Failed to fetch entity");
24249
- console.log(source_default.red("Error:"), fetchError || "Entity not found");
24398
+ spinner.fail("Failed to fetch record");
24399
+ console.log(source_default.red("Error:"), fetchError || "Record not found");
24250
24400
  }
24251
24401
  process.exit(1);
24252
24402
  }
24253
24403
  if (!jsonMode)
24254
- spinner.succeed("Entity loaded");
24404
+ spinner.succeed("Record loaded");
24255
24405
  const result = data;
24256
24406
  const entity = result.entity;
24257
24407
  const entityType = result.entityType;
@@ -24269,7 +24419,7 @@ entitiesCommand.command("delete <id>").description("Delete an entity").option("-
24269
24419
  }
24270
24420
  if (!opts.yes && !jsonMode && isInteractive2()) {
24271
24421
  const confirmed = await esm_default2({
24272
- message: "Are you sure you want to delete this entity?",
24422
+ message: "Are you sure you want to delete this record?",
24273
24423
  default: false
24274
24424
  });
24275
24425
  if (!confirmed) {
@@ -24278,13 +24428,13 @@ entitiesCommand.command("delete <id>").description("Delete an entity").option("-
24278
24428
  }
24279
24429
  }
24280
24430
  if (!jsonMode)
24281
- spinner.start("Deleting entity");
24282
- const { error } = await removeEntity(id, env2);
24431
+ spinner.start("Deleting record");
24432
+ const { error } = await removeEntity(id, env2, orgId);
24283
24433
  if (error) {
24284
24434
  if (jsonMode) {
24285
24435
  console.log(JSON.stringify({ success: false, error }));
24286
24436
  } else {
24287
- spinner.fail("Failed to delete entity");
24437
+ spinner.fail("Failed to delete record");
24288
24438
  console.log(source_default.red("Error:"), error);
24289
24439
  }
24290
24440
  process.exit(1);
@@ -24292,18 +24442,19 @@ entitiesCommand.command("delete <id>").description("Delete an entity").option("-
24292
24442
  if (jsonMode) {
24293
24443
  console.log(JSON.stringify({ success: true, id }));
24294
24444
  } else {
24295
- spinner.succeed("Entity deleted");
24445
+ spinner.succeed("Record deleted");
24296
24446
  console.log();
24297
24447
  }
24298
24448
  });
24299
- entitiesCommand.command("search <type> <query>").description("Search entities").option("--env <environment>", "Environment (development|production)", "development").option("--limit <n>", "Maximum results", "25").option("--json", "Output raw JSON").action(async (type, query, opts) => {
24449
+ entitiesCommand.command("search <type> <query>").description("Search records").option("--env <environment>", "Environment (development|production)", "development").option("--limit <n>", "Maximum results", "25").option("--json", "Output raw JSON").action(async (type, query, opts) => {
24300
24450
  await ensureAuth();
24301
24451
  const spinner = ora();
24302
24452
  const env2 = opts.env;
24453
+ const orgId = getOrgId();
24303
24454
  spinner.start(`Searching ${type} for "${query}"`);
24304
24455
  const [searchResult, typeResult] = await Promise.all([
24305
- searchEntities(type, query, env2, parseInt(opts.limit, 10)),
24306
- queryEntityTypeBySlug(type, env2)
24456
+ searchEntities(type, query, env2, parseInt(opts.limit, 10), orgId),
24457
+ queryEntityTypeBySlug(type, env2, orgId)
24307
24458
  ]);
24308
24459
  if (searchResult.error || !searchResult.data) {
24309
24460
  spinner.fail("Search failed");
@@ -25298,7 +25449,7 @@ async function setIntegrationStatus(provider, env2, status) {
25298
25449
  }
25299
25450
 
25300
25451
  // src/cli/commands/integration.ts
25301
- var VALID_PROVIDERS = ["airtable", "resend"];
25452
+ var VALID_PROVIDERS = ["airtable", "resend", "flow"];
25302
25453
  async function ensureAuth3() {
25303
25454
  const cwd = process.cwd();
25304
25455
  const nonInteractive = !isInteractive2();
@@ -25351,6 +25502,8 @@ function getProviderHelp(provider) {
25351
25502
  return `Usage: struere integration airtable --token <pat> [--base-id <id>] [--test]`;
25352
25503
  case "resend":
25353
25504
  return `Usage: struere integration resend --from-email <email> [--from-name <name>] [--reply-to <email>]`;
25505
+ case "flow":
25506
+ return `Usage: struere integration flow --api-url <url> --api-key <key> --secret-key <secret> [--return-url <url>]`;
25354
25507
  default:
25355
25508
  return "";
25356
25509
  }
@@ -25378,9 +25531,23 @@ function buildConfigFromOpts(provider, opts) {
25378
25531
  return null;
25379
25532
  return config;
25380
25533
  }
25534
+ if (provider === "flow") {
25535
+ const config = {};
25536
+ if (opts.apiUrl)
25537
+ config.apiUrl = opts.apiUrl;
25538
+ if (opts.apiKey)
25539
+ config.apiKey = opts.apiKey;
25540
+ if (opts.secretKey)
25541
+ config.secretKey = opts.secretKey;
25542
+ if (opts.returnUrl)
25543
+ config.returnUrl = opts.returnUrl;
25544
+ if (Object.keys(config).length === 0)
25545
+ return null;
25546
+ return config;
25547
+ }
25381
25548
  return null;
25382
25549
  }
25383
- var integrationCommand = new Command("integration").description("Manage integrations").argument("[provider]", "Integration provider (airtable, resend)").option("--env <environment>", "Environment (development|production)", "development").option("--token <pat>", "Personal access token (airtable)").option("--base-id <id>", "Default base ID (airtable)").option("--from-email <email>", "From email address (resend)").option("--from-name <name>", "From display name (resend)").option("--reply-to <email>", "Reply-to address (resend)").option("--test", "Test the connection after saving").option("--remove", "Remove integration config").option("--enable", "Enable integration").option("--disable", "Disable integration").option("--status", "Show current config status").option("--yes", "Skip confirmation prompts").option("--json", "Output raw JSON").action(async (provider, opts) => {
25550
+ var integrationCommand = new Command("integration").description("Manage integrations").argument("[provider]", "Integration provider (airtable, resend, flow)").option("--env <environment>", "Environment (development|production)", "development").option("--token <pat>", "Personal access token (airtable)").option("--base-id <id>", "Default base ID (airtable)").option("--from-email <email>", "From email address (resend)").option("--from-name <name>", "From display name (resend)").option("--reply-to <email>", "Reply-to address (resend)").option("--api-url <url>", "API URL (flow)").option("--api-key <key>", "API key (flow)").option("--secret-key <secret>", "Secret key (flow)").option("--return-url <url>", "Return URL after payment (flow)").option("--test", "Test the connection after saving").option("--remove", "Remove integration config").option("--enable", "Enable integration").option("--disable", "Disable integration").option("--status", "Show current config status").option("--yes", "Skip confirmation prompts").option("--json", "Output raw JSON").action(async (provider, opts) => {
25384
25551
  await ensureAuth3();
25385
25552
  const env2 = opts.env;
25386
25553
  const out = createOutput();
@@ -25555,10 +25722,154 @@ var integrationCommand = new Command("integration").description("Manage integrat
25555
25722
  }
25556
25723
  console.log();
25557
25724
  });
25725
+
25726
+ // src/cli/commands/compile-prompt.ts
25727
+ var compilePromptCommand = new Command("compile-prompt").description("Compile and preview an agent's system prompt after template processing").argument("<agent-slug>", "Agent slug to compile prompt for").option("--env <env>", "Environment: development | production", "development").option("--message <msg>", "Sample message for template context").option("--channel <channel>", "Sample channel (whatsapp, widget, api, dashboard)").option("--param <key=value...>", "Custom thread param (repeatable)", (val, acc) => {
25728
+ acc.push(val);
25729
+ return acc;
25730
+ }, []).option("--json", "Output full JSON (raw + compiled + context)").option("--raw", "Show raw uncompiled template instead of compiled").action(async (agentSlug, options) => {
25731
+ const spinner = ora();
25732
+ const cwd = process.cwd();
25733
+ const nonInteractive = !isInteractive2();
25734
+ const jsonMode = !!options.json;
25735
+ if (!hasProject(cwd)) {
25736
+ if (nonInteractive) {
25737
+ if (jsonMode) {
25738
+ console.log(JSON.stringify({ success: false, error: "No struere.json found" }));
25739
+ } else {
25740
+ console.log(source_default.red("No struere.json found. Run struere init first."));
25741
+ }
25742
+ process.exit(1);
25743
+ }
25744
+ console.log(source_default.yellow("No struere.json found - initializing project..."));
25745
+ console.log();
25746
+ const success = await runInit(cwd);
25747
+ if (!success) {
25748
+ process.exit(1);
25749
+ }
25750
+ console.log();
25751
+ }
25752
+ const project = loadProject(cwd);
25753
+ if (!project) {
25754
+ if (jsonMode) {
25755
+ console.log(JSON.stringify({ success: false, error: "Failed to load struere.json" }));
25756
+ } else {
25757
+ console.log(source_default.red("Failed to load struere.json"));
25758
+ }
25759
+ process.exit(1);
25760
+ }
25761
+ let credentials = loadCredentials();
25762
+ const apiKey = getApiKey();
25763
+ if (!credentials && !apiKey) {
25764
+ if (nonInteractive) {
25765
+ if (jsonMode) {
25766
+ console.log(JSON.stringify({ success: false, error: "Not authenticated. Set STRUERE_API_KEY or run struere login." }));
25767
+ } else {
25768
+ console.log(source_default.red("Not authenticated. Set STRUERE_API_KEY or run struere login."));
25769
+ }
25770
+ process.exit(1);
25771
+ }
25772
+ console.log(source_default.yellow("Not logged in - authenticating..."));
25773
+ console.log();
25774
+ credentials = await performLogin();
25775
+ if (!credentials) {
25776
+ console.log(source_default.red("Authentication failed"));
25777
+ process.exit(1);
25778
+ }
25779
+ console.log();
25780
+ }
25781
+ const threadMetadata = {};
25782
+ for (const param of options.param) {
25783
+ const eqIndex = param.indexOf("=");
25784
+ if (eqIndex === -1) {
25785
+ if (jsonMode) {
25786
+ console.log(JSON.stringify({ success: false, error: `Invalid param format: ${param}. Use key=value.` }));
25787
+ } else {
25788
+ console.log(source_default.red(`Invalid param format: ${param}. Use key=value.`));
25789
+ }
25790
+ process.exit(1);
25791
+ }
25792
+ const key = param.slice(0, eqIndex);
25793
+ const value = param.slice(eqIndex + 1);
25794
+ threadMetadata[key] = value;
25795
+ }
25796
+ const environment = options.env;
25797
+ if (!jsonMode) {
25798
+ spinner.start(`Compiling prompt for ${source_default.cyan(agentSlug)} (${environment})`);
25799
+ }
25800
+ const doCompile = async () => {
25801
+ return compilePrompt({
25802
+ slug: agentSlug,
25803
+ environment,
25804
+ message: options.message,
25805
+ channel: options.channel,
25806
+ threadMetadata: Object.keys(threadMetadata).length > 0 ? threadMetadata : undefined
25807
+ });
25808
+ };
25809
+ let { result, error } = await doCompile();
25810
+ if (error && isAuthError(error) && !nonInteractive) {
25811
+ if (!jsonMode)
25812
+ spinner.fail("Session expired - re-authenticating...");
25813
+ clearCredentials();
25814
+ credentials = await performLogin();
25815
+ if (!credentials) {
25816
+ if (jsonMode) {
25817
+ console.log(JSON.stringify({ success: false, error: "Authentication failed" }));
25818
+ } else {
25819
+ console.log(source_default.red("Authentication failed"));
25820
+ }
25821
+ process.exit(1);
25822
+ }
25823
+ const retry = await doCompile();
25824
+ result = retry.result;
25825
+ error = retry.error;
25826
+ if (!jsonMode && !error)
25827
+ spinner.succeed("Compiled prompt");
25828
+ }
25829
+ if (error) {
25830
+ if (jsonMode) {
25831
+ console.log(JSON.stringify({ success: false, error }));
25832
+ } else {
25833
+ spinner.fail("Failed to compile prompt");
25834
+ console.log(source_default.red("Error:"), error);
25835
+ }
25836
+ process.exit(1);
25837
+ }
25838
+ if (!result) {
25839
+ if (jsonMode) {
25840
+ console.log(JSON.stringify({ success: false, error: "No result returned" }));
25841
+ } else {
25842
+ spinner.fail("No result returned");
25843
+ }
25844
+ process.exit(1);
25845
+ }
25846
+ if (!jsonMode)
25847
+ spinner.succeed("Compiled prompt");
25848
+ if (jsonMode) {
25849
+ console.log(JSON.stringify({
25850
+ success: true,
25851
+ raw: result.raw,
25852
+ compiled: result.compiled,
25853
+ context: result.context
25854
+ }, null, 2));
25855
+ } else if (options.raw) {
25856
+ console.log();
25857
+ console.log(source_default.bold("Raw System Prompt"));
25858
+ console.log(source_default.gray("\u2500".repeat(60)));
25859
+ console.log(result.raw);
25860
+ console.log(source_default.gray("\u2500".repeat(60)));
25861
+ } else {
25862
+ console.log();
25863
+ console.log(source_default.bold("Compiled System Prompt"));
25864
+ console.log(source_default.gray("\u2500".repeat(60)));
25865
+ console.log(result.compiled);
25866
+ console.log(source_default.gray("\u2500".repeat(60)));
25867
+ }
25868
+ });
25558
25869
  // package.json
25559
25870
  var package_default = {
25560
25871
  name: "struere",
25561
- version: "0.9.5",
25872
+ version: "0.9.7",
25562
25873
  description: "Build, test, and deploy AI agents",
25563
25874
  keywords: [
25564
25875
  "ai",
@@ -25673,4 +25984,5 @@ program.addCommand(docsCommand);
25673
25984
  program.addCommand(evalCommand);
25674
25985
  program.addCommand(templatesCommand);
25675
25986
  program.addCommand(integrationCommand);
25987
+ program.addCommand(compilePromptCommand);
25676
25988
  program.parse();