@burtson-labs/agent-core 1.6.38 → 1.6.40

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.
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Phase 3 — completion contracts, evidence, verification nodes.
3
+ *
4
+ * A node that "completed" without producing what it promised is the graph
5
+ * version of the claim-without-doing problem the loop's detectors chase in
6
+ * prose. Contracts make the promise EXPLICIT and machine-checkable:
7
+ * an executor returns an outcome + evidence, the scheduler checks the node's
8
+ * contract against them, and a violation IS a failure — dependents skip, the
9
+ * run reports failed, nobody builds on unverified work.
10
+ *
11
+ * Contracts are deliberately DECLARATIVE (plain data, serializable):
12
+ * - a future planner (Phase 9) can propose them alongside a GraphSpec;
13
+ * - checkpoints (Phase 5) can persist them;
14
+ * - hosts can render "why is this node failed" without executing anything.
15
+ * Anything needing custom logic belongs in a verification NODE — independent
16
+ * work the scheduler runs like any other node — not in a contract lambda.
17
+ */
18
+ import type { CompletionContract, EvidenceItem, GraphNodeSpec, NodeExecutor, NodeRunContext } from './types';
19
+ /**
20
+ * Check a contract. Returns human-readable violations — empty array = pass.
21
+ * Pure and total: bad regex sources become a violation, never a throw.
22
+ */
23
+ export declare function checkContract(contract: CompletionContract | undefined, outcome: {
24
+ output?: unknown;
25
+ evidence?: EvidenceItem[];
26
+ }): string[];
27
+ /** What a verifier decides about upstream work. */
28
+ export interface Verdict {
29
+ pass: boolean;
30
+ /** Required when pass=false — a verdict without reasons is unactionable. */
31
+ reasons?: string[];
32
+ }
33
+ export type VerifierFn = (ctx: NodeRunContext) => Promise<Verdict> | Verdict;
34
+ /**
35
+ * Build an INDEPENDENT verification node for `targetId`: it depends on the
36
+ * target, runs the verifier against the target's result, and fails the graph
37
+ * branch when the verdict is negative — so anything depending on the verify
38
+ * node only runs over verified work. (Chain: work → verify → consume.)
39
+ *
40
+ * The verifier is ordinary node work — it can be a wrapped loop turn (a second
41
+ * model reviewing the first's output) or plain code (run the tests, diff the
42
+ * artifact). The scheduler treats it like any node; there is no special path.
43
+ */
44
+ export declare function verificationNode(id: string, targetId: string, verifier: VerifierFn, spec?: Partial<Pick<GraphNodeSpec, 'label' | 'dependsOn'>>): {
45
+ node: GraphNodeSpec;
46
+ executor: NodeExecutor;
47
+ };
48
+ //# sourceMappingURL=contracts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../src/graph/contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,cAAc,EACf,MAAM,SAAS,CAAC;AAEjB;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,kBAAkB,GAAG,SAAS,EACxC,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAA;CAAE,GACvD,MAAM,EAAE,CA8BV;AAID,mDAAmD;AACnD,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,OAAO,CAAC;IACd,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;AAE7E;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,UAAU,EACpB,IAAI,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,OAAO,GAAG,WAAW,CAAC,CAAC,GACzD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAA;CAAE,CAmBjD"}
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ /**
3
+ * Phase 3 — completion contracts, evidence, verification nodes.
4
+ *
5
+ * A node that "completed" without producing what it promised is the graph
6
+ * version of the claim-without-doing problem the loop's detectors chase in
7
+ * prose. Contracts make the promise EXPLICIT and machine-checkable:
8
+ * an executor returns an outcome + evidence, the scheduler checks the node's
9
+ * contract against them, and a violation IS a failure — dependents skip, the
10
+ * run reports failed, nobody builds on unverified work.
11
+ *
12
+ * Contracts are deliberately DECLARATIVE (plain data, serializable):
13
+ * - a future planner (Phase 9) can propose them alongside a GraphSpec;
14
+ * - checkpoints (Phase 5) can persist them;
15
+ * - hosts can render "why is this node failed" without executing anything.
16
+ * Anything needing custom logic belongs in a verification NODE — independent
17
+ * work the scheduler runs like any other node — not in a contract lambda.
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.checkContract = checkContract;
21
+ exports.verificationNode = verificationNode;
22
+ /**
23
+ * Check a contract. Returns human-readable violations — empty array = pass.
24
+ * Pure and total: bad regex sources become a violation, never a throw.
25
+ */
26
+ function checkContract(contract, outcome) {
27
+ if (!contract)
28
+ return [];
29
+ const violations = [];
30
+ const text = typeof outcome.output === 'string'
31
+ ? outcome.output
32
+ : outcome.output === undefined
33
+ ? ''
34
+ : JSON.stringify(outcome.output);
35
+ if (contract.outputNonEmpty && text.trim().length === 0) {
36
+ violations.push('contract: output is empty');
37
+ }
38
+ if (contract.outputMatches) {
39
+ try {
40
+ const re = new RegExp(contract.outputMatches, 's');
41
+ if (!re.test(text)) {
42
+ violations.push(`contract: output does not match /${contract.outputMatches}/`);
43
+ }
44
+ }
45
+ catch {
46
+ violations.push(`contract: invalid outputMatches regex /${contract.outputMatches}/`);
47
+ }
48
+ }
49
+ for (const req of contract.requireEvidence ?? []) {
50
+ const min = Math.max(1, req.min ?? 1);
51
+ const count = (outcome.evidence ?? []).filter((e) => e.kind === req.kind).length;
52
+ if (count < min) {
53
+ violations.push(`contract: needs ${min} evidence of kind "${req.kind}", got ${count}`);
54
+ }
55
+ }
56
+ return violations;
57
+ }
58
+ /**
59
+ * Build an INDEPENDENT verification node for `targetId`: it depends on the
60
+ * target, runs the verifier against the target's result, and fails the graph
61
+ * branch when the verdict is negative — so anything depending on the verify
62
+ * node only runs over verified work. (Chain: work → verify → consume.)
63
+ *
64
+ * The verifier is ordinary node work — it can be a wrapped loop turn (a second
65
+ * model reviewing the first's output) or plain code (run the tests, diff the
66
+ * artifact). The scheduler treats it like any node; there is no special path.
67
+ */
68
+ function verificationNode(id, targetId, verifier, spec) {
69
+ const node = {
70
+ id,
71
+ label: spec?.label ?? `verify ${targetId}`,
72
+ dependsOn: [...new Set([targetId, ...(spec?.dependsOn ?? [])])],
73
+ };
74
+ const executor = async (ctx) => {
75
+ const verdict = await verifier(ctx);
76
+ if (!verdict.pass) {
77
+ const reasons = verdict.reasons?.length ? verdict.reasons.join('; ') : 'no reasons given';
78
+ throw new Error(`verification failed for ${targetId}: ${reasons}`);
79
+ }
80
+ return {
81
+ output: verdict,
82
+ summary: `verified ${targetId}`,
83
+ evidence: [{ kind: 'verification', detail: targetId, data: verdict }],
84
+ };
85
+ };
86
+ return { node, executor };
87
+ }
88
+ //# sourceMappingURL=contracts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../src/graph/contracts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export * from './types';
2
+ export * from './scheduler';
3
+ export * from './loopNode';
4
+ export * from './contracts';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/graph/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./types"), exports);
18
+ __exportStar(require("./scheduler"), exports);
19
+ __exportStar(require("./loopNode"), exports);
20
+ __exportStar(require("./contracts"), exports);
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/graph/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,8CAA4B;AAC5B,6CAA2B;AAC3B,8CAA4B"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Phase 2 plumbing: run one ToolUseLoop turn as a graph node — the loop is
3
+ * wrapped, never rewritten. Each execution builds a FRESH loop + conversation;
4
+ * cross-node context flows explicitly through upstream outputs folded into the
5
+ * node's prompt (no shared hidden state between nodes, which is what makes a
6
+ * graph inspectable and retryable per-node later).
7
+ */
8
+ import { type ToolUseLoopOptions } from '../tools/tool-use-loop';
9
+ import type { ChatFn, ToolExecutionContext } from '../tools/tool-types';
10
+ import type { ToolRegistry } from '../tools/tool-registry';
11
+ import type { NodeExecutor, NodeRunContext } from './types';
12
+ export interface LoopNodeDeps {
13
+ registry: ToolRegistry;
14
+ ctx: ToolExecutionContext;
15
+ /** ChatFn shared by every execution of this node. Provide exactly one of
16
+ * `chat` / `chatFactory`. */
17
+ chat?: ChatFn;
18
+ /** Builds a fresh ChatFn per node execution (per-node provider/model). */
19
+ chatFactory?: () => ChatFn | Promise<ChatFn>;
20
+ systemPrompt?: string;
21
+ /** Forwarded into the loop (beforeToolExecute gate, emitEvent, budgets…).
22
+ * The graph run's AbortSignal is injected automatically. */
23
+ loopOptions?: ToolUseLoopOptions;
24
+ }
25
+ /**
26
+ * Build the node's prompt. Default folds each upstream node's summary/output
27
+ * under a heading so the model sees exactly what earlier nodes produced.
28
+ */
29
+ export type NodePromptBuilder = (ctx: NodeRunContext) => string;
30
+ export declare function defaultNodePrompt(base: string): NodePromptBuilder;
31
+ /** Wrap one loop run as a NodeExecutor. */
32
+ export declare function wrapLoopAsNode(deps: LoopNodeDeps, buildPrompt: NodePromptBuilder): NodeExecutor;
33
+ //# sourceMappingURL=loopNode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopNode.d.ts","sourceRoot":"","sources":["../../src/graph/loopNode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACpF,OAAO,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAgB,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE1E,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,YAAY,CAAC;IACvB,GAAG,EAAE,oBAAoB,CAAC;IAC1B;kCAC8B;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;iEAC6D;IAC7D,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,cAAc,KAAK,MAAM,CAAC;AAEhE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAWjE;AAED,2CAA2C;AAC3C,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,iBAAiB,GAAG,YAAY,CAsC/F"}
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultNodePrompt = defaultNodePrompt;
4
+ exports.wrapLoopAsNode = wrapLoopAsNode;
5
+ /**
6
+ * Phase 2 plumbing: run one ToolUseLoop turn as a graph node — the loop is
7
+ * wrapped, never rewritten. Each execution builds a FRESH loop + conversation;
8
+ * cross-node context flows explicitly through upstream outputs folded into the
9
+ * node's prompt (no shared hidden state between nodes, which is what makes a
10
+ * graph inspectable and retryable per-node later).
11
+ */
12
+ const tool_use_loop_1 = require("../tools/tool-use-loop");
13
+ function defaultNodePrompt(base) {
14
+ return (ctx) => {
15
+ const upstreamIds = Object.keys(ctx.upstream);
16
+ if (upstreamIds.length === 0)
17
+ return base;
18
+ const sections = upstreamIds.map((id) => {
19
+ const r = ctx.upstream[id];
20
+ const body = r.summary ?? (typeof r.output === 'string' ? r.output : JSON.stringify(r.output ?? ''));
21
+ return `### Result of "${id}"\n${(body ?? '').toString().slice(0, 4000)}`;
22
+ });
23
+ return `${base}\n\n## Upstream results\n\n${sections.join('\n\n')}`;
24
+ };
25
+ }
26
+ /** Wrap one loop run as a NodeExecutor. */
27
+ function wrapLoopAsNode(deps, buildPrompt) {
28
+ if (!deps.chat && !deps.chatFactory) {
29
+ throw new Error('wrapLoopAsNode: provide chat or chatFactory');
30
+ }
31
+ return async (nodeCtx) => {
32
+ const chat = deps.chatFactory ? await deps.chatFactory() : deps.chat;
33
+ // Auto-evidence: successful edit-tool results become 'file-changed'
34
+ // evidence without the executor author doing anything — so a contract
35
+ // like requireEvidence:[{kind:'file-changed'}] works out of the box.
36
+ // The caller's own emitEvent (if any) still sees every event.
37
+ const EDIT_TOOLS = new Set(['write_file', 'apply_edit', 'replace_range', 'apply_patch', 'delete_file']);
38
+ const evidence = [];
39
+ const lastPath = new Map();
40
+ const callerEmit = deps.loopOptions?.emitEvent;
41
+ const emitEvent = (type, payload) => {
42
+ const p = (payload ?? {});
43
+ if (type === 'tool_loop:tool_execute' && p.name && EDIT_TOOLS.has(p.name)) {
44
+ lastPath.set(p.name, p.params?.path ?? '');
45
+ }
46
+ else if (type === 'tool_loop:tool_result' && p.name && EDIT_TOOLS.has(p.name) && !p.isError) {
47
+ evidence.push({ kind: 'file-changed', detail: lastPath.get(p.name) || undefined });
48
+ }
49
+ callerEmit?.(type, payload);
50
+ };
51
+ const loop = (0, tool_use_loop_1.createToolUseLoop)(deps.registry, deps.ctx, {
52
+ ...(deps.loopOptions ?? {}),
53
+ emitEvent,
54
+ signal: nodeCtx.signal,
55
+ });
56
+ const result = await loop.run(buildPrompt(nodeCtx), chat, deps.systemPrompt);
57
+ if (result.cancelled) {
58
+ throw new Error('node cancelled');
59
+ }
60
+ return {
61
+ output: result.finalResponse,
62
+ summary: result.finalResponse.slice(0, 200),
63
+ evidence,
64
+ };
65
+ };
66
+ }
67
+ //# sourceMappingURL=loopNode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopNode.js","sourceRoot":"","sources":["../../src/graph/loopNode.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Graph scheduler — deterministic host code that runs a validated DAG.
3
+ * (Phase 4's conservative core, shipped with Phase 1 so the types are provably
4
+ * runnable; budgets/checkpoints layer on later without changing this surface.)
5
+ *
6
+ * Semantics:
7
+ * - A node runs once ALL of its dependencies are 'done'.
8
+ * - `maxConcurrency` caps simultaneously-running nodes. Default 2 — the
9
+ * plan's "safe default concurrency": enough to prove parallel lift, small
10
+ * enough that filesystem/tool contention stays rare. Callers raise it
11
+ * deliberately.
12
+ * - Failure is contained, not contagious across branches: when a node fails,
13
+ * its transitive dependents are 'skipped'; independent branches keep
14
+ * running to completion. Overall status is then 'failed'.
15
+ * - Cancellation (opts.signal) stops launching new nodes; already-running
16
+ * executors receive the same signal and are awaited; never-started nodes
17
+ * end 'cancelled'. Overall status 'cancelled' (a cancelled run never
18
+ * reports 'failed' — the user stopped it, it didn't break).
19
+ * - Events mirror the tool loop's (type, payload) convention so hosts fold
20
+ * graph progress into the SAME stream that already carries tool_loop:*
21
+ * (Phase 7): graph:start, graph:node_start, graph:node_done,
22
+ * graph:node_failed, graph:node_skipped, graph:node_cancelled, graph:done.
23
+ */
24
+ import { type GraphRunResult, type GraphSpec, type NodeExecutor } from './types';
25
+ export interface RunGraphOptions {
26
+ /** Cap on simultaneously running nodes. Default 2 (conservative). */
27
+ maxConcurrency?: number;
28
+ /** Abort the whole run. */
29
+ signal?: AbortSignal;
30
+ /** Progress events — same shape as the tool loop's emitEvent. */
31
+ emitEvent?: (type: string, payload?: unknown) => void;
32
+ }
33
+ /** Executors per node id, or one executor shared by every node. */
34
+ export type GraphExecutors = NodeExecutor | Record<string, NodeExecutor>;
35
+ export declare function runGraph(spec: GraphSpec, executors: GraphExecutors, opts?: RunGraphOptions): Promise<GraphRunResult>;
36
+ //# sourceMappingURL=scheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/graph/scheduler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,YAAY,EAElB,MAAM,SAAS,CAAC;AAGjB,MAAM,WAAW,eAAe;IAC9B,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2BAA2B;IAC3B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,iEAAiE;IACjE,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CACvD;AAED,mEAAmE;AACnE,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AAEzE,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,SAAS,EACf,SAAS,EAAE,cAAc,EACzB,IAAI,GAAE,eAAoB,GACzB,OAAO,CAAC,cAAc,CAAC,CA6JzB"}
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runGraph = runGraph;
4
+ /**
5
+ * Graph scheduler — deterministic host code that runs a validated DAG.
6
+ * (Phase 4's conservative core, shipped with Phase 1 so the types are provably
7
+ * runnable; budgets/checkpoints layer on later without changing this surface.)
8
+ *
9
+ * Semantics:
10
+ * - A node runs once ALL of its dependencies are 'done'.
11
+ * - `maxConcurrency` caps simultaneously-running nodes. Default 2 — the
12
+ * plan's "safe default concurrency": enough to prove parallel lift, small
13
+ * enough that filesystem/tool contention stays rare. Callers raise it
14
+ * deliberately.
15
+ * - Failure is contained, not contagious across branches: when a node fails,
16
+ * its transitive dependents are 'skipped'; independent branches keep
17
+ * running to completion. Overall status is then 'failed'.
18
+ * - Cancellation (opts.signal) stops launching new nodes; already-running
19
+ * executors receive the same signal and are awaited; never-started nodes
20
+ * end 'cancelled'. Overall status 'cancelled' (a cancelled run never
21
+ * reports 'failed' — the user stopped it, it didn't break).
22
+ * - Events mirror the tool loop's (type, payload) convention so hosts fold
23
+ * graph progress into the SAME stream that already carries tool_loop:*
24
+ * (Phase 7): graph:start, graph:node_start, graph:node_done,
25
+ * graph:node_failed, graph:node_skipped, graph:node_cancelled, graph:done.
26
+ */
27
+ const types_1 = require("./types");
28
+ const contracts_1 = require("./contracts");
29
+ async function runGraph(spec, executors, opts = {}) {
30
+ const startedAt = Date.now();
31
+ const validation = (0, types_1.validateGraph)(spec);
32
+ if (!validation.ok) {
33
+ throw new Error(`invalid graph: ${validation.errors.join('; ')}`);
34
+ }
35
+ const maxConcurrency = Math.max(1, opts.maxConcurrency ?? 2);
36
+ const emit = opts.emitEvent ?? (() => undefined);
37
+ const signal = opts.signal;
38
+ const executorFor = (id) => {
39
+ if (typeof executors === 'function')
40
+ return executors;
41
+ const fn = executors[id];
42
+ if (!fn)
43
+ throw new Error(`no executor for node: ${id}`);
44
+ return fn;
45
+ };
46
+ // Resolve every executor up front so a missing one fails the run BEFORE any
47
+ // node starts, not halfway through.
48
+ for (const node of spec.nodes)
49
+ executorFor(node.id);
50
+ const results = {};
51
+ for (const node of spec.nodes) {
52
+ results[node.id] = { id: node.id, state: 'pending' };
53
+ }
54
+ const dependents = new Map();
55
+ for (const node of spec.nodes) {
56
+ for (const dep of node.dependsOn ?? []) {
57
+ const list = dependents.get(dep) ?? [];
58
+ list.push(node.id);
59
+ dependents.set(dep, list);
60
+ }
61
+ }
62
+ const deps = new Map(spec.nodes.map((n) => [n.id, n.dependsOn ?? []]));
63
+ const labelOf = new Map(spec.nodes.map((n) => [n.id, n.label ?? n.id]));
64
+ const specOf = new Map(spec.nodes.map((n) => [n.id, n]));
65
+ const running = new Map();
66
+ let anyFailed = false;
67
+ const readyToRun = (id) => results[id].state === 'pending' &&
68
+ (deps.get(id) ?? []).every((d) => results[d].state === 'done');
69
+ /** A dependency failed or was skipped/cancelled → this node can never run. */
70
+ const blocked = (id) => results[id].state === 'pending' &&
71
+ (deps.get(id) ?? []).some((d) => {
72
+ const s = results[d].state;
73
+ return s === 'failed' || s === 'skipped' || s === 'cancelled';
74
+ });
75
+ const markSkippedCascade = () => {
76
+ // Iterate to a fixed point: skipping a node can block its own dependents.
77
+ let changed = true;
78
+ while (changed) {
79
+ changed = false;
80
+ for (const node of spec.nodes) {
81
+ if (blocked(node.id)) {
82
+ results[node.id] = { ...results[node.id], state: 'skipped' };
83
+ emit('graph:node_skipped', { id: node.id, label: labelOf.get(node.id) });
84
+ changed = true;
85
+ }
86
+ }
87
+ }
88
+ };
89
+ const launch = (id) => {
90
+ const record = results[id];
91
+ record.state = 'running';
92
+ record.startedAt = Date.now();
93
+ emit('graph:node_start', { id, label: labelOf.get(id) });
94
+ const upstream = {};
95
+ for (const d of deps.get(id) ?? [])
96
+ upstream[d] = results[d];
97
+ const promise = (async () => {
98
+ try {
99
+ const outcome = await executorFor(id)({
100
+ nodeId: id,
101
+ signal: signal ?? new AbortController().signal,
102
+ upstream,
103
+ });
104
+ // Phase 3: the node only counts as done if its completion contract
105
+ // holds. A violation is a FAILURE — "finished but produced nothing it
106
+ // promised" must not feed downstream nodes.
107
+ const violations = (0, contracts_1.checkContract)(specOf.get(id)?.contract, outcome ?? {});
108
+ record.output = outcome?.output;
109
+ record.summary = outcome?.summary;
110
+ record.evidence = outcome?.evidence;
111
+ if (violations.length > 0) {
112
+ record.state = 'failed';
113
+ record.error = violations.join('; ');
114
+ record.contractViolations = violations;
115
+ anyFailed = true;
116
+ emit('graph:node_contract_violation', { id, label: labelOf.get(id), violations });
117
+ emit('graph:node_failed', { id, label: labelOf.get(id), error: record.error });
118
+ }
119
+ else {
120
+ record.state = 'done';
121
+ emit('graph:node_done', { id, label: labelOf.get(id), summary: record.summary });
122
+ }
123
+ }
124
+ catch (err) {
125
+ record.state = 'failed';
126
+ record.error = err instanceof Error ? err.message : String(err);
127
+ anyFailed = true;
128
+ emit('graph:node_failed', { id, label: labelOf.get(id), error: record.error });
129
+ }
130
+ finally {
131
+ record.endedAt = Date.now();
132
+ record.durationMs = record.endedAt - (record.startedAt ?? record.endedAt);
133
+ running.delete(id);
134
+ }
135
+ })();
136
+ running.set(id, promise);
137
+ };
138
+ emit('graph:start', { nodes: spec.nodes.length, maxConcurrency });
139
+ // Main pump: launch every ready node up to the cap, wait for one running
140
+ // node to settle, repeat. Skip-cascade runs each pass so a failure releases
141
+ // its blocked subtree immediately (as 'skipped', not stuck 'pending').
142
+ for (;;) {
143
+ markSkippedCascade();
144
+ if (!signal?.aborted) {
145
+ for (const node of spec.nodes) {
146
+ if (running.size >= maxConcurrency)
147
+ break;
148
+ if (readyToRun(node.id))
149
+ launch(node.id);
150
+ }
151
+ }
152
+ if (running.size === 0)
153
+ break;
154
+ await Promise.race(running.values());
155
+ }
156
+ // Anything still pending at the end: cancelled (signal aborted before it
157
+ // could start) — by construction nothing else can remain pending.
158
+ for (const node of spec.nodes) {
159
+ if (results[node.id].state === 'pending') {
160
+ results[node.id] = { ...results[node.id], state: 'cancelled' };
161
+ emit('graph:node_cancelled', { id: node.id, label: labelOf.get(node.id) });
162
+ }
163
+ }
164
+ const status = signal?.aborted
165
+ ? 'cancelled'
166
+ : anyFailed
167
+ ? 'failed'
168
+ : 'completed';
169
+ const result = {
170
+ status,
171
+ nodes: results,
172
+ durationMs: Date.now() - startedAt,
173
+ };
174
+ emit('graph:done', {
175
+ status,
176
+ durationMs: result.durationMs,
177
+ done: Object.values(results).filter((r) => r.state === 'done').length,
178
+ failed: Object.values(results).filter((r) => r.state === 'failed').length,
179
+ skipped: Object.values(results).filter((r) => r.state === 'skipped').length,
180
+ });
181
+ return result;
182
+ }
183
+ //# sourceMappingURL=scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/graph/scheduler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Graph runtime — types. (Phase 1 of the graph plan.)
3
+ *
4
+ * A run is a DAG of nodes; each node's executor runs only after every node it
5
+ * depends on has finished. The existing ToolUseLoop is NOT rewritten — a node
6
+ * executor typically wraps one loop run (see loopNode.ts), so a graph is
7
+ * "several of today's turns with explicit dependencies" rather than a new
8
+ * agent architecture. Nothing in the framework consumes this module yet; hosts
9
+ * opt in explicitly (that's the feature flag — zero behavior change until a
10
+ * host wires it).
11
+ *
12
+ * Design rules:
13
+ * - The planner (model) may eventually PROPOSE a GraphSpec, but it never owns
14
+ * scheduling. The scheduler is deterministic host code.
15
+ * - Node states form a strict machine:
16
+ * pending → running → done | failed
17
+ * pending → skipped (an upstream dependency failed or was skipped)
18
+ * pending → cancelled (the run's signal aborted before it started)
19
+ * Terminal states never transition again.
20
+ */
21
+ /** A structured claim about what a node actually did (Phase 3).
22
+ * e.g. { kind: 'file-changed', detail: 'src/x.ts' }. JSON-serializable. */
23
+ export interface EvidenceItem {
24
+ kind: string;
25
+ detail?: string;
26
+ data?: unknown;
27
+ }
28
+ export interface EvidenceRequirement {
29
+ kind: string;
30
+ /** Minimum count of matching items. Default 1. */
31
+ min?: number;
32
+ }
33
+ /** Declarative completion contract: what a node MUST produce to count as
34
+ * done. Checked by the scheduler after the executor resolves; violations are
35
+ * failures (dependents skip). Plain data on purpose — proposable by a future
36
+ * planner, persistable by future checkpoints. */
37
+ export interface CompletionContract {
38
+ outputNonEmpty?: boolean;
39
+ /** Regex source the (stringified) output must match (flags: 's'). */
40
+ outputMatches?: string;
41
+ requireEvidence?: EvidenceRequirement[];
42
+ }
43
+ /** One node in the DAG. */
44
+ export interface GraphNodeSpec {
45
+ /** Unique id within the graph. */
46
+ id: string;
47
+ /** Ids of nodes that must complete (state 'done') before this one runs. */
48
+ dependsOn?: string[];
49
+ /** Human label for UIs; falls back to id. */
50
+ label?: string;
51
+ /** Completion contract enforced on this node's outcome. */
52
+ contract?: CompletionContract;
53
+ }
54
+ export interface GraphSpec {
55
+ nodes: GraphNodeSpec[];
56
+ }
57
+ export type NodeState = 'pending' | 'running' | 'done' | 'failed' | 'skipped' | 'cancelled';
58
+ /** What an executor returns on success. `output` is handed to downstream
59
+ * executors verbatim; `summary` is a short human line for UIs/events. */
60
+ export interface NodeOutcome {
61
+ output?: unknown;
62
+ summary?: string;
63
+ /** Structured claims about what was actually done — checked against the
64
+ * node's contract and carried on the result for downstream/UIs. */
65
+ evidence?: EvidenceItem[];
66
+ }
67
+ /** Terminal record for one node after a run. */
68
+ export interface NodeResult {
69
+ id: string;
70
+ state: NodeState;
71
+ output?: unknown;
72
+ summary?: string;
73
+ evidence?: EvidenceItem[];
74
+ /** Set when state === 'failed'. */
75
+ error?: string;
76
+ /** Set when the failure was a contract violation (state 'failed'). */
77
+ contractViolations?: string[];
78
+ startedAt?: number;
79
+ endedAt?: number;
80
+ durationMs?: number;
81
+ }
82
+ export type GraphRunStatus = 'completed' | 'failed' | 'cancelled';
83
+ export interface GraphRunResult {
84
+ status: GraphRunStatus;
85
+ /** Terminal result per node id — every node in the spec appears. */
86
+ nodes: Record<string, NodeResult>;
87
+ durationMs: number;
88
+ }
89
+ /** Context handed to a node's executor when it runs. */
90
+ export interface NodeRunContext {
91
+ nodeId: string;
92
+ /** Abort signal for the whole graph run — executors must respect it. */
93
+ signal: AbortSignal;
94
+ /** Terminal results of this node's direct dependencies (all state 'done'). */
95
+ upstream: Record<string, NodeResult>;
96
+ }
97
+ export type NodeExecutor = (ctx: NodeRunContext) => Promise<NodeOutcome> | NodeOutcome;
98
+ export interface GraphValidation {
99
+ ok: boolean;
100
+ errors: string[];
101
+ }
102
+ /**
103
+ * Structural validation: duplicate ids, unknown/self dependencies, cycles.
104
+ * Kahn's algorithm for cycle detection — if a topological pass can't consume
105
+ * every node, whatever remains is (part of) a cycle and gets named in the
106
+ * error so the author can see it.
107
+ */
108
+ export declare function validateGraph(spec: GraphSpec): GraphValidation;
109
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/graph/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH;4EAC4E;AAC5E,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;kDAGkD;AAClD,MAAM,WAAW,kBAAkB;IACjC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,mBAAmB,EAAE,CAAC;CACzC;AAED,2BAA2B;AAC3B,MAAM,WAAW,aAAa;IAC5B,kCAAkC;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AAED,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAC;AAE5F;0EAC0E;AAC1E,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;wEACoE;IACpE,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,gDAAgD;AAChD,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;IAC1B,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,cAAc,CAAC;IACvB,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wDAAwD;AACxD,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,MAAM,EAAE,WAAW,CAAC;IACpB,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACtC;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW,CAAC;AAEvF,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,GAAG,eAAe,CA2C9D"}
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ /**
3
+ * Graph runtime — types. (Phase 1 of the graph plan.)
4
+ *
5
+ * A run is a DAG of nodes; each node's executor runs only after every node it
6
+ * depends on has finished. The existing ToolUseLoop is NOT rewritten — a node
7
+ * executor typically wraps one loop run (see loopNode.ts), so a graph is
8
+ * "several of today's turns with explicit dependencies" rather than a new
9
+ * agent architecture. Nothing in the framework consumes this module yet; hosts
10
+ * opt in explicitly (that's the feature flag — zero behavior change until a
11
+ * host wires it).
12
+ *
13
+ * Design rules:
14
+ * - The planner (model) may eventually PROPOSE a GraphSpec, but it never owns
15
+ * scheduling. The scheduler is deterministic host code.
16
+ * - Node states form a strict machine:
17
+ * pending → running → done | failed
18
+ * pending → skipped (an upstream dependency failed or was skipped)
19
+ * pending → cancelled (the run's signal aborted before it started)
20
+ * Terminal states never transition again.
21
+ */
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.validateGraph = validateGraph;
24
+ /**
25
+ * Structural validation: duplicate ids, unknown/self dependencies, cycles.
26
+ * Kahn's algorithm for cycle detection — if a topological pass can't consume
27
+ * every node, whatever remains is (part of) a cycle and gets named in the
28
+ * error so the author can see it.
29
+ */
30
+ function validateGraph(spec) {
31
+ const errors = [];
32
+ const ids = new Set();
33
+ for (const node of spec.nodes) {
34
+ if (!node.id || node.id.trim().length === 0)
35
+ errors.push('node with empty id');
36
+ else if (ids.has(node.id))
37
+ errors.push(`duplicate node id: ${node.id}`);
38
+ else
39
+ ids.add(node.id);
40
+ }
41
+ for (const node of spec.nodes) {
42
+ for (const dep of node.dependsOn ?? []) {
43
+ if (dep === node.id)
44
+ errors.push(`node ${node.id} depends on itself`);
45
+ else if (!ids.has(dep))
46
+ errors.push(`node ${node.id} depends on unknown node: ${dep}`);
47
+ }
48
+ }
49
+ if (errors.length === 0) {
50
+ // Kahn: repeatedly remove nodes with no unconsumed deps.
51
+ const indegree = new Map();
52
+ const dependents = new Map();
53
+ for (const node of spec.nodes) {
54
+ indegree.set(node.id, (node.dependsOn ?? []).length);
55
+ for (const dep of node.dependsOn ?? []) {
56
+ const list = dependents.get(dep) ?? [];
57
+ list.push(node.id);
58
+ dependents.set(dep, list);
59
+ }
60
+ }
61
+ const queue = spec.nodes.filter((n) => (indegree.get(n.id) ?? 0) === 0).map((n) => n.id);
62
+ let consumed = 0;
63
+ while (queue.length > 0) {
64
+ const id = queue.shift();
65
+ consumed += 1;
66
+ for (const next of dependents.get(id) ?? []) {
67
+ const left = (indegree.get(next) ?? 1) - 1;
68
+ indegree.set(next, left);
69
+ if (left === 0)
70
+ queue.push(next);
71
+ }
72
+ }
73
+ if (consumed !== spec.nodes.length) {
74
+ const cyclic = spec.nodes.filter((n) => (indegree.get(n.id) ?? 0) > 0).map((n) => n.id);
75
+ errors.push(`cycle detected involving: ${cyclic.join(', ')}`);
76
+ }
77
+ }
78
+ return { ok: errors.length === 0, errors };
79
+ }
80
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/graph/types.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -12,6 +12,7 @@ export interface CreateAgentRuntimeOptions extends Partial<Omit<AgentRuntimeOpti
12
12
  }
13
13
  export declare const createAgentRuntime: (options?: CreateAgentRuntimeOptions) => AgentRuntime;
14
14
  export * from './tools';
15
+ export * from './graph';
15
16
  export * from './mcp';
16
17
  export { redactSecrets, redactSecretsString, BUILTIN_SECRET_PATTERNS, type SecretPattern, type RedactionResult } from './security/secretPatterns';
17
18
  export { TelemetryExporter, resolveTelemetryConfig, TTFT_BUCKETS, DURATION_BUCKETS, type TelemetryConfig } from './telemetry/otlpExporter';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,EAC5B,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACd,WAAW,EACX,WAAW,EACX,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,wBAAwB,CAAC;AAEhC,MAAM,WAAW,yBAA0B,SAAQ,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,CAAC;IAC/F,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,eAAO,MAAM,kBAAkB,GAAI,UAAS,yBAA8B,KAAG,YAO5E,CAAC;AAGF,cAAc,SAAS,CAAC;AAKxB,cAAc,OAAO,CAAC;AAKtB,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,uBAAuB,EACvB,KAAK,aAAa,EAClB,KAAK,eAAe,EACrB,MAAM,2BAA2B,CAAC;AAInC,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,YAAY,EACZ,gBAAgB,EAChB,KAAK,eAAe,EACrB,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,EAC5B,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACd,WAAW,EACX,WAAW,EACX,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,wBAAwB,CAAC;AAEhC,MAAM,WAAW,yBAA0B,SAAQ,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,CAAC;IAC/F,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,eAAO,MAAM,kBAAkB,GAAI,UAAS,yBAA8B,KAAG,YAO5E,CAAC;AAGF,cAAc,SAAS,CAAC;AAGxB,cAAc,SAAS,CAAC;AAKxB,cAAc,OAAO,CAAC;AAKtB,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,uBAAuB,EACvB,KAAK,aAAa,EAClB,KAAK,eAAe,EACrB,MAAM,2BAA2B,CAAC;AAInC,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,YAAY,EACZ,gBAAgB,EAChB,KAAK,eAAe,EACrB,MAAM,0BAA0B,CAAC"}
package/dist/index.js CHANGED
@@ -38,6 +38,9 @@ const createAgentRuntime = (options = {}) => {
38
38
  exports.createAgentRuntime = createAgentRuntime;
39
39
  // Tool system
40
40
  __exportStar(require("./tools"), exports);
41
+ // Graph runtime (DAG of loop-wrapping nodes). Nothing in the framework
42
+ // consumes it yet — hosts opt in explicitly; zero behavior change until then.
43
+ __exportStar(require("./graph"), exports);
41
44
  // MCP — Model Context Protocol client (Phase 1: groundwork). See
42
45
  // docs/integration-playlist/mcp-roadmap.md. Off by default — hosts
43
46
  // that don't construct an McpClientPool get zero behavior change.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AACA,yDAAsD;AACtD,+EAAiF;AAGjF,gDAA8B;AAC9B,gDAA8B;AAC9B,uCAAkD;AAAzC,0GAAA,iBAAiB,OAAA;AAE1B,+DAIqC;AADnC,oHAAA,iBAAiB,OAAA;AAGnB,6EAG4C;AAF1C,qIAAA,2BAA2B,OAAA;AAI7B,uDAUgC;AAT9B,4GAAA,YAAY,OAAA;AAeP,MAAM,kBAAkB,GAAG,CAAC,UAAqC,EAAE,EAAgB,EAAE;IAC1F,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IACxD,MAAM,QAAQ,GAAG,gBAAgB,IAAI,IAAI,oDAA2B,EAAE,CAAC;IACvE,OAAO,IAAI,2BAAY,CAAC;QACtB,QAAQ;QACR,GAAI,IAA8C;KACnD,CAAC,CAAC;AACL,CAAC,CAAC;AAPW,QAAA,kBAAkB,sBAO7B;AAEF,cAAc;AACd,0CAAwB;AAExB,iEAAiE;AACjE,mEAAmE;AACnE,kEAAkE;AAClE,wCAAsB;AAEtB,wDAAwD;AACxD,mEAAmE;AACnE,4CAA4C;AAC5C,4DAMmC;AALjC,+GAAA,aAAa,OAAA;AACb,qHAAA,mBAAmB,OAAA;AACnB,yHAAA,uBAAuB,OAAA;AAKzB,iFAAiF;AACjF,iFAAiF;AACjF,yDAMkC;AALhC,iHAAA,iBAAiB,OAAA;AACjB,sHAAA,sBAAsB,OAAA;AACtB,4GAAA,YAAY,OAAA;AACZ,gHAAA,gBAAgB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AACA,yDAAsD;AACtD,+EAAiF;AAGjF,gDAA8B;AAC9B,gDAA8B;AAC9B,uCAAkD;AAAzC,0GAAA,iBAAiB,OAAA;AAE1B,+DAIqC;AADnC,oHAAA,iBAAiB,OAAA;AAGnB,6EAG4C;AAF1C,qIAAA,2BAA2B,OAAA;AAI7B,uDAUgC;AAT9B,4GAAA,YAAY,OAAA;AAeP,MAAM,kBAAkB,GAAG,CAAC,UAAqC,EAAE,EAAgB,EAAE;IAC1F,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IACxD,MAAM,QAAQ,GAAG,gBAAgB,IAAI,IAAI,oDAA2B,EAAE,CAAC;IACvE,OAAO,IAAI,2BAAY,CAAC;QACtB,QAAQ;QACR,GAAI,IAA8C;KACnD,CAAC,CAAC;AACL,CAAC,CAAC;AAPW,QAAA,kBAAkB,sBAO7B;AAEF,cAAc;AACd,0CAAwB;AACxB,uEAAuE;AACvE,8EAA8E;AAC9E,0CAAwB;AAExB,iEAAiE;AACjE,mEAAmE;AACnE,kEAAkE;AAClE,wCAAsB;AAEtB,wDAAwD;AACxD,mEAAmE;AACnE,4CAA4C;AAC5C,4DAMmC;AALjC,+GAAA,aAAa,OAAA;AACb,qHAAA,mBAAmB,OAAA;AACnB,yHAAA,uBAAuB,OAAA;AAKzB,iFAAiF;AACjF,iFAAiF;AACjF,yDAMkC;AALhC,iHAAA,iBAAiB,OAAA;AACjB,sHAAA,sBAAsB,OAAA;AACtB,4GAAA,YAAY,OAAA;AACZ,gHAAA,gBAAgB,OAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burtson-labs/agent-core",
3
- "version": "1.6.38",
3
+ "version": "1.6.40",
4
4
  "author": {
5
5
  "name": "Burtson Labs",
6
6
  "email": "team@burtson.ai",