@loopstack/agent-example-workflow 0.2.1 → 0.3.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/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # @loopstack/agent-example-workflow
2
+
3
+ Demonstrates how to launch `AgentWorkflow` from [`@loopstack/agent`](../../features/agent-module) as a sub-workflow with custom tools (`weather_lookup`, `calculator`) and render progress/results in Studio.
4
+
5
+ ## By using this example you'll get...
6
+
7
+ - A parent workflow that queues `AgentWorkflow` via `WORKFLOW_ORCHESTRATOR`
8
+ - A `LinkDocument` that embeds the running child workflow
9
+ - A callback transition that stores the final agent response as a `MessageDocument`
10
+
11
+ ## Installation
12
+
13
+ ```sh
14
+ npm install @loopstack/agent-example-workflow
15
+ ```
16
+
17
+ `@loopstack/agent` requires an LLM provider configuration. Use `AgentExampleModule.forFeature({ llm: ... })` when you want to override provider config per module.
18
+
19
+ ## How It Works
20
+
21
+ 1. `start` queues `AgentWorkflow` with a system prompt and selected tools.
22
+ 2. A `LinkDocument` is saved to show embedded progress in Studio.
23
+ 3. When the child workflow finishes, `agentComplete` receives callback payload data.
24
+ 4. The workflow marks the link as successful and saves the final assistant message.
25
+
26
+ ## Public API
27
+
28
+ - `AgentExampleModule`
29
+ - `AgentExampleWorkflow`
30
+ - `CalculatorTool`
31
+ - `WeatherLookupTool`
32
+
33
+ ## Dependencies
34
+
35
+ - `@loopstack/common`
36
+ - `@loopstack/agent`
@@ -1,3 +1,8 @@
1
+ import { DynamicModule } from '@nestjs/common';
2
+ import type { LlmModuleConfig } from '@loopstack/llm-provider-module';
1
3
  export declare class AgentExampleModule {
4
+ static forFeature(config?: {
5
+ llm?: LlmModuleConfig;
6
+ }): DynamicModule;
2
7
  }
3
8
  //# sourceMappingURL=agent-example.module.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent-example.module.d.ts","sourceRoot":"","sources":["../src/agent-example.module.ts"],"names":[],"mappings":"AAMA,qBAKa,kBAAkB;CAAG"}
1
+ {"version":3,"file":"agent-example.module.d.ts","sourceRoot":"","sources":["../src/agent-example.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAU,MAAM,gBAAgB,CAAC;AAEvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAUtE,qBAKa,kBAAkB;IAC7B,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,eAAe,CAAA;KAAE,GAAG,aAAa;CAQrE"}
@@ -12,14 +12,28 @@ const agent_1 = require("@loopstack/agent");
12
12
  const agent_example_workflow_1 = require("./agent-example.workflow");
13
13
  const calculator_tool_1 = require("./tools/calculator.tool");
14
14
  const weather_lookup_tool_1 = require("./tools/weather-lookup.tool");
15
+ const PROVIDERS = [agent_example_workflow_1.AgentExampleWorkflow, calculator_tool_1.CalculatorTool, weather_lookup_tool_1.WeatherLookupTool];
16
+ let AgentExampleRootModule = class AgentExampleRootModule {
17
+ };
18
+ AgentExampleRootModule = __decorate([
19
+ (0, common_1.Module)({})
20
+ ], AgentExampleRootModule);
15
21
  let AgentExampleModule = class AgentExampleModule {
22
+ static forFeature(config) {
23
+ return {
24
+ module: AgentExampleRootModule,
25
+ imports: [agent_1.AgentModule.forFeature(config)],
26
+ providers: PROVIDERS,
27
+ exports: PROVIDERS,
28
+ };
29
+ }
16
30
  };
17
31
  exports.AgentExampleModule = AgentExampleModule;
18
32
  exports.AgentExampleModule = AgentExampleModule = __decorate([
19
33
  (0, common_1.Module)({
20
34
  imports: [agent_1.AgentModule],
21
- providers: [agent_example_workflow_1.AgentExampleWorkflow, calculator_tool_1.CalculatorTool, weather_lookup_tool_1.WeatherLookupTool],
22
- exports: [agent_example_workflow_1.AgentExampleWorkflow, calculator_tool_1.CalculatorTool, weather_lookup_tool_1.WeatherLookupTool],
35
+ providers: PROVIDERS,
36
+ exports: PROVIDERS,
23
37
  })
24
38
  ], AgentExampleModule);
25
39
  //# sourceMappingURL=agent-example.module.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent-example.module.js","sourceRoot":"","sources":["../src/agent-example.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,4CAA+C;AAC/C,qEAAgE;AAChE,6DAAyD;AACzD,qEAAgE;AAOzD,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;CAAG,CAAA;AAArB,gDAAkB;6BAAlB,kBAAkB;IAL9B,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,mBAAW,CAAC;QACtB,SAAS,EAAE,CAAC,6CAAoB,EAAE,gCAAc,EAAE,uCAAiB,CAAC;QACpE,OAAO,EAAE,CAAC,6CAAoB,EAAE,gCAAc,EAAE,uCAAiB,CAAC;KACnE,CAAC;GACW,kBAAkB,CAAG"}
1
+ {"version":3,"file":"agent-example.module.js","sourceRoot":"","sources":["../src/agent-example.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAuD;AACvD,4CAA+C;AAE/C,qEAAgE;AAChE,6DAAyD;AACzD,qEAAgE;AAEhE,MAAM,SAAS,GAAG,CAAC,6CAAoB,EAAE,gCAAc,EAAE,uCAAiB,CAAC,CAAC;AAG5E,IAAM,sBAAsB,GAA5B,MAAM,sBAAsB;CAAG,CAAA;AAAzB,sBAAsB;IAD3B,IAAA,eAAM,EAAC,EAAE,CAAC;GACL,sBAAsB,CAAG;AAOxB,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAC7B,MAAM,CAAC,UAAU,CAAC,MAAkC;QAClD,OAAO;YACL,MAAM,EAAE,sBAAsB;YAC9B,OAAO,EAAE,CAAC,mBAAW,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YACzC,SAAS,EAAE,SAAS;YACpB,OAAO,EAAE,SAAS;SACnB,CAAC;IACJ,CAAC;CACF,CAAA;AATY,gDAAkB;6BAAlB,kBAAkB;IAL9B,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,mBAAW,CAAC;QACtB,SAAS,EAAE,SAAS;QACpB,OAAO,EAAE,SAAS;KACnB,CAAC;GACW,kBAAkB,CAS9B"}
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { AgentWorkflow } from '@loopstack/agent';
2
3
  import { BaseWorkflow } from '@loopstack/common';
3
4
  declare const AgentCallbackSchema: z.ZodObject<{
4
5
  workflowId: z.ZodString;
@@ -9,9 +10,10 @@ declare const AgentCallbackSchema: z.ZodObject<{
9
10
  }, z.core.$strip>;
10
11
  type AgentCallback = z.infer<typeof AgentCallbackSchema>;
11
12
  export declare class AgentExampleWorkflow extends BaseWorkflow {
12
- private agent;
13
- start(): Promise<void>;
14
- agentComplete(payload: AgentCallback): Promise<void>;
13
+ private readonly agentWorkflow;
14
+ constructor(agentWorkflow: AgentWorkflow);
15
+ start(state: Record<string, unknown>): Promise<Record<string, unknown>>;
16
+ agentComplete(state: Record<string, unknown>, payload: AgentCallback): Promise<unknown>;
15
17
  }
16
18
  export {};
17
19
  //# sourceMappingURL=agent-example.workflow.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent-example.workflow.d.ts","sourceRoot":"","sources":["../src/agent-example.workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EACL,YAAY,EASb,MAAM,mBAAmB,CAAC;AAE3B,QAAA,MAAM,mBAAmB;;;;;;iBAEvB,CAAC;AAEH,KAAK,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEzD,qBAGa,oBAAqB,SAAQ,YAAY;IAClC,OAAO,CAAC,KAAK,CAAgB;IAGzC,KAAK;IAsBL,aAAa,CAAC,OAAO,EAAE,aAAa;CAY3C"}
1
+ {"version":3,"file":"agent-example.workflow.d.ts","sourceRoot":"","sources":["../src/agent-example.workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EACL,YAAY,EAOb,MAAM,mBAAmB,CAAC;AAE3B,QAAA,MAAM,mBAAmB;;;;;;iBAEvB,CAAC;AAEH,KAAK,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEzD,qBAIa,oBAAqB,SAAQ,YAAY;IACxC,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAAb,aAAa,EAAE,aAAa;IAKnD,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAwBvE,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC;CAa9F"}
@@ -17,47 +17,52 @@ const AgentCallbackSchema = common_1.CallbackSchema.extend({
17
17
  data: zod_1.z.object({ response: zod_1.z.string() }),
18
18
  });
19
19
  let AgentExampleWorkflow = class AgentExampleWorkflow extends common_1.BaseWorkflow {
20
- agent;
21
- async start() {
22
- const result = await this.agent.run({
20
+ agentWorkflow;
21
+ constructor(agentWorkflow) {
22
+ super();
23
+ this.agentWorkflow = agentWorkflow;
24
+ }
25
+ async start(state) {
26
+ const result = await this.agentWorkflow.run({
23
27
  system: this.render(__dirname + '/templates/system.md'),
24
- tools: ['weatherLookup', 'calculator'],
28
+ tools: ['weather_lookup', 'calculator'],
25
29
  userMessage: "What's the weather in Tokyo? Also, what is 42 * 17?",
26
- }, { alias: 'agent', callback: { transition: 'agentComplete' } });
27
- await this.repository.save(common_1.LinkDocument, { label: 'Agent working...', workflowId: result.workflowId, embed: true, expanded: true }, { id: `link_${result.workflowId}` });
30
+ }, { callback: { transition: 'agentComplete' } });
31
+ await this.documentStore.save(common_1.LinkDocument, { label: 'Agent working...', workflowId: result.workflowId, embed: true, expanded: true }, { id: `link_${result.workflowId}` });
32
+ return state;
28
33
  }
29
- async agentComplete(payload) {
30
- await this.repository.save(common_1.LinkDocument, { label: 'Agent complete', status: 'success', workflowId: payload.workflowId }, { id: `link_${payload.workflowId}` });
31
- await this.repository.save(common_1.MessageDocument, {
34
+ async agentComplete(state, payload) {
35
+ await this.documentStore.save(common_1.LinkDocument, { label: 'Agent complete', status: 'success', workflowId: payload.workflowId }, { id: `link_${payload.workflowId}` });
36
+ await this.documentStore.save(common_1.MessageDocument, {
32
37
  role: 'assistant',
33
38
  content: payload.data.response,
34
39
  });
40
+ return {};
35
41
  }
36
42
  };
37
43
  exports.AgentExampleWorkflow = AgentExampleWorkflow;
38
44
  __decorate([
39
- (0, common_1.InjectWorkflow)(),
40
- __metadata("design:type", agent_1.AgentWorkflow)
41
- ], AgentExampleWorkflow.prototype, "agent", void 0);
42
- __decorate([
43
- (0, common_1.Initial)({ to: 'running' }),
45
+ (0, common_1.Transition)({ to: 'running' }),
44
46
  __metadata("design:type", Function),
45
- __metadata("design:paramtypes", []),
47
+ __metadata("design:paramtypes", [Object]),
46
48
  __metadata("design:returntype", Promise)
47
49
  ], AgentExampleWorkflow.prototype, "start", null);
48
50
  __decorate([
49
- (0, common_1.Final)({
51
+ (0, common_1.Transition)({
50
52
  from: 'running',
53
+ to: 'end',
51
54
  wait: true,
52
55
  schema: AgentCallbackSchema,
53
56
  }),
54
57
  __metadata("design:type", Function),
55
- __metadata("design:paramtypes", [Object]),
58
+ __metadata("design:paramtypes", [Object, Object]),
56
59
  __metadata("design:returntype", Promise)
57
60
  ], AgentExampleWorkflow.prototype, "agentComplete", null);
58
61
  exports.AgentExampleWorkflow = AgentExampleWorkflow = __decorate([
59
62
  (0, common_1.Workflow)({
60
- uiConfig: __dirname + '/agent-example.ui.yaml',
61
- })
63
+ title: 'Agent Example',
64
+ description: 'Launches a generic agent sub-workflow with weather and calculator tools.',
65
+ }),
66
+ __metadata("design:paramtypes", [agent_1.AgentWorkflow])
62
67
  ], AgentExampleWorkflow);
63
68
  //# sourceMappingURL=agent-example.workflow.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent-example.workflow.js","sourceRoot":"","sources":["../src/agent-example.workflow.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6BAAwB;AACxB,4CAAiD;AACjD,8CAU2B;AAE3B,MAAM,mBAAmB,GAAG,uBAAc,CAAC,MAAM,CAAC;IAChD,IAAI,EAAE,OAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,EAAE,CAAC;CACzC,CAAC,CAAC;AAOI,IAAM,oBAAoB,GAA1B,MAAM,oBAAqB,SAAQ,qBAAY;IAC1B,KAAK,CAAgB;IAGzC,AAAN,KAAK,CAAC,KAAK;QACT,MAAM,MAAM,GAAgB,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAC9C;YACE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,GAAG,sBAAsB,CAAC;YACvD,KAAK,EAAE,CAAC,eAAe,EAAE,YAAY,CAAC;YACtC,WAAW,EAAE,qDAAqD;SACnE,EACD,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,eAAe,EAAE,EAAE,CAC9D,CAAC;QAEF,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CACxB,qBAAY,EACZ,EAAE,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EACzF,EAAE,EAAE,EAAE,QAAQ,MAAM,CAAC,UAAU,EAAE,EAAE,CACpC,CAAC;IACJ,CAAC;IAOK,AAAN,KAAK,CAAC,aAAa,CAAC,OAAsB;QACxC,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CACxB,qBAAY,EACZ,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,EAC9E,EAAE,EAAE,EAAE,QAAQ,OAAO,CAAC,UAAU,EAAE,EAAE,CACrC,CAAC;QAEF,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,wBAAe,EAAE;YAC1C,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ;SAC/B,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AAtCY,oDAAoB;AACL;IAAzB,IAAA,uBAAc,GAAE;8BAAgB,qBAAa;mDAAC;AAGzC;IADL,IAAA,gBAAO,EAAC,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC;;;;iDAgB1B;AAOK;IALL,IAAA,cAAK,EAAC;QACL,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,mBAAmB;KAC5B,CAAC;;;;yDAYD;+BArCU,oBAAoB;IAHhC,IAAA,iBAAQ,EAAC;QACR,QAAQ,EAAE,SAAS,GAAG,wBAAwB;KAC/C,CAAC;GACW,oBAAoB,CAsChC"}
1
+ {"version":3,"file":"agent-example.workflow.js","sourceRoot":"","sources":["../src/agent-example.workflow.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6BAAwB;AACxB,4CAAiD;AACjD,8CAQ2B;AAE3B,MAAM,mBAAmB,GAAG,uBAAc,CAAC,MAAM,CAAC;IAChD,IAAI,EAAE,OAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,EAAE,CAAC;CACzC,CAAC,CAAC;AAQI,IAAM,oBAAoB,GAA1B,MAAM,oBAAqB,SAAQ,qBAAY;IACvB;IAA7B,YAA6B,aAA4B;QACvD,KAAK,EAAE,CAAC;QADmB,kBAAa,GAAb,aAAa,CAAe;IAEzD,CAAC;IAGK,AAAN,KAAK,CAAC,KAAK,CAAC,KAA8B;QACxC,MAAM,MAAM,GAAgB,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CACtD;YACE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,GAAG,sBAAsB,CAAC;YACvD,KAAK,EAAE,CAAC,gBAAgB,EAAE,YAAY,CAAC;YACvC,WAAW,EAAE,qDAAqD;SACnE,EACD,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,eAAe,EAAE,EAAE,CAC9C,CAAC;QAEF,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAC3B,qBAAY,EACZ,EAAE,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EACzF,EAAE,EAAE,EAAE,QAAQ,MAAM,CAAC,UAAU,EAAE,EAAE,CACpC,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC;IAQK,AAAN,KAAK,CAAC,aAAa,CAAC,KAA8B,EAAE,OAAsB;QACxE,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAC3B,qBAAY,EACZ,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,EAC9E,EAAE,EAAE,EAAE,QAAQ,OAAO,CAAC,UAAU,EAAE,EAAE,CACrC,CAAC;QAEF,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,wBAAe,EAAE;YAC7C,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ;SAC/B,CAAC,CAAC;QACH,OAAO,EAAE,CAAC;IACZ,CAAC;CACF,CAAA;AA3CY,oDAAoB;AAMzB;IADL,IAAA,mBAAU,EAAC,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC;;;;iDAiB7B;AAQK;IANL,IAAA,mBAAU,EAAC;QACV,IAAI,EAAE,SAAS;QACf,EAAE,EAAE,KAAK;QACT,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,mBAAmB;KAC5B,CAAC;;;;yDAaD;+BA1CU,oBAAoB;IAJhC,IAAA,iBAAQ,EAAC;QACR,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,0EAA0E;KACxF,CAAC;qCAE4C,qBAAa;GAD9C,oBAAoB,CA2ChC"}
@@ -1,9 +1,15 @@
1
1
  import { BaseTool, ToolResult } from '@loopstack/common';
2
- export declare class CalculatorTool extends BaseTool {
3
- call(args: {
2
+ import type { LoopstackContext } from '@loopstack/common';
3
+ export type CalculatorResult = string;
4
+ export declare class CalculatorTool extends BaseTool<{
5
+ operation: string;
6
+ a: number;
7
+ b: number;
8
+ }, object, CalculatorResult> {
9
+ protected handle(args: {
4
10
  operation: string;
5
11
  a: number;
6
12
  b: number;
7
- }): Promise<ToolResult>;
13
+ }, _ctx: LoopstackContext): Promise<ToolResult<CalculatorResult>>;
8
14
  }
9
15
  //# sourceMappingURL=calculator.tool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"calculator.tool.d.ts","sourceRoot":"","sources":["../../src/tools/calculator.tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAQ,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/D,qBAUa,cAAe,SAAQ,QAAQ;IAC1C,IAAI,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC;CA2B7E"}
1
+ {"version":3,"file":"calculator.tool.d.ts","sourceRoot":"","sources":["../../src/tools/calculator.tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAQ,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEtC,qBASa,cAAe,SAAQ,QAAQ,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,MAAM,EAAE,gBAAgB,CAAC;cACjG,MAAM,CACpB,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,EACjD,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;CA2BzC"}
@@ -10,7 +10,7 @@ exports.CalculatorTool = void 0;
10
10
  const zod_1 = require("zod");
11
11
  const common_1 = require("@loopstack/common");
12
12
  let CalculatorTool = class CalculatorTool extends common_1.BaseTool {
13
- call(args) {
13
+ async handle(args, _ctx) {
14
14
  let result;
15
15
  switch (args.operation) {
16
16
  case 'add':
@@ -24,24 +24,23 @@ let CalculatorTool = class CalculatorTool extends common_1.BaseTool {
24
24
  break;
25
25
  case 'divide':
26
26
  if (args.b === 0) {
27
- return Promise.resolve({ data: 'Error: Division by zero', error: 'Cannot divide by zero' });
27
+ return { data: 'Error: Division by zero', error: 'Cannot divide by zero' };
28
28
  }
29
29
  result = args.a / args.b;
30
30
  break;
31
31
  default:
32
- return Promise.resolve({ data: `Unknown operation: ${args.operation}`, error: 'Unsupported operation' });
32
+ return { data: `Unknown operation: ${args.operation}`, error: 'Unsupported operation' };
33
33
  }
34
- return Promise.resolve({
34
+ return {
35
35
  data: `${args.a} ${args.operation} ${args.b} = ${result}`,
36
- });
36
+ };
37
37
  }
38
38
  };
39
39
  exports.CalculatorTool = CalculatorTool;
40
40
  exports.CalculatorTool = CalculatorTool = __decorate([
41
41
  (0, common_1.Tool)({
42
- uiConfig: {
43
- description: 'Perform a basic arithmetic calculation. Supports add, subtract, multiply, divide.',
44
- },
42
+ name: 'calculator',
43
+ description: 'Perform a basic arithmetic calculation. Supports add, subtract, multiply, divide.',
45
44
  schema: zod_1.z.object({
46
45
  operation: zod_1.z.enum(['add', 'subtract', 'multiply', 'divide']).describe('The arithmetic operation.'),
47
46
  a: zod_1.z.number().describe('First operand.'),
@@ -1 +1 @@
1
- {"version":3,"file":"calculator.tool.js","sourceRoot":"","sources":["../../src/tools/calculator.tool.ts"],"names":[],"mappings":";;;;;;;;;AAAA,6BAAwB;AACxB,8CAA+D;AAYxD,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,iBAAQ;IAC1C,IAAI,CAAC,IAAiD;QACpD,IAAI,MAAc,CAAC;QAEnB,QAAQ,IAAI,CAAC,SAAS,EAAE,CAAC;YACvB,KAAK,KAAK;gBACR,MAAM,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;gBACzB,MAAM;YACR,KAAK,UAAU;gBACb,MAAM,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;gBACzB,MAAM;YACR,KAAK,UAAU;gBACb,MAAM,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;gBACzB,MAAM;YACR,KAAK,QAAQ;gBACX,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;oBACjB,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,yBAAyB,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC,CAAC;gBAC9F,CAAC;gBACD,MAAM,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;gBACzB,MAAM;YACR;gBACE,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,sBAAsB,IAAI,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC,CAAC;QAC7G,CAAC;QAED,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,MAAM,MAAM,EAAE;SAC1D,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AA5BY,wCAAc;yBAAd,cAAc;IAV1B,IAAA,aAAI,EAAC;QACJ,QAAQ,EAAE;YACR,WAAW,EAAE,mFAAmF;SACjG;QACD,MAAM,EAAE,OAAC,CAAC,MAAM,CAAC;YACf,SAAS,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,2BAA2B,CAAC;YAClG,CAAC,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC;YACxC,CAAC,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;SAC1C,CAAC;KACH,CAAC;GACW,cAAc,CA4B1B"}
1
+ {"version":3,"file":"calculator.tool.js","sourceRoot":"","sources":["../../src/tools/calculator.tool.ts"],"names":[],"mappings":";;;;;;;;;AAAA,6BAAwB;AACxB,8CAA+D;AAcxD,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,iBAA+E;IACvG,KAAK,CAAC,MAAM,CACpB,IAAiD,EACjD,IAAsB;QAEtB,IAAI,MAAc,CAAC;QAEnB,QAAQ,IAAI,CAAC,SAAS,EAAE,CAAC;YACvB,KAAK,KAAK;gBACR,MAAM,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;gBACzB,MAAM;YACR,KAAK,UAAU;gBACb,MAAM,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;gBACzB,MAAM;YACR,KAAK,UAAU;gBACb,MAAM,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;gBACzB,MAAM;YACR,KAAK,QAAQ;gBACX,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;oBACjB,OAAO,EAAE,IAAI,EAAE,yBAAyB,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC;gBAC7E,CAAC;gBACD,MAAM,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;gBACzB,MAAM;YACR;gBACE,OAAO,EAAE,IAAI,EAAE,sBAAsB,IAAI,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC;QAC5F,CAAC;QAED,OAAO;YACL,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,MAAM,MAAM,EAAE;SAC1D,CAAC;IACJ,CAAC;CACF,CAAA;AA/BY,wCAAc;yBAAd,cAAc;IAT1B,IAAA,aAAI,EAAC;QACJ,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,mFAAmF;QAChG,MAAM,EAAE,OAAC,CAAC,MAAM,CAAC;YACf,SAAS,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,2BAA2B,CAAC;YAClG,CAAC,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC;YACxC,CAAC,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;SAC1C,CAAC;KACH,CAAC;GACW,cAAc,CA+B1B"}
@@ -1,7 +1,11 @@
1
1
  import { BaseTool, ToolResult } from '@loopstack/common';
2
- export declare class WeatherLookupTool extends BaseTool {
3
- call(args: {
2
+ import type { LoopstackContext } from '@loopstack/common';
3
+ export type WeatherLookupResult = string;
4
+ export declare class WeatherLookupTool extends BaseTool<{
5
+ city: string;
6
+ }, object, WeatherLookupResult> {
7
+ protected handle(args: {
4
8
  city: string;
5
- }): Promise<ToolResult>;
9
+ }, _ctx: LoopstackContext): Promise<ToolResult<WeatherLookupResult>>;
6
10
  }
7
11
  //# sourceMappingURL=weather-lookup.tool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"weather-lookup.tool.d.ts","sourceRoot":"","sources":["../../src/tools/weather-lookup.tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAQ,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/D,qBAQa,iBAAkB,SAAQ,QAAQ;IAC7C,IAAI,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC;CAelD"}
1
+ {"version":3,"file":"weather-lookup.tool.d.ts","sourceRoot":"","sources":["../../src/tools/weather-lookup.tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAQ,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC;AAEzC,qBAOa,iBAAkB,SAAQ,QAAQ,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,MAAM,EAAE,mBAAmB,CAAC;cAC5E,MAAM,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;CAejH"}
@@ -10,7 +10,7 @@ exports.WeatherLookupTool = void 0;
10
10
  const zod_1 = require("zod");
11
11
  const common_1 = require("@loopstack/common");
12
12
  let WeatherLookupTool = class WeatherLookupTool extends common_1.BaseTool {
13
- call(args) {
13
+ async handle(args, _ctx) {
14
14
  const forecasts = {
15
15
  london: '14°C, cloudy with light rain',
16
16
  tokyo: '22°C, sunny with clear skies',
@@ -26,9 +26,8 @@ let WeatherLookupTool = class WeatherLookupTool extends common_1.BaseTool {
26
26
  exports.WeatherLookupTool = WeatherLookupTool;
27
27
  exports.WeatherLookupTool = WeatherLookupTool = __decorate([
28
28
  (0, common_1.Tool)({
29
- uiConfig: {
30
- description: 'Look up the current weather for a given city. Returns a simulated forecast.',
31
- },
29
+ name: 'weather_lookup',
30
+ description: 'Look up the current weather for a given city. Returns a simulated forecast.',
32
31
  schema: zod_1.z.object({
33
32
  city: zod_1.z.string().describe('The city name to look up weather for.'),
34
33
  }),
@@ -1 +1 @@
1
- {"version":3,"file":"weather-lookup.tool.js","sourceRoot":"","sources":["../../src/tools/weather-lookup.tool.ts"],"names":[],"mappings":";;;;;;;;;AAAA,6BAAwB;AACxB,8CAA+D;AAUxD,IAAM,iBAAiB,GAAvB,MAAM,iBAAkB,SAAQ,iBAAQ;IAC7C,IAAI,CAAC,IAAsB;QAEzB,MAAM,SAAS,GAA2B;YACxC,MAAM,EAAE,8BAA8B;YACtC,KAAK,EAAE,8BAA8B;YACrC,UAAU,EAAE,qBAAqB;SAClC,CAAC;QAEF,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,2BAA2B,CAAC;QAE9D,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,cAAc,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE;SAC5C,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AAhBY,8CAAiB;4BAAjB,iBAAiB;IAR7B,IAAA,aAAI,EAAC;QACJ,QAAQ,EAAE;YACR,WAAW,EAAE,6EAA6E;SAC3F;QACD,MAAM,EAAE,OAAC,CAAC,MAAM,CAAC;YACf,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;SACnE,CAAC;KACH,CAAC;GACW,iBAAiB,CAgB7B"}
1
+ {"version":3,"file":"weather-lookup.tool.js","sourceRoot":"","sources":["../../src/tools/weather-lookup.tool.ts"],"names":[],"mappings":";;;;;;;;;AAAA,6BAAwB;AACxB,8CAA+D;AAYxD,IAAM,iBAAiB,GAAvB,MAAM,iBAAkB,SAAQ,iBAAuD;IAClF,KAAK,CAAC,MAAM,CAAC,IAAsB,EAAE,IAAsB;QAEnE,MAAM,SAAS,GAA2B;YACxC,MAAM,EAAE,8BAA8B;YACtC,KAAK,EAAE,8BAA8B;YACrC,UAAU,EAAE,qBAAqB;SAClC,CAAC;QAEF,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,2BAA2B,CAAC;QAE9D,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,cAAc,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE;SAC5C,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AAhBY,8CAAiB;4BAAjB,iBAAiB;IAP7B,IAAA,aAAI,EAAC;QACJ,IAAI,EAAE,gBAAgB;QACtB,WAAW,EAAE,6EAA6E;QAC1F,MAAM,EAAE,OAAC,CAAC,MAAM,CAAC;YACf,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;SACnE,CAAC;KACH,CAAC;GACW,iBAAiB,CAgB7B"}
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "claude",
10
10
  "sub-workflow"
11
11
  ],
12
- "version": "0.2.1",
12
+ "version": "0.3.1",
13
13
  "license": "MIT",
14
14
  "author": {
15
15
  "name": "Jakob Klippel",
@@ -30,9 +30,8 @@
30
30
  "watch": "nest build --watch"
31
31
  },
32
32
  "dependencies": {
33
- "@loopstack/agent": "^0.4.1",
34
- "@loopstack/common": "^0.31.0",
35
- "@loopstack/core": "^0.31.0",
33
+ "@loopstack/agent": "^0.5.0",
34
+ "@loopstack/common": "^0.32.1",
36
35
  "@nestjs/common": "^11.1.19",
37
36
  "zod": "^4.3.6"
38
37
  },
@@ -8,22 +8,22 @@ import { AgentExampleWorkflow } from '../agent-example.workflow';
8
8
  import { CalculatorTool } from '../tools/calculator.tool';
9
9
  import { WeatherLookupTool } from '../tools/weather-lookup.tool';
10
10
 
11
+ const mockAgentWorkflow = {
12
+ run: vi.fn(),
13
+ };
14
+
11
15
  describe('AgentExampleWorkflow', () => {
12
16
  let module: TestingModule;
13
17
  let workflow: AgentExampleWorkflow;
14
18
  let processor: WorkflowProcessorService;
15
19
 
16
- const mockAgent = {
17
- run: vi.fn(),
18
- };
19
-
20
20
  beforeEach(async () => {
21
21
  vi.clearAllMocks();
22
22
 
23
23
  module = await createWorkflowTest()
24
24
  .forWorkflow(AgentExampleWorkflow)
25
25
  .withProviders(CalculatorTool, WeatherLookupTool)
26
- .withMock(AgentWorkflow, mockAgent)
26
+ .withMock(AgentWorkflow, mockAgentWorkflow)
27
27
  .compile();
28
28
 
29
29
  workflow = module.get(AgentExampleWorkflow);
@@ -35,7 +35,7 @@ describe('AgentExampleWorkflow', () => {
35
35
  });
36
36
 
37
37
  it('launches AgentWorkflow and stops at running', async () => {
38
- mockAgent.run.mockResolvedValue({ workflowId: 'agent-sub-id' });
38
+ mockAgentWorkflow.run.mockResolvedValue({ workflowId: 'agent-sub-id' });
39
39
 
40
40
  const result = await processor.process(workflow, {}, createStatelessContext());
41
41
 
@@ -43,19 +43,19 @@ describe('AgentExampleWorkflow', () => {
43
43
  expect(result.stop).toBe(true);
44
44
  expect(result.place).toBe('running');
45
45
 
46
- expect(mockAgent.run).toHaveBeenCalledWith(
46
+ expect(mockAgentWorkflow.run).toHaveBeenCalledWith(
47
47
  expect.objectContaining({
48
48
  system: expect.any(String),
49
- tools: ['weatherLookup', 'calculator'],
49
+ tools: ['weather_lookup', 'calculator'],
50
50
  userMessage: expect.any(String),
51
51
  }),
52
- expect.objectContaining({ alias: 'agent', callback: { transition: 'agentComplete' } }),
52
+ { callback: { transition: 'agentComplete' } },
53
53
  );
54
54
 
55
55
  expect(result.documents).toEqual(
56
56
  expect.arrayContaining([
57
57
  expect.objectContaining({
58
- className: 'LinkDocument',
58
+ documentName: 'link',
59
59
  content: expect.objectContaining({ workflowId: 'agent-sub-id' }),
60
60
  }),
61
61
  ]),
@@ -89,7 +89,7 @@ describe('AgentExampleWorkflow', () => {
89
89
  expect(result.documents).toEqual(
90
90
  expect.arrayContaining([
91
91
  expect.objectContaining({
92
- className: 'MessageDocument',
92
+ documentName: 'message',
93
93
  content: expect.objectContaining({ content: expect.stringContaining('714') }),
94
94
  }),
95
95
  ]),
@@ -1,12 +1,27 @@
1
- import { Module } from '@nestjs/common';
1
+ import { DynamicModule, Module } from '@nestjs/common';
2
2
  import { AgentModule } from '@loopstack/agent';
3
+ import type { LlmModuleConfig } from '@loopstack/llm-provider-module';
3
4
  import { AgentExampleWorkflow } from './agent-example.workflow';
4
5
  import { CalculatorTool } from './tools/calculator.tool';
5
6
  import { WeatherLookupTool } from './tools/weather-lookup.tool';
6
7
 
8
+ const PROVIDERS = [AgentExampleWorkflow, CalculatorTool, WeatherLookupTool];
9
+
10
+ @Module({})
11
+ class AgentExampleRootModule {}
12
+
7
13
  @Module({
8
14
  imports: [AgentModule],
9
- providers: [AgentExampleWorkflow, CalculatorTool, WeatherLookupTool],
10
- exports: [AgentExampleWorkflow, CalculatorTool, WeatherLookupTool],
15
+ providers: PROVIDERS,
16
+ exports: PROVIDERS,
11
17
  })
12
- export class AgentExampleModule {}
18
+ export class AgentExampleModule {
19
+ static forFeature(config?: { llm?: LlmModuleConfig }): DynamicModule {
20
+ return {
21
+ module: AgentExampleRootModule,
22
+ imports: [AgentModule.forFeature(config)],
23
+ providers: PROVIDERS,
24
+ exports: PROVIDERS,
25
+ };
26
+ }
27
+ }
@@ -3,12 +3,10 @@ import { AgentWorkflow } from '@loopstack/agent';
3
3
  import {
4
4
  BaseWorkflow,
5
5
  CallbackSchema,
6
- Final,
7
- Initial,
8
- InjectWorkflow,
9
6
  LinkDocument,
10
7
  MessageDocument,
11
8
  QueueResult,
9
+ Transition,
12
10
  Workflow,
13
11
  } from '@loopstack/common';
14
12
 
@@ -19,44 +17,50 @@ const AgentCallbackSchema = CallbackSchema.extend({
19
17
  type AgentCallback = z.infer<typeof AgentCallbackSchema>;
20
18
 
21
19
  @Workflow({
22
- uiConfig: __dirname + '/agent-example.ui.yaml',
20
+ title: 'Agent Example',
21
+ description: 'Launches a generic agent sub-workflow with weather and calculator tools.',
23
22
  })
24
23
  export class AgentExampleWorkflow extends BaseWorkflow {
25
- @InjectWorkflow() private agent: AgentWorkflow;
24
+ constructor(private readonly agentWorkflow: AgentWorkflow) {
25
+ super();
26
+ }
26
27
 
27
- @Initial({ to: 'running' })
28
- async start() {
29
- const result: QueueResult = await this.agent.run(
28
+ @Transition({ to: 'running' })
29
+ async start(state: Record<string, unknown>): Promise<Record<string, unknown>> {
30
+ const result: QueueResult = await this.agentWorkflow.run(
30
31
  {
31
32
  system: this.render(__dirname + '/templates/system.md'),
32
- tools: ['weatherLookup', 'calculator'],
33
+ tools: ['weather_lookup', 'calculator'],
33
34
  userMessage: "What's the weather in Tokyo? Also, what is 42 * 17?",
34
35
  },
35
- { alias: 'agent', callback: { transition: 'agentComplete' } },
36
+ { callback: { transition: 'agentComplete' } },
36
37
  );
37
38
 
38
- await this.repository.save(
39
+ await this.documentStore.save(
39
40
  LinkDocument,
40
41
  { label: 'Agent working...', workflowId: result.workflowId, embed: true, expanded: true },
41
42
  { id: `link_${result.workflowId}` },
42
43
  );
44
+ return state;
43
45
  }
44
46
 
45
- @Final({
47
+ @Transition({
46
48
  from: 'running',
49
+ to: 'end',
47
50
  wait: true,
48
51
  schema: AgentCallbackSchema,
49
52
  })
50
- async agentComplete(payload: AgentCallback) {
51
- await this.repository.save(
53
+ async agentComplete(state: Record<string, unknown>, payload: AgentCallback): Promise<unknown> {
54
+ await this.documentStore.save(
52
55
  LinkDocument,
53
56
  { label: 'Agent complete', status: 'success', workflowId: payload.workflowId },
54
57
  { id: `link_${payload.workflowId}` },
55
58
  );
56
59
 
57
- await this.repository.save(MessageDocument, {
60
+ await this.documentStore.save(MessageDocument, {
58
61
  role: 'assistant',
59
62
  content: payload.data.response,
60
63
  });
64
+ return {};
61
65
  }
62
66
  }
@@ -1,18 +1,23 @@
1
1
  import { z } from 'zod';
2
2
  import { BaseTool, Tool, ToolResult } from '@loopstack/common';
3
+ import type { LoopstackContext } from '@loopstack/common';
4
+
5
+ export type CalculatorResult = string;
3
6
 
4
7
  @Tool({
5
- uiConfig: {
6
- description: 'Perform a basic arithmetic calculation. Supports add, subtract, multiply, divide.',
7
- },
8
+ name: 'calculator',
9
+ description: 'Perform a basic arithmetic calculation. Supports add, subtract, multiply, divide.',
8
10
  schema: z.object({
9
11
  operation: z.enum(['add', 'subtract', 'multiply', 'divide']).describe('The arithmetic operation.'),
10
12
  a: z.number().describe('First operand.'),
11
13
  b: z.number().describe('Second operand.'),
12
14
  }),
13
15
  })
14
- export class CalculatorTool extends BaseTool {
15
- call(args: { operation: string; a: number; b: number }): Promise<ToolResult> {
16
+ export class CalculatorTool extends BaseTool<{ operation: string; a: number; b: number }, object, CalculatorResult> {
17
+ protected async handle(
18
+ args: { operation: string; a: number; b: number },
19
+ _ctx: LoopstackContext,
20
+ ): Promise<ToolResult<CalculatorResult>> {
16
21
  let result: number;
17
22
 
18
23
  switch (args.operation) {
@@ -27,16 +32,16 @@ export class CalculatorTool extends BaseTool {
27
32
  break;
28
33
  case 'divide':
29
34
  if (args.b === 0) {
30
- return Promise.resolve({ data: 'Error: Division by zero', error: 'Cannot divide by zero' });
35
+ return { data: 'Error: Division by zero', error: 'Cannot divide by zero' };
31
36
  }
32
37
  result = args.a / args.b;
33
38
  break;
34
39
  default:
35
- return Promise.resolve({ data: `Unknown operation: ${args.operation}`, error: 'Unsupported operation' });
40
+ return { data: `Unknown operation: ${args.operation}`, error: 'Unsupported operation' };
36
41
  }
37
42
 
38
- return Promise.resolve({
43
+ return {
39
44
  data: `${args.a} ${args.operation} ${args.b} = ${result}`,
40
- });
45
+ };
41
46
  }
42
47
  }
@@ -1,16 +1,18 @@
1
1
  import { z } from 'zod';
2
2
  import { BaseTool, Tool, ToolResult } from '@loopstack/common';
3
+ import type { LoopstackContext } from '@loopstack/common';
4
+
5
+ export type WeatherLookupResult = string;
3
6
 
4
7
  @Tool({
5
- uiConfig: {
6
- description: 'Look up the current weather for a given city. Returns a simulated forecast.',
7
- },
8
+ name: 'weather_lookup',
9
+ description: 'Look up the current weather for a given city. Returns a simulated forecast.',
8
10
  schema: z.object({
9
11
  city: z.string().describe('The city name to look up weather for.'),
10
12
  }),
11
13
  })
12
- export class WeatherLookupTool extends BaseTool {
13
- call(args: { city: string }): Promise<ToolResult> {
14
+ export class WeatherLookupTool extends BaseTool<{ city: string }, object, WeatherLookupResult> {
15
+ protected async handle(args: { city: string }, _ctx: LoopstackContext): Promise<ToolResult<WeatherLookupResult>> {
14
16
  // Simulated weather data for demonstration purposes
15
17
  const forecasts: Record<string, string> = {
16
18
  london: '14°C, cloudy with light rain',
@@ -1,2 +0,0 @@
1
- title: 'Agent Example'
2
- description: Launches a generic agent sub-workflow with weather and calculator tools.
@@ -1,2 +0,0 @@
1
- title: 'Agent Example'
2
- description: Launches a generic agent sub-workflow with weather and calculator tools.