agentic-flow 3.1.0 → 3.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.
- package/.agents/skills/agentic-flow-ecosystem/SKILL.md +51 -0
- package/.claude/skills/agentic-flow-ecosystem/skill.md +59 -0
- package/.claude/skills/agentic-flow-quickstart/skill.md +6 -6
- package/.claude/skills/hooks-automation/skill.md +11 -11
- package/.claude/skills/memory-patterns/skill.md +7 -7
- package/.claude/skills/sparc-methodology/skill.md +13 -13
- package/.claude/skills/swarm-coordination/skill.md +5 -5
- package/.claude/skills/worker-benchmarks/skill.md +5 -5
- package/.claude/skills/worker-integration/skill.md +5 -5
- package/CHANGELOG.md +50 -0
- package/README.md +82 -67
- package/dist/.tsbuildinfo +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +9 -0
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/config/claudeFlow.d.ts +1 -1
- package/dist/core/agentdb-fast.d.ts +21 -11
- package/dist/core/agentdb-fast.d.ts.map +1 -1
- package/dist/core/agentdb-fast.js +39 -14
- package/dist/core/agentdb-fast.js.map +1 -1
- package/dist/integrations/agent-booster.d.ts +35 -0
- package/dist/integrations/agent-booster.d.ts.map +1 -0
- package/dist/integrations/agent-booster.js +45 -0
- package/dist/integrations/agent-booster.js.map +1 -0
- package/dist/integrations/index.d.ts +15 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +11 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/integrations/onnx-wasm-embedder.d.ts +59 -0
- package/dist/integrations/onnx-wasm-embedder.d.ts.map +1 -0
- package/dist/integrations/onnx-wasm-embedder.js +145 -0
- package/dist/integrations/onnx-wasm-embedder.js.map +1 -0
- package/dist/integrations/optional.d.ts +32 -0
- package/dist/integrations/optional.d.ts.map +1 -0
- package/dist/integrations/optional.js +83 -0
- package/dist/integrations/optional.js.map +1 -0
- package/dist/integrations/prompt-injection.d.ts +52 -0
- package/dist/integrations/prompt-injection.d.ts.map +1 -0
- package/dist/integrations/prompt-injection.js +126 -0
- package/dist/integrations/prompt-injection.js.map +1 -0
- package/dist/integrations/sublinear.d.ts +99 -0
- package/dist/integrations/sublinear.d.ts.map +1 -0
- package/dist/integrations/sublinear.js +303 -0
- package/dist/integrations/sublinear.js.map +1 -0
- package/dist/integrations/task-partition.d.ts +40 -0
- package/dist/integrations/task-partition.d.ts.map +1 -0
- package/dist/integrations/task-partition.js +173 -0
- package/dist/integrations/task-partition.js.map +1 -0
- package/dist/intelligence/RuVectorIntelligence.d.ts.map +1 -1
- package/dist/intelligence/RuVectorIntelligence.js +4 -3
- package/dist/intelligence/RuVectorIntelligence.js.map +1 -1
- package/dist/mcp/mcp-policy.d.ts.map +1 -1
- package/dist/mcp/mcp-policy.js +2 -0
- package/dist/mcp/mcp-policy.js.map +1 -1
- package/dist/mcp/standalone-stdio.js +12 -26
- package/dist/mcp/standalone-stdio.js.map +1 -1
- package/dist/mcp/tools/ecosystem-tools.d.ts +49 -0
- package/dist/mcp/tools/ecosystem-tools.d.ts.map +1 -0
- package/dist/mcp/tools/ecosystem-tools.js +148 -0
- package/dist/mcp/tools/ecosystem-tools.js.map +1 -0
- package/dist/optimizations/configuration-tuning.d.ts +1 -1
- package/dist/routing/SemanticRouter.d.ts +25 -9
- package/dist/routing/SemanticRouter.d.ts.map +1 -1
- package/dist/routing/SemanticRouter.js +63 -12
- package/dist/routing/SemanticRouter.js.map +1 -1
- package/dist/services/sona-loader.d.ts +15 -1
- package/dist/services/sona-loader.d.ts.map +1 -1
- package/dist/services/sona-loader.js +54 -2
- package/dist/services/sona-loader.js.map +1 -1
- package/dist/utils/input-validator.d.ts +10 -2
- package/dist/utils/input-validator.d.ts.map +1 -1
- package/dist/utils/input-validator.js +30 -2
- package/dist/utils/input-validator.js.map +1 -1
- package/dist/utils/model-cache.d.ts.map +1 -1
- package/dist/utils/model-cache.js +6 -25
- package/dist/utils/model-cache.js.map +1 -1
- package/dist/wasm/onnx-embeddings-wasm.d.ts.map +1 -1
- package/dist/wasm/onnx-embeddings-wasm.js +21 -10
- package/dist/wasm/onnx-embeddings-wasm.js.map +1 -1
- package/docs/integrations/FASTMCP_CLI_INTEGRATION.md +1 -1
- package/package.json +13 -8
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linear solves and PageRank through `@ruvnet/sublinear-core`, verified.
|
|
3
|
+
*
|
|
4
|
+
* @ruvnet/sublinear-core (optionalDependency, zero dependencies, ~220 kB) is
|
|
5
|
+
* the embeddable core of sublinear-time-solver: sparse iterative solvers
|
|
6
|
+
* (Gauss-Seidel, conjugate gradient, Jacobi, Neumann), PageRank, personalized
|
|
7
|
+
* PageRank and local forward push. It reports the residual of the x it
|
|
8
|
+
* returns, but every answer is still checked here against ||Mx - b||_inf, and
|
|
9
|
+
* a built-in Gauss-Seidel solve replaces it when the check fails or the
|
|
10
|
+
* package is not installed.
|
|
11
|
+
*
|
|
12
|
+
* The 5 bundled `sublinear/*` agents name sublinear-time-solver tools; the
|
|
13
|
+
* `sublinear_solve` / `sublinear_pagerank` MCP tools in this package give them
|
|
14
|
+
* a working in-process path without a separate MCP server.
|
|
15
|
+
*/
|
|
16
|
+
export declare const SUBLINEAR_CORE = "@ruvnet/sublinear-core";
|
|
17
|
+
export interface SparseEntry {
|
|
18
|
+
row: number;
|
|
19
|
+
col: number;
|
|
20
|
+
value: number;
|
|
21
|
+
}
|
|
22
|
+
export type MatrixInput = number[][] | {
|
|
23
|
+
size: number;
|
|
24
|
+
entries: SparseEntry[];
|
|
25
|
+
};
|
|
26
|
+
export type SolveMethod = 'auto' | 'gauss-seidel' | 'conjugate-gradient' | 'jacobi' | 'neumann';
|
|
27
|
+
export type SublinearEngine = 'sublinear-core' | 'builtin';
|
|
28
|
+
export interface LinearSolveResult {
|
|
29
|
+
solution: number[];
|
|
30
|
+
/** max_i |(Mx - b)_i|, recomputed here from the returned solution. */
|
|
31
|
+
residual: number;
|
|
32
|
+
converged: boolean;
|
|
33
|
+
iterations: number;
|
|
34
|
+
diagonallyDominant: boolean;
|
|
35
|
+
engine: SublinearEngine;
|
|
36
|
+
/** Method that produced the solution. */
|
|
37
|
+
method: Exclude<SolveMethod, 'auto'>;
|
|
38
|
+
/** Set when the library answered but failed verification. */
|
|
39
|
+
libraryRejected?: string;
|
|
40
|
+
}
|
|
41
|
+
/** The core module, or null when it is not installed. */
|
|
42
|
+
export declare function loadSublinearCore(): Promise<any | null>;
|
|
43
|
+
/**
|
|
44
|
+
* Solve Mx = b. Intended for (row) diagonally dominant or symmetric positive
|
|
45
|
+
* definite M; other matrices are attempted with Gauss-Seidel and reported with
|
|
46
|
+
* `converged: false` if it fails.
|
|
47
|
+
*/
|
|
48
|
+
export declare function solveLinearSystem(matrix: MatrixInput, b: number[], options?: {
|
|
49
|
+
tolerance?: number;
|
|
50
|
+
maxIterations?: number;
|
|
51
|
+
method?: SolveMethod;
|
|
52
|
+
engine?: 'auto' | 'builtin';
|
|
53
|
+
}): Promise<LinearSolveResult>;
|
|
54
|
+
export interface PageRankEdge {
|
|
55
|
+
from: string;
|
|
56
|
+
to: string;
|
|
57
|
+
weight?: number;
|
|
58
|
+
}
|
|
59
|
+
export interface PageRankOptions {
|
|
60
|
+
/** Probability of following an out-edge (1 - restart probability). Default 0.85. */
|
|
61
|
+
damping?: number;
|
|
62
|
+
/** Extra nodes with no edges. */
|
|
63
|
+
nodes?: string[];
|
|
64
|
+
/** Personalized PageRank: restart at these nodes (equal weight) or by weight. */
|
|
65
|
+
seeds?: string[] | Record<string, number>;
|
|
66
|
+
/**
|
|
67
|
+
* With `seeds`: estimate by local forward push instead of power iteration.
|
|
68
|
+
* Work depends on `epsilon`, not on the graph size; scores of nodes far from
|
|
69
|
+
* the seeds are left at 0 and `residualMass` bounds the total L1 error.
|
|
70
|
+
*/
|
|
71
|
+
approximate?: boolean;
|
|
72
|
+
/** Forward-push residual threshold. Default 1e-6. */
|
|
73
|
+
epsilon?: number;
|
|
74
|
+
/** Return only the top N in `ranking` (and `scores`, for approximate runs). */
|
|
75
|
+
top?: number;
|
|
76
|
+
engine?: 'auto' | 'builtin';
|
|
77
|
+
}
|
|
78
|
+
export interface PageRankResult {
|
|
79
|
+
scores: Record<string, number>;
|
|
80
|
+
ranking: Array<{
|
|
81
|
+
node: string;
|
|
82
|
+
score: number;
|
|
83
|
+
}>;
|
|
84
|
+
engine: SublinearEngine;
|
|
85
|
+
method: 'power-iteration' | 'forward-push' | 'gauss-seidel';
|
|
86
|
+
personalized: boolean;
|
|
87
|
+
/** Linear-system residual (gauss-seidel) or last L1 change (power iteration). */
|
|
88
|
+
residual: number;
|
|
89
|
+
/** forward-push only: unpushed mass, an upper bound on the total L1 error. */
|
|
90
|
+
residualMass?: number;
|
|
91
|
+
/** Set when the library answered but failed verification. */
|
|
92
|
+
libraryRejected?: string;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* PageRank over a directed graph, or personalized PageRank from `seeds`.
|
|
96
|
+
* Scores sum to 1 (approximate runs: to 1 - residualMass).
|
|
97
|
+
*/
|
|
98
|
+
export declare function pageRank(edges: PageRankEdge[], options?: PageRankOptions): Promise<PageRankResult>;
|
|
99
|
+
//# sourceMappingURL=sublinear.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sublinear.d.ts","sourceRoot":"","sources":["../../src/integrations/sublinear.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linear solves and PageRank through `@ruvnet/sublinear-core`, verified.
|
|
3
|
+
*
|
|
4
|
+
* @ruvnet/sublinear-core (optionalDependency, zero dependencies, ~220 kB) is
|
|
5
|
+
* the embeddable core of sublinear-time-solver: sparse iterative solvers
|
|
6
|
+
* (Gauss-Seidel, conjugate gradient, Jacobi, Neumann), PageRank, personalized
|
|
7
|
+
* PageRank and local forward push. It reports the residual of the x it
|
|
8
|
+
* returns, but every answer is still checked here against ||Mx - b||_inf, and
|
|
9
|
+
* a built-in Gauss-Seidel solve replaces it when the check fails or the
|
|
10
|
+
* package is not installed.
|
|
11
|
+
*
|
|
12
|
+
* The 5 bundled `sublinear/*` agents name sublinear-time-solver tools; the
|
|
13
|
+
* `sublinear_solve` / `sublinear_pagerank` MCP tools in this package give them
|
|
14
|
+
* a working in-process path without a separate MCP server.
|
|
15
|
+
*/
|
|
16
|
+
import { importOptional } from './optional.js';
|
|
17
|
+
export const SUBLINEAR_CORE = '@ruvnet/sublinear-core';
|
|
18
|
+
function toCsr(m) {
|
|
19
|
+
if (Array.isArray(m)) {
|
|
20
|
+
const n = m.length;
|
|
21
|
+
const rows = m.map((row, i) => {
|
|
22
|
+
if (!Array.isArray(row) || row.length !== n)
|
|
23
|
+
throw new Error(`matrix must be square; row ${i} has ${row?.length}`);
|
|
24
|
+
const out = [];
|
|
25
|
+
row.forEach((v, j) => {
|
|
26
|
+
if (!Number.isFinite(v))
|
|
27
|
+
throw new Error(`matrix[${i}][${j}] is not finite`);
|
|
28
|
+
if (v !== 0)
|
|
29
|
+
out.push([j, v]);
|
|
30
|
+
});
|
|
31
|
+
return out;
|
|
32
|
+
});
|
|
33
|
+
return { n, rows, diag: m.map((row, i) => row[i]) };
|
|
34
|
+
}
|
|
35
|
+
const n = m.size;
|
|
36
|
+
if (!Number.isInteger(n) || n < 1)
|
|
37
|
+
throw new Error('size must be a positive integer');
|
|
38
|
+
const acc = Array.from({ length: n }, () => new Map());
|
|
39
|
+
for (const { row, col, value } of m.entries) {
|
|
40
|
+
if (!Number.isInteger(row) || !Number.isInteger(col) || row < 0 || col < 0 || row >= n || col >= n) {
|
|
41
|
+
throw new Error(`entry (${row}, ${col}) is outside a ${n}x${n} matrix`);
|
|
42
|
+
}
|
|
43
|
+
if (!Number.isFinite(value))
|
|
44
|
+
throw new Error(`entry (${row}, ${col}) is not finite`);
|
|
45
|
+
acc[row].set(col, (acc[row].get(col) ?? 0) + value);
|
|
46
|
+
}
|
|
47
|
+
const rows = acc.map((r) => [...r.entries()].filter(([, v]) => v !== 0));
|
|
48
|
+
return { n, rows, diag: acc.map((r, i) => r.get(i) ?? 0) };
|
|
49
|
+
}
|
|
50
|
+
function residualInf(a, x, b) {
|
|
51
|
+
let worst = 0;
|
|
52
|
+
for (let i = 0; i < a.n; i++) {
|
|
53
|
+
let s = 0;
|
|
54
|
+
for (const [j, v] of a.rows[i])
|
|
55
|
+
s += v * x[j];
|
|
56
|
+
worst = Math.max(worst, Math.abs(s - b[i]));
|
|
57
|
+
}
|
|
58
|
+
return worst;
|
|
59
|
+
}
|
|
60
|
+
function isDiagonallyDominant(a) {
|
|
61
|
+
return a.rows.every((row, i) => {
|
|
62
|
+
let off = 0;
|
|
63
|
+
for (const [j, v] of row)
|
|
64
|
+
if (j !== i)
|
|
65
|
+
off += Math.abs(v);
|
|
66
|
+
return Math.abs(a.diag[i]) >= off && a.diag[i] !== 0;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
function gaussSeidel(a, b, tol, maxIterations) {
|
|
70
|
+
const x = new Array(a.n).fill(0);
|
|
71
|
+
let it = 0;
|
|
72
|
+
for (; it < maxIterations; it++) {
|
|
73
|
+
for (let i = 0; i < a.n; i++) {
|
|
74
|
+
if (a.diag[i] === 0)
|
|
75
|
+
throw new Error(`zero diagonal at row ${i}: Gauss-Seidel needs a nonzero diagonal`);
|
|
76
|
+
let s = b[i];
|
|
77
|
+
for (const [j, v] of a.rows[i])
|
|
78
|
+
if (j !== i)
|
|
79
|
+
s -= v * x[j];
|
|
80
|
+
x[i] = s / a.diag[i];
|
|
81
|
+
}
|
|
82
|
+
if (residualInf(a, x, b) <= tol)
|
|
83
|
+
return { x, iterations: it + 1 };
|
|
84
|
+
}
|
|
85
|
+
return { x, iterations: it };
|
|
86
|
+
}
|
|
87
|
+
/** The core module, or null when it is not installed. */
|
|
88
|
+
export async function loadSublinearCore() {
|
|
89
|
+
const mod = await importOptional(SUBLINEAR_CORE);
|
|
90
|
+
return typeof mod?.solve === 'function' && typeof mod?.pageRank === 'function' ? mod : null;
|
|
91
|
+
}
|
|
92
|
+
function coreSolve(core, a, b, tol, maxIterations, method) {
|
|
93
|
+
const rowIndices = [];
|
|
94
|
+
const colIndices = [];
|
|
95
|
+
const values = [];
|
|
96
|
+
a.rows.forEach((row, i) => {
|
|
97
|
+
for (const [j, v] of row) {
|
|
98
|
+
rowIndices.push(i);
|
|
99
|
+
colIndices.push(j);
|
|
100
|
+
values.push(v);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
const A = core.csrFromCoo({ rows: a.n, cols: a.n, rowIndices, colIndices, values });
|
|
104
|
+
// Core stops on the relative L2 residual ||b - Ax||_2 / ||b||_2. The local
|
|
105
|
+
// gate is an absolute inf-norm bound, and ||r||_inf <= ||r||_2, so asking
|
|
106
|
+
// core for tol / sqrt(n) keeps every converged core answer inside it.
|
|
107
|
+
return core.solve(A, b, { method, tolerance: tol / Math.sqrt(a.n), maxIterations });
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Solve Mx = b. Intended for (row) diagonally dominant or symmetric positive
|
|
111
|
+
* definite M; other matrices are attempted with Gauss-Seidel and reported with
|
|
112
|
+
* `converged: false` if it fails.
|
|
113
|
+
*/
|
|
114
|
+
export async function solveLinearSystem(matrix, b, options = {}) {
|
|
115
|
+
const a = toCsr(matrix);
|
|
116
|
+
if (!Array.isArray(b) || b.length !== a.n)
|
|
117
|
+
throw new Error(`vector length ${b?.length} != matrix size ${a.n}`);
|
|
118
|
+
if (!b.every(Number.isFinite))
|
|
119
|
+
throw new Error('vector entries must be finite');
|
|
120
|
+
const tol = options.tolerance ?? 1e-8;
|
|
121
|
+
const maxIterations = Math.min(options.maxIterations ?? 10000, 1_000_000);
|
|
122
|
+
// Absolute inf-norm acceptance scaled to the problem: tol on ||b||_inf ~ 1.
|
|
123
|
+
const scale = Math.max(1, ...b.map(Math.abs));
|
|
124
|
+
const accept = tol * scale * 10;
|
|
125
|
+
const diagonallyDominant = isDiagonallyDominant(a);
|
|
126
|
+
let libraryRejected;
|
|
127
|
+
if (options.engine !== 'builtin') {
|
|
128
|
+
const core = await loadSublinearCore();
|
|
129
|
+
if (core) {
|
|
130
|
+
try {
|
|
131
|
+
const r = coreSolve(core, a, b, tol, maxIterations, options.method ?? 'auto');
|
|
132
|
+
const x = Array.from(r.x);
|
|
133
|
+
const residual = residualInf(a, x, b);
|
|
134
|
+
if (r.converged && x.every(Number.isFinite) && residual <= accept) {
|
|
135
|
+
return { solution: x, residual, converged: true, iterations: r.iterations, diagonallyDominant, engine: 'sublinear-core', method: r.method };
|
|
136
|
+
}
|
|
137
|
+
libraryRejected = r.converged
|
|
138
|
+
? `residual ${residual.toExponential(2)} above ${accept.toExponential(2)}`
|
|
139
|
+
: `${r.method} did not converge in ${r.iterations} iterations (relative residual ${Number(r.residual).toExponential(2)})`;
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
libraryRejected = err?.message ?? String(err);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const { x, iterations } = gaussSeidel(a, b, accept, maxIterations);
|
|
147
|
+
const residual = residualInf(a, x, b);
|
|
148
|
+
return {
|
|
149
|
+
solution: x,
|
|
150
|
+
residual,
|
|
151
|
+
converged: residual <= accept,
|
|
152
|
+
iterations,
|
|
153
|
+
diagonallyDominant,
|
|
154
|
+
engine: 'builtin',
|
|
155
|
+
method: 'gauss-seidel',
|
|
156
|
+
...(libraryRejected ? { libraryRejected } : {}),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function indexGraph(edges, options) {
|
|
160
|
+
const ids = new Map();
|
|
161
|
+
const names = [];
|
|
162
|
+
const add = (s) => {
|
|
163
|
+
let i = ids.get(s);
|
|
164
|
+
if (i === undefined) {
|
|
165
|
+
i = names.length;
|
|
166
|
+
ids.set(s, i);
|
|
167
|
+
names.push(s);
|
|
168
|
+
}
|
|
169
|
+
return i;
|
|
170
|
+
};
|
|
171
|
+
for (const n of options.nodes ?? [])
|
|
172
|
+
add(String(n));
|
|
173
|
+
const indexed = [];
|
|
174
|
+
for (const e of edges) {
|
|
175
|
+
const w = e.weight ?? 1;
|
|
176
|
+
if (!Number.isFinite(w) || w < 0)
|
|
177
|
+
throw new Error(`invalid edge weight ${w}`);
|
|
178
|
+
indexed.push([add(String(e.from)), add(String(e.to)), w]);
|
|
179
|
+
}
|
|
180
|
+
const out = Array.from({ length: names.length }, () => new Map());
|
|
181
|
+
for (const [a, b, w] of indexed)
|
|
182
|
+
out[a].set(b, (out[a].get(b) ?? 0) + w);
|
|
183
|
+
let teleport = null;
|
|
184
|
+
if (options.seeds !== undefined) {
|
|
185
|
+
const weights = Array.isArray(options.seeds)
|
|
186
|
+
? options.seeds.map((s) => [String(s), 1])
|
|
187
|
+
: Object.entries(options.seeds);
|
|
188
|
+
if (weights.length === 0)
|
|
189
|
+
throw new Error('seeds must name at least one node');
|
|
190
|
+
teleport = new Array(names.length).fill(0);
|
|
191
|
+
for (const [name, w] of weights) {
|
|
192
|
+
const i = ids.get(name);
|
|
193
|
+
if (i === undefined)
|
|
194
|
+
throw new Error(`unknown seed node ${name}`);
|
|
195
|
+
if (!Number.isFinite(w) || w < 0)
|
|
196
|
+
throw new Error(`invalid seed weight ${w} for ${name}`);
|
|
197
|
+
teleport[i] += w;
|
|
198
|
+
}
|
|
199
|
+
const total = teleport.reduce((s, v) => s + v, 0);
|
|
200
|
+
if (!(total > 0))
|
|
201
|
+
throw new Error('seed weights must not all be zero');
|
|
202
|
+
teleport = teleport.map((v) => v / total);
|
|
203
|
+
}
|
|
204
|
+
return { names, edges: indexed, out, teleport };
|
|
205
|
+
}
|
|
206
|
+
function rank(names, scores, top) {
|
|
207
|
+
const entries = scores instanceof Map ? [...scores] : scores.map((s, i) => [i, s]);
|
|
208
|
+
entries.sort((x, y) => y[1] - x[1] || x[0] - y[0]);
|
|
209
|
+
return (top ? entries.slice(0, top) : entries).map(([i, score]) => ({ node: names[i], score }));
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Built-in PageRank as a linear system: (I - d·Pᵀ) y = v, scores = y / Σy,
|
|
213
|
+
* with v uniform or the seed distribution. With dangling rows left at zero
|
|
214
|
+
* this equals PageRank whose dangling mass follows the teleport vector, which
|
|
215
|
+
* is also what the core computes.
|
|
216
|
+
*/
|
|
217
|
+
async function builtinPageRank(g, d) {
|
|
218
|
+
const n = g.names.length;
|
|
219
|
+
const entries = [];
|
|
220
|
+
for (let i = 0; i < n; i++)
|
|
221
|
+
entries.push({ row: i, col: i, value: 1 });
|
|
222
|
+
g.out.forEach((links, src) => {
|
|
223
|
+
let total = 0;
|
|
224
|
+
for (const w of links.values())
|
|
225
|
+
total += w;
|
|
226
|
+
if (total === 0)
|
|
227
|
+
return;
|
|
228
|
+
for (const [dst, w] of links)
|
|
229
|
+
entries.push({ row: dst, col: src, value: -d * (w / total) });
|
|
230
|
+
});
|
|
231
|
+
const v = g.teleport ?? new Array(n).fill(1);
|
|
232
|
+
const res = await solveLinearSystem({ size: n, entries }, v, { tolerance: 1e-10, engine: 'builtin' });
|
|
233
|
+
const sum = res.solution.reduce((s, x) => s + x, 0) || 1;
|
|
234
|
+
return { scores: res.solution.map((x) => x / sum), residual: res.residual };
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* PageRank over a directed graph, or personalized PageRank from `seeds`.
|
|
238
|
+
* Scores sum to 1 (approximate runs: to 1 - residualMass).
|
|
239
|
+
*/
|
|
240
|
+
export async function pageRank(edges, options = {}) {
|
|
241
|
+
const d = options.damping ?? 0.85;
|
|
242
|
+
if (!(d > 0 && d < 1))
|
|
243
|
+
throw new Error('damping must be in (0, 1)');
|
|
244
|
+
if (options.approximate && options.seeds === undefined) {
|
|
245
|
+
throw new Error('approximate (forward push) needs seeds: it estimates personalized PageRank around them');
|
|
246
|
+
}
|
|
247
|
+
const g = indexGraph(edges, options);
|
|
248
|
+
const n = g.names.length;
|
|
249
|
+
const personalized = g.teleport !== null;
|
|
250
|
+
if (n === 0)
|
|
251
|
+
return { scores: {}, ranking: [], engine: 'builtin', method: 'gauss-seidel', personalized, residual: 0 };
|
|
252
|
+
let libraryRejected;
|
|
253
|
+
const core = options.engine === 'builtin' ? null : await loadSublinearCore();
|
|
254
|
+
if (core) {
|
|
255
|
+
try {
|
|
256
|
+
const graph = core.graphFromEdges(g.edges, { n });
|
|
257
|
+
const seeds = g.teleport ? new Map(g.teleport.flatMap((w, i) => (w > 0 ? [[i, w]] : []))) : null;
|
|
258
|
+
if (options.approximate && seeds) {
|
|
259
|
+
const r = core.forwardPush(graph, seeds, { damping: d, epsilon: options.epsilon ?? 1e-6 });
|
|
260
|
+
let mass = 0;
|
|
261
|
+
for (const s of r.scores.values())
|
|
262
|
+
mass += s;
|
|
263
|
+
// Forward push keeps p + r = 1 exactly; check that the books balance.
|
|
264
|
+
if (r.converged && Math.abs(mass + r.residualMass - 1) <= 1e-6) {
|
|
265
|
+
const ranking = rank(g.names, r.scores, options.top);
|
|
266
|
+
const scores = {};
|
|
267
|
+
for (const { node, score } of ranking)
|
|
268
|
+
scores[node] = score;
|
|
269
|
+
return { scores, ranking, engine: 'sublinear-core', method: 'forward-push', personalized, residual: r.residualMass, residualMass: r.residualMass };
|
|
270
|
+
}
|
|
271
|
+
libraryRejected = r.converged ? `forward push mass ${mass + r.residualMass} != 1` : `forward push stopped after ${r.pushes} pushes`;
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
const opts = { damping: d, tolerance: 1e-12, maxIterations: 10000 };
|
|
275
|
+
const r = seeds ? core.personalizedPageRank(graph, seeds, opts) : core.pageRank(graph, opts);
|
|
276
|
+
const x = Array.from(r.scores);
|
|
277
|
+
const total = x.reduce((s, v) => s + v, 0);
|
|
278
|
+
if (r.converged && x.every((v) => Number.isFinite(v) && v >= 0) && Math.abs(total - 1) <= 1e-8) {
|
|
279
|
+
const scores = {};
|
|
280
|
+
g.names.forEach((name, i) => (scores[name] = x[i]));
|
|
281
|
+
return { scores, ranking: rank(g.names, x, options.top), engine: 'sublinear-core', method: 'power-iteration', personalized, residual: r.delta };
|
|
282
|
+
}
|
|
283
|
+
libraryRejected = r.converged ? `scores sum to ${total}, not 1` : `power iteration did not converge (delta ${r.delta})`;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
catch (err) {
|
|
287
|
+
libraryRejected = err?.message ?? String(err);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
const { scores: x, residual } = await builtinPageRank(g, d);
|
|
291
|
+
const scores = {};
|
|
292
|
+
g.names.forEach((name, i) => (scores[name] = x[i]));
|
|
293
|
+
return {
|
|
294
|
+
scores,
|
|
295
|
+
ranking: rank(g.names, x, options.top),
|
|
296
|
+
engine: 'builtin',
|
|
297
|
+
method: 'gauss-seidel',
|
|
298
|
+
personalized,
|
|
299
|
+
residual,
|
|
300
|
+
...(libraryRejected ? { libraryRejected } : {}),
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
//# sourceMappingURL=sublinear.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sublinear.js","sourceRoot":"","sources":["../../src/integrations/sublinear.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Linear solves and PageRank through `@ruvnet/sublinear-core`, verified.\n *\n * @ruvnet/sublinear-core (optionalDependency, zero dependencies, ~220 kB) is\n * the embeddable core of sublinear-time-solver: sparse iterative solvers\n * (Gauss-Seidel, conjugate gradient, Jacobi, Neumann), PageRank, personalized\n * PageRank and local forward push. It reports the residual of the x it\n * returns, but every answer is still checked here against ||Mx - b||_inf, and\n * a built-in Gauss-Seidel solve replaces it when the check fails or the\n * package is not installed.\n *\n * The 5 bundled `sublinear/*` agents name sublinear-time-solver tools; the\n * `sublinear_solve` / `sublinear_pagerank` MCP tools in this package give them\n * a working in-process path without a separate MCP server.\n */\n\nimport { importOptional } from './optional.js';\n\nexport const SUBLINEAR_CORE = '@ruvnet/sublinear-core';\n\nexport interface SparseEntry {\n row: number;\n col: number;\n value: number;\n}\n\nexport type MatrixInput = number[][] | { size: number; entries: SparseEntry[] };\n\nexport type SolveMethod = 'auto' | 'gauss-seidel' | 'conjugate-gradient' | 'jacobi' | 'neumann';\n\nexport type SublinearEngine = 'sublinear-core' | 'builtin';\n\nexport interface LinearSolveResult {\n solution: number[];\n /** max_i |(Mx - b)_i|, recomputed here from the returned solution. */\n residual: number;\n converged: boolean;\n iterations: number;\n diagonallyDominant: boolean;\n engine: SublinearEngine;\n /** Method that produced the solution. */\n method: Exclude<SolveMethod, 'auto'>;\n /** Set when the library answered but failed verification. */\n libraryRejected?: string;\n}\n\ninterface Csr {\n n: number;\n rows: Array<Array<[number, number]>>; // per row: [col, value]\n diag: number[];\n}\n\nfunction toCsr(m: MatrixInput): Csr {\n if (Array.isArray(m)) {\n const n = m.length;\n const rows = m.map((row, i) => {\n if (!Array.isArray(row) || row.length !== n) throw new Error(`matrix must be square; row ${i} has ${row?.length}`);\n const out: Array<[number, number]> = [];\n row.forEach((v, j) => {\n if (!Number.isFinite(v)) throw new Error(`matrix[${i}][${j}] is not finite`);\n if (v !== 0) out.push([j, v]);\n });\n return out;\n });\n return { n, rows, diag: m.map((row, i) => row[i]) };\n }\n const n = m.size;\n if (!Number.isInteger(n) || n < 1) throw new Error('size must be a positive integer');\n const acc: Array<Map<number, number>> = Array.from({ length: n }, () => new Map());\n for (const { row, col, value } of m.entries) {\n if (!Number.isInteger(row) || !Number.isInteger(col) || row < 0 || col < 0 || row >= n || col >= n) {\n throw new Error(`entry (${row}, ${col}) is outside a ${n}x${n} matrix`);\n }\n if (!Number.isFinite(value)) throw new Error(`entry (${row}, ${col}) is not finite`);\n acc[row].set(col, (acc[row].get(col) ?? 0) + value);\n }\n const rows = acc.map((r) => [...r.entries()].filter(([, v]) => v !== 0));\n return { n, rows, diag: acc.map((r, i) => r.get(i) ?? 0) };\n}\n\nfunction residualInf(a: Csr, x: ArrayLike<number>, b: number[]): number {\n let worst = 0;\n for (let i = 0; i < a.n; i++) {\n let s = 0;\n for (const [j, v] of a.rows[i]) s += v * x[j];\n worst = Math.max(worst, Math.abs(s - b[i]));\n }\n return worst;\n}\n\nfunction isDiagonallyDominant(a: Csr): boolean {\n return a.rows.every((row, i) => {\n let off = 0;\n for (const [j, v] of row) if (j !== i) off += Math.abs(v);\n return Math.abs(a.diag[i]) >= off && a.diag[i] !== 0;\n });\n}\n\nfunction gaussSeidel(a: Csr, b: number[], tol: number, maxIterations: number) {\n const x = new Array(a.n).fill(0);\n let it = 0;\n for (; it < maxIterations; it++) {\n for (let i = 0; i < a.n; i++) {\n if (a.diag[i] === 0) throw new Error(`zero diagonal at row ${i}: Gauss-Seidel needs a nonzero diagonal`);\n let s = b[i];\n for (const [j, v] of a.rows[i]) if (j !== i) s -= v * x[j];\n x[i] = s / a.diag[i];\n }\n if (residualInf(a, x, b) <= tol) return { x, iterations: it + 1 };\n }\n return { x, iterations: it };\n}\n\n/** The core module, or null when it is not installed. */\nexport async function loadSublinearCore(): Promise<any | null> {\n const mod = await importOptional<any>(SUBLINEAR_CORE);\n return typeof mod?.solve === 'function' && typeof mod?.pageRank === 'function' ? mod : null;\n}\n\nfunction coreSolve(core: any, a: Csr, b: number[], tol: number, maxIterations: number, method: SolveMethod) {\n const rowIndices: number[] = [];\n const colIndices: number[] = [];\n const values: number[] = [];\n a.rows.forEach((row, i) => {\n for (const [j, v] of row) {\n rowIndices.push(i);\n colIndices.push(j);\n values.push(v);\n }\n });\n const A = core.csrFromCoo({ rows: a.n, cols: a.n, rowIndices, colIndices, values });\n // Core stops on the relative L2 residual ||b - Ax||_2 / ||b||_2. The local\n // gate is an absolute inf-norm bound, and ||r||_inf <= ||r||_2, so asking\n // core for tol / sqrt(n) keeps every converged core answer inside it.\n return core.solve(A, b, { method, tolerance: tol / Math.sqrt(a.n), maxIterations });\n}\n\n/**\n * Solve Mx = b. Intended for (row) diagonally dominant or symmetric positive\n * definite M; other matrices are attempted with Gauss-Seidel and reported with\n * `converged: false` if it fails.\n */\nexport async function solveLinearSystem(\n matrix: MatrixInput,\n b: number[],\n options: { tolerance?: number; maxIterations?: number; method?: SolveMethod; engine?: 'auto' | 'builtin' } = {},\n): Promise<LinearSolveResult> {\n const a = toCsr(matrix);\n if (!Array.isArray(b) || b.length !== a.n) throw new Error(`vector length ${b?.length} != matrix size ${a.n}`);\n if (!b.every(Number.isFinite)) throw new Error('vector entries must be finite');\n const tol = options.tolerance ?? 1e-8;\n const maxIterations = Math.min(options.maxIterations ?? 10000, 1_000_000);\n // Absolute inf-norm acceptance scaled to the problem: tol on ||b||_inf ~ 1.\n const scale = Math.max(1, ...b.map(Math.abs));\n const accept = tol * scale * 10;\n const diagonallyDominant = isDiagonallyDominant(a);\n\n let libraryRejected: string | undefined;\n if (options.engine !== 'builtin') {\n const core = await loadSublinearCore();\n if (core) {\n try {\n const r = coreSolve(core, a, b, tol, maxIterations, options.method ?? 'auto');\n const x: number[] = Array.from(r.x as Float64Array);\n const residual = residualInf(a, x, b);\n if (r.converged && x.every(Number.isFinite) && residual <= accept) {\n return { solution: x, residual, converged: true, iterations: r.iterations, diagonallyDominant, engine: 'sublinear-core', method: r.method };\n }\n libraryRejected = r.converged\n ? `residual ${residual.toExponential(2)} above ${accept.toExponential(2)}`\n : `${r.method} did not converge in ${r.iterations} iterations (relative residual ${Number(r.residual).toExponential(2)})`;\n } catch (err: any) {\n libraryRejected = err?.message ?? String(err);\n }\n }\n }\n\n const { x, iterations } = gaussSeidel(a, b, accept, maxIterations);\n const residual = residualInf(a, x, b);\n return {\n solution: x,\n residual,\n converged: residual <= accept,\n iterations,\n diagonallyDominant,\n engine: 'builtin',\n method: 'gauss-seidel',\n ...(libraryRejected ? { libraryRejected } : {}),\n };\n}\n\nexport interface PageRankEdge {\n from: string;\n to: string;\n weight?: number;\n}\n\nexport interface PageRankOptions {\n /** Probability of following an out-edge (1 - restart probability). Default 0.85. */\n damping?: number;\n /** Extra nodes with no edges. */\n nodes?: string[];\n /** Personalized PageRank: restart at these nodes (equal weight) or by weight. */\n seeds?: string[] | Record<string, number>;\n /**\n * With `seeds`: estimate by local forward push instead of power iteration.\n * Work depends on `epsilon`, not on the graph size; scores of nodes far from\n * the seeds are left at 0 and `residualMass` bounds the total L1 error.\n */\n approximate?: boolean;\n /** Forward-push residual threshold. Default 1e-6. */\n epsilon?: number;\n /** Return only the top N in `ranking` (and `scores`, for approximate runs). */\n top?: number;\n engine?: 'auto' | 'builtin';\n}\n\nexport interface PageRankResult {\n scores: Record<string, number>;\n ranking: Array<{ node: string; score: number }>;\n engine: SublinearEngine;\n method: 'power-iteration' | 'forward-push' | 'gauss-seidel';\n personalized: boolean;\n /** Linear-system residual (gauss-seidel) or last L1 change (power iteration). */\n residual: number;\n /** forward-push only: unpushed mass, an upper bound on the total L1 error. */\n residualMass?: number;\n /** Set when the library answered but failed verification. */\n libraryRejected?: string;\n}\n\ninterface IndexedGraph {\n names: string[];\n edges: Array<[number, number, number]>;\n out: Array<Map<number, number>>;\n teleport: number[] | null; // normalized seed distribution, null = uniform\n}\n\nfunction indexGraph(edges: PageRankEdge[], options: PageRankOptions): IndexedGraph {\n const ids = new Map<string, number>();\n const names: string[] = [];\n const add = (s: string) => {\n let i = ids.get(s);\n if (i === undefined) {\n i = names.length;\n ids.set(s, i);\n names.push(s);\n }\n return i;\n };\n for (const n of options.nodes ?? []) add(String(n));\n const indexed: Array<[number, number, number]> = [];\n for (const e of edges) {\n const w = e.weight ?? 1;\n if (!Number.isFinite(w) || w < 0) throw new Error(`invalid edge weight ${w}`);\n indexed.push([add(String(e.from)), add(String(e.to)), w]);\n }\n const out: Array<Map<number, number>> = Array.from({ length: names.length }, () => new Map());\n for (const [a, b, w] of indexed) out[a].set(b, (out[a].get(b) ?? 0) + w);\n\n let teleport: number[] | null = null;\n if (options.seeds !== undefined) {\n const weights: Array<[string, number]> = Array.isArray(options.seeds)\n ? options.seeds.map((s) => [String(s), 1])\n : Object.entries(options.seeds);\n if (weights.length === 0) throw new Error('seeds must name at least one node');\n teleport = new Array(names.length).fill(0);\n for (const [name, w] of weights) {\n const i = ids.get(name);\n if (i === undefined) throw new Error(`unknown seed node ${name}`);\n if (!Number.isFinite(w) || w < 0) throw new Error(`invalid seed weight ${w} for ${name}`);\n teleport[i] += w;\n }\n const total = teleport.reduce((s, v) => s + v, 0);\n if (!(total > 0)) throw new Error('seed weights must not all be zero');\n teleport = teleport.map((v) => v / total);\n }\n return { names, edges: indexed, out, teleport };\n}\n\nfunction rank(names: string[], scores: Map<number, number> | number[], top?: number) {\n const entries: Array<[number, number]> = scores instanceof Map ? [...scores] : scores.map((s, i) => [i, s]);\n entries.sort((x, y) => y[1] - x[1] || x[0] - y[0]);\n return (top ? entries.slice(0, top) : entries).map(([i, score]) => ({ node: names[i], score }));\n}\n\n/**\n * Built-in PageRank as a linear system: (I - d·Pᵀ) y = v, scores = y / Σy,\n * with v uniform or the seed distribution. With dangling rows left at zero\n * this equals PageRank whose dangling mass follows the teleport vector, which\n * is also what the core computes.\n */\nasync function builtinPageRank(g: IndexedGraph, d: number) {\n const n = g.names.length;\n const entries: SparseEntry[] = [];\n for (let i = 0; i < n; i++) entries.push({ row: i, col: i, value: 1 });\n g.out.forEach((links, src) => {\n let total = 0;\n for (const w of links.values()) total += w;\n if (total === 0) return;\n for (const [dst, w] of links) entries.push({ row: dst, col: src, value: -d * (w / total) });\n });\n const v = g.teleport ?? new Array(n).fill(1);\n const res = await solveLinearSystem({ size: n, entries }, v, { tolerance: 1e-10, engine: 'builtin' });\n const sum = res.solution.reduce((s, x) => s + x, 0) || 1;\n return { scores: res.solution.map((x) => x / sum), residual: res.residual };\n}\n\n/**\n * PageRank over a directed graph, or personalized PageRank from `seeds`.\n * Scores sum to 1 (approximate runs: to 1 - residualMass).\n */\nexport async function pageRank(edges: PageRankEdge[], options: PageRankOptions = {}): Promise<PageRankResult> {\n const d = options.damping ?? 0.85;\n if (!(d > 0 && d < 1)) throw new Error('damping must be in (0, 1)');\n if (options.approximate && options.seeds === undefined) {\n throw new Error('approximate (forward push) needs seeds: it estimates personalized PageRank around them');\n }\n const g = indexGraph(edges, options);\n const n = g.names.length;\n const personalized = g.teleport !== null;\n if (n === 0) return { scores: {}, ranking: [], engine: 'builtin', method: 'gauss-seidel', personalized, residual: 0 };\n\n let libraryRejected: string | undefined;\n const core = options.engine === 'builtin' ? null : await loadSublinearCore();\n if (core) {\n try {\n const graph = core.graphFromEdges(g.edges, { n });\n const seeds = g.teleport ? new Map(g.teleport.flatMap((w, i) => (w > 0 ? [[i, w] as [number, number]] : []))) : null;\n\n if (options.approximate && seeds) {\n const r = core.forwardPush(graph, seeds, { damping: d, epsilon: options.epsilon ?? 1e-6 });\n let mass = 0;\n for (const s of r.scores.values()) mass += s;\n // Forward push keeps p + r = 1 exactly; check that the books balance.\n if (r.converged && Math.abs(mass + r.residualMass - 1) <= 1e-6) {\n const ranking = rank(g.names, r.scores, options.top);\n const scores: Record<string, number> = {};\n for (const { node, score } of ranking) scores[node] = score;\n return { scores, ranking, engine: 'sublinear-core', method: 'forward-push', personalized, residual: r.residualMass, residualMass: r.residualMass };\n }\n libraryRejected = r.converged ? `forward push mass ${mass + r.residualMass} != 1` : `forward push stopped after ${r.pushes} pushes`;\n } else {\n const opts = { damping: d, tolerance: 1e-12, maxIterations: 10000 };\n const r = seeds ? core.personalizedPageRank(graph, seeds, opts) : core.pageRank(graph, opts);\n const x: number[] = Array.from(r.scores as Float64Array);\n const total = x.reduce((s, v) => s + v, 0);\n if (r.converged && x.every((v) => Number.isFinite(v) && v >= 0) && Math.abs(total - 1) <= 1e-8) {\n const scores: Record<string, number> = {};\n g.names.forEach((name, i) => (scores[name] = x[i]));\n return { scores, ranking: rank(g.names, x, options.top), engine: 'sublinear-core', method: 'power-iteration', personalized, residual: r.delta };\n }\n libraryRejected = r.converged ? `scores sum to ${total}, not 1` : `power iteration did not converge (delta ${r.delta})`;\n }\n } catch (err: any) {\n libraryRejected = err?.message ?? String(err);\n }\n }\n\n const { scores: x, residual } = await builtinPageRank(g, d);\n const scores: Record<string, number> = {};\n g.names.forEach((name, i) => (scores[name] = x[i]));\n return {\n scores,\n ranking: rank(g.names, x, options.top),\n engine: 'builtin',\n method: 'gauss-seidel',\n personalized,\n residual,\n ...(libraryRejected ? { libraryRejected } : {}),\n };\n}\n"]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Split a task-dependency graph into two groups with the least coupling.
|
|
3
|
+
*
|
|
4
|
+
* A global minimum cut over the (undirected, weighted) dependency graph finds
|
|
5
|
+
* the split that severs the fewest/lightest dependencies — the natural seam for
|
|
6
|
+
* handing work to two agent teams so they block on each other least.
|
|
7
|
+
*
|
|
8
|
+
* Engine: `@ruvector/mincut-wasm` (optionalDependency) when installed; a
|
|
9
|
+
* built-in Stoer-Wagner implementation otherwise (O(n^3), capped at
|
|
10
|
+
* BUILTIN_MAX_TASKS). Both are exact, so they agree on the cut weight.
|
|
11
|
+
*
|
|
12
|
+
* A global min cut can be lopsided (one loosely-attached task vs the rest):
|
|
13
|
+
* that is the correct answer to "where is the weakest seam", not a balance
|
|
14
|
+
* guarantee. Tasks with no dependencies have nothing to cut and are reported
|
|
15
|
+
* in `isolated` rather than forced into a side.
|
|
16
|
+
*/
|
|
17
|
+
export interface TaskDependency {
|
|
18
|
+
from: string;
|
|
19
|
+
to: string;
|
|
20
|
+
/** Coupling strength, default 1. Must be finite and >= 0. */
|
|
21
|
+
weight?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface TaskPartition {
|
|
24
|
+
groups: [string[], string[]];
|
|
25
|
+
/** Tasks that have no dependencies at all. */
|
|
26
|
+
isolated: string[];
|
|
27
|
+
/** Sum of weights of the dependencies crossing between the groups. */
|
|
28
|
+
cutWeight: number;
|
|
29
|
+
cutEdges: Array<{
|
|
30
|
+
from: string;
|
|
31
|
+
to: string;
|
|
32
|
+
weight: number;
|
|
33
|
+
}>;
|
|
34
|
+
engine: 'mincut-wasm' | 'builtin';
|
|
35
|
+
}
|
|
36
|
+
export declare const BUILTIN_MAX_TASKS = 400;
|
|
37
|
+
export declare function partitionTaskGraph(tasks: string[], dependencies: TaskDependency[], options?: {
|
|
38
|
+
engine?: 'auto' | 'builtin';
|
|
39
|
+
}): Promise<TaskPartition>;
|
|
40
|
+
//# sourceMappingURL=task-partition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-partition.d.ts","sourceRoot":"","sources":["../../src/integrations/task-partition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7B,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9D,MAAM,EAAE,aAAa,GAAG,SAAS,CAAC;CACnC;AAED,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAmGrC,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EAAE,EACf,YAAY,EAAE,cAAc,EAAE,EAC9B,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAO,GAC5C,OAAO,CAAC,aAAa,CAAC,CAkExB"}
|