pulse-coder-engine 0.0.1-alpha.10 → 0.0.1-alpha.11
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/built-in/index.cjs +47 -34
- package/dist/built-in/index.cjs.map +1 -1
- package/dist/built-in/index.d.cts +2 -2
- package/dist/built-in/index.d.ts +2 -2
- package/dist/built-in/index.js +47 -34
- package/dist/built-in/index.js.map +1 -1
- package/dist/{index-C7fdydbL.d.cts → index-BeWyLfso.d.cts} +60 -29
- package/dist/{index-C7fdydbL.d.ts → index-BeWyLfso.d.ts} +60 -29
- package/dist/index.cjs +113 -85
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -18
- package/dist/index.d.ts +32 -18
- package/dist/index.js +113 -85
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { FlexibleSchema, ModelMessage, LanguageModel, Tool as Tool$1 } from 'ai';
|
|
2
1
|
import { EventEmitter } from 'events';
|
|
2
|
+
import { ModelMessage, FlexibleSchema, LanguageModel } from 'ai';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Custom LLM provider factory - receives a model name and returns a LanguageModel.
|
|
@@ -77,6 +77,58 @@ interface ILogger {
|
|
|
77
77
|
error(message: string, error?: Error, meta?: Record<string, unknown>): void;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
/** Convenience: a value that may be wrapped in a Promise. */
|
|
81
|
+
type Promisable<T> = T | Promise<T>;
|
|
82
|
+
interface BeforeRunInput {
|
|
83
|
+
context: Context;
|
|
84
|
+
systemPrompt?: SystemPromptOption;
|
|
85
|
+
tools: Record<string, any>;
|
|
86
|
+
}
|
|
87
|
+
interface BeforeRunResult {
|
|
88
|
+
systemPrompt?: SystemPromptOption;
|
|
89
|
+
tools?: Record<string, any>;
|
|
90
|
+
}
|
|
91
|
+
type BeforeLLMCallInput = BeforeRunInput;
|
|
92
|
+
type BeforeLLMCallResult = BeforeRunResult;
|
|
93
|
+
interface AfterRunInput {
|
|
94
|
+
context: Context;
|
|
95
|
+
result: string;
|
|
96
|
+
}
|
|
97
|
+
interface AfterLLMCallInput {
|
|
98
|
+
context: Context;
|
|
99
|
+
finishReason: string;
|
|
100
|
+
text: string;
|
|
101
|
+
}
|
|
102
|
+
interface BeforeToolCallInput {
|
|
103
|
+
name: string;
|
|
104
|
+
input: any;
|
|
105
|
+
}
|
|
106
|
+
interface BeforeToolCallResult {
|
|
107
|
+
input?: any;
|
|
108
|
+
}
|
|
109
|
+
interface AfterToolCallInput {
|
|
110
|
+
name: string;
|
|
111
|
+
input: any;
|
|
112
|
+
output: any;
|
|
113
|
+
}
|
|
114
|
+
interface AfterToolCallResult {
|
|
115
|
+
output?: any;
|
|
116
|
+
}
|
|
117
|
+
interface EngineHookMap {
|
|
118
|
+
/** Fires once at the start of Engine.run(), before entering the loop. */
|
|
119
|
+
beforeRun: (input: BeforeRunInput) => Promisable<BeforeRunResult | void>;
|
|
120
|
+
/** Fires once when Engine.run() finishes. Read-only. */
|
|
121
|
+
afterRun: (input: AfterRunInput) => Promisable<void>;
|
|
122
|
+
/** Fires before each LLM call inside the loop (including retries after tool-calls). */
|
|
123
|
+
beforeLLMCall: (input: BeforeLLMCallInput) => Promisable<BeforeLLMCallResult | void>;
|
|
124
|
+
/** Fires after each LLM call completes. Read-only. */
|
|
125
|
+
afterLLMCall: (input: AfterLLMCallInput) => Promisable<void>;
|
|
126
|
+
/** Fires before each individual tool execution. Can modify input or throw to abort. */
|
|
127
|
+
beforeToolCall: (input: BeforeToolCallInput) => Promisable<BeforeToolCallResult | void>;
|
|
128
|
+
/** Fires after each individual tool execution. Can modify output. */
|
|
129
|
+
afterToolCall: (input: AfterToolCallInput) => Promisable<AfterToolCallResult | void>;
|
|
130
|
+
}
|
|
131
|
+
type EngineHookName = keyof EngineHookMap;
|
|
80
132
|
interface EnginePlugin {
|
|
81
133
|
name: string;
|
|
82
134
|
version: string;
|
|
@@ -86,28 +138,13 @@ interface EnginePlugin {
|
|
|
86
138
|
afterInitialize?(context: EnginePluginContext): Promise<void>;
|
|
87
139
|
destroy?(context: EnginePluginContext): Promise<void>;
|
|
88
140
|
}
|
|
89
|
-
interface EngineRunHookInput {
|
|
90
|
-
context: Context;
|
|
91
|
-
messages: ModelMessage[];
|
|
92
|
-
tools: Record<string, Tool$1>;
|
|
93
|
-
systemPrompt?: SystemPromptOption;
|
|
94
|
-
hooks?: ToolHooks;
|
|
95
|
-
}
|
|
96
|
-
interface EngineRunHookResult {
|
|
97
|
-
systemPrompt?: SystemPromptOption;
|
|
98
|
-
hooks?: ToolHooks;
|
|
99
|
-
}
|
|
100
|
-
type EngineRunHook = (input: EngineRunHookInput) => Promise<EngineRunHookResult | void> | EngineRunHookResult | void;
|
|
101
141
|
interface EnginePluginContext {
|
|
102
|
-
registerTool(name: string, tool:
|
|
103
|
-
registerTools(tools: Record<string,
|
|
104
|
-
getTool(name: string):
|
|
142
|
+
registerTool(name: string, tool: any): void;
|
|
143
|
+
registerTools(tools: Record<string, any>): void;
|
|
144
|
+
getTool(name: string): any;
|
|
105
145
|
/** Returns a snapshot of all tools registered by plugins so far. */
|
|
106
|
-
getTools(): Record<string,
|
|
107
|
-
|
|
108
|
-
getRunHook(name: string): EngineRunHook | undefined;
|
|
109
|
-
registerProtocol(name: string, handler: ProtocolHandler): void;
|
|
110
|
-
getProtocol(name: string): ProtocolHandler | undefined;
|
|
146
|
+
getTools(): Record<string, any>;
|
|
147
|
+
registerHook<K extends EngineHookName>(hookName: K, handler: EngineHookMap[K]): void;
|
|
111
148
|
registerService<T>(name: string, service: T): void;
|
|
112
149
|
getService<T>(name: string): T | undefined;
|
|
113
150
|
getConfig<T>(key: string): T | undefined;
|
|
@@ -120,10 +157,6 @@ interface EnginePluginContext {
|
|
|
120
157
|
error(message: string, error?: Error, meta?: any): void;
|
|
121
158
|
};
|
|
122
159
|
}
|
|
123
|
-
interface ProtocolHandler {
|
|
124
|
-
name: string;
|
|
125
|
-
handle(message: any): Promise<any>;
|
|
126
|
-
}
|
|
127
160
|
interface EnginePluginLoadOptions {
|
|
128
161
|
plugins?: EnginePlugin[];
|
|
129
162
|
dirs?: string[];
|
|
@@ -241,7 +274,6 @@ interface PlanModeService {
|
|
|
241
274
|
getModePolicy(mode?: PlanMode): ModePolicy;
|
|
242
275
|
getToolMetadata(toolNames: string[]): ToolMeta[];
|
|
243
276
|
buildPromptAppend(toolNames: string[], transition?: PlanModeTransitionResult): string;
|
|
244
|
-
applyHooks(baseHooks?: ToolHooks): ToolHooks;
|
|
245
277
|
getEvents(limit?: number): PlanModeEvent[];
|
|
246
278
|
}
|
|
247
279
|
type LoggerLike = EnginePluginContext['logger'];
|
|
@@ -258,9 +290,8 @@ declare class BuiltInPlanModeService implements PlanModeService {
|
|
|
258
290
|
getModePolicy(mode?: PlanMode): ModePolicy;
|
|
259
291
|
getToolMetadata(toolNames: string[]): ToolMeta[];
|
|
260
292
|
buildPromptAppend(toolNames: string[], transition?: PlanModeTransitionResult): string;
|
|
261
|
-
applyHooks(baseHooks?: ToolHooks): ToolHooks;
|
|
262
293
|
getEvents(limit?: number): PlanModeEvent[];
|
|
263
|
-
|
|
294
|
+
observePotentialPolicyViolation(toolName: string, input: unknown): void;
|
|
264
295
|
private inferToolMeta;
|
|
265
296
|
private getLatestUserText;
|
|
266
297
|
private messageContentToText;
|
|
@@ -274,4 +305,4 @@ declare const builtInPlanModePlugin: EnginePlugin;
|
|
|
274
305
|
*/
|
|
275
306
|
declare const builtInPlugins: (EnginePlugin | SubAgentPlugin)[];
|
|
276
307
|
|
|
277
|
-
export {
|
|
308
|
+
export { type AfterLLMCallInput as A, type BeforeLLMCallInput as B, type ClarificationRequest as C, builtInPlanModePlugin as D, type EngineHookMap as E, builtInPlugins as F, builtInSkillsPlugin as G, SubAgentPlugin as H, type ILogger as I, type LLMProviderFactory as L, type ModePolicy as M, type PlanMode as P, type SystemPromptOption as S, type Tool as T, type Context as a, type ToolExecutionContext as b, type EnginePluginLoadOptions as c, type ToolHooks as d, type EngineHookName as e, type AfterRunInput as f, type AfterToolCallInput as g, type AfterToolCallResult as h, type BeforeLLMCallResult as i, type BeforeRunInput as j, type BeforeRunResult as k, type BeforeToolCallInput as l, type BeforeToolCallResult as m, BuiltInPlanModeService as n, BuiltInSkillRegistry as o, type EnginePlugin as p, type EnginePluginContext as q, type PlanIntentLabel as r, type PlanModeEvent as s, type PlanModeEventName as t, type PlanModeService as u, type PlanModeTransitionResult as v, type ToolCategory as w, type ToolMeta as x, type ToolRisk as y, builtInMCPPlugin as z };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { FlexibleSchema, ModelMessage, LanguageModel, Tool as Tool$1 } from 'ai';
|
|
2
1
|
import { EventEmitter } from 'events';
|
|
2
|
+
import { ModelMessage, FlexibleSchema, LanguageModel } from 'ai';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Custom LLM provider factory - receives a model name and returns a LanguageModel.
|
|
@@ -77,6 +77,58 @@ interface ILogger {
|
|
|
77
77
|
error(message: string, error?: Error, meta?: Record<string, unknown>): void;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
/** Convenience: a value that may be wrapped in a Promise. */
|
|
81
|
+
type Promisable<T> = T | Promise<T>;
|
|
82
|
+
interface BeforeRunInput {
|
|
83
|
+
context: Context;
|
|
84
|
+
systemPrompt?: SystemPromptOption;
|
|
85
|
+
tools: Record<string, any>;
|
|
86
|
+
}
|
|
87
|
+
interface BeforeRunResult {
|
|
88
|
+
systemPrompt?: SystemPromptOption;
|
|
89
|
+
tools?: Record<string, any>;
|
|
90
|
+
}
|
|
91
|
+
type BeforeLLMCallInput = BeforeRunInput;
|
|
92
|
+
type BeforeLLMCallResult = BeforeRunResult;
|
|
93
|
+
interface AfterRunInput {
|
|
94
|
+
context: Context;
|
|
95
|
+
result: string;
|
|
96
|
+
}
|
|
97
|
+
interface AfterLLMCallInput {
|
|
98
|
+
context: Context;
|
|
99
|
+
finishReason: string;
|
|
100
|
+
text: string;
|
|
101
|
+
}
|
|
102
|
+
interface BeforeToolCallInput {
|
|
103
|
+
name: string;
|
|
104
|
+
input: any;
|
|
105
|
+
}
|
|
106
|
+
interface BeforeToolCallResult {
|
|
107
|
+
input?: any;
|
|
108
|
+
}
|
|
109
|
+
interface AfterToolCallInput {
|
|
110
|
+
name: string;
|
|
111
|
+
input: any;
|
|
112
|
+
output: any;
|
|
113
|
+
}
|
|
114
|
+
interface AfterToolCallResult {
|
|
115
|
+
output?: any;
|
|
116
|
+
}
|
|
117
|
+
interface EngineHookMap {
|
|
118
|
+
/** Fires once at the start of Engine.run(), before entering the loop. */
|
|
119
|
+
beforeRun: (input: BeforeRunInput) => Promisable<BeforeRunResult | void>;
|
|
120
|
+
/** Fires once when Engine.run() finishes. Read-only. */
|
|
121
|
+
afterRun: (input: AfterRunInput) => Promisable<void>;
|
|
122
|
+
/** Fires before each LLM call inside the loop (including retries after tool-calls). */
|
|
123
|
+
beforeLLMCall: (input: BeforeLLMCallInput) => Promisable<BeforeLLMCallResult | void>;
|
|
124
|
+
/** Fires after each LLM call completes. Read-only. */
|
|
125
|
+
afterLLMCall: (input: AfterLLMCallInput) => Promisable<void>;
|
|
126
|
+
/** Fires before each individual tool execution. Can modify input or throw to abort. */
|
|
127
|
+
beforeToolCall: (input: BeforeToolCallInput) => Promisable<BeforeToolCallResult | void>;
|
|
128
|
+
/** Fires after each individual tool execution. Can modify output. */
|
|
129
|
+
afterToolCall: (input: AfterToolCallInput) => Promisable<AfterToolCallResult | void>;
|
|
130
|
+
}
|
|
131
|
+
type EngineHookName = keyof EngineHookMap;
|
|
80
132
|
interface EnginePlugin {
|
|
81
133
|
name: string;
|
|
82
134
|
version: string;
|
|
@@ -86,28 +138,13 @@ interface EnginePlugin {
|
|
|
86
138
|
afterInitialize?(context: EnginePluginContext): Promise<void>;
|
|
87
139
|
destroy?(context: EnginePluginContext): Promise<void>;
|
|
88
140
|
}
|
|
89
|
-
interface EngineRunHookInput {
|
|
90
|
-
context: Context;
|
|
91
|
-
messages: ModelMessage[];
|
|
92
|
-
tools: Record<string, Tool$1>;
|
|
93
|
-
systemPrompt?: SystemPromptOption;
|
|
94
|
-
hooks?: ToolHooks;
|
|
95
|
-
}
|
|
96
|
-
interface EngineRunHookResult {
|
|
97
|
-
systemPrompt?: SystemPromptOption;
|
|
98
|
-
hooks?: ToolHooks;
|
|
99
|
-
}
|
|
100
|
-
type EngineRunHook = (input: EngineRunHookInput) => Promise<EngineRunHookResult | void> | EngineRunHookResult | void;
|
|
101
141
|
interface EnginePluginContext {
|
|
102
|
-
registerTool(name: string, tool:
|
|
103
|
-
registerTools(tools: Record<string,
|
|
104
|
-
getTool(name: string):
|
|
142
|
+
registerTool(name: string, tool: any): void;
|
|
143
|
+
registerTools(tools: Record<string, any>): void;
|
|
144
|
+
getTool(name: string): any;
|
|
105
145
|
/** Returns a snapshot of all tools registered by plugins so far. */
|
|
106
|
-
getTools(): Record<string,
|
|
107
|
-
|
|
108
|
-
getRunHook(name: string): EngineRunHook | undefined;
|
|
109
|
-
registerProtocol(name: string, handler: ProtocolHandler): void;
|
|
110
|
-
getProtocol(name: string): ProtocolHandler | undefined;
|
|
146
|
+
getTools(): Record<string, any>;
|
|
147
|
+
registerHook<K extends EngineHookName>(hookName: K, handler: EngineHookMap[K]): void;
|
|
111
148
|
registerService<T>(name: string, service: T): void;
|
|
112
149
|
getService<T>(name: string): T | undefined;
|
|
113
150
|
getConfig<T>(key: string): T | undefined;
|
|
@@ -120,10 +157,6 @@ interface EnginePluginContext {
|
|
|
120
157
|
error(message: string, error?: Error, meta?: any): void;
|
|
121
158
|
};
|
|
122
159
|
}
|
|
123
|
-
interface ProtocolHandler {
|
|
124
|
-
name: string;
|
|
125
|
-
handle(message: any): Promise<any>;
|
|
126
|
-
}
|
|
127
160
|
interface EnginePluginLoadOptions {
|
|
128
161
|
plugins?: EnginePlugin[];
|
|
129
162
|
dirs?: string[];
|
|
@@ -241,7 +274,6 @@ interface PlanModeService {
|
|
|
241
274
|
getModePolicy(mode?: PlanMode): ModePolicy;
|
|
242
275
|
getToolMetadata(toolNames: string[]): ToolMeta[];
|
|
243
276
|
buildPromptAppend(toolNames: string[], transition?: PlanModeTransitionResult): string;
|
|
244
|
-
applyHooks(baseHooks?: ToolHooks): ToolHooks;
|
|
245
277
|
getEvents(limit?: number): PlanModeEvent[];
|
|
246
278
|
}
|
|
247
279
|
type LoggerLike = EnginePluginContext['logger'];
|
|
@@ -258,9 +290,8 @@ declare class BuiltInPlanModeService implements PlanModeService {
|
|
|
258
290
|
getModePolicy(mode?: PlanMode): ModePolicy;
|
|
259
291
|
getToolMetadata(toolNames: string[]): ToolMeta[];
|
|
260
292
|
buildPromptAppend(toolNames: string[], transition?: PlanModeTransitionResult): string;
|
|
261
|
-
applyHooks(baseHooks?: ToolHooks): ToolHooks;
|
|
262
293
|
getEvents(limit?: number): PlanModeEvent[];
|
|
263
|
-
|
|
294
|
+
observePotentialPolicyViolation(toolName: string, input: unknown): void;
|
|
264
295
|
private inferToolMeta;
|
|
265
296
|
private getLatestUserText;
|
|
266
297
|
private messageContentToText;
|
|
@@ -274,4 +305,4 @@ declare const builtInPlanModePlugin: EnginePlugin;
|
|
|
274
305
|
*/
|
|
275
306
|
declare const builtInPlugins: (EnginePlugin | SubAgentPlugin)[];
|
|
276
307
|
|
|
277
|
-
export {
|
|
308
|
+
export { type AfterLLMCallInput as A, type BeforeLLMCallInput as B, type ClarificationRequest as C, builtInPlanModePlugin as D, type EngineHookMap as E, builtInPlugins as F, builtInSkillsPlugin as G, SubAgentPlugin as H, type ILogger as I, type LLMProviderFactory as L, type ModePolicy as M, type PlanMode as P, type SystemPromptOption as S, type Tool as T, type Context as a, type ToolExecutionContext as b, type EnginePluginLoadOptions as c, type ToolHooks as d, type EngineHookName as e, type AfterRunInput as f, type AfterToolCallInput as g, type AfterToolCallResult as h, type BeforeLLMCallResult as i, type BeforeRunInput as j, type BeforeRunResult as k, type BeforeToolCallInput as l, type BeforeToolCallResult as m, BuiltInPlanModeService as n, BuiltInSkillRegistry as o, type EnginePlugin as p, type EnginePluginContext as q, type PlanIntentLabel as r, type PlanModeEvent as s, type PlanModeEventName as t, type PlanModeService as u, type PlanModeTransitionResult as v, type ToolCategory as w, type ToolMeta as x, type ToolRisk as y, builtInMCPPlugin as z };
|
package/dist/index.cjs
CHANGED
|
@@ -415,15 +415,28 @@ var maybeCompactContext = async (context, options) => {
|
|
|
415
415
|
};
|
|
416
416
|
|
|
417
417
|
// src/core/loop.ts
|
|
418
|
-
function
|
|
418
|
+
function wrapToolsWithHooks(tools, beforeHooks, afterHooks) {
|
|
419
419
|
const wrapped = {};
|
|
420
420
|
for (const [name, t] of Object.entries(tools)) {
|
|
421
421
|
wrapped[name] = {
|
|
422
422
|
...t,
|
|
423
423
|
execute: async (input, ctx) => {
|
|
424
|
-
|
|
424
|
+
let finalInput = input;
|
|
425
|
+
for (const hook of beforeHooks) {
|
|
426
|
+
const result = await hook({ name, input: finalInput });
|
|
427
|
+
if (result && "input" in result) {
|
|
428
|
+
finalInput = result.input;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
425
431
|
const output = await t.execute(finalInput, ctx);
|
|
426
|
-
|
|
432
|
+
let finalOutput = output;
|
|
433
|
+
for (const hook of afterHooks) {
|
|
434
|
+
const result = await hook({ name, input: finalInput, output: finalOutput });
|
|
435
|
+
if (result && "output" in result) {
|
|
436
|
+
finalOutput = result.output;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
return finalOutput;
|
|
427
440
|
}
|
|
428
441
|
};
|
|
429
442
|
}
|
|
@@ -433,6 +446,7 @@ async function loop(context, options) {
|
|
|
433
446
|
let errorCount = 0;
|
|
434
447
|
let totalSteps = 0;
|
|
435
448
|
let compactionAttempts = 0;
|
|
449
|
+
const loopHooks = options?.hooks ?? {};
|
|
436
450
|
while (true) {
|
|
437
451
|
try {
|
|
438
452
|
if (compactionAttempts < MAX_COMPACTION_ATTEMPTS) {
|
|
@@ -449,8 +463,24 @@ async function loop(context, options) {
|
|
|
449
463
|
}
|
|
450
464
|
}
|
|
451
465
|
let tools = options?.tools || {};
|
|
452
|
-
|
|
453
|
-
|
|
466
|
+
let systemPrompt = options?.systemPrompt;
|
|
467
|
+
if (loopHooks.beforeLLMCall?.length) {
|
|
468
|
+
for (const hook of loopHooks.beforeLLMCall) {
|
|
469
|
+
const result2 = await hook({ context, systemPrompt, tools });
|
|
470
|
+
if (result2) {
|
|
471
|
+
if ("systemPrompt" in result2 && result2.systemPrompt !== void 0) {
|
|
472
|
+
systemPrompt = result2.systemPrompt;
|
|
473
|
+
}
|
|
474
|
+
if ("tools" in result2 && result2.tools !== void 0) {
|
|
475
|
+
tools = result2.tools;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
const beforeToolHooks = loopHooks.beforeToolCall ?? [];
|
|
481
|
+
const afterToolHooks = loopHooks.afterToolCall ?? [];
|
|
482
|
+
if (beforeToolHooks.length || afterToolHooks.length) {
|
|
483
|
+
tools = wrapToolsWithHooks(tools, beforeToolHooks, afterToolHooks);
|
|
454
484
|
}
|
|
455
485
|
const toolExecutionContext = {
|
|
456
486
|
onClarificationRequest: options?.onClarificationRequest,
|
|
@@ -461,7 +491,7 @@ async function loop(context, options) {
|
|
|
461
491
|
toolExecutionContext,
|
|
462
492
|
provider: options?.provider,
|
|
463
493
|
model: options?.model,
|
|
464
|
-
systemPrompt
|
|
494
|
+
systemPrompt,
|
|
465
495
|
onStepFinish: (step) => {
|
|
466
496
|
options?.onStepFinish?.(step);
|
|
467
497
|
},
|
|
@@ -489,6 +519,11 @@ async function loop(context, options) {
|
|
|
489
519
|
options?.onResponse?.(messages);
|
|
490
520
|
}
|
|
491
521
|
}
|
|
522
|
+
if (loopHooks.afterLLMCall?.length) {
|
|
523
|
+
for (const hook of loopHooks.afterLLMCall) {
|
|
524
|
+
await hook({ context, finishReason, text });
|
|
525
|
+
}
|
|
526
|
+
}
|
|
492
527
|
if (finishReason === "stop") {
|
|
493
528
|
return text || "Task completed.";
|
|
494
529
|
}
|
|
@@ -1066,9 +1101,15 @@ var PluginManager = class {
|
|
|
1066
1101
|
enginePlugins = /* @__PURE__ */ new Map();
|
|
1067
1102
|
userConfigPlugins = [];
|
|
1068
1103
|
tools = /* @__PURE__ */ new Map();
|
|
1069
|
-
|
|
1104
|
+
hooks = {
|
|
1105
|
+
beforeRun: [],
|
|
1106
|
+
afterRun: [],
|
|
1107
|
+
beforeLLMCall: [],
|
|
1108
|
+
afterLLMCall: [],
|
|
1109
|
+
beforeToolCall: [],
|
|
1110
|
+
afterToolCall: []
|
|
1111
|
+
};
|
|
1070
1112
|
services = /* @__PURE__ */ new Map();
|
|
1071
|
-
protocols = /* @__PURE__ */ new Map();
|
|
1072
1113
|
config = /* @__PURE__ */ new Map();
|
|
1073
1114
|
events = new import_events.EventEmitter();
|
|
1074
1115
|
logger;
|
|
@@ -1177,14 +1218,10 @@ var PluginManager = class {
|
|
|
1177
1218
|
},
|
|
1178
1219
|
getTool: (name) => this.tools.get(name),
|
|
1179
1220
|
getTools: () => Object.fromEntries(this.tools),
|
|
1180
|
-
|
|
1181
|
-
this.
|
|
1182
|
-
|
|
1183
|
-
getRunHook: (name) => this.runHooks.get(name),
|
|
1184
|
-
registerProtocol: (name, handler) => {
|
|
1185
|
-
this.protocols.set(name, handler);
|
|
1221
|
+
registerHook: (hookName, handler) => {
|
|
1222
|
+
this.hooks[hookName].push(handler);
|
|
1223
|
+
this.logger.debug(`Plugin "${plugin.name}" registered hook: ${hookName}`);
|
|
1186
1224
|
},
|
|
1187
|
-
getProtocol: (name) => this.protocols.get(name),
|
|
1188
1225
|
registerService: (name, service) => {
|
|
1189
1226
|
this.services.set(name, service);
|
|
1190
1227
|
},
|
|
@@ -1380,10 +1417,10 @@ var PluginManager = class {
|
|
|
1380
1417
|
return Object.fromEntries(this.tools);
|
|
1381
1418
|
}
|
|
1382
1419
|
/**
|
|
1383
|
-
*
|
|
1420
|
+
* 获取指定类型的 hook 处理函数数组
|
|
1384
1421
|
*/
|
|
1385
|
-
|
|
1386
|
-
return
|
|
1422
|
+
getHooks(hookName) {
|
|
1423
|
+
return [...this.hooks[hookName]];
|
|
1387
1424
|
}
|
|
1388
1425
|
/**
|
|
1389
1426
|
* 服务获取
|
|
@@ -1391,12 +1428,6 @@ var PluginManager = class {
|
|
|
1391
1428
|
getService(name) {
|
|
1392
1429
|
return this.services.get(name);
|
|
1393
1430
|
}
|
|
1394
|
-
/**
|
|
1395
|
-
* 协议获取
|
|
1396
|
-
*/
|
|
1397
|
-
getProtocol(name) {
|
|
1398
|
-
return this.protocols.get(name);
|
|
1399
|
-
}
|
|
1400
1431
|
/**
|
|
1401
1432
|
* 获取插件状态
|
|
1402
1433
|
*/
|
|
@@ -1405,9 +1436,10 @@ var PluginManager = class {
|
|
|
1405
1436
|
enginePlugins: Array.from(this.enginePlugins.keys()),
|
|
1406
1437
|
userConfigPlugins: this.userConfigPlugins.map((c) => c.name || "unnamed"),
|
|
1407
1438
|
tools: Array.from(this.tools.keys()),
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1439
|
+
hooks: Object.fromEntries(
|
|
1440
|
+
Object.entries(this.hooks).map(([k, v]) => [k, v.length])
|
|
1441
|
+
),
|
|
1442
|
+
services: Array.from(this.services.keys())
|
|
1411
1443
|
};
|
|
1412
1444
|
}
|
|
1413
1445
|
/**
|
|
@@ -1884,25 +1916,6 @@ var BuiltInPlanModeService = class {
|
|
|
1884
1916
|
}
|
|
1885
1917
|
return lines.join("\n");
|
|
1886
1918
|
}
|
|
1887
|
-
applyHooks(baseHooks) {
|
|
1888
|
-
return {
|
|
1889
|
-
onBeforeToolCall: async (name, input) => {
|
|
1890
|
-
this.observePotentialPolicyViolation(name, input);
|
|
1891
|
-
if (baseHooks?.onBeforeToolCall) {
|
|
1892
|
-
const nextInput = await baseHooks.onBeforeToolCall(name, input);
|
|
1893
|
-
return nextInput ?? input;
|
|
1894
|
-
}
|
|
1895
|
-
return input;
|
|
1896
|
-
},
|
|
1897
|
-
onAfterToolCall: async (name, input, output) => {
|
|
1898
|
-
if (baseHooks?.onAfterToolCall) {
|
|
1899
|
-
const nextOutput = await baseHooks.onAfterToolCall(name, input, output);
|
|
1900
|
-
return nextOutput ?? output;
|
|
1901
|
-
}
|
|
1902
|
-
return output;
|
|
1903
|
-
}
|
|
1904
|
-
};
|
|
1905
|
-
}
|
|
1906
1919
|
getEvents(limit = 50) {
|
|
1907
1920
|
return this.events.slice(-Math.max(0, limit));
|
|
1908
1921
|
}
|
|
@@ -2039,21 +2052,18 @@ var builtInPlanModePlugin = {
|
|
|
2039
2052
|
version: "1.0.0",
|
|
2040
2053
|
async initialize(context) {
|
|
2041
2054
|
const service = new BuiltInPlanModeService(context.logger, context.events, "executing");
|
|
2042
|
-
context.
|
|
2055
|
+
context.registerHook("beforeLLMCall", ({ context: runContext, tools, systemPrompt }) => {
|
|
2043
2056
|
const mode = service.getMode();
|
|
2044
2057
|
if (mode === "executing") {
|
|
2045
|
-
return
|
|
2046
|
-
systemPrompt,
|
|
2047
|
-
hooks
|
|
2048
|
-
};
|
|
2058
|
+
return;
|
|
2049
2059
|
}
|
|
2050
2060
|
const transition = service.processContextMessages(runContext.messages);
|
|
2051
2061
|
const append = service.buildPromptAppend(Object.keys(tools), transition);
|
|
2052
2062
|
const finalSystemPrompt = appendSystemPrompt(systemPrompt, append);
|
|
2053
|
-
return {
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2063
|
+
return { systemPrompt: finalSystemPrompt };
|
|
2064
|
+
});
|
|
2065
|
+
context.registerHook("beforeToolCall", ({ name, input }) => {
|
|
2066
|
+
service.observePotentialPolicyViolation(name, input);
|
|
2057
2067
|
});
|
|
2058
2068
|
context.registerService("planMode", service);
|
|
2059
2069
|
context.registerService("planModeService", service);
|
|
@@ -2264,52 +2274,70 @@ var Engine = class {
|
|
|
2264
2274
|
// 默认启用扫描
|
|
2265
2275
|
};
|
|
2266
2276
|
}
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
+
/**
|
|
2278
|
+
* Collect all hooks for a given loop invocation.
|
|
2279
|
+
* Merges plugin hooks with the legacy EngineOptions.hooks (ToolHooks).
|
|
2280
|
+
*/
|
|
2281
|
+
collectLoopHooks() {
|
|
2282
|
+
const loopHooks = {
|
|
2283
|
+
beforeLLMCall: this.pluginManager.getHooks("beforeLLMCall"),
|
|
2284
|
+
afterLLMCall: this.pluginManager.getHooks("afterLLMCall"),
|
|
2285
|
+
beforeToolCall: [...this.pluginManager.getHooks("beforeToolCall")],
|
|
2286
|
+
afterToolCall: [...this.pluginManager.getHooks("afterToolCall")]
|
|
2287
|
+
};
|
|
2288
|
+
const legacyHooks = this.options.hooks;
|
|
2289
|
+
if (legacyHooks?.onBeforeToolCall) {
|
|
2290
|
+
const legacyBefore = legacyHooks.onBeforeToolCall;
|
|
2291
|
+
loopHooks.beforeToolCall.push(async ({ name, input }) => {
|
|
2292
|
+
const modified = await legacyBefore(name, input);
|
|
2293
|
+
return modified !== void 0 ? { input: modified } : void 0;
|
|
2277
2294
|
});
|
|
2278
|
-
if (!result) {
|
|
2279
|
-
continue;
|
|
2280
|
-
}
|
|
2281
|
-
if ("systemPrompt" in result) {
|
|
2282
|
-
nextSystemPrompt = result.systemPrompt;
|
|
2283
|
-
}
|
|
2284
|
-
if ("hooks" in result) {
|
|
2285
|
-
nextHooks = result.hooks;
|
|
2286
|
-
}
|
|
2287
2295
|
}
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2296
|
+
if (legacyHooks?.onAfterToolCall) {
|
|
2297
|
+
const legacyAfter = legacyHooks.onAfterToolCall;
|
|
2298
|
+
loopHooks.afterToolCall.push(async ({ name, input, output }) => {
|
|
2299
|
+
const modified = await legacyAfter(name, input, output);
|
|
2300
|
+
return modified !== void 0 ? { output: modified } : void 0;
|
|
2301
|
+
});
|
|
2302
|
+
}
|
|
2303
|
+
return loopHooks;
|
|
2292
2304
|
}
|
|
2293
2305
|
/**
|
|
2294
2306
|
* 运行AI循环
|
|
2295
2307
|
*/
|
|
2296
2308
|
async run(context, options) {
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
const
|
|
2300
|
-
|
|
2309
|
+
let systemPrompt = options?.systemPrompt ?? this.options.systemPrompt;
|
|
2310
|
+
let tools = { ...this.tools };
|
|
2311
|
+
const beforeRunHooks = this.pluginManager.getHooks("beforeRun");
|
|
2312
|
+
for (const hook of beforeRunHooks) {
|
|
2313
|
+
const result = await hook({ context, systemPrompt, tools });
|
|
2314
|
+
if (result) {
|
|
2315
|
+
if ("systemPrompt" in result && result.systemPrompt !== void 0) {
|
|
2316
|
+
systemPrompt = result.systemPrompt;
|
|
2317
|
+
}
|
|
2318
|
+
if ("tools" in result && result.tools !== void 0) {
|
|
2319
|
+
tools = result.tools;
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
const loopHooks = this.collectLoopHooks();
|
|
2324
|
+
const resultText = await loop(context, {
|
|
2301
2325
|
...options,
|
|
2302
|
-
tools
|
|
2303
|
-
// Engine 级别选项作为默认值;调用方通过 options 传入可在单次调用中覆盖
|
|
2326
|
+
tools,
|
|
2304
2327
|
provider: options?.provider ?? this.options.llmProvider,
|
|
2305
2328
|
model: options?.model ?? this.options.model,
|
|
2306
2329
|
systemPrompt,
|
|
2307
|
-
hooks,
|
|
2330
|
+
hooks: loopHooks,
|
|
2308
2331
|
onToolCall: (toolCall) => {
|
|
2309
2332
|
options?.onToolCall?.(toolCall);
|
|
2310
2333
|
},
|
|
2311
2334
|
onClarificationRequest: options?.onClarificationRequest
|
|
2312
2335
|
});
|
|
2336
|
+
const afterRunHooks = this.pluginManager.getHooks("afterRun");
|
|
2337
|
+
for (const hook of afterRunHooks) {
|
|
2338
|
+
await hook({ context, result: resultText });
|
|
2339
|
+
}
|
|
2340
|
+
return resultText;
|
|
2313
2341
|
}
|
|
2314
2342
|
/**
|
|
2315
2343
|
* 获取插件状态
|