@modular-prompt/process 0.1.28 → 0.2.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 +49 -58
- package/dist/workflows/agentic-workflow/agentic-workflow.d.ts +12 -8
- package/dist/workflows/agentic-workflow/agentic-workflow.d.ts.map +1 -1
- package/dist/workflows/agentic-workflow/agentic-workflow.js +186 -205
- package/dist/workflows/agentic-workflow/agentic-workflow.js.map +1 -1
- package/dist/workflows/agentic-workflow/index.d.ts +5 -2
- package/dist/workflows/agentic-workflow/index.d.ts.map +1 -1
- package/dist/workflows/agentic-workflow/index.js +5 -2
- package/dist/workflows/agentic-workflow/index.js.map +1 -1
- package/dist/workflows/agentic-workflow/process/builtin-tools.d.ts +31 -0
- package/dist/workflows/agentic-workflow/process/builtin-tools.d.ts.map +1 -0
- package/dist/workflows/agentic-workflow/process/builtin-tools.js +158 -0
- package/dist/workflows/agentic-workflow/process/builtin-tools.js.map +1 -0
- package/dist/workflows/agentic-workflow/process/format-helpers.d.ts +11 -0
- package/dist/workflows/agentic-workflow/process/format-helpers.d.ts.map +1 -0
- package/dist/workflows/agentic-workflow/process/format-helpers.js +18 -0
- package/dist/workflows/agentic-workflow/process/format-helpers.js.map +1 -0
- package/dist/workflows/agentic-workflow/process/index.d.ts +7 -0
- package/dist/workflows/agentic-workflow/process/index.d.ts.map +1 -0
- package/dist/workflows/agentic-workflow/process/index.js +7 -0
- package/dist/workflows/agentic-workflow/process/index.js.map +1 -0
- package/dist/workflows/agentic-workflow/process/query-with-tools.d.ts +37 -0
- package/dist/workflows/agentic-workflow/process/query-with-tools.d.ts.map +1 -0
- package/dist/workflows/agentic-workflow/process/query-with-tools.js +118 -0
- package/dist/workflows/agentic-workflow/process/query-with-tools.js.map +1 -0
- package/dist/workflows/agentic-workflow/task-types/execution-tasks.d.ts +35 -0
- package/dist/workflows/agentic-workflow/task-types/execution-tasks.d.ts.map +1 -0
- package/dist/workflows/agentic-workflow/task-types/execution-tasks.js +155 -0
- package/dist/workflows/agentic-workflow/task-types/execution-tasks.js.map +1 -0
- package/dist/workflows/agentic-workflow/task-types/index.d.ts +37 -0
- package/dist/workflows/agentic-workflow/task-types/index.d.ts.map +1 -0
- package/dist/workflows/agentic-workflow/task-types/index.js +103 -0
- package/dist/workflows/agentic-workflow/task-types/index.js.map +1 -0
- package/dist/workflows/agentic-workflow/task-types/output.d.ts +16 -0
- package/dist/workflows/agentic-workflow/task-types/output.d.ts.map +1 -0
- package/dist/workflows/agentic-workflow/task-types/output.js +32 -0
- package/dist/workflows/agentic-workflow/task-types/output.js.map +1 -0
- package/dist/workflows/agentic-workflow/task-types/planning.d.ts +19 -0
- package/dist/workflows/agentic-workflow/task-types/planning.d.ts.map +1 -0
- package/dist/workflows/agentic-workflow/task-types/planning.js +77 -0
- package/dist/workflows/agentic-workflow/task-types/planning.js.map +1 -0
- package/dist/workflows/agentic-workflow/types.d.ts +83 -37
- package/dist/workflows/agentic-workflow/types.d.ts.map +1 -1
- package/dist/workflows/agentic-workflow/types.js +27 -1
- package/dist/workflows/agentic-workflow/types.js.map +1 -1
- package/dist/workflows/concat-process-workflow.d.ts +3 -2
- package/dist/workflows/concat-process-workflow.d.ts.map +1 -1
- package/dist/workflows/concat-process-workflow.js +41 -5
- package/dist/workflows/concat-process-workflow.js.map +1 -1
- package/dist/workflows/default-workflow.d.ts +3 -2
- package/dist/workflows/default-workflow.d.ts.map +1 -1
- package/dist/workflows/default-workflow.js +14 -1
- package/dist/workflows/default-workflow.js.map +1 -1
- package/dist/workflows/dialogue-workflow.d.ts +3 -2
- package/dist/workflows/dialogue-workflow.d.ts.map +1 -1
- package/dist/workflows/dialogue-workflow.js +15 -3
- package/dist/workflows/dialogue-workflow.js.map +1 -1
- package/dist/workflows/driver-input.d.ts +16 -0
- package/dist/workflows/driver-input.d.ts.map +1 -0
- package/dist/workflows/driver-input.js +18 -0
- package/dist/workflows/driver-input.js.map +1 -0
- package/dist/workflows/index.d.ts +6 -3
- package/dist/workflows/index.d.ts.map +1 -1
- package/dist/workflows/index.js +5 -2
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/self-prompting-workflow/self-prompting-workflow.d.ts +3 -2
- package/dist/workflows/self-prompting-workflow/self-prompting-workflow.d.ts.map +1 -1
- package/dist/workflows/self-prompting-workflow/self-prompting-workflow.js +4 -3
- package/dist/workflows/self-prompting-workflow/self-prompting-workflow.js.map +1 -1
- package/dist/workflows/stream-workflow.d.ts +3 -2
- package/dist/workflows/stream-workflow.d.ts.map +1 -1
- package/dist/workflows/stream-workflow.js +11 -3
- package/dist/workflows/stream-workflow.js.map +1 -1
- package/dist/workflows/summarize-workflow.d.ts +3 -2
- package/dist/workflows/summarize-workflow.d.ts.map +1 -1
- package/dist/workflows/summarize-workflow.js +11 -2
- package/dist/workflows/summarize-workflow.js.map +1 -1
- package/package.json +4 -3
- package/dist/workflows/agent-workflow.d.ts +0 -55
- package/dist/workflows/agent-workflow.d.ts.map +0 -1
- package/dist/workflows/agent-workflow.js +0 -337
- package/dist/workflows/agent-workflow.js.map +0 -1
- package/dist/workflows/agentic-workflow/modules/agentic.d.ts +0 -12
- package/dist/workflows/agentic-workflow/modules/agentic.d.ts.map +0 -1
- package/dist/workflows/agentic-workflow/modules/agentic.js +0 -22
- package/dist/workflows/agentic-workflow/modules/agentic.js.map +0 -1
- package/dist/workflows/agentic-workflow/modules/execution-freeform.d.ts +0 -15
- package/dist/workflows/agentic-workflow/modules/execution-freeform.d.ts.map +0 -1
- package/dist/workflows/agentic-workflow/modules/execution-freeform.js +0 -140
- package/dist/workflows/agentic-workflow/modules/execution-freeform.js.map +0 -1
- package/dist/workflows/agentic-workflow/modules/execution.d.ts +0 -11
- package/dist/workflows/agentic-workflow/modules/execution.d.ts.map +0 -1
- package/dist/workflows/agentic-workflow/modules/execution.js +0 -180
- package/dist/workflows/agentic-workflow/modules/execution.js.map +0 -1
- package/dist/workflows/agentic-workflow/modules/index.d.ts +0 -6
- package/dist/workflows/agentic-workflow/modules/index.d.ts.map +0 -1
- package/dist/workflows/agentic-workflow/modules/index.js +0 -7
- package/dist/workflows/agentic-workflow/modules/index.js.map +0 -1
- package/dist/workflows/agentic-workflow/modules/integration.d.ts +0 -11
- package/dist/workflows/agentic-workflow/modules/integration.d.ts.map +0 -1
- package/dist/workflows/agentic-workflow/modules/integration.js +0 -85
- package/dist/workflows/agentic-workflow/modules/integration.js.map +0 -1
- package/dist/workflows/agentic-workflow/modules/planning.d.ts +0 -11
- package/dist/workflows/agentic-workflow/modules/planning.d.ts.map +0 -1
- package/dist/workflows/agentic-workflow/modules/planning.js +0 -103
- package/dist/workflows/agentic-workflow/modules/planning.js.map +0 -1
package/README.md
CHANGED
|
@@ -10,6 +10,8 @@ npm install @modular-prompt/process
|
|
|
10
10
|
|
|
11
11
|
## ワークフロー
|
|
12
12
|
|
|
13
|
+
すべてのワークフロー関数は第1引数として `DriverInput` 型(`AIDriver` または `DriverSet`)を受け入れます。これにより、単一のドライバーまたは役割別の複数ドライバーを柔軟に指定できます。
|
|
14
|
+
|
|
13
15
|
### 基本ワークフロー
|
|
14
16
|
|
|
15
17
|
- **`defaultProcess`** - 最小のワークフロー(compile + driver.query)
|
|
@@ -19,7 +21,9 @@ npm install @modular-prompt/process
|
|
|
19
21
|
### チャンク処理ワークフロー
|
|
20
22
|
|
|
21
23
|
- **`streamProcess`** - ステートを保持しながらチャンクを逐次処理
|
|
24
|
+
- 内部で `streamProcessing` モジュールを自動的にマージ
|
|
22
25
|
- **`concatProcess`** - 各チャンクを独立して処理し、結果を結合
|
|
26
|
+
- 内部で `concatProcessing` モジュールを自動的にマージ
|
|
23
27
|
|
|
24
28
|
### エージェント型ワークフロー
|
|
25
29
|
|
|
@@ -69,14 +73,20 @@ console.log(result.output); // AIの応答
|
|
|
69
73
|
|
|
70
74
|
```typescript
|
|
71
75
|
import { streamProcess } from '@modular-prompt/process';
|
|
72
|
-
import { streamProcessing } from '@modular-prompt/process';
|
|
73
76
|
import { TestDriver } from '@modular-prompt/driver';
|
|
74
77
|
|
|
75
78
|
const driver = new TestDriver(['response1', 'response2']);
|
|
76
79
|
|
|
80
|
+
// streamProcessingモジュールは自動的にマージされるため、
|
|
81
|
+
// ユーザーモジュールのみを渡すことができます
|
|
82
|
+
const userModule = {
|
|
83
|
+
objective: ['チャンクを順次処理して要約を作成'],
|
|
84
|
+
instructions: ['各チャンクの内容を前の状態と統合']
|
|
85
|
+
};
|
|
86
|
+
|
|
77
87
|
const result = await streamProcess(
|
|
78
88
|
driver,
|
|
79
|
-
streamProcessing
|
|
89
|
+
userModule, // streamProcessingは内部で自動マージ
|
|
80
90
|
{
|
|
81
91
|
chunks: [{ content: 'text1' }, { content: 'text2' }],
|
|
82
92
|
state: { content: '', usage: 0 }
|
|
@@ -122,79 +132,60 @@ const context = {
|
|
|
122
132
|
}
|
|
123
133
|
};
|
|
124
134
|
|
|
125
|
-
//
|
|
135
|
+
// ワークフロー実行(planning → execution tasks → output)
|
|
126
136
|
const result = await agenticProcess(driver, userModule, context, {
|
|
127
|
-
|
|
137
|
+
maxTasks: 5, // 最大5タスクまで
|
|
128
138
|
});
|
|
129
139
|
|
|
130
140
|
console.log(result.output); // 最終的な献立提案
|
|
131
|
-
console.log(result.metadata); // {
|
|
141
|
+
console.log(result.metadata); // { planTasks, executedTasks, toolCallsUsed, finishReason }
|
|
132
142
|
```
|
|
133
143
|
|
|
134
|
-
###
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
import { agentProcess } from '@modular-prompt/process';
|
|
138
|
-
import { TestDriver } from '@modular-prompt/driver';
|
|
139
|
-
|
|
140
|
-
const driver = new TestDriver();
|
|
141
|
-
|
|
142
|
-
const userModule = {
|
|
143
|
-
objective: ['週末旅行プランを提案する'],
|
|
144
|
-
instructions: [
|
|
145
|
-
'- 交通手段・宿泊先・食事プランを検討する',
|
|
146
|
-
'- 入力データに応じて実行計画を自律的に組み立てる'
|
|
147
|
-
]
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
const context = {
|
|
151
|
-
objective: '週末旅行プランを提案する',
|
|
152
|
-
inputs: {
|
|
153
|
-
budget: '50,000円',
|
|
154
|
-
city: '箱根'
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
const actions = {
|
|
159
|
-
lookupHotel: async (params: { city: string }) => {
|
|
160
|
-
return { recommended: [`${params.city} 温泉旅館`] };
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
const result = await agentProcess(driver, userModule, context, {
|
|
165
|
-
maxSteps: 4,
|
|
166
|
-
actions
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
console.log(result.output);
|
|
170
|
-
console.log(result.metadata); // { planSteps: 3, executedSteps: 3, actionsUsed: 1 }
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
### アクション(外部ツール)の使用
|
|
144
|
+
### 外部ツールの使用
|
|
174
145
|
|
|
175
146
|
```typescript
|
|
176
147
|
import { agenticProcess } from '@modular-prompt/process';
|
|
148
|
+
import type { ToolSpec } from '@modular-prompt/process';
|
|
177
149
|
|
|
178
|
-
//
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
150
|
+
// 外部ツールの定義(definition + handler)
|
|
151
|
+
const tools: ToolSpec[] = [
|
|
152
|
+
{
|
|
153
|
+
definition: {
|
|
154
|
+
name: 'fetchWeather',
|
|
155
|
+
description: 'Get weather information for a location',
|
|
156
|
+
parameters: {
|
|
157
|
+
type: 'object',
|
|
158
|
+
properties: {
|
|
159
|
+
location: { type: 'string', description: 'City name' }
|
|
160
|
+
},
|
|
161
|
+
required: ['location'],
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
handler: async (params) => {
|
|
165
|
+
const response = await fetch(`https://api.weather.com/${params.location}`);
|
|
166
|
+
return JSON.stringify(await response.json());
|
|
167
|
+
},
|
|
183
168
|
},
|
|
184
|
-
|
|
185
|
-
// レシピ検索APIを呼び出し
|
|
186
|
-
return { recipes: [...] };
|
|
187
|
-
}
|
|
188
|
-
};
|
|
169
|
+
];
|
|
189
170
|
|
|
190
171
|
const result = await agenticProcess(driver, userModule, context, {
|
|
191
|
-
|
|
192
|
-
|
|
172
|
+
tools, // 外部ツールを渡す
|
|
173
|
+
maxTasks: 5,
|
|
193
174
|
});
|
|
194
175
|
|
|
195
|
-
//
|
|
176
|
+
// 外部ツール呼び出しが発生するとワークフローは中断し、
|
|
177
|
+
// pendingToolCalls として返却される
|
|
178
|
+
if (result.metadata.finishReason === 'tool_calls') {
|
|
179
|
+
// 呼び出し元でツールを実行し、結果を渡して再開する
|
|
180
|
+
console.log(result.context.executionLog);
|
|
181
|
+
}
|
|
196
182
|
```
|
|
197
183
|
|
|
184
|
+
## 開発者向けドキュメント
|
|
185
|
+
|
|
186
|
+
ワークフロー実装者向けのドキュメント:
|
|
187
|
+
|
|
188
|
+
- **[ワークフローログ規約](./docs/WORKFLOW_LOG_CONVENTIONS.md)** - Logger 使用規約とログ出力の標準化
|
|
198
189
|
|
|
199
190
|
## ライセンス
|
|
200
191
|
|
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
import type { PromptModule } from '@modular-prompt/core';
|
|
2
|
-
import type { AIDriver, WorkflowResult } from '../types.js';
|
|
3
|
-
import type { AgenticWorkflowContext, AgenticWorkflowOptions } from './types.js';
|
|
4
1
|
/**
|
|
5
|
-
* Agentic workflow -
|
|
2
|
+
* Agentic workflow v2 - task sequence based processing
|
|
3
|
+
*
|
|
4
|
+
* Fixed phases are replaced by a task sequence.
|
|
5
|
+
* Each task type has its own prompt construction and input contract.
|
|
6
6
|
*
|
|
7
7
|
* Flow:
|
|
8
|
-
* 1.
|
|
9
|
-
* 2.
|
|
10
|
-
* 3.
|
|
8
|
+
* 1. Bootstrap: Generate initial task list [planning, outputXxx]
|
|
9
|
+
* 2. Task loop: Execute each task sequentially
|
|
10
|
+
* 3. Output: Last task (outputMessage/outputStructured) result is the final output
|
|
11
11
|
*/
|
|
12
|
-
|
|
12
|
+
import type { PromptModule } from '@modular-prompt/core';
|
|
13
|
+
import type { WorkflowResult } from '../types.js';
|
|
14
|
+
import type { AgenticWorkflowContext, AgenticWorkflowOptions } from './types.js';
|
|
15
|
+
import { type DriverInput } from '../driver-input.js';
|
|
16
|
+
export declare function agenticProcess(driver: DriverInput, module: PromptModule<AgenticWorkflowContext>, context: AgenticWorkflowContext, options?: AgenticWorkflowOptions): Promise<WorkflowResult<AgenticWorkflowContext>>;
|
|
13
17
|
//# sourceMappingURL=agentic-workflow.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agentic-workflow.d.ts","sourceRoot":"","sources":["../../../src/workflows/agentic-workflow/agentic-workflow.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agentic-workflow.d.ts","sourceRoot":"","sources":["../../../src/workflows/agentic-workflow/agentic-workflow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,sBAAsB,CAAC;AAGzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EACV,sBAAsB,EACtB,sBAAsB,EAKvB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,KAAK,WAAW,EAAiB,MAAM,oBAAoB,CAAC;AAiKrE,wBAAsB,cAAc,CAClC,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,YAAY,CAAC,sBAAsB,CAAC,EAC5C,OAAO,EAAE,sBAAsB,EAC/B,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,cAAc,CAAC,sBAAsB,CAAC,CAAC,CAqHjD"}
|
|
@@ -1,235 +1,216 @@
|
|
|
1
|
-
import { compile, merge } from '@modular-prompt/core';
|
|
2
|
-
import { WorkflowExecutionError } from '../types.js';
|
|
3
|
-
import { agentic } from './modules/agentic.js';
|
|
4
|
-
import { planning } from './modules/planning.js';
|
|
5
|
-
import { execution } from './modules/execution.js';
|
|
6
|
-
import { executionFreeform } from './modules/execution-freeform.js';
|
|
7
|
-
import { integration } from './modules/integration.js';
|
|
8
1
|
/**
|
|
9
|
-
*
|
|
2
|
+
* Agentic workflow v2 - task sequence based processing
|
|
3
|
+
*
|
|
4
|
+
* Fixed phases are replaced by a task sequence.
|
|
5
|
+
* Each task type has its own prompt construction and input contract.
|
|
6
|
+
*
|
|
7
|
+
* Flow:
|
|
8
|
+
* 1. Bootstrap: Generate initial task list [planning, outputXxx]
|
|
9
|
+
* 2. Task loop: Execute each task sequentially
|
|
10
|
+
* 3. Output: Last task (outputMessage/outputStructured) result is the final output
|
|
10
11
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (!planResult.structuredOutput) {
|
|
26
|
-
throw new WorkflowExecutionError('Planning did not return structured output', context, {
|
|
27
|
-
phase: 'planning',
|
|
28
|
-
partialResult: planResult.content
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
const plan = planResult.structuredOutput;
|
|
32
|
-
// Validate and limit steps
|
|
33
|
-
if (!plan.steps || !Array.isArray(plan.steps)) {
|
|
34
|
-
throw new WorkflowExecutionError('Invalid plan structure: steps is not an array', context, {
|
|
35
|
-
phase: 'planning',
|
|
36
|
-
partialResult: JSON.stringify(planResult.structuredOutput)
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
// Limit number of steps
|
|
40
|
-
if (plan.steps.length > maxSteps) {
|
|
41
|
-
plan.steps = plan.steps.slice(0, maxSteps);
|
|
42
|
-
}
|
|
43
|
-
return plan;
|
|
44
|
-
}
|
|
45
|
-
catch (error) {
|
|
46
|
-
if (error instanceof WorkflowExecutionError) {
|
|
47
|
-
throw error;
|
|
48
|
-
}
|
|
49
|
-
throw new WorkflowExecutionError(error, context, {
|
|
50
|
-
phase: 'planning'
|
|
51
|
-
});
|
|
52
|
-
}
|
|
12
|
+
import { merge, resolve } from '@modular-prompt/core';
|
|
13
|
+
import { Logger } from '@modular-prompt/utils';
|
|
14
|
+
import { DEFAULT_DRIVER_ROLE } from './types.js';
|
|
15
|
+
import { resolveDriver } from '../driver-input.js';
|
|
16
|
+
import { getTaskTypeConfig, taskCommon } from './task-types/index.js';
|
|
17
|
+
import { createPlanningTools, createExecutionBuiltinTools, createUpdateStateTool, } from './process/builtin-tools.js';
|
|
18
|
+
import { queryWithTools, rethrowAsWorkflowError } from './process/query-with-tools.js';
|
|
19
|
+
const logger = new Logger({ prefix: 'process', context: 'agentic' });
|
|
20
|
+
/**
|
|
21
|
+
* Strip <think>...</think> blocks from model output.
|
|
22
|
+
* Thinking traces are internal reasoning and should not be passed to subsequent tasks.
|
|
23
|
+
*/
|
|
24
|
+
function stripThinkBlocks(text) {
|
|
25
|
+
return text.replace(/<think>[\s\S]*?<\/think>\s*/g, '').replace(/^[\s\S]*?<\/think>\s*/g, '').trim();
|
|
53
26
|
}
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// Bootstrap
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
54
30
|
/**
|
|
55
|
-
*
|
|
31
|
+
* Generate the initial task list based on the user module.
|
|
32
|
+
* - Always starts with a planning task.
|
|
33
|
+
* - Ends with outputStructured (if schema) or outputMessage.
|
|
56
34
|
*/
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
actionResult = await actions[action.tool](action.params, context);
|
|
65
|
-
}
|
|
66
|
-
catch (error) {
|
|
67
|
-
throw new WorkflowExecutionError(`Tool '${action.tool}' failed: ${error.message}`, {
|
|
68
|
-
...context,
|
|
69
|
-
executionLog,
|
|
70
|
-
currentStep: step
|
|
71
|
-
}, {
|
|
72
|
-
phase: 'execution',
|
|
73
|
-
partialResult: executionLog.map(log => log.result).join('\n\n')
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
// Execute step with AI
|
|
80
|
-
const executionPhaseModule = useFreeform ? executionFreeform : execution;
|
|
81
|
-
// For freeform mode, omit user's instructions to use plan-based guidelines/constraints instead
|
|
82
|
-
// For structured mode, use user's instructions as-is
|
|
83
|
-
const userModule = useFreeform
|
|
84
|
-
? { ...module, instructions: undefined }
|
|
85
|
-
: module;
|
|
86
|
-
const executionModule = merge(agentic, executionPhaseModule, userModule);
|
|
87
|
-
const stepContext = {
|
|
88
|
-
...context,
|
|
89
|
-
currentStep: step,
|
|
90
|
-
actionResult,
|
|
91
|
-
executionLog
|
|
92
|
-
};
|
|
93
|
-
const prompt = compile(executionModule, stepContext);
|
|
94
|
-
try {
|
|
95
|
-
const stepResult = await driver.query(prompt);
|
|
96
|
-
logger?.debug(`Execution step ${step.id} - AI generated:`, stepResult.content);
|
|
97
|
-
// Check finish reason
|
|
98
|
-
if (stepResult.finishReason && stepResult.finishReason !== 'stop') {
|
|
99
|
-
throw new WorkflowExecutionError(`Step execution failed with reason: ${stepResult.finishReason}`, stepContext, {
|
|
100
|
-
phase: 'execution',
|
|
101
|
-
partialResult: executionLog.map(log => log.result).join('\n\n'),
|
|
102
|
-
finishReason: stepResult.finishReason
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
// Get reasoning, result and nextState from structured output
|
|
106
|
-
let reasoning;
|
|
107
|
-
let result;
|
|
108
|
-
let nextState;
|
|
109
|
-
if (stepResult.structuredOutput) {
|
|
110
|
-
const output = stepResult.structuredOutput;
|
|
111
|
-
reasoning = output.reasoning || '';
|
|
112
|
-
result = output.result || stepResult.content;
|
|
113
|
-
nextState = output.nextState || '';
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
// Fallback if structured output is not available
|
|
117
|
-
reasoning = '';
|
|
118
|
-
result = stepResult.content;
|
|
119
|
-
nextState = '';
|
|
120
|
-
}
|
|
121
|
-
// Update context state with nextState for the next step
|
|
122
|
-
context.state = {
|
|
123
|
-
content: nextState,
|
|
124
|
-
usage: stepResult.usage?.totalTokens
|
|
125
|
-
};
|
|
126
|
-
// Create execution log entry (without nextState - it's in context.state now)
|
|
127
|
-
return {
|
|
128
|
-
stepId: step.id,
|
|
129
|
-
reasoning,
|
|
130
|
-
result,
|
|
131
|
-
actionResult,
|
|
132
|
-
metadata: {
|
|
133
|
-
usage: stepResult.usage
|
|
134
|
-
}
|
|
135
|
-
};
|
|
35
|
+
function bootstrap(module, enablePlanning) {
|
|
36
|
+
const tasks = [];
|
|
37
|
+
if (enablePlanning) {
|
|
38
|
+
tasks.push({
|
|
39
|
+
instruction: 'Analyze the prompt and register tasks',
|
|
40
|
+
taskType: 'planning',
|
|
41
|
+
});
|
|
136
42
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
phase: 'execution',
|
|
143
|
-
partialResult: executionLog.map(log => log.result).join('\n\n')
|
|
43
|
+
else {
|
|
44
|
+
// No planning: default to a single output task
|
|
45
|
+
tasks.push({
|
|
46
|
+
instruction: 'Compose the response using the preceding task results.',
|
|
47
|
+
taskType: 'output',
|
|
144
48
|
});
|
|
145
49
|
}
|
|
50
|
+
return tasks;
|
|
146
51
|
}
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
// Task execution
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
147
55
|
/**
|
|
148
|
-
*
|
|
56
|
+
* Get builtin tools for a task based on its type config.
|
|
149
57
|
*/
|
|
150
|
-
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const step = plan.steps[i];
|
|
157
|
-
const logEntry = await executeStep(driver, module, context, step, actions, executionLog, useFreeform, logger);
|
|
158
|
-
executionLog.push(logEntry);
|
|
58
|
+
function getBuiltinToolsForTask(taskType, taskList, currentIndex, context) {
|
|
59
|
+
const config = getTaskTypeConfig(taskType);
|
|
60
|
+
const toolNames = new Set(config.builtinToolNames);
|
|
61
|
+
const allTools = [];
|
|
62
|
+
if (toolNames.has('__insert_tasks')) {
|
|
63
|
+
allTools.push(...createPlanningTools(taskList, currentIndex));
|
|
159
64
|
}
|
|
160
|
-
|
|
65
|
+
if (toolNames.has('__update_state')) {
|
|
66
|
+
allTools.push(createUpdateStateTool(context));
|
|
67
|
+
}
|
|
68
|
+
if (toolNames.has('__time')) {
|
|
69
|
+
// createExecutionBuiltinTools returns [__insert_tasks, __time]
|
|
70
|
+
// We only want __time if __insert_tasks is not already added
|
|
71
|
+
const execTools = createExecutionBuiltinTools(taskList, currentIndex);
|
|
72
|
+
const timeOnly = execTools.filter(t => t.definition.name === '__time');
|
|
73
|
+
allTools.push(...timeOnly);
|
|
74
|
+
}
|
|
75
|
+
return allTools;
|
|
161
76
|
}
|
|
162
77
|
/**
|
|
163
|
-
* Execute
|
|
78
|
+
* Execute a single task.
|
|
164
79
|
*/
|
|
165
|
-
async function
|
|
166
|
-
const
|
|
167
|
-
|
|
80
|
+
async function executeTask(driver, userModule, context, task, taskIndex, taskList, externalTools, maxToolCalls) {
|
|
81
|
+
const taskLogger = logger.context(`agentic:task:${taskIndex + 1}:${task.taskType}`);
|
|
82
|
+
taskLogger.info('[start]', task.instruction);
|
|
83
|
+
const taskConfig = getTaskTypeConfig(task.taskType);
|
|
84
|
+
// Build workflowBase from resolved userModule
|
|
85
|
+
// output tasks get the full userModule; other tasks get objective/terms/state only
|
|
86
|
+
const workflowBase = task.taskType === 'output'
|
|
87
|
+
? { ...userModule }
|
|
88
|
+
: {
|
|
89
|
+
objective: userModule.objective,
|
|
90
|
+
terms: userModule.terms,
|
|
91
|
+
state: userModule.state,
|
|
92
|
+
};
|
|
93
|
+
// Merge and resolve (taskCommon first for objective framing)
|
|
94
|
+
const resolved = resolve(merge(workflowBase, taskCommon, taskConfig.module), context);
|
|
95
|
+
const builtinTools = getBuiltinToolsForTask(task.taskType, taskList, taskIndex, context);
|
|
96
|
+
const externalToolDefs = externalTools.map(t => t.definition);
|
|
97
|
+
const allToolNames = [...builtinTools.map(t => t.definition.name), ...externalToolDefs.map(t => t.name)];
|
|
98
|
+
taskLogger.verbose('[prompt]', JSON.stringify(resolved), allToolNames.length > 0 ? `tools: [${allToolNames.join(', ')}]` : '');
|
|
99
|
+
const driverRole = task.driverRole || DEFAULT_DRIVER_ROLE[task.taskType];
|
|
168
100
|
try {
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
return
|
|
101
|
+
const isPlanning = task.taskType === 'planning';
|
|
102
|
+
const toolChoice = isPlanning ? 'required' : 'auto';
|
|
103
|
+
const result = await queryWithTools(resolveDriver(driver, driverRole), resolved, builtinTools, {
|
|
104
|
+
externalToolDefs: externalToolDefs.length > 0 ? externalToolDefs : undefined,
|
|
105
|
+
toolChoice,
|
|
106
|
+
maxIterations: maxToolCalls,
|
|
107
|
+
stopAfterToolCall: isPlanning,
|
|
108
|
+
logger: taskLogger,
|
|
109
|
+
});
|
|
110
|
+
taskLogger.info('[end]');
|
|
111
|
+
return {
|
|
112
|
+
taskType: task.taskType,
|
|
113
|
+
result: stripThinkBlocks(result.content),
|
|
114
|
+
pendingToolCalls: result.pendingToolCalls,
|
|
115
|
+
metadata: {
|
|
116
|
+
usage: result.usage,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
180
119
|
}
|
|
181
120
|
catch (error) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
throw new WorkflowExecutionError(error, context, {
|
|
186
|
-
phase: 'integration',
|
|
187
|
-
partialResult: executionLog.map(log => log.result).join('\n\n')
|
|
121
|
+
rethrowAsWorkflowError(error, context, {
|
|
122
|
+
phase: task.taskType,
|
|
123
|
+
partialResult: context.executionLog?.map(log => log.result).join('\n\n') || '',
|
|
188
124
|
});
|
|
189
125
|
}
|
|
190
126
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
* Flow:
|
|
195
|
-
* 1. Planning phase: Generate execution plan using structured outputs
|
|
196
|
-
* 2. Execution phase: Execute each step (with optional actions)
|
|
197
|
-
* 3. Integration phase: Integrate results and generate final output
|
|
198
|
-
*/
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
// Main workflow
|
|
129
|
+
// ---------------------------------------------------------------------------
|
|
199
130
|
export async function agenticProcess(driver, module, context, options = {}) {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
//
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
131
|
+
logger.info('[start] agentic workflow');
|
|
132
|
+
const { maxTasks = 10, tools = [], maxToolCalls = 10, enablePlanning = true, includeThinking = false, } = options;
|
|
133
|
+
// Resolve user module: DynamicContent → static values
|
|
134
|
+
// userModule is available throughout the workflow via context.userModule
|
|
135
|
+
const userModule = resolve(module, context);
|
|
136
|
+
context.userModule = userModule;
|
|
137
|
+
// Bootstrap task list
|
|
138
|
+
const taskList = bootstrap(userModule, enablePlanning);
|
|
139
|
+
const executionLog = context.executionLog
|
|
140
|
+
? [...context.executionLog]
|
|
141
|
+
: [];
|
|
142
|
+
const startIndex = executionLog.length;
|
|
143
|
+
// Task loop
|
|
144
|
+
for (let i = startIndex; i < taskList.length; i++) {
|
|
145
|
+
// Guard: max tasks
|
|
146
|
+
if (i >= maxTasks) {
|
|
147
|
+
logger.info('[end] Max tasks reached', `(${maxTasks})`);
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
const task = taskList[i];
|
|
151
|
+
const currentContext = {
|
|
152
|
+
...context,
|
|
153
|
+
taskList,
|
|
154
|
+
executionLog,
|
|
155
|
+
currentTaskIndex: i,
|
|
156
|
+
};
|
|
157
|
+
const logEntry = await executeTask(driver, userModule, currentContext, task, i, taskList, tools, maxToolCalls);
|
|
158
|
+
executionLog.push(logEntry);
|
|
159
|
+
}
|
|
160
|
+
// Auto-append output task if the last executed task was not output
|
|
161
|
+
const lastExecuted = executionLog[executionLog.length - 1];
|
|
162
|
+
if (lastExecuted && lastExecuted.taskType !== 'output') {
|
|
163
|
+
const outputTask = {
|
|
164
|
+
instruction: 'Compose the response using the preceding task results.',
|
|
165
|
+
taskType: 'output',
|
|
166
|
+
};
|
|
167
|
+
taskList.push(outputTask);
|
|
168
|
+
const outputIndex = taskList.length - 1;
|
|
169
|
+
const outputContext = {
|
|
170
|
+
...context,
|
|
171
|
+
taskList,
|
|
172
|
+
executionLog,
|
|
173
|
+
currentTaskIndex: outputIndex,
|
|
174
|
+
};
|
|
175
|
+
const outputLog = await executeTask(driver, userModule, outputContext, outputTask, outputIndex, taskList, tools, maxToolCalls);
|
|
176
|
+
executionLog.push(outputLog);
|
|
177
|
+
}
|
|
178
|
+
// Final output: last task's result, optionally prefixed with intermediate results as <think>
|
|
179
|
+
const lastLog = executionLog[executionLog.length - 1];
|
|
180
|
+
const finalResult = lastLog?.result || '';
|
|
181
|
+
let output;
|
|
182
|
+
if (includeThinking && executionLog.length > 1) {
|
|
183
|
+
const intermediateLog = executionLog.slice(0, -1);
|
|
184
|
+
const thinkingLines = intermediateLog
|
|
185
|
+
.map(log => `[${log.taskType}]\n${log.result}`)
|
|
186
|
+
.join('\n\n');
|
|
187
|
+
output = `<think>\n${thinkingLines}\n</think>\n\n${finalResult}`;
|
|
208
188
|
}
|
|
209
189
|
else {
|
|
210
|
-
|
|
211
|
-
plan = currentContext.plan;
|
|
190
|
+
output = finalResult;
|
|
212
191
|
}
|
|
213
|
-
//
|
|
214
|
-
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
// Complete
|
|
221
|
-
const finalContext = {
|
|
222
|
-
...currentContext,
|
|
223
|
-
phase: 'complete'
|
|
224
|
-
};
|
|
192
|
+
// Determine finishReason
|
|
193
|
+
const hasPendingToolCalls = executionLog.some(log => log.pendingToolCalls && log.pendingToolCalls.length > 0);
|
|
194
|
+
const finishReason = hasPendingToolCalls
|
|
195
|
+
? 'tool_calls'
|
|
196
|
+
: 'stop';
|
|
197
|
+
const totalToolCalls = executionLog.reduce((sum, log) => sum + (log.pendingToolCalls?.length || 0), 0);
|
|
198
|
+
logger.info('[end] agentic workflow');
|
|
225
199
|
return {
|
|
226
|
-
output
|
|
227
|
-
context:
|
|
200
|
+
output,
|
|
201
|
+
context: {
|
|
202
|
+
...context,
|
|
203
|
+
taskList,
|
|
204
|
+
executionLog,
|
|
205
|
+
currentTaskIndex: taskList.length,
|
|
206
|
+
},
|
|
228
207
|
metadata: {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
208
|
+
planTasks: taskList.length,
|
|
209
|
+
executedTasks: executionLog.length,
|
|
210
|
+
toolCallsUsed: totalToolCalls,
|
|
211
|
+
finishReason,
|
|
212
|
+
usage: lastLog?.metadata?.usage,
|
|
213
|
+
},
|
|
233
214
|
};
|
|
234
215
|
}
|
|
235
216
|
//# sourceMappingURL=agentic-workflow.js.map
|