@limo-labs/deity 0.2.1 → 0.3.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +130 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -10
- package/dist/index.d.ts +22 -10
- package/dist/index.js +129 -17
- package/dist/index.js.map +1 -1
- package/dist/{jsx-dev-runtime-Dg782FK5.d.cts → jsx-dev-runtime-BQMsrQII.d.cts} +11 -9
- package/dist/{jsx-dev-runtime-Dg782FK5.d.ts → jsx-dev-runtime-BQMsrQII.d.ts} +11 -9
- package/dist/jsx-dev-runtime.d.cts +1 -1
- package/dist/jsx-dev-runtime.d.ts +1 -1
- package/dist/jsx-runtime.d.cts +1 -1
- package/dist/jsx-runtime.d.ts +1 -1
- package/package.json +1 -1
- package/README.md +0 -681
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, description, tags, loopValidator, loopConfig, tools: propsTools, mode, children } = props;
|
|
68
|
+
const resolvedMode = mode ?? "llm";
|
|
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 (resolvedMode === "pure") {
|
|
80
|
+
throw new Error("Agent: pure mode 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
|
-
|
|
83
|
-
|
|
84
|
-
|
|
86
|
+
let prompt;
|
|
87
|
+
let rest;
|
|
88
|
+
if (resolvedMode === "pure") {
|
|
89
|
+
const firstNonTools = nonToolsChildren[0];
|
|
90
|
+
if (firstNonTools?.type === "Prompt") {
|
|
91
|
+
prompt = firstNonTools;
|
|
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
|
-
|
|
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);
|
|
@@ -109,7 +127,8 @@ function Agent(props) {
|
|
|
109
127
|
tags,
|
|
110
128
|
loopValidator,
|
|
111
129
|
loopConfig,
|
|
112
|
-
tools: mergedTools
|
|
130
|
+
tools: mergedTools,
|
|
131
|
+
mode: resolvedMode
|
|
113
132
|
},
|
|
114
133
|
children: orderedChildren
|
|
115
134
|
};
|
|
@@ -1079,13 +1098,14 @@ function compileAgent(ast) {
|
|
|
1079
1098
|
const resultNode = children.find((n) => n?.type === "Result");
|
|
1080
1099
|
const validateNode = children.find((n) => n?.type === "Validate");
|
|
1081
1100
|
const retryNode = children.find((n) => n?.type === "Retry");
|
|
1082
|
-
|
|
1101
|
+
const mode = ast.props.mode ?? "llm";
|
|
1102
|
+
if (mode !== "pure" && !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;
|
|
@@ -1097,6 +1117,9 @@ function compileAgent(ast) {
|
|
|
1097
1117
|
buildPrompt,
|
|
1098
1118
|
extractOutput
|
|
1099
1119
|
};
|
|
1120
|
+
if (mode === "pure") {
|
|
1121
|
+
component.mode = "pure";
|
|
1122
|
+
}
|
|
1100
1123
|
if (validateOutput) {
|
|
1101
1124
|
component.validateOutput = validateOutput;
|
|
1102
1125
|
}
|
|
@@ -1237,6 +1260,9 @@ function createLazyAgentComponent(astNode) {
|
|
|
1237
1260
|
get loopConfig() {
|
|
1238
1261
|
return astNode.props.loopConfig;
|
|
1239
1262
|
},
|
|
1263
|
+
get mode() {
|
|
1264
|
+
return astNode.props.mode;
|
|
1265
|
+
},
|
|
1240
1266
|
// Lazy methods - compile on first call
|
|
1241
1267
|
buildPrompt(ctx) {
|
|
1242
1268
|
return ensureCompiled().buildPrompt(ctx);
|
|
@@ -2876,6 +2902,7 @@ var DEFAULT_LLM_LOOP_CONFIG = {
|
|
|
2876
2902
|
// 2 minutes
|
|
2877
2903
|
verbose: false
|
|
2878
2904
|
};
|
|
2905
|
+
var DEADLINE_PROMPT = `\u26A0\uFE0F DEADLINE REACHED: You have reached the maximum allowed rounds or time limit. You MUST immediately provide your final answer based on the information gathered so far. Do NOT call any more tools. Respond with your best final output NOW.`;
|
|
2879
2906
|
async function executeLLMLoop(adapter, initialMessages, tools, config, ctx, loopConfig = {}, validator) {
|
|
2880
2907
|
const cfg = { ...DEFAULT_LLM_LOOP_CONFIG, ...loopConfig };
|
|
2881
2908
|
const messagesWithMemory = await injectRelevantMemories(
|
|
@@ -2889,6 +2916,7 @@ async function executeLLMLoop(adapter, initialMessages, tools, config, ctx, loop
|
|
|
2889
2916
|
let toolCallsExecuted = 0;
|
|
2890
2917
|
let response;
|
|
2891
2918
|
let toolCallsThisRound = [];
|
|
2919
|
+
const startTime = Date.now();
|
|
2892
2920
|
while (rounds < cfg.maxToolRounds) {
|
|
2893
2921
|
rounds++;
|
|
2894
2922
|
toolCallsThisRound = [];
|
|
@@ -2936,10 +2964,6 @@ async function executeLLMLoop(adapter, initialMessages, tools, config, ctx, loop
|
|
|
2936
2964
|
}
|
|
2937
2965
|
break;
|
|
2938
2966
|
}
|
|
2939
|
-
if (rounds >= cfg.maxToolRounds) {
|
|
2940
|
-
errors.push(`Maximum tool rounds (${cfg.maxToolRounds}) exceeded`);
|
|
2941
|
-
break;
|
|
2942
|
-
}
|
|
2943
2967
|
for (const toolCall of response.toolCalls) {
|
|
2944
2968
|
const alreadyExecuted = toolCall._alreadyExecuted;
|
|
2945
2969
|
if (alreadyExecuted) {
|
|
@@ -3007,6 +3031,23 @@ async function executeLLMLoop(adapter, initialMessages, tools, config, ctx, loop
|
|
|
3007
3031
|
if (allPreExecuted) {
|
|
3008
3032
|
break;
|
|
3009
3033
|
}
|
|
3034
|
+
const isTimeout = cfg.timeout > 0 && Date.now() - startTime >= cfg.timeout;
|
|
3035
|
+
const isLastRound = rounds >= cfg.maxToolRounds;
|
|
3036
|
+
if (isTimeout || isLastRound) {
|
|
3037
|
+
messages.push({
|
|
3038
|
+
role: "user",
|
|
3039
|
+
content: DEADLINE_PROMPT
|
|
3040
|
+
});
|
|
3041
|
+
try {
|
|
3042
|
+
response = await adapter.generate(messages, void 0, config, ctx);
|
|
3043
|
+
messages.push({ role: "assistant", content: response.content });
|
|
3044
|
+
} catch (_error) {
|
|
3045
|
+
}
|
|
3046
|
+
errors.push(
|
|
3047
|
+
isTimeout ? `Timeout reached (${cfg.timeout}ms)` : `Maximum tool rounds (${cfg.maxToolRounds}) reached`
|
|
3048
|
+
);
|
|
3049
|
+
break;
|
|
3050
|
+
}
|
|
3010
3051
|
}
|
|
3011
3052
|
return {
|
|
3012
3053
|
response,
|
|
@@ -3246,6 +3287,17 @@ async function executeWithRetry(component, ctx, executeFn) {
|
|
|
3246
3287
|
}
|
|
3247
3288
|
const shouldRetry = retryConfig.shouldRetry ? retryConfig.shouldRetry(attempts, output, ctx) : attempts < retryConfig.maxAttempts;
|
|
3248
3289
|
if (!shouldRetry) {
|
|
3290
|
+
const lastOutput = outputHistory[outputHistory.length - 1];
|
|
3291
|
+
if (lastOutput !== void 0) {
|
|
3292
|
+
return {
|
|
3293
|
+
output: lastOutput,
|
|
3294
|
+
success: true,
|
|
3295
|
+
attempts,
|
|
3296
|
+
errors: validation.errors ?? ["Validation failed (used best-effort output)"],
|
|
3297
|
+
validationHistory,
|
|
3298
|
+
outputHistory
|
|
3299
|
+
};
|
|
3300
|
+
}
|
|
3249
3301
|
return {
|
|
3250
3302
|
success: false,
|
|
3251
3303
|
attempts,
|
|
@@ -3330,6 +3382,13 @@ function parseComponentOutput(content, schema) {
|
|
|
3330
3382
|
}
|
|
3331
3383
|
|
|
3332
3384
|
// src/engine/executor.ts
|
|
3385
|
+
var EMPTY_LLM_RESULT = {
|
|
3386
|
+
response: { content: "" },
|
|
3387
|
+
messages: [],
|
|
3388
|
+
rounds: 0,
|
|
3389
|
+
toolCallsExecuted: 0,
|
|
3390
|
+
errors: []
|
|
3391
|
+
};
|
|
3333
3392
|
async function executeComponent(component, ctx, adapter, config) {
|
|
3334
3393
|
const startTime = Date.now();
|
|
3335
3394
|
const llmResults = [];
|
|
@@ -4344,7 +4403,7 @@ zod.z.object({
|
|
|
4344
4403
|
sessionId: zod.z.string().min(1, "Session ID cannot be empty"),
|
|
4345
4404
|
workflowName: zod.z.string().min(1, "Workflow name cannot be empty"),
|
|
4346
4405
|
pausedAt: zod.z.string().datetime("Must be ISO 8601 datetime"),
|
|
4347
|
-
version: zod.z.string().regex(/^\d+\.\d+\.\d+$/, "Must be semver format (e.g.,
|
|
4406
|
+
version: zod.z.string().regex(/^\d+\.\d+\.\d+$/, "Must be semver format (e.g., 1.0.0)"),
|
|
4348
4407
|
state: PausedSessionStateSchema,
|
|
4349
4408
|
metadata: PausedSessionMetadataSchema
|
|
4350
4409
|
});
|
|
@@ -4360,7 +4419,7 @@ var SessionSerializer = class {
|
|
|
4360
4419
|
metadata;
|
|
4361
4420
|
constructor() {
|
|
4362
4421
|
this.metadata = {
|
|
4363
|
-
version: "
|
|
4422
|
+
version: "1.0.0",
|
|
4364
4423
|
timestamp: /* @__PURE__ */ new Date(),
|
|
4365
4424
|
specialFields: []
|
|
4366
4425
|
};
|
|
@@ -5030,6 +5089,9 @@ async function executeStepNode(node, ctx, adapter, config) {
|
|
|
5030
5089
|
if (!node.component) {
|
|
5031
5090
|
throw new Error("Step node missing component");
|
|
5032
5091
|
}
|
|
5092
|
+
if (node.component.mode === "pure") {
|
|
5093
|
+
return executePureComponent(node.component, ctx);
|
|
5094
|
+
}
|
|
5033
5095
|
if (!adapter) {
|
|
5034
5096
|
if (node.component.model?.adapter) {
|
|
5035
5097
|
adapter = node.component.model.adapter;
|
|
@@ -5217,6 +5279,56 @@ function createIterationContext(baseCtx, currentItem, index, totalItems, itemMod
|
|
|
5217
5279
|
isLastIteration: index === totalItems - 1
|
|
5218
5280
|
};
|
|
5219
5281
|
}
|
|
5282
|
+
async function executePureComponent(component, ctx) {
|
|
5283
|
+
ctx.ui?.startStep(component.id, component.id);
|
|
5284
|
+
await ctx.trace.log({
|
|
5285
|
+
type: "stage_start",
|
|
5286
|
+
stageId: component.id,
|
|
5287
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
5288
|
+
});
|
|
5289
|
+
try {
|
|
5290
|
+
if (!component.extractOutput) {
|
|
5291
|
+
throw new Error(`Pure component '${component.id}' must have extractOutput defined`);
|
|
5292
|
+
}
|
|
5293
|
+
const output = await Promise.resolve(
|
|
5294
|
+
component.extractOutput(ctx, EMPTY_LLM_RESULT)
|
|
5295
|
+
);
|
|
5296
|
+
const schemaResult = component.outputSchema.safeParse(output);
|
|
5297
|
+
if (!schemaResult.success) {
|
|
5298
|
+
const errors = schemaResult.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`).join("; ");
|
|
5299
|
+
throw new Error(`Pure component '${component.id}' output validation failed: ${errors}`);
|
|
5300
|
+
}
|
|
5301
|
+
const validatedOutput = schemaResult.data;
|
|
5302
|
+
if (component.validateOutput) {
|
|
5303
|
+
const validationResult = await Promise.resolve(
|
|
5304
|
+
component.validateOutput(validatedOutput, ctx)
|
|
5305
|
+
);
|
|
5306
|
+
if (!validationResult.valid) {
|
|
5307
|
+
const feedback = validationResult.feedback || validationResult.errors?.join("; ") || "Validation failed";
|
|
5308
|
+
throw new Error(`Pure component '${component.id}' validateOutput failed: ${feedback}`);
|
|
5309
|
+
}
|
|
5310
|
+
}
|
|
5311
|
+
if (ctx instanceof ExecutionContext) {
|
|
5312
|
+
ctx.previousOutputs[component.id] = validatedOutput;
|
|
5313
|
+
}
|
|
5314
|
+
await ctx.trace.log({
|
|
5315
|
+
type: "stage_complete",
|
|
5316
|
+
output: validatedOutput,
|
|
5317
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
5318
|
+
});
|
|
5319
|
+
ctx.ui?.completeStep(component.id, "Pure execution complete");
|
|
5320
|
+
return validatedOutput;
|
|
5321
|
+
} catch (error) {
|
|
5322
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
5323
|
+
await ctx.trace.log({
|
|
5324
|
+
type: "stage_failed",
|
|
5325
|
+
error: errorMessage,
|
|
5326
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
5327
|
+
});
|
|
5328
|
+
ctx.ui?.failStep(component.id, errorMessage);
|
|
5329
|
+
throw error;
|
|
5330
|
+
}
|
|
5331
|
+
}
|
|
5220
5332
|
function createStepNode(component) {
|
|
5221
5333
|
return {
|
|
5222
5334
|
type: "step",
|
|
@@ -5252,8 +5364,10 @@ function createLoopNode(child, maxIterations) {
|
|
|
5252
5364
|
|
|
5253
5365
|
exports.Agent = Agent;
|
|
5254
5366
|
exports.Conditional = Conditional;
|
|
5367
|
+
exports.DEADLINE_PROMPT = DEADLINE_PROMPT;
|
|
5255
5368
|
exports.DEBUG_ENABLED = DEBUG_ENABLED;
|
|
5256
5369
|
exports.DebugLogger = DebugLogger;
|
|
5370
|
+
exports.EMPTY_LLM_RESULT = EMPTY_LLM_RESULT;
|
|
5257
5371
|
exports.ForEach = ForEach;
|
|
5258
5372
|
exports.InMemoryStore = InMemoryStore;
|
|
5259
5373
|
exports.InMemoryTrace = InMemoryTrace;
|