@loopstack/agent-example-workflow 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-example.module.d.ts +3 -0
- package/dist/agent-example.module.d.ts.map +1 -0
- package/dist/agent-example.module.js +26 -0
- package/dist/agent-example.module.js.map +1 -0
- package/dist/agent-example.ui.yaml +2 -0
- package/dist/agent-example.workflow.d.ts +17 -0
- package/dist/agent-example.workflow.d.ts.map +1 -0
- package/dist/agent-example.workflow.js +67 -0
- package/dist/agent-example.workflow.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/calculator.tool.d.ts +9 -0
- package/dist/tools/calculator.tool.d.ts.map +1 -0
- package/dist/tools/calculator.tool.js +52 -0
- package/dist/tools/calculator.tool.js.map +1 -0
- package/dist/tools/index.d.ts +3 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +19 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/weather-lookup.tool.d.ts +7 -0
- package/dist/tools/weather-lookup.tool.d.ts.map +1 -0
- package/dist/tools/weather-lookup.tool.js +37 -0
- package/dist/tools/weather-lookup.tool.js.map +1 -0
- package/package.json +85 -0
- package/src/__tests__/agent-example.workflow.spec.ts +98 -0
- package/src/agent-example.module.ts +13 -0
- package/src/agent-example.ui.yaml +2 -0
- package/src/agent-example.workflow.ts +67 -0
- package/src/index.ts +3 -0
- package/src/tools/calculator.tool.ts +42 -0
- package/src/tools/index.ts +2 -0
- package/src/tools/weather-lookup.tool.ts +28 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-example.module.d.ts","sourceRoot":"","sources":["../src/agent-example.module.ts"],"names":[],"mappings":"AAOA,qBAKa,kBAAkB;CAAG"}
|
|
@@ -0,0 +1,26 @@
|
|
|
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.AgentExampleModule = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
const agent_1 = require("@loopstack/agent");
|
|
12
|
+
const core_1 = require("@loopstack/core");
|
|
13
|
+
const agent_example_workflow_1 = require("./agent-example.workflow");
|
|
14
|
+
const calculator_tool_1 = require("./tools/calculator.tool");
|
|
15
|
+
const weather_lookup_tool_1 = require("./tools/weather-lookup.tool");
|
|
16
|
+
let AgentExampleModule = class AgentExampleModule {
|
|
17
|
+
};
|
|
18
|
+
exports.AgentExampleModule = AgentExampleModule;
|
|
19
|
+
exports.AgentExampleModule = AgentExampleModule = __decorate([
|
|
20
|
+
(0, common_1.Module)({
|
|
21
|
+
imports: [core_1.LoopCoreModule, agent_1.AgentModule],
|
|
22
|
+
providers: [agent_example_workflow_1.AgentExampleWorkflow, calculator_tool_1.CalculatorTool, weather_lookup_tool_1.WeatherLookupTool],
|
|
23
|
+
exports: [agent_example_workflow_1.AgentExampleWorkflow, calculator_tool_1.CalculatorTool, weather_lookup_tool_1.WeatherLookupTool],
|
|
24
|
+
})
|
|
25
|
+
], AgentExampleModule);
|
|
26
|
+
//# sourceMappingURL=agent-example.module.js.map
|
|
@@ -0,0 +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,0CAAiD;AACjD,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,qBAAc,EAAE,mBAAW,CAAC;QACtC,SAAS,EAAE,CAAC,6CAAoB,EAAE,gCAAc,EAAE,uCAAiB,CAAC;QACpE,OAAO,EAAE,CAAC,6CAAoB,EAAE,gCAAc,EAAE,uCAAiB,CAAC;KACnE,CAAC;GACW,kBAAkB,CAAG"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { BaseWorkflow } from '@loopstack/common';
|
|
3
|
+
declare const AgentCallbackSchema: z.ZodObject<{
|
|
4
|
+
workflowId: z.ZodString;
|
|
5
|
+
status: z.ZodString;
|
|
6
|
+
data: z.ZodObject<{
|
|
7
|
+
response: z.ZodString;
|
|
8
|
+
}, z.core.$strip>;
|
|
9
|
+
}, z.core.$strip>;
|
|
10
|
+
type AgentCallback = z.infer<typeof AgentCallbackSchema>;
|
|
11
|
+
export declare class AgentExampleWorkflow extends BaseWorkflow {
|
|
12
|
+
private agent;
|
|
13
|
+
start(): Promise<void>;
|
|
14
|
+
agentComplete(payload: AgentCallback): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=agent-example.workflow.d.ts.map
|
|
@@ -0,0 +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;AAOzD,qBAGa,oBAAqB,SAAQ,YAAY;IAClC,OAAO,CAAC,KAAK,CAAgB;IAGzC,KAAK;IAsBL,aAAa,CAAC,OAAO,EAAE,aAAa;CAY3C"}
|
|
@@ -0,0 +1,67 @@
|
|
|
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.AgentExampleWorkflow = void 0;
|
|
13
|
+
const zod_1 = require("zod");
|
|
14
|
+
const agent_1 = require("@loopstack/agent");
|
|
15
|
+
const common_1 = require("@loopstack/common");
|
|
16
|
+
const AgentCallbackSchema = common_1.CallbackSchema.extend({
|
|
17
|
+
data: zod_1.z.object({ response: zod_1.z.string() }),
|
|
18
|
+
});
|
|
19
|
+
const SYSTEM_PROMPT = `You are a helpful assistant with access to a weather lookup tool and a calculator.
|
|
20
|
+
When the user asks about weather, use the weatherLookup tool.
|
|
21
|
+
When the user asks for calculations, use the calculator tool.
|
|
22
|
+
Provide a concise, helpful response summarizing the results.`;
|
|
23
|
+
let AgentExampleWorkflow = class AgentExampleWorkflow extends common_1.BaseWorkflow {
|
|
24
|
+
agent;
|
|
25
|
+
async start() {
|
|
26
|
+
const result = await this.agent.run({
|
|
27
|
+
system: SYSTEM_PROMPT,
|
|
28
|
+
tools: ['weatherLookup', 'calculator'],
|
|
29
|
+
userMessage: "What's the weather in Tokyo? Also, what is 42 * 17?",
|
|
30
|
+
}, { alias: 'agent', callback: { transition: 'agentComplete' } });
|
|
31
|
+
await this.repository.save(common_1.LinkDocument, { label: 'Agent working...', workflowId: result.workflowId, embed: true, expanded: true }, { id: `link_${result.workflowId}` });
|
|
32
|
+
}
|
|
33
|
+
async agentComplete(payload) {
|
|
34
|
+
await this.repository.save(common_1.LinkDocument, { label: 'Agent complete', status: 'success', workflowId: payload.workflowId }, { id: `link_${payload.workflowId}` });
|
|
35
|
+
await this.repository.save(common_1.MessageDocument, {
|
|
36
|
+
role: 'assistant',
|
|
37
|
+
content: payload.data.response,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
exports.AgentExampleWorkflow = AgentExampleWorkflow;
|
|
42
|
+
__decorate([
|
|
43
|
+
(0, common_1.InjectWorkflow)(),
|
|
44
|
+
__metadata("design:type", agent_1.AgentWorkflow)
|
|
45
|
+
], AgentExampleWorkflow.prototype, "agent", void 0);
|
|
46
|
+
__decorate([
|
|
47
|
+
(0, common_1.Initial)({ to: 'running' }),
|
|
48
|
+
__metadata("design:type", Function),
|
|
49
|
+
__metadata("design:paramtypes", []),
|
|
50
|
+
__metadata("design:returntype", Promise)
|
|
51
|
+
], AgentExampleWorkflow.prototype, "start", null);
|
|
52
|
+
__decorate([
|
|
53
|
+
(0, common_1.Final)({
|
|
54
|
+
from: 'running',
|
|
55
|
+
wait: true,
|
|
56
|
+
schema: AgentCallbackSchema,
|
|
57
|
+
}),
|
|
58
|
+
__metadata("design:type", Function),
|
|
59
|
+
__metadata("design:paramtypes", [Object]),
|
|
60
|
+
__metadata("design:returntype", Promise)
|
|
61
|
+
], AgentExampleWorkflow.prototype, "agentComplete", null);
|
|
62
|
+
exports.AgentExampleWorkflow = AgentExampleWorkflow = __decorate([
|
|
63
|
+
(0, common_1.Workflow)({
|
|
64
|
+
uiConfig: __dirname + '/agent-example.ui.yaml',
|
|
65
|
+
})
|
|
66
|
+
], AgentExampleWorkflow);
|
|
67
|
+
//# sourceMappingURL=agent-example.workflow.js.map
|
|
@@ -0,0 +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;AAIH,MAAM,aAAa,GAAG;;;6DAGuC,CAAC;AAKvD,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,aAAa;YACrB,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"}
|
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,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
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("./agent-example.module"), exports);
|
|
18
|
+
__exportStar(require("./agent-example.workflow"), exports);
|
|
19
|
+
__exportStar(require("./tools"), exports);
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAuC;AACvC,2DAAyC;AACzC,0CAAwB"}
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
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.CalculatorTool = void 0;
|
|
10
|
+
const zod_1 = require("zod");
|
|
11
|
+
const common_1 = require("@loopstack/common");
|
|
12
|
+
let CalculatorTool = class CalculatorTool extends common_1.BaseTool {
|
|
13
|
+
call(args) {
|
|
14
|
+
let result;
|
|
15
|
+
switch (args.operation) {
|
|
16
|
+
case 'add':
|
|
17
|
+
result = args.a + args.b;
|
|
18
|
+
break;
|
|
19
|
+
case 'subtract':
|
|
20
|
+
result = args.a - args.b;
|
|
21
|
+
break;
|
|
22
|
+
case 'multiply':
|
|
23
|
+
result = args.a * args.b;
|
|
24
|
+
break;
|
|
25
|
+
case 'divide':
|
|
26
|
+
if (args.b === 0) {
|
|
27
|
+
return Promise.resolve({ data: 'Error: Division by zero', error: 'Cannot divide by zero' });
|
|
28
|
+
}
|
|
29
|
+
result = args.a / args.b;
|
|
30
|
+
break;
|
|
31
|
+
default:
|
|
32
|
+
return Promise.resolve({ data: `Unknown operation: ${args.operation}`, error: 'Unsupported operation' });
|
|
33
|
+
}
|
|
34
|
+
return Promise.resolve({
|
|
35
|
+
data: `${args.a} ${args.operation} ${args.b} = ${result}`,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
exports.CalculatorTool = CalculatorTool;
|
|
40
|
+
exports.CalculatorTool = CalculatorTool = __decorate([
|
|
41
|
+
(0, common_1.Tool)({
|
|
42
|
+
uiConfig: {
|
|
43
|
+
description: 'Perform a basic arithmetic calculation. Supports add, subtract, multiply, divide.',
|
|
44
|
+
},
|
|
45
|
+
schema: zod_1.z.object({
|
|
46
|
+
operation: zod_1.z.enum(['add', 'subtract', 'multiply', 'divide']).describe('The arithmetic operation.'),
|
|
47
|
+
a: zod_1.z.number().describe('First operand.'),
|
|
48
|
+
b: zod_1.z.number().describe('Second operand.'),
|
|
49
|
+
}),
|
|
50
|
+
})
|
|
51
|
+
], CalculatorTool);
|
|
52
|
+
//# sourceMappingURL=calculator.tool.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC"}
|
|
@@ -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("./weather-lookup.tool"), exports);
|
|
18
|
+
__exportStar(require("./calculator.tool"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wDAAsC;AACtC,oDAAkC"}
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
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.WeatherLookupTool = void 0;
|
|
10
|
+
const zod_1 = require("zod");
|
|
11
|
+
const common_1 = require("@loopstack/common");
|
|
12
|
+
let WeatherLookupTool = class WeatherLookupTool extends common_1.BaseTool {
|
|
13
|
+
call(args) {
|
|
14
|
+
const forecasts = {
|
|
15
|
+
london: '14°C, cloudy with light rain',
|
|
16
|
+
tokyo: '22°C, sunny with clear skies',
|
|
17
|
+
'new york': '18°C, partly cloudy',
|
|
18
|
+
};
|
|
19
|
+
const key = args.city.toLowerCase();
|
|
20
|
+
const weather = forecasts[key] ?? `21°C, pleasant conditions`;
|
|
21
|
+
return Promise.resolve({
|
|
22
|
+
data: `Weather in ${args.city}: ${weather}`,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
exports.WeatherLookupTool = WeatherLookupTool;
|
|
27
|
+
exports.WeatherLookupTool = WeatherLookupTool = __decorate([
|
|
28
|
+
(0, common_1.Tool)({
|
|
29
|
+
uiConfig: {
|
|
30
|
+
description: 'Look up the current weather for a given city. Returns a simulated forecast.',
|
|
31
|
+
},
|
|
32
|
+
schema: zod_1.z.object({
|
|
33
|
+
city: zod_1.z.string().describe('The city name to look up weather for.'),
|
|
34
|
+
}),
|
|
35
|
+
})
|
|
36
|
+
], WeatherLookupTool);
|
|
37
|
+
//# sourceMappingURL=weather-lookup.tool.js.map
|
|
@@ -0,0 +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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@loopstack/agent-example-workflow",
|
|
3
|
+
"displayName": "Agent Example",
|
|
4
|
+
"description": "Example workflow that launches @loopstack/agent's AgentWorkflow as a sub-workflow with custom tools",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"example",
|
|
7
|
+
"agent",
|
|
8
|
+
"workflow",
|
|
9
|
+
"claude",
|
|
10
|
+
"sub-workflow"
|
|
11
|
+
],
|
|
12
|
+
"version": "0.1.1",
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"author": {
|
|
15
|
+
"name": "Jakob Klippel",
|
|
16
|
+
"url": "https://github.com/loopstack-ai"
|
|
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/agent": "^0.2.0",
|
|
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/agent-example.module.ts",
|
|
58
|
+
"className": "AgentExampleModule"
|
|
59
|
+
}
|
|
60
|
+
],
|
|
61
|
+
"workflows": [
|
|
62
|
+
{
|
|
63
|
+
"path": "src/agent-example.workflow.ts",
|
|
64
|
+
"className": "AgentExampleWorkflow",
|
|
65
|
+
"propertyName": "agentExample"
|
|
66
|
+
}
|
|
67
|
+
],
|
|
68
|
+
"tools": [
|
|
69
|
+
{
|
|
70
|
+
"path": "src/tools/calculator.tool.ts",
|
|
71
|
+
"className": "CalculatorTool",
|
|
72
|
+
"propertyName": "calculator"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"path": "src/tools/weather-lookup.tool.ts",
|
|
76
|
+
"className": "WeatherLookupTool",
|
|
77
|
+
"propertyName": "weatherLookup"
|
|
78
|
+
}
|
|
79
|
+
],
|
|
80
|
+
"installModes": [
|
|
81
|
+
"add",
|
|
82
|
+
"install"
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { TestingModule } from '@nestjs/testing';
|
|
2
|
+
import { AgentWorkflow } from '@loopstack/agent';
|
|
3
|
+
import { RunContext, WorkflowEntity } from '@loopstack/common';
|
|
4
|
+
import { LoopCoreModule, WorkflowProcessorService } from '@loopstack/core';
|
|
5
|
+
import { createStatelessContext, createWorkflowTest } from '@loopstack/testing';
|
|
6
|
+
import { AgentExampleWorkflow } from '../agent-example.workflow';
|
|
7
|
+
import { CalculatorTool } from '../tools/calculator.tool';
|
|
8
|
+
import { WeatherLookupTool } from '../tools/weather-lookup.tool';
|
|
9
|
+
|
|
10
|
+
describe('AgentExampleWorkflow', () => {
|
|
11
|
+
let module: TestingModule;
|
|
12
|
+
let workflow: AgentExampleWorkflow;
|
|
13
|
+
let processor: WorkflowProcessorService;
|
|
14
|
+
|
|
15
|
+
const mockAgent = {
|
|
16
|
+
run: jest.fn(),
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
beforeEach(async () => {
|
|
20
|
+
jest.clearAllMocks();
|
|
21
|
+
|
|
22
|
+
module = await createWorkflowTest()
|
|
23
|
+
.forWorkflow(AgentExampleWorkflow)
|
|
24
|
+
.withImports(LoopCoreModule)
|
|
25
|
+
.withProviders(CalculatorTool, WeatherLookupTool)
|
|
26
|
+
.withMock(AgentWorkflow, mockAgent)
|
|
27
|
+
.compile();
|
|
28
|
+
|
|
29
|
+
workflow = module.get(AgentExampleWorkflow);
|
|
30
|
+
processor = module.get(WorkflowProcessorService);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
afterEach(async () => {
|
|
34
|
+
await module.close();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('launches AgentWorkflow and stops at running', async () => {
|
|
38
|
+
mockAgent.run.mockResolvedValue({ workflowId: 'agent-sub-id' });
|
|
39
|
+
|
|
40
|
+
const result = await processor.process(workflow, {}, createStatelessContext());
|
|
41
|
+
|
|
42
|
+
expect(result.hasError).toBe(false);
|
|
43
|
+
expect(result.stop).toBe(true);
|
|
44
|
+
expect(result.place).toBe('running');
|
|
45
|
+
|
|
46
|
+
expect(mockAgent.run).toHaveBeenCalledWith(
|
|
47
|
+
expect.objectContaining({
|
|
48
|
+
system: expect.any(String),
|
|
49
|
+
tools: ['weatherLookup', 'calculator'],
|
|
50
|
+
userMessage: expect.any(String),
|
|
51
|
+
}),
|
|
52
|
+
expect.objectContaining({ alias: 'agent', callback: { transition: 'agentComplete' } }),
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
expect(result.documents).toEqual(
|
|
56
|
+
expect.arrayContaining([
|
|
57
|
+
expect.objectContaining({
|
|
58
|
+
className: 'LinkDocument',
|
|
59
|
+
content: expect.objectContaining({ workflowId: 'agent-sub-id' }),
|
|
60
|
+
}),
|
|
61
|
+
]),
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('saves the agent response as a MessageDocument when resumed', async () => {
|
|
66
|
+
const workflowId = '00000000-0000-0000-0000-000000000001';
|
|
67
|
+
const context = {
|
|
68
|
+
workflowEntity: {
|
|
69
|
+
id: workflowId,
|
|
70
|
+
place: 'running',
|
|
71
|
+
documents: [],
|
|
72
|
+
} as Partial<WorkflowEntity>,
|
|
73
|
+
payload: {
|
|
74
|
+
transition: {
|
|
75
|
+
id: 'agentComplete',
|
|
76
|
+
workflowId,
|
|
77
|
+
payload: {
|
|
78
|
+
workflowId,
|
|
79
|
+
status: 'completed',
|
|
80
|
+
data: { response: 'Tokyo is 22°C and sunny. 42 * 17 = 714.' },
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
} as unknown as RunContext;
|
|
85
|
+
|
|
86
|
+
const result = await processor.process(workflow, {}, context);
|
|
87
|
+
|
|
88
|
+
expect(result.hasError).toBe(false);
|
|
89
|
+
expect(result.documents).toEqual(
|
|
90
|
+
expect.arrayContaining([
|
|
91
|
+
expect.objectContaining({
|
|
92
|
+
className: 'MessageDocument',
|
|
93
|
+
content: expect.objectContaining({ content: expect.stringContaining('714') }),
|
|
94
|
+
}),
|
|
95
|
+
]),
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Module } from '@nestjs/common';
|
|
2
|
+
import { AgentModule } from '@loopstack/agent';
|
|
3
|
+
import { LoopCoreModule } from '@loopstack/core';
|
|
4
|
+
import { AgentExampleWorkflow } from './agent-example.workflow';
|
|
5
|
+
import { CalculatorTool } from './tools/calculator.tool';
|
|
6
|
+
import { WeatherLookupTool } from './tools/weather-lookup.tool';
|
|
7
|
+
|
|
8
|
+
@Module({
|
|
9
|
+
imports: [LoopCoreModule, AgentModule],
|
|
10
|
+
providers: [AgentExampleWorkflow, CalculatorTool, WeatherLookupTool],
|
|
11
|
+
exports: [AgentExampleWorkflow, CalculatorTool, WeatherLookupTool],
|
|
12
|
+
})
|
|
13
|
+
export class AgentExampleModule {}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { AgentWorkflow } from '@loopstack/agent';
|
|
3
|
+
import {
|
|
4
|
+
BaseWorkflow,
|
|
5
|
+
CallbackSchema,
|
|
6
|
+
Final,
|
|
7
|
+
Initial,
|
|
8
|
+
InjectWorkflow,
|
|
9
|
+
LinkDocument,
|
|
10
|
+
MessageDocument,
|
|
11
|
+
QueueResult,
|
|
12
|
+
Workflow,
|
|
13
|
+
} from '@loopstack/common';
|
|
14
|
+
|
|
15
|
+
const AgentCallbackSchema = CallbackSchema.extend({
|
|
16
|
+
data: z.object({ response: z.string() }),
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
type AgentCallback = z.infer<typeof AgentCallbackSchema>;
|
|
20
|
+
|
|
21
|
+
const SYSTEM_PROMPT = `You are a helpful assistant with access to a weather lookup tool and a calculator.
|
|
22
|
+
When the user asks about weather, use the weatherLookup tool.
|
|
23
|
+
When the user asks for calculations, use the calculator tool.
|
|
24
|
+
Provide a concise, helpful response summarizing the results.`;
|
|
25
|
+
|
|
26
|
+
@Workflow({
|
|
27
|
+
uiConfig: __dirname + '/agent-example.ui.yaml',
|
|
28
|
+
})
|
|
29
|
+
export class AgentExampleWorkflow extends BaseWorkflow {
|
|
30
|
+
@InjectWorkflow() private agent: AgentWorkflow;
|
|
31
|
+
|
|
32
|
+
@Initial({ to: 'running' })
|
|
33
|
+
async start() {
|
|
34
|
+
const result: QueueResult = await this.agent.run(
|
|
35
|
+
{
|
|
36
|
+
system: SYSTEM_PROMPT,
|
|
37
|
+
tools: ['weatherLookup', 'calculator'],
|
|
38
|
+
userMessage: "What's the weather in Tokyo? Also, what is 42 * 17?",
|
|
39
|
+
},
|
|
40
|
+
{ alias: 'agent', callback: { transition: 'agentComplete' } },
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
await this.repository.save(
|
|
44
|
+
LinkDocument,
|
|
45
|
+
{ label: 'Agent working...', workflowId: result.workflowId, embed: true, expanded: true },
|
|
46
|
+
{ id: `link_${result.workflowId}` },
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@Final({
|
|
51
|
+
from: 'running',
|
|
52
|
+
wait: true,
|
|
53
|
+
schema: AgentCallbackSchema,
|
|
54
|
+
})
|
|
55
|
+
async agentComplete(payload: AgentCallback) {
|
|
56
|
+
await this.repository.save(
|
|
57
|
+
LinkDocument,
|
|
58
|
+
{ label: 'Agent complete', status: 'success', workflowId: payload.workflowId },
|
|
59
|
+
{ id: `link_${payload.workflowId}` },
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
await this.repository.save(MessageDocument, {
|
|
63
|
+
role: 'assistant',
|
|
64
|
+
content: payload.data.response,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { BaseTool, Tool, ToolResult } from '@loopstack/common';
|
|
3
|
+
|
|
4
|
+
@Tool({
|
|
5
|
+
uiConfig: {
|
|
6
|
+
description: 'Perform a basic arithmetic calculation. Supports add, subtract, multiply, divide.',
|
|
7
|
+
},
|
|
8
|
+
schema: z.object({
|
|
9
|
+
operation: z.enum(['add', 'subtract', 'multiply', 'divide']).describe('The arithmetic operation.'),
|
|
10
|
+
a: z.number().describe('First operand.'),
|
|
11
|
+
b: z.number().describe('Second operand.'),
|
|
12
|
+
}),
|
|
13
|
+
})
|
|
14
|
+
export class CalculatorTool extends BaseTool {
|
|
15
|
+
call(args: { operation: string; a: number; b: number }): Promise<ToolResult> {
|
|
16
|
+
let result: number;
|
|
17
|
+
|
|
18
|
+
switch (args.operation) {
|
|
19
|
+
case 'add':
|
|
20
|
+
result = args.a + args.b;
|
|
21
|
+
break;
|
|
22
|
+
case 'subtract':
|
|
23
|
+
result = args.a - args.b;
|
|
24
|
+
break;
|
|
25
|
+
case 'multiply':
|
|
26
|
+
result = args.a * args.b;
|
|
27
|
+
break;
|
|
28
|
+
case 'divide':
|
|
29
|
+
if (args.b === 0) {
|
|
30
|
+
return Promise.resolve({ data: 'Error: Division by zero', error: 'Cannot divide by zero' });
|
|
31
|
+
}
|
|
32
|
+
result = args.a / args.b;
|
|
33
|
+
break;
|
|
34
|
+
default:
|
|
35
|
+
return Promise.resolve({ data: `Unknown operation: ${args.operation}`, error: 'Unsupported operation' });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return Promise.resolve({
|
|
39
|
+
data: `${args.a} ${args.operation} ${args.b} = ${result}`,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { BaseTool, Tool, ToolResult } from '@loopstack/common';
|
|
3
|
+
|
|
4
|
+
@Tool({
|
|
5
|
+
uiConfig: {
|
|
6
|
+
description: 'Look up the current weather for a given city. Returns a simulated forecast.',
|
|
7
|
+
},
|
|
8
|
+
schema: z.object({
|
|
9
|
+
city: z.string().describe('The city name to look up weather for.'),
|
|
10
|
+
}),
|
|
11
|
+
})
|
|
12
|
+
export class WeatherLookupTool extends BaseTool {
|
|
13
|
+
call(args: { city: string }): Promise<ToolResult> {
|
|
14
|
+
// Simulated weather data for demonstration purposes
|
|
15
|
+
const forecasts: Record<string, string> = {
|
|
16
|
+
london: '14°C, cloudy with light rain',
|
|
17
|
+
tokyo: '22°C, sunny with clear skies',
|
|
18
|
+
'new york': '18°C, partly cloudy',
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const key = args.city.toLowerCase();
|
|
22
|
+
const weather = forecasts[key] ?? `21°C, pleasant conditions`;
|
|
23
|
+
|
|
24
|
+
return Promise.resolve({
|
|
25
|
+
data: `Weather in ${args.city}: ${weather}`,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|