struere 0.9.6 → 0.9.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/struere.js +623 -194
- 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/dev.d.ts.map +1 -1
- package/dist/cli/commands/entities.d.ts.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/integration.d.ts.map +1 -1
- package/dist/cli/commands/org.d.ts +5 -0
- package/dist/cli/commands/org.d.ts.map +1 -0
- package/dist/cli/index.js +1027 -591
- package/dist/cli/utils/__tests__/plugin.test.d.ts +2 -0
- package/dist/cli/utils/__tests__/plugin.test.d.ts.map +1 -0
- package/dist/cli/utils/config.d.ts +2 -2
- package/dist/cli/utils/config.d.ts.map +1 -1
- package/dist/cli/utils/convex.d.ts +24 -1
- package/dist/cli/utils/convex.d.ts.map +1 -1
- package/dist/cli/utils/entities.d.ts.map +1 -1
- package/dist/cli/utils/evals.d.ts.map +1 -1
- package/dist/cli/utils/extractor.d.ts +3 -0
- package/dist/cli/utils/extractor.d.ts.map +1 -1
- package/dist/cli/utils/integrations.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/cli/utils/whatsapp.d.ts +4 -4
- package/dist/cli/utils/whatsapp.d.ts.map +1 -1
- package/dist/define/__tests__/agent.test.d.ts +2 -0
- package/dist/define/__tests__/agent.test.d.ts.map +1 -0
- package/dist/define/__tests__/entityType.test.d.ts +2 -0
- package/dist/define/__tests__/entityType.test.d.ts.map +1 -0
- package/dist/define/__tests__/role.test.d.ts +2 -0
- package/dist/define/__tests__/role.test.d.ts.map +1 -0
- package/dist/define/__tests__/trigger.test.d.ts +2 -0
- package/dist/define/__tests__/trigger.test.d.ts.map +1 -0
- package/dist/define/entityType.d.ts +1 -1
- package/dist/define/entityType.d.ts.map +1 -1
- package/dist/define/index.d.ts +1 -2
- package/dist/define/index.d.ts.map +1 -1
- package/dist/define/tools.d.ts +1 -0
- package/dist/define/tools.d.ts.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -35
- package/dist/types.d.ts +58 -21
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/bin/struere.js
CHANGED
|
@@ -19463,11 +19463,13 @@ function getApiKey() {
|
|
|
19463
19463
|
return process.env.STRUERE_API_KEY || null;
|
|
19464
19464
|
}
|
|
19465
19465
|
|
|
19466
|
-
// src/cli/utils/
|
|
19466
|
+
// src/cli/utils/config.ts
|
|
19467
19467
|
var CONVEX_URL = process.env.STRUERE_CONVEX_URL || "https://rapid-wildebeest-172.convex.cloud";
|
|
19468
19468
|
function getSiteUrl() {
|
|
19469
19469
|
return CONVEX_URL.replace(".cloud", ".site");
|
|
19470
19470
|
}
|
|
19471
|
+
|
|
19472
|
+
// src/cli/utils/convex.ts
|
|
19471
19473
|
async function refreshToken() {
|
|
19472
19474
|
const credentials = loadCredentials();
|
|
19473
19475
|
if (!credentials?.sessionId)
|
|
@@ -19492,6 +19494,38 @@ async function refreshToken() {
|
|
|
19492
19494
|
return null;
|
|
19493
19495
|
}
|
|
19494
19496
|
}
|
|
19497
|
+
async function createOrganization(token, name, slug) {
|
|
19498
|
+
const response = await fetch(`${CONVEX_URL}/api/action`, {
|
|
19499
|
+
method: "POST",
|
|
19500
|
+
headers: {
|
|
19501
|
+
"Content-Type": "application/json",
|
|
19502
|
+
Authorization: `Bearer ${token}`
|
|
19503
|
+
},
|
|
19504
|
+
body: JSON.stringify({
|
|
19505
|
+
path: "organizations:createFromCli",
|
|
19506
|
+
args: { name, slug }
|
|
19507
|
+
}),
|
|
19508
|
+
signal: AbortSignal.timeout(30000)
|
|
19509
|
+
});
|
|
19510
|
+
const text = await response.text();
|
|
19511
|
+
let json;
|
|
19512
|
+
try {
|
|
19513
|
+
json = JSON.parse(text);
|
|
19514
|
+
} catch {
|
|
19515
|
+
return { error: text || `HTTP ${response.status}` };
|
|
19516
|
+
}
|
|
19517
|
+
if (!response.ok) {
|
|
19518
|
+
const msg = json.errorData?.message || json.errorMessage || text;
|
|
19519
|
+
return { error: msg };
|
|
19520
|
+
}
|
|
19521
|
+
if (json.status === "success" && json.value) {
|
|
19522
|
+
return { organization: json.value };
|
|
19523
|
+
}
|
|
19524
|
+
if (json.status === "error") {
|
|
19525
|
+
return { error: json.errorData?.message || json.errorMessage || "Unknown error" };
|
|
19526
|
+
}
|
|
19527
|
+
return { error: `Unexpected response: ${text}` };
|
|
19528
|
+
}
|
|
19495
19529
|
async function listMyOrganizations(token) {
|
|
19496
19530
|
const response = await fetch(`${CONVEX_URL}/api/query`, {
|
|
19497
19531
|
method: "POST",
|
|
@@ -19710,6 +19744,115 @@ async function getSyncState(organizationId, environment) {
|
|
|
19710
19744
|
}
|
|
19711
19745
|
return { error: `Unexpected response: ${JSON.stringify(result)}` };
|
|
19712
19746
|
}
|
|
19747
|
+
async function compilePrompt(options) {
|
|
19748
|
+
const credentials = loadCredentials();
|
|
19749
|
+
const apiKey = getApiKey();
|
|
19750
|
+
if (apiKey && !credentials?.token) {
|
|
19751
|
+
const siteUrl = getSiteUrl();
|
|
19752
|
+
try {
|
|
19753
|
+
const response2 = await fetch(`${siteUrl}/v1/compile-prompt`, {
|
|
19754
|
+
method: "POST",
|
|
19755
|
+
headers: {
|
|
19756
|
+
"Content-Type": "application/json",
|
|
19757
|
+
Authorization: `Bearer ${apiKey}`
|
|
19758
|
+
},
|
|
19759
|
+
body: JSON.stringify({
|
|
19760
|
+
slug: options.slug,
|
|
19761
|
+
message: options.message,
|
|
19762
|
+
channel: options.channel,
|
|
19763
|
+
threadMetadata: options.threadMetadata
|
|
19764
|
+
}),
|
|
19765
|
+
signal: AbortSignal.timeout(30000)
|
|
19766
|
+
});
|
|
19767
|
+
const text2 = await response2.text();
|
|
19768
|
+
let json2;
|
|
19769
|
+
try {
|
|
19770
|
+
json2 = JSON.parse(text2);
|
|
19771
|
+
} catch {
|
|
19772
|
+
return { error: text2 || `HTTP ${response2.status}` };
|
|
19773
|
+
}
|
|
19774
|
+
if (!response2.ok) {
|
|
19775
|
+
return { error: json2.error || text2 };
|
|
19776
|
+
}
|
|
19777
|
+
return { result: json2 };
|
|
19778
|
+
} catch (err) {
|
|
19779
|
+
if (err instanceof DOMException && err.name === "TimeoutError") {
|
|
19780
|
+
return { error: "Request timed out after 30s" };
|
|
19781
|
+
}
|
|
19782
|
+
return { error: `Network error: ${err instanceof Error ? err.message : String(err)}` };
|
|
19783
|
+
}
|
|
19784
|
+
}
|
|
19785
|
+
if (credentials?.sessionId) {
|
|
19786
|
+
await refreshToken();
|
|
19787
|
+
}
|
|
19788
|
+
const freshCredentials = loadCredentials();
|
|
19789
|
+
const token = apiKey || freshCredentials?.token;
|
|
19790
|
+
if (!token) {
|
|
19791
|
+
return { error: "Not authenticated" };
|
|
19792
|
+
}
|
|
19793
|
+
const agentResponse = await fetch(`${CONVEX_URL}/api/query`, {
|
|
19794
|
+
method: "POST",
|
|
19795
|
+
headers: {
|
|
19796
|
+
"Content-Type": "application/json",
|
|
19797
|
+
Authorization: `Bearer ${token}`
|
|
19798
|
+
},
|
|
19799
|
+
body: JSON.stringify({
|
|
19800
|
+
path: "agents:getBySlug",
|
|
19801
|
+
args: { slug: options.slug }
|
|
19802
|
+
})
|
|
19803
|
+
});
|
|
19804
|
+
if (!agentResponse.ok) {
|
|
19805
|
+
return { error: await agentResponse.text() };
|
|
19806
|
+
}
|
|
19807
|
+
const agentResult = await agentResponse.json();
|
|
19808
|
+
if (agentResult.status === "error") {
|
|
19809
|
+
return { error: agentResult.errorMessage || "Failed to look up agent" };
|
|
19810
|
+
}
|
|
19811
|
+
if (!agentResult.value) {
|
|
19812
|
+
return { error: `Agent not found: ${options.slug}` };
|
|
19813
|
+
}
|
|
19814
|
+
const response = await fetch(`${CONVEX_URL}/api/action`, {
|
|
19815
|
+
method: "POST",
|
|
19816
|
+
headers: {
|
|
19817
|
+
"Content-Type": "application/json",
|
|
19818
|
+
Authorization: `Bearer ${token}`
|
|
19819
|
+
},
|
|
19820
|
+
body: JSON.stringify({
|
|
19821
|
+
path: "agents:compileSystemPrompt",
|
|
19822
|
+
args: {
|
|
19823
|
+
agentId: agentResult.value._id,
|
|
19824
|
+
environment: options.environment,
|
|
19825
|
+
sampleContext: {
|
|
19826
|
+
message: options.message,
|
|
19827
|
+
channel: options.channel,
|
|
19828
|
+
threadMetadata: options.threadMetadata
|
|
19829
|
+
}
|
|
19830
|
+
}
|
|
19831
|
+
}),
|
|
19832
|
+
signal: AbortSignal.timeout(30000)
|
|
19833
|
+
});
|
|
19834
|
+
const text = await response.text();
|
|
19835
|
+
let json;
|
|
19836
|
+
try {
|
|
19837
|
+
json = JSON.parse(text);
|
|
19838
|
+
} catch {
|
|
19839
|
+
return { error: text || `HTTP ${response.status}` };
|
|
19840
|
+
}
|
|
19841
|
+
if (!response.ok) {
|
|
19842
|
+
const msg = json.errorData?.message || json.errorMessage || text;
|
|
19843
|
+
return { error: msg };
|
|
19844
|
+
}
|
|
19845
|
+
if (json.status === "success" && json.value) {
|
|
19846
|
+
return { result: json.value };
|
|
19847
|
+
}
|
|
19848
|
+
if (json.status === "success" && json.value === null) {
|
|
19849
|
+
return { error: `Agent not found or no config for environment: ${options.environment}` };
|
|
19850
|
+
}
|
|
19851
|
+
if (json.status === "error") {
|
|
19852
|
+
return { error: json.errorData?.message || json.errorMessage || "Unknown error from Convex" };
|
|
19853
|
+
}
|
|
19854
|
+
return { error: `Unexpected response: ${text}` };
|
|
19855
|
+
}
|
|
19713
19856
|
async function getPullState(organizationId, environment = "development") {
|
|
19714
19857
|
const credentials = loadCredentials();
|
|
19715
19858
|
const apiKey = getApiKey();
|
|
@@ -19802,6 +19945,7 @@ async function browserLoginInternal(spinner) {
|
|
|
19802
19945
|
const authPromise = new Promise((resolve, reject) => {
|
|
19803
19946
|
const server = Bun.serve({
|
|
19804
19947
|
port: AUTH_CALLBACK_PORT,
|
|
19948
|
+
hostname: "127.0.0.1",
|
|
19805
19949
|
async fetch(req) {
|
|
19806
19950
|
const url = new URL(req.url);
|
|
19807
19951
|
if (url.pathname === "/callback") {
|
|
@@ -19870,7 +20014,7 @@ async function browserLoginInternal(spinner) {
|
|
|
19870
20014
|
if (organizations.length > 0) {
|
|
19871
20015
|
console.log(source_default.gray("Organizations:"), organizations.map((o) => o.name).join(", "));
|
|
19872
20016
|
} else {
|
|
19873
|
-
console.log(source_default.yellow("No organizations found.
|
|
20017
|
+
console.log(source_default.yellow("No organizations found. Run"), source_default.cyan("struere org create"), source_default.yellow("to create one."));
|
|
19874
20018
|
}
|
|
19875
20019
|
console.log();
|
|
19876
20020
|
return credentials;
|
|
@@ -20102,9 +20246,9 @@ logs/
|
|
|
20102
20246
|
}
|
|
20103
20247
|
function getEntityTypeTs(name, slug) {
|
|
20104
20248
|
const displayName = name.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
20105
|
-
return `import {
|
|
20249
|
+
return `import { defineData } from 'struere'
|
|
20106
20250
|
|
|
20107
|
-
export default
|
|
20251
|
+
export default defineData({
|
|
20108
20252
|
name: "${displayName}",
|
|
20109
20253
|
slug: "${slug}",
|
|
20110
20254
|
schema: {
|
|
@@ -20182,7 +20326,7 @@ export default defineTools([
|
|
|
20182
20326
|
},
|
|
20183
20327
|
},
|
|
20184
20328
|
},
|
|
20185
|
-
handler: async (args, context, fetch) => {
|
|
20329
|
+
handler: async (args, context, struere, fetch) => {
|
|
20186
20330
|
const timezone = (args.timezone as string) || 'UTC'
|
|
20187
20331
|
const now = new Date()
|
|
20188
20332
|
return {
|
|
@@ -20211,7 +20355,7 @@ export default defineTools([
|
|
|
20211
20355
|
},
|
|
20212
20356
|
required: ['message'],
|
|
20213
20357
|
},
|
|
20214
|
-
handler: async (args, context, fetch) => {
|
|
20358
|
+
handler: async (args, context, struere, fetch) => {
|
|
20215
20359
|
const webhookUrl = process.env.SLACK_WEBHOOK_URL
|
|
20216
20360
|
if (!webhookUrl) {
|
|
20217
20361
|
return { success: false, error: 'SLACK_WEBHOOK_URL not configured' }
|
|
@@ -20520,11 +20664,11 @@ function validateObjectProperties(schema, path) {
|
|
|
20520
20664
|
}
|
|
20521
20665
|
}
|
|
20522
20666
|
|
|
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('
|
|
20667
|
+
function defineData(config) {
|
|
20668
|
+
if (!config.name) throw new Error('Data type name is required')
|
|
20669
|
+
if (!config.slug) throw new Error('Data type slug is required')
|
|
20670
|
+
if (!config.schema) throw new Error('Data type schema is required')
|
|
20671
|
+
if (config.schema.type !== 'object') throw new Error('Data type schema must be an object type')
|
|
20528
20672
|
if (config.schema.properties) {
|
|
20529
20673
|
for (const [key, value] of Object.entries(config.schema.properties)) {
|
|
20530
20674
|
validateObjectProperties(value, key)
|
|
@@ -20552,6 +20696,15 @@ function defineTrigger(config) {
|
|
|
20552
20696
|
if (!action.tool) throw new Error('Trigger action tool is required')
|
|
20553
20697
|
if (!action.args || typeof action.args !== 'object') throw new Error('Trigger action args must be an object')
|
|
20554
20698
|
}
|
|
20699
|
+
if (config.schedule) {
|
|
20700
|
+
if (config.schedule.delay !== undefined && config.schedule.at !== undefined) throw new Error('Trigger schedule cannot have both "delay" and "at"')
|
|
20701
|
+
if (config.schedule.delay !== undefined && typeof config.schedule.delay !== 'number') throw new Error('Trigger schedule.delay must be a number')
|
|
20702
|
+
if (config.schedule.at !== undefined && typeof config.schedule.at !== 'string') throw new Error('Trigger schedule.at must be a string')
|
|
20703
|
+
}
|
|
20704
|
+
if (config.retry) {
|
|
20705
|
+
if (config.retry.maxAttempts !== undefined && (typeof config.retry.maxAttempts !== 'number' || config.retry.maxAttempts < 1)) throw new Error('Trigger retry.maxAttempts must be a positive number')
|
|
20706
|
+
if (config.retry.backoffMs !== undefined && (typeof config.retry.backoffMs !== 'number' || config.retry.backoffMs < 0)) throw new Error('Trigger retry.backoffMs must be a non-negative number')
|
|
20707
|
+
}
|
|
20555
20708
|
return config
|
|
20556
20709
|
}
|
|
20557
20710
|
|
|
@@ -20582,24 +20735,7 @@ function defineTools(tools) {
|
|
|
20582
20735
|
})
|
|
20583
20736
|
}
|
|
20584
20737
|
|
|
20585
|
-
|
|
20586
|
-
const defaultConfig = {
|
|
20587
|
-
port: 3000,
|
|
20588
|
-
host: 'localhost',
|
|
20589
|
-
cors: { origins: ['http://localhost:3000'], credentials: true },
|
|
20590
|
-
logging: { level: 'info', format: 'pretty' },
|
|
20591
|
-
auth: { type: 'none' },
|
|
20592
|
-
}
|
|
20593
|
-
return {
|
|
20594
|
-
...defaultConfig,
|
|
20595
|
-
...config,
|
|
20596
|
-
cors: config.cors ? { ...defaultConfig.cors, ...config.cors } : defaultConfig.cors,
|
|
20597
|
-
logging: config.logging ? { ...defaultConfig.logging, ...config.logging } : defaultConfig.logging,
|
|
20598
|
-
auth: config.auth ? { ...defaultConfig.auth, ...config.auth } : defaultConfig.auth,
|
|
20599
|
-
}
|
|
20600
|
-
}
|
|
20601
|
-
|
|
20602
|
-
export { defineAgent, defineRole, defineEntityType, defineTrigger, defineTools, defineConfig }
|
|
20738
|
+
export { defineAgent, defineRole, defineData, defineTrigger, defineTools }
|
|
20603
20739
|
`;
|
|
20604
20740
|
function registerStruerePlugin() {
|
|
20605
20741
|
if (registered)
|
|
@@ -20645,11 +20781,6 @@ var TYPE_DECLARATIONS = `declare module 'struere' {
|
|
|
20645
20781
|
export interface ToolContext {
|
|
20646
20782
|
conversationId: string
|
|
20647
20783
|
userId?: string
|
|
20648
|
-
state: {
|
|
20649
|
-
get<T>(key: string): Promise<T | undefined>
|
|
20650
|
-
set<T>(key: string, value: T): Promise<void>
|
|
20651
|
-
delete(key: string): Promise<void>
|
|
20652
|
-
}
|
|
20653
20784
|
}
|
|
20654
20785
|
|
|
20655
20786
|
export type ToolHandler = (params: Record<string, unknown>, context: ToolContext) => Promise<unknown>
|
|
@@ -20678,6 +20809,12 @@ var TYPE_DECLARATIONS = `declare module 'struere' {
|
|
|
20678
20809
|
model?: ModelConfig
|
|
20679
20810
|
tools?: string[]
|
|
20680
20811
|
firstMessageSuggestions?: string[]
|
|
20812
|
+
threadContextParams?: Array<{
|
|
20813
|
+
name: string
|
|
20814
|
+
type: 'string' | 'number' | 'boolean'
|
|
20815
|
+
required?: boolean
|
|
20816
|
+
description?: string
|
|
20817
|
+
}>
|
|
20681
20818
|
}
|
|
20682
20819
|
|
|
20683
20820
|
export interface JSONSchemaProperty {
|
|
@@ -20714,13 +20851,12 @@ var TYPE_DECLARATIONS = `declare module 'struere' {
|
|
|
20714
20851
|
resource: string
|
|
20715
20852
|
actions: string[]
|
|
20716
20853
|
effect: 'allow' | 'deny'
|
|
20717
|
-
priority?: number
|
|
20718
20854
|
}
|
|
20719
20855
|
|
|
20720
20856
|
export interface ScopeRuleConfig {
|
|
20721
20857
|
entityType: string
|
|
20722
20858
|
field: string
|
|
20723
|
-
operator: 'eq' | '
|
|
20859
|
+
operator: 'eq' | 'neq' | 'in' | 'contains'
|
|
20724
20860
|
value: string
|
|
20725
20861
|
}
|
|
20726
20862
|
|
|
@@ -20755,31 +20891,23 @@ var TYPE_DECLARATIONS = `declare module 'struere' {
|
|
|
20755
20891
|
condition?: Record<string, unknown>
|
|
20756
20892
|
}
|
|
20757
20893
|
actions: TriggerAction[]
|
|
20758
|
-
|
|
20759
|
-
|
|
20760
|
-
|
|
20761
|
-
|
|
20762
|
-
|
|
20763
|
-
cors?: {
|
|
20764
|
-
origins: string[]
|
|
20765
|
-
credentials?: boolean
|
|
20766
|
-
}
|
|
20767
|
-
logging?: {
|
|
20768
|
-
level: 'debug' | 'info' | 'warn' | 'error'
|
|
20769
|
-
format?: 'json' | 'pretty'
|
|
20894
|
+
schedule?: {
|
|
20895
|
+
delay?: number
|
|
20896
|
+
at?: string
|
|
20897
|
+
offset?: number
|
|
20898
|
+
cancelPrevious?: boolean
|
|
20770
20899
|
}
|
|
20771
|
-
|
|
20772
|
-
|
|
20773
|
-
|
|
20900
|
+
retry?: {
|
|
20901
|
+
maxAttempts?: number
|
|
20902
|
+
backoffMs?: number
|
|
20774
20903
|
}
|
|
20775
20904
|
}
|
|
20776
20905
|
|
|
20777
20906
|
export function defineAgent(config: AgentConfig): AgentConfig
|
|
20778
20907
|
export function defineRole(config: RoleConfig): RoleConfig
|
|
20779
|
-
export function
|
|
20908
|
+
export function defineData(config: EntityTypeConfig): EntityTypeConfig
|
|
20780
20909
|
export function defineTrigger(config: TriggerConfig): TriggerConfig
|
|
20781
20910
|
export function defineTools(tools: ToolDefinition[]): ToolReference[]
|
|
20782
|
-
export function defineConfig(config?: Partial<FrameworkConfig>): FrameworkConfig
|
|
20783
20911
|
}
|
|
20784
20912
|
`;
|
|
20785
20913
|
function generateTypeDeclarations(cwd) {
|
|
@@ -20950,7 +21078,7 @@ function buildProjectContext(orgName, resources) {
|
|
|
20950
21078
|
}
|
|
20951
21079
|
if (resources.entityTypes.length > 0) {
|
|
20952
21080
|
lines.push("");
|
|
20953
|
-
lines.push(`###
|
|
21081
|
+
lines.push(`### Data Types (${resources.entityTypes.length})`);
|
|
20954
21082
|
for (const et of resources.entityTypes) {
|
|
20955
21083
|
const fields = et.schema?.properties ? Object.keys(et.schema.properties).join(", ") : "";
|
|
20956
21084
|
const fieldStr = fields ? ` \u2014 fields: ${fields}` : "";
|
|
@@ -20986,7 +21114,7 @@ function buildDocument(projectContext) {
|
|
|
20986
21114
|
const lines = [];
|
|
20987
21115
|
lines.push(`# Struere Workspace`);
|
|
20988
21116
|
lines.push("");
|
|
20989
|
-
lines.push(`> This is a Struere workspace project. You define agents,
|
|
21117
|
+
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
21118
|
lines.push("");
|
|
20991
21119
|
lines.push(`## Agent Usage`);
|
|
20992
21120
|
lines.push("");
|
|
@@ -21006,7 +21134,7 @@ function buildDocument(projectContext) {
|
|
|
21006
21134
|
lines.push("");
|
|
21007
21135
|
lines.push("**JSON output**: Most commands support `--json` for structured output:");
|
|
21008
21136
|
lines.push("```bash");
|
|
21009
|
-
lines.push("struere
|
|
21137
|
+
lines.push("struere data list <type> --json");
|
|
21010
21138
|
lines.push("struere status --json");
|
|
21011
21139
|
lines.push("struere deploy --json --force");
|
|
21012
21140
|
lines.push("```");
|
|
@@ -21023,7 +21151,7 @@ function buildDocument(projectContext) {
|
|
|
21023
21151
|
lines.push("");
|
|
21024
21152
|
lines.push("```");
|
|
21025
21153
|
lines.push("agents/ # Agent definitions (one file per agent)");
|
|
21026
|
-
lines.push("entity-types/ #
|
|
21154
|
+
lines.push("entity-types/ # Data type schemas (like DB tables)");
|
|
21027
21155
|
lines.push("roles/ # RBAC roles with policies, scope rules, field masks");
|
|
21028
21156
|
lines.push("triggers/ # Automation rules (react to entity changes)");
|
|
21029
21157
|
lines.push("tools/index.ts # Custom tools shared by all agents");
|
|
@@ -21039,16 +21167,16 @@ function buildDocument(projectContext) {
|
|
|
21039
21167
|
lines.push("| `struere sync` | One-shot sync to Convex and exit (agent-friendly) |");
|
|
21040
21168
|
lines.push("| `struere dev` | Watch files and sync to Convex on save |");
|
|
21041
21169
|
lines.push("| `struere deploy` | Push development config to production |");
|
|
21042
|
-
lines.push("| `struere add agent\\|
|
|
21170
|
+
lines.push("| `struere add agent\\|data-type\\|role\\|trigger\\|eval\\|fixture <name>` | Scaffold a new resource |");
|
|
21043
21171
|
lines.push("| `struere status` | Compare local vs remote state |");
|
|
21044
21172
|
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
|
|
21173
|
+
lines.push("| `struere data types` | List data types in an environment |");
|
|
21174
|
+
lines.push("| `struere data list <type>` | List records (supports `--status`, `--limit`, `--json`) |");
|
|
21175
|
+
lines.push("| `struere data get <id>` | Get record details |");
|
|
21176
|
+
lines.push("| `struere data create <type>` | Create record (interactive or `--data <json>`) |");
|
|
21177
|
+
lines.push("| `struere data update <id>` | Update record (`--data <json>`, `--status`) |");
|
|
21178
|
+
lines.push("| `struere data delete <id>` | Delete record (with confirmation) |");
|
|
21179
|
+
lines.push("| `struere data search <type> <query>` | Search records by text |");
|
|
21052
21180
|
lines.push("| `struere eval run <suite>` | Run an eval suite and write Markdown results |");
|
|
21053
21181
|
lines.push("| `struere eval run <suite> --case <name>` | Run specific case(s) by name |");
|
|
21054
21182
|
lines.push("| `struere eval run <suite> --tag <tag>` | Run cases matching a tag |");
|
|
@@ -21060,7 +21188,7 @@ function buildDocument(projectContext) {
|
|
|
21060
21188
|
lines.push("");
|
|
21061
21189
|
lines.push(`## Key Patterns`);
|
|
21062
21190
|
lines.push("");
|
|
21063
|
-
lines.push("- **Imports**: `import { defineAgent,
|
|
21191
|
+
lines.push("- **Imports**: `import { defineAgent, defineData, defineRole, defineTrigger, defineTools } from 'struere'`");
|
|
21064
21192
|
lines.push("- **Default model**: `grok-4-1-fast` (provider: `xai`). Also supports `anthropic`, `openai` and `google`");
|
|
21065
21193
|
lines.push("- **Scope rule values**: `actor.userId`, `actor.entityId`, `actor.organizationId`, `actor.relatedIds:TYPE`, `literal:VALUE`");
|
|
21066
21194
|
lines.push("- **Policy actions**: `create`, `read`, `update`, `delete`, `list` (deny overrides allow)");
|
|
@@ -21157,7 +21285,7 @@ function buildDocument(projectContext) {
|
|
|
21157
21285
|
lines.push("### SDK");
|
|
21158
21286
|
lines.push(`- [SDK Overview](${DOCS_BASE}/sdk/overview.md)`);
|
|
21159
21287
|
lines.push(`- [defineAgent](${DOCS_BASE}/sdk/define-agent.md)`);
|
|
21160
|
-
lines.push(`- [
|
|
21288
|
+
lines.push(`- [defineData](${DOCS_BASE}/sdk/define-data.md)`);
|
|
21161
21289
|
lines.push(`- [defineRole](${DOCS_BASE}/sdk/define-role.md)`);
|
|
21162
21290
|
lines.push(`- [defineTrigger](${DOCS_BASE}/sdk/define-trigger.md)`);
|
|
21163
21291
|
lines.push(`- [defineTools](${DOCS_BASE}/sdk/define-tools.md)`);
|
|
@@ -21168,7 +21296,7 @@ function buildDocument(projectContext) {
|
|
|
21168
21296
|
lines.push(`- [System Prompt Templates](${DOCS_BASE}/tools/system-prompt-templates.md)`);
|
|
21169
21297
|
lines.push("");
|
|
21170
21298
|
lines.push("### Platform");
|
|
21171
|
-
lines.push(`- [
|
|
21299
|
+
lines.push(`- [Data](${DOCS_BASE}/platform/data.md)`);
|
|
21172
21300
|
lines.push(`- [Permissions](${DOCS_BASE}/platform/permissions.md)`);
|
|
21173
21301
|
lines.push(`- [Agents](${DOCS_BASE}/platform/agents.md)`);
|
|
21174
21302
|
lines.push(`- [Events](${DOCS_BASE}/platform/events.md)`);
|
|
@@ -21335,6 +21463,112 @@ function isOrgAccessError(error) {
|
|
|
21335
21463
|
return message.includes("Access denied") || message.includes("not a member") || message.includes("Organization not found");
|
|
21336
21464
|
}
|
|
21337
21465
|
|
|
21466
|
+
// src/cli/commands/org.ts
|
|
21467
|
+
async function promptCreateOrg(token) {
|
|
21468
|
+
if (!isInteractive2()) {
|
|
21469
|
+
console.log(source_default.red("No organizations found. Run struere org create to create one."));
|
|
21470
|
+
return null;
|
|
21471
|
+
}
|
|
21472
|
+
const shouldCreate = await esm_default2({
|
|
21473
|
+
message: "No organizations found. Create one now?",
|
|
21474
|
+
default: true
|
|
21475
|
+
});
|
|
21476
|
+
if (!shouldCreate)
|
|
21477
|
+
return null;
|
|
21478
|
+
const name = await esm_default3({
|
|
21479
|
+
message: "Organization name:",
|
|
21480
|
+
validate: (v) => v.trim().length > 0 || "Name is required"
|
|
21481
|
+
});
|
|
21482
|
+
const slug = slugify(name.trim());
|
|
21483
|
+
const spinner = ora();
|
|
21484
|
+
spinner.start("Creating organization");
|
|
21485
|
+
const { organization, error } = await createOrganization(token, name.trim(), slug);
|
|
21486
|
+
if (error || !organization) {
|
|
21487
|
+
spinner.fail("Failed to create organization");
|
|
21488
|
+
console.log(source_default.red(error || "Unknown error"));
|
|
21489
|
+
return null;
|
|
21490
|
+
}
|
|
21491
|
+
spinner.succeed(`Created organization ${source_default.cyan(organization.name)} (${organization.slug})`);
|
|
21492
|
+
return organization;
|
|
21493
|
+
}
|
|
21494
|
+
var orgCommand = new Command("org").description("Manage organizations");
|
|
21495
|
+
orgCommand.command("list").description("List your organizations").option("--json", "Output as JSON").action(async (options) => {
|
|
21496
|
+
const credentials = loadCredentials();
|
|
21497
|
+
if (!credentials) {
|
|
21498
|
+
console.log(source_default.red("Not authenticated. Run struere login first."));
|
|
21499
|
+
process.exit(1);
|
|
21500
|
+
}
|
|
21501
|
+
await refreshToken();
|
|
21502
|
+
const fresh = loadCredentials();
|
|
21503
|
+
const token = fresh?.token || credentials.token;
|
|
21504
|
+
const spinner = ora();
|
|
21505
|
+
spinner.start("Fetching organizations");
|
|
21506
|
+
const { organizations, error } = await listMyOrganizations(token);
|
|
21507
|
+
if (error) {
|
|
21508
|
+
spinner.fail("Failed to fetch organizations");
|
|
21509
|
+
console.log(source_default.red(error));
|
|
21510
|
+
process.exit(1);
|
|
21511
|
+
}
|
|
21512
|
+
spinner.stop();
|
|
21513
|
+
if (options.json) {
|
|
21514
|
+
console.log(JSON.stringify(organizations, null, 2));
|
|
21515
|
+
return;
|
|
21516
|
+
}
|
|
21517
|
+
if (organizations.length === 0) {
|
|
21518
|
+
console.log(source_default.yellow("No organizations found."));
|
|
21519
|
+
console.log(source_default.gray("Run"), source_default.cyan("struere org create"), source_default.gray("to create one."));
|
|
21520
|
+
return;
|
|
21521
|
+
}
|
|
21522
|
+
console.log();
|
|
21523
|
+
console.log(source_default.bold("Organizations"));
|
|
21524
|
+
console.log();
|
|
21525
|
+
for (const org of organizations) {
|
|
21526
|
+
console.log(` ${source_default.cyan(org.name)} ${source_default.gray(`(${org.slug})`)} ${source_default.gray(`- ${org.role}`)}`);
|
|
21527
|
+
}
|
|
21528
|
+
console.log();
|
|
21529
|
+
});
|
|
21530
|
+
orgCommand.command("create").argument("[name]", "Organization name").description("Create a new organization").option("--slug <slug>", "Custom slug").option("--json", "Output as JSON").action(async (nameArg, options) => {
|
|
21531
|
+
const credentials = loadCredentials();
|
|
21532
|
+
if (!credentials) {
|
|
21533
|
+
console.log(source_default.red("Not authenticated. Run struere login first."));
|
|
21534
|
+
process.exit(1);
|
|
21535
|
+
}
|
|
21536
|
+
await refreshToken();
|
|
21537
|
+
const fresh = loadCredentials();
|
|
21538
|
+
const token = fresh?.token || credentials.token;
|
|
21539
|
+
let name = nameArg;
|
|
21540
|
+
if (!name) {
|
|
21541
|
+
if (!isInteractive2()) {
|
|
21542
|
+
console.log(source_default.red("Organization name is required in non-interactive mode."));
|
|
21543
|
+
process.exit(1);
|
|
21544
|
+
}
|
|
21545
|
+
name = await esm_default3({
|
|
21546
|
+
message: "Organization name:",
|
|
21547
|
+
validate: (v) => v.trim().length > 0 || "Name is required"
|
|
21548
|
+
});
|
|
21549
|
+
}
|
|
21550
|
+
name = name.trim();
|
|
21551
|
+
const slug = options.slug || slugify(name);
|
|
21552
|
+
const spinner = ora();
|
|
21553
|
+
spinner.start("Creating organization");
|
|
21554
|
+
const { organization, error } = await createOrganization(token, name, slug);
|
|
21555
|
+
if (error || !organization) {
|
|
21556
|
+
spinner.fail("Failed to create organization");
|
|
21557
|
+
console.log(source_default.red(error || "Unknown error"));
|
|
21558
|
+
process.exit(1);
|
|
21559
|
+
}
|
|
21560
|
+
spinner.stop();
|
|
21561
|
+
if (options.json) {
|
|
21562
|
+
console.log(JSON.stringify(organization, null, 2));
|
|
21563
|
+
return;
|
|
21564
|
+
}
|
|
21565
|
+
console.log(source_default.green("\u2713"), `Created organization ${source_default.cyan(organization.name)} (${organization.slug})`);
|
|
21566
|
+
console.log();
|
|
21567
|
+
console.log(source_default.gray("Next steps:"));
|
|
21568
|
+
console.log(source_default.gray(" \u2022"), source_default.cyan("struere init"), source_default.gray("- Initialize a project"));
|
|
21569
|
+
console.log();
|
|
21570
|
+
});
|
|
21571
|
+
|
|
21338
21572
|
// src/cli/commands/init.ts
|
|
21339
21573
|
async function runInit(cwd, selectedOrg) {
|
|
21340
21574
|
const spinner = ora();
|
|
@@ -21363,10 +21597,11 @@ async function runInit(cwd, selectedOrg) {
|
|
|
21363
21597
|
return false;
|
|
21364
21598
|
}
|
|
21365
21599
|
if (organizations.length === 0) {
|
|
21366
|
-
|
|
21367
|
-
|
|
21368
|
-
|
|
21369
|
-
|
|
21600
|
+
const created = await promptCreateOrg(credentials.token);
|
|
21601
|
+
if (!created)
|
|
21602
|
+
return false;
|
|
21603
|
+
org = created;
|
|
21604
|
+
} else if (organizations.length === 1) {
|
|
21370
21605
|
org = organizations[0];
|
|
21371
21606
|
} else {
|
|
21372
21607
|
org = await esm_default4({
|
|
@@ -21444,12 +21679,17 @@ var initCommand = new Command("init").description("Initialize a new Struere orga
|
|
|
21444
21679
|
console.log(source_default.red("Failed to fetch organizations:"), error);
|
|
21445
21680
|
process.exit(1);
|
|
21446
21681
|
}
|
|
21447
|
-
if (organizations.length === 0) {
|
|
21448
|
-
console.log(source_default.red("No organizations found. Please create one in the dashboard first."));
|
|
21449
|
-
process.exit(1);
|
|
21450
|
-
}
|
|
21451
21682
|
let selectedOrg;
|
|
21452
|
-
if (
|
|
21683
|
+
if (organizations.length === 0) {
|
|
21684
|
+
if (nonInteractive) {
|
|
21685
|
+
console.log(source_default.red("No organizations found. Run struere org create to create one."));
|
|
21686
|
+
process.exit(1);
|
|
21687
|
+
}
|
|
21688
|
+
const created = await promptCreateOrg(credentials?.token || "");
|
|
21689
|
+
if (!created)
|
|
21690
|
+
process.exit(1);
|
|
21691
|
+
selectedOrg = created;
|
|
21692
|
+
} else if (options.org) {
|
|
21453
21693
|
const found = organizations.find((o) => o.slug === options.org);
|
|
21454
21694
|
if (!found) {
|
|
21455
21695
|
console.log(source_default.red(`Organization "${options.org}" not found.`));
|
|
@@ -21505,7 +21745,7 @@ var initCommand = new Command("init").description("Initialize a new Struere orga
|
|
|
21505
21745
|
console.log();
|
|
21506
21746
|
console.log(source_default.gray("Project structure:"));
|
|
21507
21747
|
console.log(source_default.gray(" agents/ "), source_default.cyan("Agent definitions"));
|
|
21508
|
-
console.log(source_default.gray(" entity-types/ "), source_default.cyan("
|
|
21748
|
+
console.log(source_default.gray(" entity-types/ "), source_default.cyan("Data type schemas"));
|
|
21509
21749
|
console.log(source_default.gray(" roles/ "), source_default.cyan("Role + permission definitions"));
|
|
21510
21750
|
console.log(source_default.gray(" tools/ "), source_default.cyan("Shared custom tools"));
|
|
21511
21751
|
console.log();
|
|
@@ -21563,7 +21803,9 @@ var BUILTIN_TOOLS = [
|
|
|
21563
21803
|
"airtable.createRecords",
|
|
21564
21804
|
"airtable.updateRecords",
|
|
21565
21805
|
"airtable.deleteRecords",
|
|
21566
|
-
"email.send"
|
|
21806
|
+
"email.send",
|
|
21807
|
+
"payment.create",
|
|
21808
|
+
"payment.getStatus"
|
|
21567
21809
|
];
|
|
21568
21810
|
function extractSyncPayload(resources) {
|
|
21569
21811
|
const customToolsMap = new Map;
|
|
@@ -21618,7 +21860,9 @@ function extractSyncPayload(resources) {
|
|
|
21618
21860
|
userMessage: t.user,
|
|
21619
21861
|
assertions: t.assertions
|
|
21620
21862
|
})),
|
|
21621
|
-
finalAssertions: c.finalAssertions
|
|
21863
|
+
finalAssertions: c.finalAssertions,
|
|
21864
|
+
channel: c.channel,
|
|
21865
|
+
contextParams: c.contextParams
|
|
21622
21866
|
}))
|
|
21623
21867
|
})) : undefined;
|
|
21624
21868
|
const triggers = resources.triggers.length > 0 ? resources.triggers.map((t) => ({
|
|
@@ -21683,7 +21927,8 @@ function extractAgentPayload(agent, customToolsMap) {
|
|
|
21683
21927
|
name: customTool.name,
|
|
21684
21928
|
description: customTool.description,
|
|
21685
21929
|
parameters: customTool.parameters || { type: "object", properties: {} },
|
|
21686
|
-
handlerCode: extractHandlerCode(customTool._originalHandler || customTool.handler)
|
|
21930
|
+
handlerCode: extractHandlerCode(customTool._originalHandler || customTool.handler),
|
|
21931
|
+
...customTool.templateOnly && { templateOnly: true }
|
|
21687
21932
|
};
|
|
21688
21933
|
});
|
|
21689
21934
|
return {
|
|
@@ -21734,7 +21979,9 @@ function getBuiltinToolDescription(name) {
|
|
|
21734
21979
|
"airtable.createRecords": "Create up to 10 records in an Airtable table",
|
|
21735
21980
|
"airtable.updateRecords": "Update up to 10 records in an Airtable table",
|
|
21736
21981
|
"airtable.deleteRecords": "Delete up to 10 records from an Airtable table",
|
|
21737
|
-
"email.send": "Send an email via Resend"
|
|
21982
|
+
"email.send": "Send an email via Resend",
|
|
21983
|
+
"payment.create": "Create a payment link via Flow.cl and return the URL",
|
|
21984
|
+
"payment.getStatus": "Check the current status of a payment"
|
|
21738
21985
|
};
|
|
21739
21986
|
return descriptions[name] || name;
|
|
21740
21987
|
}
|
|
@@ -22042,6 +22289,24 @@ function getBuiltinToolParameters(name) {
|
|
|
22042
22289
|
replyTo: { type: "string", description: "Reply-to email address" }
|
|
22043
22290
|
},
|
|
22044
22291
|
required: ["to", "subject"]
|
|
22292
|
+
},
|
|
22293
|
+
"payment.create": {
|
|
22294
|
+
type: "object",
|
|
22295
|
+
properties: {
|
|
22296
|
+
amount: { type: "number", description: "Payment amount in the smallest currency unit" },
|
|
22297
|
+
description: { type: "string", description: "Description of the payment" },
|
|
22298
|
+
currency: { type: "string", description: "Currency code (defaults to CLP)" },
|
|
22299
|
+
customerEmail: { type: "string", description: "Customer email address" },
|
|
22300
|
+
entityId: { type: "string", description: "Optional entity ID to link the payment to" }
|
|
22301
|
+
},
|
|
22302
|
+
required: ["amount", "description"]
|
|
22303
|
+
},
|
|
22304
|
+
"payment.getStatus": {
|
|
22305
|
+
type: "object",
|
|
22306
|
+
properties: {
|
|
22307
|
+
entityId: { type: "string", description: "Payment entity ID to check status for" }
|
|
22308
|
+
},
|
|
22309
|
+
required: ["entityId"]
|
|
22045
22310
|
}
|
|
22046
22311
|
};
|
|
22047
22312
|
return schemas[name] || { type: "object", properties: {} };
|
|
@@ -22118,7 +22383,7 @@ async function checkForDeletions(resources, organizationId, environment) {
|
|
|
22118
22383
|
deletions.push({ type: "Agents", remote: remoteState.agents.length, local: payload.agents.length, deleted: deletedAgents });
|
|
22119
22384
|
const deletedEntityTypes = remoteState.entityTypes.filter((et) => !localSlugs.entityTypes.has(et.slug)).map((et) => et.name);
|
|
22120
22385
|
if (deletedEntityTypes.length > 0)
|
|
22121
|
-
deletions.push({ type: "
|
|
22386
|
+
deletions.push({ type: "Data types", remote: remoteState.entityTypes.length, local: payload.entityTypes.length, deleted: deletedEntityTypes });
|
|
22122
22387
|
const deletedRoles = remoteState.roles.filter((r) => !localSlugs.roles.has(r.name)).map((r) => r.name);
|
|
22123
22388
|
if (deletedRoles.length > 0)
|
|
22124
22389
|
deletions.push({ type: "Roles", remote: remoteState.roles.length, local: payload.roles.length, deleted: deletedRoles });
|
|
@@ -22223,7 +22488,7 @@ var syncCommand = new Command("sync").description("Sync resources to Convex and
|
|
|
22223
22488
|
process.exit(1);
|
|
22224
22489
|
}
|
|
22225
22490
|
if (!jsonMode && !options.dryRun)
|
|
22226
|
-
output.succeed(`Loaded ${resources.agents.length} agents, ${resources.entityTypes.length}
|
|
22491
|
+
output.succeed(`Loaded ${resources.agents.length} agents, ${resources.entityTypes.length} data types, ${resources.roles.length} roles`);
|
|
22227
22492
|
} catch (error) {
|
|
22228
22493
|
if (jsonMode) {
|
|
22229
22494
|
console.log(JSON.stringify({ success: false, error: error instanceof Error ? error.message : String(error) }));
|
|
@@ -22255,7 +22520,7 @@ var syncCommand = new Command("sync").description("Sync resources to Convex and
|
|
|
22255
22520
|
console.log(source_default.bold("Dry run \u2014 nothing will be synced"));
|
|
22256
22521
|
console.log();
|
|
22257
22522
|
console.log(source_default.gray(" Agents:"), payload.agents.map((a) => a.slug).join(", ") || "none");
|
|
22258
|
-
console.log(source_default.gray("
|
|
22523
|
+
console.log(source_default.gray(" Data types:"), payload.entityTypes.map((et) => et.slug).join(", ") || "none");
|
|
22259
22524
|
console.log(source_default.gray(" Roles:"), payload.roles.map((r) => r.name).join(", ") || "none");
|
|
22260
22525
|
console.log(source_default.gray(" Triggers:"), (payload.triggers || []).map((t) => t.slug).join(", ") || "none");
|
|
22261
22526
|
if (deletions.length > 0) {
|
|
@@ -22421,7 +22686,7 @@ var devCommand = new Command("dev").description("Watch files and sync to develop
|
|
|
22421
22686
|
spinner.start("Loading resources");
|
|
22422
22687
|
try {
|
|
22423
22688
|
loadedResources = await loadAllResources(cwd);
|
|
22424
|
-
spinner.succeed(`Loaded ${loadedResources.agents.length} agents, ${loadedResources.entityTypes.length}
|
|
22689
|
+
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
22690
|
for (const err of loadedResources.errors) {
|
|
22426
22691
|
console.log(source_default.red(" \u2716"), err);
|
|
22427
22692
|
}
|
|
@@ -22524,9 +22789,15 @@ var devCommand = new Command("dev").description("Watch files and sync to develop
|
|
|
22524
22789
|
persistent: true,
|
|
22525
22790
|
usePolling: false
|
|
22526
22791
|
});
|
|
22527
|
-
|
|
22528
|
-
|
|
22529
|
-
|
|
22792
|
+
let debounceTimer = null;
|
|
22793
|
+
let pendingChanges = [];
|
|
22794
|
+
const triggerSync = async () => {
|
|
22795
|
+
const changes = [...pendingChanges];
|
|
22796
|
+
pendingChanges = [];
|
|
22797
|
+
for (const { path, action } of changes) {
|
|
22798
|
+
const relativePath = path.replace(cwd, ".");
|
|
22799
|
+
console.log(source_default.gray(`${action}: ${relativePath}`));
|
|
22800
|
+
}
|
|
22530
22801
|
const syncSpinner = ora("Syncing...").start();
|
|
22531
22802
|
try {
|
|
22532
22803
|
await performDevSync(cwd, project.organization.id);
|
|
@@ -22554,6 +22825,15 @@ var devCommand = new Command("dev").description("Watch files and sync to develop
|
|
|
22554
22825
|
}
|
|
22555
22826
|
}
|
|
22556
22827
|
};
|
|
22828
|
+
const handleFileChange = (path, action) => {
|
|
22829
|
+
pendingChanges.push({ path, action });
|
|
22830
|
+
if (debounceTimer)
|
|
22831
|
+
clearTimeout(debounceTimer);
|
|
22832
|
+
debounceTimer = setTimeout(() => {
|
|
22833
|
+
debounceTimer = null;
|
|
22834
|
+
triggerSync();
|
|
22835
|
+
}, 300);
|
|
22836
|
+
};
|
|
22557
22837
|
watcher.on("change", (path) => handleFileChange(path, "Changed"));
|
|
22558
22838
|
watcher.on("add", (path) => handleFileChange(path, "Added"));
|
|
22559
22839
|
watcher.on("unlink", (path) => handleFileChange(path, "Removed"));
|
|
@@ -22634,7 +22914,7 @@ var deployCommand = new Command("deploy").description("Deploy all resources to p
|
|
|
22634
22914
|
try {
|
|
22635
22915
|
resources = await loadAllResources(cwd);
|
|
22636
22916
|
if (!jsonMode)
|
|
22637
|
-
spinner.succeed(`Loaded ${resources.agents.length} agents, ${resources.entityTypes.length}
|
|
22917
|
+
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
22918
|
for (const err of resources.errors) {
|
|
22639
22919
|
if (!jsonMode)
|
|
22640
22920
|
console.log(source_default.red(" \u2716"), err);
|
|
@@ -22698,7 +22978,7 @@ var deployCommand = new Command("deploy").description("Deploy all resources to p
|
|
|
22698
22978
|
console.log(source_default.gray(" -"), `${source_default.cyan(agent.name)} (${agent.slug}) v${agent.version}`);
|
|
22699
22979
|
}
|
|
22700
22980
|
console.log();
|
|
22701
|
-
console.log("
|
|
22981
|
+
console.log("Data types:");
|
|
22702
22982
|
for (const et of resources.entityTypes) {
|
|
22703
22983
|
console.log(source_default.gray(" -"), source_default.cyan(et.name), `(${et.slug})`);
|
|
22704
22984
|
}
|
|
@@ -22976,7 +23256,7 @@ var whoamiCommand = new Command("whoami").description("Show current logged in us
|
|
|
22976
23256
|
});
|
|
22977
23257
|
|
|
22978
23258
|
// src/cli/commands/add.ts
|
|
22979
|
-
var addCommand = new Command("add").description("Scaffold a new resource").argument("<type>", "Resource type: agent,
|
|
23259
|
+
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
23260
|
const cwd = process.cwd();
|
|
22981
23261
|
console.log();
|
|
22982
23262
|
if (!hasProject(cwd)) {
|
|
@@ -23003,17 +23283,19 @@ var addCommand = new Command("add").description("Scaffold a new resource").argum
|
|
|
23003
23283
|
console.log(source_default.yellow("Agent already exists:"), `agents/${slug}.ts`);
|
|
23004
23284
|
}
|
|
23005
23285
|
break;
|
|
23286
|
+
case "data-type":
|
|
23287
|
+
case "datatype":
|
|
23006
23288
|
case "entity-type":
|
|
23007
23289
|
case "entitytype":
|
|
23008
23290
|
case "type":
|
|
23009
23291
|
result = scaffoldEntityType(cwd, displayName, slug);
|
|
23010
23292
|
if (result.createdFiles.length > 0) {
|
|
23011
|
-
console.log(source_default.green("\u2713"), `Created
|
|
23293
|
+
console.log(source_default.green("\u2713"), `Created data type "${displayName}"`);
|
|
23012
23294
|
for (const file of result.createdFiles) {
|
|
23013
23295
|
console.log(source_default.gray(" \u2192"), file);
|
|
23014
23296
|
}
|
|
23015
23297
|
} else {
|
|
23016
|
-
console.log(source_default.yellow("
|
|
23298
|
+
console.log(source_default.yellow("Data type already exists:"), `entity-types/${slug}.ts`);
|
|
23017
23299
|
}
|
|
23018
23300
|
break;
|
|
23019
23301
|
case "role":
|
|
@@ -23070,10 +23352,10 @@ var addCommand = new Command("add").description("Scaffold a new resource").argum
|
|
|
23070
23352
|
console.log();
|
|
23071
23353
|
console.log("Available types:");
|
|
23072
23354
|
console.log(source_default.gray(" -"), source_default.cyan("agent"), "- Create an AI agent");
|
|
23073
|
-
console.log(source_default.gray(" -"), source_default.cyan("
|
|
23355
|
+
console.log(source_default.gray(" -"), source_default.cyan("data-type"), "- Create a data type schema");
|
|
23074
23356
|
console.log(source_default.gray(" -"), source_default.cyan("role"), "- Create a role with permissions");
|
|
23075
23357
|
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
|
|
23358
|
+
console.log(source_default.gray(" -"), source_default.cyan("trigger"), "- Create a data trigger");
|
|
23077
23359
|
console.log(source_default.gray(" -"), source_default.cyan("fixture"), "- Create a test data fixture (YAML)");
|
|
23078
23360
|
console.log();
|
|
23079
23361
|
process.exit(1);
|
|
@@ -23153,7 +23435,7 @@ var statusCommand = new Command("status").description("Compare local vs remote s
|
|
|
23153
23435
|
try {
|
|
23154
23436
|
localResources = await loadAllResources(cwd);
|
|
23155
23437
|
if (!jsonMode) {
|
|
23156
|
-
spinner.succeed(`Loaded ${localResources.agents.length} agents, ${localResources.entityTypes.length}
|
|
23438
|
+
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
23439
|
for (const err of localResources.errors) {
|
|
23158
23440
|
console.log(source_default.red(" \u2716"), err);
|
|
23159
23441
|
}
|
|
@@ -23241,10 +23523,10 @@ var statusCommand = new Command("status").description("Compare local vs remote s
|
|
|
23241
23523
|
}
|
|
23242
23524
|
}
|
|
23243
23525
|
console.log();
|
|
23244
|
-
console.log(source_default.bold("
|
|
23526
|
+
console.log(source_default.bold("Data Types"));
|
|
23245
23527
|
console.log(source_default.gray("\u2500".repeat(60)));
|
|
23246
23528
|
if (localResources.entityTypes.length === 0 && devState.entityTypes.length === 0) {
|
|
23247
|
-
console.log(source_default.gray(" No
|
|
23529
|
+
console.log(source_default.gray(" No data types"));
|
|
23248
23530
|
} else {
|
|
23249
23531
|
for (const et of localResources.entityTypes) {
|
|
23250
23532
|
const remote = devState.entityTypes.find((r) => r.slug === et.slug);
|
|
@@ -23390,9 +23672,9 @@ function generateEntityTypeFile(entityType) {
|
|
|
23390
23672
|
if (entityType.displayConfig) {
|
|
23391
23673
|
parts.push(` displayConfig: ${stringifyValue(entityType.displayConfig, 2)}`);
|
|
23392
23674
|
}
|
|
23393
|
-
return `import {
|
|
23675
|
+
return `import { defineData } from 'struere'
|
|
23394
23676
|
|
|
23395
|
-
export default
|
|
23677
|
+
export default defineData({
|
|
23396
23678
|
${parts.join(`,
|
|
23397
23679
|
`)},
|
|
23398
23680
|
})
|
|
@@ -23480,13 +23762,13 @@ export default defineTools([])
|
|
|
23480
23762
|
` parameters: ${stringifyValue(tool.parameters, 4)}`
|
|
23481
23763
|
];
|
|
23482
23764
|
if (tool.handlerCode) {
|
|
23483
|
-
parts.push(` handler: async (args, context, fetch) => {
|
|
23765
|
+
parts.push(` handler: async (args, context, struere, fetch) => {
|
|
23484
23766
|
${tool.handlerCode.split(`
|
|
23485
23767
|
`).join(`
|
|
23486
23768
|
`)}
|
|
23487
23769
|
}`);
|
|
23488
23770
|
} else {
|
|
23489
|
-
parts.push(` handler: async (args, context, fetch) => {
|
|
23771
|
+
parts.push(` handler: async (args, context, struere, fetch) => {
|
|
23490
23772
|
throw new Error("TODO: implement handler")
|
|
23491
23773
|
}`);
|
|
23492
23774
|
}
|
|
@@ -23776,7 +24058,6 @@ var pullCommand = new Command("pull").description("Pull remote resources to loca
|
|
|
23776
24058
|
});
|
|
23777
24059
|
|
|
23778
24060
|
// src/cli/utils/entities.ts
|
|
23779
|
-
var CONVEX_URL2 = process.env.STRUERE_CONVEX_URL || "https://rapid-wildebeest-172.convex.cloud";
|
|
23780
24061
|
function getToken() {
|
|
23781
24062
|
const credentials = loadCredentials();
|
|
23782
24063
|
const apiKey = getApiKey();
|
|
@@ -23786,7 +24067,7 @@ async function convexQuery(path, args) {
|
|
|
23786
24067
|
const token = getToken();
|
|
23787
24068
|
if (!token)
|
|
23788
24069
|
return { error: "Not authenticated" };
|
|
23789
|
-
const response = await fetch(`${
|
|
24070
|
+
const response = await fetch(`${CONVEX_URL}/api/query`, {
|
|
23790
24071
|
method: "POST",
|
|
23791
24072
|
headers: {
|
|
23792
24073
|
"Content-Type": "application/json",
|
|
@@ -23815,7 +24096,7 @@ async function convexMutation(path, args) {
|
|
|
23815
24096
|
const token = getToken();
|
|
23816
24097
|
if (!token)
|
|
23817
24098
|
return { error: "Not authenticated" };
|
|
23818
|
-
const response = await fetch(`${
|
|
24099
|
+
const response = await fetch(`${CONVEX_URL}/api/mutation`, {
|
|
23819
24100
|
method: "POST",
|
|
23820
24101
|
headers: {
|
|
23821
24102
|
"Content-Type": "application/json",
|
|
@@ -24001,20 +24282,20 @@ function flattenEntityForTable(entity) {
|
|
|
24001
24282
|
status: entity.status
|
|
24002
24283
|
};
|
|
24003
24284
|
}
|
|
24004
|
-
var entitiesCommand = new Command("
|
|
24005
|
-
entitiesCommand.command("types").description("List available
|
|
24285
|
+
var entitiesCommand = new Command("data").description("Manage data records");
|
|
24286
|
+
entitiesCommand.command("types").description("List available data types").option("--env <environment>", "Environment (development|production)", "development").option("--json", "Output raw JSON").action(async (opts) => {
|
|
24006
24287
|
await ensureAuth();
|
|
24007
24288
|
const spinner = ora();
|
|
24008
24289
|
const env2 = opts.env;
|
|
24009
24290
|
const orgId = getOrgId();
|
|
24010
|
-
spinner.start("Fetching
|
|
24291
|
+
spinner.start("Fetching data types");
|
|
24011
24292
|
const { data, error } = await queryEntityTypes(env2, orgId);
|
|
24012
24293
|
if (error || !data) {
|
|
24013
|
-
spinner.fail("Failed to fetch
|
|
24294
|
+
spinner.fail("Failed to fetch data types");
|
|
24014
24295
|
console.log(source_default.red("Error:"), error);
|
|
24015
24296
|
process.exit(1);
|
|
24016
24297
|
}
|
|
24017
|
-
spinner.succeed("
|
|
24298
|
+
spinner.succeed("Data types loaded");
|
|
24018
24299
|
const types = data;
|
|
24019
24300
|
if (opts.json) {
|
|
24020
24301
|
console.log(JSON.stringify(types, null, 2));
|
|
@@ -24037,12 +24318,12 @@ entitiesCommand.command("types").description("List available entity types").opti
|
|
|
24037
24318
|
}));
|
|
24038
24319
|
console.log();
|
|
24039
24320
|
});
|
|
24040
|
-
entitiesCommand.command("list <type>").description("List
|
|
24321
|
+
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) => {
|
|
24041
24322
|
await ensureAuth();
|
|
24042
24323
|
const spinner = ora();
|
|
24043
24324
|
const env2 = opts.env;
|
|
24044
24325
|
const orgId = getOrgId();
|
|
24045
|
-
spinner.start(`Fetching ${type}
|
|
24326
|
+
spinner.start(`Fetching ${type} records`);
|
|
24046
24327
|
const [entitiesResult, typeResult] = await Promise.all([
|
|
24047
24328
|
queryEntities(type, env2, {
|
|
24048
24329
|
status: opts.status,
|
|
@@ -24051,12 +24332,12 @@ entitiesCommand.command("list <type>").description("List entities of a type").op
|
|
|
24051
24332
|
queryEntityTypeBySlug(type, env2, orgId)
|
|
24052
24333
|
]);
|
|
24053
24334
|
if (entitiesResult.error || !entitiesResult.data) {
|
|
24054
|
-
spinner.fail(`Failed to fetch ${type}
|
|
24335
|
+
spinner.fail(`Failed to fetch ${type} records`);
|
|
24055
24336
|
console.log(source_default.red("Error:"), entitiesResult.error);
|
|
24056
24337
|
process.exit(1);
|
|
24057
24338
|
}
|
|
24058
24339
|
const entities = entitiesResult.data;
|
|
24059
|
-
spinner.succeed(`Found ${entities.length} ${type}
|
|
24340
|
+
spinner.succeed(`Found ${entities.length} ${type} records`);
|
|
24060
24341
|
if (opts.json) {
|
|
24061
24342
|
console.log(JSON.stringify(entities, null, 2));
|
|
24062
24343
|
return;
|
|
@@ -24069,27 +24350,27 @@ entitiesCommand.command("list <type>").description("List entities of a type").op
|
|
|
24069
24350
|
renderTable(columns, entities.map(flattenEntityForTable));
|
|
24070
24351
|
console.log();
|
|
24071
24352
|
});
|
|
24072
|
-
entitiesCommand.command("get <id>").description("Get
|
|
24353
|
+
entitiesCommand.command("get <id>").description("Get record details").option("--env <environment>", "Environment (development|production)", "development").option("--json", "Output raw JSON").action(async (rawId, opts) => {
|
|
24073
24354
|
await ensureAuth();
|
|
24074
24355
|
const spinner = ora();
|
|
24075
24356
|
const env2 = opts.env;
|
|
24076
24357
|
const orgId = getOrgId();
|
|
24077
|
-
spinner.start("Resolving
|
|
24358
|
+
spinner.start("Resolving record ID");
|
|
24078
24359
|
const resolved = await resolveEntityId(rawId, env2, orgId);
|
|
24079
24360
|
if (resolved.error || !resolved.data) {
|
|
24080
|
-
spinner.fail("
|
|
24081
|
-
console.log(source_default.red("Error:"), resolved.error || `No
|
|
24361
|
+
spinner.fail("Record not found");
|
|
24362
|
+
console.log(source_default.red("Error:"), resolved.error || `No record matched "${rawId}"`);
|
|
24082
24363
|
process.exit(1);
|
|
24083
24364
|
}
|
|
24084
24365
|
const id = resolved.data;
|
|
24085
|
-
spinner.text = "Fetching
|
|
24366
|
+
spinner.text = "Fetching record";
|
|
24086
24367
|
const { data, error } = await queryEntity(id, env2, orgId);
|
|
24087
24368
|
if (error || !data) {
|
|
24088
|
-
spinner.fail("Failed to fetch
|
|
24089
|
-
console.log(source_default.red("Error:"), error || "
|
|
24369
|
+
spinner.fail("Failed to fetch record");
|
|
24370
|
+
console.log(source_default.red("Error:"), error || "Record not found");
|
|
24090
24371
|
process.exit(1);
|
|
24091
24372
|
}
|
|
24092
|
-
spinner.succeed("
|
|
24373
|
+
spinner.succeed("Record loaded");
|
|
24093
24374
|
const result = data;
|
|
24094
24375
|
if (opts.json) {
|
|
24095
24376
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -24117,7 +24398,7 @@ entitiesCommand.command("get <id>").description("Get entity details").option("--
|
|
|
24117
24398
|
}
|
|
24118
24399
|
console.log();
|
|
24119
24400
|
});
|
|
24120
|
-
entitiesCommand.command("create <type>").description("Create a new
|
|
24401
|
+
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) => {
|
|
24121
24402
|
await ensureAuth();
|
|
24122
24403
|
const spinner = ora();
|
|
24123
24404
|
const env2 = opts.env;
|
|
@@ -24137,7 +24418,7 @@ entitiesCommand.command("create <type>").description("Create a new entity").opti
|
|
|
24137
24418
|
spinner.start(`Fetching ${type} schema`);
|
|
24138
24419
|
const { data: typeData, error: error2 } = await queryEntityTypeBySlug(type, env2, orgId);
|
|
24139
24420
|
if (error2 || !typeData) {
|
|
24140
|
-
spinner.fail(`
|
|
24421
|
+
spinner.fail(`Data type not found: ${type}`);
|
|
24141
24422
|
console.log(source_default.red("Error:"), error2 || "Not found");
|
|
24142
24423
|
process.exit(1);
|
|
24143
24424
|
}
|
|
@@ -24146,7 +24427,7 @@ entitiesCommand.command("create <type>").description("Create a new entity").opti
|
|
|
24146
24427
|
const entityType = typeData;
|
|
24147
24428
|
const schema = entityType.schema;
|
|
24148
24429
|
if (!schema?.properties) {
|
|
24149
|
-
console.log(source_default.red("
|
|
24430
|
+
console.log(source_default.red("Data type has no schema properties defined"));
|
|
24150
24431
|
process.exit(1);
|
|
24151
24432
|
}
|
|
24152
24433
|
data = {};
|
|
@@ -24175,14 +24456,14 @@ entitiesCommand.command("create <type>").description("Create a new entity").opti
|
|
|
24175
24456
|
}
|
|
24176
24457
|
console.log();
|
|
24177
24458
|
}
|
|
24178
|
-
spinner.start(`Creating ${type}
|
|
24459
|
+
spinner.start(`Creating ${type} record`);
|
|
24179
24460
|
const { data: result, error } = await createEntity(type, data, env2, opts.status, orgId);
|
|
24180
24461
|
if (error) {
|
|
24181
|
-
spinner.fail("Failed to create
|
|
24462
|
+
spinner.fail("Failed to create record");
|
|
24182
24463
|
console.log(source_default.red("Error:"), error);
|
|
24183
24464
|
process.exit(1);
|
|
24184
24465
|
}
|
|
24185
|
-
spinner.succeed(`
|
|
24466
|
+
spinner.succeed(`Record created`);
|
|
24186
24467
|
if (opts.json) {
|
|
24187
24468
|
console.log(JSON.stringify({ id: result }, null, 2));
|
|
24188
24469
|
} else {
|
|
@@ -24191,7 +24472,7 @@ entitiesCommand.command("create <type>").description("Create a new entity").opti
|
|
|
24191
24472
|
console.log();
|
|
24192
24473
|
}
|
|
24193
24474
|
});
|
|
24194
|
-
entitiesCommand.command("update <id>").description("Update
|
|
24475
|
+
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) => {
|
|
24195
24476
|
await ensureAuth();
|
|
24196
24477
|
const spinner = ora();
|
|
24197
24478
|
const env2 = opts.env;
|
|
@@ -24209,63 +24490,63 @@ entitiesCommand.command("update <id>").description("Update an entity").option("-
|
|
|
24209
24490
|
process.exit(1);
|
|
24210
24491
|
}
|
|
24211
24492
|
}
|
|
24212
|
-
spinner.start("Resolving
|
|
24493
|
+
spinner.start("Resolving record ID");
|
|
24213
24494
|
const resolved = await resolveEntityId(rawId, env2, orgId);
|
|
24214
24495
|
if (resolved.error || !resolved.data) {
|
|
24215
|
-
spinner.fail("
|
|
24216
|
-
console.log(source_default.red("Error:"), resolved.error || `No
|
|
24496
|
+
spinner.fail("Record not found");
|
|
24497
|
+
console.log(source_default.red("Error:"), resolved.error || `No record matched "${rawId}"`);
|
|
24217
24498
|
process.exit(1);
|
|
24218
24499
|
}
|
|
24219
24500
|
const id = resolved.data;
|
|
24220
|
-
spinner.text = "Updating
|
|
24501
|
+
spinner.text = "Updating record";
|
|
24221
24502
|
const { data: result, error } = await updateEntity(id, data, env2, opts.status, orgId);
|
|
24222
24503
|
if (error) {
|
|
24223
|
-
spinner.fail("Failed to update
|
|
24504
|
+
spinner.fail("Failed to update record");
|
|
24224
24505
|
console.log(source_default.red("Error:"), error);
|
|
24225
24506
|
process.exit(1);
|
|
24226
24507
|
}
|
|
24227
|
-
spinner.succeed("
|
|
24508
|
+
spinner.succeed("Record updated");
|
|
24228
24509
|
if (opts.json) {
|
|
24229
24510
|
console.log(JSON.stringify(result, null, 2));
|
|
24230
24511
|
} else {
|
|
24231
24512
|
console.log();
|
|
24232
|
-
console.log(source_default.green("
|
|
24513
|
+
console.log(source_default.green(" Record updated successfully"));
|
|
24233
24514
|
console.log();
|
|
24234
24515
|
}
|
|
24235
24516
|
});
|
|
24236
|
-
entitiesCommand.command("delete <id>").description("Delete
|
|
24517
|
+
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) => {
|
|
24237
24518
|
await ensureAuth();
|
|
24238
24519
|
const spinner = ora();
|
|
24239
24520
|
const env2 = opts.env;
|
|
24240
24521
|
const orgId = getOrgId();
|
|
24241
24522
|
const jsonMode = !!opts.json;
|
|
24242
24523
|
if (!jsonMode)
|
|
24243
|
-
spinner.start("Resolving
|
|
24524
|
+
spinner.start("Resolving record ID");
|
|
24244
24525
|
const resolved = await resolveEntityId(rawId, env2, orgId);
|
|
24245
24526
|
if (resolved.error || !resolved.data) {
|
|
24246
24527
|
if (jsonMode) {
|
|
24247
|
-
console.log(JSON.stringify({ success: false, error: resolved.error || `No
|
|
24528
|
+
console.log(JSON.stringify({ success: false, error: resolved.error || `No record matched "${rawId}"` }));
|
|
24248
24529
|
} else {
|
|
24249
|
-
spinner.fail("
|
|
24250
|
-
console.log(source_default.red("Error:"), resolved.error || `No
|
|
24530
|
+
spinner.fail("Record not found");
|
|
24531
|
+
console.log(source_default.red("Error:"), resolved.error || `No record matched "${rawId}"`);
|
|
24251
24532
|
}
|
|
24252
24533
|
process.exit(1);
|
|
24253
24534
|
}
|
|
24254
24535
|
const id = resolved.data;
|
|
24255
24536
|
if (!jsonMode)
|
|
24256
|
-
spinner.text = "Fetching
|
|
24537
|
+
spinner.text = "Fetching record";
|
|
24257
24538
|
const { data, error: fetchError } = await queryEntity(id, env2, orgId);
|
|
24258
24539
|
if (fetchError || !data) {
|
|
24259
24540
|
if (jsonMode) {
|
|
24260
|
-
console.log(JSON.stringify({ success: false, error: fetchError || "
|
|
24541
|
+
console.log(JSON.stringify({ success: false, error: fetchError || "Record not found" }));
|
|
24261
24542
|
} else {
|
|
24262
|
-
spinner.fail("Failed to fetch
|
|
24263
|
-
console.log(source_default.red("Error:"), fetchError || "
|
|
24543
|
+
spinner.fail("Failed to fetch record");
|
|
24544
|
+
console.log(source_default.red("Error:"), fetchError || "Record not found");
|
|
24264
24545
|
}
|
|
24265
24546
|
process.exit(1);
|
|
24266
24547
|
}
|
|
24267
24548
|
if (!jsonMode)
|
|
24268
|
-
spinner.succeed("
|
|
24549
|
+
spinner.succeed("Record loaded");
|
|
24269
24550
|
const result = data;
|
|
24270
24551
|
const entity = result.entity;
|
|
24271
24552
|
const entityType = result.entityType;
|
|
@@ -24283,7 +24564,7 @@ entitiesCommand.command("delete <id>").description("Delete an entity").option("-
|
|
|
24283
24564
|
}
|
|
24284
24565
|
if (!opts.yes && !jsonMode && isInteractive2()) {
|
|
24285
24566
|
const confirmed = await esm_default2({
|
|
24286
|
-
message: "Are you sure you want to delete this
|
|
24567
|
+
message: "Are you sure you want to delete this record?",
|
|
24287
24568
|
default: false
|
|
24288
24569
|
});
|
|
24289
24570
|
if (!confirmed) {
|
|
@@ -24292,13 +24573,13 @@ entitiesCommand.command("delete <id>").description("Delete an entity").option("-
|
|
|
24292
24573
|
}
|
|
24293
24574
|
}
|
|
24294
24575
|
if (!jsonMode)
|
|
24295
|
-
spinner.start("Deleting
|
|
24576
|
+
spinner.start("Deleting record");
|
|
24296
24577
|
const { error } = await removeEntity(id, env2, orgId);
|
|
24297
24578
|
if (error) {
|
|
24298
24579
|
if (jsonMode) {
|
|
24299
24580
|
console.log(JSON.stringify({ success: false, error }));
|
|
24300
24581
|
} else {
|
|
24301
|
-
spinner.fail("Failed to delete
|
|
24582
|
+
spinner.fail("Failed to delete record");
|
|
24302
24583
|
console.log(source_default.red("Error:"), error);
|
|
24303
24584
|
}
|
|
24304
24585
|
process.exit(1);
|
|
@@ -24306,11 +24587,11 @@ entitiesCommand.command("delete <id>").description("Delete an entity").option("-
|
|
|
24306
24587
|
if (jsonMode) {
|
|
24307
24588
|
console.log(JSON.stringify({ success: true, id }));
|
|
24308
24589
|
} else {
|
|
24309
|
-
spinner.succeed("
|
|
24590
|
+
spinner.succeed("Record deleted");
|
|
24310
24591
|
console.log();
|
|
24311
24592
|
}
|
|
24312
24593
|
});
|
|
24313
|
-
entitiesCommand.command("search <type> <query>").description("Search
|
|
24594
|
+
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) => {
|
|
24314
24595
|
await ensureAuth();
|
|
24315
24596
|
const spinner = ora();
|
|
24316
24597
|
const env2 = opts.env;
|
|
@@ -24345,7 +24626,6 @@ import { join as join9 } from "path";
|
|
|
24345
24626
|
import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync6 } from "fs";
|
|
24346
24627
|
|
|
24347
24628
|
// src/cli/utils/evals.ts
|
|
24348
|
-
var CONVEX_URL3 = process.env.STRUERE_CONVEX_URL || "https://rapid-wildebeest-172.convex.cloud";
|
|
24349
24629
|
function getToken2() {
|
|
24350
24630
|
const credentials = loadCredentials();
|
|
24351
24631
|
const apiKey = getApiKey();
|
|
@@ -24356,7 +24636,7 @@ function getToken2() {
|
|
|
24356
24636
|
}
|
|
24357
24637
|
async function convexQuery2(path, args) {
|
|
24358
24638
|
const token = getToken2();
|
|
24359
|
-
const response = await fetch(`${
|
|
24639
|
+
const response = await fetch(`${CONVEX_URL}/api/query`, {
|
|
24360
24640
|
method: "POST",
|
|
24361
24641
|
headers: {
|
|
24362
24642
|
"Content-Type": "application/json",
|
|
@@ -24381,7 +24661,7 @@ async function convexQuery2(path, args) {
|
|
|
24381
24661
|
}
|
|
24382
24662
|
async function convexMutation2(path, args) {
|
|
24383
24663
|
const token = getToken2();
|
|
24384
|
-
const response = await fetch(`${
|
|
24664
|
+
const response = await fetch(`${CONVEX_URL}/api/mutation`, {
|
|
24385
24665
|
method: "POST",
|
|
24386
24666
|
headers: {
|
|
24387
24667
|
"Content-Type": "application/json",
|
|
@@ -24798,10 +25078,6 @@ evalCommand.addCommand(runCommand);
|
|
|
24798
25078
|
import { readFileSync as readFileSync4 } from "fs";
|
|
24799
25079
|
|
|
24800
25080
|
// src/cli/utils/whatsapp.ts
|
|
24801
|
-
var CONVEX_URL4 = process.env.STRUERE_CONVEX_URL || "https://rapid-wildebeest-172.convex.cloud";
|
|
24802
|
-
function getSiteUrl2() {
|
|
24803
|
-
return CONVEX_URL4.replace(".cloud", ".site");
|
|
24804
|
-
}
|
|
24805
25081
|
function getToken3() {
|
|
24806
25082
|
const credentials = loadCredentials();
|
|
24807
25083
|
const apiKey = getApiKey();
|
|
@@ -24811,7 +25087,7 @@ async function httpPost(path, body) {
|
|
|
24811
25087
|
const apiKey = getApiKey();
|
|
24812
25088
|
if (!apiKey)
|
|
24813
25089
|
return { error: "Not authenticated" };
|
|
24814
|
-
const siteUrl =
|
|
25090
|
+
const siteUrl = getSiteUrl();
|
|
24815
25091
|
try {
|
|
24816
25092
|
const response = await fetch(`${siteUrl}${path}`, {
|
|
24817
25093
|
method: "POST",
|
|
@@ -24844,7 +25120,7 @@ async function convexAction(path, args) {
|
|
|
24844
25120
|
const token = getToken3();
|
|
24845
25121
|
if (!token)
|
|
24846
25122
|
return { error: "Not authenticated" };
|
|
24847
|
-
const response = await fetch(`${
|
|
25123
|
+
const response = await fetch(`${CONVEX_URL}/api/action`, {
|
|
24848
25124
|
method: "POST",
|
|
24849
25125
|
headers: {
|
|
24850
25126
|
"Content-Type": "application/json",
|
|
@@ -24873,7 +25149,7 @@ async function convexQuery3(path, args) {
|
|
|
24873
25149
|
const token = getToken3();
|
|
24874
25150
|
if (!token)
|
|
24875
25151
|
return { error: "Not authenticated" };
|
|
24876
|
-
const response = await fetch(`${
|
|
25152
|
+
const response = await fetch(`${CONVEX_URL}/api/query`, {
|
|
24877
25153
|
method: "POST",
|
|
24878
25154
|
headers: {
|
|
24879
25155
|
"Content-Type": "application/json",
|
|
@@ -24907,16 +25183,15 @@ async function listWhatsAppConnections(env2) {
|
|
|
24907
25183
|
}
|
|
24908
25184
|
return convexQuery3("whatsapp:listConnections", { environment: env2 });
|
|
24909
25185
|
}
|
|
24910
|
-
async function listTemplates(connectionId
|
|
25186
|
+
async function listTemplates(connectionId) {
|
|
24911
25187
|
if (getApiKey()) {
|
|
24912
25188
|
return httpPost("/v1/templates/list", { connectionId });
|
|
24913
25189
|
}
|
|
24914
25190
|
return convexAction("whatsappActions:listTemplates", {
|
|
24915
|
-
connectionId
|
|
24916
|
-
environment: env2
|
|
25191
|
+
connectionId
|
|
24917
25192
|
});
|
|
24918
25193
|
}
|
|
24919
|
-
async function createTemplate(connectionId,
|
|
25194
|
+
async function createTemplate(connectionId, name, language, category, components, allowCategoryChange) {
|
|
24920
25195
|
if (getApiKey()) {
|
|
24921
25196
|
return httpPost("/v1/templates/create", {
|
|
24922
25197
|
connectionId,
|
|
@@ -24929,7 +25204,6 @@ async function createTemplate(connectionId, env2, name, language, category, comp
|
|
|
24929
25204
|
}
|
|
24930
25205
|
return convexAction("whatsappActions:createTemplate", {
|
|
24931
25206
|
connectionId,
|
|
24932
|
-
environment: env2,
|
|
24933
25207
|
name,
|
|
24934
25208
|
language,
|
|
24935
25209
|
category,
|
|
@@ -24937,23 +25211,21 @@ async function createTemplate(connectionId, env2, name, language, category, comp
|
|
|
24937
25211
|
...allowCategoryChange !== undefined && { allowCategoryChange }
|
|
24938
25212
|
});
|
|
24939
25213
|
}
|
|
24940
|
-
async function deleteTemplate(connectionId,
|
|
25214
|
+
async function deleteTemplate(connectionId, name) {
|
|
24941
25215
|
if (getApiKey()) {
|
|
24942
25216
|
return httpPost("/v1/templates/delete", { connectionId, name });
|
|
24943
25217
|
}
|
|
24944
25218
|
return convexAction("whatsappActions:deleteTemplate", {
|
|
24945
25219
|
connectionId,
|
|
24946
|
-
environment: env2,
|
|
24947
25220
|
name
|
|
24948
25221
|
});
|
|
24949
25222
|
}
|
|
24950
|
-
async function getTemplateStatus(connectionId,
|
|
25223
|
+
async function getTemplateStatus(connectionId, name) {
|
|
24951
25224
|
if (getApiKey()) {
|
|
24952
25225
|
return httpPost("/v1/templates/status", { connectionId, name });
|
|
24953
25226
|
}
|
|
24954
25227
|
return convexAction("whatsappActions:getTemplateStatus", {
|
|
24955
25228
|
connectionId,
|
|
24956
|
-
environment: env2,
|
|
24957
25229
|
name
|
|
24958
25230
|
});
|
|
24959
25231
|
}
|
|
@@ -25049,13 +25321,12 @@ function statusColor2(status) {
|
|
|
25049
25321
|
}
|
|
25050
25322
|
}
|
|
25051
25323
|
var templatesCommand = new Command("templates").description("Manage WhatsApp message templates");
|
|
25052
|
-
templatesCommand.command("list").description("List all message templates").option("--
|
|
25324
|
+
templatesCommand.command("list").description("List all message templates").option("--connection <id>", "WhatsApp connection ID").option("--json", "Output raw JSON").action(async (opts) => {
|
|
25053
25325
|
await ensureAuth2();
|
|
25054
|
-
const
|
|
25055
|
-
const connectionId = await resolveConnectionId(env2, opts.connection);
|
|
25326
|
+
const connectionId = await resolveConnectionId("development", opts.connection);
|
|
25056
25327
|
const out = createOutput();
|
|
25057
25328
|
out.start("Fetching templates");
|
|
25058
|
-
const { data, error } = await listTemplates(connectionId
|
|
25329
|
+
const { data, error } = await listTemplates(connectionId);
|
|
25059
25330
|
if (error) {
|
|
25060
25331
|
out.fail("Failed to fetch templates");
|
|
25061
25332
|
out.error(error);
|
|
@@ -25087,10 +25358,9 @@ templatesCommand.command("list").description("List all message templates").optio
|
|
|
25087
25358
|
})));
|
|
25088
25359
|
console.log();
|
|
25089
25360
|
});
|
|
25090
|
-
templatesCommand.command("create <name>").description("Create a new message template").option("--
|
|
25361
|
+
templatesCommand.command("create <name>").description("Create a new message template").option("--connection <id>", "WhatsApp connection ID").option("--language <code>", "Language code", "en_US").option("--category <cat>", "Category (UTILITY|MARKETING|AUTHENTICATION)", "UTILITY").option("--components <json>", "Components as JSON string").option("--file <path>", "Read components from a JSON file").option("--allow-category-change", "Allow Meta to reassign category").option("--json", "Output raw JSON").action(async (name, opts) => {
|
|
25091
25362
|
await ensureAuth2();
|
|
25092
|
-
const
|
|
25093
|
-
const connectionId = await resolveConnectionId(env2, opts.connection);
|
|
25363
|
+
const connectionId = await resolveConnectionId("development", opts.connection);
|
|
25094
25364
|
let components;
|
|
25095
25365
|
if (opts.file) {
|
|
25096
25366
|
try {
|
|
@@ -25118,7 +25388,7 @@ templatesCommand.command("create <name>").description("Create a new message temp
|
|
|
25118
25388
|
}
|
|
25119
25389
|
const out = createOutput();
|
|
25120
25390
|
out.start(`Creating template "${name}"`);
|
|
25121
|
-
const { data, error } = await createTemplate(connectionId,
|
|
25391
|
+
const { data, error } = await createTemplate(connectionId, name, opts.language, opts.category.toUpperCase(), components, opts.allowCategoryChange);
|
|
25122
25392
|
if (error) {
|
|
25123
25393
|
out.fail("Failed to create template");
|
|
25124
25394
|
out.error(error);
|
|
@@ -25136,10 +25406,9 @@ templatesCommand.command("create <name>").description("Create a new message temp
|
|
|
25136
25406
|
console.log();
|
|
25137
25407
|
}
|
|
25138
25408
|
});
|
|
25139
|
-
templatesCommand.command("delete <name>").description("Delete a message template").option("--
|
|
25409
|
+
templatesCommand.command("delete <name>").description("Delete a message template").option("--connection <id>", "WhatsApp connection ID").option("--yes", "Skip confirmation").action(async (name, opts) => {
|
|
25140
25410
|
await ensureAuth2();
|
|
25141
|
-
const
|
|
25142
|
-
const connectionId = await resolveConnectionId(env2, opts.connection);
|
|
25411
|
+
const connectionId = await resolveConnectionId("development", opts.connection);
|
|
25143
25412
|
if (!opts.yes && isInteractive2()) {
|
|
25144
25413
|
const confirmed = await esm_default2({
|
|
25145
25414
|
message: `Delete template "${name}"? This cannot be undone.`,
|
|
@@ -25152,7 +25421,7 @@ templatesCommand.command("delete <name>").description("Delete a message template
|
|
|
25152
25421
|
}
|
|
25153
25422
|
const out = createOutput();
|
|
25154
25423
|
out.start(`Deleting template "${name}"`);
|
|
25155
|
-
const { error } = await deleteTemplate(connectionId,
|
|
25424
|
+
const { error } = await deleteTemplate(connectionId, name);
|
|
25156
25425
|
if (error) {
|
|
25157
25426
|
out.fail("Failed to delete template");
|
|
25158
25427
|
out.error(error);
|
|
@@ -25161,13 +25430,12 @@ templatesCommand.command("delete <name>").description("Delete a message template
|
|
|
25161
25430
|
out.succeed(`Template "${name}" deleted`);
|
|
25162
25431
|
console.log();
|
|
25163
25432
|
});
|
|
25164
|
-
templatesCommand.command("status <name>").description("Check template approval status").option("--
|
|
25433
|
+
templatesCommand.command("status <name>").description("Check template approval status").option("--connection <id>", "WhatsApp connection ID").option("--json", "Output raw JSON").action(async (name, opts) => {
|
|
25165
25434
|
await ensureAuth2();
|
|
25166
|
-
const
|
|
25167
|
-
const connectionId = await resolveConnectionId(env2, opts.connection);
|
|
25435
|
+
const connectionId = await resolveConnectionId("development", opts.connection);
|
|
25168
25436
|
const out = createOutput();
|
|
25169
25437
|
out.start(`Checking status for "${name}"`);
|
|
25170
|
-
const { data, error } = await getTemplateStatus(connectionId,
|
|
25438
|
+
const { data, error } = await getTemplateStatus(connectionId, name);
|
|
25171
25439
|
if (error) {
|
|
25172
25440
|
out.fail("Failed to fetch template status");
|
|
25173
25441
|
out.error(error);
|
|
@@ -25200,7 +25468,6 @@ templatesCommand.command("status <name>").description("Check template approval s
|
|
|
25200
25468
|
});
|
|
25201
25469
|
|
|
25202
25470
|
// src/cli/utils/integrations.ts
|
|
25203
|
-
var CONVEX_URL5 = process.env.STRUERE_CONVEX_URL || "https://rapid-wildebeest-172.convex.cloud";
|
|
25204
25471
|
function getToken4() {
|
|
25205
25472
|
const credentials = loadCredentials();
|
|
25206
25473
|
const apiKey = getApiKey();
|
|
@@ -25210,7 +25477,7 @@ async function convexQuery4(path, args) {
|
|
|
25210
25477
|
const token = getToken4();
|
|
25211
25478
|
if (!token)
|
|
25212
25479
|
return { error: "Not authenticated" };
|
|
25213
|
-
const response = await fetch(`${
|
|
25480
|
+
const response = await fetch(`${CONVEX_URL}/api/query`, {
|
|
25214
25481
|
method: "POST",
|
|
25215
25482
|
headers: {
|
|
25216
25483
|
"Content-Type": "application/json",
|
|
@@ -25239,7 +25506,7 @@ async function convexMutation3(path, args) {
|
|
|
25239
25506
|
const token = getToken4();
|
|
25240
25507
|
if (!token)
|
|
25241
25508
|
return { error: "Not authenticated" };
|
|
25242
|
-
const response = await fetch(`${
|
|
25509
|
+
const response = await fetch(`${CONVEX_URL}/api/mutation`, {
|
|
25243
25510
|
method: "POST",
|
|
25244
25511
|
headers: {
|
|
25245
25512
|
"Content-Type": "application/json",
|
|
@@ -25268,7 +25535,7 @@ async function convexAction2(path, args) {
|
|
|
25268
25535
|
const token = getToken4();
|
|
25269
25536
|
if (!token)
|
|
25270
25537
|
return { error: "Not authenticated" };
|
|
25271
|
-
const response = await fetch(`${
|
|
25538
|
+
const response = await fetch(`${CONVEX_URL}/api/action`, {
|
|
25272
25539
|
method: "POST",
|
|
25273
25540
|
headers: {
|
|
25274
25541
|
"Content-Type": "application/json",
|
|
@@ -25313,7 +25580,7 @@ async function setIntegrationStatus(provider, env2, status) {
|
|
|
25313
25580
|
}
|
|
25314
25581
|
|
|
25315
25582
|
// src/cli/commands/integration.ts
|
|
25316
|
-
var VALID_PROVIDERS = ["airtable", "resend"];
|
|
25583
|
+
var VALID_PROVIDERS = ["airtable", "resend", "flow"];
|
|
25317
25584
|
async function ensureAuth3() {
|
|
25318
25585
|
const cwd = process.cwd();
|
|
25319
25586
|
const nonInteractive = !isInteractive2();
|
|
@@ -25366,6 +25633,8 @@ function getProviderHelp(provider) {
|
|
|
25366
25633
|
return `Usage: struere integration airtable --token <pat> [--base-id <id>] [--test]`;
|
|
25367
25634
|
case "resend":
|
|
25368
25635
|
return `Usage: struere integration resend --from-email <email> [--from-name <name>] [--reply-to <email>]`;
|
|
25636
|
+
case "flow":
|
|
25637
|
+
return `Usage: struere integration flow --api-url <url> --api-key <key> --secret-key <secret> [--return-url <url>]`;
|
|
25369
25638
|
default:
|
|
25370
25639
|
return "";
|
|
25371
25640
|
}
|
|
@@ -25393,9 +25662,23 @@ function buildConfigFromOpts(provider, opts) {
|
|
|
25393
25662
|
return null;
|
|
25394
25663
|
return config;
|
|
25395
25664
|
}
|
|
25665
|
+
if (provider === "flow") {
|
|
25666
|
+
const config = {};
|
|
25667
|
+
if (opts.apiUrl)
|
|
25668
|
+
config.apiUrl = opts.apiUrl;
|
|
25669
|
+
if (opts.apiKey)
|
|
25670
|
+
config.apiKey = opts.apiKey;
|
|
25671
|
+
if (opts.secretKey)
|
|
25672
|
+
config.secretKey = opts.secretKey;
|
|
25673
|
+
if (opts.returnUrl)
|
|
25674
|
+
config.returnUrl = opts.returnUrl;
|
|
25675
|
+
if (Object.keys(config).length === 0)
|
|
25676
|
+
return null;
|
|
25677
|
+
return config;
|
|
25678
|
+
}
|
|
25396
25679
|
return null;
|
|
25397
25680
|
}
|
|
25398
|
-
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) => {
|
|
25681
|
+
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) => {
|
|
25399
25682
|
await ensureAuth3();
|
|
25400
25683
|
const env2 = opts.env;
|
|
25401
25684
|
const out = createOutput();
|
|
@@ -25570,10 +25853,154 @@ var integrationCommand = new Command("integration").description("Manage integrat
|
|
|
25570
25853
|
}
|
|
25571
25854
|
console.log();
|
|
25572
25855
|
});
|
|
25856
|
+
|
|
25857
|
+
// src/cli/commands/compile-prompt.ts
|
|
25858
|
+
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) => {
|
|
25859
|
+
acc.push(val);
|
|
25860
|
+
return acc;
|
|
25861
|
+
}, []).option("--json", "Output full JSON (raw + compiled + context)").option("--raw", "Show raw uncompiled template instead of compiled").action(async (agentSlug, options) => {
|
|
25862
|
+
const spinner = ora();
|
|
25863
|
+
const cwd = process.cwd();
|
|
25864
|
+
const nonInteractive = !isInteractive2();
|
|
25865
|
+
const jsonMode = !!options.json;
|
|
25866
|
+
if (!hasProject(cwd)) {
|
|
25867
|
+
if (nonInteractive) {
|
|
25868
|
+
if (jsonMode) {
|
|
25869
|
+
console.log(JSON.stringify({ success: false, error: "No struere.json found" }));
|
|
25870
|
+
} else {
|
|
25871
|
+
console.log(source_default.red("No struere.json found. Run struere init first."));
|
|
25872
|
+
}
|
|
25873
|
+
process.exit(1);
|
|
25874
|
+
}
|
|
25875
|
+
console.log(source_default.yellow("No struere.json found - initializing project..."));
|
|
25876
|
+
console.log();
|
|
25877
|
+
const success = await runInit(cwd);
|
|
25878
|
+
if (!success) {
|
|
25879
|
+
process.exit(1);
|
|
25880
|
+
}
|
|
25881
|
+
console.log();
|
|
25882
|
+
}
|
|
25883
|
+
const project = loadProject(cwd);
|
|
25884
|
+
if (!project) {
|
|
25885
|
+
if (jsonMode) {
|
|
25886
|
+
console.log(JSON.stringify({ success: false, error: "Failed to load struere.json" }));
|
|
25887
|
+
} else {
|
|
25888
|
+
console.log(source_default.red("Failed to load struere.json"));
|
|
25889
|
+
}
|
|
25890
|
+
process.exit(1);
|
|
25891
|
+
}
|
|
25892
|
+
let credentials = loadCredentials();
|
|
25893
|
+
const apiKey = getApiKey();
|
|
25894
|
+
if (!credentials && !apiKey) {
|
|
25895
|
+
if (nonInteractive) {
|
|
25896
|
+
if (jsonMode) {
|
|
25897
|
+
console.log(JSON.stringify({ success: false, error: "Not authenticated. Set STRUERE_API_KEY or run struere login." }));
|
|
25898
|
+
} else {
|
|
25899
|
+
console.log(source_default.red("Not authenticated. Set STRUERE_API_KEY or run struere login."));
|
|
25900
|
+
}
|
|
25901
|
+
process.exit(1);
|
|
25902
|
+
}
|
|
25903
|
+
console.log(source_default.yellow("Not logged in - authenticating..."));
|
|
25904
|
+
console.log();
|
|
25905
|
+
credentials = await performLogin();
|
|
25906
|
+
if (!credentials) {
|
|
25907
|
+
console.log(source_default.red("Authentication failed"));
|
|
25908
|
+
process.exit(1);
|
|
25909
|
+
}
|
|
25910
|
+
console.log();
|
|
25911
|
+
}
|
|
25912
|
+
const threadMetadata = {};
|
|
25913
|
+
for (const param of options.param) {
|
|
25914
|
+
const eqIndex = param.indexOf("=");
|
|
25915
|
+
if (eqIndex === -1) {
|
|
25916
|
+
if (jsonMode) {
|
|
25917
|
+
console.log(JSON.stringify({ success: false, error: `Invalid param format: ${param}. Use key=value.` }));
|
|
25918
|
+
} else {
|
|
25919
|
+
console.log(source_default.red(`Invalid param format: ${param}. Use key=value.`));
|
|
25920
|
+
}
|
|
25921
|
+
process.exit(1);
|
|
25922
|
+
}
|
|
25923
|
+
const key = param.slice(0, eqIndex);
|
|
25924
|
+
const value = param.slice(eqIndex + 1);
|
|
25925
|
+
threadMetadata[key] = value;
|
|
25926
|
+
}
|
|
25927
|
+
const environment = options.env;
|
|
25928
|
+
if (!jsonMode) {
|
|
25929
|
+
spinner.start(`Compiling prompt for ${source_default.cyan(agentSlug)} (${environment})`);
|
|
25930
|
+
}
|
|
25931
|
+
const doCompile = async () => {
|
|
25932
|
+
return compilePrompt({
|
|
25933
|
+
slug: agentSlug,
|
|
25934
|
+
environment,
|
|
25935
|
+
message: options.message,
|
|
25936
|
+
channel: options.channel,
|
|
25937
|
+
threadMetadata: Object.keys(threadMetadata).length > 0 ? threadMetadata : undefined
|
|
25938
|
+
});
|
|
25939
|
+
};
|
|
25940
|
+
let { result, error } = await doCompile();
|
|
25941
|
+
if (error && isAuthError(error) && !nonInteractive) {
|
|
25942
|
+
if (!jsonMode)
|
|
25943
|
+
spinner.fail("Session expired - re-authenticating...");
|
|
25944
|
+
clearCredentials();
|
|
25945
|
+
credentials = await performLogin();
|
|
25946
|
+
if (!credentials) {
|
|
25947
|
+
if (jsonMode) {
|
|
25948
|
+
console.log(JSON.stringify({ success: false, error: "Authentication failed" }));
|
|
25949
|
+
} else {
|
|
25950
|
+
console.log(source_default.red("Authentication failed"));
|
|
25951
|
+
}
|
|
25952
|
+
process.exit(1);
|
|
25953
|
+
}
|
|
25954
|
+
const retry = await doCompile();
|
|
25955
|
+
result = retry.result;
|
|
25956
|
+
error = retry.error;
|
|
25957
|
+
if (!jsonMode && !error)
|
|
25958
|
+
spinner.succeed("Compiled prompt");
|
|
25959
|
+
}
|
|
25960
|
+
if (error) {
|
|
25961
|
+
if (jsonMode) {
|
|
25962
|
+
console.log(JSON.stringify({ success: false, error }));
|
|
25963
|
+
} else {
|
|
25964
|
+
spinner.fail("Failed to compile prompt");
|
|
25965
|
+
console.log(source_default.red("Error:"), error);
|
|
25966
|
+
}
|
|
25967
|
+
process.exit(1);
|
|
25968
|
+
}
|
|
25969
|
+
if (!result) {
|
|
25970
|
+
if (jsonMode) {
|
|
25971
|
+
console.log(JSON.stringify({ success: false, error: "No result returned" }));
|
|
25972
|
+
} else {
|
|
25973
|
+
spinner.fail("No result returned");
|
|
25974
|
+
}
|
|
25975
|
+
process.exit(1);
|
|
25976
|
+
}
|
|
25977
|
+
if (!jsonMode)
|
|
25978
|
+
spinner.succeed("Compiled prompt");
|
|
25979
|
+
if (jsonMode) {
|
|
25980
|
+
console.log(JSON.stringify({
|
|
25981
|
+
success: true,
|
|
25982
|
+
raw: result.raw,
|
|
25983
|
+
compiled: result.compiled,
|
|
25984
|
+
context: result.context
|
|
25985
|
+
}, null, 2));
|
|
25986
|
+
} else if (options.raw) {
|
|
25987
|
+
console.log();
|
|
25988
|
+
console.log(source_default.bold("Raw System Prompt"));
|
|
25989
|
+
console.log(source_default.gray("\u2500".repeat(60)));
|
|
25990
|
+
console.log(result.raw);
|
|
25991
|
+
console.log(source_default.gray("\u2500".repeat(60)));
|
|
25992
|
+
} else {
|
|
25993
|
+
console.log();
|
|
25994
|
+
console.log(source_default.bold("Compiled System Prompt"));
|
|
25995
|
+
console.log(source_default.gray("\u2500".repeat(60)));
|
|
25996
|
+
console.log(result.compiled);
|
|
25997
|
+
console.log(source_default.gray("\u2500".repeat(60)));
|
|
25998
|
+
}
|
|
25999
|
+
});
|
|
25573
26000
|
// package.json
|
|
25574
26001
|
var package_default = {
|
|
25575
26002
|
name: "struere",
|
|
25576
|
-
version: "0.9.
|
|
26003
|
+
version: "0.9.9",
|
|
25577
26004
|
description: "Build, test, and deploy AI agents",
|
|
25578
26005
|
keywords: [
|
|
25579
26006
|
"ai",
|
|
@@ -25677,6 +26104,7 @@ program.addCommand(initCommand);
|
|
|
25677
26104
|
program.addCommand(loginCommand);
|
|
25678
26105
|
program.addCommand(logoutCommand);
|
|
25679
26106
|
program.addCommand(whoamiCommand);
|
|
26107
|
+
program.addCommand(orgCommand);
|
|
25680
26108
|
program.addCommand(syncCommand);
|
|
25681
26109
|
program.addCommand(devCommand);
|
|
25682
26110
|
program.addCommand(deployCommand);
|
|
@@ -25688,4 +26116,5 @@ program.addCommand(docsCommand);
|
|
|
25688
26116
|
program.addCommand(evalCommand);
|
|
25689
26117
|
program.addCommand(templatesCommand);
|
|
25690
26118
|
program.addCommand(integrationCommand);
|
|
26119
|
+
program.addCommand(compilePromptCommand);
|
|
25691
26120
|
program.parse();
|