@almadar/agent 1.2.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
- export { E as EVENT_BUDGETS, S as SessionManager, e as SessionManagerOptions, f as Skill, g as SkillAgentOptions, h as SkillAgentResult, i as SkillLoader, j as SkillMeta, k as SkillRefLoader, m as createSkillAgent, p as getBudgetWarningMessage, q as getEventBudget, r as getInterruptConfig, t as resumeSkillAgent } from '../index-D-Ahuo6F.js';
1
+ export { E as EVENT_BUDGETS, S as SessionManager, e as SessionManagerOptions, f as Skill, g as SkillAgentOptions, h as SkillAgentResult, i as SkillLoader, j as SkillMeta, k as SkillRefLoader, m as createSkillAgent, p as getBudgetWarningMessage, q as getEventBudget, r as getInterruptConfig, t as resumeSkillAgent } from '../index-DNe7JzkE.js';
2
2
  export { Command } from '@langchain/langgraph';
3
3
  export { P as PersistenceMode, S as SessionMetadata, e as SessionRecord } from '../firestore-checkpointer-CkNKXoun.js';
4
4
  import '@almadar/llm';
5
- import '../orbital-subagent-cNfTLdXQ.js';
5
+ import '../orbital-subagent-CiOIu9Ax.js';
6
6
  import '@langchain/core/tools';
7
7
  import 'zod';
8
8
  import '../api-types-BW_58thJ.js';
@@ -13,8 +13,7 @@ import * as fs4 from 'fs/promises';
13
13
  import * as domain_language_star from '@almadar/core/domain-language';
14
14
  import * as fs3 from 'fs';
15
15
  import crypto, { randomUUID } from 'crypto';
16
- import { getFullOrbitalPrompt, generateKflowDesignSkill, getRequirementsTraitPrompt, getKeyBehaviorsReference, getSExprQuickRef, getCommonErrorsSection, getArchitectureSection } from '@almadar/skills';
17
- import { formatRecommendationsForPrompt, buildRecommendationContext, recommendPatterns } from '@almadar/patterns';
16
+ import { getFullOrbitalPrompt, getRequirementsTraitPrompt, getKeyBehaviorsReference, getSExprQuickRef, getCommonErrorsSection, getArchitectureSection } from '@almadar/skills';
18
17
  import { GitHubIntegration } from '@almadar/integrations';
19
18
  import { BaseCheckpointSaver } from '@langchain/langgraph-checkpoint';
20
19
 
@@ -1051,6 +1050,77 @@ npx kflow domain:validate input.orb --verbose
1051
1050
 
1052
1051
  // src/tools/finish-task.ts
1053
1052
  var execAsync2 = promisify(exec);
1053
+ var PROP_CORRECTIONS = {
1054
+ onSubmit: "submitEvent",
1055
+ onCancel: "cancelEvent",
1056
+ headerActions: "actions",
1057
+ loading: "isLoading",
1058
+ fieldNames: "fields"
1059
+ };
1060
+ function autoCorrectProps(schema) {
1061
+ let corrections = 0;
1062
+ JSON.stringify(schema);
1063
+ function walkAndFix(obj) {
1064
+ if (Array.isArray(obj)) {
1065
+ return obj.map(walkAndFix);
1066
+ }
1067
+ if (obj && typeof obj === "object") {
1068
+ const result = {};
1069
+ for (const [key, value] of Object.entries(obj)) {
1070
+ if (key in PROP_CORRECTIONS) {
1071
+ result[PROP_CORRECTIONS[key]] = walkAndFix(value);
1072
+ corrections++;
1073
+ } else {
1074
+ result[key] = walkAndFix(value);
1075
+ }
1076
+ }
1077
+ return result;
1078
+ }
1079
+ return obj;
1080
+ }
1081
+ const fixed = walkAndFix(schema);
1082
+ Object.assign(schema, fixed);
1083
+ return corrections;
1084
+ }
1085
+ function checkCompositionQuality(schema) {
1086
+ const warnings = [];
1087
+ const orbitals = schema.orbitals;
1088
+ if (!Array.isArray(orbitals)) return warnings;
1089
+ for (const orbital of orbitals) {
1090
+ const orbObj = orbital;
1091
+ const traits = orbObj.traits;
1092
+ if (!Array.isArray(traits)) continue;
1093
+ for (const trait of traits) {
1094
+ const traitObj = trait;
1095
+ const transitions = traitObj.stateMachine?.transitions;
1096
+ if (!Array.isArray(transitions)) continue;
1097
+ for (const transition of transitions) {
1098
+ const trans = transition;
1099
+ if (trans.event !== "INIT") continue;
1100
+ const effects = trans.effects;
1101
+ if (!Array.isArray(effects)) continue;
1102
+ const mainRenderUIs = effects.filter(
1103
+ (e) => Array.isArray(e) && e[0] === "render-ui" && e[1] === "main"
1104
+ );
1105
+ if (mainRenderUIs.length > 1) {
1106
+ warnings.push(
1107
+ `\u26A0\uFE0F ${orbObj.name}/${traitObj.name} INIT has ${mainRenderUIs.length} flat render-ui calls to main. Should be a single composed stack with children.`
1108
+ );
1109
+ }
1110
+ if (mainRenderUIs.length === 1) {
1111
+ const renderPayload = mainRenderUIs[0];
1112
+ const payload = renderPayload[2];
1113
+ if (payload && payload.type !== "stack" && !payload.children) {
1114
+ warnings.push(
1115
+ `\u26A0\uFE0F ${orbObj.name}/${traitObj.name} INIT renders a single flat ${payload.type} to main. Should be a composed stack with header, metrics, and data sections.`
1116
+ );
1117
+ }
1118
+ }
1119
+ }
1120
+ }
1121
+ }
1122
+ return warnings;
1123
+ }
1054
1124
  async function collectOrbitalsFromDir(workDir) {
1055
1125
  const orbitalsDir = path.join(workDir, ".orbitals");
1056
1126
  try {
@@ -1105,6 +1175,8 @@ function createFinishTaskTool(workDir) {
1105
1175
  let stats = null;
1106
1176
  let validationResult = null;
1107
1177
  let source = null;
1178
+ let propCorrections = 0;
1179
+ let compositionWarnings = [];
1108
1180
  if (workDir) {
1109
1181
  const orbitals = await collectOrbitalsFromDir(workDir);
1110
1182
  if (orbitals.length > 0) {
@@ -1149,6 +1221,10 @@ function createFinishTaskTool(workDir) {
1149
1221
  } catch {
1150
1222
  }
1151
1223
  }
1224
+ if (combinedSchema) {
1225
+ propCorrections = autoCorrectProps(combinedSchema);
1226
+ compositionWarnings = checkCompositionQuality(combinedSchema);
1227
+ }
1152
1228
  if (combinedSchema) {
1153
1229
  const schemaPath = path.join(workDir, "schema.json");
1154
1230
  await fs4.writeFile(schemaPath, JSON.stringify(combinedSchema, null, 2));
@@ -1168,6 +1244,10 @@ function createFinishTaskTool(workDir) {
1168
1244
  errorCount: validationResult.errors?.length || 0,
1169
1245
  warningCount: validationResult.warnings?.length || 0
1170
1246
  } : void 0,
1247
+ designQuality: {
1248
+ propCorrections: propCorrections || 0,
1249
+ compositionWarnings: compositionWarnings || []
1250
+ },
1171
1251
  schemaPath: combinedSchema ? path.join(workDir, "schema.json") : input.schemaPath,
1172
1252
  nextAction: "NONE - Task is complete. Output a brief success message to the user."
1173
1253
  };
@@ -2328,273 +2408,6 @@ function createSchemaChunkingTools(workDir) {
2328
2408
  applyChunk: createApplyChunkTool(workDir)
2329
2409
  };
2330
2410
  }
2331
- var designCache = /* @__PURE__ */ new Map();
2332
- var CACHE_TTL_MS2 = 24 * 60 * 60 * 1e3;
2333
- var CACHE_VERSION2 = 1;
2334
- function generateFingerprint2(input) {
2335
- const normalized = JSON.stringify({
2336
- version: CACHE_VERSION2,
2337
- ...input
2338
- });
2339
- return crypto.createHash("sha256").update(normalized).digest("hex").slice(0, 16);
2340
- }
2341
- function getCached2(fingerprint) {
2342
- const entry = designCache.get(fingerprint);
2343
- if (!entry) return null;
2344
- if (Date.now() - entry.timestamp > CACHE_TTL_MS2) {
2345
- designCache.delete(fingerprint);
2346
- return null;
2347
- }
2348
- return entry;
2349
- }
2350
- var STATIC_DESIGN_PROMPT = null;
2351
- function getDesignSystemPrompt() {
2352
- if (!STATIC_DESIGN_PROMPT) {
2353
- const skill = generateKflowDesignSkill();
2354
- STATIC_DESIGN_PROMPT = skill.content;
2355
- }
2356
- return STATIC_DESIGN_PROMPT;
2357
- }
2358
- function getPatternRecommendations(input) {
2359
- const recContext = buildRecommendationContext({
2360
- state: input.from,
2361
- event: input.event,
2362
- slot: input.slot,
2363
- domainCategory: input.domainCategory,
2364
- entityFields: input.entityFields
2365
- });
2366
- return recommendPatterns(recContext, 8);
2367
- }
2368
- function buildDesignUserPrompt(input) {
2369
- const fieldList = input.entityFields.map((f) => {
2370
- let desc = ` - ${f.name}: ${f.type}`;
2371
- if (f.values) desc += ` (values: ${f.values.join(", ")})`;
2372
- return desc;
2373
- }).join("\n");
2374
- const hints = [];
2375
- if (input.designStyle) hints.push(`Style: ${input.designStyle}`);
2376
- if (input.flowPattern) hints.push(`Flow: ${input.flowPattern}`);
2377
- if (input.listPattern) hints.push(`List: ${input.listPattern}`);
2378
- if (input.formPattern) hints.push(`Form: ${input.formPattern}`);
2379
- if (input.detailPattern) hints.push(`Detail: ${input.detailPattern}`);
2380
- const vocab = input.vocabulary ? Object.entries(input.vocabulary).map(([k, v]) => ` ${k} \u2192 "${v}"`).join("\n") : "";
2381
- return `Design render-ui effects for this transition:
2382
-
2383
- ## Transition
2384
- - **From**: ${input.from}
2385
- - **To**: ${input.to}
2386
- - **Event**: ${input.event}
2387
- - **Slot**: ${input.slot}
2388
-
2389
- ## Entity: ${input.entityName}
2390
- ${fieldList}
2391
-
2392
- ## Domain
2393
- - **Category**: ${input.domainCategory || "business"}
2394
- ${vocab ? `- **Vocabulary**:
2395
- ${vocab}` : ""}
2396
- ${hints.length > 0 ? `- **Design Hints**: ${hints.join(", ")}` : ""}
2397
-
2398
- ${input.recommendationsSection || ""}
2399
-
2400
- ${input.existingEffects ? `## Existing Effects (enhance these)
2401
- \`\`\`json
2402
- ${JSON.stringify(input.existingEffects, null, 2)}
2403
- \`\`\`` : ""}
2404
-
2405
- Return ONLY the JSON array of render-ui effect tuples.`;
2406
- }
2407
- var DesignTransitionSchema = z.object({
2408
- from: z.string().describe('Source state name (e.g., "Browsing")'),
2409
- to: z.string().describe('Target state name (e.g., "Browsing" for self-loop, "Creating" for transition)'),
2410
- event: z.string().describe('Event name (e.g., "INIT", "CREATE", "VIEW", "EDIT", "DELETE", "SAVE", "CANCEL")'),
2411
- slot: z.string().describe('UI slot to render into: "main", "modal", "drawer", "sidebar", "overlay"'),
2412
- entityName: z.string().describe('Entity name (e.g., "Task", "Order")'),
2413
- entityFields: z.array(z.object({
2414
- name: z.string(),
2415
- type: z.string(),
2416
- values: z.array(z.string()).optional()
2417
- })).describe("Entity fields with types and optional enum values"),
2418
- domainCategory: AgentDomainCategorySchema.optional().describe("Domain category for pattern selection"),
2419
- vocabulary: z.record(z.string(), z.string()).optional().describe('Domain vocabulary mapping (e.g., { "create": "Place Order", "item": "Order" })'),
2420
- designStyle: z.enum(["minimal", "modern", "playful", "data-driven", "immersive"]).optional().describe("Visual style hint"),
2421
- flowPattern: z.enum(["hub-spoke", "master-detail", "crud-cycle", "linear", "role-based"]).optional().describe("Application flow pattern"),
2422
- listPattern: z.enum(["entity-table", "entity-cards", "entity-list"]).optional().describe("Preferred list pattern"),
2423
- formPattern: z.enum(["modal", "drawer", "page"]).optional().describe("Preferred form pattern"),
2424
- detailPattern: z.enum(["drawer", "page", "split"]).optional().describe("Preferred detail view pattern"),
2425
- existingEffects: z.array(z.any()).optional().describe("Existing render-ui effects to enhance (for refinement passes)")
2426
- });
2427
- function createDesignTransitionTool(options = {}) {
2428
- let eventCallback = options.onEvent;
2429
- const setEventCallback = (callback) => {
2430
- eventCallback = callback;
2431
- };
2432
- const emitEvent = (transitionId, type, data) => {
2433
- if (eventCallback) {
2434
- eventCallback(transitionId, {
2435
- type,
2436
- data,
2437
- timestamp: Date.now()
2438
- });
2439
- }
2440
- };
2441
- const designTransitionTool = tool(
2442
- async (input) => {
2443
- const transitionId = `${input.entityName}:${input.from}->${input.to}:${input.event}`;
2444
- const fingerprint = generateFingerprint2({
2445
- from: input.from,
2446
- to: input.to,
2447
- event: input.event,
2448
- slot: input.slot,
2449
- entityName: input.entityName,
2450
- entityFields: input.entityFields,
2451
- domainCategory: input.domainCategory,
2452
- designStyle: input.designStyle,
2453
- flowPattern: input.flowPattern,
2454
- listPattern: input.listPattern
2455
- });
2456
- try {
2457
- emitEvent(transitionId, "message", {
2458
- content: `Designing UI for ${transitionId}`,
2459
- role: "assistant",
2460
- isComplete: false
2461
- });
2462
- const cached = getCached2(fingerprint);
2463
- if (cached) {
2464
- emitEvent(transitionId, "generation_log", {
2465
- level: "info",
2466
- message: `Design cache HIT for ${transitionId}`,
2467
- data: { fingerprint }
2468
- });
2469
- return JSON.stringify({
2470
- success: true,
2471
- transitionId,
2472
- effects: cached.effects,
2473
- cached: true,
2474
- usage: cached.usage
2475
- });
2476
- }
2477
- const recommendations = getPatternRecommendations(input);
2478
- const recommendationsSection = formatRecommendationsForPrompt(recommendations);
2479
- const systemPrompt = getDesignSystemPrompt();
2480
- const userPrompt = buildDesignUserPrompt({
2481
- ...input,
2482
- recommendationsSection
2483
- });
2484
- emitEvent(transitionId, "tool_call", {
2485
- tool: "llm_design_transition",
2486
- args: {
2487
- transition: transitionId,
2488
- slot: input.slot,
2489
- domain: input.domainCategory
2490
- }
2491
- });
2492
- const client = new LLMClient({
2493
- provider: "anthropic",
2494
- model: "claude-sonnet-4-20250514",
2495
- temperature: 0.1
2496
- // Slight creativity for design
2497
- });
2498
- const response = await client.callWithCache({
2499
- systemPrompt: "",
2500
- systemBlocks: [{
2501
- type: "text",
2502
- text: systemPrompt,
2503
- cache_control: { type: "ephemeral" }
2504
- }],
2505
- userPrompt,
2506
- maxTokens: 4096,
2507
- rawText: true
2508
- });
2509
- const rawText = (response.raw || String(response.data) || "").trim();
2510
- let effects;
2511
- try {
2512
- const jsonText = rawText.replace(/^```(?:json)?\n?/m, "").replace(/\n?```$/m, "").trim();
2513
- effects = JSON.parse(jsonText);
2514
- if (!Array.isArray(effects)) {
2515
- effects = [effects];
2516
- }
2517
- } catch {
2518
- return JSON.stringify({
2519
- success: false,
2520
- transitionId,
2521
- error: "Failed to parse design output as JSON",
2522
- rawOutput: rawText
2523
- });
2524
- }
2525
- const usage = {
2526
- inputTokens: response.usage?.promptTokens || 0,
2527
- outputTokens: response.usage?.completionTokens || 0,
2528
- totalTokens: response.usage?.totalTokens || 0
2529
- };
2530
- designCache.set(fingerprint, {
2531
- effects,
2532
- timestamp: Date.now(),
2533
- usage
2534
- });
2535
- emitEvent(transitionId, "tool_result", {
2536
- tool: "llm_design_transition",
2537
- result: { fingerprint, effectCount: effects.length, usage },
2538
- success: true
2539
- });
2540
- emitEvent(transitionId, "message", {
2541
- content: `Designed ${effects.length} effect(s) for ${transitionId} (${usage.totalTokens} tokens)`,
2542
- role: "assistant",
2543
- isComplete: true
2544
- });
2545
- return JSON.stringify({
2546
- success: true,
2547
- transitionId,
2548
- effects,
2549
- cached: false,
2550
- usage,
2551
- recommendedPatterns: recommendations.map((r) => r.pattern)
2552
- });
2553
- } catch (error) {
2554
- const errorMessage = error instanceof Error ? error.message : String(error);
2555
- emitEvent(transitionId, "error", {
2556
- error: errorMessage,
2557
- code: "DESIGN_TRANSITION_ERROR"
2558
- });
2559
- return JSON.stringify({
2560
- success: false,
2561
- transitionId,
2562
- error: errorMessage
2563
- });
2564
- }
2565
- },
2566
- {
2567
- name: "design_transition",
2568
- description: `Design rich render-ui effects for a single orbital transition.
2569
-
2570
- Takes the transition context (from/to state, event, entity, domain) and produces
2571
- polished render-ui effects using the full pattern catalog.
2572
-
2573
- USE THIS TOOL WHEN:
2574
- - Generating INIT transitions (always compose header + stats + content)
2575
- - Generating CREATE/EDIT transitions (form with proper fields)
2576
- - Generating VIEW transitions (detail with tabs for related entities)
2577
- - Enhancing existing render-ui effects that are too basic
2578
-
2579
- The tool uses a specialized design skill with pattern catalog, layout composition,
2580
- and domain-aware pattern selection to produce rich UI.
2581
-
2582
- RETURNS: { success, effects: [["render-ui", slot, config], ...], transitionId, usage }
2583
-
2584
- The effects array contains ONLY render-ui tuples. Non-UI effects (persist, emit, set)
2585
- are NOT included \u2014 you must preserve those from the original transition.
2586
-
2587
- INTEGRATION: After calling this tool, use extract_chunk to get the orbital,
2588
- replace the render-ui effects in the target transition (keep persist/emit/set effects),
2589
- then apply_chunk to merge back into schema.json.`,
2590
- schema: DesignTransitionSchema
2591
- }
2592
- );
2593
- return {
2594
- tool: designTransitionTool,
2595
- setEventCallback
2596
- };
2597
- }
2598
2411
  function createGitHubTools(config) {
2599
2412
  const { token, owner = "", repo = "", workDir } = config;
2600
2413
  const integrationConfig = {
@@ -3814,11 +3627,9 @@ ${skillContents}`;
3814
3627
  const validateSchemaTool = createValidateSchemaTool(workDir);
3815
3628
  const ORBITAL_SKILLS = ["kflow-orbitals", "kflow-orbital-games", "kflow-orbital-fixing"];
3816
3629
  const LEAN_SKILLS = ["kflow-lean-orbitals", "kflow-lean-fixing"];
3817
- const DESIGN_SKILLS = ["kflow-design", "kflow-lean-design"];
3818
3630
  const isOrbitalSkill = primarySkill.name === "kflow-orbitals";
3819
3631
  const isLeanSkill = LEAN_SKILLS.includes(primarySkill.name);
3820
- const isDesignSkill = DESIGN_SKILLS.includes(primarySkill.name);
3821
- const needsChunkingTools = ORBITAL_SKILLS.includes(primarySkill.name) || isDesignSkill;
3632
+ const needsChunkingTools = ORBITAL_SKILLS.includes(primarySkill.name);
3822
3633
  let orbitalTool;
3823
3634
  let setOrbitalEventCallback;
3824
3635
  let setOrbitalCompleteCallback;
@@ -3844,11 +3655,6 @@ ${skillContents}`;
3844
3655
  console.log(`[SkillAgent] Domain orbital tools enabled for ${primarySkill.name} skill`);
3845
3656
  }
3846
3657
  }
3847
- const needsDesignTool = isDesignSkill || ORBITAL_SKILLS.includes(primarySkill.name);
3848
- const designTool = needsDesignTool ? createDesignTransitionTool() : null;
3849
- if (designTool && verbose) {
3850
- console.log(`[SkillAgent] Design transition tool enabled for ${primarySkill.name} skill`);
3851
- }
3852
3658
  const githubTools = options.githubConfig ? createGitHubToolsArray({
3853
3659
  token: options.githubConfig.token,
3854
3660
  owner: options.githubConfig.owner,
@@ -3872,7 +3678,6 @@ ${skillContents}`;
3872
3678
  chunkingTools.extractChunk,
3873
3679
  chunkingTools.applyChunk
3874
3680
  ] : [],
3875
- ...designTool ? [designTool.tool] : [],
3876
3681
  ...githubTools || []
3877
3682
  ];
3878
3683
  const checkpointer = sessions.getCheckpointer(threadId);