@synergenius/flow-weaver 0.24.2 → 0.24.4
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/agent-loop.js +28 -0
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/types.d.ts +27 -0
- package/dist/cli/flow-weaver.mjs +18 -5
- package/dist/generated-version.d.ts +1 -1
- package/dist/generated-version.js +1 -1
- package/dist/parser.js +19 -5
- package/package.json +1 -1
package/dist/agent/agent-loop.js
CHANGED
|
@@ -79,6 +79,17 @@ export async function runAgentLoop(provider, tools, executor, messages, options)
|
|
|
79
79
|
}
|
|
80
80
|
// If no tool calls, we're done
|
|
81
81
|
if (finishReason !== 'tool_calls' || collectedToolCalls.length === 0) {
|
|
82
|
+
// Final turn hook
|
|
83
|
+
if (options?.onTurnEnd) {
|
|
84
|
+
await options.onTurnEnd({
|
|
85
|
+
iteration,
|
|
86
|
+
maxIterations,
|
|
87
|
+
messages: conversation,
|
|
88
|
+
toolCallCount,
|
|
89
|
+
usage: { promptTokens: totalPromptTokens, completionTokens: totalCompletionTokens },
|
|
90
|
+
isFinalTurn: true,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
82
93
|
return buildResult(finishReason !== 'error', text || 'Task completed', conversation, toolCallCount, totalPromptTokens, totalCompletionTokens);
|
|
83
94
|
}
|
|
84
95
|
// Execute tool calls and add results to conversation
|
|
@@ -106,6 +117,23 @@ export async function runAgentLoop(provider, tools, executor, messages, options)
|
|
|
106
117
|
toolCallId: tc.id,
|
|
107
118
|
});
|
|
108
119
|
}
|
|
120
|
+
// Between-turns hook — runs after tool execution, before next LLM call
|
|
121
|
+
if (options?.onTurnEnd) {
|
|
122
|
+
const turnResult = await options.onTurnEnd({
|
|
123
|
+
iteration,
|
|
124
|
+
maxIterations,
|
|
125
|
+
messages: conversation,
|
|
126
|
+
toolCallCount,
|
|
127
|
+
usage: { promptTokens: totalPromptTokens, completionTokens: totalCompletionTokens },
|
|
128
|
+
isFinalTurn: false,
|
|
129
|
+
});
|
|
130
|
+
if (turnResult?.continue === false) {
|
|
131
|
+
return buildResult(true, turnResult.injectMessage ?? 'Stopped by hook', conversation, toolCallCount, totalPromptTokens, totalCompletionTokens);
|
|
132
|
+
}
|
|
133
|
+
if (turnResult?.injectMessage) {
|
|
134
|
+
conversation.push({ role: 'user', content: turnResult.injectMessage });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
109
137
|
}
|
|
110
138
|
return buildResult(false, `Reached max iterations (${maxIterations})`, conversation, toolCallCount, totalPromptTokens, totalCompletionTokens);
|
|
111
139
|
}
|
package/dist/agent/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Provider-agnostic agent loop with MCP bridge for tool execution.
|
|
5
5
|
* Built-in providers: Anthropic API, Claude CLI, OpenAI-compatible (GPT-4o, Groq, Ollama, etc).
|
|
6
6
|
*/
|
|
7
|
-
export type { SplitPrompt, StreamEvent, AgentMessage, AgentProvider, ToolDefinition, ToolExecutor, ToolEvent, McpBridge, AgentLoopOptions, AgentLoopResult, StreamOptions, SpawnFn, ClaudeCliProviderOptions, CliSessionOptions, Logger, } from './types.js';
|
|
7
|
+
export type { SplitPrompt, TurnEndContext, TurnEndResult, StreamEvent, AgentMessage, AgentProvider, ToolDefinition, ToolExecutor, ToolEvent, McpBridge, AgentLoopOptions, AgentLoopResult, StreamOptions, SpawnFn, ClaudeCliProviderOptions, CliSessionOptions, Logger, } from './types.js';
|
|
8
8
|
export { joinSplitPrompt } from './types.js';
|
|
9
9
|
export { runAgentLoop } from './agent-loop.js';
|
|
10
10
|
export { AnthropicProvider, createAnthropicProvider } from './providers/anthropic.js';
|
package/dist/agent/types.d.ts
CHANGED
|
@@ -105,6 +105,31 @@ export interface McpBridge {
|
|
|
105
105
|
/** Tear down the socket server and remove temp files */
|
|
106
106
|
cleanup: () => void;
|
|
107
107
|
}
|
|
108
|
+
/** Context passed to the onTurnEnd callback after each agent loop iteration. */
|
|
109
|
+
export interface TurnEndContext {
|
|
110
|
+
/** Current iteration number (0-based). */
|
|
111
|
+
iteration: number;
|
|
112
|
+
/** Maximum iterations configured. */
|
|
113
|
+
maxIterations: number;
|
|
114
|
+
/** Full conversation history up to this point. */
|
|
115
|
+
messages: ReadonlyArray<AgentMessage>;
|
|
116
|
+
/** Total tool calls executed so far. */
|
|
117
|
+
toolCallCount: number;
|
|
118
|
+
/** Cumulative token usage. */
|
|
119
|
+
usage: {
|
|
120
|
+
promptTokens: number;
|
|
121
|
+
completionTokens: number;
|
|
122
|
+
};
|
|
123
|
+
/** true if the model stopped calling tools (final turn). */
|
|
124
|
+
isFinalTurn: boolean;
|
|
125
|
+
}
|
|
126
|
+
/** Result from the onTurnEnd callback. */
|
|
127
|
+
export interface TurnEndResult {
|
|
128
|
+
/** If false, abort the agent loop early. */
|
|
129
|
+
continue?: boolean;
|
|
130
|
+
/** Optional message to inject into the conversation (steering nudge). */
|
|
131
|
+
injectMessage?: string;
|
|
132
|
+
}
|
|
108
133
|
export interface AgentLoopOptions {
|
|
109
134
|
systemPrompt?: SplitPrompt;
|
|
110
135
|
maxIterations?: number;
|
|
@@ -113,6 +138,8 @@ export interface AgentLoopOptions {
|
|
|
113
138
|
signal?: AbortSignal;
|
|
114
139
|
onToolEvent?: (event: ToolEvent) => void;
|
|
115
140
|
onStreamEvent?: (event: StreamEvent) => void;
|
|
141
|
+
/** Called after each agent loop iteration (between turns and on final turn). */
|
|
142
|
+
onTurnEnd?: (context: TurnEndContext) => Promise<TurnEndResult | void>;
|
|
116
143
|
logger?: Logger;
|
|
117
144
|
}
|
|
118
145
|
export interface AgentLoopResult {
|
package/dist/cli/flow-weaver.mjs
CHANGED
|
@@ -9886,7 +9886,7 @@ var VERSION;
|
|
|
9886
9886
|
var init_generated_version = __esm({
|
|
9887
9887
|
"src/generated-version.ts"() {
|
|
9888
9888
|
"use strict";
|
|
9889
|
-
VERSION = "0.24.
|
|
9889
|
+
VERSION = "0.24.4";
|
|
9890
9890
|
}
|
|
9891
9891
|
});
|
|
9892
9892
|
|
|
@@ -36231,9 +36231,22 @@ var init_parser2 = __esm({
|
|
|
36231
36231
|
const cacheKey = `npm:${imp.importSource}`;
|
|
36232
36232
|
if (this.importCache.has(cacheKey)) {
|
|
36233
36233
|
const cached2 = this.importCache.get(cacheKey);
|
|
36234
|
-
const
|
|
36235
|
-
|
|
36236
|
-
|
|
36234
|
+
const resolvedDts = resolvePackageTypesPath(imp.importSource, currentDir);
|
|
36235
|
+
let cacheValid = false;
|
|
36236
|
+
if (resolvedDts) {
|
|
36237
|
+
try {
|
|
36238
|
+
const dtsStats = fs5.statSync(resolvedDts);
|
|
36239
|
+
cacheValid = cached2.mtime === dtsStats.mtimeMs;
|
|
36240
|
+
} catch {
|
|
36241
|
+
}
|
|
36242
|
+
} else {
|
|
36243
|
+
cacheValid = true;
|
|
36244
|
+
}
|
|
36245
|
+
if (cacheValid) {
|
|
36246
|
+
const found = cached2.nodeTypes.find((nt) => nt.functionName === imp.functionName);
|
|
36247
|
+
if (found) {
|
|
36248
|
+
return { ...found, name: imp.name, importSource: imp.importSource };
|
|
36249
|
+
}
|
|
36237
36250
|
}
|
|
36238
36251
|
}
|
|
36239
36252
|
const dtsPath = resolvePackageTypesPath(imp.importSource, currentDir);
|
|
@@ -95960,7 +95973,7 @@ function parseIntStrict(value) {
|
|
|
95960
95973
|
// src/cli/index.ts
|
|
95961
95974
|
init_logger();
|
|
95962
95975
|
init_error_utils();
|
|
95963
|
-
var version2 = true ? "0.24.
|
|
95976
|
+
var version2 = true ? "0.24.4" : "0.0.0-dev";
|
|
95964
95977
|
var program2 = new Command();
|
|
95965
95978
|
program2.name("fw").description("Flow Weaver Annotations - Compile and validate workflow files").option("-v, --version", "Output the current version").option("--no-color", "Disable colors").option("--color", "Force colors").on("option:version", () => {
|
|
95966
95979
|
logger.banner(version2);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.24.
|
|
1
|
+
export declare const VERSION = "0.24.4";
|
|
2
2
|
//# sourceMappingURL=generated-version.d.ts.map
|
package/dist/parser.js
CHANGED
|
@@ -610,14 +610,28 @@ export class AnnotationParser {
|
|
|
610
610
|
* Resolve an npm package @fwImport to a node type by reading .d.ts declarations.
|
|
611
611
|
*/
|
|
612
612
|
resolveNpmImportAnnotation(imp, currentDir) {
|
|
613
|
-
// Check cache
|
|
613
|
+
// Check cache (with mtime validation — same pattern as resolveNpmImports)
|
|
614
614
|
const cacheKey = `npm:${imp.importSource}`;
|
|
615
615
|
if (this.importCache.has(cacheKey)) {
|
|
616
616
|
const cached = this.importCache.get(cacheKey);
|
|
617
|
-
const
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
617
|
+
const resolvedDts = resolvePackageTypesPath(imp.importSource, currentDir);
|
|
618
|
+
let cacheValid = false;
|
|
619
|
+
if (resolvedDts) {
|
|
620
|
+
try {
|
|
621
|
+
const dtsStats = fs.statSync(resolvedDts);
|
|
622
|
+
cacheValid = cached.mtime === dtsStats.mtimeMs;
|
|
623
|
+
}
|
|
624
|
+
catch { /* file gone — re-parse */ }
|
|
625
|
+
}
|
|
626
|
+
else {
|
|
627
|
+
// No .d.ts found — trust cache (package may have been removed)
|
|
628
|
+
cacheValid = true;
|
|
629
|
+
}
|
|
630
|
+
if (cacheValid) {
|
|
631
|
+
const found = cached.nodeTypes.find((nt) => nt.functionName === imp.functionName);
|
|
632
|
+
if (found) {
|
|
633
|
+
return { ...found, name: imp.name, importSource: imp.importSource };
|
|
634
|
+
}
|
|
621
635
|
}
|
|
622
636
|
}
|
|
623
637
|
// Resolve .d.ts path
|
package/package.json
CHANGED