struere 0.12.7 → 0.12.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 +447 -181
- package/dist/cli/commands/chat.d.ts.map +1 -1
- package/dist/cli/commands/compile-prompt.d.ts.map +1 -1
- package/dist/cli/commands/deploy.d.ts.map +1 -1
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/run-tool.d.ts.map +1 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/sync.d.ts.map +1 -1
- package/dist/cli/commands/triggers.d.ts.map +1 -1
- package/dist/cli/index.js +447 -181
- package/dist/cli/utils/convex.d.ts +44 -2
- package/dist/cli/utils/convex.d.ts.map +1 -1
- package/dist/cli/utils/extractor.d.ts +6 -0
- package/dist/cli/utils/extractor.d.ts.map +1 -1
- package/dist/cli/utils/loader.d.ts +1 -0
- package/dist/cli/utils/loader.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/triggers.d.ts +3 -2
- package/dist/cli/utils/triggers.d.ts.map +1 -1
- package/dist/cli/utils/validator.d.ts +8 -0
- package/dist/cli/utils/validator.d.ts.map +1 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/bin/struere.js
CHANGED
|
@@ -33,11 +33,24 @@ __export(exports_convex, {
|
|
|
33
33
|
getSyncState: () => getSyncState,
|
|
34
34
|
getSiteUrl: () => getSiteUrl,
|
|
35
35
|
getPullState: () => getPullState,
|
|
36
|
+
fireTrigger: () => fireTrigger,
|
|
36
37
|
createOrganization: () => createOrganization,
|
|
37
38
|
compilePrompt: () => compilePrompt,
|
|
38
39
|
chatWithRouter: () => chatWithRouter,
|
|
39
40
|
chatWithAgent: () => chatWithAgent
|
|
40
41
|
});
|
|
42
|
+
function isAuthErrorMessage(error) {
|
|
43
|
+
return error.includes("Unauthenticated") || error.includes("OIDC") || error.includes("token") || error.includes("expired");
|
|
44
|
+
}
|
|
45
|
+
async function withAuthRetry(fn) {
|
|
46
|
+
const result = await fn();
|
|
47
|
+
if (!result.error || !isAuthErrorMessage(result.error))
|
|
48
|
+
return result;
|
|
49
|
+
const refreshed = await refreshToken();
|
|
50
|
+
if (!refreshed)
|
|
51
|
+
return result;
|
|
52
|
+
return fn();
|
|
53
|
+
}
|
|
41
54
|
async function refreshToken() {
|
|
42
55
|
const credentials = loadCredentials();
|
|
43
56
|
if (!credentials?.sessionId)
|
|
@@ -211,6 +224,9 @@ async function syncViaHttp(apiKey, payload) {
|
|
|
211
224
|
return json;
|
|
212
225
|
}
|
|
213
226
|
async function syncOrganization(payload) {
|
|
227
|
+
return withAuthRetry(() => _syncOrganization(payload));
|
|
228
|
+
}
|
|
229
|
+
async function _syncOrganization(payload) {
|
|
214
230
|
const credentials = loadCredentials();
|
|
215
231
|
const apiKey = getApiKey();
|
|
216
232
|
if (apiKey && !credentials?.token) {
|
|
@@ -274,6 +290,9 @@ async function syncOrganization(payload) {
|
|
|
274
290
|
return { success: false, error: `Unexpected response: ${text}` };
|
|
275
291
|
}
|
|
276
292
|
async function getSyncState(organizationId, environment) {
|
|
293
|
+
return withAuthRetry(() => _getSyncState(organizationId, environment));
|
|
294
|
+
}
|
|
295
|
+
async function _getSyncState(organizationId, environment) {
|
|
277
296
|
const credentials = loadCredentials();
|
|
278
297
|
const apiKey = getApiKey();
|
|
279
298
|
if (apiKey && !credentials?.token) {
|
|
@@ -330,6 +349,9 @@ async function getSyncState(organizationId, environment) {
|
|
|
330
349
|
return { error: `Unexpected response: ${JSON.stringify(result)}` };
|
|
331
350
|
}
|
|
332
351
|
async function compilePrompt(options) {
|
|
352
|
+
return withAuthRetry(() => _compilePrompt(options));
|
|
353
|
+
}
|
|
354
|
+
async function _compilePrompt(options) {
|
|
333
355
|
const credentials = loadCredentials();
|
|
334
356
|
const apiKey = getApiKey();
|
|
335
357
|
if (apiKey && !credentials?.token) {
|
|
@@ -440,6 +462,9 @@ async function compilePrompt(options) {
|
|
|
440
462
|
return { error: `Unexpected response: ${text}` };
|
|
441
463
|
}
|
|
442
464
|
async function runTool(options) {
|
|
465
|
+
return withAuthRetry(() => _runTool(options));
|
|
466
|
+
}
|
|
467
|
+
async function _runTool(options) {
|
|
443
468
|
const credentials = loadCredentials();
|
|
444
469
|
const apiKey = getApiKey();
|
|
445
470
|
if (apiKey && !credentials?.token) {
|
|
@@ -484,6 +509,43 @@ async function runTool(options) {
|
|
|
484
509
|
if (!token) {
|
|
485
510
|
return { error: "Not authenticated" };
|
|
486
511
|
}
|
|
512
|
+
if (!options.agentSlug) {
|
|
513
|
+
const response2 = await fetch(`${CONVEX_URL}/api/action`, {
|
|
514
|
+
method: "POST",
|
|
515
|
+
headers: {
|
|
516
|
+
"Content-Type": "application/json",
|
|
517
|
+
Authorization: `Bearer ${token}`
|
|
518
|
+
},
|
|
519
|
+
body: JSON.stringify({
|
|
520
|
+
path: "toolTesting:runTool",
|
|
521
|
+
args: {
|
|
522
|
+
environment: options.environment,
|
|
523
|
+
toolName: options.toolName,
|
|
524
|
+
toolArgs: options.toolArgs,
|
|
525
|
+
organizationId: options.organizationId
|
|
526
|
+
}
|
|
527
|
+
}),
|
|
528
|
+
signal: AbortSignal.timeout(30000)
|
|
529
|
+
});
|
|
530
|
+
const text2 = await response2.text();
|
|
531
|
+
let json2;
|
|
532
|
+
try {
|
|
533
|
+
json2 = JSON.parse(text2);
|
|
534
|
+
} catch {
|
|
535
|
+
return { error: text2 || `HTTP ${response2.status}` };
|
|
536
|
+
}
|
|
537
|
+
if (!response2.ok) {
|
|
538
|
+
const msg = json2.errorData?.message || json2.errorMessage || text2;
|
|
539
|
+
return { error: msg };
|
|
540
|
+
}
|
|
541
|
+
if (json2.status === "success" && json2.value) {
|
|
542
|
+
return { result: json2.value };
|
|
543
|
+
}
|
|
544
|
+
if (json2.status === "error") {
|
|
545
|
+
return { error: json2.errorData?.message || json2.errorMessage || "Unknown error from Convex" };
|
|
546
|
+
}
|
|
547
|
+
return { error: `Unexpected response: ${text2}` };
|
|
548
|
+
}
|
|
487
549
|
const agentResponse = await fetch(`${CONVEX_URL}/api/query`, {
|
|
488
550
|
method: "POST",
|
|
489
551
|
headers: {
|
|
@@ -545,7 +607,97 @@ async function runTool(options) {
|
|
|
545
607
|
}
|
|
546
608
|
return { error: `Unexpected response: ${text}` };
|
|
547
609
|
}
|
|
610
|
+
async function fireTrigger(options) {
|
|
611
|
+
return withAuthRetry(() => _fireTrigger(options));
|
|
612
|
+
}
|
|
613
|
+
async function _fireTrigger(options) {
|
|
614
|
+
const credentials = loadCredentials();
|
|
615
|
+
const apiKey = getApiKey();
|
|
616
|
+
if (apiKey && !credentials?.token) {
|
|
617
|
+
const siteUrl = getSiteUrl();
|
|
618
|
+
try {
|
|
619
|
+
const response2 = await fetch(`${siteUrl}/v1/fire-trigger`, {
|
|
620
|
+
method: "POST",
|
|
621
|
+
headers: {
|
|
622
|
+
"Content-Type": "application/json",
|
|
623
|
+
Authorization: `Bearer ${apiKey}`
|
|
624
|
+
},
|
|
625
|
+
body: JSON.stringify({
|
|
626
|
+
slug: options.slug,
|
|
627
|
+
entityId: options.entityId,
|
|
628
|
+
data: options.data
|
|
629
|
+
}),
|
|
630
|
+
signal: AbortSignal.timeout(60000)
|
|
631
|
+
});
|
|
632
|
+
const text2 = await response2.text();
|
|
633
|
+
let json2;
|
|
634
|
+
try {
|
|
635
|
+
json2 = JSON.parse(text2);
|
|
636
|
+
} catch {
|
|
637
|
+
return { error: text2 || `HTTP ${response2.status}` };
|
|
638
|
+
}
|
|
639
|
+
if (!response2.ok) {
|
|
640
|
+
return { error: json2.error || text2 };
|
|
641
|
+
}
|
|
642
|
+
return { result: json2 };
|
|
643
|
+
} catch (err) {
|
|
644
|
+
if (err instanceof DOMException && err.name === "TimeoutError") {
|
|
645
|
+
return { error: "Request timed out after 60s" };
|
|
646
|
+
}
|
|
647
|
+
return { error: `Network error: ${err instanceof Error ? err.message : String(err)}` };
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
if (credentials?.sessionId) {
|
|
651
|
+
await refreshToken();
|
|
652
|
+
}
|
|
653
|
+
const freshCredentials = loadCredentials();
|
|
654
|
+
const token = apiKey || freshCredentials?.token;
|
|
655
|
+
if (!token) {
|
|
656
|
+
return { error: "Not authenticated" };
|
|
657
|
+
}
|
|
658
|
+
const response = await fetch(`${CONVEX_URL}/api/action`, {
|
|
659
|
+
method: "POST",
|
|
660
|
+
headers: {
|
|
661
|
+
"Content-Type": "application/json",
|
|
662
|
+
Authorization: `Bearer ${token}`
|
|
663
|
+
},
|
|
664
|
+
body: JSON.stringify({
|
|
665
|
+
path: "triggers:fire",
|
|
666
|
+
args: {
|
|
667
|
+
slug: options.slug,
|
|
668
|
+
environment: options.environment,
|
|
669
|
+
entityId: options.entityId,
|
|
670
|
+
data: options.data
|
|
671
|
+
}
|
|
672
|
+
}),
|
|
673
|
+
signal: AbortSignal.timeout(60000)
|
|
674
|
+
});
|
|
675
|
+
const text = await response.text();
|
|
676
|
+
let json;
|
|
677
|
+
try {
|
|
678
|
+
json = JSON.parse(text);
|
|
679
|
+
} catch {
|
|
680
|
+
return { error: text || `HTTP ${response.status}` };
|
|
681
|
+
}
|
|
682
|
+
if (!response.ok) {
|
|
683
|
+
const msg = json.errorData?.message || json.errorMessage || text;
|
|
684
|
+
return { error: msg };
|
|
685
|
+
}
|
|
686
|
+
if (json.status === "success" && json.value) {
|
|
687
|
+
return { result: json.value };
|
|
688
|
+
}
|
|
689
|
+
if (json.status === "success" && json.value === null) {
|
|
690
|
+
return { error: `Trigger not found: ${options.slug}` };
|
|
691
|
+
}
|
|
692
|
+
if (json.status === "error") {
|
|
693
|
+
return { error: json.errorData?.message || json.errorMessage || "Unknown error from Convex" };
|
|
694
|
+
}
|
|
695
|
+
return { error: `Unexpected response: ${text}` };
|
|
696
|
+
}
|
|
548
697
|
async function chatWithAgent(options) {
|
|
698
|
+
return withAuthRetry(() => _chatWithAgent(options));
|
|
699
|
+
}
|
|
700
|
+
async function _chatWithAgent(options) {
|
|
549
701
|
const credentials = loadCredentials();
|
|
550
702
|
const apiKey = getApiKey();
|
|
551
703
|
if (apiKey && !credentials?.token) {
|
|
@@ -639,6 +791,9 @@ async function chatWithAgent(options) {
|
|
|
639
791
|
}
|
|
640
792
|
}
|
|
641
793
|
async function chatWithRouter(options) {
|
|
794
|
+
return withAuthRetry(() => _chatWithRouter(options));
|
|
795
|
+
}
|
|
796
|
+
async function _chatWithRouter(options) {
|
|
642
797
|
const credentials = loadCredentials();
|
|
643
798
|
const apiKey = getApiKey();
|
|
644
799
|
if (credentials?.sessionId) {
|
|
@@ -698,6 +853,9 @@ async function chatWithRouter(options) {
|
|
|
698
853
|
}
|
|
699
854
|
}
|
|
700
855
|
async function getPullState(organizationId, environment = "development") {
|
|
856
|
+
return withAuthRetry(() => _getPullState(organizationId, environment));
|
|
857
|
+
}
|
|
858
|
+
async function _getPullState(organizationId, environment = "development") {
|
|
701
859
|
const credentials = loadCredentials();
|
|
702
860
|
const apiKey = getApiKey();
|
|
703
861
|
if (apiKey && !credentials?.token) {
|
|
@@ -803,7 +961,7 @@ async function getValidToken() {
|
|
|
803
961
|
if (!credentials?.token)
|
|
804
962
|
return { error: "Not authenticated. Run `struere login`." };
|
|
805
963
|
const expiry = getJwtExpiry(credentials.token);
|
|
806
|
-
const needsRefresh = !expiry || expiry.getTime() - Date.now() <
|
|
964
|
+
const needsRefresh = !expiry || expiry.getTime() - Date.now() < 300000;
|
|
807
965
|
if (!needsRefresh)
|
|
808
966
|
return { token: credentials.token };
|
|
809
967
|
const { refreshToken: refreshToken2 } = await Promise.resolve().then(() => (init_convex(), exports_convex));
|
|
@@ -1684,7 +1842,7 @@ function defineTrigger(config) {
|
|
|
1684
1842
|
if (!config.slug) throw new Error('Trigger slug is required')
|
|
1685
1843
|
if (!config.on) throw new Error('Trigger "on" configuration is required')
|
|
1686
1844
|
if (config.on.schedule) {
|
|
1687
|
-
const parts = config.on.schedule.trim().split(
|
|
1845
|
+
const parts = config.on.schedule.trim().split(/\\s+/)
|
|
1688
1846
|
if (parts.length !== 5) throw new Error('Invalid cron expression: expected 5 fields, got ' + parts.length)
|
|
1689
1847
|
} else {
|
|
1690
1848
|
if (!config.on.entityType) throw new Error('Trigger entityType is required')
|
|
@@ -2062,6 +2220,26 @@ async function importUserFile(filePath) {
|
|
|
2062
2220
|
${detail}`);
|
|
2063
2221
|
}
|
|
2064
2222
|
}
|
|
2223
|
+
function formatResourceSummary(resources) {
|
|
2224
|
+
const parts = [];
|
|
2225
|
+
if (resources.agents.length > 0)
|
|
2226
|
+
parts.push(`${resources.agents.length} agents`);
|
|
2227
|
+
if (resources.entityTypes.length > 0)
|
|
2228
|
+
parts.push(`${resources.entityTypes.length} data types`);
|
|
2229
|
+
if (resources.roles.length > 0)
|
|
2230
|
+
parts.push(`${resources.roles.length} roles`);
|
|
2231
|
+
if (resources.customTools.length > 0)
|
|
2232
|
+
parts.push(`${resources.customTools.length} custom tools`);
|
|
2233
|
+
if (resources.routers.length > 0)
|
|
2234
|
+
parts.push(`${resources.routers.length} routers`);
|
|
2235
|
+
if (resources.triggers.length > 0)
|
|
2236
|
+
parts.push(`${resources.triggers.length} triggers`);
|
|
2237
|
+
if (resources.evalSuites.length > 0)
|
|
2238
|
+
parts.push(`${resources.evalSuites.length} eval suites`);
|
|
2239
|
+
if (resources.fixtures.length > 0)
|
|
2240
|
+
parts.push(`${resources.fixtures.length} fixtures`);
|
|
2241
|
+
return `Loaded ${parts.join(", ") || "no resources"}`;
|
|
2242
|
+
}
|
|
2065
2243
|
async function loadAllResources(cwd) {
|
|
2066
2244
|
const errors = [];
|
|
2067
2245
|
const agents = await loadTsDirectory(join5(cwd, "agents"));
|
|
@@ -2932,7 +3110,8 @@ function extractAgentPayload(agent, customToolsMap) {
|
|
|
2932
3110
|
model: {
|
|
2933
3111
|
model: agent.model?.model || "openai/gpt-5-mini",
|
|
2934
3112
|
temperature: agent.model?.temperature,
|
|
2935
|
-
maxTokens: agent.model?.maxTokens
|
|
3113
|
+
maxTokens: agent.model?.maxTokens,
|
|
3114
|
+
reasoning: agent.model?.reasoning
|
|
2936
3115
|
},
|
|
2937
3116
|
tools
|
|
2938
3117
|
};
|
|
@@ -2954,6 +3133,59 @@ function extractHandlerCode(handler) {
|
|
|
2954
3133
|
return code;
|
|
2955
3134
|
}
|
|
2956
3135
|
|
|
3136
|
+
// src/cli/utils/validator.ts
|
|
3137
|
+
var INTEGRATION_PREFIXES = {
|
|
3138
|
+
"whatsapp.": "WhatsApp (Kapso)",
|
|
3139
|
+
"calendar.": "Google Calendar",
|
|
3140
|
+
"airtable.": "Airtable",
|
|
3141
|
+
"email.": "Resend",
|
|
3142
|
+
"payment.": "Flow / Polar"
|
|
3143
|
+
};
|
|
3144
|
+
function validateResources(payload, resources) {
|
|
3145
|
+
const warnings = [];
|
|
3146
|
+
const errors = [];
|
|
3147
|
+
const agentSlugs = new Set(payload.agents.map((a) => a.slug));
|
|
3148
|
+
if (payload.routers) {
|
|
3149
|
+
for (const router of payload.routers) {
|
|
3150
|
+
for (const agentRef of router.agents) {
|
|
3151
|
+
if (!agentSlugs.has(agentRef.slug)) {
|
|
3152
|
+
errors.push(`Router "${router.name}" references agent "${agentRef.slug}" but no agent with that slug exists`);
|
|
3153
|
+
}
|
|
3154
|
+
}
|
|
3155
|
+
if (!agentSlugs.has(router.fallback)) {
|
|
3156
|
+
errors.push(`Router "${router.name}" has fallback "${router.fallback}" but no agent with that slug exists`);
|
|
3157
|
+
}
|
|
3158
|
+
if (router.rules) {
|
|
3159
|
+
for (const rule of router.rules) {
|
|
3160
|
+
if (!agentSlugs.has(rule.route)) {
|
|
3161
|
+
errors.push(`Router "${router.name}" has rule routing to "${rule.route}" but no agent with that slug exists`);
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3164
|
+
}
|
|
3165
|
+
}
|
|
3166
|
+
}
|
|
3167
|
+
const entityTypeSlugs = new Set(payload.entityTypes.map((et) => et.slug));
|
|
3168
|
+
if (payload.triggers) {
|
|
3169
|
+
for (const trigger of payload.triggers) {
|
|
3170
|
+
if (trigger.entityType && !entityTypeSlugs.has(trigger.entityType)) {
|
|
3171
|
+
errors.push(`Trigger "${trigger.name}" references entity type "${trigger.entityType}" but no entity type with that slug exists`);
|
|
3172
|
+
}
|
|
3173
|
+
}
|
|
3174
|
+
}
|
|
3175
|
+
const seenIntegrations = new Set;
|
|
3176
|
+
for (const agent of payload.agents) {
|
|
3177
|
+
for (const toolName of agent.tools) {
|
|
3178
|
+
for (const [prefix, integration] of Object.entries(INTEGRATION_PREFIXES)) {
|
|
3179
|
+
if (toolName.startsWith(prefix) && !seenIntegrations.has(integration)) {
|
|
3180
|
+
seenIntegrations.add(integration);
|
|
3181
|
+
warnings.push(`Agent "${agent.name}" uses ${toolName} \u2014 ensure ${integration} integration is configured`);
|
|
3182
|
+
}
|
|
3183
|
+
}
|
|
3184
|
+
}
|
|
3185
|
+
}
|
|
3186
|
+
return { warnings, errors };
|
|
3187
|
+
}
|
|
3188
|
+
|
|
2957
3189
|
// src/cli/commands/sync.ts
|
|
2958
3190
|
async function performDevSync(cwd, organizationId) {
|
|
2959
3191
|
generateTypeDeclarations(cwd);
|
|
@@ -2964,6 +3196,16 @@ ${resources.errors.join(`
|
|
|
2964
3196
|
`)}`);
|
|
2965
3197
|
}
|
|
2966
3198
|
const payload = extractSyncPayload(resources);
|
|
3199
|
+
const validation = validateResources(payload, resources);
|
|
3200
|
+
for (const warning of validation.warnings) {
|
|
3201
|
+
console.log(chalk6.yellow(`\u26A0 ${warning}`));
|
|
3202
|
+
}
|
|
3203
|
+
if (validation.errors.length > 0) {
|
|
3204
|
+
for (const error of validation.errors) {
|
|
3205
|
+
console.log(chalk6.red(`\u2716 ${error}`));
|
|
3206
|
+
}
|
|
3207
|
+
throw new Error(`${validation.errors.length} validation error(s) \u2014 fix the issues above before syncing`);
|
|
3208
|
+
}
|
|
2967
3209
|
const devResult = await syncOrganization({
|
|
2968
3210
|
agents: payload.agents,
|
|
2969
3211
|
tools: payload.tools,
|
|
@@ -3033,6 +3275,7 @@ async function checkForDeletions(resources, organizationId, environment) {
|
|
|
3033
3275
|
return deletions;
|
|
3034
3276
|
}
|
|
3035
3277
|
async function syncToEnvironment(cwd, organizationId, environment) {
|
|
3278
|
+
generateTypeDeclarations(cwd);
|
|
3036
3279
|
const resources = await loadAllResources(cwd);
|
|
3037
3280
|
if (resources.errors.length > 0) {
|
|
3038
3281
|
throw new Error(`${resources.errors.length} resource loading error(s):
|
|
@@ -3040,6 +3283,16 @@ ${resources.errors.join(`
|
|
|
3040
3283
|
`)}`);
|
|
3041
3284
|
}
|
|
3042
3285
|
const payload = extractSyncPayload(resources);
|
|
3286
|
+
const validation = validateResources(payload, resources);
|
|
3287
|
+
for (const warning of validation.warnings) {
|
|
3288
|
+
console.log(chalk6.yellow(`\u26A0 ${warning}`));
|
|
3289
|
+
}
|
|
3290
|
+
if (validation.errors.length > 0) {
|
|
3291
|
+
for (const error of validation.errors) {
|
|
3292
|
+
console.log(chalk6.red(`\u2716 ${error}`));
|
|
3293
|
+
}
|
|
3294
|
+
throw new Error(`${validation.errors.length} validation error(s) \u2014 fix the issues above before syncing`);
|
|
3295
|
+
}
|
|
3043
3296
|
if (environment === "eval") {
|
|
3044
3297
|
const result = await syncOrganization({
|
|
3045
3298
|
agents: payload.agents,
|
|
@@ -3107,6 +3360,7 @@ var syncCommand = new Command5("sync").description("Sync resources to Convex and
|
|
|
3107
3360
|
output.info(`Environment: ${environment}${syncEval && environment === "development" ? " + eval" : ""}`);
|
|
3108
3361
|
console.log();
|
|
3109
3362
|
}
|
|
3363
|
+
generateTypeDeclarations(cwd);
|
|
3110
3364
|
if (!jsonMode)
|
|
3111
3365
|
output.start("Loading resources");
|
|
3112
3366
|
let resources;
|
|
@@ -3124,7 +3378,7 @@ var syncCommand = new Command5("sync").description("Sync resources to Convex and
|
|
|
3124
3378
|
process.exit(1);
|
|
3125
3379
|
}
|
|
3126
3380
|
if (!jsonMode && !options.dryRun)
|
|
3127
|
-
output.succeed(
|
|
3381
|
+
output.succeed(formatResourceSummary(resources));
|
|
3128
3382
|
} catch (error) {
|
|
3129
3383
|
if (jsonMode) {
|
|
3130
3384
|
console.log(JSON.stringify({ success: false, error: error instanceof Error ? error.message : String(error) }));
|
|
@@ -3233,32 +3487,13 @@ var syncCommand = new Command5("sync").description("Sync resources to Convex and
|
|
|
3233
3487
|
}));
|
|
3234
3488
|
}
|
|
3235
3489
|
} catch (error) {
|
|
3236
|
-
if (
|
|
3237
|
-
|
|
3238
|
-
clearCredentials();
|
|
3239
|
-
const newCredentials = await performLogin();
|
|
3240
|
-
if (!newCredentials) {
|
|
3241
|
-
output.error("Authentication failed");
|
|
3242
|
-
process.exit(1);
|
|
3243
|
-
}
|
|
3244
|
-
output.start("Syncing to Convex");
|
|
3245
|
-
try {
|
|
3246
|
-
const result = await syncToEnvironment(cwd, project.organization.id, environment);
|
|
3247
|
-
output.succeed(`Synced to ${environment}`);
|
|
3248
|
-
} catch (retryError) {
|
|
3249
|
-
output.fail("Sync failed");
|
|
3250
|
-
output.error(retryError instanceof Error ? retryError.message : String(retryError));
|
|
3251
|
-
process.exit(1);
|
|
3252
|
-
}
|
|
3490
|
+
if (jsonMode) {
|
|
3491
|
+
console.log(JSON.stringify({ success: false, error: error instanceof Error ? error.message : String(error) }));
|
|
3253
3492
|
} else {
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
} else {
|
|
3257
|
-
output.fail("Sync failed");
|
|
3258
|
-
output.error(error instanceof Error ? error.message : String(error));
|
|
3259
|
-
}
|
|
3260
|
-
process.exit(1);
|
|
3493
|
+
output.fail("Sync failed");
|
|
3494
|
+
output.error(error instanceof Error ? error.message : String(error));
|
|
3261
3495
|
}
|
|
3496
|
+
process.exit(1);
|
|
3262
3497
|
}
|
|
3263
3498
|
});
|
|
3264
3499
|
|
|
@@ -3325,7 +3560,7 @@ var devCommand = new Command6("dev").description("Watch files and sync to develo
|
|
|
3325
3560
|
spinner.start("Loading resources");
|
|
3326
3561
|
try {
|
|
3327
3562
|
loadedResources = await loadAllResources(cwd);
|
|
3328
|
-
spinner.succeed(
|
|
3563
|
+
spinner.succeed(formatResourceSummary(loadedResources));
|
|
3329
3564
|
for (const err of loadedResources.errors) {
|
|
3330
3565
|
console.log(chalk7.red(" \u2716"), err);
|
|
3331
3566
|
}
|
|
@@ -3372,28 +3607,7 @@ var devCommand = new Command6("dev").description("Watch files and sync to develo
|
|
|
3372
3607
|
await performDevSync(cwd, project.organization.id);
|
|
3373
3608
|
spinner.succeed("Synced to development");
|
|
3374
3609
|
} catch (error) {
|
|
3375
|
-
if (
|
|
3376
|
-
spinner.fail("Session expired - re-authenticating...");
|
|
3377
|
-
clearCredentials();
|
|
3378
|
-
credentials = await performLogin();
|
|
3379
|
-
if (!credentials) {
|
|
3380
|
-
console.log(chalk7.red("Authentication failed"));
|
|
3381
|
-
process.exit(1);
|
|
3382
|
-
}
|
|
3383
|
-
spinner.start("Syncing to Convex");
|
|
3384
|
-
try {
|
|
3385
|
-
await performDevSync(cwd, project.organization.id);
|
|
3386
|
-
spinner.succeed("Synced to development");
|
|
3387
|
-
} catch (retryError) {
|
|
3388
|
-
spinner.fail("Sync failed");
|
|
3389
|
-
console.log(chalk7.red("Error:"), retryError instanceof Error ? retryError.message : String(retryError));
|
|
3390
|
-
}
|
|
3391
|
-
} else if (isAuthError(error) && nonInteractive) {
|
|
3392
|
-
spinner.fail("API key authentication failed");
|
|
3393
|
-
console.log(chalk7.red("Error:"), error instanceof Error ? error.message : String(error));
|
|
3394
|
-
console.log(chalk7.gray("Check that STRUERE_API_KEY is valid and not expired."));
|
|
3395
|
-
process.exit(1);
|
|
3396
|
-
} else if (isOrgAccessError(error)) {
|
|
3610
|
+
if (isOrgAccessError(error)) {
|
|
3397
3611
|
spinner.fail("Organization access denied");
|
|
3398
3612
|
console.log();
|
|
3399
3613
|
console.log(chalk7.red("You do not have access to organization:"), chalk7.cyan(project.organization.name));
|
|
@@ -3443,26 +3657,8 @@ var devCommand = new Command6("dev").description("Watch files and sync to develo
|
|
|
3443
3657
|
await performDevSync(cwd, project.organization.id);
|
|
3444
3658
|
syncSpinner.succeed("Synced");
|
|
3445
3659
|
} catch (error) {
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
clearCredentials();
|
|
3449
|
-
const newCredentials = await performLogin();
|
|
3450
|
-
if (!newCredentials) {
|
|
3451
|
-
console.log(chalk7.red("Authentication failed"));
|
|
3452
|
-
return;
|
|
3453
|
-
}
|
|
3454
|
-
const retrySyncSpinner = ora6("Syncing...").start();
|
|
3455
|
-
try {
|
|
3456
|
-
await performDevSync(cwd, project.organization.id);
|
|
3457
|
-
retrySyncSpinner.succeed("Synced");
|
|
3458
|
-
} catch (retryError) {
|
|
3459
|
-
retrySyncSpinner.fail("Sync failed");
|
|
3460
|
-
console.log(chalk7.red("Error:"), retryError instanceof Error ? retryError.message : String(retryError));
|
|
3461
|
-
}
|
|
3462
|
-
} else {
|
|
3463
|
-
syncSpinner.fail("Sync failed");
|
|
3464
|
-
console.log(chalk7.red("Error:"), error instanceof Error ? error.message : String(error));
|
|
3465
|
-
}
|
|
3660
|
+
syncSpinner.fail("Sync failed");
|
|
3661
|
+
console.log(chalk7.red("Error:"), error instanceof Error ? error.message : String(error));
|
|
3466
3662
|
}
|
|
3467
3663
|
};
|
|
3468
3664
|
const handleFileChange = (path, action) => {
|
|
@@ -3554,13 +3750,14 @@ var deployCommand = new Command7("deploy").description("Deploy all resources to
|
|
|
3554
3750
|
}
|
|
3555
3751
|
console.log();
|
|
3556
3752
|
}
|
|
3753
|
+
generateTypeDeclarations(cwd);
|
|
3557
3754
|
if (!jsonMode)
|
|
3558
3755
|
spinner.start("Loading resources");
|
|
3559
3756
|
let resources;
|
|
3560
3757
|
try {
|
|
3561
3758
|
resources = await loadAllResources(cwd);
|
|
3562
3759
|
if (!jsonMode)
|
|
3563
|
-
spinner.succeed(
|
|
3760
|
+
spinner.succeed(formatResourceSummary(resources));
|
|
3564
3761
|
for (const err of resources.errors) {
|
|
3565
3762
|
if (!jsonMode)
|
|
3566
3763
|
console.log(chalk8.red(" \u2716"), err);
|
|
@@ -3593,6 +3790,28 @@ var deployCommand = new Command7("deploy").description("Deploy all resources to
|
|
|
3593
3790
|
return;
|
|
3594
3791
|
}
|
|
3595
3792
|
const payload = extractSyncPayload(resources);
|
|
3793
|
+
const validation = validateResources(payload, resources);
|
|
3794
|
+
if (validation.warnings.length > 0 || validation.errors.length > 0) {
|
|
3795
|
+
if (!jsonMode) {
|
|
3796
|
+
for (const warning of validation.warnings) {
|
|
3797
|
+
console.log(chalk8.yellow(`\u26A0 ${warning}`));
|
|
3798
|
+
}
|
|
3799
|
+
for (const error of validation.errors) {
|
|
3800
|
+
console.log(chalk8.red(`\u2716 ${error}`));
|
|
3801
|
+
}
|
|
3802
|
+
}
|
|
3803
|
+
if (validation.errors.length > 0) {
|
|
3804
|
+
if (jsonMode) {
|
|
3805
|
+
console.log(JSON.stringify({ success: false, error: `${validation.errors.length} validation error(s)`, errors: validation.errors, warnings: validation.warnings }));
|
|
3806
|
+
} else {
|
|
3807
|
+
console.log();
|
|
3808
|
+
console.log(chalk8.red(`${validation.errors.length} validation error(s) \u2014 fix the issues above before deploying`));
|
|
3809
|
+
}
|
|
3810
|
+
process.exit(1);
|
|
3811
|
+
}
|
|
3812
|
+
if (!jsonMode)
|
|
3813
|
+
console.log();
|
|
3814
|
+
}
|
|
3596
3815
|
if (!jsonMode)
|
|
3597
3816
|
spinner.start("Checking remote state");
|
|
3598
3817
|
let deletions = [];
|
|
@@ -3731,52 +3950,7 @@ var deployCommand = new Command7("deploy").description("Deploy all resources to
|
|
|
3731
3950
|
console.log();
|
|
3732
3951
|
}
|
|
3733
3952
|
} catch (error) {
|
|
3734
|
-
if (
|
|
3735
|
-
if (!jsonMode)
|
|
3736
|
-
spinner.fail("Session expired - re-authenticating...");
|
|
3737
|
-
clearCredentials();
|
|
3738
|
-
credentials = await performLogin();
|
|
3739
|
-
if (!credentials) {
|
|
3740
|
-
if (jsonMode) {
|
|
3741
|
-
console.log(JSON.stringify({ success: false, error: "Authentication failed" }));
|
|
3742
|
-
} else {
|
|
3743
|
-
console.log(chalk8.red("Authentication failed"));
|
|
3744
|
-
}
|
|
3745
|
-
process.exit(1);
|
|
3746
|
-
}
|
|
3747
|
-
if (!jsonMode)
|
|
3748
|
-
spinner.start("Deploying to production");
|
|
3749
|
-
try {
|
|
3750
|
-
const syncResult = await syncOrganization({
|
|
3751
|
-
agents: payload.agents,
|
|
3752
|
-
entityTypes: payload.entityTypes,
|
|
3753
|
-
roles: payload.roles,
|
|
3754
|
-
triggers: payload.triggers,
|
|
3755
|
-
tools: payload.tools,
|
|
3756
|
-
organizationId: project.organization.id,
|
|
3757
|
-
environment: "production"
|
|
3758
|
-
});
|
|
3759
|
-
if (!syncResult.success) {
|
|
3760
|
-
throw new Error(syncResult.error || "Deploy failed");
|
|
3761
|
-
}
|
|
3762
|
-
if (!jsonMode) {
|
|
3763
|
-
spinner.succeed("Deployed to production");
|
|
3764
|
-
console.log();
|
|
3765
|
-
console.log(chalk8.green("Success!"), "All resources deployed to production");
|
|
3766
|
-
console.log();
|
|
3767
|
-
} else {
|
|
3768
|
-
console.log(JSON.stringify({ success: true, environment: "production" }));
|
|
3769
|
-
}
|
|
3770
|
-
} catch (retryError) {
|
|
3771
|
-
if (jsonMode) {
|
|
3772
|
-
console.log(JSON.stringify({ success: false, error: retryError instanceof Error ? retryError.message : String(retryError) }));
|
|
3773
|
-
} else {
|
|
3774
|
-
spinner.fail("Deployment failed");
|
|
3775
|
-
console.log(chalk8.red("Error:"), retryError instanceof Error ? retryError.message : String(retryError));
|
|
3776
|
-
}
|
|
3777
|
-
process.exit(1);
|
|
3778
|
-
}
|
|
3779
|
-
} else if (isOrgAccessError(error)) {
|
|
3953
|
+
if (isOrgAccessError(error)) {
|
|
3780
3954
|
if (jsonMode) {
|
|
3781
3955
|
console.log(JSON.stringify({ success: false, error: `Organization access denied: ${project.organization.name}` }));
|
|
3782
3956
|
} else {
|
|
@@ -4110,6 +4284,7 @@ var statusCommand = new Command11("status").description("Compare local vs remote
|
|
|
4110
4284
|
}
|
|
4111
4285
|
console.log();
|
|
4112
4286
|
}
|
|
4287
|
+
generateTypeDeclarations(cwd);
|
|
4113
4288
|
if (!jsonMode)
|
|
4114
4289
|
spinner.start("Loading local resources");
|
|
4115
4290
|
let localResources;
|
|
@@ -7147,6 +7322,7 @@ import ora14 from "ora";
|
|
|
7147
7322
|
// src/cli/utils/triggers.ts
|
|
7148
7323
|
init_credentials();
|
|
7149
7324
|
init_config();
|
|
7325
|
+
init_convex();
|
|
7150
7326
|
function getToken3() {
|
|
7151
7327
|
const credentials = loadCredentials();
|
|
7152
7328
|
const apiKey = getApiKey();
|
|
@@ -7248,8 +7424,8 @@ async function listTriggerExecutions(options) {
|
|
|
7248
7424
|
...options.limit && { limit: options.limit }
|
|
7249
7425
|
});
|
|
7250
7426
|
}
|
|
7251
|
-
async function getTriggerExecutionDetail(eventId) {
|
|
7252
|
-
return convexQuery6("triggers:getExecutionDetail", { eventId });
|
|
7427
|
+
async function getTriggerExecutionDetail(eventId, environment) {
|
|
7428
|
+
return convexQuery6("triggers:getExecutionDetail", { eventId, ...environment && { environment } });
|
|
7253
7429
|
}
|
|
7254
7430
|
async function convexAction3(path, args) {
|
|
7255
7431
|
const token = getToken3();
|
|
@@ -7575,7 +7751,7 @@ triggersCommand.command("runs [slug]").description("List trigger runs").option("
|
|
|
7575
7751
|
}
|
|
7576
7752
|
console.log();
|
|
7577
7753
|
renderTable([
|
|
7578
|
-
{ key: "id", label: "ID", width:
|
|
7754
|
+
{ key: "id", label: "ID", width: 40 },
|
|
7579
7755
|
{ key: "trigger", label: "Trigger", width: 16 },
|
|
7580
7756
|
{ key: "status", label: "Status", width: 10 },
|
|
7581
7757
|
{ key: "attempts", label: "Attempts", width: 8 },
|
|
@@ -7702,7 +7878,7 @@ triggersCommand.command("stats").description("Show trigger run statistics").opti
|
|
|
7702
7878
|
process.exit(1);
|
|
7703
7879
|
}
|
|
7704
7880
|
});
|
|
7705
|
-
triggersCommand.command("logs [slug]").description("View trigger execution history").option("--env <environment>", "Environment", "development").option("--limit <n>", "Maximum results", "10").option("--json", "Output raw JSON").action(async (slug, opts) => {
|
|
7881
|
+
triggersCommand.command("logs [slug]").description("View trigger execution history").option("--env <environment>", "Environment", "development").option("--limit <n>", "Maximum results", "10").option("--json", "Output raw JSON").option("-v, --verbose", "Show full error messages").action(async (slug, opts) => {
|
|
7706
7882
|
await ensureAuth5();
|
|
7707
7883
|
const spinner = ora14();
|
|
7708
7884
|
try {
|
|
@@ -7719,12 +7895,12 @@ triggersCommand.command("logs [slug]").description("View trigger execution histo
|
|
|
7719
7895
|
}
|
|
7720
7896
|
console.log();
|
|
7721
7897
|
renderTable([
|
|
7722
|
-
{ key: "id", label: "ID", width:
|
|
7898
|
+
{ key: "id", label: "ID", width: 40 },
|
|
7723
7899
|
{ key: "trigger", label: "Trigger", width: 16 },
|
|
7724
7900
|
{ key: "status", label: "Status", width: 8 },
|
|
7725
7901
|
{ key: "steps", label: "Steps", width: 7 },
|
|
7726
7902
|
{ key: "duration", label: "Duration", width: 10 },
|
|
7727
|
-
{ key: "error", label: "Error", width:
|
|
7903
|
+
{ key: "error", label: "Error", width: 50 },
|
|
7728
7904
|
{ key: "time", label: "Time", width: 10 }
|
|
7729
7905
|
], executions.map((e) => {
|
|
7730
7906
|
const status = e.eventType === "trigger.executed" ? "success" : "failed";
|
|
@@ -7737,10 +7913,23 @@ triggersCommand.command("logs [slug]").description("View trigger execution histo
|
|
|
7737
7913
|
status: statusColor4(status),
|
|
7738
7914
|
steps: `${passed}/${log.length}`,
|
|
7739
7915
|
duration: `${totalMs}ms`,
|
|
7740
|
-
error: status === "failed" ? (e.payload?.error ?? "").slice(0,
|
|
7916
|
+
error: status === "failed" ? (e.payload?.error ?? "").slice(0, 80) : "",
|
|
7741
7917
|
time: relativeTime2(e.timestamp ?? Date.now())
|
|
7742
7918
|
};
|
|
7743
7919
|
}));
|
|
7920
|
+
if (opts.verbose) {
|
|
7921
|
+
const failures = executions.filter((e) => e.eventType === "trigger.failed");
|
|
7922
|
+
if (failures.length) {
|
|
7923
|
+
console.log();
|
|
7924
|
+
console.log(chalk20.bold("Error Details"));
|
|
7925
|
+
console.log(chalk20.gray("\u2500".repeat(60)));
|
|
7926
|
+
for (const f of failures) {
|
|
7927
|
+
console.log(` ${chalk20.cyan(f.payload?.triggerSlug ?? "")} ${chalk20.gray(relativeTime2(f.timestamp ?? Date.now()))}`);
|
|
7928
|
+
console.log(` ${chalk20.red(f.payload?.error ?? "Unknown error")}`);
|
|
7929
|
+
console.log();
|
|
7930
|
+
}
|
|
7931
|
+
}
|
|
7932
|
+
}
|
|
7744
7933
|
console.log();
|
|
7745
7934
|
} catch (err) {
|
|
7746
7935
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -7753,12 +7942,36 @@ triggersCommand.command("logs [slug]").description("View trigger execution histo
|
|
|
7753
7942
|
process.exit(1);
|
|
7754
7943
|
}
|
|
7755
7944
|
});
|
|
7756
|
-
triggersCommand.command("log <
|
|
7945
|
+
triggersCommand.command("log <identifier>").description("View detailed trigger execution log (by event ID or trigger slug)").option("--env <environment>", "Environment", "development").option("--nth <n>", "Show nth most recent execution (when using slug)", "1").option("--json", "Output raw JSON").option("-v, --verbose", "Show detailed agent tool calls").action(async (identifier, opts) => {
|
|
7757
7946
|
await ensureAuth5();
|
|
7758
7947
|
const spinner = ora14();
|
|
7759
7948
|
try {
|
|
7949
|
+
let eventId = identifier;
|
|
7950
|
+
const isConvexId = identifier.includes("_") || identifier.length > 30;
|
|
7951
|
+
if (!isConvexId) {
|
|
7952
|
+
spinner.start("Resolving trigger slug to latest execution");
|
|
7953
|
+
const executions = await listTriggerExecutions({
|
|
7954
|
+
environment: opts.env,
|
|
7955
|
+
triggerSlug: identifier,
|
|
7956
|
+
limit: parseInt(opts.nth, 10)
|
|
7957
|
+
});
|
|
7958
|
+
if (!executions.length) {
|
|
7959
|
+
spinner.fail(`No executions found for trigger "${identifier}" in ${opts.env}`);
|
|
7960
|
+
if (opts.json) {
|
|
7961
|
+
console.log(JSON.stringify({ success: false, error: `No executions found for trigger "${identifier}"` }));
|
|
7962
|
+
}
|
|
7963
|
+
process.exit(1);
|
|
7964
|
+
}
|
|
7965
|
+
const idx = parseInt(opts.nth, 10) - 1;
|
|
7966
|
+
if (idx >= executions.length) {
|
|
7967
|
+
spinner.fail(`Only ${executions.length} executions found, cannot get #${opts.nth}`);
|
|
7968
|
+
process.exit(1);
|
|
7969
|
+
}
|
|
7970
|
+
eventId = executions[idx]._id;
|
|
7971
|
+
spinner.succeed(`Found execution for "${identifier}"`);
|
|
7972
|
+
}
|
|
7760
7973
|
spinner.start("Fetching execution detail");
|
|
7761
|
-
const event = await getTriggerExecutionDetail(eventId);
|
|
7974
|
+
const event = await getTriggerExecutionDetail(eventId, opts.env);
|
|
7762
7975
|
if (!event) {
|
|
7763
7976
|
spinner.fail("Execution not found");
|
|
7764
7977
|
if (opts.json) {
|
|
@@ -7964,6 +8177,79 @@ triggersCommand.command("retry-event <event-id>").description("Retry a failed im
|
|
|
7964
8177
|
process.exit(1);
|
|
7965
8178
|
}
|
|
7966
8179
|
});
|
|
8180
|
+
triggersCommand.command("fire <slug>").description("Manually fire a trigger").option("--env <environment>", "Environment (development|production|eval)", "development").option("--entity <entityId>", "Entity ID to provide as context").option("--data <json>", "JSON data for template context").option("--json", "Output raw JSON").option("--confirm", "Skip production confirmation").option("-v, --verbose", "Show detailed agent tool calls").action(async (slug, opts) => {
|
|
8181
|
+
await ensureAuth5();
|
|
8182
|
+
const spinner = ora14();
|
|
8183
|
+
const environment = opts.env;
|
|
8184
|
+
if (environment === "production" && !opts.confirm && isInteractive()) {
|
|
8185
|
+
const readline = await import("readline");
|
|
8186
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
8187
|
+
await new Promise((resolve) => {
|
|
8188
|
+
rl.question(chalk20.yellow(`WARNING: Firing trigger in PRODUCTION environment.
|
|
8189
|
+
Press Enter to continue or Ctrl+C to cancel: `), resolve);
|
|
8190
|
+
});
|
|
8191
|
+
rl.close();
|
|
8192
|
+
}
|
|
8193
|
+
let data;
|
|
8194
|
+
if (opts.data) {
|
|
8195
|
+
try {
|
|
8196
|
+
data = JSON.parse(opts.data);
|
|
8197
|
+
} catch {
|
|
8198
|
+
console.log(chalk20.red("Error: --data must be valid JSON"));
|
|
8199
|
+
process.exit(1);
|
|
8200
|
+
}
|
|
8201
|
+
}
|
|
8202
|
+
try {
|
|
8203
|
+
spinner.start(`Firing trigger ${chalk20.cyan(slug)}...`);
|
|
8204
|
+
const { result, error } = await fireTrigger({
|
|
8205
|
+
slug,
|
|
8206
|
+
environment,
|
|
8207
|
+
entityId: opts.entity,
|
|
8208
|
+
data
|
|
8209
|
+
});
|
|
8210
|
+
if (error) {
|
|
8211
|
+
spinner.fail("Trigger execution failed");
|
|
8212
|
+
if (opts.json) {
|
|
8213
|
+
console.log(JSON.stringify({ success: false, error }));
|
|
8214
|
+
} else {
|
|
8215
|
+
console.log(chalk20.red("Error:"), error);
|
|
8216
|
+
}
|
|
8217
|
+
process.exit(1);
|
|
8218
|
+
}
|
|
8219
|
+
if (!result) {
|
|
8220
|
+
spinner.fail("No result returned");
|
|
8221
|
+
process.exit(1);
|
|
8222
|
+
}
|
|
8223
|
+
if (result.success) {
|
|
8224
|
+
spinner.succeed(chalk20.green(`Trigger ${chalk20.cyan(slug)} fired successfully`));
|
|
8225
|
+
} else {
|
|
8226
|
+
spinner.fail(chalk20.red(`Trigger ${chalk20.cyan(slug)} execution failed`));
|
|
8227
|
+
}
|
|
8228
|
+
if (opts.json) {
|
|
8229
|
+
console.log(JSON.stringify(result, null, 2));
|
|
8230
|
+
return;
|
|
8231
|
+
}
|
|
8232
|
+
console.log();
|
|
8233
|
+
console.log(` ${chalk20.gray("Trigger:")} ${chalk20.cyan(result.trigger.name)} (${result.trigger.slug})`);
|
|
8234
|
+
console.log(` ${chalk20.gray("Environment:")} ${chalk20.cyan(result.environment)}`);
|
|
8235
|
+
console.log(` ${chalk20.gray("Status:")} ${result.success ? chalk20.green("success") : chalk20.red("failed")}`);
|
|
8236
|
+
if (result.executionLog?.length) {
|
|
8237
|
+
renderExecutionLog(result.executionLog, opts.verbose);
|
|
8238
|
+
}
|
|
8239
|
+
if (!result.success) {
|
|
8240
|
+
process.exit(1);
|
|
8241
|
+
}
|
|
8242
|
+
} catch (err) {
|
|
8243
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
8244
|
+
spinner.fail("Failed to fire trigger");
|
|
8245
|
+
if (opts.json) {
|
|
8246
|
+
console.log(JSON.stringify({ success: false, error: message }));
|
|
8247
|
+
} else {
|
|
8248
|
+
console.log(chalk20.red("Error:"), message);
|
|
8249
|
+
}
|
|
8250
|
+
process.exit(1);
|
|
8251
|
+
}
|
|
8252
|
+
});
|
|
7967
8253
|
|
|
7968
8254
|
// src/cli/commands/compile-prompt.ts
|
|
7969
8255
|
init_credentials();
|
|
@@ -8054,26 +8340,7 @@ var compilePromptCommand = new Command19("compile-prompt").description("Compile
|
|
|
8054
8340
|
threadMetadata: Object.keys(threadMetadata).length > 0 ? threadMetadata : undefined
|
|
8055
8341
|
});
|
|
8056
8342
|
};
|
|
8057
|
-
|
|
8058
|
-
if (error && isAuthError(error) && !nonInteractive) {
|
|
8059
|
-
if (!jsonMode)
|
|
8060
|
-
spinner.fail("Session expired - re-authenticating...");
|
|
8061
|
-
clearCredentials();
|
|
8062
|
-
credentials = await performLogin();
|
|
8063
|
-
if (!credentials) {
|
|
8064
|
-
if (jsonMode) {
|
|
8065
|
-
console.log(JSON.stringify({ success: false, error: "Authentication failed" }));
|
|
8066
|
-
} else {
|
|
8067
|
-
console.log(chalk21.red("Authentication failed"));
|
|
8068
|
-
}
|
|
8069
|
-
process.exit(1);
|
|
8070
|
-
}
|
|
8071
|
-
const retry = await doCompile();
|
|
8072
|
-
result = retry.result;
|
|
8073
|
-
error = retry.error;
|
|
8074
|
-
if (!jsonMode && !error)
|
|
8075
|
-
spinner.succeed("Compiled prompt");
|
|
8076
|
-
}
|
|
8343
|
+
const { result, error } = await doCompile();
|
|
8077
8344
|
if (error) {
|
|
8078
8345
|
if (jsonMode) {
|
|
8079
8346
|
console.log(JSON.stringify({ success: false, error }));
|
|
@@ -8121,7 +8388,7 @@ import { Command as Command20 } from "commander";
|
|
|
8121
8388
|
import chalk22 from "chalk";
|
|
8122
8389
|
import ora16 from "ora";
|
|
8123
8390
|
init_convex();
|
|
8124
|
-
var runToolCommand = new Command20("run-tool").description("Run a tool as it would execute during a real agent conversation").argument("<
|
|
8391
|
+
var runToolCommand = new Command20("run-tool").description("Run a tool as it would execute during a real agent conversation").argument("<tool-name>", "Tool name (e.g., entity.query, run_scrapers)").option("--agent <slug>", "Agent slug (optional \u2014 omit to run without agent context)").option("--env <environment>", "Environment: development | production | eval", "development").option("--args <json>", "Tool arguments as JSON string", "{}").option("--args-file <path>", "Read tool arguments from a JSON file").option("--json", "Output full JSON result").option("--confirm", "Skip production confirmation prompt").action(async (toolName, options) => {
|
|
8125
8392
|
const spinner = ora16();
|
|
8126
8393
|
const cwd = process.cwd();
|
|
8127
8394
|
const nonInteractive = !isInteractive();
|
|
@@ -8190,6 +8457,9 @@ var runToolCommand = new Command20("run-tool").description("Run a tool as it wou
|
|
|
8190
8457
|
process.exit(1);
|
|
8191
8458
|
}
|
|
8192
8459
|
const environment = options.env;
|
|
8460
|
+
if (!options.agent && !toolName.includes(".") && !jsonMode) {
|
|
8461
|
+
console.log(chalk22.dim(`Tip: Running without agent context. Use --agent <slug> to run with a specific agent.`));
|
|
8462
|
+
}
|
|
8193
8463
|
if (environment === "production" && !options.confirm && !nonInteractive) {
|
|
8194
8464
|
const readline = await import("readline");
|
|
8195
8465
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -8201,37 +8471,18 @@ var runToolCommand = new Command20("run-tool").description("Run a tool as it wou
|
|
|
8201
8471
|
rl.close();
|
|
8202
8472
|
}
|
|
8203
8473
|
if (!jsonMode) {
|
|
8204
|
-
spinner.start(`Running ${chalk22.cyan(toolName)} on ${chalk22.cyan(
|
|
8474
|
+
spinner.start(`Running ${chalk22.cyan(toolName)}${options.agent ? ` on ${chalk22.cyan(options.agent)}` : ""} (${environment})`);
|
|
8205
8475
|
}
|
|
8206
8476
|
const doRunTool = async () => {
|
|
8207
8477
|
return runTool({
|
|
8208
|
-
agentSlug,
|
|
8478
|
+
agentSlug: options.agent,
|
|
8209
8479
|
toolName,
|
|
8210
8480
|
toolArgs,
|
|
8211
8481
|
environment,
|
|
8212
8482
|
organizationId: project?.organization.id
|
|
8213
8483
|
});
|
|
8214
8484
|
};
|
|
8215
|
-
|
|
8216
|
-
if (error && isAuthError(error) && !nonInteractive) {
|
|
8217
|
-
if (!jsonMode)
|
|
8218
|
-
spinner.fail("Session expired - re-authenticating...");
|
|
8219
|
-
clearCredentials();
|
|
8220
|
-
credentials = await performLogin();
|
|
8221
|
-
if (!credentials) {
|
|
8222
|
-
if (jsonMode) {
|
|
8223
|
-
console.log(JSON.stringify({ success: false, error: "Authentication failed" }));
|
|
8224
|
-
} else {
|
|
8225
|
-
console.log(chalk22.red("Authentication failed"));
|
|
8226
|
-
}
|
|
8227
|
-
process.exit(1);
|
|
8228
|
-
}
|
|
8229
|
-
const retry = await doRunTool();
|
|
8230
|
-
result = retry.result;
|
|
8231
|
-
error = retry.error;
|
|
8232
|
-
if (!jsonMode && !error)
|
|
8233
|
-
spinner.succeed(`Ran ${chalk22.cyan(toolName)}`);
|
|
8234
|
-
}
|
|
8485
|
+
const { result, error } = await doRunTool();
|
|
8235
8486
|
if (error) {
|
|
8236
8487
|
if (jsonMode) {
|
|
8237
8488
|
console.log(JSON.stringify({ success: false, error }));
|
|
@@ -8258,7 +8509,7 @@ var runToolCommand = new Command20("run-tool").description("Run a tool as it wou
|
|
|
8258
8509
|
process.exit(1);
|
|
8259
8510
|
}
|
|
8260
8511
|
if (!jsonMode) {
|
|
8261
|
-
spinner.succeed(`Ran ${chalk22.cyan(toolName)} on ${chalk22.cyan(result.agent.slug)} (${result.environment}) in ${result.durationMs}ms`);
|
|
8512
|
+
spinner.succeed(`Ran ${chalk22.cyan(toolName)}${result.agent ? ` on ${chalk22.cyan(result.agent.slug)}` : ""} (${result.environment}) in ${result.durationMs}ms`);
|
|
8262
8513
|
}
|
|
8263
8514
|
if (jsonMode) {
|
|
8264
8515
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -8279,7 +8530,18 @@ import chalk23 from "chalk";
|
|
|
8279
8530
|
import ora17 from "ora";
|
|
8280
8531
|
import readline from "readline";
|
|
8281
8532
|
init_convex();
|
|
8282
|
-
|
|
8533
|
+
function printExecutionMeta(meta) {
|
|
8534
|
+
console.log(chalk23.dim(`Model: ${meta.model} | Duration: ${meta.durationMs}ms`));
|
|
8535
|
+
if (meta.toolCallSummary.length > 0) {
|
|
8536
|
+
console.log(chalk23.dim("Tool calls:"));
|
|
8537
|
+
for (const tc of meta.toolCallSummary) {
|
|
8538
|
+
const status = tc.status === "success" ? chalk23.green("ok") : chalk23.red(tc.status);
|
|
8539
|
+
const err = tc.errorMessage ? chalk23.red(` \u2014 ${tc.errorMessage}`) : "";
|
|
8540
|
+
console.log(chalk23.dim(` ${tc.name} ${status} ${tc.durationMs}ms${err}`));
|
|
8541
|
+
}
|
|
8542
|
+
}
|
|
8543
|
+
}
|
|
8544
|
+
var chatCommand = new Command21("chat").description("Chat with an agent or via a router").argument("<slug>", "Agent slug (or router slug when --router is used)").option("--env <environment>", "Environment: development | production | eval", "development").option("--thread <id>", "Continue an existing thread").option("--message <msg>", "Single message mode (send and exit)").option("--json", "Output JSON").option("--channel <channel>", "Channel identifier", "api").option("-v, --verbose", "Show execution metadata (model, duration, tool calls)").option("--confirm", "Skip production warning prompt").option("--router", "Chat via a router instead of directly with an agent").option("--phone <number>", "Sender phone number for routing rules").action(async (slug, options) => {
|
|
8283
8545
|
const spinner = ora17();
|
|
8284
8546
|
const cwd = process.cwd();
|
|
8285
8547
|
const nonInteractive = !isInteractive();
|
|
@@ -8427,16 +8689,18 @@ var chatCommand = new Command21("chat").description("Chat with an agent or via a
|
|
|
8427
8689
|
console.log("\u2500".repeat(60));
|
|
8428
8690
|
console.log();
|
|
8429
8691
|
if (routerResult.routedToAgent) {
|
|
8430
|
-
console.log(chalk23.
|
|
8431
|
-
|
|
8692
|
+
console.log(chalk23.green(`${routerResult.routedToAgent}`) + chalk23.dim(` (${routerResult.routedToAgentSlug})`) + chalk23.magenta(" \u2190 routed") + chalk23.dim(":"));
|
|
8693
|
+
} else {
|
|
8694
|
+
console.log(chalk23.green("Agent:"));
|
|
8432
8695
|
}
|
|
8433
|
-
console.log(chalk23.green("Agent:"));
|
|
8434
8696
|
console.log(result.message);
|
|
8435
8697
|
console.log();
|
|
8436
8698
|
if (options.verbose) {
|
|
8437
8699
|
console.log(chalk23.dim(`Thread: ${result.threadId}`));
|
|
8438
8700
|
console.log(chalk23.dim(`Tokens: ${result.usage.inputTokens} in / ${result.usage.outputTokens} out (${result.usage.totalTokens} total)`));
|
|
8439
|
-
|
|
8701
|
+
if (result._executionMeta) {
|
|
8702
|
+
printExecutionMeta(result._executionMeta);
|
|
8703
|
+
}
|
|
8440
8704
|
} else {
|
|
8441
8705
|
console.log(chalk23.dim(`Thread: ${result.threadId} | Tokens: ${result.usage.totalTokens}`));
|
|
8442
8706
|
}
|
|
@@ -8538,16 +8802,18 @@ var chatCommand = new Command21("chat").description("Chat with an agent or via a
|
|
|
8538
8802
|
const interactiveRouterResult = result;
|
|
8539
8803
|
console.log();
|
|
8540
8804
|
if (interactiveRouterResult.routedToAgent) {
|
|
8541
|
-
console.log(chalk23.
|
|
8542
|
-
|
|
8805
|
+
console.log(chalk23.green(`${interactiveRouterResult.routedToAgent}`) + chalk23.dim(` (${interactiveRouterResult.routedToAgentSlug})`) + chalk23.magenta(" \u2190 routed") + chalk23.dim(":"));
|
|
8806
|
+
} else {
|
|
8807
|
+
console.log(chalk23.green("Agent:"));
|
|
8543
8808
|
}
|
|
8544
|
-
console.log(chalk23.green("Agent:"));
|
|
8545
8809
|
console.log(result.message);
|
|
8546
8810
|
console.log();
|
|
8547
8811
|
if (options.verbose) {
|
|
8548
8812
|
console.log(chalk23.dim(`Thread: ${result.threadId}`));
|
|
8549
8813
|
console.log(chalk23.dim(`Tokens: ${result.usage.inputTokens} in / ${result.usage.outputTokens} out (${result.usage.totalTokens} total)`));
|
|
8550
|
-
|
|
8814
|
+
if (result._executionMeta) {
|
|
8815
|
+
printExecutionMeta(result._executionMeta);
|
|
8816
|
+
}
|
|
8551
8817
|
} else {
|
|
8552
8818
|
console.log(chalk23.dim(`Tokens: ${result.usage.totalTokens}`));
|
|
8553
8819
|
}
|
|
@@ -8763,7 +9029,7 @@ whatsappCommand.command("set-agent <connection> <agent-slug>").description("Assi
|
|
|
8763
9029
|
// package.json
|
|
8764
9030
|
var package_default = {
|
|
8765
9031
|
name: "struere",
|
|
8766
|
-
version: "0.12.
|
|
9032
|
+
version: "0.12.9",
|
|
8767
9033
|
description: "Build, test, and deploy AI agents",
|
|
8768
9034
|
keywords: [
|
|
8769
9035
|
"ai",
|