@almadar/agent 1.3.2 → 1.6.0
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 +8 -5
package/dist/tools/index.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { AgentDomainCategorySchema, isOrbitalDefinition, isEntityReference, getTraitName } from '@almadar/core/types';
|
|
2
2
|
import { tool } from '@langchain/core/tools';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { exec, spawn } from 'child_process';
|
|
4
|
+
import { exec, spawn, execSync } from 'child_process';
|
|
5
5
|
import * as path from 'path';
|
|
6
|
+
import path__default from 'path';
|
|
6
7
|
import { promisify } from 'util';
|
|
7
8
|
import * as fs4 from 'fs/promises';
|
|
8
9
|
import { isStructuredOutputAvailable, getStructuredOutputClient, LLMClient } from '@almadar/llm';
|
|
9
10
|
import * as domain_language_star from '@almadar/core/domain-language';
|
|
10
11
|
import * as fs3 from 'fs';
|
|
12
|
+
import fs3__default from 'fs';
|
|
11
13
|
import crypto, { randomUUID } from 'crypto';
|
|
12
|
-
import { getKeyBehaviorsReference, getSExprQuickRef, getCommonErrorsSection, getArchitectureSection,
|
|
14
|
+
import { getKeyBehaviorsReference, getSExprQuickRef, getCommonErrorsSection, getArchitectureSection, getSubagentSystemPrompt, getRequirementsTraitPrompt, getFullOrbitalPrompt } from '@almadar/skills';
|
|
15
|
+
import os from 'os';
|
|
13
16
|
import { GitHubIntegration } from '@almadar/integrations';
|
|
14
17
|
|
|
15
18
|
var __defProp = Object.defineProperty;
|
|
@@ -207,20 +210,40 @@ ${guidance}
|
|
|
207
210
|
|
|
208
211
|
${CACHE_BREAK}
|
|
209
212
|
|
|
210
|
-
## Current Orbital Unit
|
|
213
|
+
## Current Orbital Unit (INPUT)
|
|
211
214
|
Name: ${orbital.name}
|
|
212
215
|
Entity: ${entityName}
|
|
213
216
|
Persistence: ${persistence}
|
|
214
217
|
Fields: ${fieldNames}
|
|
215
218
|
Traits: ${orbital.traits.map(getTraitName).join(", ")}
|
|
216
219
|
${contextSection}
|
|
217
|
-
|
|
220
|
+
|
|
221
|
+
## Required Output Structure
|
|
222
|
+
Generate a complete FullOrbitalUnit with this EXACT structure:
|
|
223
|
+
|
|
224
|
+
\`\`\`json
|
|
225
|
+
{
|
|
226
|
+
"name": "${orbital.name}",
|
|
227
|
+
"entity": { // \u2190 REQUIRED FIELD
|
|
228
|
+
"name": "${entityName}",
|
|
229
|
+
"collection": "${entityName.toLowerCase()}s",
|
|
230
|
+
"persistence": "${persistence}",
|
|
231
|
+
"fields": [ ... ]
|
|
232
|
+
},
|
|
233
|
+
"traits": [ ... ],
|
|
234
|
+
"pages": [ ... ]
|
|
235
|
+
}
|
|
236
|
+
\`\`\`
|
|
237
|
+
|
|
238
|
+
**CRITICAL:** The "entity" field is REQUIRED at the orbital level. Do NOT omit it.
|
|
239
|
+
|
|
240
|
+
Additional requirements:
|
|
218
241
|
- Full field definitions with types and validation
|
|
219
242
|
- Trait state machines with transitions and effects
|
|
220
243
|
- Business rule validation using "guard" (singular, NOT "guards") S-expression on SAVE transitions
|
|
221
244
|
- Pages with trait references
|
|
222
245
|
- domainContext with category, vocabulary, and requestFragment
|
|
223
|
-
- design with style and uxHints
|
|
246
|
+
- design with style and uxHints
|
|
224
247
|
`;
|
|
225
248
|
return {
|
|
226
249
|
prompt,
|
|
@@ -260,7 +283,7 @@ ${guidance}`,
|
|
|
260
283
|
const userBlocks = [
|
|
261
284
|
{
|
|
262
285
|
type: "text",
|
|
263
|
-
text: `## Current Orbital Unit
|
|
286
|
+
text: `## Current Orbital Unit (INPUT)
|
|
264
287
|
Name: ${orbital.name}
|
|
265
288
|
Entity: ${entityName}
|
|
266
289
|
Persistence: ${persistence}
|
|
@@ -268,7 +291,40 @@ Fields: ${fieldNames}
|
|
|
268
291
|
Traits: ${orbital.traits.map(getTraitName).join(", ")}
|
|
269
292
|
${contextSection}${connectivitySection ? `
|
|
270
293
|
${connectivitySection}` : ""}
|
|
271
|
-
|
|
294
|
+
|
|
295
|
+
## REQUIRED OUTPUT - VERIFICATION CHECKLIST
|
|
296
|
+
|
|
297
|
+
Before generating output, verify:
|
|
298
|
+
- [ ] "entity" field is present at the TOP LEVEL of the orbital object
|
|
299
|
+
- [ ] entity.name = "${entityName}"
|
|
300
|
+
- [ ] entity.collection = "${entityName.toLowerCase()}s"
|
|
301
|
+
- [ ] entity.persistence = "${persistence}"
|
|
302
|
+
- [ ] entity.fields array has at least ${inlineEntity?.fields.length || 1} field(s)
|
|
303
|
+
- [ ] Full orbital structure includes: name, entity, traits, pages, domainContext, design
|
|
304
|
+
|
|
305
|
+
## Output Structure (Generate This Exact JSON)
|
|
306
|
+
|
|
307
|
+
\`\`\`json
|
|
308
|
+
{
|
|
309
|
+
"name": "${orbital.name}",
|
|
310
|
+
"entity": { // \u2190 THIS FIELD IS MANDATORY
|
|
311
|
+
"name": "${entityName}",
|
|
312
|
+
"collection": "${entityName.toLowerCase()}s",
|
|
313
|
+
"persistence": "${persistence}",
|
|
314
|
+
"fields": [${inlineEntity?.fields.map((f) => `
|
|
315
|
+
{ "name": "${f.name}", "type": "${f.type}"${f.required ? ', "required": true' : ""} }`).join(",") || ""}
|
|
316
|
+
]
|
|
317
|
+
},
|
|
318
|
+
"traits": [ ... trait definitions with state machines ... ],
|
|
319
|
+
"pages": [ ... page definitions ... ],
|
|
320
|
+
"domainContext": { ... domain info ... },
|
|
321
|
+
"design": { ... styling info ... }
|
|
322
|
+
}
|
|
323
|
+
\`\`\`
|
|
324
|
+
|
|
325
|
+
**MANDATORY:** If the output does not have an "entity" field at the orbital level, it is INVALID.
|
|
326
|
+
|
|
327
|
+
Additional requirements:
|
|
272
328
|
- Full field definitions with types and validation
|
|
273
329
|
- Trait state machines with transitions and effects
|
|
274
330
|
- Business rule validation using "guard" (singular, NOT "guards") S-expression on SAVE transitions
|
|
@@ -303,6 +359,28 @@ var init_cache = __esm({
|
|
|
303
359
|
init_prompt_assembler();
|
|
304
360
|
}
|
|
305
361
|
});
|
|
362
|
+
|
|
363
|
+
// src/agent/interrupt-config.ts
|
|
364
|
+
var CRITICAL_COMMAND_PATTERNS = [
|
|
365
|
+
/\bpnpm\s+publish\b/,
|
|
366
|
+
/\bnpm\s+publish\b/,
|
|
367
|
+
/\bgit\s+push\b.*\bmain\b/,
|
|
368
|
+
/\bgit\s+push\b.*\bmaster\b/,
|
|
369
|
+
/\bgit\s+push\b.*--force\b/,
|
|
370
|
+
/\brm\s+-rf\b/,
|
|
371
|
+
/\brmdir\b/,
|
|
372
|
+
/firebase\s+deploy/,
|
|
373
|
+
/gcloud\s+.*deploy/,
|
|
374
|
+
/\.env\b/
|
|
375
|
+
];
|
|
376
|
+
function classifyCommand(command) {
|
|
377
|
+
for (const pattern of CRITICAL_COMMAND_PATTERNS) {
|
|
378
|
+
if (pattern.test(command)) return "critical";
|
|
379
|
+
}
|
|
380
|
+
return "sensitive";
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// src/tools/execute.ts
|
|
306
384
|
var DANGEROUS_COMMANDS = [
|
|
307
385
|
"rm",
|
|
308
386
|
"rmdir",
|
|
@@ -419,14 +497,26 @@ function validateCommandPaths(command, workDir) {
|
|
|
419
497
|
}
|
|
420
498
|
return null;
|
|
421
499
|
}
|
|
422
|
-
function createExecuteTool(workDir) {
|
|
500
|
+
function createExecuteTool(workDir, auditLog) {
|
|
423
501
|
const normalizedWorkDir = path.resolve(workDir);
|
|
424
502
|
return tool(
|
|
425
503
|
async ({ command, timeout = 6e4 }) => {
|
|
426
504
|
const validationError = validateCommandPaths(command, workDir);
|
|
427
505
|
if (validationError) {
|
|
506
|
+
auditLog?.append({
|
|
507
|
+
event: "EXECUTE_BLOCKED",
|
|
508
|
+
command,
|
|
509
|
+
reason: validationError,
|
|
510
|
+
gate: classifyCommand(command)
|
|
511
|
+
});
|
|
428
512
|
return validationError;
|
|
429
513
|
}
|
|
514
|
+
auditLog?.append({
|
|
515
|
+
event: "EXECUTE_START",
|
|
516
|
+
command,
|
|
517
|
+
gate: classifyCommand(command),
|
|
518
|
+
workDir: normalizedWorkDir
|
|
519
|
+
});
|
|
430
520
|
return new Promise((resolve2) => {
|
|
431
521
|
const parts = command.split(" ");
|
|
432
522
|
const cmd = parts[0];
|
|
@@ -469,6 +559,13 @@ function createExecuteTool(workDir) {
|
|
|
469
559
|
|
|
470
560
|
Stderr:
|
|
471
561
|
${stderr}` : "");
|
|
562
|
+
auditLog?.append({
|
|
563
|
+
event: "EXECUTE_COMPLETE",
|
|
564
|
+
command,
|
|
565
|
+
exitCode: code,
|
|
566
|
+
outputLength: output.length,
|
|
567
|
+
success: code === 0
|
|
568
|
+
});
|
|
472
569
|
if (code === 0) {
|
|
473
570
|
resolve2(output || "Command completed successfully (no output)");
|
|
474
571
|
} else {
|
|
@@ -1918,7 +2015,8 @@ async function generateFullOrbital(client, orbital, options = {}) {
|
|
|
1918
2015
|
traitCount: orbital.traits.length,
|
|
1919
2016
|
hasRequirements: !!requirements
|
|
1920
2017
|
}));
|
|
1921
|
-
const
|
|
2018
|
+
const basePrompt = getSubagentSystemPrompt();
|
|
2019
|
+
const systemPrompt = requirements ? getRequirementsAwareFullOrbitalPrompt(requirements, basePrompt) : basePrompt;
|
|
1922
2020
|
const useCache = client.getProvider() === "anthropic";
|
|
1923
2021
|
let result;
|
|
1924
2022
|
let fingerprint;
|
|
@@ -1989,8 +2087,7 @@ Return valid JSON matching the FullOrbitalUnit schema.`;
|
|
|
1989
2087
|
logs
|
|
1990
2088
|
};
|
|
1991
2089
|
}
|
|
1992
|
-
function getRequirementsAwareFullOrbitalPrompt(requirements) {
|
|
1993
|
-
const basePrompt = getFullOrbitalPrompt();
|
|
2090
|
+
function getRequirementsAwareFullOrbitalPrompt(requirements, basePrompt = getSubagentSystemPrompt()) {
|
|
1994
2091
|
const requirementsGuidance = getRequirementsTraitPrompt();
|
|
1995
2092
|
const sections = [];
|
|
1996
2093
|
if (requirements.guards && requirements.guards.length > 0) {
|
|
@@ -3302,27 +3399,27 @@ var CombineSchemaInputSchema = z.object({
|
|
|
3302
3399
|
validate: z.boolean().optional().default(true)
|
|
3303
3400
|
});
|
|
3304
3401
|
async function autoCollectOrbitals(workDir) {
|
|
3305
|
-
const
|
|
3306
|
-
const
|
|
3307
|
-
const orbitalsDir =
|
|
3308
|
-
if (!
|
|
3309
|
-
const files2 =
|
|
3402
|
+
const fs7 = await import('fs');
|
|
3403
|
+
const path8 = await import('path');
|
|
3404
|
+
const orbitalsDir = path8.join(workDir, ".orbitals");
|
|
3405
|
+
if (!fs7.existsSync(orbitalsDir)) {
|
|
3406
|
+
const files2 = fs7.readdirSync(workDir).filter(
|
|
3310
3407
|
(f) => f.endsWith(".json") && (f.startsWith("orbital-") || f.includes("orbital"))
|
|
3311
3408
|
);
|
|
3312
3409
|
if (files2.length === 0) {
|
|
3313
3410
|
throw new Error("No orbitals found. Generate orbitals first using generate_orbital, or provide them directly.");
|
|
3314
3411
|
}
|
|
3315
3412
|
return files2.map((f) => {
|
|
3316
|
-
const content =
|
|
3413
|
+
const content = fs7.readFileSync(path8.join(workDir, f), "utf-8");
|
|
3317
3414
|
return JSON.parse(content);
|
|
3318
3415
|
});
|
|
3319
3416
|
}
|
|
3320
|
-
const files =
|
|
3417
|
+
const files = fs7.readdirSync(orbitalsDir).filter((f) => f.endsWith(".json"));
|
|
3321
3418
|
if (files.length === 0) {
|
|
3322
3419
|
throw new Error("No orbitals found in .orbitals/ directory.");
|
|
3323
3420
|
}
|
|
3324
3421
|
return files.map((f) => {
|
|
3325
|
-
const content =
|
|
3422
|
+
const content = fs7.readFileSync(path8.join(orbitalsDir, f), "utf-8");
|
|
3326
3423
|
return JSON.parse(content);
|
|
3327
3424
|
});
|
|
3328
3425
|
}
|
|
@@ -3644,6 +3741,865 @@ function createSchemaChunkingTools(workDir) {
|
|
|
3644
3741
|
applyChunk: createApplyChunkTool(workDir)
|
|
3645
3742
|
};
|
|
3646
3743
|
}
|
|
3744
|
+
|
|
3745
|
+
// src/orchestration/complexity-classifier.ts
|
|
3746
|
+
function classifyComplexity(orbitalCount) {
|
|
3747
|
+
if (orbitalCount <= 0) {
|
|
3748
|
+
throw new Error(`Invalid orbital count: ${orbitalCount}`);
|
|
3749
|
+
}
|
|
3750
|
+
if (orbitalCount === 1) {
|
|
3751
|
+
return {
|
|
3752
|
+
level: "simple",
|
|
3753
|
+
orbitalCount,
|
|
3754
|
+
recommendedProvider: "qwen",
|
|
3755
|
+
reasoning: "Single orbital - Qwen 397B is fast and cost-effective"
|
|
3756
|
+
};
|
|
3757
|
+
}
|
|
3758
|
+
if (orbitalCount <= 3) {
|
|
3759
|
+
return {
|
|
3760
|
+
level: "medium",
|
|
3761
|
+
orbitalCount,
|
|
3762
|
+
recommendedProvider: "qwen",
|
|
3763
|
+
reasoning: "2-3 orbitals - Qwen 397B handles well with good speed/cost"
|
|
3764
|
+
};
|
|
3765
|
+
}
|
|
3766
|
+
return {
|
|
3767
|
+
level: "complex",
|
|
3768
|
+
orbitalCount,
|
|
3769
|
+
recommendedProvider: "multi-provider",
|
|
3770
|
+
reasoning: "4+ orbitals - Multi-provider parallel for optimal speed"
|
|
3771
|
+
};
|
|
3772
|
+
}
|
|
3773
|
+
function estimateComplexity(prompt) {
|
|
3774
|
+
const lowerPrompt = prompt.toLowerCase();
|
|
3775
|
+
const entityPatterns = [
|
|
3776
|
+
/entity[:s]/g,
|
|
3777
|
+
/entities:/g,
|
|
3778
|
+
/- \w+:/g,
|
|
3779
|
+
// List items like "- Task:"
|
|
3780
|
+
/model[s]?:/g,
|
|
3781
|
+
/table[s]?:/g
|
|
3782
|
+
];
|
|
3783
|
+
let entityMatches = 0;
|
|
3784
|
+
for (const pattern of entityPatterns) {
|
|
3785
|
+
const matches = lowerPrompt.match(pattern);
|
|
3786
|
+
if (matches) {
|
|
3787
|
+
entityMatches += matches.length;
|
|
3788
|
+
}
|
|
3789
|
+
}
|
|
3790
|
+
const featureIndicators = [
|
|
3791
|
+
"dashboard",
|
|
3792
|
+
"workflow",
|
|
3793
|
+
"admin",
|
|
3794
|
+
"portal",
|
|
3795
|
+
"system",
|
|
3796
|
+
"management",
|
|
3797
|
+
"booking",
|
|
3798
|
+
"appointment",
|
|
3799
|
+
"inventory",
|
|
3800
|
+
"e-commerce",
|
|
3801
|
+
"healthcare",
|
|
3802
|
+
"patient",
|
|
3803
|
+
"doctor"
|
|
3804
|
+
];
|
|
3805
|
+
let featureMatches = 0;
|
|
3806
|
+
for (const indicator of featureIndicators) {
|
|
3807
|
+
if (lowerPrompt.includes(indicator)) {
|
|
3808
|
+
featureMatches++;
|
|
3809
|
+
}
|
|
3810
|
+
}
|
|
3811
|
+
const lengthScore = prompt.length > 500 ? 2 : prompt.length > 200 ? 1 : 0;
|
|
3812
|
+
const score = entityMatches + featureMatches + lengthScore;
|
|
3813
|
+
if (score <= 2) {
|
|
3814
|
+
return { estimatedLevel: "simple", confidence: score === 0 ? "low" : "medium" };
|
|
3815
|
+
}
|
|
3816
|
+
if (score <= 5) {
|
|
3817
|
+
return { estimatedLevel: "medium", confidence: "medium" };
|
|
3818
|
+
}
|
|
3819
|
+
return { estimatedLevel: "complex", confidence: "high" };
|
|
3820
|
+
}
|
|
3821
|
+
function getExecutionStrategy(complexity) {
|
|
3822
|
+
switch (complexity.level) {
|
|
3823
|
+
case "simple":
|
|
3824
|
+
case "medium":
|
|
3825
|
+
return {
|
|
3826
|
+
type: "single",
|
|
3827
|
+
provider: "openrouter",
|
|
3828
|
+
model: "qwen/qwen3.5-397b-a17b",
|
|
3829
|
+
parallelization: 1
|
|
3830
|
+
};
|
|
3831
|
+
case "complex":
|
|
3832
|
+
return {
|
|
3833
|
+
type: "multi-provider",
|
|
3834
|
+
provider: "mixed",
|
|
3835
|
+
model: "deepseek-chat + qwen/qwen3.5-397b-a17b",
|
|
3836
|
+
parallelization: 2
|
|
3837
|
+
};
|
|
3838
|
+
}
|
|
3839
|
+
}
|
|
3840
|
+
function buildOrbitalDefinition(unit) {
|
|
3841
|
+
const traits = unit.traits.map((t) => ({
|
|
3842
|
+
name: t,
|
|
3843
|
+
category: "interaction",
|
|
3844
|
+
linkedEntity: unit.entity,
|
|
3845
|
+
stateMachine: {
|
|
3846
|
+
states: [{ name: "Browsing", isInitial: true }],
|
|
3847
|
+
events: [{ key: "INIT", name: "Initialize" }],
|
|
3848
|
+
transitions: []
|
|
3849
|
+
}
|
|
3850
|
+
}));
|
|
3851
|
+
const pages = [
|
|
3852
|
+
{
|
|
3853
|
+
name: `${unit.name}Page`,
|
|
3854
|
+
path: `/${unit.entity.toLowerCase()}s`,
|
|
3855
|
+
traits: traits.map((t) => ({ ref: t.name }))
|
|
3856
|
+
}
|
|
3857
|
+
];
|
|
3858
|
+
return {
|
|
3859
|
+
name: unit.name,
|
|
3860
|
+
entity: {
|
|
3861
|
+
name: unit.entity,
|
|
3862
|
+
collection: `${unit.entity.toLowerCase()}s`,
|
|
3863
|
+
fields: [{ name: "id", type: "string", required: true }]
|
|
3864
|
+
},
|
|
3865
|
+
traits,
|
|
3866
|
+
pages
|
|
3867
|
+
};
|
|
3868
|
+
}
|
|
3869
|
+
function normalizeDecomposedUnit(unit) {
|
|
3870
|
+
const u = unit;
|
|
3871
|
+
let entityName;
|
|
3872
|
+
if (typeof u.entity === "string") {
|
|
3873
|
+
entityName = u.entity;
|
|
3874
|
+
} else if (u.entity && typeof u.entity === "object") {
|
|
3875
|
+
const entityObj = u.entity;
|
|
3876
|
+
entityName = typeof entityObj.name === "string" ? entityObj.name : "Unknown";
|
|
3877
|
+
} else {
|
|
3878
|
+
entityName = "Unknown";
|
|
3879
|
+
}
|
|
3880
|
+
let traitNames = [];
|
|
3881
|
+
if (Array.isArray(u.traits)) {
|
|
3882
|
+
traitNames = u.traits.map((t) => {
|
|
3883
|
+
if (typeof t === "string") return t;
|
|
3884
|
+
if (t && typeof t === "object") {
|
|
3885
|
+
const to = t;
|
|
3886
|
+
return typeof to.name === "string" ? to.name : String(t);
|
|
3887
|
+
}
|
|
3888
|
+
return String(t);
|
|
3889
|
+
});
|
|
3890
|
+
}
|
|
3891
|
+
return {
|
|
3892
|
+
name: typeof u.name === "string" ? u.name : "Unnamed",
|
|
3893
|
+
entity: entityName,
|
|
3894
|
+
traits: traitNames
|
|
3895
|
+
};
|
|
3896
|
+
}
|
|
3897
|
+
async function decomposeRequest(prompt, skillContent, _config) {
|
|
3898
|
+
const client = new LLMClient({
|
|
3899
|
+
provider: "anthropic",
|
|
3900
|
+
model: "claude-sonnet-4-20250514"
|
|
3901
|
+
});
|
|
3902
|
+
const systemPrompt = `${skillContent}
|
|
3903
|
+
|
|
3904
|
+
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).`;
|
|
3905
|
+
const userPrompt = `Decompose this request into orbital units:
|
|
3906
|
+
|
|
3907
|
+
${prompt}
|
|
3908
|
+
|
|
3909
|
+
Return ONLY a JSON array. Each object must have:
|
|
3910
|
+
- name: orbital name (e.g., "Task Management")
|
|
3911
|
+
- entity: entity name as a STRING (e.g., "Task")
|
|
3912
|
+
- traits: array of trait names as strings (e.g., ["TaskInteraction"])`;
|
|
3913
|
+
const result = await client.call({
|
|
3914
|
+
systemPrompt,
|
|
3915
|
+
userPrompt,
|
|
3916
|
+
maxTokens: 4096,
|
|
3917
|
+
skipSchemaValidation: true
|
|
3918
|
+
});
|
|
3919
|
+
const rawUnits = Array.isArray(result) ? result : [result];
|
|
3920
|
+
return rawUnits.map(normalizeDecomposedUnit);
|
|
3921
|
+
}
|
|
3922
|
+
async function generateWithSingleProvider(units, config) {
|
|
3923
|
+
const client = new LLMClient({
|
|
3924
|
+
provider: "openrouter",
|
|
3925
|
+
model: "qwen/qwen3.5-397b-a17b"
|
|
3926
|
+
});
|
|
3927
|
+
if (config.verbose !== false) {
|
|
3928
|
+
console.log(`[Router] Using single provider (Qwen) for ${units.length} orbitals`);
|
|
3929
|
+
}
|
|
3930
|
+
const orbitals = [];
|
|
3931
|
+
for (const unit of units) {
|
|
3932
|
+
if (config.verbose !== false) {
|
|
3933
|
+
console.log(`[Router] Generating: ${unit.name}...`);
|
|
3934
|
+
}
|
|
3935
|
+
const startTime = Date.now();
|
|
3936
|
+
try {
|
|
3937
|
+
const orbitalDef = buildOrbitalDefinition(unit);
|
|
3938
|
+
const result = await generateFullOrbital(client, orbitalDef, {
|
|
3939
|
+
requirements: { entities: [unit.entity] },
|
|
3940
|
+
maxTokens: 8192
|
|
3941
|
+
});
|
|
3942
|
+
if (config.verbose !== false) {
|
|
3943
|
+
console.log(`[Router] \u2705 ${unit.name}: ${((Date.now() - startTime) / 1e3).toFixed(1)}s`);
|
|
3944
|
+
}
|
|
3945
|
+
orbitals.push(result.orbital);
|
|
3946
|
+
} catch (error) {
|
|
3947
|
+
if (config.verbose !== false) {
|
|
3948
|
+
console.log(`[Router] \u274C ${unit.name}: Failed - ${error instanceof Error ? error.message.slice(0, 50) : "Unknown"}`);
|
|
3949
|
+
}
|
|
3950
|
+
}
|
|
3951
|
+
}
|
|
3952
|
+
return orbitals;
|
|
3953
|
+
}
|
|
3954
|
+
async function generateWithMultiProvider(units, config) {
|
|
3955
|
+
if (config.verbose !== false) {
|
|
3956
|
+
console.log(`[Router] Using multi-provider parallel for ${units.length} orbitals`);
|
|
3957
|
+
}
|
|
3958
|
+
const midpoint = Math.ceil(units.length / 2);
|
|
3959
|
+
const deepseekUnits = units.slice(0, midpoint);
|
|
3960
|
+
const qwenUnits = units.slice(midpoint);
|
|
3961
|
+
if (config.verbose !== false) {
|
|
3962
|
+
console.log(`[Router] Split: ${deepseekUnits.length} to DeepSeek, ${qwenUnits.length} to Qwen`);
|
|
3963
|
+
}
|
|
3964
|
+
const deepseekClient = new LLMClient({
|
|
3965
|
+
provider: "deepseek",
|
|
3966
|
+
model: "deepseek-chat"
|
|
3967
|
+
});
|
|
3968
|
+
const qwenClient = new LLMClient({
|
|
3969
|
+
provider: "openrouter",
|
|
3970
|
+
model: "qwen/qwen3.5-397b-a17b"
|
|
3971
|
+
});
|
|
3972
|
+
const [deepseekResults, qwenResults] = await Promise.all([
|
|
3973
|
+
Promise.all(
|
|
3974
|
+
deepseekUnits.map(async (unit) => {
|
|
3975
|
+
if (config.verbose !== false) {
|
|
3976
|
+
console.log(`[Router] [DeepSeek] Generating: ${unit.name}...`);
|
|
3977
|
+
}
|
|
3978
|
+
const startTime = Date.now();
|
|
3979
|
+
try {
|
|
3980
|
+
const orbitalDef = buildOrbitalDefinition(unit);
|
|
3981
|
+
const result = await generateFullOrbital(deepseekClient, orbitalDef, {
|
|
3982
|
+
requirements: { entities: [unit.entity] },
|
|
3983
|
+
maxTokens: 8192
|
|
3984
|
+
});
|
|
3985
|
+
if (config.verbose !== false) {
|
|
3986
|
+
console.log(`[Router] [DeepSeek] \u2705 ${unit.name}: ${((Date.now() - startTime) / 1e3).toFixed(1)}s`);
|
|
3987
|
+
}
|
|
3988
|
+
return result.orbital;
|
|
3989
|
+
} catch (error) {
|
|
3990
|
+
if (config.verbose !== false) {
|
|
3991
|
+
console.log(`[Router] [DeepSeek] \u274C ${unit.name}: Failed`);
|
|
3992
|
+
}
|
|
3993
|
+
return null;
|
|
3994
|
+
}
|
|
3995
|
+
})
|
|
3996
|
+
),
|
|
3997
|
+
Promise.all(
|
|
3998
|
+
qwenUnits.map(async (unit) => {
|
|
3999
|
+
if (config.verbose !== false) {
|
|
4000
|
+
console.log(`[Router] [Qwen] Generating: ${unit.name}...`);
|
|
4001
|
+
}
|
|
4002
|
+
const startTime = Date.now();
|
|
4003
|
+
try {
|
|
4004
|
+
const orbitalDef = buildOrbitalDefinition(unit);
|
|
4005
|
+
const result = await generateFullOrbital(qwenClient, orbitalDef, {
|
|
4006
|
+
requirements: { entities: [unit.entity] },
|
|
4007
|
+
maxTokens: 8192
|
|
4008
|
+
});
|
|
4009
|
+
if (config.verbose !== false) {
|
|
4010
|
+
console.log(`[Router] [Qwen] \u2705 ${unit.name}: ${((Date.now() - startTime) / 1e3).toFixed(1)}s`);
|
|
4011
|
+
}
|
|
4012
|
+
return result.orbital;
|
|
4013
|
+
} catch (error) {
|
|
4014
|
+
if (config.verbose !== false) {
|
|
4015
|
+
console.log(`[Router] [Qwen] \u274C ${unit.name}: Failed`);
|
|
4016
|
+
}
|
|
4017
|
+
return null;
|
|
4018
|
+
}
|
|
4019
|
+
})
|
|
4020
|
+
)
|
|
4021
|
+
]);
|
|
4022
|
+
return [...deepseekResults, ...qwenResults].filter((o) => o !== null);
|
|
4023
|
+
}
|
|
4024
|
+
async function routeGeneration(prompt, skillContent, config = {}) {
|
|
4025
|
+
const totalStart = Date.now();
|
|
4026
|
+
if (config.verbose !== false) {
|
|
4027
|
+
console.log("[Router] Step 1: Decomposing request...");
|
|
4028
|
+
}
|
|
4029
|
+
const decomposeStart = Date.now();
|
|
4030
|
+
const units = await decomposeRequest(prompt, skillContent);
|
|
4031
|
+
const decomposeMs = Date.now() - decomposeStart;
|
|
4032
|
+
if (config.verbose !== false) {
|
|
4033
|
+
console.log(`[Router] \u2705 Decomposed into ${units.length} orbitals (${(decomposeMs / 1e3).toFixed(1)}s)`);
|
|
4034
|
+
}
|
|
4035
|
+
const complexity = classifyComplexity(units.length);
|
|
4036
|
+
const strategy = getExecutionStrategy(complexity);
|
|
4037
|
+
if (config.verbose !== false) {
|
|
4038
|
+
console.log(`[Router] Complexity: ${complexity.level} (${units.length} orbitals)`);
|
|
4039
|
+
console.log(`[Router] Strategy: ${strategy.type} (${strategy.provider})`);
|
|
4040
|
+
}
|
|
4041
|
+
const generateStart = Date.now();
|
|
4042
|
+
let orbitals;
|
|
4043
|
+
if (complexity.level === "complex") {
|
|
4044
|
+
orbitals = await generateWithMultiProvider(units, config);
|
|
4045
|
+
} else {
|
|
4046
|
+
orbitals = await generateWithSingleProvider(units, config);
|
|
4047
|
+
}
|
|
4048
|
+
const generateMs = Date.now() - generateStart;
|
|
4049
|
+
const totalMs = Date.now() - totalStart;
|
|
4050
|
+
if (config.verbose !== false) {
|
|
4051
|
+
console.log(`[Router] \u2705 Generated ${orbitals.length}/${units.length} orbitals`);
|
|
4052
|
+
console.log(`[Router] Total time: ${(totalMs / 1e3).toFixed(1)}s`);
|
|
4053
|
+
}
|
|
4054
|
+
return {
|
|
4055
|
+
orbitals,
|
|
4056
|
+
complexity,
|
|
4057
|
+
timing: {
|
|
4058
|
+
decomposeMs,
|
|
4059
|
+
generateMs,
|
|
4060
|
+
totalMs
|
|
4061
|
+
},
|
|
4062
|
+
provider: strategy.provider
|
|
4063
|
+
};
|
|
4064
|
+
}
|
|
4065
|
+
function quickComplexityCheck(prompt) {
|
|
4066
|
+
const estimate = estimateComplexity(prompt);
|
|
4067
|
+
const estimatedCounts = {
|
|
4068
|
+
simple: 1,
|
|
4069
|
+
medium: 2,
|
|
4070
|
+
complex: 6
|
|
4071
|
+
};
|
|
4072
|
+
return {
|
|
4073
|
+
likelyComplex: estimate.estimatedLevel === "complex",
|
|
4074
|
+
confidence: estimate.confidence,
|
|
4075
|
+
estimatedOrbitals: estimatedCounts[estimate.estimatedLevel]
|
|
4076
|
+
};
|
|
4077
|
+
}
|
|
4078
|
+
async function createFixPlan(schema, errors, config) {
|
|
4079
|
+
const planStart = Date.now();
|
|
4080
|
+
const criticalErrors = errors.filter(
|
|
4081
|
+
(e) => e.code?.includes("ENTITY") || e.code?.includes("REQUIRED") || e.code?.includes("JSON")
|
|
4082
|
+
);
|
|
4083
|
+
const warningErrors = errors.filter((e) => !criticalErrors.includes(e));
|
|
4084
|
+
const orbitalErrors = /* @__PURE__ */ new Map();
|
|
4085
|
+
errors.forEach((error, index) => {
|
|
4086
|
+
let pathStr;
|
|
4087
|
+
if (Array.isArray(error.path)) {
|
|
4088
|
+
pathStr = error.path.join(".");
|
|
4089
|
+
} else if (typeof error.path === "string") {
|
|
4090
|
+
pathStr = error.path;
|
|
4091
|
+
} else {
|
|
4092
|
+
pathStr = String(error.path || "");
|
|
4093
|
+
}
|
|
4094
|
+
const match = pathStr.match(/orbitals\[(\d+)\]/);
|
|
4095
|
+
const orbitalIndex = match ? parseInt(match[1], 10) : -1;
|
|
4096
|
+
if (orbitalIndex >= 0) {
|
|
4097
|
+
if (!orbitalErrors.has(orbitalIndex)) {
|
|
4098
|
+
orbitalErrors.set(orbitalIndex, []);
|
|
4099
|
+
}
|
|
4100
|
+
orbitalErrors.get(orbitalIndex).push(index);
|
|
4101
|
+
}
|
|
4102
|
+
});
|
|
4103
|
+
const executionOrder = [];
|
|
4104
|
+
const affectedOrbitals = [];
|
|
4105
|
+
for (const [orbitalIndex, errorIndices] of orbitalErrors) {
|
|
4106
|
+
const orbital = schema.orbitals[orbitalIndex];
|
|
4107
|
+
if (orbital) {
|
|
4108
|
+
affectedOrbitals.push(orbital.name);
|
|
4109
|
+
const midPoint = Math.ceil(errorIndices.length / 2);
|
|
4110
|
+
const batches = [
|
|
4111
|
+
errorIndices.slice(0, midPoint),
|
|
4112
|
+
errorIndices.slice(midPoint)
|
|
4113
|
+
].filter((b) => b.length > 0);
|
|
4114
|
+
batches.forEach((batch, batchIndex) => {
|
|
4115
|
+
executionOrder.push({
|
|
4116
|
+
id: `fix-${orbitalIndex}-${batchIndex}`,
|
|
4117
|
+
description: `Fix ${batch.length} errors in ${orbital.name}`,
|
|
4118
|
+
orbitalIndex,
|
|
4119
|
+
errorIndices: batch,
|
|
4120
|
+
provider: batchIndex === 0 ? "deepseek" : "qwen",
|
|
4121
|
+
dependencies: []
|
|
4122
|
+
});
|
|
4123
|
+
});
|
|
4124
|
+
}
|
|
4125
|
+
}
|
|
4126
|
+
let parallelizationStrategy = "single";
|
|
4127
|
+
if (executionOrder.length >= 4) {
|
|
4128
|
+
parallelizationStrategy = "multi-provider";
|
|
4129
|
+
} else if (JSON.stringify(schema).length > 5e4) {
|
|
4130
|
+
parallelizationStrategy = "chunked";
|
|
4131
|
+
}
|
|
4132
|
+
const plan = {
|
|
4133
|
+
summary: {
|
|
4134
|
+
totalErrors: errors.length,
|
|
4135
|
+
criticalErrors: criticalErrors.length,
|
|
4136
|
+
warningErrors: warningErrors.length,
|
|
4137
|
+
affectedOrbitals: [...new Set(affectedOrbitals)]
|
|
4138
|
+
},
|
|
4139
|
+
executionOrder,
|
|
4140
|
+
parallelizationStrategy
|
|
4141
|
+
};
|
|
4142
|
+
if (config.verbose) {
|
|
4143
|
+
console.log(`[Fixing] Plan created in ${Date.now() - planStart}ms`);
|
|
4144
|
+
console.log(`[Fixing] Strategy: ${parallelizationStrategy}`);
|
|
4145
|
+
console.log(`[Fixing] Steps: ${executionOrder.length}`);
|
|
4146
|
+
}
|
|
4147
|
+
return plan;
|
|
4148
|
+
}
|
|
4149
|
+
async function executeFixStep(schema, step, errors, config) {
|
|
4150
|
+
const orbital = schema.orbitals[step.orbitalIndex];
|
|
4151
|
+
if (!orbital) {
|
|
4152
|
+
return { success: false, updatedOrbital: null };
|
|
4153
|
+
}
|
|
4154
|
+
const client = step.provider === "deepseek" ? new LLMClient({
|
|
4155
|
+
provider: "deepseek",
|
|
4156
|
+
model: "deepseek-chat"
|
|
4157
|
+
}) : new LLMClient({
|
|
4158
|
+
provider: "openrouter",
|
|
4159
|
+
model: "qwen/qwen3.5-397b-a17b"
|
|
4160
|
+
});
|
|
4161
|
+
const stepErrors = step.errorIndices.map((i) => errors[i]);
|
|
4162
|
+
const skillContent = config.skillContent || "";
|
|
4163
|
+
const hasBindingErrors = stepErrors.some(
|
|
4164
|
+
(e) => e.message?.toLowerCase().includes("binding") || e.code?.toLowerCase().includes("binding")
|
|
4165
|
+
);
|
|
4166
|
+
const bindingGuidance = hasBindingErrors ? `
|
|
4167
|
+
## BINDING ERROR FIXES
|
|
4168
|
+
|
|
4169
|
+
Common binding mistakes and fixes:
|
|
4170
|
+
|
|
4171
|
+
\u274C INVALID:
|
|
4172
|
+
- "@count" \u2192 missing entity reference
|
|
4173
|
+
- "@status" \u2192 missing entity reference
|
|
4174
|
+
- "@count:status=active" \u2192 wrong syntax
|
|
4175
|
+
|
|
4176
|
+
\u2705 VALID (from skill):
|
|
4177
|
+
- "@entity.count" - entity field reference
|
|
4178
|
+
- "@entity.status" - enum field reference
|
|
4179
|
+
- "@payload.data" - event payload data
|
|
4180
|
+
- "@state" - current state name
|
|
4181
|
+
- "@now" - current timestamp
|
|
4182
|
+
|
|
4183
|
+
Replace bare field names like "@count" with proper entity references like "@entity.count".
|
|
4184
|
+
` : "";
|
|
4185
|
+
const systemPrompt = `${skillContent}
|
|
4186
|
+
|
|
4187
|
+
${bindingGuidance}
|
|
4188
|
+
|
|
4189
|
+
## FIXING INSTRUCTIONS
|
|
4190
|
+
|
|
4191
|
+
You are fixing validation errors in an OrbitalSchema orbital.
|
|
4192
|
+
|
|
4193
|
+
Rules:
|
|
4194
|
+
1. Preserve ALL valid content - only fix the reported errors
|
|
4195
|
+
2. Return the COMPLETE orbital with entity, traits, and pages
|
|
4196
|
+
3. Ensure entity has: name, collection, and fields array
|
|
4197
|
+
4. Use valid binding formats: @entity.field, @payload.field, @state
|
|
4198
|
+
|
|
4199
|
+
Return ONLY the fixed orbital as valid JSON.`;
|
|
4200
|
+
const userPrompt = `Fix these validation errors in orbital "${orbital.name}":
|
|
4201
|
+
|
|
4202
|
+
ERRORS:
|
|
4203
|
+
${stepErrors.map((e) => {
|
|
4204
|
+
const path8 = Array.isArray(e.path) ? e.path.join(".") : e.path;
|
|
4205
|
+
return `- Path: ${path8}
|
|
4206
|
+
Code: ${e.code}
|
|
4207
|
+
Message: ${e.message}`;
|
|
4208
|
+
}).join("\n")}
|
|
4209
|
+
|
|
4210
|
+
CURRENT ORBITAL (JSON):
|
|
4211
|
+
${JSON.stringify(orbital, null, 2)}
|
|
4212
|
+
|
|
4213
|
+
Return the COMPLETE fixed orbital as JSON with all fields (entity, traits, pages).`;
|
|
4214
|
+
try {
|
|
4215
|
+
const result = await client.call({
|
|
4216
|
+
systemPrompt,
|
|
4217
|
+
userPrompt,
|
|
4218
|
+
maxTokens: 8192,
|
|
4219
|
+
skipSchemaValidation: true
|
|
4220
|
+
});
|
|
4221
|
+
return {
|
|
4222
|
+
success: true,
|
|
4223
|
+
updatedOrbital: result
|
|
4224
|
+
};
|
|
4225
|
+
} catch (error) {
|
|
4226
|
+
return {
|
|
4227
|
+
success: false,
|
|
4228
|
+
updatedOrbital: null
|
|
4229
|
+
};
|
|
4230
|
+
}
|
|
4231
|
+
}
|
|
4232
|
+
async function executeFixPlan(schema, plan, errors, config) {
|
|
4233
|
+
const executeStart = Date.now();
|
|
4234
|
+
const updatedSchema = { ...schema };
|
|
4235
|
+
if (plan.parallelizationStrategy === "multi-provider") {
|
|
4236
|
+
const deepseekSteps = plan.executionOrder.filter((s) => s.provider === "deepseek");
|
|
4237
|
+
const qwenSteps = plan.executionOrder.filter((s) => s.provider === "qwen");
|
|
4238
|
+
if (config.verbose) {
|
|
4239
|
+
console.log(`[Fixing] Executing ${deepseekSteps.length} steps on DeepSeek, ${qwenSteps.length} on Qwen`);
|
|
4240
|
+
}
|
|
4241
|
+
const [deepseekResults, qwenResults] = await Promise.all([
|
|
4242
|
+
Promise.all(deepseekSteps.map((step) => executeFixStep(schema, step, errors, config))),
|
|
4243
|
+
Promise.all(qwenSteps.map((step) => executeFixStep(schema, step, errors, config)))
|
|
4244
|
+
]);
|
|
4245
|
+
deepseekSteps.forEach((step, i) => {
|
|
4246
|
+
if (deepseekResults[i].success) {
|
|
4247
|
+
updatedSchema.orbitals[step.orbitalIndex] = deepseekResults[i].updatedOrbital;
|
|
4248
|
+
}
|
|
4249
|
+
});
|
|
4250
|
+
qwenSteps.forEach((step, i) => {
|
|
4251
|
+
if (qwenResults[i].success) {
|
|
4252
|
+
updatedSchema.orbitals[step.orbitalIndex] = qwenResults[i].updatedOrbital;
|
|
4253
|
+
}
|
|
4254
|
+
});
|
|
4255
|
+
} else {
|
|
4256
|
+
for (const step of plan.executionOrder) {
|
|
4257
|
+
if (config.verbose) {
|
|
4258
|
+
console.log(`[Fixing] Executing: ${step.description}`);
|
|
4259
|
+
}
|
|
4260
|
+
const result = await executeFixStep(schema, step, errors, config);
|
|
4261
|
+
if (result.success) {
|
|
4262
|
+
updatedSchema.orbitals[step.orbitalIndex] = result.updatedOrbital;
|
|
4263
|
+
}
|
|
4264
|
+
}
|
|
4265
|
+
}
|
|
4266
|
+
if (config.verbose) {
|
|
4267
|
+
console.log(`[Fixing] Execution completed in ${Date.now() - executeStart}ms`);
|
|
4268
|
+
}
|
|
4269
|
+
return updatedSchema;
|
|
4270
|
+
}
|
|
4271
|
+
function validateSchema(schema) {
|
|
4272
|
+
const tempDir = path__default.join(os.tmpdir(), "almadar-fixing");
|
|
4273
|
+
fs3__default.mkdirSync(tempDir, { recursive: true });
|
|
4274
|
+
const tempFile = path__default.join(tempDir, `schema-${Date.now()}.orb`);
|
|
4275
|
+
try {
|
|
4276
|
+
fs3__default.writeFileSync(tempFile, JSON.stringify(schema, null, 2));
|
|
4277
|
+
const output = execSync(`npx @almadar/cli validate --json "${tempFile}"`, {
|
|
4278
|
+
encoding: "utf-8",
|
|
4279
|
+
timeout: 3e4
|
|
4280
|
+
});
|
|
4281
|
+
fs3__default.unlinkSync(tempFile);
|
|
4282
|
+
const result = JSON.parse(output);
|
|
4283
|
+
return {
|
|
4284
|
+
valid: result.valid,
|
|
4285
|
+
errors: result.errors || []
|
|
4286
|
+
};
|
|
4287
|
+
} catch (error) {
|
|
4288
|
+
try {
|
|
4289
|
+
fs3__default.unlinkSync(tempFile);
|
|
4290
|
+
} catch {
|
|
4291
|
+
}
|
|
4292
|
+
try {
|
|
4293
|
+
const result = JSON.parse(error.stdout || "{}");
|
|
4294
|
+
return {
|
|
4295
|
+
valid: false,
|
|
4296
|
+
errors: result.errors || []
|
|
4297
|
+
};
|
|
4298
|
+
} catch {
|
|
4299
|
+
return {
|
|
4300
|
+
valid: false,
|
|
4301
|
+
errors: [{ code: "ERROR", message: error.message, path: [""], severity: "error" }]
|
|
4302
|
+
};
|
|
4303
|
+
}
|
|
4304
|
+
}
|
|
4305
|
+
}
|
|
4306
|
+
async function orchestrateFixing(schema, config = {}) {
|
|
4307
|
+
const totalStart = Date.now();
|
|
4308
|
+
if (config.verbose) {
|
|
4309
|
+
console.log("[Fixing] Starting Plan-Then-Execute fixing workflow");
|
|
4310
|
+
}
|
|
4311
|
+
const initialValidation = validateSchema(schema);
|
|
4312
|
+
if (initialValidation.valid) {
|
|
4313
|
+
return {
|
|
4314
|
+
success: true,
|
|
4315
|
+
fixedSchema: schema,
|
|
4316
|
+
plan: {
|
|
4317
|
+
summary: { totalErrors: 0, criticalErrors: 0, warningErrors: 0, affectedOrbitals: [] },
|
|
4318
|
+
executionOrder: [],
|
|
4319
|
+
parallelizationStrategy: "single"
|
|
4320
|
+
},
|
|
4321
|
+
stepsCompleted: 0,
|
|
4322
|
+
stepsTotal: 0,
|
|
4323
|
+
remainingErrors: [],
|
|
4324
|
+
timing: {
|
|
4325
|
+
planMs: 0,
|
|
4326
|
+
executeMs: 0,
|
|
4327
|
+
verifyMs: 0,
|
|
4328
|
+
totalMs: Date.now() - totalStart
|
|
4329
|
+
}
|
|
4330
|
+
};
|
|
4331
|
+
}
|
|
4332
|
+
const planStart = Date.now();
|
|
4333
|
+
const plan = await createFixPlan(schema, initialValidation.errors, config);
|
|
4334
|
+
const planMs = Date.now() - planStart;
|
|
4335
|
+
const executeStart = Date.now();
|
|
4336
|
+
let fixedSchema = await executeFixPlan(schema, plan, initialValidation.errors, config);
|
|
4337
|
+
const executeMs = Date.now() - executeStart;
|
|
4338
|
+
const verifyStart = Date.now();
|
|
4339
|
+
const finalValidation = validateSchema(fixedSchema);
|
|
4340
|
+
const verifyMs = Date.now() - verifyStart;
|
|
4341
|
+
let retries = 0;
|
|
4342
|
+
const maxRetries = config.maxRetries || 2;
|
|
4343
|
+
while (!finalValidation.valid && retries < maxRetries) {
|
|
4344
|
+
if (config.verbose) {
|
|
4345
|
+
console.log(`[Fixing] Retrying (${retries + 1}/${maxRetries})...`);
|
|
4346
|
+
}
|
|
4347
|
+
const retryPlan = await createFixPlan(fixedSchema, finalValidation.errors, config);
|
|
4348
|
+
fixedSchema = await executeFixPlan(fixedSchema, retryPlan, finalValidation.errors, config);
|
|
4349
|
+
const retryValidation = validateSchema(fixedSchema);
|
|
4350
|
+
if (retryValidation.valid || retryValidation.errors.length < finalValidation.errors.length) {
|
|
4351
|
+
finalValidation.errors = retryValidation.errors;
|
|
4352
|
+
finalValidation.valid = retryValidation.valid;
|
|
4353
|
+
}
|
|
4354
|
+
retries++;
|
|
4355
|
+
}
|
|
4356
|
+
const totalMs = Date.now() - totalStart;
|
|
4357
|
+
if (config.verbose) {
|
|
4358
|
+
console.log("[Fixing] === Summary ===");
|
|
4359
|
+
console.log(`[Fixing] Plan: ${planMs}ms, Execute: ${executeMs}ms, Verify: ${verifyMs}ms`);
|
|
4360
|
+
console.log(`[Fixing] Total: ${totalMs}ms`);
|
|
4361
|
+
console.log(`[Fixing] Errors: ${initialValidation.errors.length} \u2192 ${finalValidation.errors.length}`);
|
|
4362
|
+
console.log(`[Fixing] Success: ${finalValidation.valid ? "YES" : "PARTIAL"}`);
|
|
4363
|
+
}
|
|
4364
|
+
return {
|
|
4365
|
+
success: finalValidation.valid,
|
|
4366
|
+
fixedSchema: finalValidation.valid ? fixedSchema : null,
|
|
4367
|
+
plan,
|
|
4368
|
+
stepsCompleted: plan.executionOrder.length - retries,
|
|
4369
|
+
stepsTotal: plan.executionOrder.length,
|
|
4370
|
+
remainingErrors: finalValidation.errors,
|
|
4371
|
+
timing: {
|
|
4372
|
+
planMs,
|
|
4373
|
+
executeMs,
|
|
4374
|
+
verifyMs,
|
|
4375
|
+
totalMs
|
|
4376
|
+
}
|
|
4377
|
+
};
|
|
4378
|
+
}
|
|
4379
|
+
|
|
4380
|
+
// src/tools/orchestrated-generation.ts
|
|
4381
|
+
function createOrchestratedGenerationTool(options) {
|
|
4382
|
+
const { skillContent, verbose = false } = options;
|
|
4383
|
+
return tool(
|
|
4384
|
+
async ({ prompt }) => {
|
|
4385
|
+
const startTime = Date.now();
|
|
4386
|
+
if (verbose) {
|
|
4387
|
+
console.log("[OrchestratedGeneration] Starting generation...");
|
|
4388
|
+
console.log(`[OrchestratedGeneration] Prompt length: ${prompt.length} chars`);
|
|
4389
|
+
}
|
|
4390
|
+
const quickCheck = quickComplexityCheck(prompt);
|
|
4391
|
+
if (verbose) {
|
|
4392
|
+
console.log(`[OrchestratedGeneration] Quick check: ~${quickCheck.estimatedOrbitals} orbitals (${quickCheck.confidence} confidence)`);
|
|
4393
|
+
}
|
|
4394
|
+
try {
|
|
4395
|
+
const result = await routeGeneration(prompt, skillContent, {
|
|
4396
|
+
verbose
|
|
4397
|
+
});
|
|
4398
|
+
const totalTime = Date.now() - startTime;
|
|
4399
|
+
if (verbose) {
|
|
4400
|
+
console.log(`[OrchestratedGeneration] \u2705 Success: ${result.orbitals.length} orbitals`);
|
|
4401
|
+
console.log(`[OrchestratedGeneration] Provider: ${result.provider}`);
|
|
4402
|
+
console.log(`[OrchestratedGeneration] Total time: ${totalTime}ms`);
|
|
4403
|
+
}
|
|
4404
|
+
const schema = {
|
|
4405
|
+
name: "GeneratedApp",
|
|
4406
|
+
version: "1.0.0",
|
|
4407
|
+
orbitals: result.orbitals
|
|
4408
|
+
};
|
|
4409
|
+
return {
|
|
4410
|
+
success: true,
|
|
4411
|
+
schema,
|
|
4412
|
+
complexity: result.complexity,
|
|
4413
|
+
provider: result.provider,
|
|
4414
|
+
timing: result.timing
|
|
4415
|
+
};
|
|
4416
|
+
} catch (error) {
|
|
4417
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4418
|
+
if (verbose) {
|
|
4419
|
+
console.log(`[OrchestratedGeneration] \u274C Failed: ${errorMessage}`);
|
|
4420
|
+
}
|
|
4421
|
+
return {
|
|
4422
|
+
success: false,
|
|
4423
|
+
error: errorMessage
|
|
4424
|
+
};
|
|
4425
|
+
}
|
|
4426
|
+
},
|
|
4427
|
+
{
|
|
4428
|
+
name: "generate_schema_orchestrated",
|
|
4429
|
+
description: `Generate an OrbitalSchema using complexity-based provider routing.
|
|
4430
|
+
|
|
4431
|
+
This tool automatically selects the best generation strategy:
|
|
4432
|
+
- Simple (1 orbital) \u2192 Fast single-provider generation
|
|
4433
|
+
- Medium (2-3 orbitals) \u2192 Efficient single-provider generation
|
|
4434
|
+
- Complex (4+ orbitals) \u2192 Parallel multi-provider generation
|
|
4435
|
+
|
|
4436
|
+
The tool handles decomposition, provider selection, and result combination automatically.`,
|
|
4437
|
+
schema: z.object({
|
|
4438
|
+
prompt: z.string().describe("User prompt describing the application to generate")
|
|
4439
|
+
})
|
|
4440
|
+
}
|
|
4441
|
+
);
|
|
4442
|
+
}
|
|
4443
|
+
function createComplexityCheckTool() {
|
|
4444
|
+
return tool(
|
|
4445
|
+
async ({ prompt }) => {
|
|
4446
|
+
const check = quickComplexityCheck(prompt);
|
|
4447
|
+
return {
|
|
4448
|
+
estimatedOrbitals: check.estimatedOrbitals,
|
|
4449
|
+
confidence: check.confidence,
|
|
4450
|
+
likelyComplex: check.likelyComplex,
|
|
4451
|
+
recommendedStrategy: check.likelyComplex ? "multi-provider-parallel" : "single-provider"
|
|
4452
|
+
};
|
|
4453
|
+
},
|
|
4454
|
+
{
|
|
4455
|
+
name: "check_complexity",
|
|
4456
|
+
description: "Quickly estimate the complexity of a generation request without actually generating. Returns estimated orbital count and recommended strategy.",
|
|
4457
|
+
schema: z.object({
|
|
4458
|
+
prompt: z.string().describe("User prompt describing the application")
|
|
4459
|
+
})
|
|
4460
|
+
}
|
|
4461
|
+
);
|
|
4462
|
+
}
|
|
4463
|
+
function validateSchema2(schema) {
|
|
4464
|
+
const tempDir = path__default.join(os.tmpdir(), "almadar-fixing");
|
|
4465
|
+
fs3__default.mkdirSync(tempDir, { recursive: true });
|
|
4466
|
+
const tempFile = path__default.join(tempDir, `schema-${Date.now()}.orb`);
|
|
4467
|
+
try {
|
|
4468
|
+
fs3__default.writeFileSync(tempFile, JSON.stringify(schema, null, 2));
|
|
4469
|
+
const output = execSync(`npx @almadar/cli validate --json "${tempFile}"`, {
|
|
4470
|
+
encoding: "utf-8",
|
|
4471
|
+
timeout: 3e4
|
|
4472
|
+
});
|
|
4473
|
+
fs3__default.unlinkSync(tempFile);
|
|
4474
|
+
const result = JSON.parse(output);
|
|
4475
|
+
return {
|
|
4476
|
+
valid: result.valid,
|
|
4477
|
+
errors: result.errors || []
|
|
4478
|
+
};
|
|
4479
|
+
} catch (error) {
|
|
4480
|
+
try {
|
|
4481
|
+
fs3__default.unlinkSync(tempFile);
|
|
4482
|
+
} catch {
|
|
4483
|
+
}
|
|
4484
|
+
try {
|
|
4485
|
+
const result = JSON.parse(error.stdout || "{}");
|
|
4486
|
+
return {
|
|
4487
|
+
valid: false,
|
|
4488
|
+
errors: result.errors || []
|
|
4489
|
+
};
|
|
4490
|
+
} catch {
|
|
4491
|
+
return {
|
|
4492
|
+
valid: false,
|
|
4493
|
+
errors: [{ code: "ERROR", message: error.message }]
|
|
4494
|
+
};
|
|
4495
|
+
}
|
|
4496
|
+
}
|
|
4497
|
+
}
|
|
4498
|
+
function createOrchestratedFixingTool(options) {
|
|
4499
|
+
const { skillContent, maxRetries = 2, verbose = false } = options;
|
|
4500
|
+
return tool(
|
|
4501
|
+
async ({ schema }) => {
|
|
4502
|
+
const typedSchema = schema;
|
|
4503
|
+
if (verbose) {
|
|
4504
|
+
console.log("[OrchestratedFixing] Starting fixing workflow...");
|
|
4505
|
+
}
|
|
4506
|
+
const initialValidation = validateSchema2(typedSchema);
|
|
4507
|
+
if (initialValidation.valid) {
|
|
4508
|
+
if (verbose) {
|
|
4509
|
+
console.log("[OrchestratedFixing] Schema is already valid");
|
|
4510
|
+
}
|
|
4511
|
+
return {
|
|
4512
|
+
success: true,
|
|
4513
|
+
schema: typedSchema,
|
|
4514
|
+
fixSummary: {
|
|
4515
|
+
totalErrors: 0,
|
|
4516
|
+
errorsFixed: 0,
|
|
4517
|
+
errorsRemaining: 0,
|
|
4518
|
+
strategy: "none-needed",
|
|
4519
|
+
stepsExecuted: 0
|
|
4520
|
+
},
|
|
4521
|
+
timing: {
|
|
4522
|
+
planMs: 0,
|
|
4523
|
+
executeMs: 0,
|
|
4524
|
+
verifyMs: 0,
|
|
4525
|
+
totalMs: 0
|
|
4526
|
+
}
|
|
4527
|
+
};
|
|
4528
|
+
}
|
|
4529
|
+
if (verbose) {
|
|
4530
|
+
console.log(`[OrchestratedFixing] Found ${initialValidation.errors.length} errors to fix`);
|
|
4531
|
+
}
|
|
4532
|
+
try {
|
|
4533
|
+
const result = await orchestrateFixing(typedSchema, {
|
|
4534
|
+
maxRetries,
|
|
4535
|
+
verbose,
|
|
4536
|
+
skillContent
|
|
4537
|
+
});
|
|
4538
|
+
if (verbose) {
|
|
4539
|
+
console.log(`[OrchestratedFixing] ${result.success ? "\u2705" : "\u26A0\uFE0F"} Fix complete`);
|
|
4540
|
+
console.log(`[OrchestratedFixing] Errors: ${result.plan.summary.totalErrors} \u2192 ${result.remainingErrors.length}`);
|
|
4541
|
+
}
|
|
4542
|
+
return {
|
|
4543
|
+
success: result.success,
|
|
4544
|
+
schema: result.fixedSchema || typedSchema,
|
|
4545
|
+
fixSummary: {
|
|
4546
|
+
totalErrors: result.plan.summary.totalErrors,
|
|
4547
|
+
errorsFixed: result.plan.summary.totalErrors - result.remainingErrors.length,
|
|
4548
|
+
errorsRemaining: result.remainingErrors.length,
|
|
4549
|
+
strategy: result.plan.parallelizationStrategy,
|
|
4550
|
+
stepsExecuted: result.stepsCompleted
|
|
4551
|
+
},
|
|
4552
|
+
timing: result.timing
|
|
4553
|
+
};
|
|
4554
|
+
} catch (error) {
|
|
4555
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4556
|
+
if (verbose) {
|
|
4557
|
+
console.log(`[OrchestratedFixing] \u274C Failed: ${errorMessage}`);
|
|
4558
|
+
}
|
|
4559
|
+
return {
|
|
4560
|
+
success: false,
|
|
4561
|
+
schema: typedSchema,
|
|
4562
|
+
error: errorMessage
|
|
4563
|
+
};
|
|
4564
|
+
}
|
|
4565
|
+
},
|
|
4566
|
+
{
|
|
4567
|
+
name: "fix_schema_orchestrated",
|
|
4568
|
+
description: `Fix validation errors in an OrbitalSchema using Plan-Then-Execute strategy.
|
|
4569
|
+
|
|
4570
|
+
This tool:
|
|
4571
|
+
1. Validates the schema to identify errors
|
|
4572
|
+
2. Creates a fix plan based on error types
|
|
4573
|
+
3. Applies fixes using the fixing skill guidance
|
|
4574
|
+
4. Re-validates and retries if needed
|
|
4575
|
+
|
|
4576
|
+
Works with single or multi-orbital schemas, automatically selecting the best strategy.`,
|
|
4577
|
+
schema: z.object({
|
|
4578
|
+
schema: z.object({}).describe("The OrbitalSchema to fix")
|
|
4579
|
+
})
|
|
4580
|
+
}
|
|
4581
|
+
);
|
|
4582
|
+
}
|
|
4583
|
+
function createValidateTool() {
|
|
4584
|
+
return tool(
|
|
4585
|
+
async ({ schema }) => {
|
|
4586
|
+
const typedSchema = schema;
|
|
4587
|
+
const result = validateSchema2(typedSchema);
|
|
4588
|
+
return {
|
|
4589
|
+
valid: result.valid,
|
|
4590
|
+
errorCount: result.errors.length,
|
|
4591
|
+
errors: result.errors
|
|
4592
|
+
};
|
|
4593
|
+
},
|
|
4594
|
+
{
|
|
4595
|
+
name: "validate_schema",
|
|
4596
|
+
description: "Validate an OrbitalSchema and return any errors without attempting to fix them.",
|
|
4597
|
+
schema: z.object({
|
|
4598
|
+
schema: z.object({}).describe("The OrbitalSchema to validate")
|
|
4599
|
+
})
|
|
4600
|
+
}
|
|
4601
|
+
);
|
|
4602
|
+
}
|
|
3647
4603
|
function createGitHubTools(config) {
|
|
3648
4604
|
const { token, owner = "", repo = "", workDir } = config;
|
|
3649
4605
|
const integrationConfig = {
|
|
@@ -4017,6 +4973,6 @@ function createAgentTools(workDir) {
|
|
|
4017
4973
|
};
|
|
4018
4974
|
}
|
|
4019
4975
|
|
|
4020
|
-
export { createAgentTools, createApplyChunkTool, createCombineSchemasTool, createConstructCombinedDomainTool, createDomainOrbitalTools, createExecuteTool, createExtractChunkTool, createFinishTaskTool, createGenerateOrbitalDomainTool, createGenerateSchemaTool, createGitHubTools, createGitHubToolsArray, createOrbitalBatchSubagentTool, createOrbitalSubagentTool, createQuerySchemaStructureTool, createSchemaChunkingTools, createSubagentEventWrapper, createTraitEventWrapper, createTraitSubagentTool, createValidateSchemaTool, validateCommandPaths };
|
|
4976
|
+
export { createAgentTools, createApplyChunkTool, createCombineSchemasTool, createComplexityCheckTool, createConstructCombinedDomainTool, createDomainOrbitalTools, createExecuteTool, createExtractChunkTool, createFinishTaskTool, createGenerateOrbitalDomainTool, createGenerateSchemaTool, createGitHubTools, createGitHubToolsArray, createOrbitalBatchSubagentTool, createOrbitalSubagentTool, createOrchestratedFixingTool, createOrchestratedGenerationTool, createQuerySchemaStructureTool, createSchemaChunkingTools, createSubagentEventWrapper, createTraitEventWrapper, createTraitSubagentTool, createValidateSchemaTool, createValidateTool, validateCommandPaths };
|
|
4021
4977
|
//# sourceMappingURL=index.js.map
|
|
4022
4978
|
//# sourceMappingURL=index.js.map
|