@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.
@@ -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, createRequirementsClient } from '@almadar/llm';
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 fs4 from 'fs/promises';
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.json (NOT /schema.json or absolute paths)
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.json --json
1416
- - npx kflow compile ./schema.json -o ./app --verify
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.json");
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 fs4.access(schemaPath);
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.json. Create it first with write_file."
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.json file in the workspace.
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 fs4.stat(orbitalsDir);
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 fs4.readdir(orbitalsDir);
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 fs4.readFile(path.join(orbitalsDir, file), "utf-8");
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 fs4.readFile(domainPath, "utf-8");
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.json");
2145
- await fs4.writeFile(schemaPath, JSON.stringify(combinedSchema, null, 2));
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.json") : input.schemaPath,
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: `Signal that the orbital generation workflow is COMPLETE.
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("Brief summary of what was accomplished"),
2184
- schemaPath: z.string().optional().describe("Path to the combined schema file if already written")
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.sort(),
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.join(", ")}
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
- return JSON.stringify({
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 a full orbital schema from an OrbitalUnit.
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. For each orbital, call generate_orbital with embedded context
3030
- 3. Collect results and merge into final schema`,
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 fs4.mkdir(chunksPath, { recursive: true });
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 fs4.readFile(filePath, "utf-8");
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.json")')
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 fs4.readFile(filePath, "utf-8");
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 fs4.writeFile(chunkFile, chunkContent);
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 fs4.access(chunkFilePath);
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 fs4.readFile(chunkFilePath, "utf-8");
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 fs4.readFile(meta.sourceFile, "utf-8");
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 fs4.writeFile(meta.sourceFile, output);
3288
- await fs4.unlink(chunkFilePath);
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.code?.includes("ENTITY") || e.code?.includes("REQUIRED") || e.code?.includes("JSON")
3798
+ (e) => e.severity === "error" || e.code?.includes("ENTITY") || e.code?.includes("REQUIRED")
3655
3799
  );
3656
- const warningErrors = errors.filter((e) => !criticalErrors.includes(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 skillContent = config.skillContent || "";
3736
- const hasBindingErrors = stepErrors.some(
3737
- (e) => e.message?.toLowerCase().includes("binding") || e.code?.toLowerCase().includes("binding")
3738
- );
3739
- const bindingGuidance = hasBindingErrors ? `
3740
- ## BINDING ERROR FIXES
3741
-
3742
- Common binding mistakes and fixes:
3743
-
3744
- \u274C INVALID:
3745
- - "@count" \u2192 missing entity reference
3746
- - "@status" \u2192 missing entity reference
3747
- - "@count:status=active" \u2192 wrong syntax
3748
-
3749
- \u2705 VALID (from skill):
3750
- - "@entity.count" - entity field reference
3751
- - "@entity.status" - enum field reference
3752
- - "@payload.data" - event payload data
3753
- - "@state" - current state name
3754
- - "@now" - current timestamp
3755
-
3756
- Replace bare field names like "@count" with proper entity references like "@entity.count".
3757
- ` : "";
3758
- const systemPrompt = `${skillContent}
3759
-
3760
- ${bindingGuidance}
3761
-
3762
- ## FIXING INSTRUCTIONS
3763
-
3764
- You are fixing validation errors in an OrbitalSchema orbital.
3765
-
3766
- Rules:
3767
- 1. Preserve ALL valid content - only fix the reported errors
3768
- 2. Return the COMPLETE orbital with entity, traits, and pages
3769
- 3. Ensure entity has: name, collection, and fields array
3770
- 4. Use valid binding formats: @entity.field, @payload.field, @state
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 validation errors in orbital "${orbital.name}":
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 with all fields (entity, traits, pages).`;
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: true,
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 orchestrateFixing(schema, config = {}) {
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
- const finalValidation = validateSchema(fixedSchema);
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
- schema,
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 using complexity-based provider routing.
4003
-
4004
- This tool automatically selects the best generation strategy:
4005
- - Simple (1 orbital) \u2192 Fast single-provider generation
4006
- - Medium (2-3 orbitals) \u2192 Efficient single-provider generation
4007
- - Complex (4+ orbitals) \u2192 Parallel multi-provider generation
4008
-
4009
- The tool handles decomposition, provider selection, and result combination automatically.`,
4161
+ description: `Generate an OrbitalSchema with automatic complexity-based provider routing.`,
4010
4162
  schema: z.object({
4011
- prompt: z.string().describe("User prompt describing the application to generate")
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 orchestrateFixing(typedSchema, {
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 systemPrompt = [
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, HITLWorkflowEngine, HITLv2Manager, MemoryIntegrationEngine, ReActEngine, ReActWorkflowEngine, ReActWorkflowExecutor, SessionManager, createEvalWorkflowWrapper, createHITLWorkflowEngine, createHITLv2Manager, createMemoryIntegration, createMultiStageApprovalWorkflow, createReActEngine, createReActWorkflowEngine, createReActWorkflowExecutor, createSchemaGenerationHITLWorkflow, createSkillAgent, createWorkflowToolWrapper, getBudgetWarningMessage, getEventBudget, getInterruptConfig, resumeSkillAgent };
5878
+ export { EVENT_BUDGETS, SessionManager, createEvalWorkflowWrapper, createSkillAgent, createWorkflowToolWrapper, getBudgetWarningMessage, getEventBudget, getInterruptConfig, resumeSkillAgent };
7769
5879
  //# sourceMappingURL=index.js.map
7770
5880
  //# sourceMappingURL=index.js.map