@almadar/agent 1.6.0 → 1.6.2
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 +3 -731
- package/dist/agent/index.js +294 -2184
- package/dist/agent/index.js.map +1 -1
- package/dist/{firestore-checkpointer-BkFR-sZM.d.ts → firestore-checkpointer-CkNKXoun.d.ts} +1 -1
- package/dist/{index-DGdLGf-L.d.ts → index-CV-YHG_P.d.ts} +25 -21
- package/dist/{workflow-tool-wrapper-CXD0A7l3.d.ts → index-CmTX9IiH.d.ts} +4 -3
- package/dist/index.d.ts +9 -536
- package/dist/index.js +3191 -3560
- package/dist/index.js.map +1 -1
- package/dist/{orbital-subagent-CHEeQQr_.d.ts → orbital-subagent-B9lvv_NS.d.ts} +28 -26
- package/dist/persistence/index.d.ts +2 -2
- package/dist/tools/index.d.ts +2 -2
- package/dist/tools/index.js +283 -131
- package/dist/tools/index.js.map +1 -1
- package/dist/workspace/index.d.ts +355 -0
- package/dist/workspace/index.js +675 -0
- package/dist/workspace/index.js.map +1 -0
- package/package.json +11 -9
- package/dist/prompts/index.d.ts +0 -23
- package/dist/prompts/index.js +0 -126
- package/dist/prompts/index.js.map +0 -1
package/dist/agent/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { AgentDomainCategorySchema, isOrbitalDefinition, isEntityReference, getT
|
|
|
2
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
|
-
import { LLMClient, ANTHROPIC_MODELS, createAnthropicClient, OPENROUTER_MODELS, createOpenRouterClient, KIMI_MODELS, createKimiClient, OPENAI_MODELS, createOpenAIClient, DEEPSEEK_MODELS, createDeepSeekClient
|
|
5
|
+
import { LLMClient, ANTHROPIC_MODELS, createAnthropicClient, OPENROUTER_MODELS, createOpenRouterClient, KIMI_MODELS, createKimiClient, OPENAI_MODELS, createOpenAIClient, DEEPSEEK_MODELS, createDeepSeekClient } from '@almadar/llm';
|
|
6
6
|
import { FilesystemBackend, createDeepAgent } from 'deepagents';
|
|
7
7
|
import { MemorySaver } from '@langchain/langgraph';
|
|
8
8
|
export { Command } from '@langchain/langgraph';
|
|
@@ -11,7 +11,7 @@ import { exec, spawn, execSync } from 'child_process';
|
|
|
11
11
|
import * as path from 'path';
|
|
12
12
|
import path__default from 'path';
|
|
13
13
|
import { promisify } from 'util';
|
|
14
|
-
import * as
|
|
14
|
+
import * as fs5 from 'fs/promises';
|
|
15
15
|
import * as domain_language_star from '@almadar/core/domain-language';
|
|
16
16
|
import * as fs3 from 'fs';
|
|
17
17
|
import fs3__default from 'fs';
|
|
@@ -1408,12 +1408,12 @@ ${output}`);
|
|
|
1408
1408
|
description: `Execute a shell command in the workspace directory.
|
|
1409
1409
|
|
|
1410
1410
|
IMPORTANT: You are restricted to your workspace directory. Use RELATIVE paths only:
|
|
1411
|
-
- ./schema.
|
|
1411
|
+
- ./schema.orb (NOT /schema.orb or absolute paths)
|
|
1412
1412
|
- ./app (NOT /app or absolute paths)
|
|
1413
1413
|
|
|
1414
1414
|
Examples:
|
|
1415
|
-
- orbital validate ./schema.
|
|
1416
|
-
- npx kflow compile ./schema.
|
|
1415
|
+
- orbital validate ./schema.orb --json
|
|
1416
|
+
- npx kflow compile ./schema.orb -o ./app --verify
|
|
1417
1417
|
- cd ./app && npm install
|
|
1418
1418
|
|
|
1419
1419
|
Commands using absolute paths outside your workspace will be blocked.`,
|
|
@@ -1427,7 +1427,7 @@ Commands using absolute paths outside your workspace will be blocked.`,
|
|
|
1427
1427
|
var execAsync = promisify(exec);
|
|
1428
1428
|
var MAX_VALIDATION_ATTEMPTS = 5;
|
|
1429
1429
|
function createValidateSchemaTool(workDir) {
|
|
1430
|
-
const schemaPath = path.join(workDir, "schema.
|
|
1430
|
+
const schemaPath = path.join(workDir, "schema.orb");
|
|
1431
1431
|
let validationAttempts = 0;
|
|
1432
1432
|
return tool(
|
|
1433
1433
|
async () => {
|
|
@@ -1443,7 +1443,7 @@ function createValidateSchemaTool(workDir) {
|
|
|
1443
1443
|
}
|
|
1444
1444
|
try {
|
|
1445
1445
|
try {
|
|
1446
|
-
await
|
|
1446
|
+
await fs5.access(schemaPath);
|
|
1447
1447
|
} catch {
|
|
1448
1448
|
return JSON.stringify({
|
|
1449
1449
|
success: false,
|
|
@@ -1452,7 +1452,7 @@ function createValidateSchemaTool(workDir) {
|
|
|
1452
1452
|
errors: [{
|
|
1453
1453
|
code: "FILE_NOT_FOUND",
|
|
1454
1454
|
path: "",
|
|
1455
|
-
message: "File not found: schema.
|
|
1455
|
+
message: "File not found: schema.orb. Create it first with write_file."
|
|
1456
1456
|
}]
|
|
1457
1457
|
});
|
|
1458
1458
|
}
|
|
@@ -1513,7 +1513,7 @@ function createValidateSchemaTool(workDir) {
|
|
|
1513
1513
|
},
|
|
1514
1514
|
{
|
|
1515
1515
|
name: "validate_schema",
|
|
1516
|
-
description: `Validate the schema.
|
|
1516
|
+
description: `Validate the schema.orb file in the workspace.
|
|
1517
1517
|
|
|
1518
1518
|
Runs validation using \`npx @almadar/cli validate --json\`.
|
|
1519
1519
|
|
|
@@ -2039,14 +2039,14 @@ function checkCompositionQuality(schema) {
|
|
|
2039
2039
|
async function collectOrbitalsFromDir(workDir) {
|
|
2040
2040
|
const orbitalsDir = path.join(workDir, ".orbitals");
|
|
2041
2041
|
try {
|
|
2042
|
-
const dirStat = await
|
|
2042
|
+
const dirStat = await fs5.stat(orbitalsDir);
|
|
2043
2043
|
if (!dirStat.isDirectory()) {
|
|
2044
2044
|
return [];
|
|
2045
2045
|
}
|
|
2046
2046
|
} catch {
|
|
2047
2047
|
return [];
|
|
2048
2048
|
}
|
|
2049
|
-
const files = await
|
|
2049
|
+
const files = await fs5.readdir(orbitalsDir);
|
|
2050
2050
|
const jsonFiles = files.filter((f) => f.endsWith(".json"));
|
|
2051
2051
|
if (jsonFiles.length === 0) {
|
|
2052
2052
|
return [];
|
|
@@ -2054,7 +2054,7 @@ async function collectOrbitalsFromDir(workDir) {
|
|
|
2054
2054
|
const orbitals = [];
|
|
2055
2055
|
for (const file of jsonFiles) {
|
|
2056
2056
|
try {
|
|
2057
|
-
const content = await
|
|
2057
|
+
const content = await fs5.readFile(path.join(orbitalsDir, file), "utf-8");
|
|
2058
2058
|
orbitals.push(JSON.parse(content));
|
|
2059
2059
|
} catch {
|
|
2060
2060
|
}
|
|
@@ -2108,7 +2108,7 @@ function createFinishTaskTool(workDir) {
|
|
|
2108
2108
|
} else {
|
|
2109
2109
|
const domainPath = path.join(workDir, "domain.txt");
|
|
2110
2110
|
try {
|
|
2111
|
-
const domainText = await
|
|
2111
|
+
const domainText = await fs5.readFile(domainPath, "utf-8");
|
|
2112
2112
|
if (domainText.trim()) {
|
|
2113
2113
|
source = "domain";
|
|
2114
2114
|
const appName = input.summary?.match(/Generated \d+ orbitals?:?\s*(.+)/)?.[1] || "Application";
|
|
@@ -2141,8 +2141,8 @@ function createFinishTaskTool(workDir) {
|
|
|
2141
2141
|
compositionWarnings = checkCompositionQuality(combinedSchema);
|
|
2142
2142
|
}
|
|
2143
2143
|
if (combinedSchema) {
|
|
2144
|
-
const schemaPath = path.join(workDir, "schema.
|
|
2145
|
-
await
|
|
2144
|
+
const schemaPath = path.join(workDir, "schema.orb");
|
|
2145
|
+
await fs5.writeFile(schemaPath, JSON.stringify(combinedSchema, null, 2));
|
|
2146
2146
|
validationResult = await validateSchemaWithCLI(schemaPath);
|
|
2147
2147
|
}
|
|
2148
2148
|
}
|
|
@@ -2163,25 +2163,16 @@ function createFinishTaskTool(workDir) {
|
|
|
2163
2163
|
propCorrections: propCorrections || 0,
|
|
2164
2164
|
compositionWarnings: compositionWarnings || []
|
|
2165
2165
|
},
|
|
2166
|
-
schemaPath: combinedSchema ? path.join(workDir, "schema.
|
|
2166
|
+
schemaPath: combinedSchema ? path.join(workDir, "schema.orb") : input.schemaPath,
|
|
2167
2167
|
nextAction: "NONE - Task is complete. Output a brief success message to the user."
|
|
2168
2168
|
};
|
|
2169
2169
|
},
|
|
2170
2170
|
{
|
|
2171
2171
|
name: "finish_task",
|
|
2172
|
-
description: `
|
|
2173
|
-
|
|
2174
|
-
\u26A0\uFE0F IMPORTANT: After calling this tool, STOP. Do not make any more tool calls.
|
|
2175
|
-
|
|
2176
|
-
WHAT IT DOES:
|
|
2177
|
-
1. Automatically collects orbitals from .orbitals/ directory
|
|
2178
|
-
2. Combines them into a single OrbitalSchema
|
|
2179
|
-
3. Validates the combined schema
|
|
2180
|
-
4. Writes schema.json to workspace
|
|
2181
|
-
5. Returns success with stats`,
|
|
2172
|
+
description: `Complete workflow: collect orbitals from .orbitals/, combine into schema, validate, write schema.orb. STOP after calling.`,
|
|
2182
2173
|
schema: z.object({
|
|
2183
|
-
summary: z.string().describe("
|
|
2184
|
-
schemaPath: z.string().optional().describe("
|
|
2174
|
+
summary: z.string().describe("What was accomplished"),
|
|
2175
|
+
schemaPath: z.string().optional().describe("Schema file path if already written")
|
|
2185
2176
|
})
|
|
2186
2177
|
}
|
|
2187
2178
|
);
|
|
@@ -2195,7 +2186,7 @@ function generateFingerprint(spec) {
|
|
|
2195
2186
|
entity: spec.entity,
|
|
2196
2187
|
pages: spec.pages,
|
|
2197
2188
|
traits: spec.traits.sort(),
|
|
2198
|
-
patterns: spec.patterns
|
|
2189
|
+
patterns: spec.patterns?.sort() || [],
|
|
2199
2190
|
emits: spec.emits?.sort() || [],
|
|
2200
2191
|
listens: spec.listens?.map((l) => `${l.event}:${l.triggers}`).sort() || []
|
|
2201
2192
|
});
|
|
@@ -2332,7 +2323,7 @@ ${relations}` : ""}
|
|
|
2332
2323
|
${pagesInfo}
|
|
2333
2324
|
|
|
2334
2325
|
**Behaviors**: ${spec.traits.join(", ")}
|
|
2335
|
-
**UI Patterns**: ${spec.patterns
|
|
2326
|
+
**UI Patterns**: ${spec.patterns?.join(", ") || "auto-detect from traits"}
|
|
2336
2327
|
${emitsInfo}
|
|
2337
2328
|
${listensInfo}
|
|
2338
2329
|
|
|
@@ -2364,7 +2355,7 @@ var GenerateOrbitalDomainSchema = z.object({
|
|
|
2364
2355
|
isInitial: z.boolean().optional()
|
|
2365
2356
|
})),
|
|
2366
2357
|
traits: z.array(z.string()),
|
|
2367
|
-
patterns: z.array(z.string()),
|
|
2358
|
+
patterns: z.array(z.string()).optional(),
|
|
2368
2359
|
domainContext: z.object({
|
|
2369
2360
|
request: z.string(),
|
|
2370
2361
|
requestFragment: z.string().optional(),
|
|
@@ -2510,7 +2501,7 @@ function createGenerateOrbitalDomainTool(options = {}) {
|
|
|
2510
2501
|
cached: false,
|
|
2511
2502
|
domainWritten: true,
|
|
2512
2503
|
usage,
|
|
2513
|
-
domainText
|
|
2504
|
+
domainLength: domainText.length
|
|
2514
2505
|
});
|
|
2515
2506
|
} catch (error) {
|
|
2516
2507
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -2788,6 +2779,88 @@ ${sections.join("\n\n")}
|
|
|
2788
2779
|
`;
|
|
2789
2780
|
}
|
|
2790
2781
|
|
|
2782
|
+
// src/evals/utils/compact-orbital.ts
|
|
2783
|
+
function compactField(f) {
|
|
2784
|
+
let desc = `${f.name}:${f.type}`;
|
|
2785
|
+
if (f.required) desc += "*";
|
|
2786
|
+
if (f.values) desc += `(${f.values.length})`;
|
|
2787
|
+
if (f.relation) desc += `\u2192${f.relation.entity}`;
|
|
2788
|
+
return desc;
|
|
2789
|
+
}
|
|
2790
|
+
function getStateName(state) {
|
|
2791
|
+
return typeof state === "string" ? state : state.name;
|
|
2792
|
+
}
|
|
2793
|
+
function getTraitRef(ref) {
|
|
2794
|
+
return typeof ref === "string" ? ref : ref.ref;
|
|
2795
|
+
}
|
|
2796
|
+
function compactOrbital(orbital) {
|
|
2797
|
+
const lines = [];
|
|
2798
|
+
lines.push(`orbital: ${orbital.name}`);
|
|
2799
|
+
if (orbital.entity) {
|
|
2800
|
+
const e = orbital.entity;
|
|
2801
|
+
const fieldSummary = e.fields?.map(compactField).join(", ") || "none";
|
|
2802
|
+
const collection = e.collection ? ` (${e.collection})` : "";
|
|
2803
|
+
lines.push(` entity: ${e.name}${collection} [${fieldSummary}] ${e.fields?.length || 0} fields`);
|
|
2804
|
+
}
|
|
2805
|
+
if (orbital.traits) {
|
|
2806
|
+
for (const trait of orbital.traits) {
|
|
2807
|
+
const sm = trait.stateMachine;
|
|
2808
|
+
if (sm) {
|
|
2809
|
+
const stateNames = sm.states?.map(getStateName) || [];
|
|
2810
|
+
const stateList = stateNames.join("\u2192");
|
|
2811
|
+
const stateCount = stateNames.length;
|
|
2812
|
+
const eventCount = sm.events?.length || 0;
|
|
2813
|
+
const transCount = sm.transitions?.length || 0;
|
|
2814
|
+
lines.push(` trait: ${trait.name} [${stateList}] ${stateCount} states, ${eventCount} events, ${transCount} transitions`);
|
|
2815
|
+
} else {
|
|
2816
|
+
lines.push(` trait: ${trait.name}`);
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2819
|
+
}
|
|
2820
|
+
if (orbital.pages) {
|
|
2821
|
+
for (const page of orbital.pages) {
|
|
2822
|
+
const traitRefs = page.traits?.map(getTraitRef).join(", ") || "none";
|
|
2823
|
+
lines.push(` page: ${page.path} \u2192 ${traitRefs}`);
|
|
2824
|
+
}
|
|
2825
|
+
}
|
|
2826
|
+
if (orbital.emits?.length) {
|
|
2827
|
+
lines.push(` emits: ${orbital.emits.join(", ")}`);
|
|
2828
|
+
}
|
|
2829
|
+
if (orbital.listens?.length) {
|
|
2830
|
+
lines.push(` listens: ${orbital.listens.map((l) => `${l.event} \u2192 ${l.triggers}`).join(", ")}`);
|
|
2831
|
+
}
|
|
2832
|
+
return lines.join("\n");
|
|
2833
|
+
}
|
|
2834
|
+
function compactSchema(schema) {
|
|
2835
|
+
const lines = [];
|
|
2836
|
+
if (schema.name) {
|
|
2837
|
+
lines.push(`schema: ${schema.name} v${schema.version || "1.0.0"}`);
|
|
2838
|
+
}
|
|
2839
|
+
const orbitals = schema.orbitals || [];
|
|
2840
|
+
lines.push(`orbitals: ${orbitals.length}`);
|
|
2841
|
+
for (const orbital of orbitals) {
|
|
2842
|
+
lines.push(compactOrbital(orbital));
|
|
2843
|
+
}
|
|
2844
|
+
return lines.join("\n");
|
|
2845
|
+
}
|
|
2846
|
+
function compactOrbitalResult(result) {
|
|
2847
|
+
if (!result.orbital) {
|
|
2848
|
+
return JSON.stringify({ success: false, error: "Generation failed" });
|
|
2849
|
+
}
|
|
2850
|
+
const orbital = result.orbital;
|
|
2851
|
+
const summary = compactOrbital(orbital);
|
|
2852
|
+
const validationLine = result.validation ? result.validation.valid ? " validation: valid" : ` validation: INVALID (${result.validation.errors?.map((e) => e.message).join("; ") || "unknown errors"})` : "";
|
|
2853
|
+
const usageLine = result.usage ? ` tokens: ${result.usage.totalTokens || 0}` : "";
|
|
2854
|
+
const compactLines = [
|
|
2855
|
+
`success: true`,
|
|
2856
|
+
`fingerprint: ${result.fingerprint || "none"}`,
|
|
2857
|
+
summary,
|
|
2858
|
+
validationLine,
|
|
2859
|
+
usageLine
|
|
2860
|
+
].filter(Boolean);
|
|
2861
|
+
return compactLines.join("\n");
|
|
2862
|
+
}
|
|
2863
|
+
|
|
2791
2864
|
// src/tools/orbital-subagent.ts
|
|
2792
2865
|
function getEntityName3(entity) {
|
|
2793
2866
|
if (isEntityReference(entity)) {
|
|
@@ -2809,8 +2882,8 @@ var OrbitalInputSchema = z.object({
|
|
|
2809
2882
|
})
|
|
2810
2883
|
)
|
|
2811
2884
|
}),
|
|
2812
|
-
traits: z.array(z.string()),
|
|
2813
|
-
patterns: z.array(z.string()),
|
|
2885
|
+
traits: z.array(z.string()).default([]),
|
|
2886
|
+
patterns: z.array(z.string()).optional(),
|
|
2814
2887
|
pages: z.array(
|
|
2815
2888
|
z.object({
|
|
2816
2889
|
name: z.string(),
|
|
@@ -2997,7 +3070,16 @@ function createOrbitalSubagentTool(options = {}) {
|
|
|
2997
3070
|
});
|
|
2998
3071
|
}
|
|
2999
3072
|
}
|
|
3000
|
-
|
|
3073
|
+
if (options.workDir && finalOrbital) {
|
|
3074
|
+
const orbitalsDir = path.join(options.workDir, ".orbitals");
|
|
3075
|
+
fs3.mkdirSync(orbitalsDir, { recursive: true });
|
|
3076
|
+
const safeFileName = orbitalUnit.name.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3077
|
+
fs3.writeFileSync(
|
|
3078
|
+
path.join(orbitalsDir, `${safeFileName}.json`),
|
|
3079
|
+
JSON.stringify(finalOrbital, null, 2)
|
|
3080
|
+
);
|
|
3081
|
+
}
|
|
3082
|
+
return compactOrbitalResult({
|
|
3001
3083
|
success: true,
|
|
3002
3084
|
orbital: finalOrbital,
|
|
3003
3085
|
fingerprint: result.fingerprint,
|
|
@@ -3019,15 +3101,19 @@ function createOrbitalSubagentTool(options = {}) {
|
|
|
3019
3101
|
},
|
|
3020
3102
|
{
|
|
3021
3103
|
name: "generate_orbital",
|
|
3022
|
-
description: `Generate
|
|
3104
|
+
description: `Generate ONE orbital schema from a single OrbitalUnit.
|
|
3023
3105
|
|
|
3024
3106
|
Spawns a subagent to expand a lightweight OrbitalUnit into a complete
|
|
3025
3107
|
FullOrbitalUnit with all sections, layouts, and configurations.
|
|
3026
3108
|
|
|
3109
|
+
IMPORTANT: This tool generates exactly ONE orbital per call. Each orbital
|
|
3110
|
+
must have exactly ONE entity. For multi-entity apps, call this tool
|
|
3111
|
+
SEPARATELY for each orbital (e.g., 4 entities = 4 calls).
|
|
3112
|
+
|
|
3027
3113
|
USAGE:
|
|
3028
|
-
1. Decompose user request into OrbitalUnits
|
|
3029
|
-
2.
|
|
3030
|
-
3.
|
|
3114
|
+
1. Decompose user request into OrbitalUnits (one per entity)
|
|
3115
|
+
2. Call generate_orbital ONCE PER ORBITAL \u2014 do NOT batch multiple orbitals
|
|
3116
|
+
3. After all orbitals are generated, call finish_task`,
|
|
3031
3117
|
schema: OrbitalInputSchema
|
|
3032
3118
|
}
|
|
3033
3119
|
);
|
|
@@ -3094,7 +3180,7 @@ var CHUNKS_DIR = ".chunks";
|
|
|
3094
3180
|
async function ensureChunksDir(workspaceDir) {
|
|
3095
3181
|
const chunksPath = path.join(workspaceDir, CHUNKS_DIR);
|
|
3096
3182
|
try {
|
|
3097
|
-
await
|
|
3183
|
+
await fs5.mkdir(chunksPath, { recursive: true });
|
|
3098
3184
|
} catch {
|
|
3099
3185
|
}
|
|
3100
3186
|
return chunksPath;
|
|
@@ -3118,7 +3204,7 @@ function createQuerySchemaStructureTool(workDir) {
|
|
|
3118
3204
|
async ({ file }) => {
|
|
3119
3205
|
const filePath = path.isAbsolute(file) ? file : path.join(workDir, file);
|
|
3120
3206
|
try {
|
|
3121
|
-
const content = await
|
|
3207
|
+
const content = await fs5.readFile(filePath, "utf-8");
|
|
3122
3208
|
const schema = JSON.parse(content);
|
|
3123
3209
|
const stats = fs3.statSync(filePath);
|
|
3124
3210
|
const structure = {
|
|
@@ -3147,7 +3233,7 @@ function createQuerySchemaStructureTool(workDir) {
|
|
|
3147
3233
|
|
|
3148
3234
|
USE THIS FIRST before extracting chunks to understand what orbitals and traits exist.`,
|
|
3149
3235
|
schema: z.object({
|
|
3150
|
-
file: z.string().describe('Path to schema file (e.g., "schema.
|
|
3236
|
+
file: z.string().describe('Path to schema file (e.g., "schema.orb")')
|
|
3151
3237
|
})
|
|
3152
3238
|
}
|
|
3153
3239
|
);
|
|
@@ -3157,7 +3243,7 @@ function createExtractChunkTool(workDir) {
|
|
|
3157
3243
|
async ({ file, type, name, parentOrbital, includeTraits = true }) => {
|
|
3158
3244
|
const filePath = path.isAbsolute(file) ? file : path.join(workDir, file);
|
|
3159
3245
|
try {
|
|
3160
|
-
const content = await
|
|
3246
|
+
const content = await fs5.readFile(filePath, "utf-8");
|
|
3161
3247
|
const schema = JSON.parse(content);
|
|
3162
3248
|
const chunkId = randomUUID().slice(0, 8);
|
|
3163
3249
|
const chunksDir = await ensureChunksDir(workDir);
|
|
@@ -3208,7 +3294,7 @@ function createExtractChunkTool(workDir) {
|
|
|
3208
3294
|
chunkData.inlineTrait = orbital.traits[inlineTraitIndex];
|
|
3209
3295
|
}
|
|
3210
3296
|
const chunkContent = JSON.stringify(chunkData, null, 2);
|
|
3211
|
-
await
|
|
3297
|
+
await fs5.writeFile(chunkFile, chunkContent);
|
|
3212
3298
|
const relativeChunkFile = path.relative(workDir, chunkFile);
|
|
3213
3299
|
return JSON.stringify({
|
|
3214
3300
|
success: true,
|
|
@@ -3246,14 +3332,14 @@ function createApplyChunkTool(workDir) {
|
|
|
3246
3332
|
const chunkFilePath = path.join(workDir, CHUNKS_DIR, chunkFileName);
|
|
3247
3333
|
try {
|
|
3248
3334
|
try {
|
|
3249
|
-
await
|
|
3335
|
+
await fs5.access(chunkFilePath);
|
|
3250
3336
|
} catch {
|
|
3251
3337
|
return JSON.stringify({ error: `Chunk file not found: ${chunkFileName}.` });
|
|
3252
3338
|
}
|
|
3253
|
-
const chunkContent = await
|
|
3339
|
+
const chunkContent = await fs5.readFile(chunkFilePath, "utf-8");
|
|
3254
3340
|
const chunkData = JSON.parse(chunkContent);
|
|
3255
3341
|
const { meta } = chunkData;
|
|
3256
|
-
const schemaContent = await
|
|
3342
|
+
const schemaContent = await fs5.readFile(meta.sourceFile, "utf-8");
|
|
3257
3343
|
const schema = JSON.parse(schemaContent);
|
|
3258
3344
|
if (meta.type === "orbital" && chunkData.orbital) {
|
|
3259
3345
|
schema.orbitals[meta.orbitalIndex] = chunkData.orbital;
|
|
@@ -3284,8 +3370,8 @@ function createApplyChunkTool(workDir) {
|
|
|
3284
3370
|
}
|
|
3285
3371
|
}
|
|
3286
3372
|
const output = JSON.stringify(schema, null, 2);
|
|
3287
|
-
await
|
|
3288
|
-
await
|
|
3373
|
+
await fs5.writeFile(meta.sourceFile, output);
|
|
3374
|
+
await fs5.unlink(chunkFilePath);
|
|
3289
3375
|
return JSON.stringify({
|
|
3290
3376
|
success: true,
|
|
3291
3377
|
message: `Changes merged into ${path.basename(meta.sourceFile)}`,
|
|
@@ -3648,12 +3734,70 @@ function quickComplexityCheck(prompt) {
|
|
|
3648
3734
|
estimatedOrbitals: estimatedCounts[estimate.estimatedLevel]
|
|
3649
3735
|
};
|
|
3650
3736
|
}
|
|
3737
|
+
function categorizeError(error) {
|
|
3738
|
+
const message = error.message?.toLowerCase() || "";
|
|
3739
|
+
const code = error.code?.toLowerCase() || "";
|
|
3740
|
+
if (message.includes("binding") || code.includes("binding")) {
|
|
3741
|
+
return "binding";
|
|
3742
|
+
}
|
|
3743
|
+
if (message.includes("state") || code.includes("state")) {
|
|
3744
|
+
return "state-machine";
|
|
3745
|
+
}
|
|
3746
|
+
if (message.includes("required") || message.includes("missing")) {
|
|
3747
|
+
return "schema";
|
|
3748
|
+
}
|
|
3749
|
+
return "other";
|
|
3750
|
+
}
|
|
3751
|
+
function getErrorSpecificGuidance(errors) {
|
|
3752
|
+
const types = new Set(errors.map(categorizeError));
|
|
3753
|
+
const guidance = [];
|
|
3754
|
+
if (types.has("binding")) {
|
|
3755
|
+
guidance.push(`
|
|
3756
|
+
## BINDING ERROR FIXES
|
|
3757
|
+
|
|
3758
|
+
Invalid bindings detected. Fix these patterns:
|
|
3759
|
+
|
|
3760
|
+
\u274C INVALID:
|
|
3761
|
+
- "@count" - missing entity reference
|
|
3762
|
+
- "@count:status=active" - wrong syntax
|
|
3763
|
+
- "@entity" - missing field
|
|
3764
|
+
|
|
3765
|
+
\u2705 VALID:
|
|
3766
|
+
- "@entity.count" - entity field reference
|
|
3767
|
+
- "@entity.status" - enum field reference
|
|
3768
|
+
- "@payload.data" - payload reference
|
|
3769
|
+
- "@state.current" - state reference
|
|
3770
|
+
|
|
3771
|
+
Replace invalid bindings with proper entity.field references.`);
|
|
3772
|
+
}
|
|
3773
|
+
if (types.has("state-machine")) {
|
|
3774
|
+
guidance.push(`
|
|
3775
|
+
## STATE MACHINE FIXES
|
|
3776
|
+
|
|
3777
|
+
Check for:
|
|
3778
|
+
- Unreachable states (no incoming transitions)
|
|
3779
|
+
- Missing transitions for events
|
|
3780
|
+
- Invalid state names
|
|
3781
|
+
|
|
3782
|
+
Ensure every state (except initial) has at least one incoming transition.`);
|
|
3783
|
+
}
|
|
3784
|
+
if (types.has("schema")) {
|
|
3785
|
+
guidance.push(`
|
|
3786
|
+
## SCHEMA FIXES
|
|
3787
|
+
|
|
3788
|
+
Check for:
|
|
3789
|
+
- Required fields (name, type for entity fields)
|
|
3790
|
+
- Missing entity definitions
|
|
3791
|
+
- Invalid type values`);
|
|
3792
|
+
}
|
|
3793
|
+
return guidance.join("\n");
|
|
3794
|
+
}
|
|
3651
3795
|
async function createFixPlan(schema, errors, config) {
|
|
3652
3796
|
const planStart = Date.now();
|
|
3653
3797
|
const criticalErrors = errors.filter(
|
|
3654
|
-
(e) => e.
|
|
3798
|
+
(e) => e.severity === "error" || e.code?.includes("ENTITY") || e.code?.includes("REQUIRED")
|
|
3655
3799
|
);
|
|
3656
|
-
const warningErrors = errors.filter((e) =>
|
|
3800
|
+
const warningErrors = errors.filter((e) => e.severity === "warning");
|
|
3657
3801
|
const orbitalErrors = /* @__PURE__ */ new Map();
|
|
3658
3802
|
errors.forEach((error, index) => {
|
|
3659
3803
|
let pathStr;
|
|
@@ -3679,6 +3823,8 @@ async function createFixPlan(schema, errors, config) {
|
|
|
3679
3823
|
const orbital = schema.orbitals[orbitalIndex];
|
|
3680
3824
|
if (orbital) {
|
|
3681
3825
|
affectedOrbitals.push(orbital.name);
|
|
3826
|
+
const stepErrors = errorIndices.map((i) => errors[i]);
|
|
3827
|
+
const errorType = categorizeError(stepErrors[0]);
|
|
3682
3828
|
const midPoint = Math.ceil(errorIndices.length / 2);
|
|
3683
3829
|
const batches = [
|
|
3684
3830
|
errorIndices.slice(0, midPoint),
|
|
@@ -3691,7 +3837,8 @@ async function createFixPlan(schema, errors, config) {
|
|
|
3691
3837
|
orbitalIndex,
|
|
3692
3838
|
errorIndices: batch,
|
|
3693
3839
|
provider: batchIndex === 0 ? "deepseek" : "qwen",
|
|
3694
|
-
dependencies: []
|
|
3840
|
+
dependencies: [],
|
|
3841
|
+
errorType
|
|
3695
3842
|
});
|
|
3696
3843
|
});
|
|
3697
3844
|
}
|
|
@@ -3716,13 +3863,14 @@ async function createFixPlan(schema, errors, config) {
|
|
|
3716
3863
|
console.log(`[Fixing] Plan created in ${Date.now() - planStart}ms`);
|
|
3717
3864
|
console.log(`[Fixing] Strategy: ${parallelizationStrategy}`);
|
|
3718
3865
|
console.log(`[Fixing] Steps: ${executionOrder.length}`);
|
|
3866
|
+
console.log(`[Fixing] Error types: ${[...new Set(executionOrder.map((s) => s.errorType))].join(", ")}`);
|
|
3719
3867
|
}
|
|
3720
3868
|
return plan;
|
|
3721
3869
|
}
|
|
3722
3870
|
async function executeFixStep(schema, step, errors, config) {
|
|
3723
3871
|
const orbital = schema.orbitals[step.orbitalIndex];
|
|
3724
3872
|
if (!orbital) {
|
|
3725
|
-
return { success: false, updatedOrbital: null };
|
|
3873
|
+
return { success: false, updatedOrbital: null, fixed: false };
|
|
3726
3874
|
}
|
|
3727
3875
|
const client = step.provider === "deepseek" ? new LLMClient({
|
|
3728
3876
|
provider: "deepseek",
|
|
@@ -3732,58 +3880,30 @@ async function executeFixStep(schema, step, errors, config) {
|
|
|
3732
3880
|
model: "qwen/qwen3.5-397b-a17b"
|
|
3733
3881
|
});
|
|
3734
3882
|
const stepErrors = step.errorIndices.map((i) => errors[i]);
|
|
3735
|
-
const
|
|
3736
|
-
const
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
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
|
|
3883
|
+
const errorGuidance = getErrorSpecificGuidance(stepErrors);
|
|
3884
|
+
const skillContext = config.skillContent || "";
|
|
3885
|
+
const systemPrompt = `You are an expert at fixing OrbitalSchema validation errors.
|
|
3886
|
+
${skillContext ? "\n" + skillContext.slice(0, 2e3) + "\n" : ""}
|
|
3887
|
+
${errorGuidance}
|
|
3888
|
+
|
|
3889
|
+
CRITICAL RULES:
|
|
3890
|
+
1. Preserve ALL valid content - only fix the errors
|
|
3891
|
+
2. Return the COMPLETE orbital with all fields (entity, traits, pages)
|
|
3892
|
+
3. Ensure the entity field is present with proper name, collection, and fields
|
|
3893
|
+
4. Use valid binding formats: @entity.field, @payload.field, @state.field
|
|
3771
3894
|
|
|
3772
3895
|
Return ONLY the fixed orbital as valid JSON.`;
|
|
3773
|
-
const userPrompt = `Fix these
|
|
3896
|
+
const userPrompt = `Fix these errors in orbital "${orbital.name}":
|
|
3774
3897
|
|
|
3775
|
-
ERRORS:
|
|
3776
|
-
${stepErrors.map((e) => {
|
|
3777
|
-
const path8 = Array.isArray(e.path) ? e.path.join(".") : e.path;
|
|
3778
|
-
return `- Path: ${path8}
|
|
3898
|
+
ERRORS TO FIX:
|
|
3899
|
+
${stepErrors.map((e) => `- Path: ${Array.isArray(e.path) ? e.path.join(".") : e.path}
|
|
3779
3900
|
Code: ${e.code}
|
|
3780
|
-
Message: ${e.message}
|
|
3781
|
-
}).join("\n")}
|
|
3901
|
+
Message: ${e.message}`).join("\n")}
|
|
3782
3902
|
|
|
3783
3903
|
CURRENT ORBITAL (JSON):
|
|
3784
3904
|
${JSON.stringify(orbital, null, 2)}
|
|
3785
3905
|
|
|
3786
|
-
Return the COMPLETE fixed orbital as JSON
|
|
3906
|
+
Return the COMPLETE fixed orbital as JSON. Include all fields (entity, traits, pages).`;
|
|
3787
3907
|
try {
|
|
3788
3908
|
const result = await client.call({
|
|
3789
3909
|
systemPrompt,
|
|
@@ -3791,14 +3911,27 @@ Return the COMPLETE fixed orbital as JSON with all fields (entity, traits, pages
|
|
|
3791
3911
|
maxTokens: 8192,
|
|
3792
3912
|
skipSchemaValidation: true
|
|
3793
3913
|
});
|
|
3914
|
+
const fixedOrbital = result;
|
|
3915
|
+
const hasEntity = fixedOrbital.entity && typeof fixedOrbital.entity === "object";
|
|
3916
|
+
const hasName = typeof fixedOrbital.name === "string";
|
|
3917
|
+
const hasTraits = Array.isArray(fixedOrbital.traits);
|
|
3918
|
+
const isValid = Boolean(hasEntity && hasName && hasTraits);
|
|
3919
|
+
if (!isValid && config.verbose) {
|
|
3920
|
+
console.log(`[Fixing] Fix validation failed: entity=${hasEntity}, name=${hasName}, traits=${hasTraits}`);
|
|
3921
|
+
}
|
|
3794
3922
|
return {
|
|
3795
|
-
success:
|
|
3796
|
-
updatedOrbital: result
|
|
3923
|
+
success: isValid,
|
|
3924
|
+
updatedOrbital: result,
|
|
3925
|
+
fixed: isValid
|
|
3797
3926
|
};
|
|
3798
3927
|
} catch (error) {
|
|
3928
|
+
if (config.verbose) {
|
|
3929
|
+
console.log(`[Fixing] Fix execution failed: ${error instanceof Error ? error.message : "Unknown"}`);
|
|
3930
|
+
}
|
|
3799
3931
|
return {
|
|
3800
3932
|
success: false,
|
|
3801
|
-
updatedOrbital: null
|
|
3933
|
+
updatedOrbital: null,
|
|
3934
|
+
fixed: false
|
|
3802
3935
|
};
|
|
3803
3936
|
}
|
|
3804
3937
|
}
|
|
@@ -3816,22 +3949,22 @@ async function executeFixPlan(schema, plan, errors, config) {
|
|
|
3816
3949
|
Promise.all(qwenSteps.map((step) => executeFixStep(schema, step, errors, config)))
|
|
3817
3950
|
]);
|
|
3818
3951
|
deepseekSteps.forEach((step, i) => {
|
|
3819
|
-
if (deepseekResults[i].success) {
|
|
3952
|
+
if (deepseekResults[i].success && deepseekResults[i].fixed) {
|
|
3820
3953
|
updatedSchema.orbitals[step.orbitalIndex] = deepseekResults[i].updatedOrbital;
|
|
3821
3954
|
}
|
|
3822
3955
|
});
|
|
3823
3956
|
qwenSteps.forEach((step, i) => {
|
|
3824
|
-
if (qwenResults[i].success) {
|
|
3957
|
+
if (qwenResults[i].success && qwenResults[i].fixed) {
|
|
3825
3958
|
updatedSchema.orbitals[step.orbitalIndex] = qwenResults[i].updatedOrbital;
|
|
3826
3959
|
}
|
|
3827
3960
|
});
|
|
3828
3961
|
} else {
|
|
3829
3962
|
for (const step of plan.executionOrder) {
|
|
3830
3963
|
if (config.verbose) {
|
|
3831
|
-
console.log(`[Fixing] Executing: ${step.description}`);
|
|
3964
|
+
console.log(`[Fixing] Executing: ${step.description} (${step.errorType})`);
|
|
3832
3965
|
}
|
|
3833
3966
|
const result = await executeFixStep(schema, step, errors, config);
|
|
3834
|
-
if (result.success) {
|
|
3967
|
+
if (result.success && result.fixed) {
|
|
3835
3968
|
updatedSchema.orbitals[step.orbitalIndex] = result.updatedOrbital;
|
|
3836
3969
|
}
|
|
3837
3970
|
}
|
|
@@ -3876,10 +4009,10 @@ function validateSchema(schema) {
|
|
|
3876
4009
|
}
|
|
3877
4010
|
}
|
|
3878
4011
|
}
|
|
3879
|
-
async function
|
|
4012
|
+
async function orchestrateFixingV2(schema, config = {}) {
|
|
3880
4013
|
const totalStart = Date.now();
|
|
3881
4014
|
if (config.verbose) {
|
|
3882
|
-
console.log("[Fixing] Starting Plan-Then-Execute fixing workflow");
|
|
4015
|
+
console.log("[Fixing V2] Starting enhanced Plan-Then-Execute fixing workflow");
|
|
3883
4016
|
}
|
|
3884
4017
|
const initialValidation = validateSchema(schema);
|
|
3885
4018
|
if (initialValidation.valid) {
|
|
@@ -3902,6 +4035,12 @@ async function orchestrateFixing(schema, config = {}) {
|
|
|
3902
4035
|
}
|
|
3903
4036
|
};
|
|
3904
4037
|
}
|
|
4038
|
+
if (config.verbose) {
|
|
4039
|
+
console.log(`[Fixing V2] Found ${initialValidation.errors.length} errors to fix`);
|
|
4040
|
+
initialValidation.errors.forEach((e) => {
|
|
4041
|
+
console.log(` - ${e.code}: ${e.message}`);
|
|
4042
|
+
});
|
|
4043
|
+
}
|
|
3905
4044
|
const planStart = Date.now();
|
|
3906
4045
|
const plan = await createFixPlan(schema, initialValidation.errors, config);
|
|
3907
4046
|
const planMs = Date.now() - planStart;
|
|
@@ -3909,17 +4048,21 @@ async function orchestrateFixing(schema, config = {}) {
|
|
|
3909
4048
|
let fixedSchema = await executeFixPlan(schema, plan, initialValidation.errors, config);
|
|
3910
4049
|
const executeMs = Date.now() - executeStart;
|
|
3911
4050
|
const verifyStart = Date.now();
|
|
3912
|
-
|
|
4051
|
+
let finalValidation = validateSchema(fixedSchema);
|
|
3913
4052
|
const verifyMs = Date.now() - verifyStart;
|
|
3914
4053
|
let retries = 0;
|
|
3915
4054
|
const maxRetries = config.maxRetries || 2;
|
|
3916
4055
|
while (!finalValidation.valid && retries < maxRetries) {
|
|
3917
4056
|
if (config.verbose) {
|
|
3918
|
-
console.log(`[Fixing] Retrying (${retries + 1}/${maxRetries})...`);
|
|
4057
|
+
console.log(`[Fixing V2] Retrying (${retries + 1}/${maxRetries})...`);
|
|
4058
|
+
console.log(`[Fixing V2] Remaining errors: ${finalValidation.errors.length}`);
|
|
3919
4059
|
}
|
|
3920
4060
|
const retryPlan = await createFixPlan(fixedSchema, finalValidation.errors, config);
|
|
3921
4061
|
fixedSchema = await executeFixPlan(fixedSchema, retryPlan, finalValidation.errors, config);
|
|
3922
4062
|
const retryValidation = validateSchema(fixedSchema);
|
|
4063
|
+
if (config.verbose) {
|
|
4064
|
+
console.log(`[Fixing V2] After retry: ${retryValidation.errors.length} errors remaining`);
|
|
4065
|
+
}
|
|
3923
4066
|
if (retryValidation.valid || retryValidation.errors.length < finalValidation.errors.length) {
|
|
3924
4067
|
finalValidation.errors = retryValidation.errors;
|
|
3925
4068
|
finalValidation.valid = retryValidation.valid;
|
|
@@ -3928,11 +4071,11 @@ async function orchestrateFixing(schema, config = {}) {
|
|
|
3928
4071
|
}
|
|
3929
4072
|
const totalMs = Date.now() - totalStart;
|
|
3930
4073
|
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"}`);
|
|
4074
|
+
console.log("[Fixing V2] === Summary ===");
|
|
4075
|
+
console.log(`[Fixing V2] Plan: ${planMs}ms, Execute: ${executeMs}ms, Verify: ${verifyMs}ms`);
|
|
4076
|
+
console.log(`[Fixing V2] Total: ${totalMs}ms`);
|
|
4077
|
+
console.log(`[Fixing V2] Errors: ${initialValidation.errors.length} \u2192 ${finalValidation.errors.length}`);
|
|
4078
|
+
console.log(`[Fixing V2] Success: ${finalValidation.valid ? "YES" : "PARTIAL"}`);
|
|
3936
4079
|
}
|
|
3937
4080
|
return {
|
|
3938
4081
|
success: finalValidation.valid,
|
|
@@ -3979,9 +4122,25 @@ function createOrchestratedGenerationTool(options) {
|
|
|
3979
4122
|
version: "1.0.0",
|
|
3980
4123
|
orbitals: result.orbitals
|
|
3981
4124
|
};
|
|
4125
|
+
if (options.workDir) {
|
|
4126
|
+
const schemaPath = path.join(options.workDir, "schema.orb");
|
|
4127
|
+
fs3.writeFileSync(schemaPath, JSON.stringify(schema, null, 2));
|
|
4128
|
+
const orbitalsDir = path.join(options.workDir, ".orbitals");
|
|
4129
|
+
fs3.mkdirSync(orbitalsDir, { recursive: true });
|
|
4130
|
+
for (const orbital of result.orbitals) {
|
|
4131
|
+
const name = ("name" in orbital ? String(orbital.name) : "unknown").replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
4132
|
+
fs3.writeFileSync(
|
|
4133
|
+
path.join(orbitalsDir, `${name}.json`),
|
|
4134
|
+
JSON.stringify(orbital, null, 2)
|
|
4135
|
+
);
|
|
4136
|
+
}
|
|
4137
|
+
}
|
|
4138
|
+
const summary = compactSchema(schema);
|
|
3982
4139
|
return {
|
|
3983
4140
|
success: true,
|
|
3984
|
-
|
|
4141
|
+
summary,
|
|
4142
|
+
orbitalCount: result.orbitals.length,
|
|
4143
|
+
schemaPath: options.workDir ? path.join(options.workDir, "schema.orb") : void 0,
|
|
3985
4144
|
complexity: result.complexity,
|
|
3986
4145
|
provider: result.provider,
|
|
3987
4146
|
timing: result.timing
|
|
@@ -3999,16 +4158,9 @@ function createOrchestratedGenerationTool(options) {
|
|
|
3999
4158
|
},
|
|
4000
4159
|
{
|
|
4001
4160
|
name: "generate_schema_orchestrated",
|
|
4002
|
-
description: `Generate an OrbitalSchema
|
|
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.`,
|
|
4161
|
+
description: `Generate an OrbitalSchema with automatic complexity-based provider routing.`,
|
|
4010
4162
|
schema: z.object({
|
|
4011
|
-
prompt: z.string().describe("
|
|
4163
|
+
prompt: z.string().describe("App description prompt")
|
|
4012
4164
|
})
|
|
4013
4165
|
}
|
|
4014
4166
|
);
|
|
@@ -4083,7 +4235,7 @@ function createOrchestratedFixingTool(options) {
|
|
|
4083
4235
|
console.log(`[OrchestratedFixing] Found ${initialValidation.errors.length} errors to fix`);
|
|
4084
4236
|
}
|
|
4085
4237
|
try {
|
|
4086
|
-
const result = await
|
|
4238
|
+
const result = await orchestrateFixingV2(typedSchema, {
|
|
4087
4239
|
maxRetries,
|
|
4088
4240
|
verbose,
|
|
4089
4241
|
skillContent
|
|
@@ -5342,7 +5494,19 @@ ${skillContents}`;
|
|
|
5342
5494
|
}
|
|
5343
5495
|
}
|
|
5344
5496
|
const memoryContext = buildMemoryContext(userPreferences, projectContext);
|
|
5345
|
-
const
|
|
5497
|
+
const useOrchestration = options.useOrchestration ?? false;
|
|
5498
|
+
const systemPrompt = useOrchestration ? `You are an orbital schema generator. You MUST use tools to complete your task. Do NOT respond with text \u2014 ONLY call tools.
|
|
5499
|
+
|
|
5500
|
+
Your workflow has exactly 2 steps:
|
|
5501
|
+
|
|
5502
|
+
STEP 1: Call the "orchestrated_generation" tool with the user's full request as the "prompt" parameter.
|
|
5503
|
+
STEP 2: After orchestrated_generation completes, call the "finish_task" tool to assemble and return the final schema.
|
|
5504
|
+
|
|
5505
|
+
IMPORTANT:
|
|
5506
|
+
- You MUST call orchestrated_generation as your FIRST action. Do not plan, analyze, or discuss \u2014 just call the tool.
|
|
5507
|
+
- Do NOT call generate_orbital directly \u2014 orchestrated_generation handles that internally.
|
|
5508
|
+
- Do NOT generate any orbital JSON yourself \u2014 the tools handle all generation.
|
|
5509
|
+
- After calling orchestrated_generation, ALWAYS call finish_task to finalize.` : [
|
|
5346
5510
|
BASE_SYSTEM_PROMPT,
|
|
5347
5511
|
"\n## Skill Instructions\n\n" + skillInstructions,
|
|
5348
5512
|
references ? "\n## Reference Documentation\n\n" + references : "",
|
|
@@ -5364,14 +5528,14 @@ ${skillContents}`;
|
|
|
5364
5528
|
const isOrbitalBatchSkill = ORBITAL_BATCH_SKILLS.includes(primarySkill.name);
|
|
5365
5529
|
const isLeanSkill = LEAN_SKILLS.includes(primarySkill.name);
|
|
5366
5530
|
const needsChunkingTools = ORBITAL_SKILLS.includes(primarySkill.name);
|
|
5367
|
-
const useOrchestration = options.useOrchestration ?? false;
|
|
5368
5531
|
let orchestratedGenerationTool;
|
|
5369
5532
|
let orchestratedFixingTool;
|
|
5370
5533
|
if (useOrchestration) {
|
|
5371
5534
|
if (isOrbitalSkill) {
|
|
5372
5535
|
orchestratedGenerationTool = createOrchestratedGenerationTool({
|
|
5373
5536
|
skillContent: primarySkill.content,
|
|
5374
|
-
verbose
|
|
5537
|
+
verbose,
|
|
5538
|
+
workDir
|
|
5375
5539
|
});
|
|
5376
5540
|
if (verbose) {
|
|
5377
5541
|
console.log(`[SkillAgent] Orchestrated generation enabled for ${primarySkill.name}`);
|
|
@@ -5399,7 +5563,8 @@ ${skillContents}`;
|
|
|
5399
5563
|
const orbitalResult = createOrbitalSubagentTool({
|
|
5400
5564
|
requirements: options.requirements,
|
|
5401
5565
|
provider: subagentProvider,
|
|
5402
|
-
model: subagentModel
|
|
5566
|
+
model: subagentModel,
|
|
5567
|
+
workDir
|
|
5403
5568
|
});
|
|
5404
5569
|
orbitalTool = orbitalResult.tool;
|
|
5405
5570
|
setOrbitalEventCallback = orbitalResult.setEventCallback;
|
|
@@ -5597,2061 +5762,6 @@ function getBudgetWarningMessage(eventCount, budget) {
|
|
|
5597
5762
|
return null;
|
|
5598
5763
|
}
|
|
5599
5764
|
|
|
5600
|
-
// src/agent/react-reflection.ts
|
|
5601
|
-
var ReActEngine = class {
|
|
5602
|
-
constructor(options = {}) {
|
|
5603
|
-
this.sessions = /* @__PURE__ */ new Map();
|
|
5604
|
-
this.options = {
|
|
5605
|
-
maxIterations: options.maxIterations ?? 10,
|
|
5606
|
-
enableReflection: options.enableReflection ?? true,
|
|
5607
|
-
enableAutoCorrect: options.enableAutoCorrect ?? true,
|
|
5608
|
-
memoryManager: options.memoryManager,
|
|
5609
|
-
onStep: options.onStep ?? (() => {
|
|
5610
|
-
}),
|
|
5611
|
-
onError: options.onError ?? (() => {
|
|
5612
|
-
})
|
|
5613
|
-
};
|
|
5614
|
-
}
|
|
5615
|
-
/**
|
|
5616
|
-
* Start a new ReAct session
|
|
5617
|
-
*/
|
|
5618
|
-
startSession(userRequest) {
|
|
5619
|
-
const sessionId = `react_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
5620
|
-
const session = {
|
|
5621
|
-
sessionId,
|
|
5622
|
-
userRequest,
|
|
5623
|
-
currentStep: 0,
|
|
5624
|
-
steps: [],
|
|
5625
|
-
maxIterations: this.options.maxIterations,
|
|
5626
|
-
state: "REASONING"
|
|
5627
|
-
};
|
|
5628
|
-
this.sessions.set(sessionId, session);
|
|
5629
|
-
return session;
|
|
5630
|
-
}
|
|
5631
|
-
/**
|
|
5632
|
-
* Execute REASON step
|
|
5633
|
-
*/
|
|
5634
|
-
async reason(sessionId, context) {
|
|
5635
|
-
const session = this.getSession(sessionId);
|
|
5636
|
-
const thought = await this.generateThought(context);
|
|
5637
|
-
const step = {
|
|
5638
|
-
stepNumber: ++session.currentStep,
|
|
5639
|
-
state: "REASONING",
|
|
5640
|
-
thought,
|
|
5641
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
5642
|
-
};
|
|
5643
|
-
session.steps.push(step);
|
|
5644
|
-
session.state = "ACTING";
|
|
5645
|
-
this.options.onStep(step);
|
|
5646
|
-
return step;
|
|
5647
|
-
}
|
|
5648
|
-
/**
|
|
5649
|
-
* Execute ACT step
|
|
5650
|
-
*/
|
|
5651
|
-
async act(sessionId, action, actionInput) {
|
|
5652
|
-
const session = this.getSession(sessionId);
|
|
5653
|
-
const previousStep = session.steps[session.steps.length - 1];
|
|
5654
|
-
const step = {
|
|
5655
|
-
stepNumber: ++session.currentStep,
|
|
5656
|
-
state: "ACTING",
|
|
5657
|
-
thought: previousStep?.thought ?? "",
|
|
5658
|
-
action,
|
|
5659
|
-
actionInput,
|
|
5660
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
5661
|
-
};
|
|
5662
|
-
session.steps.push(step);
|
|
5663
|
-
session.state = "OBSERVING";
|
|
5664
|
-
this.options.onStep(step);
|
|
5665
|
-
return step;
|
|
5666
|
-
}
|
|
5667
|
-
/**
|
|
5668
|
-
* Execute OBSERVE step
|
|
5669
|
-
*/
|
|
5670
|
-
async observe(sessionId, observation) {
|
|
5671
|
-
const session = this.getSession(sessionId);
|
|
5672
|
-
const previousStep = session.steps[session.steps.length - 1];
|
|
5673
|
-
const step = {
|
|
5674
|
-
stepNumber: ++session.currentStep,
|
|
5675
|
-
state: "OBSERVING",
|
|
5676
|
-
thought: previousStep?.thought ?? "",
|
|
5677
|
-
action: previousStep?.action,
|
|
5678
|
-
actionInput: previousStep?.actionInput,
|
|
5679
|
-
observation,
|
|
5680
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
5681
|
-
};
|
|
5682
|
-
session.steps.push(step);
|
|
5683
|
-
session.state = this.options.enableReflection ? "REFLECTING" : "COMPLETE";
|
|
5684
|
-
this.options.onStep(step);
|
|
5685
|
-
return step;
|
|
5686
|
-
}
|
|
5687
|
-
/**
|
|
5688
|
-
* Execute REFLECT step
|
|
5689
|
-
*/
|
|
5690
|
-
async reflect(sessionId, result) {
|
|
5691
|
-
const session = this.getSession(sessionId);
|
|
5692
|
-
const previousStep = session.steps[session.steps.length - 1];
|
|
5693
|
-
const reflection = await this.performReflection(session, result);
|
|
5694
|
-
const step = {
|
|
5695
|
-
stepNumber: ++session.currentStep,
|
|
5696
|
-
state: "REFLECTING",
|
|
5697
|
-
thought: previousStep?.thought ?? "",
|
|
5698
|
-
action: previousStep?.action,
|
|
5699
|
-
actionInput: previousStep?.actionInput,
|
|
5700
|
-
observation: previousStep?.observation,
|
|
5701
|
-
reflection: reflection.notes,
|
|
5702
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
5703
|
-
};
|
|
5704
|
-
session.steps.push(step);
|
|
5705
|
-
if (reflection.shouldCorrect && this.options.enableAutoCorrect) {
|
|
5706
|
-
session.state = "CORRECTING";
|
|
5707
|
-
} else {
|
|
5708
|
-
session.state = "COMPLETE";
|
|
5709
|
-
}
|
|
5710
|
-
this.options.onStep(step);
|
|
5711
|
-
return { step, reflection };
|
|
5712
|
-
}
|
|
5713
|
-
/**
|
|
5714
|
-
* Execute CORRECT step (auto-correction)
|
|
5715
|
-
*/
|
|
5716
|
-
async correct(sessionId, correctionAction, correctionInput) {
|
|
5717
|
-
const session = this.getSession(sessionId);
|
|
5718
|
-
const previousStep = session.steps[session.steps.length - 1];
|
|
5719
|
-
const step = {
|
|
5720
|
-
stepNumber: ++session.currentStep,
|
|
5721
|
-
state: "CORRECTING",
|
|
5722
|
-
thought: `Correcting: ${previousStep?.reflection}`,
|
|
5723
|
-
action: correctionAction,
|
|
5724
|
-
actionInput: correctionInput,
|
|
5725
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
5726
|
-
};
|
|
5727
|
-
session.steps.push(step);
|
|
5728
|
-
session.state = "OBSERVING";
|
|
5729
|
-
this.options.onStep(step);
|
|
5730
|
-
if (this.options.memoryManager) {
|
|
5731
|
-
await this.storeCorrection(session, step);
|
|
5732
|
-
}
|
|
5733
|
-
return step;
|
|
5734
|
-
}
|
|
5735
|
-
/**
|
|
5736
|
-
* Handle errors with context preservation
|
|
5737
|
-
*/
|
|
5738
|
-
async handleError(sessionId, error, context) {
|
|
5739
|
-
const session = this.getSession(sessionId);
|
|
5740
|
-
const step = {
|
|
5741
|
-
stepNumber: ++session.currentStep,
|
|
5742
|
-
state: "REFLECTING",
|
|
5743
|
-
thought: "",
|
|
5744
|
-
error: error.message,
|
|
5745
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
5746
|
-
};
|
|
5747
|
-
session.steps.push(step);
|
|
5748
|
-
this.options.onError(error, step);
|
|
5749
|
-
if (this.options.memoryManager) {
|
|
5750
|
-
await this.storeError(session, error, context);
|
|
5751
|
-
}
|
|
5752
|
-
return step;
|
|
5753
|
-
}
|
|
5754
|
-
/**
|
|
5755
|
-
* Get session by ID
|
|
5756
|
-
*/
|
|
5757
|
-
getSession(sessionId) {
|
|
5758
|
-
const session = this.sessions.get(sessionId);
|
|
5759
|
-
if (!session) {
|
|
5760
|
-
throw new Error(`Session not found: ${sessionId}`);
|
|
5761
|
-
}
|
|
5762
|
-
return session;
|
|
5763
|
-
}
|
|
5764
|
-
/**
|
|
5765
|
-
* Get reflection metrics
|
|
5766
|
-
*/
|
|
5767
|
-
getReflectionMetrics(sessionId) {
|
|
5768
|
-
const session = this.getSession(sessionId);
|
|
5769
|
-
const reflections = session.steps.filter((s) => s.state === "REFLECTING");
|
|
5770
|
-
const corrections = session.steps.filter((s) => s.state === "CORRECTING").length;
|
|
5771
|
-
const errors = session.steps.filter((s) => s.error).length;
|
|
5772
|
-
return {
|
|
5773
|
-
totalSteps: session.currentStep,
|
|
5774
|
-
corrections,
|
|
5775
|
-
errors,
|
|
5776
|
-
averageConfidence: reflections.length > 0 ? 0.8 : 0
|
|
5777
|
-
// Simplified
|
|
5778
|
-
};
|
|
5779
|
-
}
|
|
5780
|
-
// ============================================================================
|
|
5781
|
-
// Private Helpers
|
|
5782
|
-
// ============================================================================
|
|
5783
|
-
async generateThought(context) {
|
|
5784
|
-
return `I need to analyze the request: "${context.request}". Previous attempts: ${context.previousSteps?.length ?? 0}.`;
|
|
5785
|
-
}
|
|
5786
|
-
async performReflection(session, result) {
|
|
5787
|
-
const hasErrors = result === null || typeof result === "object" && result !== null && "error" in result;
|
|
5788
|
-
if (hasErrors) {
|
|
5789
|
-
return {
|
|
5790
|
-
shouldCorrect: true,
|
|
5791
|
-
correctionStrategy: "retry_with_validation",
|
|
5792
|
-
confidence: 0.3,
|
|
5793
|
-
notes: "Result contains errors, correction needed"
|
|
5794
|
-
};
|
|
5795
|
-
}
|
|
5796
|
-
if (session.currentStep >= session.maxIterations) {
|
|
5797
|
-
return {
|
|
5798
|
-
shouldCorrect: false,
|
|
5799
|
-
confidence: 0.9,
|
|
5800
|
-
notes: "Max iterations reached, completing task"
|
|
5801
|
-
};
|
|
5802
|
-
}
|
|
5803
|
-
return {
|
|
5804
|
-
shouldCorrect: false,
|
|
5805
|
-
confidence: 0.9,
|
|
5806
|
-
notes: "Result looks good"
|
|
5807
|
-
};
|
|
5808
|
-
}
|
|
5809
|
-
async storeCorrection(session, step) {
|
|
5810
|
-
if (!this.options.memoryManager) return;
|
|
5811
|
-
console.log(`[ReAct] Storing correction for session ${session.sessionId}`);
|
|
5812
|
-
}
|
|
5813
|
-
async storeError(session, error, context) {
|
|
5814
|
-
if (!this.options.memoryManager) return;
|
|
5815
|
-
console.log(`[ReAct] Storing error for session ${session.sessionId}: ${error.message}`);
|
|
5816
|
-
}
|
|
5817
|
-
};
|
|
5818
|
-
function createReActEngine(options) {
|
|
5819
|
-
return new ReActEngine(options);
|
|
5820
|
-
}
|
|
5821
|
-
|
|
5822
|
-
// src/agent/hitl-v2.ts
|
|
5823
|
-
var HITLv2Manager = class {
|
|
5824
|
-
constructor(options = {}) {
|
|
5825
|
-
this.pendingInterrupts = /* @__PURE__ */ new Map();
|
|
5826
|
-
this.responses = /* @__PURE__ */ new Map();
|
|
5827
|
-
this.checkpoints = /* @__PURE__ */ new Map();
|
|
5828
|
-
this.options = {
|
|
5829
|
-
defaultTimeoutMs: options.defaultTimeoutMs ?? 3e5,
|
|
5830
|
-
// 5 minutes
|
|
5831
|
-
memoryManager: options.memoryManager,
|
|
5832
|
-
onInterrupt: options.onInterrupt,
|
|
5833
|
-
onResponse: options.onResponse
|
|
5834
|
-
};
|
|
5835
|
-
}
|
|
5836
|
-
// ============================================================================
|
|
5837
|
-
// Interrupt Creation
|
|
5838
|
-
// ============================================================================
|
|
5839
|
-
/**
|
|
5840
|
-
* Create a confirmation interrupt
|
|
5841
|
-
*/
|
|
5842
|
-
async confirm(sessionId, question, options = {}) {
|
|
5843
|
-
const payload = {
|
|
5844
|
-
question,
|
|
5845
|
-
severity: options.severity ?? "info",
|
|
5846
|
-
defaultValue: options.defaultValue
|
|
5847
|
-
};
|
|
5848
|
-
const request = await this.createInterrupt(
|
|
5849
|
-
sessionId,
|
|
5850
|
-
"confirm",
|
|
5851
|
-
"Confirmation Required",
|
|
5852
|
-
question,
|
|
5853
|
-
payload,
|
|
5854
|
-
options.timeoutMs,
|
|
5855
|
-
options.context
|
|
5856
|
-
);
|
|
5857
|
-
return this.waitForResponse(request);
|
|
5858
|
-
}
|
|
5859
|
-
/**
|
|
5860
|
-
* Create an edit interrupt
|
|
5861
|
-
*/
|
|
5862
|
-
async edit(sessionId, content, options = {}) {
|
|
5863
|
-
const payload = {
|
|
5864
|
-
content,
|
|
5865
|
-
format: options.format ?? "text",
|
|
5866
|
-
schema: options.schema
|
|
5867
|
-
};
|
|
5868
|
-
const request = await this.createInterrupt(
|
|
5869
|
-
sessionId,
|
|
5870
|
-
"edit",
|
|
5871
|
-
options.title ?? "Edit Content",
|
|
5872
|
-
options.description ?? "Please review and edit the content",
|
|
5873
|
-
payload,
|
|
5874
|
-
options.timeoutMs,
|
|
5875
|
-
options.context
|
|
5876
|
-
);
|
|
5877
|
-
return this.waitForResponse(request);
|
|
5878
|
-
}
|
|
5879
|
-
/**
|
|
5880
|
-
* Create a selection interrupt
|
|
5881
|
-
*/
|
|
5882
|
-
async select(sessionId, options, config = {}) {
|
|
5883
|
-
const payload = {
|
|
5884
|
-
options,
|
|
5885
|
-
multiple: config.multiple
|
|
5886
|
-
};
|
|
5887
|
-
const request = await this.createInterrupt(
|
|
5888
|
-
sessionId,
|
|
5889
|
-
"select",
|
|
5890
|
-
config.title ?? "Make a Selection",
|
|
5891
|
-
config.description ?? "Please select an option",
|
|
5892
|
-
payload,
|
|
5893
|
-
config.timeoutMs,
|
|
5894
|
-
config.context
|
|
5895
|
-
);
|
|
5896
|
-
return this.waitForResponse(request);
|
|
5897
|
-
}
|
|
5898
|
-
/**
|
|
5899
|
-
* Create a text input interrupt
|
|
5900
|
-
*/
|
|
5901
|
-
async text(sessionId, options = {}) {
|
|
5902
|
-
const payload = {
|
|
5903
|
-
placeholder: options.placeholder,
|
|
5904
|
-
multiline: options.multiline,
|
|
5905
|
-
maxLength: options.maxLength
|
|
5906
|
-
};
|
|
5907
|
-
const request = await this.createInterrupt(
|
|
5908
|
-
sessionId,
|
|
5909
|
-
"text",
|
|
5910
|
-
options.title ?? "Input Required",
|
|
5911
|
-
options.description ?? "Please provide input",
|
|
5912
|
-
payload,
|
|
5913
|
-
options.timeoutMs,
|
|
5914
|
-
options.context
|
|
5915
|
-
);
|
|
5916
|
-
return this.waitForResponse(request);
|
|
5917
|
-
}
|
|
5918
|
-
// ============================================================================
|
|
5919
|
-
// Response Handling
|
|
5920
|
-
// ============================================================================
|
|
5921
|
-
/**
|
|
5922
|
-
* Submit a response to an interrupt
|
|
5923
|
-
*/
|
|
5924
|
-
async submitResponse(interruptId, response, userId) {
|
|
5925
|
-
const request = this.pendingInterrupts.get(interruptId);
|
|
5926
|
-
if (!request) {
|
|
5927
|
-
throw new Error(`Interrupt not found or expired: ${interruptId}`);
|
|
5928
|
-
}
|
|
5929
|
-
const responseRecord = {
|
|
5930
|
-
interruptId,
|
|
5931
|
-
response,
|
|
5932
|
-
respondedAt: /* @__PURE__ */ new Date(),
|
|
5933
|
-
userId
|
|
5934
|
-
};
|
|
5935
|
-
this.responses.set(interruptId, responseRecord);
|
|
5936
|
-
this.pendingInterrupts.delete(interruptId);
|
|
5937
|
-
if (this.options.memoryManager) {
|
|
5938
|
-
await this.storeInteraction(request, responseRecord);
|
|
5939
|
-
}
|
|
5940
|
-
this.options.onResponse?.(request, responseRecord);
|
|
5941
|
-
}
|
|
5942
|
-
/**
|
|
5943
|
-
* Cancel an interrupt
|
|
5944
|
-
*/
|
|
5945
|
-
cancelInterrupt(interruptId, reason) {
|
|
5946
|
-
const request = this.pendingInterrupts.get(interruptId);
|
|
5947
|
-
if (!request) return;
|
|
5948
|
-
this.pendingInterrupts.delete(interruptId);
|
|
5949
|
-
console.log(`[HITLv2] Interrupt ${interruptId} cancelled: ${reason ?? "No reason"}`);
|
|
5950
|
-
}
|
|
5951
|
-
// ============================================================================
|
|
5952
|
-
// Time-Travel Debugging
|
|
5953
|
-
// ============================================================================
|
|
5954
|
-
/**
|
|
5955
|
-
* Save a checkpoint for time-travel
|
|
5956
|
-
*/
|
|
5957
|
-
saveCheckpoint(checkpointId, state) {
|
|
5958
|
-
this.checkpoints.set(checkpointId, JSON.parse(JSON.stringify(state)));
|
|
5959
|
-
}
|
|
5960
|
-
/**
|
|
5961
|
-
* Restore a checkpoint
|
|
5962
|
-
*/
|
|
5963
|
-
restoreCheckpoint(checkpointId) {
|
|
5964
|
-
const checkpoint = this.checkpoints.get(checkpointId);
|
|
5965
|
-
if (!checkpoint) return null;
|
|
5966
|
-
return JSON.parse(JSON.stringify(checkpoint));
|
|
5967
|
-
}
|
|
5968
|
-
/**
|
|
5969
|
-
* List available checkpoints
|
|
5970
|
-
*/
|
|
5971
|
-
listCheckpoints() {
|
|
5972
|
-
return Array.from(this.checkpoints.keys());
|
|
5973
|
-
}
|
|
5974
|
-
/**
|
|
5975
|
-
* Rewind to checkpoint and continue
|
|
5976
|
-
*/
|
|
5977
|
-
async rewindToCheckpoint(checkpointId, sessionId, modifyFn) {
|
|
5978
|
-
let state = this.restoreCheckpoint(checkpointId);
|
|
5979
|
-
if (!state) return null;
|
|
5980
|
-
if (modifyFn) {
|
|
5981
|
-
state = modifyFn(state);
|
|
5982
|
-
}
|
|
5983
|
-
console.log(`[HITLv2] Session ${sessionId} rewound to checkpoint ${checkpointId}`);
|
|
5984
|
-
return state;
|
|
5985
|
-
}
|
|
5986
|
-
// ============================================================================
|
|
5987
|
-
// Analytics
|
|
5988
|
-
// ============================================================================
|
|
5989
|
-
/**
|
|
5990
|
-
* Get interrupt statistics
|
|
5991
|
-
*/
|
|
5992
|
-
getStats() {
|
|
5993
|
-
const responses = Array.from(this.responses.values());
|
|
5994
|
-
const totalResponseTime = responses.reduce((sum, r) => {
|
|
5995
|
-
const request = this.pendingInterrupts.get(r.interruptId);
|
|
5996
|
-
if (!request) return sum;
|
|
5997
|
-
return sum + (r.respondedAt.getTime() - request.createdAt.getTime());
|
|
5998
|
-
}, 0);
|
|
5999
|
-
return {
|
|
6000
|
-
pendingCount: this.pendingInterrupts.size,
|
|
6001
|
-
totalHandled: this.responses.size,
|
|
6002
|
-
checkpointsCount: this.checkpoints.size,
|
|
6003
|
-
averageResponseTimeMs: responses.length > 0 ? totalResponseTime / responses.length : 0
|
|
6004
|
-
};
|
|
6005
|
-
}
|
|
6006
|
-
/**
|
|
6007
|
-
* Get pending interrupts for a session
|
|
6008
|
-
*/
|
|
6009
|
-
getPendingForSession(sessionId) {
|
|
6010
|
-
return Array.from(this.pendingInterrupts.values()).filter((req) => req.sessionId === sessionId);
|
|
6011
|
-
}
|
|
6012
|
-
// ============================================================================
|
|
6013
|
-
// Private Helpers
|
|
6014
|
-
// ============================================================================
|
|
6015
|
-
async createInterrupt(sessionId, type, title, description, payload, timeoutMs, partialContext) {
|
|
6016
|
-
const interruptId = `int_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
6017
|
-
const checkpointId = `chk_${interruptId}`;
|
|
6018
|
-
const request = {
|
|
6019
|
-
interruptId,
|
|
6020
|
-
sessionId,
|
|
6021
|
-
type,
|
|
6022
|
-
title,
|
|
6023
|
-
description,
|
|
6024
|
-
context: {
|
|
6025
|
-
checkpointId,
|
|
6026
|
-
currentState: partialContext?.currentState ?? "unknown",
|
|
6027
|
-
previousActions: partialContext?.previousActions ?? [],
|
|
6028
|
-
relevantMemory: partialContext?.relevantMemory
|
|
6029
|
-
},
|
|
6030
|
-
payload,
|
|
6031
|
-
timeoutMs: timeoutMs ?? this.options.defaultTimeoutMs,
|
|
6032
|
-
createdAt: /* @__PURE__ */ new Date()
|
|
6033
|
-
};
|
|
6034
|
-
this.pendingInterrupts.set(interruptId, request);
|
|
6035
|
-
setTimeout(() => {
|
|
6036
|
-
if (this.pendingInterrupts.has(interruptId)) {
|
|
6037
|
-
this.cancelInterrupt(interruptId, "Timeout");
|
|
6038
|
-
}
|
|
6039
|
-
}, request.timeoutMs);
|
|
6040
|
-
this.options.onInterrupt?.(request);
|
|
6041
|
-
return request;
|
|
6042
|
-
}
|
|
6043
|
-
async waitForResponse(request) {
|
|
6044
|
-
return new Promise((resolve2, reject) => {
|
|
6045
|
-
const checkInterval = setInterval(() => {
|
|
6046
|
-
const response = this.responses.get(request.interruptId);
|
|
6047
|
-
if (response) {
|
|
6048
|
-
clearInterval(checkInterval);
|
|
6049
|
-
resolve2(response.response);
|
|
6050
|
-
this.responses.delete(request.interruptId);
|
|
6051
|
-
}
|
|
6052
|
-
if (!this.pendingInterrupts.has(request.interruptId)) {
|
|
6053
|
-
clearInterval(checkInterval);
|
|
6054
|
-
reject(new Error("Interrupt cancelled or expired"));
|
|
6055
|
-
}
|
|
6056
|
-
}, 100);
|
|
6057
|
-
});
|
|
6058
|
-
}
|
|
6059
|
-
async storeInteraction(request, response) {
|
|
6060
|
-
if (!this.options.memoryManager) return;
|
|
6061
|
-
console.log(`[HITLv2] Storing interaction: ${request.type} \u2192 ${JSON.stringify(response.response).slice(0, 50)}`);
|
|
6062
|
-
}
|
|
6063
|
-
};
|
|
6064
|
-
function createHITLv2Manager(options) {
|
|
6065
|
-
return new HITLv2Manager(options);
|
|
6066
|
-
}
|
|
6067
|
-
|
|
6068
|
-
// src/memory/agentic-search.ts
|
|
6069
|
-
var AgenticSearchEngine = class {
|
|
6070
|
-
constructor(memoryManager) {
|
|
6071
|
-
this.memoryManager = memoryManager;
|
|
6072
|
-
}
|
|
6073
|
-
/**
|
|
6074
|
-
* Perform agentic search through memory
|
|
6075
|
-
*/
|
|
6076
|
-
async search(params) {
|
|
6077
|
-
const startTime = Date.now();
|
|
6078
|
-
const strategy = params.strategy ?? "hybrid";
|
|
6079
|
-
const depth = params.depth ?? 3;
|
|
6080
|
-
const limit = params.limit ?? 10;
|
|
6081
|
-
let results = [];
|
|
6082
|
-
switch (strategy) {
|
|
6083
|
-
case "temporal":
|
|
6084
|
-
results = await this.temporalSearch(params, depth, limit);
|
|
6085
|
-
break;
|
|
6086
|
-
case "semantic":
|
|
6087
|
-
results = await this.semanticSearch(params, depth, limit);
|
|
6088
|
-
break;
|
|
6089
|
-
case "pattern":
|
|
6090
|
-
results = await this.patternSearch(params, depth, limit);
|
|
6091
|
-
break;
|
|
6092
|
-
case "hybrid":
|
|
6093
|
-
default:
|
|
6094
|
-
results = await this.hybridSearch(params, depth, limit);
|
|
6095
|
-
break;
|
|
6096
|
-
}
|
|
6097
|
-
results.sort((a, b) => b.relevance - a.relevance);
|
|
6098
|
-
const insights = this.generateInsights(results, params.query);
|
|
6099
|
-
const duration = Date.now() - startTime;
|
|
6100
|
-
return {
|
|
6101
|
-
results: results.slice(0, limit),
|
|
6102
|
-
insights,
|
|
6103
|
-
metadata: {
|
|
6104
|
-
strategy,
|
|
6105
|
-
depth,
|
|
6106
|
-
duration,
|
|
6107
|
-
totalResults: results.length
|
|
6108
|
-
}
|
|
6109
|
-
};
|
|
6110
|
-
}
|
|
6111
|
-
// ============================================================================
|
|
6112
|
-
// Search Strategies
|
|
6113
|
-
// ============================================================================
|
|
6114
|
-
/**
|
|
6115
|
-
* Temporal search - "What did I do last week?"
|
|
6116
|
-
* Navigates memory by time relationships
|
|
6117
|
-
*/
|
|
6118
|
-
async temporalSearch(params, _depth, limit) {
|
|
6119
|
-
const results = [];
|
|
6120
|
-
const isRecentQuery = /recent|last|latest|newest/i.test(params.query);
|
|
6121
|
-
/week|month|day|ago/i.test(params.query);
|
|
6122
|
-
const sessions = await this.memoryManager.getUserGenerationHistory(params.userId, limit * 2);
|
|
6123
|
-
for (const session of sessions) {
|
|
6124
|
-
let relevance = 0.5;
|
|
6125
|
-
let reasoning = "Recent generation session";
|
|
6126
|
-
if (isRecentQuery) {
|
|
6127
|
-
const daysAgo = (Date.now() - session.createdAt.getTime()) / (1e3 * 60 * 60 * 24);
|
|
6128
|
-
relevance = Math.max(0.1, 1 - daysAgo / 30);
|
|
6129
|
-
reasoning = `Created ${Math.round(daysAgo)} days ago`;
|
|
6130
|
-
}
|
|
6131
|
-
const sessionText = `${session.prompt} ${session.entities.join(" ")} ${session.patterns.join(" ")}`.toLowerCase();
|
|
6132
|
-
const queryTerms = params.query.toLowerCase().split(/\s+/);
|
|
6133
|
-
const termMatches = queryTerms.filter((term) => sessionText.includes(term)).length;
|
|
6134
|
-
relevance += termMatches * 0.1;
|
|
6135
|
-
if (relevance > 0.3) {
|
|
6136
|
-
results.push({
|
|
6137
|
-
type: "session",
|
|
6138
|
-
data: session,
|
|
6139
|
-
relevance: Math.min(1, relevance),
|
|
6140
|
-
reasoning,
|
|
6141
|
-
source: "generation_history",
|
|
6142
|
-
timestamp: session.createdAt
|
|
6143
|
-
});
|
|
6144
|
-
}
|
|
6145
|
-
}
|
|
6146
|
-
return results;
|
|
6147
|
-
}
|
|
6148
|
-
/**
|
|
6149
|
-
* Semantic search - "How did I handle user roles?"
|
|
6150
|
-
* Reasoning-based understanding of structure
|
|
6151
|
-
*/
|
|
6152
|
-
async semanticSearch(params, _depth, limit) {
|
|
6153
|
-
const results = [];
|
|
6154
|
-
const concepts = this.extractConcepts(params.query);
|
|
6155
|
-
const prefs = await this.memoryManager.getUserPreferences(params.userId);
|
|
6156
|
-
if (prefs) {
|
|
6157
|
-
let relevance = 0.3;
|
|
6158
|
-
const matchedConcepts = [];
|
|
6159
|
-
if (concepts.naming && prefs.namingConvention) {
|
|
6160
|
-
relevance += 0.2;
|
|
6161
|
-
matchedConcepts.push(`uses ${prefs.namingConvention}`);
|
|
6162
|
-
}
|
|
6163
|
-
if (concepts.patterns && prefs.preferredPatterns.length > 0) {
|
|
6164
|
-
const matched = prefs.preferredPatterns.filter(
|
|
6165
|
-
(p) => concepts.patterns?.some((cp) => p.toLowerCase().includes(cp.toLowerCase()))
|
|
6166
|
-
);
|
|
6167
|
-
relevance += matched.length * 0.1;
|
|
6168
|
-
matchedConcepts.push(`patterns: ${matched.join(", ")}`);
|
|
6169
|
-
}
|
|
6170
|
-
if (concepts.entities && prefs.commonEntities.length > 0) {
|
|
6171
|
-
const matched = prefs.commonEntities.filter(
|
|
6172
|
-
(e) => concepts.entities?.some((ce) => e.toLowerCase().includes(ce.toLowerCase()))
|
|
6173
|
-
);
|
|
6174
|
-
relevance += matched.length * 0.1;
|
|
6175
|
-
matchedConcepts.push(`entities: ${matched.join(", ")}`);
|
|
6176
|
-
}
|
|
6177
|
-
if (relevance > 0.4) {
|
|
6178
|
-
results.push({
|
|
6179
|
-
type: "preference",
|
|
6180
|
-
data: prefs,
|
|
6181
|
-
relevance: Math.min(1, relevance),
|
|
6182
|
-
reasoning: `User preferences match query concepts: ${matchedConcepts.join("; ")}`,
|
|
6183
|
-
source: "user_preferences",
|
|
6184
|
-
timestamp: prefs.learnedAt
|
|
6185
|
-
});
|
|
6186
|
-
}
|
|
6187
|
-
}
|
|
6188
|
-
if (params.appId) {
|
|
6189
|
-
const project = await this.memoryManager.getProjectContext(params.appId);
|
|
6190
|
-
if (project) {
|
|
6191
|
-
let relevance = 0.3;
|
|
6192
|
-
const projectText = `${project.projectName ?? ""} ${project.description ?? ""} ${project.existingEntities.join(" ")}`.toLowerCase();
|
|
6193
|
-
const queryTerms = params.query.toLowerCase().split(/\s+/);
|
|
6194
|
-
const termMatches = queryTerms.filter((term) => projectText.includes(term)).length;
|
|
6195
|
-
relevance += termMatches * 0.15;
|
|
6196
|
-
if (relevance > 0.4) {
|
|
6197
|
-
results.push({
|
|
6198
|
-
type: "project",
|
|
6199
|
-
data: project,
|
|
6200
|
-
relevance: Math.min(1, relevance),
|
|
6201
|
-
reasoning: `Project context contains ${termMatches} matching terms`,
|
|
6202
|
-
source: "project_context",
|
|
6203
|
-
timestamp: project.lastUpdatedAt
|
|
6204
|
-
});
|
|
6205
|
-
}
|
|
6206
|
-
}
|
|
6207
|
-
}
|
|
6208
|
-
const sessions = await this.memoryManager.getUserGenerationHistory(params.userId, limit);
|
|
6209
|
-
for (const session of sessions) {
|
|
6210
|
-
const sessionText = `${session.prompt} ${session.entities.join(" ")}`.toLowerCase();
|
|
6211
|
-
let relevance = 0.3;
|
|
6212
|
-
if (concepts.entities) {
|
|
6213
|
-
const entityMatches = session.entities.filter(
|
|
6214
|
-
(e) => concepts.entities?.some((ce) => e.toLowerCase().includes(ce.toLowerCase()))
|
|
6215
|
-
);
|
|
6216
|
-
relevance += entityMatches.length * 0.15;
|
|
6217
|
-
}
|
|
6218
|
-
if (concepts.patterns) {
|
|
6219
|
-
const patternMatches = session.patterns.filter(
|
|
6220
|
-
(p) => concepts.patterns?.some((cp) => p.toLowerCase().includes(cp.toLowerCase()))
|
|
6221
|
-
);
|
|
6222
|
-
relevance += patternMatches.length * 0.1;
|
|
6223
|
-
}
|
|
6224
|
-
const queryTerms = params.query.toLowerCase().split(/\s+/);
|
|
6225
|
-
const termMatches = queryTerms.filter((term) => sessionText.includes(term)).length;
|
|
6226
|
-
relevance += termMatches * 0.05;
|
|
6227
|
-
if (relevance > 0.4) {
|
|
6228
|
-
results.push({
|
|
6229
|
-
type: "session",
|
|
6230
|
-
data: session,
|
|
6231
|
-
relevance: Math.min(1, relevance),
|
|
6232
|
-
reasoning: `Session contains relevant entities, patterns, or keywords`,
|
|
6233
|
-
source: "generation_history",
|
|
6234
|
-
timestamp: session.createdAt
|
|
6235
|
-
});
|
|
6236
|
-
}
|
|
6237
|
-
}
|
|
6238
|
-
return results;
|
|
6239
|
-
}
|
|
6240
|
-
/**
|
|
6241
|
-
* Pattern search - "Show me all list views I've built"
|
|
6242
|
-
* Searches for specific patterns and effects
|
|
6243
|
-
*/
|
|
6244
|
-
async patternSearch(params, _depth, limit) {
|
|
6245
|
-
const results = [];
|
|
6246
|
-
const patternTerms = ["list", "form", "detail", "card", "table", "chart", "map", "calendar"];
|
|
6247
|
-
const matchedTerms = patternTerms.filter(
|
|
6248
|
-
(term) => params.query.toLowerCase().includes(term)
|
|
6249
|
-
);
|
|
6250
|
-
const patterns = await this.memoryManager.getUserPatterns(params.userId);
|
|
6251
|
-
for (const pattern of patterns) {
|
|
6252
|
-
let relevance = 0.3;
|
|
6253
|
-
let reasoning = `Pattern usage: ${pattern.usageCount} times`;
|
|
6254
|
-
if (matchedTerms.some((term) => pattern.patternId.toLowerCase().includes(term))) {
|
|
6255
|
-
relevance += 0.3;
|
|
6256
|
-
reasoning += ", matches query pattern type";
|
|
6257
|
-
}
|
|
6258
|
-
const successRate = pattern.usageCount > 0 ? pattern.successCount / pattern.usageCount : 0;
|
|
6259
|
-
relevance += successRate * 0.2;
|
|
6260
|
-
if (relevance > 0.4) {
|
|
6261
|
-
results.push({
|
|
6262
|
-
type: "pattern",
|
|
6263
|
-
data: pattern,
|
|
6264
|
-
relevance: Math.min(1, relevance),
|
|
6265
|
-
reasoning: `${reasoning}, ${Math.round(successRate * 100)}% success rate`,
|
|
6266
|
-
source: "pattern_affinity",
|
|
6267
|
-
timestamp: pattern.lastUsedAt
|
|
6268
|
-
});
|
|
6269
|
-
}
|
|
6270
|
-
}
|
|
6271
|
-
const sessions = await this.memoryManager.getUserGenerationHistory(params.userId, limit);
|
|
6272
|
-
for (const session of sessions) {
|
|
6273
|
-
const matchingPatterns = session.patterns.filter(
|
|
6274
|
-
(p) => matchedTerms.some((term) => p.toLowerCase().includes(term))
|
|
6275
|
-
);
|
|
6276
|
-
if (matchingPatterns.length > 0) {
|
|
6277
|
-
results.push({
|
|
6278
|
-
type: "session",
|
|
6279
|
-
data: session,
|
|
6280
|
-
relevance: 0.5 + matchingPatterns.length * 0.1,
|
|
6281
|
-
reasoning: `Session uses patterns: ${matchingPatterns.join(", ")}`,
|
|
6282
|
-
source: "generation_history",
|
|
6283
|
-
timestamp: session.createdAt
|
|
6284
|
-
});
|
|
6285
|
-
}
|
|
6286
|
-
}
|
|
6287
|
-
return results;
|
|
6288
|
-
}
|
|
6289
|
-
/**
|
|
6290
|
-
* Hybrid search - combines all strategies
|
|
6291
|
-
*/
|
|
6292
|
-
async hybridSearch(params, depth, limit) {
|
|
6293
|
-
const [temporal, semantic, pattern] = await Promise.all([
|
|
6294
|
-
this.temporalSearch(params, depth, Math.ceil(limit / 2)),
|
|
6295
|
-
this.semanticSearch(params, depth, Math.ceil(limit / 2)),
|
|
6296
|
-
this.patternSearch(params, depth, Math.ceil(limit / 2))
|
|
6297
|
-
]);
|
|
6298
|
-
const seen = /* @__PURE__ */ new Set();
|
|
6299
|
-
const combined = [];
|
|
6300
|
-
for (const result of [...temporal, ...semantic, ...pattern]) {
|
|
6301
|
-
const key = `${result.type}-${JSON.stringify(result.data)}`;
|
|
6302
|
-
if (!seen.has(key)) {
|
|
6303
|
-
seen.add(key);
|
|
6304
|
-
combined.push(result);
|
|
6305
|
-
}
|
|
6306
|
-
}
|
|
6307
|
-
return combined;
|
|
6308
|
-
}
|
|
6309
|
-
// ============================================================================
|
|
6310
|
-
// Helpers
|
|
6311
|
-
// ============================================================================
|
|
6312
|
-
/**
|
|
6313
|
-
* Extract semantic concepts from query
|
|
6314
|
-
*/
|
|
6315
|
-
extractConcepts(query) {
|
|
6316
|
-
const lower = query.toLowerCase();
|
|
6317
|
-
return {
|
|
6318
|
-
naming: /naming|case|pascal|camel|snake/i.test(lower),
|
|
6319
|
-
validation: /validat|schema|required|optional/i.test(lower),
|
|
6320
|
-
patterns: ["entity", "list", "form", "detail", "card"].filter((p) => lower.includes(p)),
|
|
6321
|
-
entities: this.extractEntityNames(lower),
|
|
6322
|
-
actions: ["create", "update", "delete", "list", "view"].filter((a) => lower.includes(a))
|
|
6323
|
-
};
|
|
6324
|
-
}
|
|
6325
|
-
/**
|
|
6326
|
-
* Extract potential entity names from query
|
|
6327
|
-
*/
|
|
6328
|
-
extractEntityNames(query) {
|
|
6329
|
-
const words = query.split(/\s+/);
|
|
6330
|
-
const entities = [];
|
|
6331
|
-
for (const word of words) {
|
|
6332
|
-
const clean = word.replace(/[^a-zA-Z]/g, "");
|
|
6333
|
-
if (clean.length > 2 && clean[0] === clean[0].toUpperCase()) {
|
|
6334
|
-
entities.push(clean);
|
|
6335
|
-
}
|
|
6336
|
-
}
|
|
6337
|
-
return entities;
|
|
6338
|
-
}
|
|
6339
|
-
/**
|
|
6340
|
-
* Generate insights from search results
|
|
6341
|
-
*/
|
|
6342
|
-
generateInsights(results, query) {
|
|
6343
|
-
const summary = `Found ${results.length} relevant memory items for "${query}"`;
|
|
6344
|
-
const patternResults = results.filter((r) => r.type === "pattern");
|
|
6345
|
-
const patterns = patternResults.length > 0 ? patternResults.slice(0, 3).map((r) => r.data.patternId) : ["No dominant patterns identified"];
|
|
6346
|
-
const sessions = results.filter((r) => r.type === "session");
|
|
6347
|
-
const trends = [];
|
|
6348
|
-
if (sessions.length > 0) {
|
|
6349
|
-
const timestamps = sessions.filter((s) => s.timestamp).map((s) => s.timestamp.getTime()).sort((a, b) => b - a);
|
|
6350
|
-
if (timestamps.length >= 2) {
|
|
6351
|
-
const avgGap = (timestamps[0] - timestamps[timestamps.length - 1]) / (timestamps.length - 1);
|
|
6352
|
-
const daysGap = avgGap / (1e3 * 60 * 60 * 24);
|
|
6353
|
-
if (daysGap < 7) {
|
|
6354
|
-
trends.push("High activity - multiple sessions per week");
|
|
6355
|
-
} else if (daysGap > 30) {
|
|
6356
|
-
trends.push("Sporadic usage - sessions spread out over time");
|
|
6357
|
-
}
|
|
6358
|
-
}
|
|
6359
|
-
}
|
|
6360
|
-
const suggestions = [];
|
|
6361
|
-
if (patterns.length > 0 && !patterns[0].includes("No dominant")) {
|
|
6362
|
-
suggestions.push(`Consider reusing pattern: ${patterns[0]}`);
|
|
6363
|
-
}
|
|
6364
|
-
const projectResults = results.filter((r) => r.type === "project");
|
|
6365
|
-
if (projectResults.length > 0) {
|
|
6366
|
-
suggestions.push("Review existing project conventions for consistency");
|
|
6367
|
-
}
|
|
6368
|
-
const interruptResults = results.filter((r) => r.type === "interrupt");
|
|
6369
|
-
if (interruptResults.length > 3) {
|
|
6370
|
-
suggestions.push("High interrupt frequency - consider adjusting auto-approval settings");
|
|
6371
|
-
}
|
|
6372
|
-
if (suggestions.length === 0) {
|
|
6373
|
-
suggestions.push("No specific suggestions based on current memory");
|
|
6374
|
-
}
|
|
6375
|
-
return { summary, patterns, trends, suggestions };
|
|
6376
|
-
}
|
|
6377
|
-
};
|
|
6378
|
-
function createAgenticSearchEngine(memoryManager) {
|
|
6379
|
-
return new AgenticSearchEngine(memoryManager);
|
|
6380
|
-
}
|
|
6381
|
-
var PreferenceLearner = class {
|
|
6382
|
-
constructor(options) {
|
|
6383
|
-
this.llmClient = options.llmClient ?? createRequirementsClient();
|
|
6384
|
-
this.memoryManager = options.memoryManager;
|
|
6385
|
-
this.confidenceThreshold = options.confidenceThreshold ?? 0.7;
|
|
6386
|
-
}
|
|
6387
|
-
/**
|
|
6388
|
-
* Analyze a session and infer user preferences
|
|
6389
|
-
*/
|
|
6390
|
-
async analyzeSession(session) {
|
|
6391
|
-
const prompt = this.buildAnalysisPrompt(session);
|
|
6392
|
-
const content = await this.llmClient.call({
|
|
6393
|
-
systemPrompt: "You analyze generation sessions and infer user preferences. Respond with JSON.",
|
|
6394
|
-
userPrompt: prompt
|
|
6395
|
-
});
|
|
6396
|
-
return this.parseAnalysisResponse(content);
|
|
6397
|
-
}
|
|
6398
|
-
/**
|
|
6399
|
-
* Learn from a session and update preferences if confidence is high
|
|
6400
|
-
*/
|
|
6401
|
-
async learnFromSession(session) {
|
|
6402
|
-
let preferences = await this.memoryManager.getUserPreferences(session.userId);
|
|
6403
|
-
if (!preferences) {
|
|
6404
|
-
preferences = {
|
|
6405
|
-
id: session.userId,
|
|
6406
|
-
userId: session.userId,
|
|
6407
|
-
namingConvention: "PascalCase",
|
|
6408
|
-
validationStyle: "strict",
|
|
6409
|
-
preferredPatterns: [],
|
|
6410
|
-
commonEntities: [],
|
|
6411
|
-
commonTraits: [],
|
|
6412
|
-
learnedAt: /* @__PURE__ */ new Date(),
|
|
6413
|
-
confidence: 0.5
|
|
6414
|
-
};
|
|
6415
|
-
}
|
|
6416
|
-
const analysis = await this.analyzeSession(session);
|
|
6417
|
-
let updated = false;
|
|
6418
|
-
for (const inference of analysis.inferences) {
|
|
6419
|
-
if (inference.confidence >= this.confidenceThreshold) {
|
|
6420
|
-
switch (inference.field) {
|
|
6421
|
-
case "namingConvention":
|
|
6422
|
-
if (this.isValidNamingConvention(inference.value)) {
|
|
6423
|
-
preferences.namingConvention = inference.value;
|
|
6424
|
-
updated = true;
|
|
6425
|
-
}
|
|
6426
|
-
break;
|
|
6427
|
-
case "validationStyle":
|
|
6428
|
-
if (this.isValidValidationStyle(inference.value)) {
|
|
6429
|
-
preferences.validationStyle = inference.value;
|
|
6430
|
-
updated = true;
|
|
6431
|
-
}
|
|
6432
|
-
break;
|
|
6433
|
-
case "preferredPatterns":
|
|
6434
|
-
if (Array.isArray(inference.value)) {
|
|
6435
|
-
preferences.preferredPatterns = [
|
|
6436
|
-
.../* @__PURE__ */ new Set([...preferences.preferredPatterns, ...inference.value])
|
|
6437
|
-
].slice(0, 10);
|
|
6438
|
-
updated = true;
|
|
6439
|
-
}
|
|
6440
|
-
break;
|
|
6441
|
-
case "commonEntities":
|
|
6442
|
-
if (Array.isArray(inference.value)) {
|
|
6443
|
-
preferences.commonEntities = [
|
|
6444
|
-
.../* @__PURE__ */ new Set([...preferences.commonEntities, ...inference.value])
|
|
6445
|
-
].slice(0, 20);
|
|
6446
|
-
updated = true;
|
|
6447
|
-
}
|
|
6448
|
-
break;
|
|
6449
|
-
}
|
|
6450
|
-
}
|
|
6451
|
-
}
|
|
6452
|
-
if (updated) {
|
|
6453
|
-
preferences.confidence = Math.min(1, preferences.confidence + 0.05);
|
|
6454
|
-
await this.memoryManager.updateUserPreferences(session.userId, preferences);
|
|
6455
|
-
}
|
|
6456
|
-
return updated ? preferences : null;
|
|
6457
|
-
}
|
|
6458
|
-
/**
|
|
6459
|
-
* Batch learn from multiple sessions
|
|
6460
|
-
*/
|
|
6461
|
-
async batchLearn(sessions) {
|
|
6462
|
-
if (sessions.length === 0) return null;
|
|
6463
|
-
const userId = sessions[0].userId;
|
|
6464
|
-
let preferences = await this.memoryManager.getUserPreferences(userId);
|
|
6465
|
-
if (!preferences) {
|
|
6466
|
-
preferences = {
|
|
6467
|
-
id: userId,
|
|
6468
|
-
userId,
|
|
6469
|
-
namingConvention: "PascalCase",
|
|
6470
|
-
validationStyle: "strict",
|
|
6471
|
-
preferredPatterns: [],
|
|
6472
|
-
commonEntities: [],
|
|
6473
|
-
commonTraits: [],
|
|
6474
|
-
learnedAt: /* @__PURE__ */ new Date(),
|
|
6475
|
-
confidence: 0.5
|
|
6476
|
-
};
|
|
6477
|
-
}
|
|
6478
|
-
const allPatterns = /* @__PURE__ */ new Set();
|
|
6479
|
-
const allEntities = /* @__PURE__ */ new Set();
|
|
6480
|
-
for (const session of sessions) {
|
|
6481
|
-
session.patterns.forEach((p) => allPatterns.add(p));
|
|
6482
|
-
session.entities.forEach((e) => allEntities.add(e));
|
|
6483
|
-
}
|
|
6484
|
-
preferences.preferredPatterns = [...allPatterns].slice(0, 10);
|
|
6485
|
-
preferences.commonEntities = [...allEntities].slice(0, 20);
|
|
6486
|
-
preferences.confidence = Math.min(1, 0.5 + sessions.length * 0.05);
|
|
6487
|
-
const aggregatePrompt = this.buildAggregatePrompt(sessions);
|
|
6488
|
-
const content = await this.llmClient.call({
|
|
6489
|
-
systemPrompt: "You analyze generation sessions and infer user preferences. Respond with JSON.",
|
|
6490
|
-
userPrompt: aggregatePrompt
|
|
6491
|
-
});
|
|
6492
|
-
const analysis = this.parseAnalysisResponse(content);
|
|
6493
|
-
for (const inference of analysis.inferences) {
|
|
6494
|
-
if (inference.confidence >= this.confidenceThreshold) {
|
|
6495
|
-
if (inference.field === "namingConvention" && this.isValidNamingConvention(inference.value)) {
|
|
6496
|
-
preferences.namingConvention = inference.value;
|
|
6497
|
-
}
|
|
6498
|
-
if (inference.field === "validationStyle" && this.isValidValidationStyle(inference.value)) {
|
|
6499
|
-
preferences.validationStyle = inference.value;
|
|
6500
|
-
}
|
|
6501
|
-
}
|
|
6502
|
-
}
|
|
6503
|
-
await this.memoryManager.updateUserPreferences(userId, preferences);
|
|
6504
|
-
return preferences;
|
|
6505
|
-
}
|
|
6506
|
-
// ==========================================================================
|
|
6507
|
-
// Prompt Building
|
|
6508
|
-
// ==========================================================================
|
|
6509
|
-
buildAnalysisPrompt(session) {
|
|
6510
|
-
return `Analyze this generation session and infer the user's preferences.
|
|
6511
|
-
|
|
6512
|
-
Session Details:
|
|
6513
|
-
- Prompt: "${session.prompt}"
|
|
6514
|
-
- Generated Entities: ${session.entities.join(", ")}
|
|
6515
|
-
- Used Patterns: ${session.patterns.join(", ")}
|
|
6516
|
-
- Skill: ${session.skill}
|
|
6517
|
-
|
|
6518
|
-
Schema Excerpt:
|
|
6519
|
-
${JSON.stringify(session.generatedSchema, null, 2).slice(0, 2e3)}
|
|
6520
|
-
|
|
6521
|
-
Analyze and infer:
|
|
6522
|
-
1. Naming convention preference (PascalCase, camelCase, snake_case)
|
|
6523
|
-
2. Validation style (strict, minimal, none)
|
|
6524
|
-
3. Preferred UI patterns
|
|
6525
|
-
4. Common entity types
|
|
6526
|
-
|
|
6527
|
-
Respond in JSON format:
|
|
6528
|
-
{
|
|
6529
|
-
"inferences": [
|
|
6530
|
-
{
|
|
6531
|
-
"field": "namingConvention",
|
|
6532
|
-
"value": "PascalCase",
|
|
6533
|
-
"confidence": 0.85,
|
|
6534
|
-
"reasoning": "User consistently uses PascalCase for entity names"
|
|
6535
|
-
}
|
|
6536
|
-
],
|
|
6537
|
-
"isHighConfidence": true
|
|
6538
|
-
}`;
|
|
6539
|
-
}
|
|
6540
|
-
buildAggregatePrompt(sessions) {
|
|
6541
|
-
const summaries = sessions.slice(0, 10).map((s) => ({
|
|
6542
|
-
prompt: s.prompt.slice(0, 100),
|
|
6543
|
-
entities: s.entities,
|
|
6544
|
-
patterns: s.patterns
|
|
6545
|
-
}));
|
|
6546
|
-
return `Analyze these ${sessions.length} generation sessions and infer the user's aggregate preferences.
|
|
6547
|
-
|
|
6548
|
-
Session Summaries:
|
|
6549
|
-
${JSON.stringify(summaries, null, 2)}
|
|
6550
|
-
|
|
6551
|
-
Infer the user's overall:
|
|
6552
|
-
1. Naming convention preference (PascalCase, camelCase, snake_case)
|
|
6553
|
-
2. Validation style (strict, minimal, none)
|
|
6554
|
-
|
|
6555
|
-
Respond in JSON format:
|
|
6556
|
-
{
|
|
6557
|
-
"inferences": [
|
|
6558
|
-
{
|
|
6559
|
-
"field": "namingConvention",
|
|
6560
|
-
"value": "PascalCase",
|
|
6561
|
-
"confidence": 0.9,
|
|
6562
|
-
"reasoning": "Used PascalCase in 8 out of 10 sessions"
|
|
6563
|
-
}
|
|
6564
|
-
],
|
|
6565
|
-
"isHighConfidence": true
|
|
6566
|
-
}`;
|
|
6567
|
-
}
|
|
6568
|
-
// ==========================================================================
|
|
6569
|
-
// Response Parsing
|
|
6570
|
-
// ==========================================================================
|
|
6571
|
-
parseAnalysisResponse(content) {
|
|
6572
|
-
try {
|
|
6573
|
-
const jsonMatch = content.match(/\{[\s\S]*\}/);
|
|
6574
|
-
if (!jsonMatch) {
|
|
6575
|
-
return { inferences: [], isHighConfidence: false };
|
|
6576
|
-
}
|
|
6577
|
-
const parsed = JSON.parse(jsonMatch[0]);
|
|
6578
|
-
if (Array.isArray(parsed.inferences)) {
|
|
6579
|
-
return {
|
|
6580
|
-
inferences: parsed.inferences.filter(
|
|
6581
|
-
(inf) => inf.field && inf.value !== void 0 && typeof inf.confidence === "number"
|
|
6582
|
-
),
|
|
6583
|
-
isHighConfidence: parsed.isHighConfidence ?? false
|
|
6584
|
-
};
|
|
6585
|
-
}
|
|
6586
|
-
return { inferences: [], isHighConfidence: false };
|
|
6587
|
-
} catch {
|
|
6588
|
-
return { inferences: [], isHighConfidence: false };
|
|
6589
|
-
}
|
|
6590
|
-
}
|
|
6591
|
-
// ==========================================================================
|
|
6592
|
-
// Validation Helpers
|
|
6593
|
-
// ==========================================================================
|
|
6594
|
-
isValidNamingConvention(value) {
|
|
6595
|
-
return typeof value === "string" && ["PascalCase", "camelCase", "snake_case"].includes(value);
|
|
6596
|
-
}
|
|
6597
|
-
isValidValidationStyle(value) {
|
|
6598
|
-
return typeof value === "string" && ["strict", "minimal", "none"].includes(value);
|
|
6599
|
-
}
|
|
6600
|
-
};
|
|
6601
|
-
function createPreferenceLearner(options) {
|
|
6602
|
-
return new PreferenceLearner(options);
|
|
6603
|
-
}
|
|
6604
|
-
|
|
6605
|
-
// src/agent/memory-integration.ts
|
|
6606
|
-
var MemoryIntegrationEngine = class {
|
|
6607
|
-
constructor(options) {
|
|
6608
|
-
this.metrics = { queries: 0, hits: 0, totalLatencyMs: 0 };
|
|
6609
|
-
this.options = {
|
|
6610
|
-
enableEpisodic: true,
|
|
6611
|
-
enableSemantic: true,
|
|
6612
|
-
enableProcedural: true,
|
|
6613
|
-
...options
|
|
6614
|
-
};
|
|
6615
|
-
this.searchEngine = createAgenticSearchEngine(options.memoryManager);
|
|
6616
|
-
this.preferenceLearner = createPreferenceLearner({
|
|
6617
|
-
memoryManager: options.memoryManager
|
|
6618
|
-
});
|
|
6619
|
-
if (!options.memoryManager) {
|
|
6620
|
-
throw new Error("MemoryManager is required for MemoryIntegrationEngine");
|
|
6621
|
-
}
|
|
6622
|
-
}
|
|
6623
|
-
// ============================================================================
|
|
6624
|
-
// Episodic Memory: Past Sessions
|
|
6625
|
-
// ============================================================================
|
|
6626
|
-
/**
|
|
6627
|
-
* Retrieve similar past generation sessions
|
|
6628
|
-
*/
|
|
6629
|
-
async retrieveSimilarSessions(request, limit = 5) {
|
|
6630
|
-
if (!this.options.enableEpisodic) return [];
|
|
6631
|
-
const start = Date.now();
|
|
6632
|
-
try {
|
|
6633
|
-
const results = await this.searchEngine.search({
|
|
6634
|
-
userId: this.options.userId,
|
|
6635
|
-
query: request,
|
|
6636
|
-
strategy: "semantic",
|
|
6637
|
-
limit
|
|
6638
|
-
});
|
|
6639
|
-
const sessions = results.results.filter((r) => r.type === "session").map((r) => {
|
|
6640
|
-
const session = r.data;
|
|
6641
|
-
return {
|
|
6642
|
-
sessionId: session.id ?? "unknown",
|
|
6643
|
-
request: session.request ?? "",
|
|
6644
|
-
schema: session.schemaSnapshot ? JSON.parse(session.schemaSnapshot) : null,
|
|
6645
|
-
success: session.success ?? false,
|
|
6646
|
-
similarity: r.relevance
|
|
6647
|
-
};
|
|
6648
|
-
});
|
|
6649
|
-
this.recordMetrics(true, Date.now() - start);
|
|
6650
|
-
return sessions;
|
|
6651
|
-
} catch (error) {
|
|
6652
|
-
this.recordMetrics(false, Date.now() - start);
|
|
6653
|
-
console.warn("[Memory] Failed to retrieve similar sessions:", error);
|
|
6654
|
-
return [];
|
|
6655
|
-
}
|
|
6656
|
-
}
|
|
6657
|
-
/**
|
|
6658
|
-
* Record a new generation session to episodic memory
|
|
6659
|
-
*/
|
|
6660
|
-
async recordSession(request, result) {
|
|
6661
|
-
if (!this.options.enableEpisodic) return;
|
|
6662
|
-
await this.options.memoryManager.recordGeneration(
|
|
6663
|
-
this.options.userId,
|
|
6664
|
-
{
|
|
6665
|
-
threadId: `thread_${Date.now()}`,
|
|
6666
|
-
prompt: request,
|
|
6667
|
-
skill: "kflow-orbitals",
|
|
6668
|
-
generatedSchema: result.schema,
|
|
6669
|
-
entities: [],
|
|
6670
|
-
patterns: [],
|
|
6671
|
-
success: result.success,
|
|
6672
|
-
validationResult: result.validationResult
|
|
6673
|
-
}
|
|
6674
|
-
);
|
|
6675
|
-
}
|
|
6676
|
-
// ============================================================================
|
|
6677
|
-
// Semantic Memory: Patterns & Preferences
|
|
6678
|
-
// ============================================================================
|
|
6679
|
-
/**
|
|
6680
|
-
* Get learned user preferences
|
|
6681
|
-
*/
|
|
6682
|
-
async getUserPreferences() {
|
|
6683
|
-
if (!this.options.enableSemantic) {
|
|
6684
|
-
return {
|
|
6685
|
-
namingConvention: "PascalCase",
|
|
6686
|
-
preferredPatterns: [],
|
|
6687
|
-
commonEntities: []
|
|
6688
|
-
};
|
|
6689
|
-
}
|
|
6690
|
-
try {
|
|
6691
|
-
const prefs = await this.options.memoryManager.getUserPreferences(
|
|
6692
|
-
this.options.userId
|
|
6693
|
-
);
|
|
6694
|
-
if (!prefs) {
|
|
6695
|
-
return {
|
|
6696
|
-
namingConvention: "PascalCase",
|
|
6697
|
-
preferredPatterns: [],
|
|
6698
|
-
commonEntities: []
|
|
6699
|
-
};
|
|
6700
|
-
}
|
|
6701
|
-
return {
|
|
6702
|
-
namingConvention: prefs.namingConvention ?? "PascalCase",
|
|
6703
|
-
preferredPatterns: prefs.preferredPatterns ?? [],
|
|
6704
|
-
commonEntities: prefs.commonEntities ?? []
|
|
6705
|
-
};
|
|
6706
|
-
} catch (error) {
|
|
6707
|
-
console.warn("[Memory] Failed to get user preferences:", error);
|
|
6708
|
-
return {
|
|
6709
|
-
namingConvention: "PascalCase",
|
|
6710
|
-
preferredPatterns: [],
|
|
6711
|
-
commonEntities: []
|
|
6712
|
-
};
|
|
6713
|
-
}
|
|
6714
|
-
}
|
|
6715
|
-
/**
|
|
6716
|
-
* Learn from user feedback
|
|
6717
|
-
*/
|
|
6718
|
-
async learnFromFeedback(feedback) {
|
|
6719
|
-
if (!this.options.enableSemantic) return;
|
|
6720
|
-
await this.options.memoryManager.updatePatternAffinity(
|
|
6721
|
-
this.options.userId,
|
|
6722
|
-
feedback.pattern,
|
|
6723
|
-
feedback.outcome,
|
|
6724
|
-
{ entityType: feedback.entityType }
|
|
6725
|
-
);
|
|
6726
|
-
}
|
|
6727
|
-
/**
|
|
6728
|
-
* Infer preferences from usage patterns
|
|
6729
|
-
*/
|
|
6730
|
-
async inferPreferences() {
|
|
6731
|
-
if (!this.options.enableSemantic) {
|
|
6732
|
-
return { confidence: 0 };
|
|
6733
|
-
}
|
|
6734
|
-
try {
|
|
6735
|
-
const sessions = await this.options.memoryManager.getUserGenerationHistory(
|
|
6736
|
-
this.options.userId,
|
|
6737
|
-
5
|
|
6738
|
-
);
|
|
6739
|
-
if (sessions.length === 0) {
|
|
6740
|
-
return { confidence: 0 };
|
|
6741
|
-
}
|
|
6742
|
-
const analysis = await this.preferenceLearner.analyzeSession(sessions[0]);
|
|
6743
|
-
const namingInference = analysis.inferences.find((i) => i.field === "namingConvention");
|
|
6744
|
-
const validationInference = analysis.inferences.find((i) => i.field === "validationStyle");
|
|
6745
|
-
return {
|
|
6746
|
-
namingConvention: namingInference?.value,
|
|
6747
|
-
validationStyle: validationInference?.value,
|
|
6748
|
-
confidence: analysis.isHighConfidence ? 0.8 : 0.5
|
|
6749
|
-
};
|
|
6750
|
-
} catch (error) {
|
|
6751
|
-
console.warn("[Memory] Failed to infer preferences:", error);
|
|
6752
|
-
return { confidence: 0 };
|
|
6753
|
-
}
|
|
6754
|
-
}
|
|
6755
|
-
// ============================================================================
|
|
6756
|
-
// Procedural Memory: Domain Workflows
|
|
6757
|
-
// ============================================================================
|
|
6758
|
-
/**
|
|
6759
|
-
* Get project context (domain-specific knowledge)
|
|
6760
|
-
*/
|
|
6761
|
-
async getProjectContext() {
|
|
6762
|
-
if (!this.options.enableProcedural || !this.options.projectId) {
|
|
6763
|
-
return void 0;
|
|
6764
|
-
}
|
|
6765
|
-
try {
|
|
6766
|
-
const context = await this.options.memoryManager.getProjectContext(
|
|
6767
|
-
this.options.projectId
|
|
6768
|
-
);
|
|
6769
|
-
if (!context) return void 0;
|
|
6770
|
-
return {
|
|
6771
|
-
domain: context.domain ?? "business",
|
|
6772
|
-
existingEntities: context.existingEntities ?? [],
|
|
6773
|
-
conventions: context.conventions ?? []
|
|
6774
|
-
};
|
|
6775
|
-
} catch (error) {
|
|
6776
|
-
console.warn("[Memory] Failed to get project context:", error);
|
|
6777
|
-
return void 0;
|
|
6778
|
-
}
|
|
6779
|
-
}
|
|
6780
|
-
/**
|
|
6781
|
-
* Update project context with new conventions
|
|
6782
|
-
*/
|
|
6783
|
-
async updateProjectContext(update) {
|
|
6784
|
-
if (!this.options.enableProcedural || !this.options.projectId) return;
|
|
6785
|
-
await this.options.memoryManager.updateProjectContext(
|
|
6786
|
-
this.options.projectId,
|
|
6787
|
-
{
|
|
6788
|
-
userId: this.options.userId,
|
|
6789
|
-
domain: update.domain,
|
|
6790
|
-
conventions: update.conventions,
|
|
6791
|
-
existingEntities: update.existingEntities
|
|
6792
|
-
}
|
|
6793
|
-
);
|
|
6794
|
-
}
|
|
6795
|
-
// ============================================================================
|
|
6796
|
-
// Combined Memory Context
|
|
6797
|
-
// ============================================================================
|
|
6798
|
-
/**
|
|
6799
|
-
* Build complete memory context for a generation request
|
|
6800
|
-
*/
|
|
6801
|
-
async buildContext(request) {
|
|
6802
|
-
const start = Date.now();
|
|
6803
|
-
const [
|
|
6804
|
-
userPreferences,
|
|
6805
|
-
similarSessions,
|
|
6806
|
-
projectContext,
|
|
6807
|
-
inferredPrefs
|
|
6808
|
-
] = await Promise.all([
|
|
6809
|
-
this.getUserPreferences(),
|
|
6810
|
-
this.retrieveSimilarSessions(request, 3),
|
|
6811
|
-
this.getProjectContext(),
|
|
6812
|
-
this.inferPreferences()
|
|
6813
|
-
]);
|
|
6814
|
-
if (inferredPrefs.confidence > 0.7) {
|
|
6815
|
-
if (inferredPrefs.namingConvention) {
|
|
6816
|
-
userPreferences.namingConvention = inferredPrefs.namingConvention;
|
|
6817
|
-
}
|
|
6818
|
-
}
|
|
6819
|
-
const latencyMs = Date.now() - start;
|
|
6820
|
-
console.log(`[Memory] Context built in ${latencyMs}ms:`, {
|
|
6821
|
-
similarSessions: similarSessions.length,
|
|
6822
|
-
hasProjectContext: !!projectContext,
|
|
6823
|
-
userPreferences: Object.keys(userPreferences).length
|
|
6824
|
-
});
|
|
6825
|
-
return {
|
|
6826
|
-
userPreferences,
|
|
6827
|
-
similarSessions,
|
|
6828
|
-
projectContext,
|
|
6829
|
-
learnedPatterns: []
|
|
6830
|
-
// Would be populated from pattern affinity
|
|
6831
|
-
};
|
|
6832
|
-
}
|
|
6833
|
-
// ============================================================================
|
|
6834
|
-
// Metrics
|
|
6835
|
-
// ============================================================================
|
|
6836
|
-
/**
|
|
6837
|
-
* Get memory quality metrics
|
|
6838
|
-
*/
|
|
6839
|
-
getMetrics() {
|
|
6840
|
-
const totalQueries = this.metrics.queries;
|
|
6841
|
-
const hits = this.metrics.hits;
|
|
6842
|
-
return {
|
|
6843
|
-
recallAccuracy: totalQueries > 0 ? hits / totalQueries : 0,
|
|
6844
|
-
precision: 0.85,
|
|
6845
|
-
// Simplified metric
|
|
6846
|
-
latencyMs: totalQueries > 0 ? this.metrics.totalLatencyMs / totalQueries : 0,
|
|
6847
|
-
cacheHitRate: 0.3
|
|
6848
|
-
// Simplified metric
|
|
6849
|
-
};
|
|
6850
|
-
}
|
|
6851
|
-
recordMetrics(hit, latencyMs) {
|
|
6852
|
-
this.metrics.queries++;
|
|
6853
|
-
if (hit) this.metrics.hits++;
|
|
6854
|
-
this.metrics.totalLatencyMs += latencyMs;
|
|
6855
|
-
}
|
|
6856
|
-
};
|
|
6857
|
-
function createMemoryIntegration(options) {
|
|
6858
|
-
return new MemoryIntegrationEngine(options);
|
|
6859
|
-
}
|
|
6860
|
-
|
|
6861
|
-
// src/tools/composition.ts
|
|
6862
|
-
var WorkflowEngine = class {
|
|
6863
|
-
constructor(executor) {
|
|
6864
|
-
this.workflows = /* @__PURE__ */ new Map();
|
|
6865
|
-
this.executor = executor;
|
|
6866
|
-
}
|
|
6867
|
-
/**
|
|
6868
|
-
* Register a workflow definition
|
|
6869
|
-
*/
|
|
6870
|
-
registerWorkflow(definition) {
|
|
6871
|
-
this.workflows.set(definition.name, definition);
|
|
6872
|
-
}
|
|
6873
|
-
/**
|
|
6874
|
-
* Execute a workflow by name
|
|
6875
|
-
*/
|
|
6876
|
-
async executeWorkflow(workflowName, inputs) {
|
|
6877
|
-
const definition = this.workflows.get(workflowName);
|
|
6878
|
-
if (!definition) {
|
|
6879
|
-
throw new Error(`Workflow not found: ${workflowName}`);
|
|
6880
|
-
}
|
|
6881
|
-
return this.runWorkflow(definition, inputs);
|
|
6882
|
-
}
|
|
6883
|
-
/**
|
|
6884
|
-
* Execute a workflow definition directly
|
|
6885
|
-
*/
|
|
6886
|
-
async runWorkflow(definition, inputs) {
|
|
6887
|
-
const workflowId = `wf_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
6888
|
-
const startTime = Date.now();
|
|
6889
|
-
const context = {
|
|
6890
|
-
workflowId,
|
|
6891
|
-
inputs,
|
|
6892
|
-
outputs: {},
|
|
6893
|
-
stepResults: /* @__PURE__ */ new Map(),
|
|
6894
|
-
metadata: {
|
|
6895
|
-
startTime,
|
|
6896
|
-
stepsCompleted: 0,
|
|
6897
|
-
stepsFailed: 0
|
|
6898
|
-
}
|
|
6899
|
-
};
|
|
6900
|
-
const steps = definition.steps.map((s) => ({ ...s, status: "pending" }));
|
|
6901
|
-
try {
|
|
6902
|
-
const executionOrder = this.resolveDependencies(steps);
|
|
6903
|
-
for (const stepId of executionOrder) {
|
|
6904
|
-
const step = steps.find((s) => s.id === stepId);
|
|
6905
|
-
if (step.condition && !step.condition(context)) {
|
|
6906
|
-
step.status = "skipped";
|
|
6907
|
-
continue;
|
|
6908
|
-
}
|
|
6909
|
-
await this.executeStep(step, context, definition);
|
|
6910
|
-
if (step.status === "error" && definition.onError === "stop") {
|
|
6911
|
-
break;
|
|
6912
|
-
}
|
|
6913
|
-
}
|
|
6914
|
-
const durationMs = Date.now() - startTime;
|
|
6915
|
-
return {
|
|
6916
|
-
success: context.metadata.stepsFailed === 0,
|
|
6917
|
-
workflowId,
|
|
6918
|
-
context,
|
|
6919
|
-
steps,
|
|
6920
|
-
durationMs
|
|
6921
|
-
};
|
|
6922
|
-
} catch (error) {
|
|
6923
|
-
return {
|
|
6924
|
-
success: false,
|
|
6925
|
-
workflowId,
|
|
6926
|
-
context,
|
|
6927
|
-
steps,
|
|
6928
|
-
durationMs: Date.now() - startTime,
|
|
6929
|
-
error: error instanceof Error ? error.message : String(error)
|
|
6930
|
-
};
|
|
6931
|
-
}
|
|
6932
|
-
}
|
|
6933
|
-
/**
|
|
6934
|
-
* Execute independent steps in parallel
|
|
6935
|
-
*/
|
|
6936
|
-
async executeParallel(steps, context) {
|
|
6937
|
-
const promises = steps.map(async (step) => {
|
|
6938
|
-
const startTime = Date.now();
|
|
6939
|
-
try {
|
|
6940
|
-
const input = typeof step.input === "function" ? step.input(context) : step.input;
|
|
6941
|
-
const output = await this.executor.execute(step.tool, input);
|
|
6942
|
-
return {
|
|
6943
|
-
stepId: step.id,
|
|
6944
|
-
success: true,
|
|
6945
|
-
output,
|
|
6946
|
-
durationMs: Date.now() - startTime
|
|
6947
|
-
};
|
|
6948
|
-
} catch (error) {
|
|
6949
|
-
return {
|
|
6950
|
-
stepId: step.id,
|
|
6951
|
-
success: false,
|
|
6952
|
-
error: error instanceof Error ? error.message : String(error),
|
|
6953
|
-
durationMs: Date.now() - startTime
|
|
6954
|
-
};
|
|
6955
|
-
}
|
|
6956
|
-
});
|
|
6957
|
-
return Promise.all(promises);
|
|
6958
|
-
}
|
|
6959
|
-
/**
|
|
6960
|
-
* Create a workflow builder for fluent API
|
|
6961
|
-
*/
|
|
6962
|
-
createWorkflow(name, description) {
|
|
6963
|
-
return new WorkflowBuilder(this, name, description);
|
|
6964
|
-
}
|
|
6965
|
-
// ============================================================================
|
|
6966
|
-
// Private Helpers
|
|
6967
|
-
// ============================================================================
|
|
6968
|
-
async executeStep(step, context, definition) {
|
|
6969
|
-
step.status = "running";
|
|
6970
|
-
step.startTime = Date.now();
|
|
6971
|
-
const maxRetries = definition.maxRetries ?? 0;
|
|
6972
|
-
let attempt = 0;
|
|
6973
|
-
while (attempt <= maxRetries) {
|
|
6974
|
-
try {
|
|
6975
|
-
const input = typeof step.input === "function" ? step.input(context) : step.input;
|
|
6976
|
-
const output = await this.executor.execute(step.tool, input);
|
|
6977
|
-
step.output = output;
|
|
6978
|
-
step.status = "success";
|
|
6979
|
-
step.endTime = Date.now();
|
|
6980
|
-
context.stepResults.set(step.id, { success: true, output });
|
|
6981
|
-
context.outputs[step.id] = output;
|
|
6982
|
-
context.metadata.stepsCompleted++;
|
|
6983
|
-
return;
|
|
6984
|
-
} catch (error) {
|
|
6985
|
-
attempt++;
|
|
6986
|
-
if (attempt > maxRetries) {
|
|
6987
|
-
step.error = error instanceof Error ? error.message : String(error);
|
|
6988
|
-
step.status = "error";
|
|
6989
|
-
step.endTime = Date.now();
|
|
6990
|
-
context.stepResults.set(step.id, { success: false, error: step.error });
|
|
6991
|
-
context.metadata.stepsFailed++;
|
|
6992
|
-
return;
|
|
6993
|
-
}
|
|
6994
|
-
await new Promise((r) => setTimeout(r, 1e3 * attempt));
|
|
6995
|
-
}
|
|
6996
|
-
}
|
|
6997
|
-
}
|
|
6998
|
-
resolveDependencies(steps) {
|
|
6999
|
-
const visited = /* @__PURE__ */ new Set();
|
|
7000
|
-
const result = [];
|
|
7001
|
-
const visit = (stepId) => {
|
|
7002
|
-
if (visited.has(stepId)) return;
|
|
7003
|
-
visited.add(stepId);
|
|
7004
|
-
const step = steps.find((s) => s.id === stepId);
|
|
7005
|
-
if (!step) return;
|
|
7006
|
-
if (step.dependsOn) {
|
|
7007
|
-
for (const dep of step.dependsOn) {
|
|
7008
|
-
visit(dep);
|
|
7009
|
-
}
|
|
7010
|
-
}
|
|
7011
|
-
result.push(stepId);
|
|
7012
|
-
};
|
|
7013
|
-
for (const step of steps) {
|
|
7014
|
-
visit(step.id);
|
|
7015
|
-
}
|
|
7016
|
-
return result;
|
|
7017
|
-
}
|
|
7018
|
-
};
|
|
7019
|
-
var WorkflowBuilder = class {
|
|
7020
|
-
constructor(engine, name, description) {
|
|
7021
|
-
this.engine = engine;
|
|
7022
|
-
this.definition = {
|
|
7023
|
-
name,
|
|
7024
|
-
description,
|
|
7025
|
-
inputs: {},
|
|
7026
|
-
steps: [],
|
|
7027
|
-
onError: "stop",
|
|
7028
|
-
maxRetries: 0
|
|
7029
|
-
};
|
|
7030
|
-
}
|
|
7031
|
-
input(name, type, required = true, defaultValue) {
|
|
7032
|
-
this.definition.inputs[name] = { type, required, default: defaultValue };
|
|
7033
|
-
return this;
|
|
7034
|
-
}
|
|
7035
|
-
step(id, tool14, input, options = {}) {
|
|
7036
|
-
this.definition.steps.push({
|
|
7037
|
-
id,
|
|
7038
|
-
name: id,
|
|
7039
|
-
tool: tool14,
|
|
7040
|
-
input,
|
|
7041
|
-
dependsOn: options.dependsOn,
|
|
7042
|
-
condition: options.condition,
|
|
7043
|
-
status: "pending"
|
|
7044
|
-
});
|
|
7045
|
-
return this;
|
|
7046
|
-
}
|
|
7047
|
-
parallel(steps) {
|
|
7048
|
-
for (const step of steps) {
|
|
7049
|
-
this.definition.steps.push({
|
|
7050
|
-
id: step.id,
|
|
7051
|
-
name: step.id,
|
|
7052
|
-
tool: step.tool,
|
|
7053
|
-
input: step.input,
|
|
7054
|
-
status: "pending"
|
|
7055
|
-
});
|
|
7056
|
-
}
|
|
7057
|
-
return this;
|
|
7058
|
-
}
|
|
7059
|
-
onError(policy) {
|
|
7060
|
-
this.definition.onError = policy;
|
|
7061
|
-
return this;
|
|
7062
|
-
}
|
|
7063
|
-
retry(maxRetries) {
|
|
7064
|
-
this.definition.maxRetries = maxRetries;
|
|
7065
|
-
return this;
|
|
7066
|
-
}
|
|
7067
|
-
build() {
|
|
7068
|
-
return this.definition;
|
|
7069
|
-
}
|
|
7070
|
-
async execute(inputs) {
|
|
7071
|
-
return this.engine.runWorkflow(this.definition, inputs);
|
|
7072
|
-
}
|
|
7073
|
-
};
|
|
7074
|
-
|
|
7075
|
-
// src/agent/react-workflow-integration.ts
|
|
7076
|
-
var ReActWorkflowExecutor = class {
|
|
7077
|
-
constructor(options) {
|
|
7078
|
-
this.telemetry = [];
|
|
7079
|
-
this.options = {
|
|
7080
|
-
...options,
|
|
7081
|
-
enableTelemetry: options.enableTelemetry ?? true,
|
|
7082
|
-
maxExecutionMs: options.maxExecutionMs ?? 6e4
|
|
7083
|
-
};
|
|
7084
|
-
this.workflowEngine = new WorkflowEngine(options.toolExecutor);
|
|
7085
|
-
}
|
|
7086
|
-
/**
|
|
7087
|
-
* Execute a workflow action within a ReAct session
|
|
7088
|
-
* This replaces simple tool calls with full workflows
|
|
7089
|
-
*/
|
|
7090
|
-
async executeWorkflowAction(session, action, context) {
|
|
7091
|
-
const startTime = Date.now();
|
|
7092
|
-
const errors = [];
|
|
7093
|
-
let totalRetries = 0;
|
|
7094
|
-
this.workflowEngine.registerWorkflow({
|
|
7095
|
-
name: action.name,
|
|
7096
|
-
description: `Workflow for ${action.name}`,
|
|
7097
|
-
inputs: Object.keys(context).reduce((acc, key) => {
|
|
7098
|
-
acc[key] = { type: "unknown", required: false };
|
|
7099
|
-
return acc;
|
|
7100
|
-
}, {}),
|
|
7101
|
-
steps: action.workflow.steps.map((step) => ({
|
|
7102
|
-
id: step.id,
|
|
7103
|
-
name: step.id,
|
|
7104
|
-
tool: step.tool,
|
|
7105
|
-
input: step.input,
|
|
7106
|
-
dependsOn: step.dependsOn,
|
|
7107
|
-
status: "pending"
|
|
7108
|
-
})),
|
|
7109
|
-
onError: "retry",
|
|
7110
|
-
maxRetries: 3
|
|
7111
|
-
});
|
|
7112
|
-
try {
|
|
7113
|
-
const result = await this.executeWithTimeout(
|
|
7114
|
-
action.name,
|
|
7115
|
-
context,
|
|
7116
|
-
this.options.maxExecutionMs
|
|
7117
|
-
);
|
|
7118
|
-
const stepsExecuted = result.steps.filter(
|
|
7119
|
-
(s) => s.status === "success" || s.status === "error"
|
|
7120
|
-
).length;
|
|
7121
|
-
totalRetries = this.telemetry.filter(
|
|
7122
|
-
(t) => t.sessionId === session.sessionId && t.actionName === action.name
|
|
7123
|
-
).reduce((sum, t) => sum + t.retryCount, 0);
|
|
7124
|
-
if (result.success && this.options.memoryManager) {
|
|
7125
|
-
await this.storeWorkflowResult(session, action.name, result);
|
|
7126
|
-
}
|
|
7127
|
-
return {
|
|
7128
|
-
success: result.success,
|
|
7129
|
-
output: result.context.outputs,
|
|
7130
|
-
stepsExecuted,
|
|
7131
|
-
durationMs: result.durationMs || Date.now() - startTime,
|
|
7132
|
-
retries: totalRetries,
|
|
7133
|
-
errors: result.error ? [result.error] : errors
|
|
7134
|
-
};
|
|
7135
|
-
} catch (error) {
|
|
7136
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
7137
|
-
errors.push(errorMessage);
|
|
7138
|
-
return {
|
|
7139
|
-
success: false,
|
|
7140
|
-
output: null,
|
|
7141
|
-
stepsExecuted: 0,
|
|
7142
|
-
durationMs: Date.now() - startTime,
|
|
7143
|
-
retries: totalRetries,
|
|
7144
|
-
errors
|
|
7145
|
-
};
|
|
7146
|
-
}
|
|
7147
|
-
}
|
|
7148
|
-
/**
|
|
7149
|
-
* Execute workflow with timeout
|
|
7150
|
-
*/
|
|
7151
|
-
async executeWithTimeout(workflowName, inputs, timeoutMs) {
|
|
7152
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
7153
|
-
setTimeout(() => reject(new Error("Workflow execution timeout")), timeoutMs);
|
|
7154
|
-
});
|
|
7155
|
-
const executionPromise = this.workflowEngine.executeWorkflow(workflowName, inputs);
|
|
7156
|
-
return Promise.race([executionPromise, timeoutPromise]);
|
|
7157
|
-
}
|
|
7158
|
-
/**
|
|
7159
|
-
* Store workflow result in memory for learning
|
|
7160
|
-
*/
|
|
7161
|
-
async storeWorkflowResult(session, actionName, result) {
|
|
7162
|
-
if (!this.options.memoryManager) return;
|
|
7163
|
-
await this.options.memoryManager.recordGeneration(
|
|
7164
|
-
session.sessionId,
|
|
7165
|
-
// Use session ID as user ID proxy
|
|
7166
|
-
{
|
|
7167
|
-
threadId: session.sessionId,
|
|
7168
|
-
prompt: `Workflow: ${actionName}`,
|
|
7169
|
-
skill: "react-workflow",
|
|
7170
|
-
generatedSchema: result.context.outputs,
|
|
7171
|
-
entities: [],
|
|
7172
|
-
patterns: [],
|
|
7173
|
-
success: result.success
|
|
7174
|
-
}
|
|
7175
|
-
);
|
|
7176
|
-
}
|
|
7177
|
-
/**
|
|
7178
|
-
* Record telemetry for a workflow step
|
|
7179
|
-
*/
|
|
7180
|
-
recordTelemetry(event) {
|
|
7181
|
-
if (!this.options.enableTelemetry) return;
|
|
7182
|
-
this.telemetry.push(event);
|
|
7183
|
-
if (this.telemetry.length > 1e3) {
|
|
7184
|
-
this.telemetry = this.telemetry.slice(-500);
|
|
7185
|
-
}
|
|
7186
|
-
}
|
|
7187
|
-
/**
|
|
7188
|
-
* Get telemetry for analysis
|
|
7189
|
-
*/
|
|
7190
|
-
getTelemetry(sessionId) {
|
|
7191
|
-
if (sessionId) {
|
|
7192
|
-
return this.telemetry.filter((t) => t.sessionId === sessionId);
|
|
7193
|
-
}
|
|
7194
|
-
return [...this.telemetry];
|
|
7195
|
-
}
|
|
7196
|
-
/**
|
|
7197
|
-
* Get workflow performance metrics
|
|
7198
|
-
*/
|
|
7199
|
-
getMetrics() {
|
|
7200
|
-
const events = this.telemetry;
|
|
7201
|
-
const uniqueWorkflows = new Set(events.map((e) => e.actionName)).size;
|
|
7202
|
-
const successCount = events.filter((e) => e.success).length;
|
|
7203
|
-
const successRate = events.length > 0 ? successCount / events.length : 0;
|
|
7204
|
-
const avgDuration = events.length > 0 ? events.reduce((sum, e) => sum + e.durationMs, 0) / events.length : 0;
|
|
7205
|
-
const avgRetries = events.length > 0 ? events.reduce((sum, e) => sum + e.retryCount, 0) / events.length : 0;
|
|
7206
|
-
const toolUsage = events.reduce((acc, e) => {
|
|
7207
|
-
acc[e.tool] = (acc[e.tool] || 0) + 1;
|
|
7208
|
-
return acc;
|
|
7209
|
-
}, {});
|
|
7210
|
-
return {
|
|
7211
|
-
totalWorkflows: uniqueWorkflows,
|
|
7212
|
-
successRate,
|
|
7213
|
-
avgDurationMs: avgDuration,
|
|
7214
|
-
avgRetries,
|
|
7215
|
-
toolUsage
|
|
7216
|
-
};
|
|
7217
|
-
}
|
|
7218
|
-
};
|
|
7219
|
-
var ReActWorkflowEngine = class {
|
|
7220
|
-
constructor(options) {
|
|
7221
|
-
this.reactEngine = new ReActEngine(options.reactOptions);
|
|
7222
|
-
this.workflowExecutor = new ReActWorkflowExecutor(options.workflowOptions);
|
|
7223
|
-
}
|
|
7224
|
-
/**
|
|
7225
|
-
* Start a new session
|
|
7226
|
-
*/
|
|
7227
|
-
startSession(userRequest) {
|
|
7228
|
-
return this.reactEngine.startSession(userRequest);
|
|
7229
|
-
}
|
|
7230
|
-
/**
|
|
7231
|
-
* Execute REASON step
|
|
7232
|
-
*/
|
|
7233
|
-
async reason(sessionId, context) {
|
|
7234
|
-
return this.reactEngine.reason(sessionId, context);
|
|
7235
|
-
}
|
|
7236
|
-
/**
|
|
7237
|
-
* Execute ACT step with workflow support
|
|
7238
|
-
*
|
|
7239
|
-
* This is the key integration point - replaces simple tool calls
|
|
7240
|
-
* with full workflows that have retry, parallel execution, etc.
|
|
7241
|
-
*/
|
|
7242
|
-
async act(sessionId, action, actionInput, workflowAction) {
|
|
7243
|
-
const session = this.reactEngine.getSession(sessionId);
|
|
7244
|
-
if (!workflowAction) {
|
|
7245
|
-
const step2 = await this.reactEngine.act(sessionId, action, actionInput);
|
|
7246
|
-
return { step: step2 };
|
|
7247
|
-
}
|
|
7248
|
-
const workflowResult = await this.workflowExecutor.executeWorkflowAction(
|
|
7249
|
-
session,
|
|
7250
|
-
workflowAction,
|
|
7251
|
-
actionInput
|
|
7252
|
-
);
|
|
7253
|
-
const step = {
|
|
7254
|
-
stepNumber: ++session.currentStep,
|
|
7255
|
-
state: "ACTING",
|
|
7256
|
-
thought: `Executing workflow: ${workflowAction.name}`,
|
|
7257
|
-
action: workflowAction.name,
|
|
7258
|
-
actionInput,
|
|
7259
|
-
observation: workflowResult.success ? `Workflow completed successfully (${workflowResult.stepsExecuted} steps)` : `Workflow failed: ${workflowResult.errors.join(", ")}`,
|
|
7260
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
7261
|
-
};
|
|
7262
|
-
session.steps.push(step);
|
|
7263
|
-
session.state = workflowResult.success ? "OBSERVING" : "REFLECTING";
|
|
7264
|
-
return { step, workflowResult };
|
|
7265
|
-
}
|
|
7266
|
-
/**
|
|
7267
|
-
* Execute OBSERVE step
|
|
7268
|
-
*/
|
|
7269
|
-
async observe(sessionId, observation) {
|
|
7270
|
-
return this.reactEngine.observe(sessionId, observation);
|
|
7271
|
-
}
|
|
7272
|
-
/**
|
|
7273
|
-
* Execute REFLECT step
|
|
7274
|
-
*/
|
|
7275
|
-
async reflect(sessionId, result) {
|
|
7276
|
-
return this.reactEngine.reflect(sessionId, result);
|
|
7277
|
-
}
|
|
7278
|
-
/**
|
|
7279
|
-
* Execute CORRECT step
|
|
7280
|
-
*/
|
|
7281
|
-
async correct(sessionId, correctionAction, correctionInput) {
|
|
7282
|
-
return this.reactEngine.correct(sessionId, correctionAction, correctionInput);
|
|
7283
|
-
}
|
|
7284
|
-
/**
|
|
7285
|
-
* Get session
|
|
7286
|
-
*/
|
|
7287
|
-
getSession(sessionId) {
|
|
7288
|
-
return this.reactEngine.getSession(sessionId);
|
|
7289
|
-
}
|
|
7290
|
-
/**
|
|
7291
|
-
* Get workflow metrics
|
|
7292
|
-
*/
|
|
7293
|
-
getWorkflowMetrics() {
|
|
7294
|
-
return this.workflowExecutor.getMetrics();
|
|
7295
|
-
}
|
|
7296
|
-
};
|
|
7297
|
-
function createReActWorkflowExecutor(options) {
|
|
7298
|
-
return new ReActWorkflowExecutor(options);
|
|
7299
|
-
}
|
|
7300
|
-
function createReActWorkflowEngine(options) {
|
|
7301
|
-
return new ReActWorkflowEngine(options);
|
|
7302
|
-
}
|
|
7303
|
-
|
|
7304
|
-
// src/agent/hitl-workflow-integration.ts
|
|
7305
|
-
var HITLWorkflowEngine = class {
|
|
7306
|
-
constructor(options) {
|
|
7307
|
-
this.gateHistory = /* @__PURE__ */ new Map();
|
|
7308
|
-
this.options = {
|
|
7309
|
-
...options,
|
|
7310
|
-
defaultTimeoutMs: options.defaultTimeoutMs ?? 3e5,
|
|
7311
|
-
// 5 minutes
|
|
7312
|
-
enableAutoApprove: options.enableAutoApprove ?? true
|
|
7313
|
-
};
|
|
7314
|
-
this.hitlManager = options.hitlManager;
|
|
7315
|
-
this.workflowEngine = new WorkflowEngine(options.toolExecutor);
|
|
7316
|
-
}
|
|
7317
|
-
/**
|
|
7318
|
-
* Execute a workflow with human gates
|
|
7319
|
-
*/
|
|
7320
|
-
async executeWorkflow(sessionId, workflow, initialContext) {
|
|
7321
|
-
const startTime = Date.now();
|
|
7322
|
-
const gatesPassed = [];
|
|
7323
|
-
const branchesTaken = [];
|
|
7324
|
-
let wasInterrupted = false;
|
|
7325
|
-
try {
|
|
7326
|
-
let context = await this.executeInitialSteps(
|
|
7327
|
-
workflow.initialSteps,
|
|
7328
|
-
initialContext
|
|
7329
|
-
);
|
|
7330
|
-
for (const gate of workflow.gates) {
|
|
7331
|
-
if (gate.condition && !gate.condition(context)) {
|
|
7332
|
-
continue;
|
|
7333
|
-
}
|
|
7334
|
-
if (this.options.enableAutoApprove && gate.autoApprove) {
|
|
7335
|
-
if (gate.autoApprove.condition(context)) {
|
|
7336
|
-
const autoResult = {
|
|
7337
|
-
gateId: gate.id,
|
|
7338
|
-
approved: true,
|
|
7339
|
-
response: { autoApproved: true, reason: gate.autoApprove.reason },
|
|
7340
|
-
respondedAt: Date.now(),
|
|
7341
|
-
autoApproved: true
|
|
7342
|
-
};
|
|
7343
|
-
gatesPassed.push(autoResult);
|
|
7344
|
-
continue;
|
|
7345
|
-
}
|
|
7346
|
-
}
|
|
7347
|
-
wasInterrupted = true;
|
|
7348
|
-
const gateResult = await this.executeHumanGate(sessionId, gate);
|
|
7349
|
-
gatesPassed.push(gateResult);
|
|
7350
|
-
if (!gateResult.approved) {
|
|
7351
|
-
return {
|
|
7352
|
-
success: false,
|
|
7353
|
-
output: null,
|
|
7354
|
-
gatesPassed,
|
|
7355
|
-
branchesTaken,
|
|
7356
|
-
durationMs: Date.now() - startTime,
|
|
7357
|
-
wasInterrupted
|
|
7358
|
-
};
|
|
7359
|
-
}
|
|
7360
|
-
context = {
|
|
7361
|
-
...context,
|
|
7362
|
-
[`gate_${gate.id}`]: gateResult.response
|
|
7363
|
-
};
|
|
7364
|
-
}
|
|
7365
|
-
let branchExecuted = false;
|
|
7366
|
-
for (const branch of workflow.branches) {
|
|
7367
|
-
if (branch.condition(context)) {
|
|
7368
|
-
branchesTaken.push(branch.id);
|
|
7369
|
-
if (branch.gate) {
|
|
7370
|
-
wasInterrupted = true;
|
|
7371
|
-
const branchGateResult = await this.executeHumanGate(
|
|
7372
|
-
sessionId,
|
|
7373
|
-
branch.gate
|
|
7374
|
-
);
|
|
7375
|
-
gatesPassed.push(branchGateResult);
|
|
7376
|
-
if (!branchGateResult.approved) {
|
|
7377
|
-
continue;
|
|
7378
|
-
}
|
|
7379
|
-
}
|
|
7380
|
-
context = await this.executeBranchSteps(branch.steps, context);
|
|
7381
|
-
branchExecuted = true;
|
|
7382
|
-
break;
|
|
7383
|
-
}
|
|
7384
|
-
}
|
|
7385
|
-
if (!branchExecuted && workflow.fallbackBranch) {
|
|
7386
|
-
branchesTaken.push(workflow.fallbackBranch.id);
|
|
7387
|
-
context = await this.executeBranchSteps(
|
|
7388
|
-
workflow.fallbackBranch.steps,
|
|
7389
|
-
context
|
|
7390
|
-
);
|
|
7391
|
-
}
|
|
7392
|
-
this.gateHistory.set(sessionId, gatesPassed);
|
|
7393
|
-
return {
|
|
7394
|
-
success: true,
|
|
7395
|
-
output: context,
|
|
7396
|
-
gatesPassed,
|
|
7397
|
-
branchesTaken,
|
|
7398
|
-
durationMs: Date.now() - startTime,
|
|
7399
|
-
wasInterrupted
|
|
7400
|
-
};
|
|
7401
|
-
} catch (error) {
|
|
7402
|
-
return {
|
|
7403
|
-
success: false,
|
|
7404
|
-
output: error instanceof Error ? error.message : String(error),
|
|
7405
|
-
gatesPassed,
|
|
7406
|
-
branchesTaken,
|
|
7407
|
-
durationMs: Date.now() - startTime,
|
|
7408
|
-
wasInterrupted
|
|
7409
|
-
};
|
|
7410
|
-
}
|
|
7411
|
-
}
|
|
7412
|
-
/**
|
|
7413
|
-
* Execute initial workflow steps
|
|
7414
|
-
*/
|
|
7415
|
-
async executeInitialSteps(steps, context) {
|
|
7416
|
-
let result = { ...context };
|
|
7417
|
-
for (const step of steps) {
|
|
7418
|
-
const output = await this.options.toolExecutor.execute(
|
|
7419
|
-
step.tool,
|
|
7420
|
-
this.interpolateInput(step.input, result)
|
|
7421
|
-
);
|
|
7422
|
-
result = { ...result, [step.tool]: output };
|
|
7423
|
-
}
|
|
7424
|
-
return result;
|
|
7425
|
-
}
|
|
7426
|
-
/**
|
|
7427
|
-
* Execute a human gate
|
|
7428
|
-
*/
|
|
7429
|
-
async executeHumanGate(sessionId, gate) {
|
|
7430
|
-
const timeoutMs = gate.timeoutMs ?? this.options.defaultTimeoutMs;
|
|
7431
|
-
switch (gate.type) {
|
|
7432
|
-
case "approval":
|
|
7433
|
-
return this.executeApprovalGate(sessionId, gate, timeoutMs);
|
|
7434
|
-
case "edit":
|
|
7435
|
-
return this.executeEditGate(sessionId, gate, timeoutMs);
|
|
7436
|
-
case "select":
|
|
7437
|
-
return this.executeSelectGate(sessionId, gate, timeoutMs);
|
|
7438
|
-
case "custom":
|
|
7439
|
-
return this.executeCustomGate(sessionId, gate, timeoutMs);
|
|
7440
|
-
default:
|
|
7441
|
-
throw new Error(`Unknown gate type: ${gate.type}`);
|
|
7442
|
-
}
|
|
7443
|
-
}
|
|
7444
|
-
/**
|
|
7445
|
-
* Execute approval gate
|
|
7446
|
-
*/
|
|
7447
|
-
async executeApprovalGate(sessionId, gate, timeoutMs) {
|
|
7448
|
-
const approved = await this.hitlManager.confirm(sessionId, gate.description, {
|
|
7449
|
-
severity: "info",
|
|
7450
|
-
timeoutMs,
|
|
7451
|
-
context: {
|
|
7452
|
-
checkpointId: `gate_${gate.id}`,
|
|
7453
|
-
currentState: "awaiting_approval",
|
|
7454
|
-
previousActions: []
|
|
7455
|
-
}
|
|
7456
|
-
});
|
|
7457
|
-
return {
|
|
7458
|
-
gateId: gate.id,
|
|
7459
|
-
approved,
|
|
7460
|
-
response: { approved },
|
|
7461
|
-
respondedAt: Date.now(),
|
|
7462
|
-
autoApproved: false
|
|
7463
|
-
};
|
|
7464
|
-
}
|
|
7465
|
-
/**
|
|
7466
|
-
* Execute edit gate
|
|
7467
|
-
*/
|
|
7468
|
-
async executeEditGate(sessionId, gate, timeoutMs) {
|
|
7469
|
-
const content = gate.payload?.content || "";
|
|
7470
|
-
const edited = await this.hitlManager.edit(sessionId, content, {
|
|
7471
|
-
format: gate.payload?.format || "text",
|
|
7472
|
-
title: gate.title,
|
|
7473
|
-
description: gate.description,
|
|
7474
|
-
timeoutMs
|
|
7475
|
-
});
|
|
7476
|
-
return {
|
|
7477
|
-
gateId: gate.id,
|
|
7478
|
-
approved: true,
|
|
7479
|
-
response: { edited, content: edited },
|
|
7480
|
-
respondedAt: Date.now(),
|
|
7481
|
-
autoApproved: false
|
|
7482
|
-
};
|
|
7483
|
-
}
|
|
7484
|
-
/**
|
|
7485
|
-
* Execute select gate
|
|
7486
|
-
*/
|
|
7487
|
-
async executeSelectGate(sessionId, gate, timeoutMs) {
|
|
7488
|
-
const options = gate.payload?.options || [];
|
|
7489
|
-
const selected = await this.hitlManager.select(sessionId, options, {
|
|
7490
|
-
multiple: gate.payload?.multiple || false,
|
|
7491
|
-
timeoutMs
|
|
7492
|
-
});
|
|
7493
|
-
return {
|
|
7494
|
-
gateId: gate.id,
|
|
7495
|
-
approved: true,
|
|
7496
|
-
response: { selected },
|
|
7497
|
-
respondedAt: Date.now(),
|
|
7498
|
-
autoApproved: false
|
|
7499
|
-
};
|
|
7500
|
-
}
|
|
7501
|
-
/**
|
|
7502
|
-
* Execute custom gate
|
|
7503
|
-
*/
|
|
7504
|
-
async executeCustomGate(sessionId, gate, timeoutMs) {
|
|
7505
|
-
const request = {
|
|
7506
|
-
interruptId: `custom_${gate.id}_${Date.now()}`,
|
|
7507
|
-
sessionId,
|
|
7508
|
-
type: "text",
|
|
7509
|
-
title: gate.title,
|
|
7510
|
-
description: gate.description,
|
|
7511
|
-
context: {
|
|
7512
|
-
checkpointId: `gate_${gate.id}`,
|
|
7513
|
-
currentState: "custom_gate",
|
|
7514
|
-
previousActions: []
|
|
7515
|
-
},
|
|
7516
|
-
payload: gate.payload || {},
|
|
7517
|
-
timeoutMs,
|
|
7518
|
-
createdAt: /* @__PURE__ */ new Date()
|
|
7519
|
-
};
|
|
7520
|
-
const response = await this.waitForResponse(request);
|
|
7521
|
-
return {
|
|
7522
|
-
gateId: gate.id,
|
|
7523
|
-
approved: true,
|
|
7524
|
-
response,
|
|
7525
|
-
respondedAt: Date.now(),
|
|
7526
|
-
autoApproved: false
|
|
7527
|
-
};
|
|
7528
|
-
}
|
|
7529
|
-
/**
|
|
7530
|
-
* Execute branch steps
|
|
7531
|
-
*/
|
|
7532
|
-
async executeBranchSteps(steps, context) {
|
|
7533
|
-
return this.executeInitialSteps(steps, context);
|
|
7534
|
-
}
|
|
7535
|
-
/**
|
|
7536
|
-
* Wait for interrupt response
|
|
7537
|
-
*/
|
|
7538
|
-
async waitForResponse(request) {
|
|
7539
|
-
return new Promise((resolve2) => {
|
|
7540
|
-
setTimeout(() => {
|
|
7541
|
-
resolve2({ timeout: true });
|
|
7542
|
-
}, request.timeoutMs || 3e5);
|
|
7543
|
-
});
|
|
7544
|
-
}
|
|
7545
|
-
/**
|
|
7546
|
-
* Interpolate input with context
|
|
7547
|
-
*/
|
|
7548
|
-
interpolateInput(input, context) {
|
|
7549
|
-
const result = {};
|
|
7550
|
-
for (const [key, value] of Object.entries(input)) {
|
|
7551
|
-
if (typeof value === "string" && value.startsWith("{{") && value.endsWith("}}")) {
|
|
7552
|
-
const path8 = value.slice(2, -2).trim();
|
|
7553
|
-
result[key] = this.getValueFromPath(context, path8);
|
|
7554
|
-
} else {
|
|
7555
|
-
result[key] = value;
|
|
7556
|
-
}
|
|
7557
|
-
}
|
|
7558
|
-
return result;
|
|
7559
|
-
}
|
|
7560
|
-
/**
|
|
7561
|
-
* Get value from path
|
|
7562
|
-
*/
|
|
7563
|
-
getValueFromPath(obj, path8) {
|
|
7564
|
-
const parts = path8.split(".");
|
|
7565
|
-
let current = obj;
|
|
7566
|
-
for (const part of parts) {
|
|
7567
|
-
if (current && typeof current === "object") {
|
|
7568
|
-
current = current[part];
|
|
7569
|
-
} else {
|
|
7570
|
-
return void 0;
|
|
7571
|
-
}
|
|
7572
|
-
}
|
|
7573
|
-
return current;
|
|
7574
|
-
}
|
|
7575
|
-
/**
|
|
7576
|
-
* Get gate history for a session
|
|
7577
|
-
*/
|
|
7578
|
-
getGateHistory(sessionId) {
|
|
7579
|
-
return this.gateHistory.get(sessionId) || [];
|
|
7580
|
-
}
|
|
7581
|
-
/**
|
|
7582
|
-
* Clear gate history
|
|
7583
|
-
*/
|
|
7584
|
-
clearGateHistory(sessionId) {
|
|
7585
|
-
if (sessionId) {
|
|
7586
|
-
this.gateHistory.delete(sessionId);
|
|
7587
|
-
} else {
|
|
7588
|
-
this.gateHistory.clear();
|
|
7589
|
-
}
|
|
7590
|
-
}
|
|
7591
|
-
};
|
|
7592
|
-
function createSchemaGenerationHITLWorkflow(complexity) {
|
|
7593
|
-
const needsReview = complexity === "complex";
|
|
7594
|
-
return {
|
|
7595
|
-
name: "schema-generation-with-review",
|
|
7596
|
-
initialSteps: [
|
|
7597
|
-
{ tool: "analyzeRequirements", input: { text: "{{requirements}}" } },
|
|
7598
|
-
{ tool: "extractEntities", input: { from: "{{analyzeRequirements}}" } }
|
|
7599
|
-
],
|
|
7600
|
-
gates: [
|
|
7601
|
-
{
|
|
7602
|
-
id: "complexity-check",
|
|
7603
|
-
type: "approval",
|
|
7604
|
-
title: "Complex Schema Detected",
|
|
7605
|
-
description: `This appears to be a ${complexity} schema. Review before proceeding?`,
|
|
7606
|
-
condition: () => needsReview,
|
|
7607
|
-
autoApprove: {
|
|
7608
|
-
condition: () => !needsReview,
|
|
7609
|
-
reason: "Simple schema, auto-approved"
|
|
7610
|
-
}
|
|
7611
|
-
}
|
|
7612
|
-
],
|
|
7613
|
-
branches: [
|
|
7614
|
-
{
|
|
7615
|
-
id: "generate-full",
|
|
7616
|
-
condition: () => true,
|
|
7617
|
-
steps: [
|
|
7618
|
-
{ tool: "generateOrbital", input: { entities: "{{extractEntities}}" } },
|
|
7619
|
-
{ tool: "validateSchema", input: { schema: "{{generateOrbital}}" } }
|
|
7620
|
-
],
|
|
7621
|
-
gate: needsReview ? {
|
|
7622
|
-
id: "schema-review",
|
|
7623
|
-
type: "edit",
|
|
7624
|
-
title: "Review Generated Schema",
|
|
7625
|
-
description: "Please review and edit the generated schema if needed.",
|
|
7626
|
-
payload: { format: "json" }
|
|
7627
|
-
} : void 0
|
|
7628
|
-
}
|
|
7629
|
-
]
|
|
7630
|
-
};
|
|
7631
|
-
}
|
|
7632
|
-
function createMultiStageApprovalWorkflow(stages) {
|
|
7633
|
-
return {
|
|
7634
|
-
name: "multi-stage-approval",
|
|
7635
|
-
initialSteps: [],
|
|
7636
|
-
gates: stages.map((stage, index) => ({
|
|
7637
|
-
id: `approval-${index}`,
|
|
7638
|
-
type: "approval",
|
|
7639
|
-
title: `${stage.name} Approval Required`,
|
|
7640
|
-
description: `Waiting for approval from ${stage.approver}`
|
|
7641
|
-
})),
|
|
7642
|
-
branches: [
|
|
7643
|
-
{
|
|
7644
|
-
id: "approved",
|
|
7645
|
-
condition: () => true,
|
|
7646
|
-
steps: [{ tool: "finalize", input: {} }]
|
|
7647
|
-
}
|
|
7648
|
-
]
|
|
7649
|
-
};
|
|
7650
|
-
}
|
|
7651
|
-
function createHITLWorkflowEngine(options) {
|
|
7652
|
-
return new HITLWorkflowEngine(options);
|
|
7653
|
-
}
|
|
7654
|
-
|
|
7655
5765
|
// src/agent/workflow-tool-wrapper.ts
|
|
7656
5766
|
function createWorkflowToolWrapper(options = {}) {
|
|
7657
5767
|
const {
|
|
@@ -7765,6 +5875,6 @@ function createEvalWorkflowWrapper(options = {}) {
|
|
|
7765
5875
|
};
|
|
7766
5876
|
}
|
|
7767
5877
|
|
|
7768
|
-
export { EVENT_BUDGETS,
|
|
5878
|
+
export { EVENT_BUDGETS, SessionManager, createEvalWorkflowWrapper, createSkillAgent, createWorkflowToolWrapper, getBudgetWarningMessage, getEventBudget, getInterruptConfig, resumeSkillAgent };
|
|
7769
5879
|
//# sourceMappingURL=index.js.map
|
|
7770
5880
|
//# sourceMappingURL=index.js.map
|