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.
- package/dist/bin/struere.js +439 -127
- package/dist/cli/commands/add.d.ts.map +1 -1
- package/dist/cli/commands/compile-prompt.d.ts +3 -0
- package/dist/cli/commands/compile-prompt.d.ts.map +1 -0
- package/dist/cli/commands/entities.d.ts.map +1 -1
- package/dist/cli/commands/integration.d.ts.map +1 -1
- package/dist/cli/index.js +442 -127
- package/dist/cli/utils/convex.d.ts +18 -0
- package/dist/cli/utils/convex.d.ts.map +1 -1
- package/dist/cli/utils/entities.d.ts +9 -9
- package/dist/cli/utils/entities.d.ts.map +1 -1
- package/dist/cli/utils/extractor.d.ts +2 -0
- package/dist/cli/utils/extractor.d.ts.map +1 -1
- package/dist/cli/utils/plugin.d.ts +1 -1
- package/dist/cli/utils/plugin.d.ts.map +1 -1
- package/dist/define/entityType.d.ts +1 -1
- package/dist/define/entityType.d.ts.map +1 -1
- package/dist/define/index.d.ts +1 -1
- package/dist/define/index.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -6
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/bin/struere.js
CHANGED
|
@@ -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 {
|
|
20215
|
+
return `import { defineData } from 'struere'
|
|
20106
20216
|
|
|
20107
|
-
export default
|
|
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
|
|
20524
|
-
if (!config.name) throw new Error('
|
|
20525
|
-
if (!config.slug) throw new Error('
|
|
20526
|
-
if (!config.schema) throw new Error('
|
|
20527
|
-
if (config.schema.type !== 'object') throw new Error('
|
|
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,
|
|
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
|
|
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(`###
|
|
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,
|
|
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
|
|
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/ #
|
|
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\\|
|
|
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
|
|
21046
|
-
lines.push("| `struere
|
|
21047
|
-
lines.push("| `struere
|
|
21048
|
-
lines.push("| `struere
|
|
21049
|
-
lines.push("| `struere
|
|
21050
|
-
lines.push("| `struere
|
|
21051
|
-
lines.push("| `struere
|
|
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,
|
|
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(`- [
|
|
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(`- [
|
|
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("
|
|
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: "
|
|
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}
|
|
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("
|
|
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}
|
|
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}
|
|
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("
|
|
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,
|
|
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
|
|
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("
|
|
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("
|
|
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
|
|
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}
|
|
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(
|
|
23180
|
-
getSyncState(
|
|
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("
|
|
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
|
|
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 {
|
|
23529
|
+
return `import { defineData } from 'struere'
|
|
23394
23530
|
|
|
23395
|
-
export default
|
|
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("
|
|
23997
|
-
entitiesCommand.command("types").description("List available
|
|
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
|
-
|
|
24002
|
-
|
|
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
|
|
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("
|
|
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
|
|
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
|
-
|
|
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}
|
|
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}
|
|
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
|
|
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
|
-
|
|
24067
|
-
|
|
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("
|
|
24070
|
-
console.log(source_default.red("Error:"), resolved.error || `No
|
|
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
|
|
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
|
|
24078
|
-
console.log(source_default.red("Error:"), error || "
|
|
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("
|
|
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
|
|
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(`
|
|
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("
|
|
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}
|
|
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
|
|
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(`
|
|
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
|
|
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
|
|
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("
|
|
24203
|
-
console.log(source_default.red("Error:"), resolved.error || `No
|
|
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
|
|
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
|
|
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("
|
|
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("
|
|
24368
|
+
console.log(source_default.green(" Record updated successfully"));
|
|
24220
24369
|
console.log();
|
|
24221
24370
|
}
|
|
24222
24371
|
});
|
|
24223
|
-
entitiesCommand.command("delete <id>").description("Delete
|
|
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
|
|
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
|
|
24383
|
+
console.log(JSON.stringify({ success: false, error: resolved.error || `No record matched "${rawId}"` }));
|
|
24234
24384
|
} else {
|
|
24235
|
-
spinner.fail("
|
|
24236
|
-
console.log(source_default.red("Error:"), resolved.error || `No
|
|
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
|
|
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 || "
|
|
24396
|
+
console.log(JSON.stringify({ success: false, error: fetchError || "Record not found" }));
|
|
24247
24397
|
} else {
|
|
24248
|
-
spinner.fail("Failed to fetch
|
|
24249
|
-
console.log(source_default.red("Error:"), fetchError || "
|
|
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("
|
|
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
|
|
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
|
|
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
|
|
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("
|
|
24445
|
+
spinner.succeed("Record deleted");
|
|
24296
24446
|
console.log();
|
|
24297
24447
|
}
|
|
24298
24448
|
});
|
|
24299
|
-
entitiesCommand.command("search <type> <query>").description("Search
|
|
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.
|
|
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();
|