@limo-labs/deity 0.2.2 → 0.3.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -64,7 +64,8 @@ var init_compile_observe = __esm({
64
64
 
65
65
  // src/components/Agent.tsx
66
66
  function Agent(props) {
67
- const { id, input, output, description, tags, loopValidator, loopConfig, tools: propsTools, children } = props;
67
+ const { id, input, output, mode, description, tags, loopValidator, loopConfig, tools: propsTools, children } = props;
68
+ const isPure = mode === "pure";
68
69
  if (!id) {
69
70
  throw new Error("Agent: id is required");
70
71
  }
@@ -75,13 +76,31 @@ function Agent(props) {
75
76
  throw new Error("Agent: output schema is required");
76
77
  }
77
78
  if (!children || children.length === 0) {
79
+ if (isPure) {
80
+ throw new Error("Agent: pure mode agent must have at least a Result child");
81
+ }
78
82
  throw new Error("Agent: must have at least Prompt and Result children");
79
83
  }
80
84
  const toolsNode = children.find((child) => child?.type === "Tools");
81
85
  const nonToolsChildren = children.filter((child) => child?.type !== "Tools");
82
- const [prompt, ...rest] = nonToolsChildren;
83
- if (!prompt || prompt.type !== "Prompt") {
84
- throw new Error("Agent: first non-Tools child must be a Prompt component");
86
+ let prompt;
87
+ let rest;
88
+ if (isPure) {
89
+ const firstChild = nonToolsChildren[0];
90
+ if (firstChild?.type === "Prompt") {
91
+ prompt = firstChild;
92
+ rest = nonToolsChildren.slice(1);
93
+ } else {
94
+ prompt = void 0;
95
+ rest = nonToolsChildren;
96
+ }
97
+ } else {
98
+ const [first, ...remaining] = nonToolsChildren;
99
+ if (!first || first.type !== "Prompt") {
100
+ throw new Error("Agent: first non-Tools child must be a Prompt component");
101
+ }
102
+ prompt = first;
103
+ rest = remaining;
85
104
  }
86
105
  const result = rest.find((child) => child?.type === "Result");
87
106
  if (!result) {
@@ -91,9 +110,8 @@ function Agent(props) {
91
110
  const validate = rest.find((child) => child?.type === "Validate");
92
111
  const retry = rest.find((child) => child?.type === "Retry");
93
112
  const mergedTools = mergeTools(propsTools, toolsNode);
94
- const orderedChildren = [
95
- prompt
96
- ];
113
+ const orderedChildren = [];
114
+ if (prompt) orderedChildren.push(prompt);
97
115
  if (observe) orderedChildren.push(observe);
98
116
  orderedChildren.push(result);
99
117
  if (validate) orderedChildren.push(validate);
@@ -105,6 +123,7 @@ function Agent(props) {
105
123
  id,
106
124
  input,
107
125
  output,
126
+ mode,
108
127
  description,
109
128
  tags,
110
129
  loopValidator,
@@ -1074,24 +1093,26 @@ function compileAgent(ast) {
1074
1093
  if (!children || children.length === 0) {
1075
1094
  throw new Error("Agent must have children");
1076
1095
  }
1096
+ const isPure = ast.props.mode === "pure";
1077
1097
  const promptNode = children.find((n) => n?.type === "Prompt");
1078
1098
  const observeNode = children.find((n) => n?.type === "Observe");
1079
1099
  const resultNode = children.find((n) => n?.type === "Result");
1080
1100
  const validateNode = children.find((n) => n?.type === "Validate");
1081
1101
  const retryNode = children.find((n) => n?.type === "Retry");
1082
- if (!promptNode) {
1102
+ if (!isPure && !promptNode) {
1083
1103
  throw new Error("Agent must have a Prompt node");
1084
1104
  }
1085
1105
  if (!resultNode) {
1086
1106
  throw new Error("Agent must have a Result node");
1087
1107
  }
1088
- const buildPrompt = compilePrompt(promptNode);
1108
+ const buildPrompt = promptNode ? compilePrompt(promptNode) : () => [];
1089
1109
  const observe = observeNode ? compileObserve(observeNode) : void 0;
1090
1110
  const extractOutput = compileResult(resultNode, observe);
1091
1111
  const validateOutput = validateNode ? compileValidate(validateNode) : void 0;
1092
1112
  const retry = retryNode ? compileRetry(retryNode) : void 0;
1093
1113
  const component = {
1094
1114
  id: ast.props.id,
1115
+ mode: ast.props.mode,
1095
1116
  inputSchema: ast.props.input,
1096
1117
  outputSchema: ast.props.output,
1097
1118
  buildPrompt,
@@ -1222,6 +1243,9 @@ function createLazyAgentComponent(astNode) {
1222
1243
  get id() {
1223
1244
  return astNode.props.id;
1224
1245
  },
1246
+ get mode() {
1247
+ return astNode.props.mode;
1248
+ },
1225
1249
  get inputSchema() {
1226
1250
  return astNode.props.input;
1227
1251
  },
@@ -2596,6 +2620,18 @@ var PreflightChecker = class {
2596
2620
  * Check agent structure
2597
2621
  */
2598
2622
  checkAgentStructure(agent, errors) {
2623
+ const isPure = agent.props.mode === "pure";
2624
+ if (isPure) {
2625
+ const resultNode2 = agent.children.find((n) => n?.type === "Result");
2626
+ if (!resultNode2) {
2627
+ errors.push({
2628
+ type: "invalid_structure",
2629
+ message: "Pure mode Agent must have a Result node",
2630
+ nodeType: "Agent"
2631
+ });
2632
+ }
2633
+ return;
2634
+ }
2599
2635
  const [promptNode, ...rest] = agent.children;
2600
2636
  if (!promptNode || promptNode.type !== "Prompt") {
2601
2637
  errors.push({
@@ -2695,6 +2731,13 @@ async function preflight(agent, options) {
2695
2731
  }
2696
2732
 
2697
2733
  // src/testing/test-utils.ts
2734
+ var EMPTY_LLM_RESULT = {
2735
+ response: { content: "", toolCalls: void 0 },
2736
+ messages: [],
2737
+ rounds: 0,
2738
+ toolCallsExecuted: 0,
2739
+ errors: []
2740
+ };
2698
2741
  async function runObserve(agent, options) {
2699
2742
  const observeNode = agent.children.find((n) => n?.type === "Observe");
2700
2743
  if (!observeNode) {
@@ -3365,6 +3408,73 @@ async function executeComponent(component, ctx, adapter, config) {
3365
3408
  stageId: component.id,
3366
3409
  timestamp: /* @__PURE__ */ new Date()
3367
3410
  });
3411
+ if (component.mode === "pure") {
3412
+ try {
3413
+ ctx.ui?.stepProgress(component.id, 50, "Executing pure agent...");
3414
+ const syntheticLLMResult = {
3415
+ response: { content: "", toolCalls: void 0 },
3416
+ messages: [],
3417
+ rounds: 0,
3418
+ toolCallsExecuted: 0,
3419
+ errors: []
3420
+ };
3421
+ let output;
3422
+ if (component.extractOutput) {
3423
+ const extracted = await Promise.resolve(component.extractOutput(ctx, syntheticLLMResult));
3424
+ const validation = component.outputSchema.safeParse(extracted);
3425
+ if (!validation.success) {
3426
+ const errors = validation.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`).join("; ");
3427
+ throw new Error(`Output validation failed: ${errors}`);
3428
+ }
3429
+ output = validation.data;
3430
+ } else {
3431
+ throw new Error("Pure mode agent must have an extractOutput (Result) function");
3432
+ }
3433
+ if (component.validateOutput) {
3434
+ const validationResult = await Promise.resolve(component.validateOutput(output, ctx));
3435
+ if (!validationResult.valid) {
3436
+ const errorMessages = validationResult.errors?.join("; ") ?? validationResult.feedback ?? "Validation failed";
3437
+ throw new Error(errorMessages);
3438
+ }
3439
+ }
3440
+ const duration2 = Date.now() - startTime;
3441
+ await ctx.trace.log({
3442
+ type: "stage_complete",
3443
+ output,
3444
+ timestamp: /* @__PURE__ */ new Date()
3445
+ });
3446
+ ctx.ui?.completeStep(
3447
+ component.id,
3448
+ `Completed (pure) in ${Math.round(duration2 / 1e3)}s`
3449
+ );
3450
+ return {
3451
+ output,
3452
+ success: true,
3453
+ attempts: 1,
3454
+ llmResults: [syntheticLLMResult],
3455
+ retryResult: {
3456
+ success: true,
3457
+ output,
3458
+ attempts: 1,
3459
+ errors: [],
3460
+ validationHistory: [],
3461
+ outputHistory: [output]
3462
+ },
3463
+ duration: duration2
3464
+ };
3465
+ } catch (error) {
3466
+ const errorMessage = error instanceof Error ? error.message : String(error);
3467
+ await ctx.trace.log({
3468
+ type: "stage_failed",
3469
+ error: errorMessage,
3470
+ timestamp: /* @__PURE__ */ new Date()
3471
+ });
3472
+ ctx.ui?.failStep(component.id, errorMessage);
3473
+ throw new Error(
3474
+ `Component ${component.id} (pure mode) failed: ${errorMessage}`
3475
+ );
3476
+ }
3477
+ }
3368
3478
  const retryResult = await executeWithRetry(
3369
3479
  component,
3370
3480
  ctx,
@@ -5060,6 +5170,10 @@ async function executeStepNode(node, ctx, adapter, config) {
5060
5170
  if (node.component.model?.adapter) {
5061
5171
  adapter = node.component.model.adapter;
5062
5172
  config = node.component.model.config;
5173
+ } else if (node.component.mode === "pure") {
5174
+ adapter = {
5175
+ generate: async () => ({ content: "", toolCalls: void 0 })
5176
+ };
5063
5177
  } else {
5064
5178
  throw new Error("No LLM adapter provided");
5065
5179
  }
@@ -5281,6 +5395,7 @@ exports.Conditional = Conditional;
5281
5395
  exports.DEADLINE_PROMPT = DEADLINE_PROMPT;
5282
5396
  exports.DEBUG_ENABLED = DEBUG_ENABLED;
5283
5397
  exports.DebugLogger = DebugLogger;
5398
+ exports.EMPTY_LLM_RESULT = EMPTY_LLM_RESULT;
5284
5399
  exports.ForEach = ForEach;
5285
5400
  exports.InMemoryStore = InMemoryStore;
5286
5401
  exports.InMemoryTrace = InMemoryTrace;