@almadar/agent 1.3.3 → 1.6.1
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/agent/index.d.ts +4 -4
- package/dist/agent/index.js +1049 -31
- package/dist/agent/index.js.map +1 -1
- package/dist/{api-types-DVdGNr2M.d.ts → api-types-Bj2jeOU7.d.ts} +4 -0
- package/dist/event-transformer/index.d.ts +1 -1
- package/dist/event-transformer/index.js +3 -1
- package/dist/event-transformer/index.js.map +1 -1
- package/dist/{index-DFJdTDbo.d.ts → index-DGdLGf-L.d.ts} +189 -12
- package/dist/index.d.ts +357 -8
- package/dist/index.js +1593 -39
- package/dist/index.js.map +1 -1
- package/dist/{orbital-subagent-CCo-ONJY.d.ts → orbital-subagent-CHEeQQr_.d.ts} +1 -1
- package/dist/tools/index.d.ts +4 -3
- package/dist/tools/index.js +976 -20
- package/dist/tools/index.js.map +1 -1
- package/dist/{interrupt-config-Bib_RCTB.d.ts → workflow-tool-wrapper-CXD0A7l3.d.ts} +159 -3
- package/package.json +7 -4
package/dist/agent/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AgentDomainCategorySchema, isOrbitalDefinition, isEntityReference, getTraitName } from '@almadar/core/types';
|
|
2
|
-
import {
|
|
2
|
+
import { getSubagentSystemPrompt, getRequirementsTraitPrompt, getKeyBehaviorsReference, getSExprQuickRef, getCommonErrorsSection, getArchitectureSection, getFullOrbitalPrompt } from '@almadar/skills';
|
|
3
3
|
import { tool } from '@langchain/core/tools';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import { LLMClient, ANTHROPIC_MODELS, createAnthropicClient, OPENROUTER_MODELS, createOpenRouterClient, KIMI_MODELS, createKimiClient, OPENAI_MODELS, createOpenAIClient, DEEPSEEK_MODELS, createDeepSeekClient, createRequirementsClient } from '@almadar/llm';
|
|
@@ -7,13 +7,16 @@ import { FilesystemBackend, createDeepAgent } from 'deepagents';
|
|
|
7
7
|
import { MemorySaver } from '@langchain/langgraph';
|
|
8
8
|
export { Command } from '@langchain/langgraph';
|
|
9
9
|
import { v4 } from 'uuid';
|
|
10
|
-
import { exec, spawn } from 'child_process';
|
|
10
|
+
import { exec, spawn, execSync } from 'child_process';
|
|
11
11
|
import * as path from 'path';
|
|
12
|
+
import path__default from 'path';
|
|
12
13
|
import { promisify } from 'util';
|
|
13
14
|
import * as fs4 from 'fs/promises';
|
|
14
15
|
import * as domain_language_star from '@almadar/core/domain-language';
|
|
15
16
|
import * as fs3 from 'fs';
|
|
17
|
+
import fs3__default from 'fs';
|
|
16
18
|
import crypto, { randomUUID } from 'crypto';
|
|
19
|
+
import os from 'os';
|
|
17
20
|
import { GitHubIntegration } from '@almadar/integrations';
|
|
18
21
|
import { BaseCheckpointSaver } from '@langchain/langgraph-checkpoint';
|
|
19
22
|
|
|
@@ -212,20 +215,40 @@ ${guidance}
|
|
|
212
215
|
|
|
213
216
|
${CACHE_BREAK}
|
|
214
217
|
|
|
215
|
-
## Current Orbital Unit
|
|
218
|
+
## Current Orbital Unit (INPUT)
|
|
216
219
|
Name: ${orbital.name}
|
|
217
220
|
Entity: ${entityName}
|
|
218
221
|
Persistence: ${persistence}
|
|
219
222
|
Fields: ${fieldNames}
|
|
220
223
|
Traits: ${orbital.traits.map(getTraitName).join(", ")}
|
|
221
224
|
${contextSection}
|
|
222
|
-
|
|
225
|
+
|
|
226
|
+
## Required Output Structure
|
|
227
|
+
Generate a complete FullOrbitalUnit with this EXACT structure:
|
|
228
|
+
|
|
229
|
+
\`\`\`json
|
|
230
|
+
{
|
|
231
|
+
"name": "${orbital.name}",
|
|
232
|
+
"entity": { // \u2190 REQUIRED FIELD
|
|
233
|
+
"name": "${entityName}",
|
|
234
|
+
"collection": "${entityName.toLowerCase()}s",
|
|
235
|
+
"persistence": "${persistence}",
|
|
236
|
+
"fields": [ ... ]
|
|
237
|
+
},
|
|
238
|
+
"traits": [ ... ],
|
|
239
|
+
"pages": [ ... ]
|
|
240
|
+
}
|
|
241
|
+
\`\`\`
|
|
242
|
+
|
|
243
|
+
**CRITICAL:** The "entity" field is REQUIRED at the orbital level. Do NOT omit it.
|
|
244
|
+
|
|
245
|
+
Additional requirements:
|
|
223
246
|
- Full field definitions with types and validation
|
|
224
247
|
- Trait state machines with transitions and effects
|
|
225
248
|
- Business rule validation using "guard" (singular, NOT "guards") S-expression on SAVE transitions
|
|
226
249
|
- Pages with trait references
|
|
227
250
|
- domainContext with category, vocabulary, and requestFragment
|
|
228
|
-
- design with style and uxHints
|
|
251
|
+
- design with style and uxHints
|
|
229
252
|
`;
|
|
230
253
|
return {
|
|
231
254
|
prompt,
|
|
@@ -265,7 +288,7 @@ ${guidance}`,
|
|
|
265
288
|
const userBlocks = [
|
|
266
289
|
{
|
|
267
290
|
type: "text",
|
|
268
|
-
text: `## Current Orbital Unit
|
|
291
|
+
text: `## Current Orbital Unit (INPUT)
|
|
269
292
|
Name: ${orbital.name}
|
|
270
293
|
Entity: ${entityName}
|
|
271
294
|
Persistence: ${persistence}
|
|
@@ -273,7 +296,40 @@ Fields: ${fieldNames}
|
|
|
273
296
|
Traits: ${orbital.traits.map(getTraitName).join(", ")}
|
|
274
297
|
${contextSection}${connectivitySection ? `
|
|
275
298
|
${connectivitySection}` : ""}
|
|
276
|
-
|
|
299
|
+
|
|
300
|
+
## REQUIRED OUTPUT - VERIFICATION CHECKLIST
|
|
301
|
+
|
|
302
|
+
Before generating output, verify:
|
|
303
|
+
- [ ] "entity" field is present at the TOP LEVEL of the orbital object
|
|
304
|
+
- [ ] entity.name = "${entityName}"
|
|
305
|
+
- [ ] entity.collection = "${entityName.toLowerCase()}s"
|
|
306
|
+
- [ ] entity.persistence = "${persistence}"
|
|
307
|
+
- [ ] entity.fields array has at least ${inlineEntity?.fields.length || 1} field(s)
|
|
308
|
+
- [ ] Full orbital structure includes: name, entity, traits, pages, domainContext, design
|
|
309
|
+
|
|
310
|
+
## Output Structure (Generate This Exact JSON)
|
|
311
|
+
|
|
312
|
+
\`\`\`json
|
|
313
|
+
{
|
|
314
|
+
"name": "${orbital.name}",
|
|
315
|
+
"entity": { // \u2190 THIS FIELD IS MANDATORY
|
|
316
|
+
"name": "${entityName}",
|
|
317
|
+
"collection": "${entityName.toLowerCase()}s",
|
|
318
|
+
"persistence": "${persistence}",
|
|
319
|
+
"fields": [${inlineEntity?.fields.map((f) => `
|
|
320
|
+
{ "name": "${f.name}", "type": "${f.type}"${f.required ? ', "required": true' : ""} }`).join(",") || ""}
|
|
321
|
+
]
|
|
322
|
+
},
|
|
323
|
+
"traits": [ ... trait definitions with state machines ... ],
|
|
324
|
+
"pages": [ ... page definitions ... ],
|
|
325
|
+
"domainContext": { ... domain info ... },
|
|
326
|
+
"design": { ... styling info ... }
|
|
327
|
+
}
|
|
328
|
+
\`\`\`
|
|
329
|
+
|
|
330
|
+
**MANDATORY:** If the output does not have an "entity" field at the orbital level, it is INVALID.
|
|
331
|
+
|
|
332
|
+
Additional requirements:
|
|
277
333
|
- Full field definitions with types and validation
|
|
278
334
|
- Trait state machines with transitions and effects
|
|
279
335
|
- Business rule validation using "guard" (singular, NOT "guards") S-expression on SAVE transitions
|
|
@@ -1157,6 +1213,16 @@ var init_orbital_batch_subagent = __esm({
|
|
|
1157
1213
|
});
|
|
1158
1214
|
}
|
|
1159
1215
|
});
|
|
1216
|
+
var DEFAULT_INTERRUPT_CONFIG = {
|
|
1217
|
+
// Shell commands always require approval
|
|
1218
|
+
execute: true
|
|
1219
|
+
};
|
|
1220
|
+
function getInterruptConfig(_skill) {
|
|
1221
|
+
const config = { ...DEFAULT_INTERRUPT_CONFIG };
|
|
1222
|
+
return config;
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
// src/tools/execute.ts
|
|
1160
1226
|
var DANGEROUS_COMMANDS = [
|
|
1161
1227
|
"rm",
|
|
1162
1228
|
"rmdir",
|
|
@@ -1273,7 +1339,7 @@ function validateCommandPaths(command, workDir) {
|
|
|
1273
1339
|
}
|
|
1274
1340
|
return null;
|
|
1275
1341
|
}
|
|
1276
|
-
function createExecuteTool(workDir) {
|
|
1342
|
+
function createExecuteTool(workDir, auditLog) {
|
|
1277
1343
|
const normalizedWorkDir = path.resolve(workDir);
|
|
1278
1344
|
return tool(
|
|
1279
1345
|
async ({ command, timeout = 6e4 }) => {
|
|
@@ -2606,7 +2672,8 @@ async function generateFullOrbital(client, orbital, options = {}) {
|
|
|
2606
2672
|
traitCount: orbital.traits.length,
|
|
2607
2673
|
hasRequirements: !!requirements
|
|
2608
2674
|
}));
|
|
2609
|
-
const
|
|
2675
|
+
const basePrompt = getSubagentSystemPrompt();
|
|
2676
|
+
const systemPrompt = requirements ? getRequirementsAwareFullOrbitalPrompt(requirements, basePrompt) : basePrompt;
|
|
2610
2677
|
const useCache = client.getProvider() === "anthropic";
|
|
2611
2678
|
let result;
|
|
2612
2679
|
let fingerprint;
|
|
@@ -2677,8 +2744,7 @@ Return valid JSON matching the FullOrbitalUnit schema.`;
|
|
|
2677
2744
|
logs
|
|
2678
2745
|
};
|
|
2679
2746
|
}
|
|
2680
|
-
function getRequirementsAwareFullOrbitalPrompt(requirements) {
|
|
2681
|
-
const basePrompt = getFullOrbitalPrompt();
|
|
2747
|
+
function getRequirementsAwareFullOrbitalPrompt(requirements, basePrompt = getSubagentSystemPrompt()) {
|
|
2682
2748
|
const requirementsGuidance = getRequirementsTraitPrompt();
|
|
2683
2749
|
const sections = [];
|
|
2684
2750
|
if (requirements.guards && requirements.guards.length > 0) {
|
|
@@ -3248,6 +3314,825 @@ function createSchemaChunkingTools(workDir) {
|
|
|
3248
3314
|
applyChunk: createApplyChunkTool(workDir)
|
|
3249
3315
|
};
|
|
3250
3316
|
}
|
|
3317
|
+
|
|
3318
|
+
// src/orchestration/complexity-classifier.ts
|
|
3319
|
+
function classifyComplexity(orbitalCount) {
|
|
3320
|
+
if (orbitalCount <= 0) {
|
|
3321
|
+
throw new Error(`Invalid orbital count: ${orbitalCount}`);
|
|
3322
|
+
}
|
|
3323
|
+
if (orbitalCount === 1) {
|
|
3324
|
+
return {
|
|
3325
|
+
level: "simple",
|
|
3326
|
+
orbitalCount,
|
|
3327
|
+
recommendedProvider: "qwen",
|
|
3328
|
+
reasoning: "Single orbital - Qwen 397B is fast and cost-effective"
|
|
3329
|
+
};
|
|
3330
|
+
}
|
|
3331
|
+
if (orbitalCount <= 3) {
|
|
3332
|
+
return {
|
|
3333
|
+
level: "medium",
|
|
3334
|
+
orbitalCount,
|
|
3335
|
+
recommendedProvider: "qwen",
|
|
3336
|
+
reasoning: "2-3 orbitals - Qwen 397B handles well with good speed/cost"
|
|
3337
|
+
};
|
|
3338
|
+
}
|
|
3339
|
+
return {
|
|
3340
|
+
level: "complex",
|
|
3341
|
+
orbitalCount,
|
|
3342
|
+
recommendedProvider: "multi-provider",
|
|
3343
|
+
reasoning: "4+ orbitals - Multi-provider parallel for optimal speed"
|
|
3344
|
+
};
|
|
3345
|
+
}
|
|
3346
|
+
function estimateComplexity(prompt) {
|
|
3347
|
+
const lowerPrompt = prompt.toLowerCase();
|
|
3348
|
+
const entityPatterns = [
|
|
3349
|
+
/entity[:s]/g,
|
|
3350
|
+
/entities:/g,
|
|
3351
|
+
/- \w+:/g,
|
|
3352
|
+
// List items like "- Task:"
|
|
3353
|
+
/model[s]?:/g,
|
|
3354
|
+
/table[s]?:/g
|
|
3355
|
+
];
|
|
3356
|
+
let entityMatches = 0;
|
|
3357
|
+
for (const pattern of entityPatterns) {
|
|
3358
|
+
const matches = lowerPrompt.match(pattern);
|
|
3359
|
+
if (matches) {
|
|
3360
|
+
entityMatches += matches.length;
|
|
3361
|
+
}
|
|
3362
|
+
}
|
|
3363
|
+
const featureIndicators = [
|
|
3364
|
+
"dashboard",
|
|
3365
|
+
"workflow",
|
|
3366
|
+
"admin",
|
|
3367
|
+
"portal",
|
|
3368
|
+
"system",
|
|
3369
|
+
"management",
|
|
3370
|
+
"booking",
|
|
3371
|
+
"appointment",
|
|
3372
|
+
"inventory",
|
|
3373
|
+
"e-commerce",
|
|
3374
|
+
"healthcare",
|
|
3375
|
+
"patient",
|
|
3376
|
+
"doctor"
|
|
3377
|
+
];
|
|
3378
|
+
let featureMatches = 0;
|
|
3379
|
+
for (const indicator of featureIndicators) {
|
|
3380
|
+
if (lowerPrompt.includes(indicator)) {
|
|
3381
|
+
featureMatches++;
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
3384
|
+
const lengthScore = prompt.length > 500 ? 2 : prompt.length > 200 ? 1 : 0;
|
|
3385
|
+
const score = entityMatches + featureMatches + lengthScore;
|
|
3386
|
+
if (score <= 2) {
|
|
3387
|
+
return { estimatedLevel: "simple", confidence: score === 0 ? "low" : "medium" };
|
|
3388
|
+
}
|
|
3389
|
+
if (score <= 5) {
|
|
3390
|
+
return { estimatedLevel: "medium", confidence: "medium" };
|
|
3391
|
+
}
|
|
3392
|
+
return { estimatedLevel: "complex", confidence: "high" };
|
|
3393
|
+
}
|
|
3394
|
+
function getExecutionStrategy(complexity) {
|
|
3395
|
+
switch (complexity.level) {
|
|
3396
|
+
case "simple":
|
|
3397
|
+
case "medium":
|
|
3398
|
+
return {
|
|
3399
|
+
type: "single",
|
|
3400
|
+
provider: "openrouter",
|
|
3401
|
+
model: "qwen/qwen3.5-397b-a17b",
|
|
3402
|
+
parallelization: 1
|
|
3403
|
+
};
|
|
3404
|
+
case "complex":
|
|
3405
|
+
return {
|
|
3406
|
+
type: "multi-provider",
|
|
3407
|
+
provider: "mixed",
|
|
3408
|
+
model: "deepseek-chat + qwen/qwen3.5-397b-a17b",
|
|
3409
|
+
parallelization: 2
|
|
3410
|
+
};
|
|
3411
|
+
}
|
|
3412
|
+
}
|
|
3413
|
+
function buildOrbitalDefinition(unit) {
|
|
3414
|
+
const traits = unit.traits.map((t) => ({
|
|
3415
|
+
name: t,
|
|
3416
|
+
category: "interaction",
|
|
3417
|
+
linkedEntity: unit.entity,
|
|
3418
|
+
stateMachine: {
|
|
3419
|
+
states: [{ name: "Browsing", isInitial: true }],
|
|
3420
|
+
events: [{ key: "INIT", name: "Initialize" }],
|
|
3421
|
+
transitions: []
|
|
3422
|
+
}
|
|
3423
|
+
}));
|
|
3424
|
+
const pages = [
|
|
3425
|
+
{
|
|
3426
|
+
name: `${unit.name}Page`,
|
|
3427
|
+
path: `/${unit.entity.toLowerCase()}s`,
|
|
3428
|
+
traits: traits.map((t) => ({ ref: t.name }))
|
|
3429
|
+
}
|
|
3430
|
+
];
|
|
3431
|
+
return {
|
|
3432
|
+
name: unit.name,
|
|
3433
|
+
entity: {
|
|
3434
|
+
name: unit.entity,
|
|
3435
|
+
collection: `${unit.entity.toLowerCase()}s`,
|
|
3436
|
+
fields: [{ name: "id", type: "string", required: true }]
|
|
3437
|
+
},
|
|
3438
|
+
traits,
|
|
3439
|
+
pages
|
|
3440
|
+
};
|
|
3441
|
+
}
|
|
3442
|
+
function normalizeDecomposedUnit(unit) {
|
|
3443
|
+
const u = unit;
|
|
3444
|
+
let entityName;
|
|
3445
|
+
if (typeof u.entity === "string") {
|
|
3446
|
+
entityName = u.entity;
|
|
3447
|
+
} else if (u.entity && typeof u.entity === "object") {
|
|
3448
|
+
const entityObj = u.entity;
|
|
3449
|
+
entityName = typeof entityObj.name === "string" ? entityObj.name : "Unknown";
|
|
3450
|
+
} else {
|
|
3451
|
+
entityName = "Unknown";
|
|
3452
|
+
}
|
|
3453
|
+
let traitNames = [];
|
|
3454
|
+
if (Array.isArray(u.traits)) {
|
|
3455
|
+
traitNames = u.traits.map((t) => {
|
|
3456
|
+
if (typeof t === "string") return t;
|
|
3457
|
+
if (t && typeof t === "object") {
|
|
3458
|
+
const to = t;
|
|
3459
|
+
return typeof to.name === "string" ? to.name : String(t);
|
|
3460
|
+
}
|
|
3461
|
+
return String(t);
|
|
3462
|
+
});
|
|
3463
|
+
}
|
|
3464
|
+
return {
|
|
3465
|
+
name: typeof u.name === "string" ? u.name : "Unnamed",
|
|
3466
|
+
entity: entityName,
|
|
3467
|
+
traits: traitNames
|
|
3468
|
+
};
|
|
3469
|
+
}
|
|
3470
|
+
async function decomposeRequest(prompt, skillContent, _config) {
|
|
3471
|
+
const client = new LLMClient({
|
|
3472
|
+
provider: "anthropic",
|
|
3473
|
+
model: "claude-sonnet-4-20250514"
|
|
3474
|
+
});
|
|
3475
|
+
const systemPrompt = `${skillContent}
|
|
3476
|
+
|
|
3477
|
+
Your task is to decompose the user request into orbital units. Return ONLY a JSON array of orbital summaries. Each item should have: name (string), entity (string), traits (array of strings).`;
|
|
3478
|
+
const userPrompt = `Decompose this request into orbital units:
|
|
3479
|
+
|
|
3480
|
+
${prompt}
|
|
3481
|
+
|
|
3482
|
+
Return ONLY a JSON array. Each object must have:
|
|
3483
|
+
- name: orbital name (e.g., "Task Management")
|
|
3484
|
+
- entity: entity name as a STRING (e.g., "Task")
|
|
3485
|
+
- traits: array of trait names as strings (e.g., ["TaskInteraction"])`;
|
|
3486
|
+
const result = await client.call({
|
|
3487
|
+
systemPrompt,
|
|
3488
|
+
userPrompt,
|
|
3489
|
+
maxTokens: 4096,
|
|
3490
|
+
skipSchemaValidation: true
|
|
3491
|
+
});
|
|
3492
|
+
const rawUnits = Array.isArray(result) ? result : [result];
|
|
3493
|
+
return rawUnits.map(normalizeDecomposedUnit);
|
|
3494
|
+
}
|
|
3495
|
+
async function generateWithSingleProvider(units, config) {
|
|
3496
|
+
const client = new LLMClient({
|
|
3497
|
+
provider: "openrouter",
|
|
3498
|
+
model: "qwen/qwen3.5-397b-a17b"
|
|
3499
|
+
});
|
|
3500
|
+
if (config.verbose !== false) {
|
|
3501
|
+
console.log(`[Router] Using single provider (Qwen) for ${units.length} orbitals`);
|
|
3502
|
+
}
|
|
3503
|
+
const orbitals = [];
|
|
3504
|
+
for (const unit of units) {
|
|
3505
|
+
if (config.verbose !== false) {
|
|
3506
|
+
console.log(`[Router] Generating: ${unit.name}...`);
|
|
3507
|
+
}
|
|
3508
|
+
const startTime = Date.now();
|
|
3509
|
+
try {
|
|
3510
|
+
const orbitalDef = buildOrbitalDefinition(unit);
|
|
3511
|
+
const result = await generateFullOrbital(client, orbitalDef, {
|
|
3512
|
+
requirements: { entities: [unit.entity] },
|
|
3513
|
+
maxTokens: 8192
|
|
3514
|
+
});
|
|
3515
|
+
if (config.verbose !== false) {
|
|
3516
|
+
console.log(`[Router] \u2705 ${unit.name}: ${((Date.now() - startTime) / 1e3).toFixed(1)}s`);
|
|
3517
|
+
}
|
|
3518
|
+
orbitals.push(result.orbital);
|
|
3519
|
+
} catch (error) {
|
|
3520
|
+
if (config.verbose !== false) {
|
|
3521
|
+
console.log(`[Router] \u274C ${unit.name}: Failed - ${error instanceof Error ? error.message.slice(0, 50) : "Unknown"}`);
|
|
3522
|
+
}
|
|
3523
|
+
}
|
|
3524
|
+
}
|
|
3525
|
+
return orbitals;
|
|
3526
|
+
}
|
|
3527
|
+
async function generateWithMultiProvider(units, config) {
|
|
3528
|
+
if (config.verbose !== false) {
|
|
3529
|
+
console.log(`[Router] Using multi-provider parallel for ${units.length} orbitals`);
|
|
3530
|
+
}
|
|
3531
|
+
const midpoint = Math.ceil(units.length / 2);
|
|
3532
|
+
const deepseekUnits = units.slice(0, midpoint);
|
|
3533
|
+
const qwenUnits = units.slice(midpoint);
|
|
3534
|
+
if (config.verbose !== false) {
|
|
3535
|
+
console.log(`[Router] Split: ${deepseekUnits.length} to DeepSeek, ${qwenUnits.length} to Qwen`);
|
|
3536
|
+
}
|
|
3537
|
+
const deepseekClient = new LLMClient({
|
|
3538
|
+
provider: "deepseek",
|
|
3539
|
+
model: "deepseek-chat"
|
|
3540
|
+
});
|
|
3541
|
+
const qwenClient = new LLMClient({
|
|
3542
|
+
provider: "openrouter",
|
|
3543
|
+
model: "qwen/qwen3.5-397b-a17b"
|
|
3544
|
+
});
|
|
3545
|
+
const [deepseekResults, qwenResults] = await Promise.all([
|
|
3546
|
+
Promise.all(
|
|
3547
|
+
deepseekUnits.map(async (unit) => {
|
|
3548
|
+
if (config.verbose !== false) {
|
|
3549
|
+
console.log(`[Router] [DeepSeek] Generating: ${unit.name}...`);
|
|
3550
|
+
}
|
|
3551
|
+
const startTime = Date.now();
|
|
3552
|
+
try {
|
|
3553
|
+
const orbitalDef = buildOrbitalDefinition(unit);
|
|
3554
|
+
const result = await generateFullOrbital(deepseekClient, orbitalDef, {
|
|
3555
|
+
requirements: { entities: [unit.entity] },
|
|
3556
|
+
maxTokens: 8192
|
|
3557
|
+
});
|
|
3558
|
+
if (config.verbose !== false) {
|
|
3559
|
+
console.log(`[Router] [DeepSeek] \u2705 ${unit.name}: ${((Date.now() - startTime) / 1e3).toFixed(1)}s`);
|
|
3560
|
+
}
|
|
3561
|
+
return result.orbital;
|
|
3562
|
+
} catch (error) {
|
|
3563
|
+
if (config.verbose !== false) {
|
|
3564
|
+
console.log(`[Router] [DeepSeek] \u274C ${unit.name}: Failed`);
|
|
3565
|
+
}
|
|
3566
|
+
return null;
|
|
3567
|
+
}
|
|
3568
|
+
})
|
|
3569
|
+
),
|
|
3570
|
+
Promise.all(
|
|
3571
|
+
qwenUnits.map(async (unit) => {
|
|
3572
|
+
if (config.verbose !== false) {
|
|
3573
|
+
console.log(`[Router] [Qwen] Generating: ${unit.name}...`);
|
|
3574
|
+
}
|
|
3575
|
+
const startTime = Date.now();
|
|
3576
|
+
try {
|
|
3577
|
+
const orbitalDef = buildOrbitalDefinition(unit);
|
|
3578
|
+
const result = await generateFullOrbital(qwenClient, orbitalDef, {
|
|
3579
|
+
requirements: { entities: [unit.entity] },
|
|
3580
|
+
maxTokens: 8192
|
|
3581
|
+
});
|
|
3582
|
+
if (config.verbose !== false) {
|
|
3583
|
+
console.log(`[Router] [Qwen] \u2705 ${unit.name}: ${((Date.now() - startTime) / 1e3).toFixed(1)}s`);
|
|
3584
|
+
}
|
|
3585
|
+
return result.orbital;
|
|
3586
|
+
} catch (error) {
|
|
3587
|
+
if (config.verbose !== false) {
|
|
3588
|
+
console.log(`[Router] [Qwen] \u274C ${unit.name}: Failed`);
|
|
3589
|
+
}
|
|
3590
|
+
return null;
|
|
3591
|
+
}
|
|
3592
|
+
})
|
|
3593
|
+
)
|
|
3594
|
+
]);
|
|
3595
|
+
return [...deepseekResults, ...qwenResults].filter((o) => o !== null);
|
|
3596
|
+
}
|
|
3597
|
+
async function routeGeneration(prompt, skillContent, config = {}) {
|
|
3598
|
+
const totalStart = Date.now();
|
|
3599
|
+
if (config.verbose !== false) {
|
|
3600
|
+
console.log("[Router] Step 1: Decomposing request...");
|
|
3601
|
+
}
|
|
3602
|
+
const decomposeStart = Date.now();
|
|
3603
|
+
const units = await decomposeRequest(prompt, skillContent);
|
|
3604
|
+
const decomposeMs = Date.now() - decomposeStart;
|
|
3605
|
+
if (config.verbose !== false) {
|
|
3606
|
+
console.log(`[Router] \u2705 Decomposed into ${units.length} orbitals (${(decomposeMs / 1e3).toFixed(1)}s)`);
|
|
3607
|
+
}
|
|
3608
|
+
const complexity = classifyComplexity(units.length);
|
|
3609
|
+
const strategy = getExecutionStrategy(complexity);
|
|
3610
|
+
if (config.verbose !== false) {
|
|
3611
|
+
console.log(`[Router] Complexity: ${complexity.level} (${units.length} orbitals)`);
|
|
3612
|
+
console.log(`[Router] Strategy: ${strategy.type} (${strategy.provider})`);
|
|
3613
|
+
}
|
|
3614
|
+
const generateStart = Date.now();
|
|
3615
|
+
let orbitals;
|
|
3616
|
+
if (complexity.level === "complex") {
|
|
3617
|
+
orbitals = await generateWithMultiProvider(units, config);
|
|
3618
|
+
} else {
|
|
3619
|
+
orbitals = await generateWithSingleProvider(units, config);
|
|
3620
|
+
}
|
|
3621
|
+
const generateMs = Date.now() - generateStart;
|
|
3622
|
+
const totalMs = Date.now() - totalStart;
|
|
3623
|
+
if (config.verbose !== false) {
|
|
3624
|
+
console.log(`[Router] \u2705 Generated ${orbitals.length}/${units.length} orbitals`);
|
|
3625
|
+
console.log(`[Router] Total time: ${(totalMs / 1e3).toFixed(1)}s`);
|
|
3626
|
+
}
|
|
3627
|
+
return {
|
|
3628
|
+
orbitals,
|
|
3629
|
+
complexity,
|
|
3630
|
+
timing: {
|
|
3631
|
+
decomposeMs,
|
|
3632
|
+
generateMs,
|
|
3633
|
+
totalMs
|
|
3634
|
+
},
|
|
3635
|
+
provider: strategy.provider
|
|
3636
|
+
};
|
|
3637
|
+
}
|
|
3638
|
+
function quickComplexityCheck(prompt) {
|
|
3639
|
+
const estimate = estimateComplexity(prompt);
|
|
3640
|
+
const estimatedCounts = {
|
|
3641
|
+
simple: 1,
|
|
3642
|
+
medium: 2,
|
|
3643
|
+
complex: 6
|
|
3644
|
+
};
|
|
3645
|
+
return {
|
|
3646
|
+
likelyComplex: estimate.estimatedLevel === "complex",
|
|
3647
|
+
confidence: estimate.confidence,
|
|
3648
|
+
estimatedOrbitals: estimatedCounts[estimate.estimatedLevel]
|
|
3649
|
+
};
|
|
3650
|
+
}
|
|
3651
|
+
async function createFixPlan(schema, errors, config) {
|
|
3652
|
+
const planStart = Date.now();
|
|
3653
|
+
const criticalErrors = errors.filter(
|
|
3654
|
+
(e) => e.code?.includes("ENTITY") || e.code?.includes("REQUIRED") || e.code?.includes("JSON")
|
|
3655
|
+
);
|
|
3656
|
+
const warningErrors = errors.filter((e) => !criticalErrors.includes(e));
|
|
3657
|
+
const orbitalErrors = /* @__PURE__ */ new Map();
|
|
3658
|
+
errors.forEach((error, index) => {
|
|
3659
|
+
let pathStr;
|
|
3660
|
+
if (Array.isArray(error.path)) {
|
|
3661
|
+
pathStr = error.path.join(".");
|
|
3662
|
+
} else if (typeof error.path === "string") {
|
|
3663
|
+
pathStr = error.path;
|
|
3664
|
+
} else {
|
|
3665
|
+
pathStr = String(error.path || "");
|
|
3666
|
+
}
|
|
3667
|
+
const match = pathStr.match(/orbitals\[(\d+)\]/);
|
|
3668
|
+
const orbitalIndex = match ? parseInt(match[1], 10) : -1;
|
|
3669
|
+
if (orbitalIndex >= 0) {
|
|
3670
|
+
if (!orbitalErrors.has(orbitalIndex)) {
|
|
3671
|
+
orbitalErrors.set(orbitalIndex, []);
|
|
3672
|
+
}
|
|
3673
|
+
orbitalErrors.get(orbitalIndex).push(index);
|
|
3674
|
+
}
|
|
3675
|
+
});
|
|
3676
|
+
const executionOrder = [];
|
|
3677
|
+
const affectedOrbitals = [];
|
|
3678
|
+
for (const [orbitalIndex, errorIndices] of orbitalErrors) {
|
|
3679
|
+
const orbital = schema.orbitals[orbitalIndex];
|
|
3680
|
+
if (orbital) {
|
|
3681
|
+
affectedOrbitals.push(orbital.name);
|
|
3682
|
+
const midPoint = Math.ceil(errorIndices.length / 2);
|
|
3683
|
+
const batches = [
|
|
3684
|
+
errorIndices.slice(0, midPoint),
|
|
3685
|
+
errorIndices.slice(midPoint)
|
|
3686
|
+
].filter((b) => b.length > 0);
|
|
3687
|
+
batches.forEach((batch, batchIndex) => {
|
|
3688
|
+
executionOrder.push({
|
|
3689
|
+
id: `fix-${orbitalIndex}-${batchIndex}`,
|
|
3690
|
+
description: `Fix ${batch.length} errors in ${orbital.name}`,
|
|
3691
|
+
orbitalIndex,
|
|
3692
|
+
errorIndices: batch,
|
|
3693
|
+
provider: batchIndex === 0 ? "deepseek" : "qwen",
|
|
3694
|
+
dependencies: []
|
|
3695
|
+
});
|
|
3696
|
+
});
|
|
3697
|
+
}
|
|
3698
|
+
}
|
|
3699
|
+
let parallelizationStrategy = "single";
|
|
3700
|
+
if (executionOrder.length >= 4) {
|
|
3701
|
+
parallelizationStrategy = "multi-provider";
|
|
3702
|
+
} else if (JSON.stringify(schema).length > 5e4) {
|
|
3703
|
+
parallelizationStrategy = "chunked";
|
|
3704
|
+
}
|
|
3705
|
+
const plan = {
|
|
3706
|
+
summary: {
|
|
3707
|
+
totalErrors: errors.length,
|
|
3708
|
+
criticalErrors: criticalErrors.length,
|
|
3709
|
+
warningErrors: warningErrors.length,
|
|
3710
|
+
affectedOrbitals: [...new Set(affectedOrbitals)]
|
|
3711
|
+
},
|
|
3712
|
+
executionOrder,
|
|
3713
|
+
parallelizationStrategy
|
|
3714
|
+
};
|
|
3715
|
+
if (config.verbose) {
|
|
3716
|
+
console.log(`[Fixing] Plan created in ${Date.now() - planStart}ms`);
|
|
3717
|
+
console.log(`[Fixing] Strategy: ${parallelizationStrategy}`);
|
|
3718
|
+
console.log(`[Fixing] Steps: ${executionOrder.length}`);
|
|
3719
|
+
}
|
|
3720
|
+
return plan;
|
|
3721
|
+
}
|
|
3722
|
+
async function executeFixStep(schema, step, errors, config) {
|
|
3723
|
+
const orbital = schema.orbitals[step.orbitalIndex];
|
|
3724
|
+
if (!orbital) {
|
|
3725
|
+
return { success: false, updatedOrbital: null };
|
|
3726
|
+
}
|
|
3727
|
+
const client = step.provider === "deepseek" ? new LLMClient({
|
|
3728
|
+
provider: "deepseek",
|
|
3729
|
+
model: "deepseek-chat"
|
|
3730
|
+
}) : new LLMClient({
|
|
3731
|
+
provider: "openrouter",
|
|
3732
|
+
model: "qwen/qwen3.5-397b-a17b"
|
|
3733
|
+
});
|
|
3734
|
+
const stepErrors = step.errorIndices.map((i) => errors[i]);
|
|
3735
|
+
const skillContent = config.skillContent || "";
|
|
3736
|
+
const hasBindingErrors = stepErrors.some(
|
|
3737
|
+
(e) => e.message?.toLowerCase().includes("binding") || e.code?.toLowerCase().includes("binding")
|
|
3738
|
+
);
|
|
3739
|
+
const bindingGuidance = hasBindingErrors ? `
|
|
3740
|
+
## BINDING ERROR FIXES
|
|
3741
|
+
|
|
3742
|
+
Common binding mistakes and fixes:
|
|
3743
|
+
|
|
3744
|
+
\u274C INVALID:
|
|
3745
|
+
- "@count" \u2192 missing entity reference
|
|
3746
|
+
- "@status" \u2192 missing entity reference
|
|
3747
|
+
- "@count:status=active" \u2192 wrong syntax
|
|
3748
|
+
|
|
3749
|
+
\u2705 VALID (from skill):
|
|
3750
|
+
- "@entity.count" - entity field reference
|
|
3751
|
+
- "@entity.status" - enum field reference
|
|
3752
|
+
- "@payload.data" - event payload data
|
|
3753
|
+
- "@state" - current state name
|
|
3754
|
+
- "@now" - current timestamp
|
|
3755
|
+
|
|
3756
|
+
Replace bare field names like "@count" with proper entity references like "@entity.count".
|
|
3757
|
+
` : "";
|
|
3758
|
+
const systemPrompt = `${skillContent}
|
|
3759
|
+
|
|
3760
|
+
${bindingGuidance}
|
|
3761
|
+
|
|
3762
|
+
## FIXING INSTRUCTIONS
|
|
3763
|
+
|
|
3764
|
+
You are fixing validation errors in an OrbitalSchema orbital.
|
|
3765
|
+
|
|
3766
|
+
Rules:
|
|
3767
|
+
1. Preserve ALL valid content - only fix the reported errors
|
|
3768
|
+
2. Return the COMPLETE orbital with entity, traits, and pages
|
|
3769
|
+
3. Ensure entity has: name, collection, and fields array
|
|
3770
|
+
4. Use valid binding formats: @entity.field, @payload.field, @state
|
|
3771
|
+
|
|
3772
|
+
Return ONLY the fixed orbital as valid JSON.`;
|
|
3773
|
+
const userPrompt = `Fix these validation errors in orbital "${orbital.name}":
|
|
3774
|
+
|
|
3775
|
+
ERRORS:
|
|
3776
|
+
${stepErrors.map((e) => {
|
|
3777
|
+
const path8 = Array.isArray(e.path) ? e.path.join(".") : e.path;
|
|
3778
|
+
return `- Path: ${path8}
|
|
3779
|
+
Code: ${e.code}
|
|
3780
|
+
Message: ${e.message}`;
|
|
3781
|
+
}).join("\n")}
|
|
3782
|
+
|
|
3783
|
+
CURRENT ORBITAL (JSON):
|
|
3784
|
+
${JSON.stringify(orbital, null, 2)}
|
|
3785
|
+
|
|
3786
|
+
Return the COMPLETE fixed orbital as JSON with all fields (entity, traits, pages).`;
|
|
3787
|
+
try {
|
|
3788
|
+
const result = await client.call({
|
|
3789
|
+
systemPrompt,
|
|
3790
|
+
userPrompt,
|
|
3791
|
+
maxTokens: 8192,
|
|
3792
|
+
skipSchemaValidation: true
|
|
3793
|
+
});
|
|
3794
|
+
return {
|
|
3795
|
+
success: true,
|
|
3796
|
+
updatedOrbital: result
|
|
3797
|
+
};
|
|
3798
|
+
} catch (error) {
|
|
3799
|
+
return {
|
|
3800
|
+
success: false,
|
|
3801
|
+
updatedOrbital: null
|
|
3802
|
+
};
|
|
3803
|
+
}
|
|
3804
|
+
}
|
|
3805
|
+
async function executeFixPlan(schema, plan, errors, config) {
|
|
3806
|
+
const executeStart = Date.now();
|
|
3807
|
+
const updatedSchema = { ...schema };
|
|
3808
|
+
if (plan.parallelizationStrategy === "multi-provider") {
|
|
3809
|
+
const deepseekSteps = plan.executionOrder.filter((s) => s.provider === "deepseek");
|
|
3810
|
+
const qwenSteps = plan.executionOrder.filter((s) => s.provider === "qwen");
|
|
3811
|
+
if (config.verbose) {
|
|
3812
|
+
console.log(`[Fixing] Executing ${deepseekSteps.length} steps on DeepSeek, ${qwenSteps.length} on Qwen`);
|
|
3813
|
+
}
|
|
3814
|
+
const [deepseekResults, qwenResults] = await Promise.all([
|
|
3815
|
+
Promise.all(deepseekSteps.map((step) => executeFixStep(schema, step, errors, config))),
|
|
3816
|
+
Promise.all(qwenSteps.map((step) => executeFixStep(schema, step, errors, config)))
|
|
3817
|
+
]);
|
|
3818
|
+
deepseekSteps.forEach((step, i) => {
|
|
3819
|
+
if (deepseekResults[i].success) {
|
|
3820
|
+
updatedSchema.orbitals[step.orbitalIndex] = deepseekResults[i].updatedOrbital;
|
|
3821
|
+
}
|
|
3822
|
+
});
|
|
3823
|
+
qwenSteps.forEach((step, i) => {
|
|
3824
|
+
if (qwenResults[i].success) {
|
|
3825
|
+
updatedSchema.orbitals[step.orbitalIndex] = qwenResults[i].updatedOrbital;
|
|
3826
|
+
}
|
|
3827
|
+
});
|
|
3828
|
+
} else {
|
|
3829
|
+
for (const step of plan.executionOrder) {
|
|
3830
|
+
if (config.verbose) {
|
|
3831
|
+
console.log(`[Fixing] Executing: ${step.description}`);
|
|
3832
|
+
}
|
|
3833
|
+
const result = await executeFixStep(schema, step, errors, config);
|
|
3834
|
+
if (result.success) {
|
|
3835
|
+
updatedSchema.orbitals[step.orbitalIndex] = result.updatedOrbital;
|
|
3836
|
+
}
|
|
3837
|
+
}
|
|
3838
|
+
}
|
|
3839
|
+
if (config.verbose) {
|
|
3840
|
+
console.log(`[Fixing] Execution completed in ${Date.now() - executeStart}ms`);
|
|
3841
|
+
}
|
|
3842
|
+
return updatedSchema;
|
|
3843
|
+
}
|
|
3844
|
+
function validateSchema(schema) {
|
|
3845
|
+
const tempDir = path__default.join(os.tmpdir(), "almadar-fixing");
|
|
3846
|
+
fs3__default.mkdirSync(tempDir, { recursive: true });
|
|
3847
|
+
const tempFile = path__default.join(tempDir, `schema-${Date.now()}.orb`);
|
|
3848
|
+
try {
|
|
3849
|
+
fs3__default.writeFileSync(tempFile, JSON.stringify(schema, null, 2));
|
|
3850
|
+
const output = execSync(`npx @almadar/cli validate --json "${tempFile}"`, {
|
|
3851
|
+
encoding: "utf-8",
|
|
3852
|
+
timeout: 3e4
|
|
3853
|
+
});
|
|
3854
|
+
fs3__default.unlinkSync(tempFile);
|
|
3855
|
+
const result = JSON.parse(output);
|
|
3856
|
+
return {
|
|
3857
|
+
valid: result.valid,
|
|
3858
|
+
errors: result.errors || []
|
|
3859
|
+
};
|
|
3860
|
+
} catch (error) {
|
|
3861
|
+
try {
|
|
3862
|
+
fs3__default.unlinkSync(tempFile);
|
|
3863
|
+
} catch {
|
|
3864
|
+
}
|
|
3865
|
+
try {
|
|
3866
|
+
const result = JSON.parse(error.stdout || "{}");
|
|
3867
|
+
return {
|
|
3868
|
+
valid: false,
|
|
3869
|
+
errors: result.errors || []
|
|
3870
|
+
};
|
|
3871
|
+
} catch {
|
|
3872
|
+
return {
|
|
3873
|
+
valid: false,
|
|
3874
|
+
errors: [{ code: "ERROR", message: error.message, path: [""], severity: "error" }]
|
|
3875
|
+
};
|
|
3876
|
+
}
|
|
3877
|
+
}
|
|
3878
|
+
}
|
|
3879
|
+
async function orchestrateFixing(schema, config = {}) {
|
|
3880
|
+
const totalStart = Date.now();
|
|
3881
|
+
if (config.verbose) {
|
|
3882
|
+
console.log("[Fixing] Starting Plan-Then-Execute fixing workflow");
|
|
3883
|
+
}
|
|
3884
|
+
const initialValidation = validateSchema(schema);
|
|
3885
|
+
if (initialValidation.valid) {
|
|
3886
|
+
return {
|
|
3887
|
+
success: true,
|
|
3888
|
+
fixedSchema: schema,
|
|
3889
|
+
plan: {
|
|
3890
|
+
summary: { totalErrors: 0, criticalErrors: 0, warningErrors: 0, affectedOrbitals: [] },
|
|
3891
|
+
executionOrder: [],
|
|
3892
|
+
parallelizationStrategy: "single"
|
|
3893
|
+
},
|
|
3894
|
+
stepsCompleted: 0,
|
|
3895
|
+
stepsTotal: 0,
|
|
3896
|
+
remainingErrors: [],
|
|
3897
|
+
timing: {
|
|
3898
|
+
planMs: 0,
|
|
3899
|
+
executeMs: 0,
|
|
3900
|
+
verifyMs: 0,
|
|
3901
|
+
totalMs: Date.now() - totalStart
|
|
3902
|
+
}
|
|
3903
|
+
};
|
|
3904
|
+
}
|
|
3905
|
+
const planStart = Date.now();
|
|
3906
|
+
const plan = await createFixPlan(schema, initialValidation.errors, config);
|
|
3907
|
+
const planMs = Date.now() - planStart;
|
|
3908
|
+
const executeStart = Date.now();
|
|
3909
|
+
let fixedSchema = await executeFixPlan(schema, plan, initialValidation.errors, config);
|
|
3910
|
+
const executeMs = Date.now() - executeStart;
|
|
3911
|
+
const verifyStart = Date.now();
|
|
3912
|
+
const finalValidation = validateSchema(fixedSchema);
|
|
3913
|
+
const verifyMs = Date.now() - verifyStart;
|
|
3914
|
+
let retries = 0;
|
|
3915
|
+
const maxRetries = config.maxRetries || 2;
|
|
3916
|
+
while (!finalValidation.valid && retries < maxRetries) {
|
|
3917
|
+
if (config.verbose) {
|
|
3918
|
+
console.log(`[Fixing] Retrying (${retries + 1}/${maxRetries})...`);
|
|
3919
|
+
}
|
|
3920
|
+
const retryPlan = await createFixPlan(fixedSchema, finalValidation.errors, config);
|
|
3921
|
+
fixedSchema = await executeFixPlan(fixedSchema, retryPlan, finalValidation.errors, config);
|
|
3922
|
+
const retryValidation = validateSchema(fixedSchema);
|
|
3923
|
+
if (retryValidation.valid || retryValidation.errors.length < finalValidation.errors.length) {
|
|
3924
|
+
finalValidation.errors = retryValidation.errors;
|
|
3925
|
+
finalValidation.valid = retryValidation.valid;
|
|
3926
|
+
}
|
|
3927
|
+
retries++;
|
|
3928
|
+
}
|
|
3929
|
+
const totalMs = Date.now() - totalStart;
|
|
3930
|
+
if (config.verbose) {
|
|
3931
|
+
console.log("[Fixing] === Summary ===");
|
|
3932
|
+
console.log(`[Fixing] Plan: ${planMs}ms, Execute: ${executeMs}ms, Verify: ${verifyMs}ms`);
|
|
3933
|
+
console.log(`[Fixing] Total: ${totalMs}ms`);
|
|
3934
|
+
console.log(`[Fixing] Errors: ${initialValidation.errors.length} \u2192 ${finalValidation.errors.length}`);
|
|
3935
|
+
console.log(`[Fixing] Success: ${finalValidation.valid ? "YES" : "PARTIAL"}`);
|
|
3936
|
+
}
|
|
3937
|
+
return {
|
|
3938
|
+
success: finalValidation.valid,
|
|
3939
|
+
fixedSchema: finalValidation.valid ? fixedSchema : null,
|
|
3940
|
+
plan,
|
|
3941
|
+
stepsCompleted: plan.executionOrder.length - retries,
|
|
3942
|
+
stepsTotal: plan.executionOrder.length,
|
|
3943
|
+
remainingErrors: finalValidation.errors,
|
|
3944
|
+
timing: {
|
|
3945
|
+
planMs,
|
|
3946
|
+
executeMs,
|
|
3947
|
+
verifyMs,
|
|
3948
|
+
totalMs
|
|
3949
|
+
}
|
|
3950
|
+
};
|
|
3951
|
+
}
|
|
3952
|
+
|
|
3953
|
+
// src/tools/orchestrated-generation.ts
|
|
3954
|
+
function createOrchestratedGenerationTool(options) {
|
|
3955
|
+
const { skillContent, verbose = false } = options;
|
|
3956
|
+
return tool(
|
|
3957
|
+
async ({ prompt }) => {
|
|
3958
|
+
const startTime = Date.now();
|
|
3959
|
+
if (verbose) {
|
|
3960
|
+
console.log("[OrchestratedGeneration] Starting generation...");
|
|
3961
|
+
console.log(`[OrchestratedGeneration] Prompt length: ${prompt.length} chars`);
|
|
3962
|
+
}
|
|
3963
|
+
const quickCheck = quickComplexityCheck(prompt);
|
|
3964
|
+
if (verbose) {
|
|
3965
|
+
console.log(`[OrchestratedGeneration] Quick check: ~${quickCheck.estimatedOrbitals} orbitals (${quickCheck.confidence} confidence)`);
|
|
3966
|
+
}
|
|
3967
|
+
try {
|
|
3968
|
+
const result = await routeGeneration(prompt, skillContent, {
|
|
3969
|
+
verbose
|
|
3970
|
+
});
|
|
3971
|
+
const totalTime = Date.now() - startTime;
|
|
3972
|
+
if (verbose) {
|
|
3973
|
+
console.log(`[OrchestratedGeneration] \u2705 Success: ${result.orbitals.length} orbitals`);
|
|
3974
|
+
console.log(`[OrchestratedGeneration] Provider: ${result.provider}`);
|
|
3975
|
+
console.log(`[OrchestratedGeneration] Total time: ${totalTime}ms`);
|
|
3976
|
+
}
|
|
3977
|
+
const schema = {
|
|
3978
|
+
name: "GeneratedApp",
|
|
3979
|
+
version: "1.0.0",
|
|
3980
|
+
orbitals: result.orbitals
|
|
3981
|
+
};
|
|
3982
|
+
return {
|
|
3983
|
+
success: true,
|
|
3984
|
+
schema,
|
|
3985
|
+
complexity: result.complexity,
|
|
3986
|
+
provider: result.provider,
|
|
3987
|
+
timing: result.timing
|
|
3988
|
+
};
|
|
3989
|
+
} catch (error) {
|
|
3990
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3991
|
+
if (verbose) {
|
|
3992
|
+
console.log(`[OrchestratedGeneration] \u274C Failed: ${errorMessage}`);
|
|
3993
|
+
}
|
|
3994
|
+
return {
|
|
3995
|
+
success: false,
|
|
3996
|
+
error: errorMessage
|
|
3997
|
+
};
|
|
3998
|
+
}
|
|
3999
|
+
},
|
|
4000
|
+
{
|
|
4001
|
+
name: "generate_schema_orchestrated",
|
|
4002
|
+
description: `Generate an OrbitalSchema using complexity-based provider routing.
|
|
4003
|
+
|
|
4004
|
+
This tool automatically selects the best generation strategy:
|
|
4005
|
+
- Simple (1 orbital) \u2192 Fast single-provider generation
|
|
4006
|
+
- Medium (2-3 orbitals) \u2192 Efficient single-provider generation
|
|
4007
|
+
- Complex (4+ orbitals) \u2192 Parallel multi-provider generation
|
|
4008
|
+
|
|
4009
|
+
The tool handles decomposition, provider selection, and result combination automatically.`,
|
|
4010
|
+
schema: z.object({
|
|
4011
|
+
prompt: z.string().describe("User prompt describing the application to generate")
|
|
4012
|
+
})
|
|
4013
|
+
}
|
|
4014
|
+
);
|
|
4015
|
+
}
|
|
4016
|
+
function validateSchema2(schema) {
|
|
4017
|
+
const tempDir = path__default.join(os.tmpdir(), "almadar-fixing");
|
|
4018
|
+
fs3__default.mkdirSync(tempDir, { recursive: true });
|
|
4019
|
+
const tempFile = path__default.join(tempDir, `schema-${Date.now()}.orb`);
|
|
4020
|
+
try {
|
|
4021
|
+
fs3__default.writeFileSync(tempFile, JSON.stringify(schema, null, 2));
|
|
4022
|
+
const output = execSync(`npx @almadar/cli validate --json "${tempFile}"`, {
|
|
4023
|
+
encoding: "utf-8",
|
|
4024
|
+
timeout: 3e4
|
|
4025
|
+
});
|
|
4026
|
+
fs3__default.unlinkSync(tempFile);
|
|
4027
|
+
const result = JSON.parse(output);
|
|
4028
|
+
return {
|
|
4029
|
+
valid: result.valid,
|
|
4030
|
+
errors: result.errors || []
|
|
4031
|
+
};
|
|
4032
|
+
} catch (error) {
|
|
4033
|
+
try {
|
|
4034
|
+
fs3__default.unlinkSync(tempFile);
|
|
4035
|
+
} catch {
|
|
4036
|
+
}
|
|
4037
|
+
try {
|
|
4038
|
+
const result = JSON.parse(error.stdout || "{}");
|
|
4039
|
+
return {
|
|
4040
|
+
valid: false,
|
|
4041
|
+
errors: result.errors || []
|
|
4042
|
+
};
|
|
4043
|
+
} catch {
|
|
4044
|
+
return {
|
|
4045
|
+
valid: false,
|
|
4046
|
+
errors: [{ code: "ERROR", message: error.message }]
|
|
4047
|
+
};
|
|
4048
|
+
}
|
|
4049
|
+
}
|
|
4050
|
+
}
|
|
4051
|
+
function createOrchestratedFixingTool(options) {
|
|
4052
|
+
const { skillContent, maxRetries = 2, verbose = false } = options;
|
|
4053
|
+
return tool(
|
|
4054
|
+
async ({ schema }) => {
|
|
4055
|
+
const typedSchema = schema;
|
|
4056
|
+
if (verbose) {
|
|
4057
|
+
console.log("[OrchestratedFixing] Starting fixing workflow...");
|
|
4058
|
+
}
|
|
4059
|
+
const initialValidation = validateSchema2(typedSchema);
|
|
4060
|
+
if (initialValidation.valid) {
|
|
4061
|
+
if (verbose) {
|
|
4062
|
+
console.log("[OrchestratedFixing] Schema is already valid");
|
|
4063
|
+
}
|
|
4064
|
+
return {
|
|
4065
|
+
success: true,
|
|
4066
|
+
schema: typedSchema,
|
|
4067
|
+
fixSummary: {
|
|
4068
|
+
totalErrors: 0,
|
|
4069
|
+
errorsFixed: 0,
|
|
4070
|
+
errorsRemaining: 0,
|
|
4071
|
+
strategy: "none-needed",
|
|
4072
|
+
stepsExecuted: 0
|
|
4073
|
+
},
|
|
4074
|
+
timing: {
|
|
4075
|
+
planMs: 0,
|
|
4076
|
+
executeMs: 0,
|
|
4077
|
+
verifyMs: 0,
|
|
4078
|
+
totalMs: 0
|
|
4079
|
+
}
|
|
4080
|
+
};
|
|
4081
|
+
}
|
|
4082
|
+
if (verbose) {
|
|
4083
|
+
console.log(`[OrchestratedFixing] Found ${initialValidation.errors.length} errors to fix`);
|
|
4084
|
+
}
|
|
4085
|
+
try {
|
|
4086
|
+
const result = await orchestrateFixing(typedSchema, {
|
|
4087
|
+
maxRetries,
|
|
4088
|
+
verbose,
|
|
4089
|
+
skillContent
|
|
4090
|
+
});
|
|
4091
|
+
if (verbose) {
|
|
4092
|
+
console.log(`[OrchestratedFixing] ${result.success ? "\u2705" : "\u26A0\uFE0F"} Fix complete`);
|
|
4093
|
+
console.log(`[OrchestratedFixing] Errors: ${result.plan.summary.totalErrors} \u2192 ${result.remainingErrors.length}`);
|
|
4094
|
+
}
|
|
4095
|
+
return {
|
|
4096
|
+
success: result.success,
|
|
4097
|
+
schema: result.fixedSchema || typedSchema,
|
|
4098
|
+
fixSummary: {
|
|
4099
|
+
totalErrors: result.plan.summary.totalErrors,
|
|
4100
|
+
errorsFixed: result.plan.summary.totalErrors - result.remainingErrors.length,
|
|
4101
|
+
errorsRemaining: result.remainingErrors.length,
|
|
4102
|
+
strategy: result.plan.parallelizationStrategy,
|
|
4103
|
+
stepsExecuted: result.stepsCompleted
|
|
4104
|
+
},
|
|
4105
|
+
timing: result.timing
|
|
4106
|
+
};
|
|
4107
|
+
} catch (error) {
|
|
4108
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4109
|
+
if (verbose) {
|
|
4110
|
+
console.log(`[OrchestratedFixing] \u274C Failed: ${errorMessage}`);
|
|
4111
|
+
}
|
|
4112
|
+
return {
|
|
4113
|
+
success: false,
|
|
4114
|
+
schema: typedSchema,
|
|
4115
|
+
error: errorMessage
|
|
4116
|
+
};
|
|
4117
|
+
}
|
|
4118
|
+
},
|
|
4119
|
+
{
|
|
4120
|
+
name: "fix_schema_orchestrated",
|
|
4121
|
+
description: `Fix validation errors in an OrbitalSchema using Plan-Then-Execute strategy.
|
|
4122
|
+
|
|
4123
|
+
This tool:
|
|
4124
|
+
1. Validates the schema to identify errors
|
|
4125
|
+
2. Creates a fix plan based on error types
|
|
4126
|
+
3. Applies fixes using the fixing skill guidance
|
|
4127
|
+
4. Re-validates and retries if needed
|
|
4128
|
+
|
|
4129
|
+
Works with single or multi-orbital schemas, automatically selecting the best strategy.`,
|
|
4130
|
+
schema: z.object({
|
|
4131
|
+
schema: z.object({}).describe("The OrbitalSchema to fix")
|
|
4132
|
+
})
|
|
4133
|
+
}
|
|
4134
|
+
);
|
|
4135
|
+
}
|
|
3251
4136
|
function createGitHubTools(config) {
|
|
3252
4137
|
const { token, owner = "", repo = "", workDir } = config;
|
|
3253
4138
|
const integrationConfig = {
|
|
@@ -4273,16 +5158,6 @@ var SessionManager = class {
|
|
|
4273
5158
|
}
|
|
4274
5159
|
};
|
|
4275
5160
|
|
|
4276
|
-
// src/agent/interrupt-config.ts
|
|
4277
|
-
var DEFAULT_INTERRUPT_CONFIG = {
|
|
4278
|
-
// Shell commands always require approval
|
|
4279
|
-
execute: true
|
|
4280
|
-
};
|
|
4281
|
-
function getInterruptConfig(_skill) {
|
|
4282
|
-
const config = { ...DEFAULT_INTERRUPT_CONFIG };
|
|
4283
|
-
return config;
|
|
4284
|
-
}
|
|
4285
|
-
|
|
4286
5161
|
// src/agent/skill-agent.ts
|
|
4287
5162
|
var BASE_SYSTEM_PROMPT = `You are a KFlow agent that helps users create and manage application schemas.
|
|
4288
5163
|
|
|
@@ -4489,6 +5364,30 @@ ${skillContents}`;
|
|
|
4489
5364
|
const isOrbitalBatchSkill = ORBITAL_BATCH_SKILLS.includes(primarySkill.name);
|
|
4490
5365
|
const isLeanSkill = LEAN_SKILLS.includes(primarySkill.name);
|
|
4491
5366
|
const needsChunkingTools = ORBITAL_SKILLS.includes(primarySkill.name);
|
|
5367
|
+
const useOrchestration = options.useOrchestration ?? false;
|
|
5368
|
+
let orchestratedGenerationTool;
|
|
5369
|
+
let orchestratedFixingTool;
|
|
5370
|
+
if (useOrchestration) {
|
|
5371
|
+
if (isOrbitalSkill) {
|
|
5372
|
+
orchestratedGenerationTool = createOrchestratedGenerationTool({
|
|
5373
|
+
skillContent: primarySkill.content,
|
|
5374
|
+
verbose
|
|
5375
|
+
});
|
|
5376
|
+
if (verbose) {
|
|
5377
|
+
console.log(`[SkillAgent] Orchestrated generation enabled for ${primarySkill.name}`);
|
|
5378
|
+
}
|
|
5379
|
+
}
|
|
5380
|
+
if (primarySkill.name === "kflow-orbital-fixing") {
|
|
5381
|
+
orchestratedFixingTool = createOrchestratedFixingTool({
|
|
5382
|
+
skillContent: primarySkill.content,
|
|
5383
|
+
maxRetries: 2,
|
|
5384
|
+
verbose
|
|
5385
|
+
});
|
|
5386
|
+
if (verbose) {
|
|
5387
|
+
console.log(`[SkillAgent] Orchestrated fixing enabled for ${primarySkill.name}`);
|
|
5388
|
+
}
|
|
5389
|
+
}
|
|
5390
|
+
}
|
|
4492
5391
|
let orbitalTool;
|
|
4493
5392
|
let setOrbitalEventCallback;
|
|
4494
5393
|
let setOrbitalCompleteCallback;
|
|
@@ -4548,10 +5447,10 @@ ${skillContents}`;
|
|
|
4548
5447
|
if (githubTools && verbose) {
|
|
4549
5448
|
console.log(`[SkillAgent] GitHub tools enabled`);
|
|
4550
5449
|
}
|
|
4551
|
-
|
|
5450
|
+
let tools = [
|
|
4552
5451
|
executeTool,
|
|
4553
5452
|
finishTaskTool,
|
|
4554
|
-
|
|
5453
|
+
validateSchemaTool,
|
|
4555
5454
|
...orbitalTool ? [orbitalTool] : [],
|
|
4556
5455
|
...orbitalBatchTool ? [orbitalBatchTool] : [],
|
|
4557
5456
|
...domainOrbitalTools ? [
|
|
@@ -4563,8 +5462,14 @@ ${skillContents}`;
|
|
|
4563
5462
|
chunkingTools.extractChunk,
|
|
4564
5463
|
chunkingTools.applyChunk
|
|
4565
5464
|
] : [],
|
|
4566
|
-
...githubTools || []
|
|
5465
|
+
...githubTools || [],
|
|
5466
|
+
// Add orchestrated tools when enabled
|
|
5467
|
+
...orchestratedGenerationTool ? [orchestratedGenerationTool] : [],
|
|
5468
|
+
...orchestratedFixingTool ? [orchestratedFixingTool] : []
|
|
4567
5469
|
];
|
|
5470
|
+
if (options.toolWrapper) {
|
|
5471
|
+
tools = tools.map(options.toolWrapper);
|
|
5472
|
+
}
|
|
4568
5473
|
const checkpointer = sessions.getCheckpointer(threadId);
|
|
4569
5474
|
const interruptConfig = options.noInterrupt ? void 0 : getInterruptConfig();
|
|
4570
5475
|
const agent = createDeepAgent({
|
|
@@ -6127,11 +7032,11 @@ var WorkflowBuilder = class {
|
|
|
6127
7032
|
this.definition.inputs[name] = { type, required, default: defaultValue };
|
|
6128
7033
|
return this;
|
|
6129
7034
|
}
|
|
6130
|
-
step(id,
|
|
7035
|
+
step(id, tool14, input, options = {}) {
|
|
6131
7036
|
this.definition.steps.push({
|
|
6132
7037
|
id,
|
|
6133
7038
|
name: id,
|
|
6134
|
-
tool:
|
|
7039
|
+
tool: tool14,
|
|
6135
7040
|
input,
|
|
6136
7041
|
dependsOn: options.dependsOn,
|
|
6137
7042
|
condition: options.condition,
|
|
@@ -6644,8 +7549,8 @@ var HITLWorkflowEngine = class {
|
|
|
6644
7549
|
const result = {};
|
|
6645
7550
|
for (const [key, value] of Object.entries(input)) {
|
|
6646
7551
|
if (typeof value === "string" && value.startsWith("{{") && value.endsWith("}}")) {
|
|
6647
|
-
const
|
|
6648
|
-
result[key] = this.getValueFromPath(context,
|
|
7552
|
+
const path8 = value.slice(2, -2).trim();
|
|
7553
|
+
result[key] = this.getValueFromPath(context, path8);
|
|
6649
7554
|
} else {
|
|
6650
7555
|
result[key] = value;
|
|
6651
7556
|
}
|
|
@@ -6655,8 +7560,8 @@ var HITLWorkflowEngine = class {
|
|
|
6655
7560
|
/**
|
|
6656
7561
|
* Get value from path
|
|
6657
7562
|
*/
|
|
6658
|
-
getValueFromPath(obj,
|
|
6659
|
-
const parts =
|
|
7563
|
+
getValueFromPath(obj, path8) {
|
|
7564
|
+
const parts = path8.split(".");
|
|
6660
7565
|
let current = obj;
|
|
6661
7566
|
for (const part of parts) {
|
|
6662
7567
|
if (current && typeof current === "object") {
|
|
@@ -6747,6 +7652,119 @@ function createHITLWorkflowEngine(options) {
|
|
|
6747
7652
|
return new HITLWorkflowEngine(options);
|
|
6748
7653
|
}
|
|
6749
7654
|
|
|
6750
|
-
|
|
7655
|
+
// src/agent/workflow-tool-wrapper.ts
|
|
7656
|
+
function createWorkflowToolWrapper(options = {}) {
|
|
7657
|
+
const {
|
|
7658
|
+
maxRetries = 3,
|
|
7659
|
+
enableTelemetry = true,
|
|
7660
|
+
timeoutMs = 6e4,
|
|
7661
|
+
backoffMs = 1e3
|
|
7662
|
+
} = options;
|
|
7663
|
+
const telemetry = [];
|
|
7664
|
+
return {
|
|
7665
|
+
wrap: (tool14) => {
|
|
7666
|
+
return {
|
|
7667
|
+
...tool14,
|
|
7668
|
+
invoke: async (...args) => {
|
|
7669
|
+
const startTime = Date.now();
|
|
7670
|
+
let retries = 0;
|
|
7671
|
+
let lastError;
|
|
7672
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
7673
|
+
try {
|
|
7674
|
+
if (Date.now() - startTime > timeoutMs) {
|
|
7675
|
+
throw new Error(`Tool ${tool14.name} exceeded timeout of ${timeoutMs}ms`);
|
|
7676
|
+
}
|
|
7677
|
+
const result = await tool14.invoke(...args);
|
|
7678
|
+
if (enableTelemetry) {
|
|
7679
|
+
telemetry.push({
|
|
7680
|
+
toolName: tool14.name,
|
|
7681
|
+
durationMs: Date.now() - startTime,
|
|
7682
|
+
retries,
|
|
7683
|
+
success: true
|
|
7684
|
+
});
|
|
7685
|
+
}
|
|
7686
|
+
return result;
|
|
7687
|
+
} catch (error) {
|
|
7688
|
+
lastError = error;
|
|
7689
|
+
const errorMsg = lastError.message?.toLowerCase() || "";
|
|
7690
|
+
const isValidationError = errorMsg.includes("expected object, received string") || errorMsg.includes("expected array, received") || errorMsg.includes("required") || errorMsg.includes("invalid") || errorMsg.includes("validation");
|
|
7691
|
+
if (isValidationError) {
|
|
7692
|
+
console.log(`[Workflow] ${tool14.name} validation error (not retryable): ${lastError.message}`);
|
|
7693
|
+
if (enableTelemetry) {
|
|
7694
|
+
telemetry.push({
|
|
7695
|
+
toolName: tool14.name,
|
|
7696
|
+
durationMs: Date.now() - startTime,
|
|
7697
|
+
retries: 0,
|
|
7698
|
+
success: false,
|
|
7699
|
+
error: lastError.message
|
|
7700
|
+
});
|
|
7701
|
+
}
|
|
7702
|
+
return {
|
|
7703
|
+
error: lastError.message,
|
|
7704
|
+
status: "error",
|
|
7705
|
+
toolName: tool14.name,
|
|
7706
|
+
suggestion: "Check the tool input format and try again with corrected parameters"
|
|
7707
|
+
};
|
|
7708
|
+
}
|
|
7709
|
+
if (attempt < maxRetries) {
|
|
7710
|
+
retries++;
|
|
7711
|
+
const waitMs = backoffMs * Math.pow(2, attempt);
|
|
7712
|
+
console.log(`[Workflow Retry] ${tool14.name} attempt ${retries}/${maxRetries}, waiting ${waitMs}ms...`);
|
|
7713
|
+
await new Promise((resolve2) => setTimeout(resolve2, waitMs));
|
|
7714
|
+
}
|
|
7715
|
+
}
|
|
7716
|
+
}
|
|
7717
|
+
if (enableTelemetry) {
|
|
7718
|
+
telemetry.push({
|
|
7719
|
+
toolName: tool14.name,
|
|
7720
|
+
durationMs: Date.now() - startTime,
|
|
7721
|
+
retries,
|
|
7722
|
+
success: false,
|
|
7723
|
+
error: lastError?.message
|
|
7724
|
+
});
|
|
7725
|
+
}
|
|
7726
|
+
return {
|
|
7727
|
+
error: lastError?.message || "Tool execution failed after retries",
|
|
7728
|
+
status: "error",
|
|
7729
|
+
toolName: tool14.name,
|
|
7730
|
+
retries
|
|
7731
|
+
};
|
|
7732
|
+
}
|
|
7733
|
+
};
|
|
7734
|
+
},
|
|
7735
|
+
getTelemetry: () => [...telemetry],
|
|
7736
|
+
resetTelemetry: () => {
|
|
7737
|
+
telemetry.length = 0;
|
|
7738
|
+
}
|
|
7739
|
+
};
|
|
7740
|
+
}
|
|
7741
|
+
function createEvalWorkflowWrapper(options = {}) {
|
|
7742
|
+
const wrapper = createWorkflowToolWrapper(options);
|
|
7743
|
+
return {
|
|
7744
|
+
...wrapper,
|
|
7745
|
+
wrap: (tool14) => {
|
|
7746
|
+
const wrapped = wrapper.wrap(tool14);
|
|
7747
|
+
const originalInvoke = wrapped.invoke;
|
|
7748
|
+
wrapped.invoke = async (...args) => {
|
|
7749
|
+
console.log(`[Workflow] Starting ${tool14.name}...`);
|
|
7750
|
+
try {
|
|
7751
|
+
const result = await originalInvoke(...args);
|
|
7752
|
+
const allMetrics = wrapper.getTelemetry();
|
|
7753
|
+
const metrics = allMetrics[allMetrics.length - 1];
|
|
7754
|
+
console.log(`[Workflow] ${tool14.name} completed (${metrics?.durationMs}ms, ${metrics?.retries} retries)`);
|
|
7755
|
+
return result;
|
|
7756
|
+
} catch (error) {
|
|
7757
|
+
const allMetrics = wrapper.getTelemetry();
|
|
7758
|
+
const metrics = allMetrics[allMetrics.length - 1];
|
|
7759
|
+
console.log(`[Workflow] ${tool14.name} failed after ${metrics?.retries} retries`);
|
|
7760
|
+
throw error;
|
|
7761
|
+
}
|
|
7762
|
+
};
|
|
7763
|
+
return wrapped;
|
|
7764
|
+
}
|
|
7765
|
+
};
|
|
7766
|
+
}
|
|
7767
|
+
|
|
7768
|
+
export { EVENT_BUDGETS, HITLWorkflowEngine, HITLv2Manager, MemoryIntegrationEngine, ReActEngine, ReActWorkflowEngine, ReActWorkflowExecutor, SessionManager, createEvalWorkflowWrapper, createHITLWorkflowEngine, createHITLv2Manager, createMemoryIntegration, createMultiStageApprovalWorkflow, createReActEngine, createReActWorkflowEngine, createReActWorkflowExecutor, createSchemaGenerationHITLWorkflow, createSkillAgent, createWorkflowToolWrapper, getBudgetWarningMessage, getEventBudget, getInterruptConfig, resumeSkillAgent };
|
|
6751
7769
|
//# sourceMappingURL=index.js.map
|
|
6752
7770
|
//# sourceMappingURL=index.js.map
|