@vauban-org/agent-sdk 1.6.4 → 1.7.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.
- package/dist/orchestration/ooda/index.d.ts +1 -1
- package/dist/orchestration/ooda/index.d.ts.map +1 -1
- package/dist/orchestration/ooda/index.js.map +1 -1
- package/dist/orchestration/ooda/react-loop.d.ts +46 -0
- package/dist/orchestration/ooda/react-loop.d.ts.map +1 -1
- package/dist/orchestration/ooda/react-loop.js +69 -5
- package/dist/orchestration/ooda/react-loop.js.map +1 -1
- package/package.json +1 -1
- package/src/orchestration/ooda/index.ts +3 -1
- package/src/orchestration/ooda/react-loop.ts +153 -8
|
@@ -32,7 +32,7 @@ export { alwaysOn } from "./guards/always-on.js";
|
|
|
32
32
|
export type { ImageMediaType, AudioMediaType, MultiModalObservation, AnthropicTextBlock, AnthropicImageBlock, AnthropicDocumentBlock, AnthropicContentBlock, } from "./multimodal.js";
|
|
33
33
|
export { isMultiModal, multiModalToAnthropicContent } from "./multimodal.js";
|
|
34
34
|
export type { ChildAgentPort, ChildAgentOptions, ChildAgentResult, } from "./child-agent.js";
|
|
35
|
-
export type { ToolCall, ReactStep, ReactResult, LLMCompletionFn, ReactMessage, LLMReactResponse, ReactLoopOptions, } from "./react-loop.js";
|
|
35
|
+
export type { ToolCall, ReactStep, ReactResult, LLMCompletionFn, ReactMessage, LLMReactResponse, ReactLoopOptions, ReactStepMeta, ReactLoopLogger, } from "./react-loop.js";
|
|
36
36
|
export { reactLoop } from "./react-loop.js";
|
|
37
37
|
export type { PlanStep, Plan, StepResult, PlanExecutionResult, } from "./plan-execute.js";
|
|
38
38
|
export { decomposeTask, executeStep } from "./plan-execute.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/orchestration/ooda/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EACV,aAAa,EACb,aAAa,EACb,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,aAAa,EACb,cAAc,EACd,eAAe,EACf,SAAS,EACT,WAAW,EACX,UAAU,EACV,cAAc,EACd,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAErD,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG/C,YAAY,EACV,eAAe,EACf,UAAU,EACV,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,4BAA4B,EAC5B,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAGnE,OAAO,EACL,aAAa,EACb,eAAe,EACf,YAAY,GACb,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAEpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,YAAY,EACV,eAAe,EACf,YAAY,EACZ,eAAe,EACf,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGnD,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,mCAAmC,CAAC;AAC3C,YAAY,EACV,uBAAuB,EACvB,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,YAAY,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGjD,YAAY,EACV,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,YAAY,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AAG7E,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EACV,QAAQ,EACR,SAAS,EACT,WAAW,EACX,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/orchestration/ooda/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/orchestration/ooda/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkBH,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAGrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAU/C,OAAO,EACL,4BAA4B,EAC5B,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,wFAAwF;AACxF,OAAO,EACL,aAAa,EACb,eAAe,EACf,YAAY,GACb,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAQrD,OAAO,EACL,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGpD,yEAAyE;AACzE,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,mCAAmC,CAAC;AAO3C,2DAA2D;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE3D,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAYjD,OAAO,EAAE,YAAY,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/orchestration/ooda/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkBH,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAGrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAU/C,OAAO,EACL,4BAA4B,EAC5B,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,wFAAwF;AACxF,OAAO,EACL,aAAa,EACb,eAAe,EACf,YAAY,GACb,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAQrD,OAAO,EACL,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGpD,yEAAyE;AACzE,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,mCAAmC,CAAC;AAO3C,2DAA2D;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE3D,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAYjD,OAAO,EAAE,YAAY,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AAqB7E,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAS5C,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAI/D,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAStE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAOxC,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtE,2CAA2C;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAItD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -67,6 +67,29 @@ export interface LLMReactResponse {
|
|
|
67
67
|
/** Whether this is a final answer (no tool calls). */
|
|
68
68
|
isFinal: boolean;
|
|
69
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Per-iteration telemetry callback metadata.
|
|
72
|
+
*
|
|
73
|
+
* @since 1.7.0
|
|
74
|
+
* @public
|
|
75
|
+
*/
|
|
76
|
+
export interface ReactStepMeta {
|
|
77
|
+
/** Iteration index (mirrors `step.index`). */
|
|
78
|
+
iteration: number;
|
|
79
|
+
/** Wall-clock duration of the iteration in milliseconds. */
|
|
80
|
+
durationMs: number;
|
|
81
|
+
/** Caller-supplied correlation id from `ReactLoopOptions.loopId`. */
|
|
82
|
+
loopId?: string;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Minimal logger contract for swallowed onStep errors.
|
|
86
|
+
*
|
|
87
|
+
* @since 1.7.0
|
|
88
|
+
* @public
|
|
89
|
+
*/
|
|
90
|
+
export interface ReactLoopLogger {
|
|
91
|
+
warn: (msg: string, meta?: Record<string, unknown>) => void;
|
|
92
|
+
}
|
|
70
93
|
export interface ReactLoopOptions {
|
|
71
94
|
/** Max steps before forced stop (default: 10). */
|
|
72
95
|
maxSteps?: number;
|
|
@@ -84,6 +107,29 @@ export interface ReactLoopOptions {
|
|
|
84
107
|
maxToolCallSize?: number;
|
|
85
108
|
/** Allowed tool names. Unlisted tools get an error feedback. */
|
|
86
109
|
allowedTools?: string[];
|
|
110
|
+
/**
|
|
111
|
+
* Called after each iteration with the completed step + timing.
|
|
112
|
+
* Fire-and-forget — errors caught + logged via opts.logger, never
|
|
113
|
+
* propagate to the loop. Use this to emit ctx.insertStep telemetry.
|
|
114
|
+
*
|
|
115
|
+
* @since 1.7.0
|
|
116
|
+
*/
|
|
117
|
+
onStep?: (step: ReactStep, meta: ReactStepMeta) => void | Promise<void>;
|
|
118
|
+
/**
|
|
119
|
+
* Optional correlation id propagated into `meta.loopId` of every
|
|
120
|
+
* `onStep` call, so callers can correlate multiple reactLoops within
|
|
121
|
+
* one OODA cycle.
|
|
122
|
+
*
|
|
123
|
+
* @since 1.7.0
|
|
124
|
+
*/
|
|
125
|
+
loopId?: string;
|
|
126
|
+
/**
|
|
127
|
+
* Logger used when `onStep` throws / rejects. Defaults to no-op
|
|
128
|
+
* (errors are silently swallowed).
|
|
129
|
+
*
|
|
130
|
+
* @since 1.7.0
|
|
131
|
+
*/
|
|
132
|
+
logger?: ReactLoopLogger;
|
|
87
133
|
}
|
|
88
134
|
/**
|
|
89
135
|
* Run a ReAct (Reasoning + Acting) loop.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-loop.d.ts","sourceRoot":"","sources":["../../../src/orchestration/ooda/react-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,MAAM,WAAW,QAAQ;IACvB,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,SAAS;IACxB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,CAC5B,QAAQ,EAAE,YAAY,EAAE,KACrB,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAE/B,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,sDAAsD;IACtD,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iCAAiC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,GAAG,EAAE,eAAe,CAAC;IACrB,iDAAiD;IACjD,WAAW,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACjD,oCAAoC;IACpC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,0DAA0D;IAC1D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"react-loop.d.ts","sourceRoot":"","sources":["../../../src/orchestration/ooda/react-loop.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,6 +18,29 @@
|
|
|
18
18
|
// ─── Constants ──────────────────────────────────────────────────────────────────
|
|
19
19
|
const DEFAULT_MAX_STEPS = 10;
|
|
20
20
|
const DEFAULT_MAX_TOOL_CALL_SIZE = 10_240; // 10KB
|
|
21
|
+
// ─── Helpers ────────────────────────────────────────────────────────────────────
|
|
22
|
+
/**
|
|
23
|
+
* Invoke the user-supplied `onStep` callback with try/catch. Errors are
|
|
24
|
+
* logged via `opts.logger?.warn` and never propagate to the caller.
|
|
25
|
+
*
|
|
26
|
+
* Handles both sync void and async returns.
|
|
27
|
+
*/
|
|
28
|
+
async function safeOnStep(cb, step, meta, logger) {
|
|
29
|
+
try {
|
|
30
|
+
const ret = cb(step, meta);
|
|
31
|
+
if (ret && typeof ret.then === "function") {
|
|
32
|
+
await ret;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
37
|
+
logger?.warn?.("reactLoop.onStep threw — error swallowed", {
|
|
38
|
+
iteration: meta.iteration,
|
|
39
|
+
loopId: meta.loopId,
|
|
40
|
+
error: message,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
21
44
|
// ─── Loop ───────────────────────────────────────────────────────────────────────
|
|
22
45
|
/**
|
|
23
46
|
* Run a ReAct (Reasoning + Acting) loop.
|
|
@@ -35,10 +58,19 @@ export async function reactLoop(opts) {
|
|
|
35
58
|
{ role: "system", content: opts.systemPrompt },
|
|
36
59
|
{ role: "user", content: opts.task },
|
|
37
60
|
];
|
|
61
|
+
const { onStep, loopId, logger } = opts;
|
|
62
|
+
/** Build telemetry meta for iteration `i`, given its start timestamp. */
|
|
63
|
+
const buildMeta = (i, iterationStart) => ({
|
|
64
|
+
iteration: i,
|
|
65
|
+
durationMs: Date.now() - iterationStart,
|
|
66
|
+
loopId,
|
|
67
|
+
});
|
|
38
68
|
for (let i = 0; i < maxSteps; i++) {
|
|
39
69
|
if (opts.signal?.aborted) {
|
|
70
|
+
// Aborted iteration — step is not finalized, onStep is NOT called.
|
|
40
71
|
return { answer: "", steps, totalSteps: i, truncated: true };
|
|
41
72
|
}
|
|
73
|
+
const iterationStart = Date.now();
|
|
42
74
|
// Thought → Action
|
|
43
75
|
const response = await opts.llm(messages);
|
|
44
76
|
steps.push({
|
|
@@ -47,8 +79,18 @@ export async function reactLoop(opts) {
|
|
|
47
79
|
action: response.toolCalls?.[0],
|
|
48
80
|
});
|
|
49
81
|
// Final answer — no tool call
|
|
50
|
-
if (response.isFinal ||
|
|
51
|
-
|
|
82
|
+
if (response.isFinal ||
|
|
83
|
+
!response.toolCalls ||
|
|
84
|
+
response.toolCalls.length === 0) {
|
|
85
|
+
if (onStep) {
|
|
86
|
+
await safeOnStep(onStep, steps[i], buildMeta(i, iterationStart), logger);
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
answer: response.content,
|
|
90
|
+
steps,
|
|
91
|
+
totalSteps: i + 1,
|
|
92
|
+
truncated: false,
|
|
93
|
+
};
|
|
52
94
|
}
|
|
53
95
|
const toolCall = response.toolCalls[0];
|
|
54
96
|
// Validate tool call size
|
|
@@ -56,14 +98,28 @@ export async function reactLoop(opts) {
|
|
|
56
98
|
if (toolJson.length > maxToolCallSize) {
|
|
57
99
|
steps[i].error = `Tool call exceeds ${maxToolCallSize}B limit`;
|
|
58
100
|
steps[i].observation = `Error: tool call too large (${toolJson.length}B > ${maxToolCallSize}B limit)`;
|
|
59
|
-
messages.push({ role: "assistant", content: response.content, name: toolCall.tool }, {
|
|
101
|
+
messages.push({ role: "assistant", content: response.content, name: toolCall.tool }, {
|
|
102
|
+
role: "tool",
|
|
103
|
+
content: steps[i].observation,
|
|
104
|
+
tool_call_id: `call_${i}`,
|
|
105
|
+
});
|
|
106
|
+
if (onStep) {
|
|
107
|
+
await safeOnStep(onStep, steps[i], buildMeta(i, iterationStart), logger);
|
|
108
|
+
}
|
|
60
109
|
continue;
|
|
61
110
|
}
|
|
62
111
|
// Check allowed tools
|
|
63
112
|
if (allowedTools && !allowedTools.includes(toolCall.tool)) {
|
|
64
113
|
steps[i].error = `Tool "${toolCall.tool}" not in allowed list`;
|
|
65
114
|
steps[i].observation = `Error: tool "${toolCall.tool}" is not allowed. Available tools: ${allowedTools.join(", ")}`;
|
|
66
|
-
messages.push({ role: "assistant", content: response.content, name: toolCall.tool }, {
|
|
115
|
+
messages.push({ role: "assistant", content: response.content, name: toolCall.tool }, {
|
|
116
|
+
role: "tool",
|
|
117
|
+
content: steps[i].observation,
|
|
118
|
+
tool_call_id: `call_${i}`,
|
|
119
|
+
});
|
|
120
|
+
if (onStep) {
|
|
121
|
+
await safeOnStep(onStep, steps[i], buildMeta(i, iterationStart), logger);
|
|
122
|
+
}
|
|
67
123
|
continue;
|
|
68
124
|
}
|
|
69
125
|
// Observation — execute tool
|
|
@@ -76,7 +132,15 @@ export async function reactLoop(opts) {
|
|
|
76
132
|
steps[i].observation = `Error executing tool "${toolCall.tool}": ${steps[i].error}`;
|
|
77
133
|
}
|
|
78
134
|
// Feed observation back into the conversation
|
|
79
|
-
messages.push({ role: "assistant", content: response.content, name: toolCall.tool }, {
|
|
135
|
+
messages.push({ role: "assistant", content: response.content, name: toolCall.tool }, {
|
|
136
|
+
role: "tool",
|
|
137
|
+
content: steps[i].observation,
|
|
138
|
+
tool_call_id: `call_${i}`,
|
|
139
|
+
});
|
|
140
|
+
// Step is fully finalized (thought + action + observation/error).
|
|
141
|
+
if (onStep) {
|
|
142
|
+
await safeOnStep(onStep, steps[i], buildMeta(i, iterationStart), logger);
|
|
143
|
+
}
|
|
80
144
|
}
|
|
81
145
|
// Truncated — max steps reached
|
|
82
146
|
const lastStep = steps[steps.length - 1];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-loop.js","sourceRoot":"","sources":["../../../src/orchestration/ooda/react-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;
|
|
1
|
+
{"version":3,"file":"react-loop.js","sourceRoot":"","sources":["../../../src/orchestration/ooda/react-loop.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -114,7 +114,7 @@ export type {
|
|
|
114
114
|
ChildAgentResult,
|
|
115
115
|
} from "./child-agent.js";
|
|
116
116
|
|
|
117
|
-
// ReactLoop — sprint-565:3
|
|
117
|
+
// ReactLoop — sprint-565:3 (+ 1.7.0 onStep telemetry)
|
|
118
118
|
export type {
|
|
119
119
|
ToolCall,
|
|
120
120
|
ReactStep,
|
|
@@ -123,6 +123,8 @@ export type {
|
|
|
123
123
|
ReactMessage,
|
|
124
124
|
LLMReactResponse,
|
|
125
125
|
ReactLoopOptions,
|
|
126
|
+
ReactStepMeta,
|
|
127
|
+
ReactLoopLogger,
|
|
126
128
|
} from "./react-loop.js";
|
|
127
129
|
export { reactLoop } from "./react-loop.js";
|
|
128
130
|
|
|
@@ -78,6 +78,31 @@ export interface LLMReactResponse {
|
|
|
78
78
|
isFinal: boolean;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Per-iteration telemetry callback metadata.
|
|
83
|
+
*
|
|
84
|
+
* @since 1.7.0
|
|
85
|
+
* @public
|
|
86
|
+
*/
|
|
87
|
+
export interface ReactStepMeta {
|
|
88
|
+
/** Iteration index (mirrors `step.index`). */
|
|
89
|
+
iteration: number;
|
|
90
|
+
/** Wall-clock duration of the iteration in milliseconds. */
|
|
91
|
+
durationMs: number;
|
|
92
|
+
/** Caller-supplied correlation id from `ReactLoopOptions.loopId`. */
|
|
93
|
+
loopId?: string;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Minimal logger contract for swallowed onStep errors.
|
|
98
|
+
*
|
|
99
|
+
* @since 1.7.0
|
|
100
|
+
* @public
|
|
101
|
+
*/
|
|
102
|
+
export interface ReactLoopLogger {
|
|
103
|
+
warn: (msg: string, meta?: Record<string, unknown>) => void;
|
|
104
|
+
}
|
|
105
|
+
|
|
81
106
|
export interface ReactLoopOptions {
|
|
82
107
|
/** Max steps before forced stop (default: 10). */
|
|
83
108
|
maxSteps?: number;
|
|
@@ -95,6 +120,29 @@ export interface ReactLoopOptions {
|
|
|
95
120
|
maxToolCallSize?: number;
|
|
96
121
|
/** Allowed tool names. Unlisted tools get an error feedback. */
|
|
97
122
|
allowedTools?: string[];
|
|
123
|
+
/**
|
|
124
|
+
* Called after each iteration with the completed step + timing.
|
|
125
|
+
* Fire-and-forget — errors caught + logged via opts.logger, never
|
|
126
|
+
* propagate to the loop. Use this to emit ctx.insertStep telemetry.
|
|
127
|
+
*
|
|
128
|
+
* @since 1.7.0
|
|
129
|
+
*/
|
|
130
|
+
onStep?: (step: ReactStep, meta: ReactStepMeta) => void | Promise<void>;
|
|
131
|
+
/**
|
|
132
|
+
* Optional correlation id propagated into `meta.loopId` of every
|
|
133
|
+
* `onStep` call, so callers can correlate multiple reactLoops within
|
|
134
|
+
* one OODA cycle.
|
|
135
|
+
*
|
|
136
|
+
* @since 1.7.0
|
|
137
|
+
*/
|
|
138
|
+
loopId?: string;
|
|
139
|
+
/**
|
|
140
|
+
* Logger used when `onStep` throws / rejects. Defaults to no-op
|
|
141
|
+
* (errors are silently swallowed).
|
|
142
|
+
*
|
|
143
|
+
* @since 1.7.0
|
|
144
|
+
*/
|
|
145
|
+
logger?: ReactLoopLogger;
|
|
98
146
|
}
|
|
99
147
|
|
|
100
148
|
// ─── Constants ──────────────────────────────────────────────────────────────────
|
|
@@ -102,6 +150,35 @@ export interface ReactLoopOptions {
|
|
|
102
150
|
const DEFAULT_MAX_STEPS = 10;
|
|
103
151
|
const DEFAULT_MAX_TOOL_CALL_SIZE = 10_240; // 10KB
|
|
104
152
|
|
|
153
|
+
// ─── Helpers ────────────────────────────────────────────────────────────────────
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Invoke the user-supplied `onStep` callback with try/catch. Errors are
|
|
157
|
+
* logged via `opts.logger?.warn` and never propagate to the caller.
|
|
158
|
+
*
|
|
159
|
+
* Handles both sync void and async returns.
|
|
160
|
+
*/
|
|
161
|
+
async function safeOnStep(
|
|
162
|
+
cb: NonNullable<ReactLoopOptions["onStep"]>,
|
|
163
|
+
step: ReactStep,
|
|
164
|
+
meta: ReactStepMeta,
|
|
165
|
+
logger: ReactLoopLogger | undefined
|
|
166
|
+
): Promise<void> {
|
|
167
|
+
try {
|
|
168
|
+
const ret = cb(step, meta);
|
|
169
|
+
if (ret && typeof (ret as Promise<void>).then === "function") {
|
|
170
|
+
await ret;
|
|
171
|
+
}
|
|
172
|
+
} catch (err) {
|
|
173
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
174
|
+
logger?.warn?.("reactLoop.onStep threw — error swallowed", {
|
|
175
|
+
iteration: meta.iteration,
|
|
176
|
+
loopId: meta.loopId,
|
|
177
|
+
error: message,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
105
182
|
// ─── Loop ───────────────────────────────────────────────────────────────────────
|
|
106
183
|
|
|
107
184
|
/**
|
|
@@ -122,11 +199,23 @@ export async function reactLoop(opts: ReactLoopOptions): Promise<ReactResult> {
|
|
|
122
199
|
{ role: "user", content: opts.task },
|
|
123
200
|
];
|
|
124
201
|
|
|
202
|
+
const { onStep, loopId, logger } = opts;
|
|
203
|
+
|
|
204
|
+
/** Build telemetry meta for iteration `i`, given its start timestamp. */
|
|
205
|
+
const buildMeta = (i: number, iterationStart: number): ReactStepMeta => ({
|
|
206
|
+
iteration: i,
|
|
207
|
+
durationMs: Date.now() - iterationStart,
|
|
208
|
+
loopId,
|
|
209
|
+
});
|
|
210
|
+
|
|
125
211
|
for (let i = 0; i < maxSteps; i++) {
|
|
126
212
|
if (opts.signal?.aborted) {
|
|
213
|
+
// Aborted iteration — step is not finalized, onStep is NOT called.
|
|
127
214
|
return { answer: "", steps, totalSteps: i, truncated: true };
|
|
128
215
|
}
|
|
129
216
|
|
|
217
|
+
const iterationStart = Date.now();
|
|
218
|
+
|
|
130
219
|
// Thought → Action
|
|
131
220
|
const response = await opts.llm(messages);
|
|
132
221
|
steps.push({
|
|
@@ -136,8 +225,25 @@ export async function reactLoop(opts: ReactLoopOptions): Promise<ReactResult> {
|
|
|
136
225
|
});
|
|
137
226
|
|
|
138
227
|
// Final answer — no tool call
|
|
139
|
-
if (
|
|
140
|
-
|
|
228
|
+
if (
|
|
229
|
+
response.isFinal ||
|
|
230
|
+
!response.toolCalls ||
|
|
231
|
+
response.toolCalls.length === 0
|
|
232
|
+
) {
|
|
233
|
+
if (onStep) {
|
|
234
|
+
await safeOnStep(
|
|
235
|
+
onStep,
|
|
236
|
+
steps[i],
|
|
237
|
+
buildMeta(i, iterationStart),
|
|
238
|
+
logger
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
return {
|
|
242
|
+
answer: response.content,
|
|
243
|
+
steps,
|
|
244
|
+
totalSteps: i + 1,
|
|
245
|
+
truncated: false,
|
|
246
|
+
};
|
|
141
247
|
}
|
|
142
248
|
|
|
143
249
|
const toolCall = response.toolCalls[0];
|
|
@@ -146,22 +252,50 @@ export async function reactLoop(opts: ReactLoopOptions): Promise<ReactResult> {
|
|
|
146
252
|
const toolJson = JSON.stringify(toolCall);
|
|
147
253
|
if (toolJson.length > maxToolCallSize) {
|
|
148
254
|
steps[i].error = `Tool call exceeds ${maxToolCallSize}B limit`;
|
|
149
|
-
steps[
|
|
255
|
+
steps[
|
|
256
|
+
i
|
|
257
|
+
].observation = `Error: tool call too large (${toolJson.length}B > ${maxToolCallSize}B limit)`;
|
|
150
258
|
messages.push(
|
|
151
259
|
{ role: "assistant", content: response.content, name: toolCall.tool },
|
|
152
|
-
{
|
|
260
|
+
{
|
|
261
|
+
role: "tool",
|
|
262
|
+
content: steps[i].observation!,
|
|
263
|
+
tool_call_id: `call_${i}`,
|
|
264
|
+
}
|
|
153
265
|
);
|
|
266
|
+
if (onStep) {
|
|
267
|
+
await safeOnStep(
|
|
268
|
+
onStep,
|
|
269
|
+
steps[i],
|
|
270
|
+
buildMeta(i, iterationStart),
|
|
271
|
+
logger
|
|
272
|
+
);
|
|
273
|
+
}
|
|
154
274
|
continue;
|
|
155
275
|
}
|
|
156
276
|
|
|
157
277
|
// Check allowed tools
|
|
158
278
|
if (allowedTools && !allowedTools.includes(toolCall.tool)) {
|
|
159
279
|
steps[i].error = `Tool "${toolCall.tool}" not in allowed list`;
|
|
160
|
-
steps[i].observation = `Error: tool "${
|
|
280
|
+
steps[i].observation = `Error: tool "${
|
|
281
|
+
toolCall.tool
|
|
282
|
+
}" is not allowed. Available tools: ${allowedTools.join(", ")}`;
|
|
161
283
|
messages.push(
|
|
162
284
|
{ role: "assistant", content: response.content, name: toolCall.tool },
|
|
163
|
-
{
|
|
285
|
+
{
|
|
286
|
+
role: "tool",
|
|
287
|
+
content: steps[i].observation!,
|
|
288
|
+
tool_call_id: `call_${i}`,
|
|
289
|
+
}
|
|
164
290
|
);
|
|
291
|
+
if (onStep) {
|
|
292
|
+
await safeOnStep(
|
|
293
|
+
onStep,
|
|
294
|
+
steps[i],
|
|
295
|
+
buildMeta(i, iterationStart),
|
|
296
|
+
logger
|
|
297
|
+
);
|
|
298
|
+
}
|
|
165
299
|
continue;
|
|
166
300
|
}
|
|
167
301
|
|
|
@@ -171,14 +305,25 @@ export async function reactLoop(opts: ReactLoopOptions): Promise<ReactResult> {
|
|
|
171
305
|
steps[i].observation = observation;
|
|
172
306
|
} catch (err) {
|
|
173
307
|
steps[i].error = err instanceof Error ? err.message : String(err);
|
|
174
|
-
steps[
|
|
308
|
+
steps[
|
|
309
|
+
i
|
|
310
|
+
].observation = `Error executing tool "${toolCall.tool}": ${steps[i].error}`;
|
|
175
311
|
}
|
|
176
312
|
|
|
177
313
|
// Feed observation back into the conversation
|
|
178
314
|
messages.push(
|
|
179
315
|
{ role: "assistant", content: response.content, name: toolCall.tool },
|
|
180
|
-
{
|
|
316
|
+
{
|
|
317
|
+
role: "tool",
|
|
318
|
+
content: steps[i].observation!,
|
|
319
|
+
tool_call_id: `call_${i}`,
|
|
320
|
+
}
|
|
181
321
|
);
|
|
322
|
+
|
|
323
|
+
// Step is fully finalized (thought + action + observation/error).
|
|
324
|
+
if (onStep) {
|
|
325
|
+
await safeOnStep(onStep, steps[i], buildMeta(i, iterationStart), logger);
|
|
326
|
+
}
|
|
182
327
|
}
|
|
183
328
|
|
|
184
329
|
// Truncated — max steps reached
|