@loopstack/delegate-error-example-workflow 0.21.6
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/delegate-error-example.module.d.ts +3 -0
- package/dist/delegate-error-example.module.d.ts.map +1 -0
- package/dist/delegate-error-example.module.js +28 -0
- package/dist/delegate-error-example.module.js.map +1 -0
- package/dist/delegate-error.ui.yaml +22 -0
- package/dist/delegate-error.workflow.d.ts +27 -0
- package/dist/delegate-error.workflow.d.ts.map +1 -0
- package/dist/delegate-error.workflow.js +173 -0
- package/dist/delegate-error.workflow.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/failing-sub-workflow.tool.d.ts +6 -0
- package/dist/tools/failing-sub-workflow.tool.d.ts.map +1 -0
- package/dist/tools/failing-sub-workflow.tool.js +40 -0
- package/dist/tools/failing-sub-workflow.tool.js.map +1 -0
- package/dist/tools/runtime-error.tool.d.ts +7 -0
- package/dist/tools/runtime-error.tool.d.ts.map +1 -0
- package/dist/tools/runtime-error.tool.js +34 -0
- package/dist/tools/runtime-error.tool.js.map +1 -0
- package/dist/tools/strict-schema.tool.d.ts +7 -0
- package/dist/tools/strict-schema.tool.d.ts.map +1 -0
- package/dist/tools/strict-schema.tool.js +32 -0
- package/dist/tools/strict-schema.tool.js.map +1 -0
- package/dist/workflows/failing.workflow.d.ts +5 -0
- package/dist/workflows/failing.workflow.d.ts.map +1 -0
- package/dist/workflows/failing.workflow.js +29 -0
- package/dist/workflows/failing.workflow.js.map +1 -0
- package/package.json +73 -0
- package/src/__tests__/delegate-error.workflow.spec.ts +216 -0
- package/src/delegate-error-example.module.ts +15 -0
- package/src/delegate-error.ui.yaml +22 -0
- package/src/delegate-error.workflow.ts +140 -0
- package/src/index.ts +2 -0
- package/src/tools/failing-sub-workflow.tool.ts +24 -0
- package/src/tools/runtime-error.tool.ts +24 -0
- package/src/tools/strict-schema.tool.ts +20 -0
- package/src/workflows/failing.workflow.ts +13 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delegate-error-example.module.d.ts","sourceRoot":"","sources":["../src/delegate-error-example.module.ts"],"names":[],"mappings":"AASA,qBAKa,0BAA0B;CAAG"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.DelegateErrorExampleModule = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
const claude_module_1 = require("@loopstack/claude-module");
|
|
12
|
+
const core_1 = require("@loopstack/core");
|
|
13
|
+
const delegate_error_workflow_1 = require("./delegate-error.workflow");
|
|
14
|
+
const failing_sub_workflow_tool_1 = require("./tools/failing-sub-workflow.tool");
|
|
15
|
+
const runtime_error_tool_1 = require("./tools/runtime-error.tool");
|
|
16
|
+
const strict_schema_tool_1 = require("./tools/strict-schema.tool");
|
|
17
|
+
const failing_workflow_1 = require("./workflows/failing.workflow");
|
|
18
|
+
let DelegateErrorExampleModule = class DelegateErrorExampleModule {
|
|
19
|
+
};
|
|
20
|
+
exports.DelegateErrorExampleModule = DelegateErrorExampleModule;
|
|
21
|
+
exports.DelegateErrorExampleModule = DelegateErrorExampleModule = __decorate([
|
|
22
|
+
(0, common_1.Module)({
|
|
23
|
+
imports: [core_1.LoopCoreModule, claude_module_1.ClaudeModule],
|
|
24
|
+
providers: [strict_schema_tool_1.StrictSchemaTool, runtime_error_tool_1.RuntimeErrorTool, failing_sub_workflow_tool_1.FailingSubWorkflowTool, failing_workflow_1.FailingWorkflow, delegate_error_workflow_1.DelegateErrorWorkflow],
|
|
25
|
+
exports: [delegate_error_workflow_1.DelegateErrorWorkflow],
|
|
26
|
+
})
|
|
27
|
+
], DelegateErrorExampleModule);
|
|
28
|
+
//# sourceMappingURL=delegate-error-example.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delegate-error-example.module.js","sourceRoot":"","sources":["../src/delegate-error-example.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,4DAAwD;AACxD,0CAAiD;AACjD,uEAAkE;AAClE,iFAA2E;AAC3E,mEAA8D;AAC9D,mEAA8D;AAC9D,mEAA+D;AAOxD,IAAM,0BAA0B,GAAhC,MAAM,0BAA0B;CAAG,CAAA;AAA7B,gEAA0B;qCAA1B,0BAA0B;IALtC,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,qBAAc,EAAE,4BAAY,CAAC;QACvC,SAAS,EAAE,CAAC,qCAAgB,EAAE,qCAAgB,EAAE,kDAAsB,EAAE,kCAAe,EAAE,+CAAqB,CAAC;QAC/G,OAAO,EAAE,CAAC,+CAAqB,CAAC;KACjC,CAAC;GACW,0BAA0B,CAAG"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
title: 'Delegate Error Handling Example'
|
|
2
|
+
|
|
3
|
+
description: |
|
|
4
|
+
Demonstrates how tool errors (validation, runtime, and failed sub-workflows)
|
|
5
|
+
are handled by DelegateToolCalls and fed back to the LLM for self-correction.
|
|
6
|
+
|
|
7
|
+
The workflow instructs the LLM to:
|
|
8
|
+
1. Call strictSchema with wrong args (triggers Zod validation error)
|
|
9
|
+
2. Observe the error and retry with correct args
|
|
10
|
+
3. Call runtimeError with shouldFail: true (triggers runtime error)
|
|
11
|
+
4. Observe the error and retry with shouldFail: false
|
|
12
|
+
5. Call failingSubWorkflow (launches a sub-workflow that fails)
|
|
13
|
+
6. Observe the sub-workflow error and summarize
|
|
14
|
+
|
|
15
|
+
ui:
|
|
16
|
+
widgets:
|
|
17
|
+
- widget: button
|
|
18
|
+
showWhen:
|
|
19
|
+
- awaiting_tools
|
|
20
|
+
options:
|
|
21
|
+
transition: cancelPendingTools
|
|
22
|
+
label: Cancel pending tools
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ClaudeGenerateText, ClaudeGenerateTextResult, DelegateToolCalls, DelegateToolCallsResult, UpdateToolResult } from '@loopstack/claude-module';
|
|
2
|
+
import { BaseWorkflow } from '@loopstack/common';
|
|
3
|
+
import { FailingSubWorkflowTool } from './tools/failing-sub-workflow.tool';
|
|
4
|
+
import { RuntimeErrorTool } from './tools/runtime-error.tool';
|
|
5
|
+
import { StrictSchemaTool } from './tools/strict-schema.tool';
|
|
6
|
+
export declare class DelegateErrorWorkflow extends BaseWorkflow {
|
|
7
|
+
claudeGenerateText: ClaudeGenerateText;
|
|
8
|
+
delegateToolCalls: DelegateToolCalls;
|
|
9
|
+
updateToolResult: UpdateToolResult;
|
|
10
|
+
strictSchema: StrictSchemaTool;
|
|
11
|
+
runtimeError: RuntimeErrorTool;
|
|
12
|
+
failingSubWorkflow: FailingSubWorkflowTool;
|
|
13
|
+
llmResult?: ClaudeGenerateTextResult;
|
|
14
|
+
delegateResult?: DelegateToolCallsResult;
|
|
15
|
+
turnCount: number;
|
|
16
|
+
setup(): Promise<void>;
|
|
17
|
+
llmTurn(): Promise<void>;
|
|
18
|
+
executeToolCalls(): Promise<void>;
|
|
19
|
+
toolResultReceived(payload: unknown): Promise<void>;
|
|
20
|
+
toolsComplete(): Promise<void>;
|
|
21
|
+
cancelPendingTools(): Promise<void>;
|
|
22
|
+
respond(): Promise<void>;
|
|
23
|
+
private hasToolCalls;
|
|
24
|
+
private allToolsComplete;
|
|
25
|
+
private isEndTurn;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=delegate-error.workflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delegate-error.workflow.d.ts","sourceRoot":"","sources":["../src/delegate-error.workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EAExB,iBAAiB,EACjB,uBAAuB,EACvB,gBAAgB,EACjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,YAAY,EASb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAU9D,qBAGa,qBAAsB,SAAQ,YAAY;IACvC,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,YAAY,EAAE,gBAAgB,CAAC;IAC/B,YAAY,EAAE,gBAAgB,CAAC;IAC/B,kBAAkB,EAAE,sBAAsB,CAAC;IAEzD,SAAS,CAAC,EAAE,wBAAwB,CAAC;IACrC,cAAc,CAAC,EAAE,uBAAuB,CAAC;IACzC,SAAS,EAAG,MAAM,CAAC;IAGb,KAAK;IAoBL,OAAO;IAwBP,gBAAgB;IAUhB,kBAAkB,CAAC,OAAO,EAAE,OAAO;IAWnC,aAAa;IAGb,kBAAkB;IASlB,OAAO;IAIb,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,SAAS;CAGlB"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.DelegateErrorWorkflow = void 0;
|
|
13
|
+
const claude_module_1 = require("@loopstack/claude-module");
|
|
14
|
+
const common_1 = require("@loopstack/common");
|
|
15
|
+
const failing_sub_workflow_tool_1 = require("./tools/failing-sub-workflow.tool");
|
|
16
|
+
const runtime_error_tool_1 = require("./tools/runtime-error.tool");
|
|
17
|
+
const strict_schema_tool_1 = require("./tools/strict-schema.tool");
|
|
18
|
+
let DelegateErrorWorkflow = class DelegateErrorWorkflow extends common_1.BaseWorkflow {
|
|
19
|
+
claudeGenerateText;
|
|
20
|
+
delegateToolCalls;
|
|
21
|
+
updateToolResult;
|
|
22
|
+
strictSchema;
|
|
23
|
+
runtimeError;
|
|
24
|
+
failingSubWorkflow;
|
|
25
|
+
llmResult;
|
|
26
|
+
delegateResult;
|
|
27
|
+
turnCount;
|
|
28
|
+
async setup() {
|
|
29
|
+
this.turnCount = 0;
|
|
30
|
+
await this.repository.save(common_1.MessageDocument, {
|
|
31
|
+
role: 'assistant',
|
|
32
|
+
content: '# Delegate Error Handling Example\n\n' +
|
|
33
|
+
'This workflow tests how tool errors are handled and fed back to the LLM.\n\n' +
|
|
34
|
+
'The LLM will deliberately trigger errors, then self-correct.',
|
|
35
|
+
});
|
|
36
|
+
await this.repository.save(claude_module_1.ClaudeMessageDocument, {
|
|
37
|
+
role: 'user',
|
|
38
|
+
content: 'Follow the instructions in your system prompt exactly. ' +
|
|
39
|
+
'Start with step 1: call strictSchema with no arguments.',
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
async llmTurn() {
|
|
43
|
+
this.turnCount++;
|
|
44
|
+
const result = await this.claudeGenerateText.call({
|
|
45
|
+
system: 'You are a test assistant that follows instructions precisely. ' +
|
|
46
|
+
'You are fully autonomous — do NOT ask the user for input or confirmation. ' +
|
|
47
|
+
'Just proceed through each step on your own.\n\n' +
|
|
48
|
+
'Complete these steps IN ORDER. Do exactly one step per turn:\n\n' +
|
|
49
|
+
'1. Call the `strictSchema` tool with NO arguments (empty object {}). This will fail — that is expected.\n' +
|
|
50
|
+
'2. After seeing the validation error, call `strictSchema` correctly with { "name": "World" }.\n' +
|
|
51
|
+
'3. Call the `runtimeError` tool with { "shouldFail": true }. This will fail — that is expected.\n' +
|
|
52
|
+
'4. After seeing the runtime error, call `runtimeError` with { "shouldFail": false }.\n' +
|
|
53
|
+
'5. Call the `failingSubWorkflow` tool with {}. This launches a sub-workflow that will fail — that is expected.\n' +
|
|
54
|
+
'6. After seeing the sub-workflow error, respond with a brief summary of what happened (do NOT call any tools).\n\n' +
|
|
55
|
+
'IMPORTANT: Only perform ONE step per turn. Do NOT skip steps. Do NOT wait for user input between steps.',
|
|
56
|
+
claude: { model: 'claude-sonnet-4-6' },
|
|
57
|
+
messagesSearchTag: 'message',
|
|
58
|
+
tools: ['strictSchema', 'runtimeError', 'failingSubWorkflow'],
|
|
59
|
+
});
|
|
60
|
+
this.llmResult = result.data;
|
|
61
|
+
}
|
|
62
|
+
async executeToolCalls() {
|
|
63
|
+
const result = await this.delegateToolCalls.call({
|
|
64
|
+
message: this.llmResult,
|
|
65
|
+
document: claude_module_1.ClaudeMessageDocument,
|
|
66
|
+
callback: { transition: 'toolResultReceived' },
|
|
67
|
+
});
|
|
68
|
+
this.delegateResult = result.data;
|
|
69
|
+
}
|
|
70
|
+
async toolResultReceived(payload) {
|
|
71
|
+
const result = await this.updateToolResult.call({
|
|
72
|
+
delegateResult: this.delegateResult,
|
|
73
|
+
completedTool: payload,
|
|
74
|
+
document: claude_module_1.ClaudeMessageDocument,
|
|
75
|
+
});
|
|
76
|
+
this.delegateResult = result.data;
|
|
77
|
+
}
|
|
78
|
+
async toolsComplete() { }
|
|
79
|
+
async cancelPendingTools() {
|
|
80
|
+
const workflowId = this.ctx.context.workflowId;
|
|
81
|
+
if (workflowId) {
|
|
82
|
+
await this.orchestrator.cancelChildren(workflowId);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async respond() {
|
|
86
|
+
await this.repository.save(claude_module_1.ClaudeMessageDocument, this.llmResult, { id: this.llmResult.id });
|
|
87
|
+
}
|
|
88
|
+
hasToolCalls() {
|
|
89
|
+
return this.llmResult?.stop_reason === 'tool_use';
|
|
90
|
+
}
|
|
91
|
+
allToolsComplete() {
|
|
92
|
+
return !!this.delegateResult?.allCompleted;
|
|
93
|
+
}
|
|
94
|
+
isEndTurn() {
|
|
95
|
+
return this.llmResult?.stop_reason === 'end_turn';
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
exports.DelegateErrorWorkflow = DelegateErrorWorkflow;
|
|
99
|
+
__decorate([
|
|
100
|
+
(0, common_1.InjectTool)(),
|
|
101
|
+
__metadata("design:type", claude_module_1.ClaudeGenerateText)
|
|
102
|
+
], DelegateErrorWorkflow.prototype, "claudeGenerateText", void 0);
|
|
103
|
+
__decorate([
|
|
104
|
+
(0, common_1.InjectTool)(),
|
|
105
|
+
__metadata("design:type", claude_module_1.DelegateToolCalls)
|
|
106
|
+
], DelegateErrorWorkflow.prototype, "delegateToolCalls", void 0);
|
|
107
|
+
__decorate([
|
|
108
|
+
(0, common_1.InjectTool)(),
|
|
109
|
+
__metadata("design:type", claude_module_1.UpdateToolResult)
|
|
110
|
+
], DelegateErrorWorkflow.prototype, "updateToolResult", void 0);
|
|
111
|
+
__decorate([
|
|
112
|
+
(0, common_1.InjectTool)(),
|
|
113
|
+
__metadata("design:type", strict_schema_tool_1.StrictSchemaTool)
|
|
114
|
+
], DelegateErrorWorkflow.prototype, "strictSchema", void 0);
|
|
115
|
+
__decorate([
|
|
116
|
+
(0, common_1.InjectTool)(),
|
|
117
|
+
__metadata("design:type", runtime_error_tool_1.RuntimeErrorTool)
|
|
118
|
+
], DelegateErrorWorkflow.prototype, "runtimeError", void 0);
|
|
119
|
+
__decorate([
|
|
120
|
+
(0, common_1.InjectTool)(),
|
|
121
|
+
__metadata("design:type", failing_sub_workflow_tool_1.FailingSubWorkflowTool)
|
|
122
|
+
], DelegateErrorWorkflow.prototype, "failingSubWorkflow", void 0);
|
|
123
|
+
__decorate([
|
|
124
|
+
(0, common_1.Initial)({ to: 'ready' }),
|
|
125
|
+
__metadata("design:type", Function),
|
|
126
|
+
__metadata("design:paramtypes", []),
|
|
127
|
+
__metadata("design:returntype", Promise)
|
|
128
|
+
], DelegateErrorWorkflow.prototype, "setup", null);
|
|
129
|
+
__decorate([
|
|
130
|
+
(0, common_1.Transition)({ from: 'ready', to: 'prompt_executed' }),
|
|
131
|
+
__metadata("design:type", Function),
|
|
132
|
+
__metadata("design:paramtypes", []),
|
|
133
|
+
__metadata("design:returntype", Promise)
|
|
134
|
+
], DelegateErrorWorkflow.prototype, "llmTurn", null);
|
|
135
|
+
__decorate([
|
|
136
|
+
(0, common_1.Transition)({ from: 'prompt_executed', to: 'awaiting_tools', priority: 10 }),
|
|
137
|
+
(0, common_1.Guard)('hasToolCalls'),
|
|
138
|
+
__metadata("design:type", Function),
|
|
139
|
+
__metadata("design:paramtypes", []),
|
|
140
|
+
__metadata("design:returntype", Promise)
|
|
141
|
+
], DelegateErrorWorkflow.prototype, "executeToolCalls", null);
|
|
142
|
+
__decorate([
|
|
143
|
+
(0, common_1.Transition)({ from: 'awaiting_tools', to: 'awaiting_tools', wait: true }),
|
|
144
|
+
__metadata("design:type", Function),
|
|
145
|
+
__metadata("design:paramtypes", [Object]),
|
|
146
|
+
__metadata("design:returntype", Promise)
|
|
147
|
+
], DelegateErrorWorkflow.prototype, "toolResultReceived", null);
|
|
148
|
+
__decorate([
|
|
149
|
+
(0, common_1.Transition)({ from: 'awaiting_tools', to: 'ready' }),
|
|
150
|
+
(0, common_1.Guard)('allToolsComplete'),
|
|
151
|
+
__metadata("design:type", Function),
|
|
152
|
+
__metadata("design:paramtypes", []),
|
|
153
|
+
__metadata("design:returntype", Promise)
|
|
154
|
+
], DelegateErrorWorkflow.prototype, "toolsComplete", null);
|
|
155
|
+
__decorate([
|
|
156
|
+
(0, common_1.Transition)({ from: 'awaiting_tools', to: 'ready', wait: true }),
|
|
157
|
+
__metadata("design:type", Function),
|
|
158
|
+
__metadata("design:paramtypes", []),
|
|
159
|
+
__metadata("design:returntype", Promise)
|
|
160
|
+
], DelegateErrorWorkflow.prototype, "cancelPendingTools", null);
|
|
161
|
+
__decorate([
|
|
162
|
+
(0, common_1.Final)({ from: 'prompt_executed' }),
|
|
163
|
+
(0, common_1.Guard)('isEndTurn'),
|
|
164
|
+
__metadata("design:type", Function),
|
|
165
|
+
__metadata("design:paramtypes", []),
|
|
166
|
+
__metadata("design:returntype", Promise)
|
|
167
|
+
], DelegateErrorWorkflow.prototype, "respond", null);
|
|
168
|
+
exports.DelegateErrorWorkflow = DelegateErrorWorkflow = __decorate([
|
|
169
|
+
(0, common_1.Workflow)({
|
|
170
|
+
uiConfig: __dirname + '/delegate-error.ui.yaml',
|
|
171
|
+
})
|
|
172
|
+
], DelegateErrorWorkflow);
|
|
173
|
+
//# sourceMappingURL=delegate-error.workflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delegate-error.workflow.js","sourceRoot":"","sources":["../src/delegate-error.workflow.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC;AAChD,cAAc,2BAA2B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./delegate-error-example.module"), exports);
|
|
18
|
+
__exportStar(require("./delegate-error.workflow"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kEAAgD;AAChD,4DAA0C"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { BaseTool, ToolCallOptions, ToolResult } from '@loopstack/common';
|
|
2
|
+
export declare class FailingSubWorkflowTool extends BaseTool {
|
|
3
|
+
private failingWorkflow;
|
|
4
|
+
call(_args: object, options?: ToolCallOptions): Promise<ToolResult>;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=failing-sub-workflow.tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"failing-sub-workflow.tool.d.ts","sourceRoot":"","sources":["../../src/tools/failing-sub-workflow.tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAwB,eAAe,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGhG,qBAQa,sBAAuB,SAAQ,QAAQ;IAChC,OAAO,CAAC,eAAe,CAAkB;IAErD,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC;CAQ1E"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.FailingSubWorkflowTool = void 0;
|
|
13
|
+
const zod_1 = require("zod");
|
|
14
|
+
const common_1 = require("@loopstack/common");
|
|
15
|
+
const failing_workflow_1 = require("../workflows/failing.workflow");
|
|
16
|
+
let FailingSubWorkflowTool = class FailingSubWorkflowTool extends common_1.BaseTool {
|
|
17
|
+
failingWorkflow;
|
|
18
|
+
async call(_args, options) {
|
|
19
|
+
const result = await this.failingWorkflow.run({}, { alias: 'failingWorkflow', callback: options?.callback });
|
|
20
|
+
return {
|
|
21
|
+
data: { workflowId: result.workflowId },
|
|
22
|
+
pending: { workflowId: result.workflowId },
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
exports.FailingSubWorkflowTool = FailingSubWorkflowTool;
|
|
27
|
+
__decorate([
|
|
28
|
+
(0, common_1.InjectWorkflow)(),
|
|
29
|
+
__metadata("design:type", failing_workflow_1.FailingWorkflow)
|
|
30
|
+
], FailingSubWorkflowTool.prototype, "failingWorkflow", void 0);
|
|
31
|
+
exports.FailingSubWorkflowTool = FailingSubWorkflowTool = __decorate([
|
|
32
|
+
(0, common_1.Tool)({
|
|
33
|
+
uiConfig: {
|
|
34
|
+
description: 'Launch an async sub-workflow that always fails. ' +
|
|
35
|
+
'Used to test that failed sub-workflow errors propagate back to the parent.',
|
|
36
|
+
},
|
|
37
|
+
schema: zod_1.z.object({}),
|
|
38
|
+
})
|
|
39
|
+
], FailingSubWorkflowTool);
|
|
40
|
+
//# sourceMappingURL=failing-sub-workflow.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"failing-sub-workflow.tool.js","sourceRoot":"","sources":["../../src/tools/failing-sub-workflow.tool.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6BAAwB;AACxB,8CAAgG;AAChG,oEAAgE;AAUzD,IAAM,sBAAsB,GAA5B,MAAM,sBAAuB,SAAQ,iBAAQ;IACxB,eAAe,CAAkB;IAE3D,KAAK,CAAC,IAAI,CAAC,KAAa,EAAE,OAAyB;QACjD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;QAE7G,OAAO;YACL,IAAI,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE;YACvC,OAAO,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE;SAC3C,CAAC;IACJ,CAAC;CACF,CAAA;AAXY,wDAAsB;AACP;IAAzB,IAAA,uBAAc,GAAE;8BAA0B,kCAAe;+DAAC;iCADhD,sBAAsB;IARlC,IAAA,aAAI,EAAC;QACJ,QAAQ,EAAE;YACR,WAAW,EACT,kDAAkD;gBAClD,4EAA4E;SAC/E;QACD,MAAM,EAAE,OAAC,CAAC,MAAM,CAAC,EAAE,CAAC;KACrB,CAAC;GACW,sBAAsB,CAWlC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-error.tool.d.ts","sourceRoot":"","sources":["../../src/tools/runtime-error.tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAQ,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/D,qBAUa,gBAAiB,SAAQ,QAAQ;IAC5C,IAAI,CAAC,IAAI,EAAE;QAAE,UAAU,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC;CASzD"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.RuntimeErrorTool = void 0;
|
|
10
|
+
const zod_1 = require("zod");
|
|
11
|
+
const common_1 = require("@loopstack/common");
|
|
12
|
+
let RuntimeErrorTool = class RuntimeErrorTool extends common_1.BaseTool {
|
|
13
|
+
call(args) {
|
|
14
|
+
if (args.shouldFail) {
|
|
15
|
+
throw new Error('Simulated runtime error: external service unavailable.');
|
|
16
|
+
}
|
|
17
|
+
return Promise.resolve({
|
|
18
|
+
data: 'Action completed successfully.',
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
exports.RuntimeErrorTool = RuntimeErrorTool;
|
|
23
|
+
exports.RuntimeErrorTool = RuntimeErrorTool = __decorate([
|
|
24
|
+
(0, common_1.Tool)({
|
|
25
|
+
uiConfig: {
|
|
26
|
+
description: 'Perform an action that may fail at runtime. ' +
|
|
27
|
+
'Pass shouldFail: true to simulate a runtime error, or false to succeed.',
|
|
28
|
+
},
|
|
29
|
+
schema: zod_1.z.object({
|
|
30
|
+
shouldFail: zod_1.z.boolean().describe('Whether the tool should simulate a runtime failure.'),
|
|
31
|
+
}),
|
|
32
|
+
})
|
|
33
|
+
], RuntimeErrorTool);
|
|
34
|
+
//# sourceMappingURL=runtime-error.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-error.tool.js","sourceRoot":"","sources":["../../src/tools/runtime-error.tool.ts"],"names":[],"mappings":";;;;;;;;;AAAA,6BAAwB;AACxB,8CAA+D;AAYxD,IAAM,gBAAgB,GAAtB,MAAM,gBAAiB,SAAQ,iBAAQ;IAC5C,IAAI,CAAC,IAA6B;QAChC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;QAC5E,CAAC;QAED,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,gCAAgC;SACvC,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AAVY,4CAAgB;2BAAhB,gBAAgB;IAV5B,IAAA,aAAI,EAAC;QACJ,QAAQ,EAAE;YACR,WAAW,EACT,8CAA8C;gBAC9C,yEAAyE;SAC5E;QACD,MAAM,EAAE,OAAC,CAAC,MAAM,CAAC;YACf,UAAU,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,qDAAqD,CAAC;SACxF,CAAC;KACH,CAAC;GACW,gBAAgB,CAU5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strict-schema.tool.d.ts","sourceRoot":"","sources":["../../src/tools/strict-schema.tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAQ,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/D,qBAUa,gBAAiB,SAAQ,QAAQ;IAC5C,IAAI,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC;CAKlD"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.StrictSchemaTool = void 0;
|
|
10
|
+
const zod_1 = require("zod");
|
|
11
|
+
const common_1 = require("@loopstack/common");
|
|
12
|
+
let StrictSchemaTool = class StrictSchemaTool extends common_1.BaseTool {
|
|
13
|
+
call(args) {
|
|
14
|
+
return Promise.resolve({
|
|
15
|
+
data: `Hello, ${args.name}! Nice to meet you.`,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
exports.StrictSchemaTool = StrictSchemaTool;
|
|
20
|
+
exports.StrictSchemaTool = StrictSchemaTool = __decorate([
|
|
21
|
+
(0, common_1.Tool)({
|
|
22
|
+
uiConfig: {
|
|
23
|
+
description: 'Greet a person by name. Requires a name argument. ' + 'Returns a greeting message.',
|
|
24
|
+
},
|
|
25
|
+
schema: zod_1.z
|
|
26
|
+
.object({
|
|
27
|
+
name: zod_1.z.string().describe('The name of the person to greet.'),
|
|
28
|
+
})
|
|
29
|
+
.strict(),
|
|
30
|
+
})
|
|
31
|
+
], StrictSchemaTool);
|
|
32
|
+
//# sourceMappingURL=strict-schema.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strict-schema.tool.js","sourceRoot":"","sources":["../../src/tools/strict-schema.tool.ts"],"names":[],"mappings":";;;;;;;;;AAAA,6BAAwB;AACxB,8CAA+D;AAYxD,IAAM,gBAAgB,GAAtB,MAAM,gBAAiB,SAAQ,iBAAQ;IAC5C,IAAI,CAAC,IAAsB;QACzB,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,UAAU,IAAI,CAAC,IAAI,qBAAqB;SAC/C,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AANY,4CAAgB;2BAAhB,gBAAgB;IAV5B,IAAA,aAAI,EAAC;QACJ,QAAQ,EAAE;YACR,WAAW,EAAE,oDAAoD,GAAG,6BAA6B;SAClG;QACD,MAAM,EAAE,OAAC;aACN,MAAM,CAAC;YACN,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;SAC9D,CAAC;aACD,MAAM,EAAE;KACZ,CAAC;GACW,gBAAgB,CAM5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"failing.workflow.d.ts","sourceRoot":"","sources":["../../src/workflows/failing.workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAqB,MAAM,mBAAmB,CAAC;AAMpE,qBACa,eAAgB,SAAQ,YAAY;IAE/C,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;CAG1B"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.FailingWorkflow = void 0;
|
|
13
|
+
const common_1 = require("@loopstack/common");
|
|
14
|
+
let FailingWorkflow = class FailingWorkflow extends common_1.BaseWorkflow {
|
|
15
|
+
start() {
|
|
16
|
+
return Promise.reject(new Error('Simulated sub-workflow failure.'));
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
exports.FailingWorkflow = FailingWorkflow;
|
|
20
|
+
__decorate([
|
|
21
|
+
(0, common_1.Initial)({ to: 'done' }),
|
|
22
|
+
__metadata("design:type", Function),
|
|
23
|
+
__metadata("design:paramtypes", []),
|
|
24
|
+
__metadata("design:returntype", Promise)
|
|
25
|
+
], FailingWorkflow.prototype, "start", null);
|
|
26
|
+
exports.FailingWorkflow = FailingWorkflow = __decorate([
|
|
27
|
+
(0, common_1.Workflow)({})
|
|
28
|
+
], FailingWorkflow);
|
|
29
|
+
//# sourceMappingURL=failing.workflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"failing.workflow.js","sourceRoot":"","sources":["../../src/workflows/failing.workflow.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAAoE;AAO7D,IAAM,eAAe,GAArB,MAAM,eAAgB,SAAQ,qBAAY;IAE/C,KAAK;QACH,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAC;IACtE,CAAC;CACF,CAAA;AALY,0CAAe;AAE1B;IADC,IAAA,gBAAO,EAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;;;;4CAGvB;0BAJU,eAAe;IAD3B,IAAA,iBAAQ,EAAC,EAAE,CAAC;GACA,eAAe,CAK3B"}
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@loopstack/delegate-error-example-workflow",
|
|
3
|
+
"displayName": "Loopstack Delegate Error Example Workflow",
|
|
4
|
+
"description": "A workflow demonstrating how tool validation errors and runtime errors are handled by DelegateToolCalls and fed back to the LLM.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"error",
|
|
7
|
+
"delegate",
|
|
8
|
+
"tool calling",
|
|
9
|
+
"example",
|
|
10
|
+
"workflow"
|
|
11
|
+
],
|
|
12
|
+
"version": "0.21.6",
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"author": {
|
|
15
|
+
"name": "Jakob Klippel",
|
|
16
|
+
"url": "https://www.linkedin.com/in/jakob-klippel/"
|
|
17
|
+
},
|
|
18
|
+
"main": "dist/index.js",
|
|
19
|
+
"types": "dist/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": "./dist/index.js",
|
|
22
|
+
"./src/*": "./src/*"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "nest build",
|
|
26
|
+
"compile": "tsc --noEmit",
|
|
27
|
+
"format": "prettier --write .",
|
|
28
|
+
"lint": "eslint .",
|
|
29
|
+
"test": "jest --passWithNoTests",
|
|
30
|
+
"watch": "nest build --watch"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@loopstack/claude-module": "^0.22.5",
|
|
34
|
+
"@loopstack/common": "^0.28.0",
|
|
35
|
+
"@loopstack/core": "^0.28.0",
|
|
36
|
+
"@nestjs/common": "^11.1.19",
|
|
37
|
+
"zod": "^4.3.6"
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist",
|
|
41
|
+
"src"
|
|
42
|
+
],
|
|
43
|
+
"jest": {
|
|
44
|
+
"testEnvironment": "node",
|
|
45
|
+
"rootDir": "src",
|
|
46
|
+
"testRegex": ".*\\.spec\\.ts$",
|
|
47
|
+
"transform": {
|
|
48
|
+
"^.+\\.ts$": "ts-jest"
|
|
49
|
+
},
|
|
50
|
+
"testTimeout": 10000,
|
|
51
|
+
"forceExit": true,
|
|
52
|
+
"maxWorkers": 1
|
|
53
|
+
},
|
|
54
|
+
"loopstack": {
|
|
55
|
+
"modules": [
|
|
56
|
+
{
|
|
57
|
+
"path": "src/delegate-error-example.module.ts",
|
|
58
|
+
"className": "DelegateErrorExampleModule"
|
|
59
|
+
}
|
|
60
|
+
],
|
|
61
|
+
"workflows": [
|
|
62
|
+
{
|
|
63
|
+
"path": "src/delegate-error.workflow.ts",
|
|
64
|
+
"className": "DelegateErrorWorkflow",
|
|
65
|
+
"propertyName": "delegateError"
|
|
66
|
+
}
|
|
67
|
+
],
|
|
68
|
+
"installModes": [
|
|
69
|
+
"add",
|
|
70
|
+
"install"
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { TestingModule } from '@nestjs/testing';
|
|
2
|
+
import { ClaudeGenerateText, ClaudeModule } from '@loopstack/claude-module';
|
|
3
|
+
import { LoopCoreModule, WorkflowProcessorService } from '@loopstack/core';
|
|
4
|
+
import { ToolMock, createStatelessContext, createWorkflowTest } from '@loopstack/testing';
|
|
5
|
+
import { DelegateErrorWorkflow } from '../delegate-error.workflow';
|
|
6
|
+
import { FailingSubWorkflowTool } from '../tools/failing-sub-workflow.tool';
|
|
7
|
+
import { RuntimeErrorTool } from '../tools/runtime-error.tool';
|
|
8
|
+
import { StrictSchemaTool } from '../tools/strict-schema.tool';
|
|
9
|
+
import { FailingWorkflow } from '../workflows/failing.workflow';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Helper to create a mock LLM response with a single tool_use block.
|
|
13
|
+
*/
|
|
14
|
+
function mockToolUseResponse(toolName: string, input: Record<string, unknown>, toolUseId = 'toolu_test_1') {
|
|
15
|
+
return {
|
|
16
|
+
data: {
|
|
17
|
+
id: 'msg_test',
|
|
18
|
+
role: 'assistant',
|
|
19
|
+
stop_reason: 'tool_use',
|
|
20
|
+
content: [
|
|
21
|
+
{ type: 'text', text: `Calling ${toolName}...` },
|
|
22
|
+
{ type: 'tool_use', id: toolUseId, name: toolName, input },
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Helper to create a mock LLM response with end_turn (no tool calls).
|
|
30
|
+
*/
|
|
31
|
+
function mockEndTurnResponse(text: string) {
|
|
32
|
+
return {
|
|
33
|
+
data: {
|
|
34
|
+
id: 'msg_final',
|
|
35
|
+
role: 'assistant',
|
|
36
|
+
stop_reason: 'end_turn',
|
|
37
|
+
content: [{ type: 'text', text }],
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
describe('DelegateErrorWorkflow', () => {
|
|
43
|
+
let module: TestingModule;
|
|
44
|
+
let workflow: DelegateErrorWorkflow;
|
|
45
|
+
let processor: WorkflowProcessorService;
|
|
46
|
+
let mockClaude: ToolMock;
|
|
47
|
+
|
|
48
|
+
beforeEach(async () => {
|
|
49
|
+
module = await createWorkflowTest()
|
|
50
|
+
.forWorkflow(DelegateErrorWorkflow)
|
|
51
|
+
.withImports(LoopCoreModule, ClaudeModule)
|
|
52
|
+
.withToolOverride(ClaudeGenerateText)
|
|
53
|
+
// Real tools — we want to test actual validation and runtime errors
|
|
54
|
+
.withProviders(StrictSchemaTool, RuntimeErrorTool, FailingSubWorkflowTool, FailingWorkflow)
|
|
55
|
+
.compile();
|
|
56
|
+
|
|
57
|
+
workflow = module.get(DelegateErrorWorkflow);
|
|
58
|
+
processor = module.get(WorkflowProcessorService);
|
|
59
|
+
mockClaude = module.get(ClaudeGenerateText);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
afterEach(async () => {
|
|
63
|
+
await module.close();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should be defined', () => {
|
|
67
|
+
expect(workflow).toBeDefined();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe('validation error (bad schema args)', () => {
|
|
71
|
+
it('should capture validation error as is_error tool result and loop back to ready', async () => {
|
|
72
|
+
// LLM calls strictSchema with empty args — Zod validation will fail
|
|
73
|
+
mockClaude.call
|
|
74
|
+
.mockResolvedValueOnce(mockToolUseResponse('strictSchema', {}))
|
|
75
|
+
.mockResolvedValueOnce(mockEndTurnResponse('Done.'));
|
|
76
|
+
|
|
77
|
+
const context = createStatelessContext();
|
|
78
|
+
const result = await processor.process(workflow, {}, context);
|
|
79
|
+
|
|
80
|
+
expect(result.hasError).toBe(false);
|
|
81
|
+
expect(result.place).toBe('end');
|
|
82
|
+
|
|
83
|
+
// ClaudeGenerateText should have been called twice:
|
|
84
|
+
// 1st: LLM returns bad tool call → error fed back → loops to ready
|
|
85
|
+
// 2nd: LLM sees the error and responds with end_turn
|
|
86
|
+
expect(mockClaude.call).toHaveBeenCalledTimes(2);
|
|
87
|
+
|
|
88
|
+
// Should have tool result documents with is_error
|
|
89
|
+
const toolResultDocs = result.documents.filter((d) =>
|
|
90
|
+
d.content?.toolResults?.some((tr: { is_error?: boolean }) => tr.is_error),
|
|
91
|
+
);
|
|
92
|
+
expect(toolResultDocs.length).toBeGreaterThan(0);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe('runtime error (tool throws)', () => {
|
|
97
|
+
it('should capture runtime error as is_error tool result and loop back to ready', async () => {
|
|
98
|
+
// LLM calls runtimeError with shouldFail: true — tool will throw
|
|
99
|
+
mockClaude.call
|
|
100
|
+
.mockResolvedValueOnce(mockToolUseResponse('runtimeError', { shouldFail: true }))
|
|
101
|
+
.mockResolvedValueOnce(mockEndTurnResponse('Done.'));
|
|
102
|
+
|
|
103
|
+
const context = createStatelessContext();
|
|
104
|
+
const result = await processor.process(workflow, {}, context);
|
|
105
|
+
|
|
106
|
+
expect(result.hasError).toBe(false);
|
|
107
|
+
expect(result.place).toBe('end');
|
|
108
|
+
expect(mockClaude.call).toHaveBeenCalledTimes(2);
|
|
109
|
+
|
|
110
|
+
const toolResultDocs = result.documents.filter((d) =>
|
|
111
|
+
d.content?.toolResults?.some((tr: { is_error?: boolean }) => tr.is_error),
|
|
112
|
+
);
|
|
113
|
+
expect(toolResultDocs.length).toBeGreaterThan(0);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
describe('successful tool call', () => {
|
|
118
|
+
it('should process successful tool call without errors', async () => {
|
|
119
|
+
// LLM calls strictSchema with valid args
|
|
120
|
+
mockClaude.call
|
|
121
|
+
.mockResolvedValueOnce(mockToolUseResponse('strictSchema', { name: 'World' }))
|
|
122
|
+
.mockResolvedValueOnce(mockEndTurnResponse('Done.'));
|
|
123
|
+
|
|
124
|
+
const context = createStatelessContext();
|
|
125
|
+
const result = await processor.process(workflow, {}, context);
|
|
126
|
+
|
|
127
|
+
expect(result.hasError).toBe(false);
|
|
128
|
+
expect(result.place).toBe('end');
|
|
129
|
+
expect(mockClaude.call).toHaveBeenCalledTimes(2);
|
|
130
|
+
|
|
131
|
+
// No error tool results
|
|
132
|
+
const errorToolResults = result.documents.filter((d) =>
|
|
133
|
+
d.content?.toolResults?.some((tr: { is_error?: boolean }) => tr.is_error),
|
|
134
|
+
);
|
|
135
|
+
expect(errorToolResults).toHaveLength(0);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
describe('error metadata in tool result documents', () => {
|
|
140
|
+
it('should include validation error message in is_error tool result', async () => {
|
|
141
|
+
mockClaude.call
|
|
142
|
+
.mockResolvedValueOnce(mockToolUseResponse('strictSchema', {}))
|
|
143
|
+
.mockResolvedValueOnce(mockEndTurnResponse('Done.'));
|
|
144
|
+
|
|
145
|
+
const context = createStatelessContext();
|
|
146
|
+
const result = await processor.process(workflow, {}, context);
|
|
147
|
+
|
|
148
|
+
expect(result.hasError).toBe(false);
|
|
149
|
+
|
|
150
|
+
const toolResultDocs = result.documents.filter((d) =>
|
|
151
|
+
d.content?.toolResults?.some((tr: { is_error?: boolean }) => tr.is_error),
|
|
152
|
+
);
|
|
153
|
+
expect(toolResultDocs.length).toBeGreaterThan(0);
|
|
154
|
+
|
|
155
|
+
const errorResult = toolResultDocs[0].content.toolResults.find((tr: { is_error?: boolean }) => tr.is_error);
|
|
156
|
+
expect(errorResult.content).toBeDefined();
|
|
157
|
+
// Zod v4 error message for missing required string field
|
|
158
|
+
expect(errorResult.content).toContain('invalid_type');
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('should include runtime error message in is_error tool result', async () => {
|
|
162
|
+
mockClaude.call
|
|
163
|
+
.mockResolvedValueOnce(mockToolUseResponse('runtimeError', { shouldFail: true }))
|
|
164
|
+
.mockResolvedValueOnce(mockEndTurnResponse('Done.'));
|
|
165
|
+
|
|
166
|
+
const context = createStatelessContext();
|
|
167
|
+
const result = await processor.process(workflow, {}, context);
|
|
168
|
+
|
|
169
|
+
expect(result.hasError).toBe(false);
|
|
170
|
+
|
|
171
|
+
const toolResultDocs = result.documents.filter((d) =>
|
|
172
|
+
d.content?.toolResults?.some((tr: { is_error?: boolean }) => tr.is_error),
|
|
173
|
+
);
|
|
174
|
+
expect(toolResultDocs.length).toBeGreaterThan(0);
|
|
175
|
+
|
|
176
|
+
const errorResult = toolResultDocs[0].content.toolResults.find((tr: { is_error?: boolean }) => tr.is_error);
|
|
177
|
+
expect(errorResult.content).toContain('external service unavailable');
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
describe('validation and runtime errors produce identical structure', () => {
|
|
182
|
+
it('should produce the same is_error tool result shape for both error types', async () => {
|
|
183
|
+
// Run validation error
|
|
184
|
+
mockClaude.call.mockResolvedValueOnce(mockToolUseResponse('strictSchema', {}));
|
|
185
|
+
const context1 = createStatelessContext();
|
|
186
|
+
const result1 = await processor.process(workflow, {}, context1);
|
|
187
|
+
|
|
188
|
+
const validationErrorDoc = result1.documents.find((d) =>
|
|
189
|
+
d.content?.toolResults?.some((tr: { is_error?: boolean }) => tr.is_error),
|
|
190
|
+
);
|
|
191
|
+
const validationError = validationErrorDoc?.content.toolResults.find((tr: { is_error?: boolean }) => tr.is_error);
|
|
192
|
+
|
|
193
|
+
// Run runtime error (fresh module needed for clean state)
|
|
194
|
+
mockClaude.call.mockResolvedValueOnce(mockToolUseResponse('runtimeError', { shouldFail: true }));
|
|
195
|
+
const context2 = createStatelessContext();
|
|
196
|
+
const result2 = await processor.process(workflow, {}, context2);
|
|
197
|
+
|
|
198
|
+
const runtimeErrorDoc = result2.documents.find((d) =>
|
|
199
|
+
d.content?.toolResults?.some((tr: { is_error?: boolean }) => tr.is_error),
|
|
200
|
+
);
|
|
201
|
+
const runtimeError = runtimeErrorDoc?.content.toolResults.find((tr: { is_error?: boolean }) => tr.is_error);
|
|
202
|
+
|
|
203
|
+
// Both should have the same structure
|
|
204
|
+
expect(validationError).toBeDefined();
|
|
205
|
+
expect(runtimeError).toBeDefined();
|
|
206
|
+
expect(validationError.type).toBe('tool_result');
|
|
207
|
+
expect(runtimeError.type).toBe('tool_result');
|
|
208
|
+
expect(validationError.is_error).toBe(true);
|
|
209
|
+
expect(runtimeError.is_error).toBe(true);
|
|
210
|
+
expect(typeof validationError.content).toBe('string');
|
|
211
|
+
expect(typeof runtimeError.content).toBe('string');
|
|
212
|
+
expect(typeof validationError.tool_use_id).toBe('string');
|
|
213
|
+
expect(typeof runtimeError.tool_use_id).toBe('string');
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Module } from '@nestjs/common';
|
|
2
|
+
import { ClaudeModule } from '@loopstack/claude-module';
|
|
3
|
+
import { LoopCoreModule } from '@loopstack/core';
|
|
4
|
+
import { DelegateErrorWorkflow } from './delegate-error.workflow';
|
|
5
|
+
import { FailingSubWorkflowTool } from './tools/failing-sub-workflow.tool';
|
|
6
|
+
import { RuntimeErrorTool } from './tools/runtime-error.tool';
|
|
7
|
+
import { StrictSchemaTool } from './tools/strict-schema.tool';
|
|
8
|
+
import { FailingWorkflow } from './workflows/failing.workflow';
|
|
9
|
+
|
|
10
|
+
@Module({
|
|
11
|
+
imports: [LoopCoreModule, ClaudeModule],
|
|
12
|
+
providers: [StrictSchemaTool, RuntimeErrorTool, FailingSubWorkflowTool, FailingWorkflow, DelegateErrorWorkflow],
|
|
13
|
+
exports: [DelegateErrorWorkflow],
|
|
14
|
+
})
|
|
15
|
+
export class DelegateErrorExampleModule {}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
title: 'Delegate Error Handling Example'
|
|
2
|
+
|
|
3
|
+
description: |
|
|
4
|
+
Demonstrates how tool errors (validation, runtime, and failed sub-workflows)
|
|
5
|
+
are handled by DelegateToolCalls and fed back to the LLM for self-correction.
|
|
6
|
+
|
|
7
|
+
The workflow instructs the LLM to:
|
|
8
|
+
1. Call strictSchema with wrong args (triggers Zod validation error)
|
|
9
|
+
2. Observe the error and retry with correct args
|
|
10
|
+
3. Call runtimeError with shouldFail: true (triggers runtime error)
|
|
11
|
+
4. Observe the error and retry with shouldFail: false
|
|
12
|
+
5. Call failingSubWorkflow (launches a sub-workflow that fails)
|
|
13
|
+
6. Observe the sub-workflow error and summarize
|
|
14
|
+
|
|
15
|
+
ui:
|
|
16
|
+
widgets:
|
|
17
|
+
- widget: button
|
|
18
|
+
showWhen:
|
|
19
|
+
- awaiting_tools
|
|
20
|
+
options:
|
|
21
|
+
transition: cancelPendingTools
|
|
22
|
+
label: Cancel pending tools
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ClaudeGenerateText,
|
|
3
|
+
ClaudeGenerateTextResult,
|
|
4
|
+
ClaudeMessageDocument,
|
|
5
|
+
DelegateToolCalls,
|
|
6
|
+
DelegateToolCallsResult,
|
|
7
|
+
UpdateToolResult,
|
|
8
|
+
} from '@loopstack/claude-module';
|
|
9
|
+
import {
|
|
10
|
+
BaseWorkflow,
|
|
11
|
+
Final,
|
|
12
|
+
Guard,
|
|
13
|
+
Initial,
|
|
14
|
+
InjectTool,
|
|
15
|
+
MessageDocument,
|
|
16
|
+
ToolResult,
|
|
17
|
+
Transition,
|
|
18
|
+
Workflow,
|
|
19
|
+
} from '@loopstack/common';
|
|
20
|
+
import { FailingSubWorkflowTool } from './tools/failing-sub-workflow.tool';
|
|
21
|
+
import { RuntimeErrorTool } from './tools/runtime-error.tool';
|
|
22
|
+
import { StrictSchemaTool } from './tools/strict-schema.tool';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Demonstrates how tool errors (validation, runtime, and failed sub-workflows)
|
|
26
|
+
* are handled by DelegateToolCalls and fed back to the LLM for self-correction.
|
|
27
|
+
*
|
|
28
|
+
* The LLM is instructed to deliberately trigger errors first, then correct them.
|
|
29
|
+
* This verifies that all error types produce identical is_error tool results
|
|
30
|
+
* and that the LLM agent loop handles them correctly.
|
|
31
|
+
*/
|
|
32
|
+
@Workflow({
|
|
33
|
+
uiConfig: __dirname + '/delegate-error.ui.yaml',
|
|
34
|
+
})
|
|
35
|
+
export class DelegateErrorWorkflow extends BaseWorkflow {
|
|
36
|
+
@InjectTool() claudeGenerateText: ClaudeGenerateText;
|
|
37
|
+
@InjectTool() delegateToolCalls: DelegateToolCalls;
|
|
38
|
+
@InjectTool() updateToolResult: UpdateToolResult;
|
|
39
|
+
@InjectTool() strictSchema: StrictSchemaTool;
|
|
40
|
+
@InjectTool() runtimeError: RuntimeErrorTool;
|
|
41
|
+
@InjectTool() failingSubWorkflow: FailingSubWorkflowTool;
|
|
42
|
+
|
|
43
|
+
llmResult?: ClaudeGenerateTextResult;
|
|
44
|
+
delegateResult?: DelegateToolCallsResult;
|
|
45
|
+
turnCount!: number;
|
|
46
|
+
|
|
47
|
+
@Initial({ to: 'ready' })
|
|
48
|
+
async setup() {
|
|
49
|
+
this.turnCount = 0;
|
|
50
|
+
|
|
51
|
+
await this.repository.save(MessageDocument, {
|
|
52
|
+
role: 'assistant',
|
|
53
|
+
content:
|
|
54
|
+
'# Delegate Error Handling Example\n\n' +
|
|
55
|
+
'This workflow tests how tool errors are handled and fed back to the LLM.\n\n' +
|
|
56
|
+
'The LLM will deliberately trigger errors, then self-correct.',
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
await this.repository.save(ClaudeMessageDocument, {
|
|
60
|
+
role: 'user',
|
|
61
|
+
content:
|
|
62
|
+
'Follow the instructions in your system prompt exactly. ' +
|
|
63
|
+
'Start with step 1: call strictSchema with no arguments.',
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@Transition({ from: 'ready', to: 'prompt_executed' })
|
|
68
|
+
async llmTurn() {
|
|
69
|
+
this.turnCount++;
|
|
70
|
+
const result: ToolResult<ClaudeGenerateTextResult> = await this.claudeGenerateText.call({
|
|
71
|
+
system:
|
|
72
|
+
'You are a test assistant that follows instructions precisely. ' +
|
|
73
|
+
'You are fully autonomous — do NOT ask the user for input or confirmation. ' +
|
|
74
|
+
'Just proceed through each step on your own.\n\n' +
|
|
75
|
+
'Complete these steps IN ORDER. Do exactly one step per turn:\n\n' +
|
|
76
|
+
'1. Call the `strictSchema` tool with NO arguments (empty object {}). This will fail — that is expected.\n' +
|
|
77
|
+
'2. After seeing the validation error, call `strictSchema` correctly with { "name": "World" }.\n' +
|
|
78
|
+
'3. Call the `runtimeError` tool with { "shouldFail": true }. This will fail — that is expected.\n' +
|
|
79
|
+
'4. After seeing the runtime error, call `runtimeError` with { "shouldFail": false }.\n' +
|
|
80
|
+
'5. Call the `failingSubWorkflow` tool with {}. This launches a sub-workflow that will fail — that is expected.\n' +
|
|
81
|
+
'6. After seeing the sub-workflow error, respond with a brief summary of what happened (do NOT call any tools).\n\n' +
|
|
82
|
+
'IMPORTANT: Only perform ONE step per turn. Do NOT skip steps. Do NOT wait for user input between steps.',
|
|
83
|
+
claude: { model: 'claude-sonnet-4-6' },
|
|
84
|
+
messagesSearchTag: 'message',
|
|
85
|
+
tools: ['strictSchema', 'runtimeError', 'failingSubWorkflow'],
|
|
86
|
+
});
|
|
87
|
+
this.llmResult = result.data;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@Transition({ from: 'prompt_executed', to: 'awaiting_tools', priority: 10 })
|
|
91
|
+
@Guard('hasToolCalls')
|
|
92
|
+
async executeToolCalls() {
|
|
93
|
+
const result: ToolResult<DelegateToolCallsResult> = await this.delegateToolCalls.call({
|
|
94
|
+
message: this.llmResult!,
|
|
95
|
+
document: ClaudeMessageDocument,
|
|
96
|
+
callback: { transition: 'toolResultReceived' },
|
|
97
|
+
});
|
|
98
|
+
this.delegateResult = result.data;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@Transition({ from: 'awaiting_tools', to: 'awaiting_tools', wait: true })
|
|
102
|
+
async toolResultReceived(payload: unknown) {
|
|
103
|
+
const result = await this.updateToolResult.call({
|
|
104
|
+
delegateResult: this.delegateResult!,
|
|
105
|
+
completedTool: payload,
|
|
106
|
+
document: ClaudeMessageDocument,
|
|
107
|
+
});
|
|
108
|
+
this.delegateResult = result.data as DelegateToolCallsResult;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@Transition({ from: 'awaiting_tools', to: 'ready' })
|
|
112
|
+
@Guard('allToolsComplete')
|
|
113
|
+
async toolsComplete() {}
|
|
114
|
+
|
|
115
|
+
@Transition({ from: 'awaiting_tools', to: 'ready', wait: true })
|
|
116
|
+
async cancelPendingTools() {
|
|
117
|
+
const workflowId = this.ctx.context.workflowId;
|
|
118
|
+
if (workflowId) {
|
|
119
|
+
await this.orchestrator.cancelChildren(workflowId);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@Final({ from: 'prompt_executed' })
|
|
124
|
+
@Guard('isEndTurn')
|
|
125
|
+
async respond() {
|
|
126
|
+
await this.repository.save(ClaudeMessageDocument, this.llmResult!, { id: this.llmResult!.id });
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private hasToolCalls(): boolean {
|
|
130
|
+
return this.llmResult?.stop_reason === 'tool_use';
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private allToolsComplete(): boolean {
|
|
134
|
+
return !!this.delegateResult?.allCompleted;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private isEndTurn(): boolean {
|
|
138
|
+
return this.llmResult?.stop_reason === 'end_turn';
|
|
139
|
+
}
|
|
140
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { BaseTool, InjectWorkflow, Tool, ToolCallOptions, ToolResult } from '@loopstack/common';
|
|
3
|
+
import { FailingWorkflow } from '../workflows/failing.workflow';
|
|
4
|
+
|
|
5
|
+
@Tool({
|
|
6
|
+
uiConfig: {
|
|
7
|
+
description:
|
|
8
|
+
'Launch an async sub-workflow that always fails. ' +
|
|
9
|
+
'Used to test that failed sub-workflow errors propagate back to the parent.',
|
|
10
|
+
},
|
|
11
|
+
schema: z.object({}),
|
|
12
|
+
})
|
|
13
|
+
export class FailingSubWorkflowTool extends BaseTool {
|
|
14
|
+
@InjectWorkflow() private failingWorkflow: FailingWorkflow;
|
|
15
|
+
|
|
16
|
+
async call(_args: object, options?: ToolCallOptions): Promise<ToolResult> {
|
|
17
|
+
const result = await this.failingWorkflow.run({}, { alias: 'failingWorkflow', callback: options?.callback });
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
data: { workflowId: result.workflowId },
|
|
21
|
+
pending: { workflowId: result.workflowId },
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { BaseTool, Tool, ToolResult } from '@loopstack/common';
|
|
3
|
+
|
|
4
|
+
@Tool({
|
|
5
|
+
uiConfig: {
|
|
6
|
+
description:
|
|
7
|
+
'Perform an action that may fail at runtime. ' +
|
|
8
|
+
'Pass shouldFail: true to simulate a runtime error, or false to succeed.',
|
|
9
|
+
},
|
|
10
|
+
schema: z.object({
|
|
11
|
+
shouldFail: z.boolean().describe('Whether the tool should simulate a runtime failure.'),
|
|
12
|
+
}),
|
|
13
|
+
})
|
|
14
|
+
export class RuntimeErrorTool extends BaseTool {
|
|
15
|
+
call(args: { shouldFail: boolean }): Promise<ToolResult> {
|
|
16
|
+
if (args.shouldFail) {
|
|
17
|
+
throw new Error('Simulated runtime error: external service unavailable.');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return Promise.resolve({
|
|
21
|
+
data: 'Action completed successfully.',
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { BaseTool, Tool, ToolResult } from '@loopstack/common';
|
|
3
|
+
|
|
4
|
+
@Tool({
|
|
5
|
+
uiConfig: {
|
|
6
|
+
description: 'Greet a person by name. Requires a name argument. ' + 'Returns a greeting message.',
|
|
7
|
+
},
|
|
8
|
+
schema: z
|
|
9
|
+
.object({
|
|
10
|
+
name: z.string().describe('The name of the person to greet.'),
|
|
11
|
+
})
|
|
12
|
+
.strict(),
|
|
13
|
+
})
|
|
14
|
+
export class StrictSchemaTool extends BaseTool {
|
|
15
|
+
call(args: { name: string }): Promise<ToolResult> {
|
|
16
|
+
return Promise.resolve({
|
|
17
|
+
data: `Hello, ${args.name}! Nice to meet you.`,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseWorkflow, Initial, Workflow } from '@loopstack/common';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A minimal sub-workflow that always fails on its initial transition.
|
|
5
|
+
* Used to verify that failed sub-workflow callbacks propagate errors to the parent.
|
|
6
|
+
*/
|
|
7
|
+
@Workflow({})
|
|
8
|
+
export class FailingWorkflow extends BaseWorkflow {
|
|
9
|
+
@Initial({ to: 'done' })
|
|
10
|
+
start(): Promise<unknown> {
|
|
11
|
+
return Promise.reject(new Error('Simulated sub-workflow failure.'));
|
|
12
|
+
}
|
|
13
|
+
}
|