@loopstack/meeting-notes-example-workflow 0.21.6 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"meeting-notes-example.module.d.ts","sourceRoot":"","sources":["../src/meeting-notes-example.module.ts"],"names":[],"mappings":"AAOA,qBAKa,yBAAyB;CAAG"}
1
+ {"version":3,"file":"meeting-notes-example.module.d.ts","sourceRoot":"","sources":["../src/meeting-notes-example.module.ts"],"names":[],"mappings":"AAMA,qBAKa,yBAAyB;CAAG"}
@@ -9,7 +9,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.MeetingNotesExampleModule = void 0;
10
10
  const common_1 = require("@nestjs/common");
11
11
  const claude_module_1 = require("@loopstack/claude-module");
12
- const core_1 = require("@loopstack/core");
13
12
  const meeting_notes_document_1 = require("./documents/meeting-notes-document");
14
13
  const optimized_notes_document_1 = require("./documents/optimized-notes-document");
15
14
  const meeting_notes_workflow_1 = require("./meeting-notes.workflow");
@@ -18,7 +17,7 @@ let MeetingNotesExampleModule = class MeetingNotesExampleModule {
18
17
  exports.MeetingNotesExampleModule = MeetingNotesExampleModule;
19
18
  exports.MeetingNotesExampleModule = MeetingNotesExampleModule = __decorate([
20
19
  (0, common_1.Module)({
21
- imports: [core_1.LoopCoreModule, claude_module_1.ClaudeModule],
20
+ imports: [claude_module_1.ClaudeModule],
22
21
  providers: [meeting_notes_workflow_1.MeetingNotesWorkflow, meeting_notes_document_1.MeetingNotesDocument, optimized_notes_document_1.OptimizedNotesDocument],
23
22
  exports: [meeting_notes_workflow_1.MeetingNotesWorkflow],
24
23
  })
@@ -1 +1 @@
1
- {"version":3,"file":"meeting-notes-example.module.js","sourceRoot":"","sources":["../src/meeting-notes-example.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,4DAAwD;AACxD,0CAAiD;AACjD,+EAA0E;AAC1E,mFAA8E;AAC9E,qEAAgE;AAOzD,IAAM,yBAAyB,GAA/B,MAAM,yBAAyB;CAAG,CAAA;AAA5B,8DAAyB;oCAAzB,yBAAyB;IALrC,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,qBAAc,EAAE,4BAAY,CAAC;QACvC,SAAS,EAAE,CAAC,6CAAoB,EAAE,6CAAoB,EAAE,iDAAsB,CAAC;QAC/E,OAAO,EAAE,CAAC,6CAAoB,CAAC;KAChC,CAAC;GACW,yBAAyB,CAAG"}
1
+ {"version":3,"file":"meeting-notes-example.module.js","sourceRoot":"","sources":["../src/meeting-notes-example.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,4DAAwD;AACxD,+EAA0E;AAC1E,mFAA8E;AAC9E,qEAAgE;AAOzD,IAAM,yBAAyB,GAA/B,MAAM,yBAAyB;CAAG,CAAA;AAA5B,8DAAyB;oCAAzB,yBAAyB;IALrC,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,4BAAY,CAAC;QACvB,SAAS,EAAE,CAAC,6CAAoB,EAAE,6CAAoB,EAAE,iDAAsB,CAAC;QAC/E,OAAO,EAAE,CAAC,6CAAoB,CAAC;KAChC,CAAC;GACW,yBAAyB,CAAG"}
@@ -1,12 +1,12 @@
1
1
  import { z } from 'zod';
2
- import { ClaudeGenerateDocument } from '@loopstack/claude-module';
3
2
  import { BaseWorkflow } from '@loopstack/common';
3
+ import { LlmGenerateObjectTool } from '@loopstack/llm-provider-module';
4
4
  import { MeetingNotesDocumentSchema } from './documents/meeting-notes-document';
5
5
  import { OptimizedMeetingNotesDocumentSchema } from './documents/optimized-notes-document';
6
6
  export declare class MeetingNotesWorkflow extends BaseWorkflow<{
7
7
  inputText: string;
8
8
  }> {
9
- claudeGenerateDocument: ClaudeGenerateDocument;
9
+ llmGenerateObject: LlmGenerateObjectTool;
10
10
  meetingNotes?: z.infer<typeof MeetingNotesDocumentSchema>;
11
11
  optimizedNotes?: z.infer<typeof OptimizedMeetingNotesDocumentSchema>;
12
12
  createForm(args: {
@@ -1 +1 @@
1
- {"version":3,"file":"meeting-notes.workflow.d.ts","sourceRoot":"","sources":["../src/meeting-notes.workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAoD,MAAM,mBAAmB,CAAC;AACnG,OAAO,EAAwB,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AACtG,OAAO,EAAE,mCAAmC,EAA0B,MAAM,sCAAsC,CAAC;AAEnH,qBAUa,oBAAqB,SAAQ,YAAY,CAAC;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;IAC7D,sBAAsB,EAAE,sBAAsB,CAAC;IAE7D,YAAY,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;IAC1D,cAAc,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,mCAAmC,CAAC,CAAC;IAG/D,UAAU,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE;IAWtC,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC;IAMhE,aAAa;IAgBb,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,mCAAmC,CAAC;CAI3E"}
1
+ {"version":3,"file":"meeting-notes.workflow.d.ts","sourceRoot":"","sources":["../src/meeting-notes.workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,YAAY,EAAoD,MAAM,mBAAmB,CAAC;AAEnG,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAwB,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AACtG,OAAO,EAAE,mCAAmC,EAA0B,MAAM,sCAAsC,CAAC;AAEnH,qBAUa,oBAAqB,SAAQ,YAAY,CAAC;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;IAE3E,iBAAiB,EAAE,qBAAqB,CAAC;IAEzC,YAAY,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;IAC1D,cAAc,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,mCAAmC,CAAC,CAAC;IAG/D,UAAU,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE;IAStC,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC;IAMhE,aAAa;IAkBb,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,mCAAmC,CAAC;CAI3E"}
@@ -11,35 +11,31 @@ var __metadata = (this && this.__metadata) || function (k, v) {
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.MeetingNotesWorkflow = void 0;
13
13
  const zod_1 = require("zod");
14
- const claude_module_1 = require("@loopstack/claude-module");
14
+ const zod_2 = require("zod");
15
15
  const common_1 = require("@loopstack/common");
16
+ const llm_provider_module_1 = require("@loopstack/llm-provider-module");
16
17
  const meeting_notes_document_1 = require("./documents/meeting-notes-document");
17
18
  const optimized_notes_document_1 = require("./documents/optimized-notes-document");
18
19
  let MeetingNotesWorkflow = class MeetingNotesWorkflow extends common_1.BaseWorkflow {
19
- claudeGenerateDocument;
20
+ llmGenerateObject;
20
21
  meetingNotes;
21
22
  optimizedNotes;
22
23
  async createForm(args) {
23
- await this.repository.save(meeting_notes_document_1.MeetingNotesDocument, {
24
- text: `Unstructured Notes:\n\n${args.inputText}`,
25
- }, { id: 'input' });
24
+ await this.repository.save(meeting_notes_document_1.MeetingNotesDocument, { text: `Unstructured Notes:\n\n${args.inputText}` }, { id: 'input' });
26
25
  }
27
26
  async userResponse(payload) {
28
27
  const result = await this.repository.save(meeting_notes_document_1.MeetingNotesDocument, payload, { id: 'input' });
29
28
  this.meetingNotes = result.content;
30
29
  }
31
30
  async optimizeNotes() {
32
- await this.claudeGenerateDocument.call({
33
- claude: { model: 'claude-sonnet-4-6' },
34
- response: {
35
- id: 'final',
36
- document: optimized_notes_document_1.OptimizedNotesDocument,
37
- },
38
- prompt: `Extract all information from the provided meeting notes into the structured document.
39
-
40
- <Meeting Notes>
41
- ${this.meetingNotes?.text}
42
- </Meeting Notes>`,
31
+ const result = await this.llmGenerateObject.call({
32
+ outputSchema: (0, zod_2.toJSONSchema)(optimized_notes_document_1.OptimizedMeetingNotesDocumentSchema),
33
+ prompt: this.render(__dirname + '/templates/extract-notes.md', { text: this.meetingNotes?.text }),
34
+ });
35
+ const objectResult = result.data;
36
+ await this.repository.save(optimized_notes_document_1.OptimizedNotesDocument, objectResult.data, {
37
+ id: 'final',
38
+ validate: 'skip',
43
39
  });
44
40
  }
45
41
  async confirm(payload) {
@@ -49,9 +45,9 @@ ${this.meetingNotes?.text}
49
45
  };
50
46
  exports.MeetingNotesWorkflow = MeetingNotesWorkflow;
51
47
  __decorate([
52
- (0, common_1.InjectTool)(),
53
- __metadata("design:type", claude_module_1.ClaudeGenerateDocument)
54
- ], MeetingNotesWorkflow.prototype, "claudeGenerateDocument", void 0);
48
+ (0, common_1.InjectTool)({ provider: 'claude', model: 'claude-sonnet-4-6' }),
49
+ __metadata("design:type", llm_provider_module_1.LlmGenerateObjectTool)
50
+ ], MeetingNotesWorkflow.prototype, "llmGenerateObject", void 0);
55
51
  __decorate([
56
52
  (0, common_1.Initial)({ to: 'waiting_for_response' }),
57
53
  __metadata("design:type", Function),
@@ -1 +1 @@
1
- {"version":3,"file":"meeting-notes.workflow.js","sourceRoot":"","sources":["../src/meeting-notes.workflow.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6BAAwB;AACxB,4DAAkE;AAClE,8CAAmG;AACnG,+EAAsG;AACtG,mFAAmH;AAY5G,IAAM,oBAAoB,GAA1B,MAAM,oBAAqB,SAAQ,qBAAmC;IAC7D,sBAAsB,CAAyB;IAE7D,YAAY,CAA8C;IAC1D,cAAc,CAAuD;IAG/D,AAAN,KAAK,CAAC,UAAU,CAAC,IAA2B;QAC1C,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CACxB,6CAAoB,EACpB;YACE,IAAI,EAAE,0BAA0B,IAAI,CAAC,SAAS,EAAE;SACjD,EACD,EAAE,EAAE,EAAE,OAAO,EAAE,CAChB,CAAC;IACJ,CAAC;IAGK,AAAN,KAAK,CAAC,YAAY,CAAC,OAAmD;QACpE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,6CAAoB,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1F,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,OAAqD,CAAC;IACnF,CAAC;IAGK,AAAN,KAAK,CAAC,aAAa;QACjB,MAAM,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC;YACrC,MAAM,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE;YACtC,QAAQ,EAAE;gBACR,EAAE,EAAE,OAAO;gBACX,QAAQ,EAAE,iDAAsB;aACjC;YACD,MAAM,EAAE;;;EAGZ,IAAI,CAAC,YAAY,EAAE,IAAI;iBACR;SACZ,CAAC,CAAC;IACL,CAAC;IAGK,AAAN,KAAK,CAAC,OAAO,CAAC,OAA4D;QACxE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,iDAAsB,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAC5F,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,OAA8D,CAAC;IAC9F,CAAC;CACF,CAAA;AA5CY,oDAAoB;AACjB;IAAb,IAAA,mBAAU,GAAE;8BAAyB,sCAAsB;oEAAC;AAMvD;IADL,IAAA,gBAAO,EAAC,EAAE,EAAE,EAAE,sBAAsB,EAAE,CAAC;;;;sDASvC;AAGK;IADL,IAAA,mBAAU,EAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,EAAE,EAAE,mBAAmB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,mDAA0B,EAAE,CAAC;;;;wDAIrH;AAGK;IADL,IAAA,mBAAU,EAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,EAAE,EAAE,iBAAiB,EAAE,CAAC;;;;yDAchE;AAGK;IADL,IAAA,cAAK,EAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,8DAAmC,EAAE,CAAC;;;;mDAI3F;+BA3CU,oBAAoB;IAVhC,IAAA,iBAAQ,EAAC;QACR,QAAQ,EAAE,SAAS,GAAG,wBAAwB;QAC9C,MAAM,EAAE,OAAC,CAAC,MAAM,CAAC;YACf,SAAS,EAAE,OAAC;iBACT,MAAM,EAAE;iBACR,OAAO,CACN,2IAA2I,CAC5I;SACJ,CAAC;KACH,CAAC;GACW,oBAAoB,CA4ChC"}
1
+ {"version":3,"file":"meeting-notes.workflow.js","sourceRoot":"","sources":["../src/meeting-notes.workflow.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6BAAwB;AACxB,6BAAmC;AACnC,8CAAmG;AAEnG,wEAAuE;AACvE,+EAAsG;AACtG,mFAAmH;AAY5G,IAAM,oBAAoB,GAA1B,MAAM,oBAAqB,SAAQ,qBAAmC;IAE3E,iBAAiB,CAAwB;IAEzC,YAAY,CAA8C;IAC1D,cAAc,CAAuD;IAG/D,AAAN,KAAK,CAAC,UAAU,CAAC,IAA2B;QAC1C,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CACxB,6CAAoB,EACpB,EAAE,IAAI,EAAE,0BAA0B,IAAI,CAAC,SAAS,EAAE,EAAE,EACpD,EAAE,EAAE,EAAE,OAAO,EAAE,CAChB,CAAC;IACJ,CAAC;IAGK,AAAN,KAAK,CAAC,YAAY,CAAC,OAAmD;QACpE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,6CAAoB,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1F,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,OAAqD,CAAC;IACnF,CAAC;IAGK,AAAN,KAAK,CAAC,aAAa;QACjB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC;YAC/C,YAAY,EAAE,IAAA,kBAAY,EAAC,8DAAmC,CAA4B;YAC1F,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,GAAG,6BAA6B,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC;SAClG,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,MAAM,CAAC,IAA+B,CAAC;QAC5D,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CACxB,iDAAsB,EACtB,YAAY,CAAC,IAA2D,EACxE;YACE,EAAE,EAAE,OAAO;YACX,QAAQ,EAAE,MAAM;SACjB,CACF,CAAC;IACJ,CAAC;IAGK,AAAN,KAAK,CAAC,OAAO,CAAC,OAA4D;QACxE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,iDAAsB,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAC5F,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,OAA8D,CAAC;IAC9F,CAAC;CACF,CAAA;AA7CY,oDAAoB;AAE/B;IADC,IAAA,mBAAU,EAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC;8BAC5C,2CAAqB;+DAAC;AAMnC;IADL,IAAA,gBAAO,EAAC,EAAE,EAAE,EAAE,sBAAsB,EAAE,CAAC;;;;sDAOvC;AAGK;IADL,IAAA,mBAAU,EAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,EAAE,EAAE,mBAAmB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,mDAA0B,EAAE,CAAC;;;;wDAIrH;AAGK;IADL,IAAA,mBAAU,EAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,EAAE,EAAE,iBAAiB,EAAE,CAAC;;;;yDAgBhE;AAGK;IADL,IAAA,cAAK,EAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,8DAAmC,EAAE,CAAC;;;;mDAI3F;+BA5CU,oBAAoB;IAVhC,IAAA,iBAAQ,EAAC;QACR,QAAQ,EAAE,SAAS,GAAG,wBAAwB;QAC9C,MAAM,EAAE,OAAC,CAAC,MAAM,CAAC;YACf,SAAS,EAAE,OAAC;iBACT,MAAM,EAAE;iBACR,OAAO,CACN,2IAA2I,CAC5I;SACJ,CAAC;KACH,CAAC;GACW,oBAAoB,CA6ChC"}
@@ -0,0 +1,5 @@
1
+ Extract all information from the provided meeting notes into the structured document.
2
+
3
+ <Meeting Notes>
4
+ {{text}}
5
+ </Meeting Notes>
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "summary",
10
10
  "workflow"
11
11
  ],
12
- "version": "0.21.6",
12
+ "version": "0.22.0",
13
13
  "license": "MIT",
14
14
  "author": {
15
15
  "name": "Jakob Klippel",
@@ -26,13 +26,14 @@
26
26
  "compile": "tsc --noEmit",
27
27
  "format": "prettier --write .",
28
28
  "lint": "eslint .",
29
- "test": "jest --passWithNoTests",
29
+ "test": "vitest run",
30
30
  "watch": "nest build --watch"
31
31
  },
32
32
  "dependencies": {
33
- "@loopstack/claude-module": "^0.22.5",
34
- "@loopstack/common": "^0.28.0",
35
- "@loopstack/core": "^0.28.0",
33
+ "@loopstack/claude-module": "^0.24.0",
34
+ "@loopstack/llm-provider-module": "^0.3.0",
35
+ "@loopstack/common": "^0.30.0",
36
+ "@loopstack/core": "^0.30.0",
36
37
  "@nestjs/common": "^11.1.19",
37
38
  "zod": "^4.3.6"
38
39
  },
@@ -40,34 +41,9 @@
40
41
  "dist",
41
42
  "src"
42
43
  ],
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/meeting-notes-example.module.ts",
58
- "className": "MeetingNotesExampleModule"
59
- }
60
- ],
61
- "workflows": [
62
- {
63
- "path": "src/meeting-notes.workflow.ts",
64
- "className": "MeetingNotesWorkflow",
65
- "propertyName": "meetingNotes"
66
- }
67
- ],
68
- "installModes": [
69
- "add",
70
- "install"
71
- ]
44
+ "devDependencies": {
45
+ "vitest": "^4.1.6",
46
+ "@swc/core": "^1.15.33",
47
+ "unplugin-swc": "^1.5.9"
72
48
  }
73
49
  }
@@ -1,7 +1,9 @@
1
1
  import { TestingModule } from '@nestjs/testing';
2
- import { ClaudeGenerateDocument, ClaudeModule } from '@loopstack/claude-module';
2
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
3
+ import { ClaudeModule } from '@loopstack/claude-module';
3
4
  import { RunContext, WorkflowEntity, getBlockTools } from '@loopstack/common';
4
- import { LoopCoreModule, WorkflowProcessorService } from '@loopstack/core';
5
+ import { WorkflowProcessorService } from '@loopstack/core';
6
+ import { LlmGenerateObjectTool } from '@loopstack/llm-provider-module';
5
7
  import { ToolMock, createStatelessContext, createWorkflowTest } from '@loopstack/testing';
6
8
  import { MeetingNotesDocument } from '../documents/meeting-notes-document';
7
9
  import { OptimizedNotesDocument } from '../documents/optimized-notes-document';
@@ -11,22 +13,20 @@ describe('MeetingNotesWorkflow', () => {
11
13
  let module: TestingModule;
12
14
  let workflow: MeetingNotesWorkflow;
13
15
  let processor: WorkflowProcessorService;
14
-
15
- let mockClaudeGenerateDocument: ToolMock;
16
+ let mockLlmGenerateObject: ToolMock;
16
17
 
17
18
  beforeEach(async () => {
18
19
  module = await createWorkflowTest()
19
20
  .forWorkflow(MeetingNotesWorkflow)
20
- .withImports(LoopCoreModule, ClaudeModule)
21
+ .withImports(ClaudeModule)
21
22
  .withProvider(MeetingNotesDocument)
22
23
  .withProvider(OptimizedNotesDocument)
23
- .withToolOverride(ClaudeGenerateDocument)
24
+ .withToolOverride(LlmGenerateObjectTool)
24
25
  .compile();
25
26
 
26
27
  workflow = module.get(MeetingNotesWorkflow);
27
28
  processor = module.get(WorkflowProcessorService);
28
-
29
- mockClaudeGenerateDocument = module.get(ClaudeGenerateDocument);
29
+ mockLlmGenerateObject = module.get(LlmGenerateObjectTool);
30
30
  });
31
31
 
32
32
  afterEach(async () => {
@@ -36,14 +36,13 @@ describe('MeetingNotesWorkflow', () => {
36
36
  describe('initialization', () => {
37
37
  it('should be defined with correct tools', () => {
38
38
  expect(workflow).toBeDefined();
39
- expect(getBlockTools(workflow)).toContain('claudeGenerateDocument');
39
+ expect(getBlockTools(workflow)).toContain('llmGenerateObject');
40
40
  });
41
41
  });
42
42
 
43
43
  describe('initial step', () => {
44
44
  it('should execute initial step and stop at waiting_for_response', async () => {
45
45
  const context = createStatelessContext();
46
-
47
46
  const result = await processor.process(workflow, {}, context);
48
47
 
49
48
  expect(result.hasError).toBe(false);
@@ -63,12 +62,10 @@ describe('MeetingNotesWorkflow', () => {
63
62
 
64
63
  it('should use custom input text when provided', async () => {
65
64
  const context = createStatelessContext();
66
-
67
65
  const result = await processor.process(workflow, { inputText: 'Custom meeting notes here' }, context);
68
66
 
69
67
  expect(result.hasError).toBe(false);
70
68
  expect(result.stop).toBe(true);
71
-
72
69
  expect(result.documents[0]).toEqual(
73
70
  expect.objectContaining({
74
71
  content: expect.objectContaining({
@@ -83,7 +80,9 @@ describe('MeetingNotesWorkflow', () => {
83
80
  it('should process user response and call LLM to optimize notes', async () => {
84
81
  const workflowId = '00000000-0000-0000-0000-000000000001';
85
82
 
86
- mockClaudeGenerateDocument.call.mockResolvedValue({ data: undefined });
83
+ mockLlmGenerateObject.call.mockResolvedValue({
84
+ data: { data: {} },
85
+ });
87
86
 
88
87
  const context = {
89
88
  workflowEntity: {
@@ -106,7 +105,6 @@ describe('MeetingNotesWorkflow', () => {
106
105
  expect(result.stop).toBe(true);
107
106
  expect(result.place).toBe('notes_optimized');
108
107
 
109
- // User response should have been saved as document
110
108
  expect(result.documents).toEqual(
111
109
  expect.arrayContaining([
112
110
  expect.objectContaining({
@@ -115,15 +113,13 @@ describe('MeetingNotesWorkflow', () => {
115
113
  ]),
116
114
  );
117
115
 
118
- // LLM should have been called to optimize notes
119
- expect(mockClaudeGenerateDocument.call).toHaveBeenCalledTimes(1);
120
- expect(mockClaudeGenerateDocument.call).toHaveBeenCalledWith(
116
+ expect(mockLlmGenerateObject.call).toHaveBeenCalledTimes(1);
117
+ expect(mockLlmGenerateObject.call).toHaveBeenCalledWith(
121
118
  expect.objectContaining({
122
- claude: { model: 'claude-sonnet-4-6' },
123
- response: expect.objectContaining({ id: 'final' }),
119
+ outputSchema: expect.any(Object),
124
120
  prompt: expect.stringContaining('meeting notes'),
125
121
  }),
126
- undefined,
122
+ expect.anything(),
127
123
  );
128
124
  });
129
125
  });
@@ -161,7 +157,6 @@ describe('MeetingNotesWorkflow', () => {
161
157
  expect(result.stop).toBe(false);
162
158
  expect(result.place).toBe('end');
163
159
 
164
- // Confirmed payload should have been saved as OptimizedNotesDocument
165
160
  expect(result.documents).toEqual(
166
161
  expect.arrayContaining([
167
162
  expect.objectContaining({
@@ -170,8 +165,7 @@ describe('MeetingNotesWorkflow', () => {
170
165
  ]),
171
166
  );
172
167
 
173
- // No additional LLM calls during confirmation
174
- expect(mockClaudeGenerateDocument.call).not.toHaveBeenCalled();
168
+ expect(mockLlmGenerateObject.call).not.toHaveBeenCalled();
175
169
  });
176
170
  });
177
171
  });
@@ -1,12 +1,11 @@
1
1
  import { Module } from '@nestjs/common';
2
2
  import { ClaudeModule } from '@loopstack/claude-module';
3
- import { LoopCoreModule } from '@loopstack/core';
4
3
  import { MeetingNotesDocument } from './documents/meeting-notes-document';
5
4
  import { OptimizedNotesDocument } from './documents/optimized-notes-document';
6
5
  import { MeetingNotesWorkflow } from './meeting-notes.workflow';
7
6
 
8
7
  @Module({
9
- imports: [LoopCoreModule, ClaudeModule],
8
+ imports: [ClaudeModule],
10
9
  providers: [MeetingNotesWorkflow, MeetingNotesDocument, OptimizedNotesDocument],
11
10
  exports: [MeetingNotesWorkflow],
12
11
  })
@@ -1,6 +1,8 @@
1
1
  import { z } from 'zod';
2
- import { ClaudeGenerateDocument } from '@loopstack/claude-module';
2
+ import { toJSONSchema } from 'zod';
3
3
  import { BaseWorkflow, Final, Initial, InjectTool, Transition, Workflow } from '@loopstack/common';
4
+ import type { LlmGenerateObjectResult } from '@loopstack/llm-provider-module';
5
+ import { LlmGenerateObjectTool } from '@loopstack/llm-provider-module';
4
6
  import { MeetingNotesDocument, MeetingNotesDocumentSchema } from './documents/meeting-notes-document';
5
7
  import { OptimizedMeetingNotesDocumentSchema, OptimizedNotesDocument } from './documents/optimized-notes-document';
6
8
 
@@ -15,7 +17,8 @@ import { OptimizedMeetingNotesDocumentSchema, OptimizedNotesDocument } from './d
15
17
  }),
16
18
  })
17
19
  export class MeetingNotesWorkflow extends BaseWorkflow<{ inputText: string }> {
18
- @InjectTool() claudeGenerateDocument: ClaudeGenerateDocument;
20
+ @InjectTool({ provider: 'claude', model: 'claude-sonnet-4-6' })
21
+ llmGenerateObject: LlmGenerateObjectTool;
19
22
 
20
23
  meetingNotes?: z.infer<typeof MeetingNotesDocumentSchema>;
21
24
  optimizedNotes?: z.infer<typeof OptimizedMeetingNotesDocumentSchema>;
@@ -24,9 +27,7 @@ export class MeetingNotesWorkflow extends BaseWorkflow<{ inputText: string }> {
24
27
  async createForm(args: { inputText: string }) {
25
28
  await this.repository.save(
26
29
  MeetingNotesDocument,
27
- {
28
- text: `Unstructured Notes:\n\n${args.inputText}`,
29
- },
30
+ { text: `Unstructured Notes:\n\n${args.inputText}` },
30
31
  { id: 'input' },
31
32
  );
32
33
  }
@@ -39,18 +40,20 @@ export class MeetingNotesWorkflow extends BaseWorkflow<{ inputText: string }> {
39
40
 
40
41
  @Transition({ from: 'response_received', to: 'notes_optimized' })
41
42
  async optimizeNotes() {
42
- await this.claudeGenerateDocument.call({
43
- claude: { model: 'claude-sonnet-4-6' },
44
- response: {
43
+ const result = await this.llmGenerateObject.call({
44
+ outputSchema: toJSONSchema(OptimizedMeetingNotesDocumentSchema) as Record<string, unknown>,
45
+ prompt: this.render(__dirname + '/templates/extract-notes.md', { text: this.meetingNotes?.text }),
46
+ });
47
+
48
+ const objectResult = result.data as LlmGenerateObjectResult;
49
+ await this.repository.save(
50
+ OptimizedNotesDocument,
51
+ objectResult.data as z.infer<typeof OptimizedMeetingNotesDocumentSchema>,
52
+ {
45
53
  id: 'final',
46
- document: OptimizedNotesDocument,
54
+ validate: 'skip',
47
55
  },
48
- prompt: `Extract all information from the provided meeting notes into the structured document.
49
-
50
- <Meeting Notes>
51
- ${this.meetingNotes?.text}
52
- </Meeting Notes>`,
53
- });
56
+ );
54
57
  }
55
58
 
56
59
  @Final({ from: 'notes_optimized', wait: true, schema: OptimizedMeetingNotesDocumentSchema })
@@ -0,0 +1,5 @@
1
+ Extract all information from the provided meeting notes into the structured document.
2
+
3
+ <Meeting Notes>
4
+ {{text}}
5
+ </Meeting Notes>