network-ai 5.2.2 → 5.3.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.
@@ -0,0 +1,246 @@
1
+ "use strict";
2
+ /**
3
+ * Partition Planner — Logical Work Partitioning for Network-AI
4
+ *
5
+ * Prevents parallel agents from performing redundant research or analysis by
6
+ * running a "meta-step" before DAG execution that generates a Scope Assignment
7
+ * Map (PartitionSchema). Each agent receives a boundary constraint injected
8
+ * into its parameters, declaring what it SHOULD focus on and what it should
9
+ * EXCLUDE.
10
+ *
11
+ * The planner also performs an overlap check — verifying that no two
12
+ * `focus_area` strings overlap semantically (or lexically, when using the
13
+ * built-in heuristic check).
14
+ *
15
+ * Zero external dependencies — the overlap checker and the planner function
16
+ * are pluggable so callers can use any LLM or rule-based strategy.
17
+ *
18
+ * @module PartitionPlanner
19
+ * @version 1.0.0
20
+ */
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.PartitionPlanner = void 0;
23
+ exports.createLexicalOverlapChecker = createLexicalOverlapChecker;
24
+ exports.createLLMPartitionPlanner = createLLMPartitionPlanner;
25
+ exports.parsePartitionJSON = parsePartitionJSON;
26
+ // ============================================================================
27
+ // BUILT-IN OVERLAP CHECKER (lexical heuristic — zero model cost)
28
+ // ============================================================================
29
+ /**
30
+ * Lexical overlap checker: considers two focus areas to overlap when they
31
+ * share significant word stems (ignoring common stop words).
32
+ *
33
+ * This is the built-in default. For true semantic overlap detection, inject
34
+ * an LLM-based `OverlapCheckFunction` via `PartitionPlannerOptions.overlapChecker`.
35
+ */
36
+ function createLexicalOverlapChecker() {
37
+ const STOP_WORDS = new Set([
38
+ 'a', 'an', 'the', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for',
39
+ 'of', 'with', 'by', 'from', 'is', 'are', 'was', 'were', 'be', 'been',
40
+ 'as', 'its', 'it', 'this', 'that', 'all', 'any', 'each', 'every',
41
+ ]);
42
+ function tokenize(text) {
43
+ return new Set(text
44
+ .toLowerCase()
45
+ .replace(/[^a-z0-9\s]/g, ' ')
46
+ .split(/\s+/)
47
+ .filter((w) => w.length > 2 && !STOP_WORDS.has(w)));
48
+ }
49
+ return async (schema) => {
50
+ const overlaps = [];
51
+ for (let i = 0; i < schema.length; i++) {
52
+ for (let j = i + 1; j < schema.length; j++) {
53
+ const tokensA = tokenize(schema[i].focus_area);
54
+ const tokensB = tokenize(schema[j].focus_area);
55
+ const shared = [];
56
+ for (const token of tokensA) {
57
+ if (tokensB.has(token))
58
+ shared.push(token);
59
+ }
60
+ // Flag as overlap when ≥ 2 shared significant words or overlap ratio > 0.4
61
+ const unionSize = new Set([...tokensA, ...tokensB]).size;
62
+ const ratio = unionSize > 0 ? shared.length / unionSize : 0;
63
+ if (shared.length >= 2 || ratio > 0.4) {
64
+ overlaps.push(`Overlap between "${schema[i].agent_type}" (focus: "${schema[i].focus_area}") and "${schema[j].agent_type}" (focus: "${schema[j].focus_area}") — shared terms: ${shared.join(', ')}`);
65
+ }
66
+ }
67
+ }
68
+ return overlaps;
69
+ };
70
+ }
71
+ /**
72
+ * Build a partition planner backed by an LLM.
73
+ *
74
+ * The LLM is asked to generate a PartitionSchema JSON array given the goal
75
+ * and the available agents. Use this for rich semantic partitioning.
76
+ *
77
+ * @param executor - Network-AI executor function
78
+ * @param plannerAgentId - Agent ID for the LLM that does partitioning
79
+ */
80
+ function createLLMPartitionPlanner(executor, plannerAgentId) {
81
+ return async (goal, agents, context) => {
82
+ const agentList = agents.map((a) => `- ${a.id}: ${a.role}`).join('\n');
83
+ const prompt = [
84
+ 'You are a work-partitioning planner for a multi-agent AI system.',
85
+ 'Generate a scope assignment for each agent to prevent redundant research.',
86
+ '',
87
+ `GOAL: ${goal}`,
88
+ '',
89
+ 'AGENTS:',
90
+ agentList,
91
+ '',
92
+ context ? `CONTEXT: ${JSON.stringify(context)}` : '',
93
+ '',
94
+ 'Respond with ONLY a JSON array where each element has:',
95
+ '- "agent_type": agent ID from the list above',
96
+ '- "focus_area": a short phrase describing what ONLY this agent researches',
97
+ '- "excluded_topics": array of topic strings this agent must NOT cover',
98
+ '',
99
+ 'Ensure no two focus_area values overlap semantically.',
100
+ '',
101
+ 'Example:',
102
+ '[{"agent_type":"researcher","focus_area":"market trends and competitive landscape","excluded_topics":["financial projections","legal compliance"]},',
103
+ ' {"agent_type":"analyst","focus_area":"financial projections and ROI analysis","excluded_topics":["market research","legal compliance"]}]',
104
+ ].filter(Boolean).join('\n');
105
+ const result = await executor(plannerAgentId, { action: 'partition', params: { prompt } }, { agentId: plannerAgentId, taskId: `partition-${Date.now()}`, metadata: { type: 'partition-planning', ...(context ?? {}) } });
106
+ if (!result.success || !result.data) {
107
+ throw new Error(`Partition planner failed: ${result.error?.message ?? 'no data returned'}`);
108
+ }
109
+ return parsePartitionJSON(typeof result.data === 'string' ? result.data : JSON.stringify(result.data));
110
+ };
111
+ }
112
+ /**
113
+ * Parse a PartitionSchema from an LLM response string.
114
+ * Handles markdown fences and leading/trailing text.
115
+ */
116
+ function parsePartitionJSON(text) {
117
+ let cleaned = text.trim();
118
+ // Strip markdown fences
119
+ const fenceOpen = cleaned.indexOf('```');
120
+ if (fenceOpen !== -1) {
121
+ const afterOpen = cleaned.indexOf('\n', fenceOpen);
122
+ const fenceClose = cleaned.indexOf('```', afterOpen !== -1 ? afterOpen : fenceOpen + 3);
123
+ if (afterOpen !== -1 && fenceClose > afterOpen) {
124
+ cleaned = cleaned.substring(afterOpen + 1, fenceClose).trim();
125
+ }
126
+ }
127
+ // Find JSON array
128
+ const arrayStart = cleaned.indexOf('[');
129
+ const arrayEnd = cleaned.lastIndexOf(']');
130
+ if (arrayStart !== -1 && arrayEnd > arrayStart) {
131
+ cleaned = cleaned.substring(arrayStart, arrayEnd + 1);
132
+ }
133
+ let parsed;
134
+ try {
135
+ parsed = JSON.parse(cleaned);
136
+ }
137
+ catch (err) {
138
+ throw new Error(`Failed to parse partition schema JSON: ${err.message}`);
139
+ }
140
+ if (!Array.isArray(parsed)) {
141
+ throw new Error('Partition schema must be a JSON array');
142
+ }
143
+ // Validate each entry
144
+ const schema = [];
145
+ for (const entry of parsed) {
146
+ if (typeof entry !== 'object' || entry === null) {
147
+ throw new Error('Each partition entry must be a JSON object');
148
+ }
149
+ const e = entry;
150
+ if (!e.agent_type || typeof e.agent_type !== 'string') {
151
+ throw new Error('Each partition entry must have a string "agent_type"');
152
+ }
153
+ if (!e.focus_area || typeof e.focus_area !== 'string') {
154
+ throw new Error(`Partition entry for "${e.agent_type}" must have a string "focus_area"`);
155
+ }
156
+ if (!Array.isArray(e.excluded_topics)) {
157
+ e.excluded_topics = [];
158
+ }
159
+ schema.push({
160
+ agent_type: e.agent_type,
161
+ focus_area: e.focus_area,
162
+ excluded_topics: e.excluded_topics.map(String),
163
+ });
164
+ }
165
+ return schema;
166
+ }
167
+ // ============================================================================
168
+ // PARTITION PLANNER (OOP interface)
169
+ // ============================================================================
170
+ /**
171
+ * PartitionPlanner generates a PartitionSchema (scope assignment map) for a
172
+ * set of agents before the DAG is executed, preventing redundant research.
173
+ *
174
+ * @example
175
+ * ```typescript
176
+ * const planner = new PartitionPlanner(myLLMPartitionPlannerFn);
177
+ * const result = await planner.plan('Analyse Q3 financial results', agents);
178
+ * // result.schema[0] = { agent_type: 'researcher', focus_area: '...', excluded_topics: [...] }
179
+ * // Inject result.schema[i] as boundary constraint into each agent's params
180
+ * ```
181
+ */
182
+ class PartitionPlanner {
183
+ plannerFn;
184
+ overlapChecker;
185
+ strictOverlap;
186
+ constructor(plannerFn, options = {}) {
187
+ this.plannerFn = plannerFn;
188
+ this.overlapChecker = options.overlapChecker ?? createLexicalOverlapChecker();
189
+ this.strictOverlap = options.strictOverlap ?? false;
190
+ }
191
+ /**
192
+ * Generate a PartitionSchema for a goal and agent list.
193
+ *
194
+ * Runs the planner then validates for overlaps. If `strictOverlap` is true
195
+ * and overlaps are found, throws an error. Otherwise overlaps are reported
196
+ * in the result.
197
+ *
198
+ * @param goal - Natural language goal
199
+ * @param agents - Available team agents
200
+ * @param context - Optional context to feed to the planner
201
+ */
202
+ async plan(goal, agents, context) {
203
+ if (!goal || typeof goal !== 'string') {
204
+ throw new Error('Goal must be a non-empty string');
205
+ }
206
+ if (!agents || agents.length === 0) {
207
+ throw new Error('At least one agent is required');
208
+ }
209
+ const schema = await this.plannerFn(goal, agents, context);
210
+ const overlaps = await this.overlapChecker(schema);
211
+ const hasOverlaps = overlaps.length > 0;
212
+ if (hasOverlaps && this.strictOverlap) {
213
+ throw new Error(`Partition schema has semantic overlaps:\n${overlaps.join('\n')}`);
214
+ }
215
+ return {
216
+ schema,
217
+ overlaps,
218
+ hasOverlaps,
219
+ createdAt: Date.now(),
220
+ };
221
+ }
222
+ /**
223
+ * Inject partition boundary constraints into agent params.
224
+ *
225
+ * Given a PartitionSchema and an existing params object for an agent,
226
+ * returns a new params object with `_partitionConstraint` added.
227
+ *
228
+ * @param agentId - Agent ID to look up in the schema
229
+ * @param params - Existing task params
230
+ * @param schema - The partition schema
231
+ */
232
+ static injectConstraint(agentId, params, schema) {
233
+ const entry = schema.find((e) => e.agent_type === agentId);
234
+ if (!entry)
235
+ return params;
236
+ return {
237
+ ...params,
238
+ _partitionConstraint: {
239
+ focus_area: entry.focus_area,
240
+ excluded_topics: entry.excluded_topics,
241
+ },
242
+ };
243
+ }
244
+ }
245
+ exports.PartitionPlanner = PartitionPlanner;
246
+ //# sourceMappingURL=partition-planner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"partition-planner.js","sourceRoot":"","sources":["../../lib/partition-planner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Route Classifier — Short-Circuit Routing for Network-AI
3
+ *
4
+ * Classifies an incoming goal into one of three categories before any
5
+ * DAG planning occurs. Simple factual lookups are routed directly to a
6
+ * single agent, bypassing the Blackboard/locking layer entirely to save
7
+ * latency and token cost. Complex synthesis uses the full DAG pipeline.
8
+ * System failures are surfaced immediately.
9
+ *
10
+ * Zero external dependencies — the classifier function is pluggable so
11
+ * callers can use any model (Haiku, Llama-3-8B, rule-based heuristic, …).
12
+ *
13
+ * @module RouteClassifier
14
+ * @version 1.0.0
15
+ */
16
+ /** The three routing categories. */
17
+ export type RouteCategory = 'FACTUAL_LOOKUP' | 'COMPLEX_SYNTHESIS' | 'SYSTEM_FAILURE';
18
+ /** Result produced by the classifier. */
19
+ export interface ClassificationResult {
20
+ /** The routing decision. */
21
+ category: RouteCategory;
22
+ /** Human-readable explanation from the classifier. */
23
+ rationale: string;
24
+ /** Confidence score 0–1 (optional — classifiers may omit this). */
25
+ confidence?: number;
26
+ /** When classification completed (epoch ms). */
27
+ classifiedAt: number;
28
+ }
29
+ /**
30
+ * A function that classifies a goal string.
31
+ *
32
+ * Implement this with a fast model call, a rule-based heuristic, or a
33
+ * combination. Must resolve — never reject — returning SYSTEM_FAILURE
34
+ * instead of throwing when the input is unclassifiable.
35
+ */
36
+ export type ClassifierFunction = (goal: string) => Promise<ClassificationResult>;
37
+ /**
38
+ * Result of a routed execution attempt (FACTUAL_LOOKUP path).
39
+ * For COMPLEX_SYNTHESIS the caller handles execution via the normal DAG pipeline.
40
+ */
41
+ export interface RouteResult {
42
+ /** The classification that drove this route. */
43
+ classification: ClassificationResult;
44
+ /** True when the request was short-circuited (FACTUAL_LOOKUP). */
45
+ shortCircuited: boolean;
46
+ /** Agent output for the short-circuit path, undefined otherwise. */
47
+ answer?: unknown;
48
+ /** Error message for SYSTEM_FAILURE. */
49
+ error?: string;
50
+ }
51
+ /** Options for {@link RouteClassifier}. */
52
+ export interface RouteClassifierOptions {
53
+ /**
54
+ * Agent ID to call for FACTUAL_LOOKUP responses.
55
+ * Required when `executor` is provided.
56
+ */
57
+ lookupAgentId?: string;
58
+ }
59
+ /**
60
+ * A simple keyword / length heuristic classifier for when you don't want to
61
+ * spend tokens on a model call for every request.
62
+ *
63
+ * Treats goals of ≤ 15 words with question-like phrasing as FACTUAL_LOOKUP
64
+ * and everything else as COMPLEX_SYNTHESIS.
65
+ */
66
+ export declare function createHeuristicClassifier(): ClassifierFunction;
67
+ /**
68
+ * Build a classifier backed by an LLM via the Network-AI executor API.
69
+ *
70
+ * @param executor - The executor function from the adapter system
71
+ * @param classifierAgentId - Agent ID for the fast classification model
72
+ */
73
+ export declare function createLLMClassifier(executor: (agentId: string, payload: {
74
+ action: string;
75
+ params: Record<string, unknown>;
76
+ }, context: {
77
+ agentId: string;
78
+ taskId: string;
79
+ metadata?: Record<string, unknown>;
80
+ }) => Promise<{
81
+ success: boolean;
82
+ data?: unknown;
83
+ error?: {
84
+ message: string;
85
+ };
86
+ }>, classifierAgentId: string): ClassifierFunction;
87
+ /**
88
+ * RouteClassifier evaluates a goal before DAG planning begins and decides
89
+ * whether to short-circuit to a single agent (FACTUAL_LOOKUP) or proceed
90
+ * with the full multi-agent pipeline (COMPLEX_SYNTHESIS).
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * const classifier = new RouteClassifier(createHeuristicClassifier());
95
+ * const { category } = await classifier.classify('What is the capital of France?');
96
+ * // category === 'FACTUAL_LOOKUP'
97
+ * ```
98
+ */
99
+ export declare class RouteClassifier {
100
+ private classifierFn;
101
+ private options;
102
+ constructor(classifierFn: ClassifierFunction, options?: RouteClassifierOptions);
103
+ /**
104
+ * Classify a goal.
105
+ */
106
+ classify(goal: string): Promise<ClassificationResult>;
107
+ /**
108
+ * Classify a goal and, if FACTUAL_LOOKUP, short-circuit to a single agent.
109
+ *
110
+ * Returns the classification result and, when short-circuited, the agent's
111
+ * direct answer. The caller should check `result.shortCircuited` — if false,
112
+ * proceed with the normal DAG pipeline.
113
+ *
114
+ * @param goal - Natural language goal
115
+ * @param executor - Agent executor (required for FACTUAL_LOOKUP short-circuit)
116
+ * @param fallbackAgentId - Agent to call on FACTUAL_LOOKUP (overrides options.lookupAgentId)
117
+ */
118
+ route(goal: string, executor?: (agentId: string, payload: {
119
+ action: string;
120
+ params: Record<string, unknown>;
121
+ }, context: {
122
+ agentId: string;
123
+ taskId: string;
124
+ metadata?: Record<string, unknown>;
125
+ }) => Promise<{
126
+ success: boolean;
127
+ data?: unknown;
128
+ error?: {
129
+ message: string;
130
+ };
131
+ }>, fallbackAgentId?: string): Promise<RouteResult>;
132
+ }
133
+ //# sourceMappingURL=route-classifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-classifier.d.ts","sourceRoot":"","sources":["../../lib/route-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,oCAAoC;AACpC,MAAM,MAAM,aAAa,GACrB,gBAAgB,GAChB,mBAAmB,GACnB,gBAAgB,CAAC;AAErB,yCAAyC;AACzC,MAAM,WAAW,oBAAoB;IACnC,4BAA4B;IAC5B,QAAQ,EAAE,aAAa,CAAC;IACxB,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAEjF;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,gDAAgD;IAChD,cAAc,EAAE,oBAAoB,CAAC;IACrC,kEAAkE;IAClE,cAAc,EAAE,OAAO,CAAC;IACxB,oEAAoE;IACpE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,2CAA2C;AAC3C,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAMD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,IAAI,kBAAkB,CAwC9D;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,CACR,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,EAC5D,OAAO,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,KAC7E,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC,EAC/E,iBAAiB,EAAE,MAAM,GACxB,kBAAkB,CAkEpB;AAMD;;;;;;;;;;;GAWG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,OAAO,CAAyB;gBAE5B,YAAY,EAAE,kBAAkB,EAAE,OAAO,GAAE,sBAA2B;IAKlF;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAY3D;;;;;;;;;;OAUG;IACG,KAAK,CACT,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,CACT,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,EAC5D,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,KAC7E,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE;YAAE,OAAO,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,EAC/E,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,WAAW,CAAC;CA2CxB"}
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ /**
3
+ * Route Classifier — Short-Circuit Routing for Network-AI
4
+ *
5
+ * Classifies an incoming goal into one of three categories before any
6
+ * DAG planning occurs. Simple factual lookups are routed directly to a
7
+ * single agent, bypassing the Blackboard/locking layer entirely to save
8
+ * latency and token cost. Complex synthesis uses the full DAG pipeline.
9
+ * System failures are surfaced immediately.
10
+ *
11
+ * Zero external dependencies — the classifier function is pluggable so
12
+ * callers can use any model (Haiku, Llama-3-8B, rule-based heuristic, …).
13
+ *
14
+ * @module RouteClassifier
15
+ * @version 1.0.0
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.RouteClassifier = void 0;
19
+ exports.createHeuristicClassifier = createHeuristicClassifier;
20
+ exports.createLLMClassifier = createLLMClassifier;
21
+ // ============================================================================
22
+ // RULE-BASED HEURISTIC CLASSIFIER (built-in, zero model cost)
23
+ // ============================================================================
24
+ /**
25
+ * A simple keyword / length heuristic classifier for when you don't want to
26
+ * spend tokens on a model call for every request.
27
+ *
28
+ * Treats goals of ≤ 15 words with question-like phrasing as FACTUAL_LOOKUP
29
+ * and everything else as COMPLEX_SYNTHESIS.
30
+ */
31
+ function createHeuristicClassifier() {
32
+ const LOOKUP_STARTERS = [
33
+ 'what is', 'what are', 'who is', 'who are', 'when is', 'when was',
34
+ 'where is', 'where was', 'how many', 'how much', 'define ', 'list ',
35
+ 'name ', 'tell me', 'give me', 'show me',
36
+ ];
37
+ return async (goal) => {
38
+ const normalized = goal.trim().toLowerCase();
39
+ if (!normalized) {
40
+ return {
41
+ category: 'SYSTEM_FAILURE',
42
+ rationale: 'Goal is empty',
43
+ confidence: 1,
44
+ classifiedAt: Date.now(),
45
+ };
46
+ }
47
+ const wordCount = normalized.split(/\s+/).length;
48
+ const isShort = wordCount <= 15;
49
+ const startsLikeQuestion = LOOKUP_STARTERS.some((s) => normalized.startsWith(s));
50
+ const endsWithQuestion = normalized.endsWith('?');
51
+ if (isShort && (startsLikeQuestion || endsWithQuestion)) {
52
+ return {
53
+ category: 'FACTUAL_LOOKUP',
54
+ rationale: `Short goal (${wordCount} words) with question-like phrasing.`,
55
+ confidence: 0.8,
56
+ classifiedAt: Date.now(),
57
+ };
58
+ }
59
+ return {
60
+ category: 'COMPLEX_SYNTHESIS',
61
+ rationale: `Goal requires multi-step reasoning (${wordCount} words).`,
62
+ confidence: 0.75,
63
+ classifiedAt: Date.now(),
64
+ };
65
+ };
66
+ }
67
+ /**
68
+ * Build a classifier backed by an LLM via the Network-AI executor API.
69
+ *
70
+ * @param executor - The executor function from the adapter system
71
+ * @param classifierAgentId - Agent ID for the fast classification model
72
+ */
73
+ function createLLMClassifier(executor, classifierAgentId) {
74
+ return async (goal) => {
75
+ const prompt = [
76
+ 'Classify the following goal into exactly one category:',
77
+ ' FACTUAL_LOOKUP — simple factual question answerable in one step',
78
+ ' COMPLEX_SYNTHESIS — requires multi-step research/reasoning/execution',
79
+ ' SYSTEM_FAILURE — invalid, malformed, or unclassifiable input',
80
+ '',
81
+ `GOAL: ${goal}`,
82
+ '',
83
+ 'Respond with ONLY valid JSON matching this schema:',
84
+ '{"category":"FACTUAL_LOOKUP|COMPLEX_SYNTHESIS|SYSTEM_FAILURE","rationale":"...","confidence":0.0-1.0}',
85
+ ].join('\n');
86
+ try {
87
+ const result = await executor(classifierAgentId, { action: 'classify', params: { prompt } }, { agentId: classifierAgentId, taskId: `classify-${Date.now()}`, metadata: { type: 'route-classification' } });
88
+ if (!result.success || !result.data) {
89
+ return {
90
+ category: 'COMPLEX_SYNTHESIS',
91
+ rationale: 'Classifier returned no data — defaulting to COMPLEX_SYNTHESIS',
92
+ confidence: 0.5,
93
+ classifiedAt: Date.now(),
94
+ };
95
+ }
96
+ // Parse response
97
+ let parsed;
98
+ const raw = typeof result.data === 'string' ? result.data : JSON.stringify(result.data);
99
+ try {
100
+ // Strip markdown fences
101
+ const cleaned = raw.replace(/```[a-z]*\n?/g, '').replace(/```/g, '').trim();
102
+ const start = cleaned.indexOf('{');
103
+ const end = cleaned.lastIndexOf('}');
104
+ parsed = JSON.parse(cleaned.substring(start, end + 1));
105
+ }
106
+ catch {
107
+ return {
108
+ category: 'COMPLEX_SYNTHESIS',
109
+ rationale: 'Classifier response parse failed — defaulting to COMPLEX_SYNTHESIS',
110
+ confidence: 0.4,
111
+ classifiedAt: Date.now(),
112
+ };
113
+ }
114
+ const validCategories = ['FACTUAL_LOOKUP', 'COMPLEX_SYNTHESIS', 'SYSTEM_FAILURE'];
115
+ const category = validCategories.includes(parsed.category) ? parsed.category : 'COMPLEX_SYNTHESIS';
116
+ return {
117
+ category,
118
+ rationale: parsed.rationale ?? '',
119
+ confidence: typeof parsed.confidence === 'number' ? Math.min(1, Math.max(0, parsed.confidence)) : undefined,
120
+ classifiedAt: Date.now(),
121
+ };
122
+ }
123
+ catch (err) {
124
+ return {
125
+ category: 'COMPLEX_SYNTHESIS',
126
+ rationale: `Classifier error (${err.message}) — defaulting to COMPLEX_SYNTHESIS`,
127
+ confidence: 0.3,
128
+ classifiedAt: Date.now(),
129
+ };
130
+ }
131
+ };
132
+ }
133
+ // ============================================================================
134
+ // ROUTE CLASSIFIER
135
+ // ============================================================================
136
+ /**
137
+ * RouteClassifier evaluates a goal before DAG planning begins and decides
138
+ * whether to short-circuit to a single agent (FACTUAL_LOOKUP) or proceed
139
+ * with the full multi-agent pipeline (COMPLEX_SYNTHESIS).
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * const classifier = new RouteClassifier(createHeuristicClassifier());
144
+ * const { category } = await classifier.classify('What is the capital of France?');
145
+ * // category === 'FACTUAL_LOOKUP'
146
+ * ```
147
+ */
148
+ class RouteClassifier {
149
+ classifierFn;
150
+ options;
151
+ constructor(classifierFn, options = {}) {
152
+ this.classifierFn = classifierFn;
153
+ this.options = options;
154
+ }
155
+ /**
156
+ * Classify a goal.
157
+ */
158
+ async classify(goal) {
159
+ if (!goal || typeof goal !== 'string') {
160
+ return {
161
+ category: 'SYSTEM_FAILURE',
162
+ rationale: 'Goal must be a non-empty string',
163
+ confidence: 1,
164
+ classifiedAt: Date.now(),
165
+ };
166
+ }
167
+ return this.classifierFn(goal);
168
+ }
169
+ /**
170
+ * Classify a goal and, if FACTUAL_LOOKUP, short-circuit to a single agent.
171
+ *
172
+ * Returns the classification result and, when short-circuited, the agent's
173
+ * direct answer. The caller should check `result.shortCircuited` — if false,
174
+ * proceed with the normal DAG pipeline.
175
+ *
176
+ * @param goal - Natural language goal
177
+ * @param executor - Agent executor (required for FACTUAL_LOOKUP short-circuit)
178
+ * @param fallbackAgentId - Agent to call on FACTUAL_LOOKUP (overrides options.lookupAgentId)
179
+ */
180
+ async route(goal, executor, fallbackAgentId) {
181
+ const classification = await this.classify(goal);
182
+ if (classification.category === 'SYSTEM_FAILURE') {
183
+ return {
184
+ classification,
185
+ shortCircuited: true,
186
+ error: `System failure: ${classification.rationale}`,
187
+ };
188
+ }
189
+ if (classification.category === 'FACTUAL_LOOKUP') {
190
+ const agentId = fallbackAgentId ?? this.options.lookupAgentId;
191
+ if (!executor || !agentId) {
192
+ // No executor configured — fall through to DAG pipeline
193
+ return { classification, shortCircuited: false };
194
+ }
195
+ try {
196
+ const result = await executor(agentId, { action: 'answer', params: { goal } }, { agentId, taskId: `lookup-${Date.now()}`, metadata: { type: 'factual-lookup' } });
197
+ return {
198
+ classification,
199
+ shortCircuited: true,
200
+ answer: result.data,
201
+ error: result.success ? undefined : result.error?.message,
202
+ };
203
+ }
204
+ catch (err) {
205
+ return {
206
+ classification,
207
+ shortCircuited: true,
208
+ error: err.message,
209
+ };
210
+ }
211
+ }
212
+ // COMPLEX_SYNTHESIS — proceed with DAG
213
+ return { classification, shortCircuited: false };
214
+ }
215
+ }
216
+ exports.RouteClassifier = RouteClassifier;
217
+ //# sourceMappingURL=route-classifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-classifier.js","sourceRoot":"","sources":["../../lib/route-classifier.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "network-ai",
3
- "version": "5.2.2",
3
+ "version": "5.3.0",
4
4
  "description": "AI agent orchestration framework for TypeScript/Node.js - 29 adapters (LangChain, AutoGen, CrewAI, OpenAI Assistants, LlamaIndex, Semantic Kernel, Haystack, DSPy, Agno, MCP, OpenClaw, A2A, Codex, MiniMax, NemoClaw, APS, Copilot, LangGraph, Anthropic Computer Use, OpenAI Agents SDK, Vertex AI, Pydantic AI, Browser Agent, Hermes, Orchestrator, RLM + streaming variants). Built-in CLI, security, swarm intelligence, real-time streaming, and agentic workflow patterns.",
5
5
  "homepage": "https://network-ai.org",
6
6
  "main": "dist/index.js",
@@ -40,6 +40,7 @@
40
40
  "test:phase9": "npx ts-node test-phase9.ts",
41
41
  "test:phase10": "npx ts-node test-phase10.ts",
42
42
  "test:topology": "npx ts-node test-topology.ts",
43
+ "test:phase12": "npx ts-node test-phase12.ts",
43
44
  "test:all": "npx ts-node run-tests.ts",
44
45
  "setup": "npx ts-node setup.ts",
45
46
  "setup:check": "npx ts-node setup.ts --check",
@@ -103,7 +104,7 @@
103
104
  "devDependencies": {
104
105
  "@types/node": "^25.6.0",
105
106
  "dotenv": "^17.4.2",
106
- "openai": "^6.34.0",
107
+ "openai": "^6.36.0",
107
108
  "ts-node": "^10.9.2",
108
109
  "typescript": "^6.0.3"
109
110
  },
package/socket.json CHANGED
@@ -1,4 +1,4 @@
1
- {
1
+ {
2
2
  "version": 2,
3
3
  "ignore": {
4
4
  "evalDynamicCodeExecution": [