agentic-flow 3.0.0 → 3.2.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.
Files changed (115) hide show
  1. package/.agents/skills/agentic-flow-ecosystem/SKILL.md +50 -0
  2. package/.claude/skills/agentic-flow-ecosystem/skill.md +58 -0
  3. package/.claude/skills/agentic-flow-quickstart/skill.md +6 -6
  4. package/.claude/skills/hooks-automation/skill.md +11 -11
  5. package/.claude/skills/memory-patterns/skill.md +7 -7
  6. package/.claude/skills/sparc-methodology/skill.md +13 -13
  7. package/.claude/skills/swarm-coordination/skill.md +5 -5
  8. package/.claude/skills/worker-benchmarks/skill.md +5 -5
  9. package/.claude/skills/worker-integration/skill.md +5 -5
  10. package/.claude/statusline.mjs +22 -5
  11. package/CHANGELOG.md +48 -0
  12. package/README.md +83 -71
  13. package/dist/.tsbuildinfo +1 -1
  14. package/dist/cli/commands/hooks.d.ts.map +1 -1
  15. package/dist/cli/commands/hooks.js +17 -17
  16. package/dist/cli/commands/hooks.js.map +1 -1
  17. package/dist/cli/commands/init.d.ts +2 -5
  18. package/dist/cli/commands/init.d.ts.map +1 -1
  19. package/dist/cli/commands/init.js +11 -15
  20. package/dist/cli/commands/init.js.map +1 -1
  21. package/dist/cli/commands/swarm.d.ts.map +1 -1
  22. package/dist/cli/commands/swarm.js +3 -2
  23. package/dist/cli/commands/swarm.js.map +1 -1
  24. package/dist/core/agentdb-fast.d.ts +21 -11
  25. package/dist/core/agentdb-fast.d.ts.map +1 -1
  26. package/dist/core/agentdb-fast.js +39 -14
  27. package/dist/core/agentdb-fast.js.map +1 -1
  28. package/dist/integrations/agent-booster.d.ts +35 -0
  29. package/dist/integrations/agent-booster.d.ts.map +1 -0
  30. package/dist/integrations/agent-booster.js +45 -0
  31. package/dist/integrations/agent-booster.js.map +1 -0
  32. package/dist/integrations/index.d.ts +15 -0
  33. package/dist/integrations/index.d.ts.map +1 -0
  34. package/dist/integrations/index.js +11 -0
  35. package/dist/integrations/index.js.map +1 -0
  36. package/dist/integrations/onnx-wasm-embedder.d.ts +59 -0
  37. package/dist/integrations/onnx-wasm-embedder.d.ts.map +1 -0
  38. package/dist/integrations/onnx-wasm-embedder.js +145 -0
  39. package/dist/integrations/onnx-wasm-embedder.js.map +1 -0
  40. package/dist/integrations/optional.d.ts +44 -0
  41. package/dist/integrations/optional.d.ts.map +1 -0
  42. package/dist/integrations/optional.js +107 -0
  43. package/dist/integrations/optional.js.map +1 -0
  44. package/dist/integrations/prompt-injection.d.ts +52 -0
  45. package/dist/integrations/prompt-injection.d.ts.map +1 -0
  46. package/dist/integrations/prompt-injection.js +126 -0
  47. package/dist/integrations/prompt-injection.js.map +1 -0
  48. package/dist/integrations/sublinear.d.ts +71 -0
  49. package/dist/integrations/sublinear.d.ts.map +1 -0
  50. package/dist/integrations/sublinear.js +227 -0
  51. package/dist/integrations/sublinear.js.map +1 -0
  52. package/dist/integrations/task-partition.d.ts +40 -0
  53. package/dist/integrations/task-partition.d.ts.map +1 -0
  54. package/dist/integrations/task-partition.js +173 -0
  55. package/dist/integrations/task-partition.js.map +1 -0
  56. package/dist/mcp/mcp-policy.d.ts.map +1 -1
  57. package/dist/mcp/mcp-policy.js +2 -0
  58. package/dist/mcp/mcp-policy.js.map +1 -1
  59. package/dist/mcp/standalone-stdio.js +12 -26
  60. package/dist/mcp/standalone-stdio.js.map +1 -1
  61. package/dist/mcp/tools/ecosystem-tools.d.ts +49 -0
  62. package/dist/mcp/tools/ecosystem-tools.d.ts.map +1 -0
  63. package/dist/mcp/tools/ecosystem-tools.js +126 -0
  64. package/dist/mcp/tools/ecosystem-tools.js.map +1 -0
  65. package/dist/proxy/anthropic-to-gemini.d.ts.map +1 -1
  66. package/dist/proxy/anthropic-to-gemini.js +10 -14
  67. package/dist/proxy/anthropic-to-gemini.js.map +1 -1
  68. package/dist/proxy/anthropic-to-openrouter.d.ts.map +1 -1
  69. package/dist/proxy/anthropic-to-openrouter.js +6 -25
  70. package/dist/proxy/anthropic-to-openrouter.js.map +1 -1
  71. package/dist/proxy/anthropic-to-requesty.d.ts.map +1 -1
  72. package/dist/proxy/anthropic-to-requesty.js +8 -10
  73. package/dist/proxy/anthropic-to-requesty.js.map +1 -1
  74. package/dist/proxy/sse-lines.d.ts +9 -0
  75. package/dist/proxy/sse-lines.d.ts.map +1 -0
  76. package/dist/proxy/sse-lines.js +37 -0
  77. package/dist/proxy/sse-lines.js.map +1 -0
  78. package/dist/reasoningbank/index.d.ts +2 -1
  79. package/dist/reasoningbank/index.d.ts.map +1 -1
  80. package/dist/reasoningbank/index.js +1 -1
  81. package/dist/reasoningbank/index.js.map +1 -1
  82. package/dist/reasoningbank/utils/embeddings.d.ts +17 -0
  83. package/dist/reasoningbank/utils/embeddings.d.ts.map +1 -1
  84. package/dist/reasoningbank/utils/embeddings.js +48 -17
  85. package/dist/reasoningbank/utils/embeddings.js.map +1 -1
  86. package/dist/routing/SemanticRouter.d.ts +25 -9
  87. package/dist/routing/SemanticRouter.d.ts.map +1 -1
  88. package/dist/routing/SemanticRouter.js +63 -12
  89. package/dist/routing/SemanticRouter.js.map +1 -1
  90. package/dist/utils/input-validator.d.ts +10 -2
  91. package/dist/utils/input-validator.d.ts.map +1 -1
  92. package/dist/utils/input-validator.js +30 -2
  93. package/dist/utils/input-validator.js.map +1 -1
  94. package/dist/utils/model-cache.d.ts.map +1 -1
  95. package/dist/utils/model-cache.js +6 -25
  96. package/dist/utils/model-cache.js.map +1 -1
  97. package/dist/utils/package-version.d.ts +9 -0
  98. package/dist/utils/package-version.d.ts.map +1 -0
  99. package/dist/utils/package-version.js +39 -0
  100. package/dist/utils/package-version.js.map +1 -0
  101. package/dist/wasm/onnx-embeddings-wasm.d.ts.map +1 -1
  102. package/dist/wasm/onnx-embeddings-wasm.js +21 -10
  103. package/dist/wasm/onnx-embeddings-wasm.js.map +1 -1
  104. package/docs/docker-tests/TEST-V1.7.8.Dockerfile +2 -2
  105. package/docs/docker-tests/TEST-V1.7.9-NODE20.Dockerfile +2 -2
  106. package/docs/docker-tests/TEST-V1.7.9.Dockerfile +2 -2
  107. package/docs/guides/CLAUDE-CODE-INTEGRATION.md +25 -8
  108. package/docs/guides/PROXY-ARCHITECTURE-AND-EXTENSION.md +22 -9
  109. package/docs/guides/STANDALONE_PROXY_GUIDE.md +16 -6
  110. package/docs/integrations/FASTMCP_CLI_INTEGRATION.md +1 -1
  111. package/docs/plans/requesty/02-architecture.md +5 -6
  112. package/docs/plans/requesty/03-implementation-phases.md +3 -4
  113. package/docs/plans/requesty/05-migration-guide.md +2 -2
  114. package/package.json +12 -7
  115. package/scripts/validate-providers.sh +7 -4
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Agent Booster edits: in-process library first, `npx` CLI as the fallback.
3
+ *
4
+ * `agent-booster` is an optionalDependency. When it is installed (the default)
5
+ * edits run in-process through its WASM engine. When it is not, we fall back
6
+ * to the pinned CLI via `npx --yes agent-booster@0.2.2 apply`, which is what
7
+ * the MCP server always did before (and which downloads on first use).
8
+ */
9
+ export declare const AGENT_BOOSTER_CLI = "agent-booster@0.2.2";
10
+ export interface BoosterEditResult {
11
+ output: string;
12
+ success: boolean;
13
+ latency: number;
14
+ confidence: number;
15
+ strategy: string;
16
+ /** How the edit was applied. */
17
+ via: 'library' | 'npx';
18
+ }
19
+ type BoosterInstance = {
20
+ apply(input: {
21
+ code: string;
22
+ edit: string;
23
+ language: string;
24
+ }): Promise<Omit<BoosterEditResult, 'via'>>;
25
+ };
26
+ /** The in-process Agent Booster, or null when the optional package is absent. */
27
+ export declare function getAgentBoosterLibrary(): Promise<BoosterInstance | null>;
28
+ /** Apply `edit` to `code`. Never shells out when the library is installed. */
29
+ export declare function applyAgentBoosterEdit(code: string, edit: string, language: string, options?: {
30
+ npxTimeoutMs?: number;
31
+ }): Promise<BoosterEditResult>;
32
+ /** Test hook. */
33
+ export declare function _resetAgentBoosterForTests(): void;
34
+ export {};
35
+ //# sourceMappingURL=agent-booster.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-booster.d.ts","sourceRoot":"","sources":["../../src/integrations/agent-booster.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,eAAO,MAAM,iBAAiB,wBAAwB,CAAC;AAEvD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,GAAG,EAAE,SAAS,GAAG,KAAK,CAAC;CACxB;AAED,KAAK,eAAe,GAAG;IACrB,KAAK,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC,CAAC;CACzG,CAAC;AAIF,iFAAiF;AACjF,wBAAgB,sBAAsB,IAAI,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CASxE;AAED,8EAA8E;AAC9E,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAAO,GACtC,OAAO,CAAC,iBAAiB,CAAC,CAc5B;AAED,iBAAiB;AACjB,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Agent Booster edits: in-process library first, `npx` CLI as the fallback.
3
+ *
4
+ * `agent-booster` is an optionalDependency. When it is installed (the default)
5
+ * edits run in-process through its WASM engine. When it is not, we fall back
6
+ * to the pinned CLI via `npx --yes agent-booster@0.2.2 apply`, which is what
7
+ * the MCP server always did before (and which downloads on first use).
8
+ */
9
+ import { execFileSync } from 'node:child_process';
10
+ import { importOptional } from './optional.js';
11
+ export const AGENT_BOOSTER_CLI = 'agent-booster@0.2.2';
12
+ let instance = null;
13
+ /** The in-process Agent Booster, or null when the optional package is absent. */
14
+ export function getAgentBoosterLibrary() {
15
+ if (!instance) {
16
+ instance = importOptional('agent-booster').then((mod) => {
17
+ const Ctor = mod?.AgentBooster ?? mod?.default?.AgentBooster ?? mod?.default;
18
+ if (typeof Ctor !== 'function')
19
+ return null;
20
+ return new Ctor({ confidenceThreshold: 0.5, maxChunks: 100 });
21
+ });
22
+ }
23
+ return instance;
24
+ }
25
+ /** Apply `edit` to `code`. Never shells out when the library is installed. */
26
+ export async function applyAgentBoosterEdit(code, edit, language, options = {}) {
27
+ const lib = await getAgentBoosterLibrary();
28
+ if (lib) {
29
+ const r = await lib.apply({ code, edit, language });
30
+ return { ...r, via: 'library' };
31
+ }
32
+ const stdout = execFileSync('npx', ['--yes', AGENT_BOOSTER_CLI, 'apply', '--language', language], {
33
+ shell: false,
34
+ encoding: 'utf-8',
35
+ input: JSON.stringify({ code, edit }),
36
+ maxBuffer: 10 * 1024 * 1024,
37
+ timeout: options.npxTimeoutMs ?? 30000,
38
+ });
39
+ return { ...JSON.parse(stdout), via: 'npx' };
40
+ }
41
+ /** Test hook. */
42
+ export function _resetAgentBoosterForTests() {
43
+ instance = null;
44
+ }
45
+ //# sourceMappingURL=agent-booster.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-booster.js","sourceRoot":"","sources":["../../src/integrations/agent-booster.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,CAAC,MAAM,iBAAiB,GAAG,qBAAqB,CAAC;AAgBvD,IAAI,QAAQ,GAA2C,IAAI,CAAC;AAE5D,iFAAiF;AACjF,MAAM,UAAU,sBAAsB;IACpC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,QAAQ,GAAG,cAAc,CAAM,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YAC3D,MAAM,IAAI,GAAG,GAAG,EAAE,YAAY,IAAI,GAAG,EAAE,OAAO,EAAE,YAAY,IAAI,GAAG,EAAE,OAAO,CAAC;YAC7E,IAAI,OAAO,IAAI,KAAK,UAAU;gBAAE,OAAO,IAAI,CAAC;YAC5C,OAAO,IAAI,IAAI,CAAC,EAAE,mBAAmB,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,CAAoB,CAAC;QACnF,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,8EAA8E;AAC9E,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,IAAY,EACZ,IAAY,EACZ,QAAgB,EAChB,UAAqC,EAAE;IAEvC,MAAM,GAAG,GAAG,MAAM,sBAAsB,EAAE,CAAC;IAC3C,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACpD,OAAO,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;IAClC,CAAC;IACD,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE;QAChG,KAAK,EAAE,KAAK;QACZ,QAAQ,EAAE,OAAO;QACjB,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACrC,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;QAC3B,OAAO,EAAE,OAAO,CAAC,YAAY,IAAI,KAAK;KACvC,CAAC,CAAC;IACH,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;AAC/C,CAAC;AAED,iBAAiB;AACjB,MAAM,UAAU,0BAA0B;IACxC,QAAQ,GAAG,IAAI,CAAC;AAClB,CAAC","sourcesContent":["/**\n * Agent Booster edits: in-process library first, `npx` CLI as the fallback.\n *\n * `agent-booster` is an optionalDependency. When it is installed (the default)\n * edits run in-process through its WASM engine. When it is not, we fall back\n * to the pinned CLI via `npx --yes agent-booster@0.2.2 apply`, which is what\n * the MCP server always did before (and which downloads on first use).\n */\n\nimport { execFileSync } from 'node:child_process';\nimport { importOptional } from './optional.js';\n\nexport const AGENT_BOOSTER_CLI = 'agent-booster@0.2.2';\n\nexport interface BoosterEditResult {\n output: string;\n success: boolean;\n latency: number;\n confidence: number;\n strategy: string;\n /** How the edit was applied. */\n via: 'library' | 'npx';\n}\n\ntype BoosterInstance = {\n apply(input: { code: string; edit: string; language: string }): Promise<Omit<BoosterEditResult, 'via'>>;\n};\n\nlet instance: Promise<BoosterInstance | null> | null = null;\n\n/** The in-process Agent Booster, or null when the optional package is absent. */\nexport function getAgentBoosterLibrary(): Promise<BoosterInstance | null> {\n if (!instance) {\n instance = importOptional<any>('agent-booster').then((mod) => {\n const Ctor = mod?.AgentBooster ?? mod?.default?.AgentBooster ?? mod?.default;\n if (typeof Ctor !== 'function') return null;\n return new Ctor({ confidenceThreshold: 0.5, maxChunks: 100 }) as BoosterInstance;\n });\n }\n return instance;\n}\n\n/** Apply `edit` to `code`. Never shells out when the library is installed. */\nexport async function applyAgentBoosterEdit(\n code: string,\n edit: string,\n language: string,\n options: { npxTimeoutMs?: number } = {},\n): Promise<BoosterEditResult> {\n const lib = await getAgentBoosterLibrary();\n if (lib) {\n const r = await lib.apply({ code, edit, language });\n return { ...r, via: 'library' };\n }\n const stdout = execFileSync('npx', ['--yes', AGENT_BOOSTER_CLI, 'apply', '--language', language], {\n shell: false,\n encoding: 'utf-8',\n input: JSON.stringify({ code, edit }),\n maxBuffer: 10 * 1024 * 1024,\n timeout: options.npxTimeoutMs ?? 30000,\n });\n return { ...JSON.parse(stdout), via: 'npx' };\n}\n\n/** Test hook. */\nexport function _resetAgentBoosterForTests(): void {\n instance = null;\n}\n"]}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * agentic-flow/integrations — programmatic access to the optional ruvnet
3
+ * package integrations (each with a built-in fallback).
4
+ */
5
+ export { scanPromptInjection, promptInjectionEngine, getInjectionPolicy } from './prompt-injection.js';
6
+ export type { InjectionScan, InjectionThreat, InjectionPolicy, InjectionSeverity } from './prompt-injection.js';
7
+ export { partitionTaskGraph } from './task-partition.js';
8
+ export type { TaskDependency, TaskPartition } from './task-partition.js';
9
+ export { solveLinearSystem, pageRank } from './sublinear.js';
10
+ export type { LinearSolveResult, PageRankResult, MatrixInput, SparseEntry } from './sublinear.js';
11
+ export { applyAgentBoosterEdit, getAgentBoosterLibrary } from './agent-booster.js';
12
+ export type { BoosterEditResult } from './agent-booster.js';
13
+ export { OnnxWasmTextEmbedder, getOnnxWasmEmbedder, loadOnnxWasmModule, onnxWasmModelCached } from './onnx-wasm-embedder.js';
14
+ export { isOptionalInstalled } from './optional.js';
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/integrations/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AACvG,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAChH,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClG,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AACnF,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC7H,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * agentic-flow/integrations — programmatic access to the optional ruvnet
3
+ * package integrations (each with a built-in fallback).
4
+ */
5
+ export { scanPromptInjection, promptInjectionEngine, getInjectionPolicy } from './prompt-injection.js';
6
+ export { partitionTaskGraph } from './task-partition.js';
7
+ export { solveLinearSystem, pageRank } from './sublinear.js';
8
+ export { applyAgentBoosterEdit, getAgentBoosterLibrary } from './agent-booster.js';
9
+ export { OnnxWasmTextEmbedder, getOnnxWasmEmbedder, loadOnnxWasmModule, onnxWasmModelCached } from './onnx-wasm-embedder.js';
10
+ export { isOptionalInstalled } from './optional.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/integrations/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEvG,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE7D,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAEnF,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC7H,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC","sourcesContent":["/**\n * agentic-flow/integrations — programmatic access to the optional ruvnet\n * package integrations (each with a built-in fallback).\n */\n\nexport { scanPromptInjection, promptInjectionEngine, getInjectionPolicy } from './prompt-injection.js';\nexport type { InjectionScan, InjectionThreat, InjectionPolicy, InjectionSeverity } from './prompt-injection.js';\nexport { partitionTaskGraph } from './task-partition.js';\nexport type { TaskDependency, TaskPartition } from './task-partition.js';\nexport { solveLinearSystem, pageRank } from './sublinear.js';\nexport type { LinearSolveResult, PageRankResult, MatrixInput, SparseEntry } from './sublinear.js';\nexport { applyAgentBoosterEdit, getAgentBoosterLibrary } from './agent-booster.js';\nexport type { BoosterEditResult } from './agent-booster.js';\nexport { OnnxWasmTextEmbedder, getOnnxWasmEmbedder, loadOnnxWasmModule, onnxWasmModelCached } from './onnx-wasm-embedder.js';\nexport { isOptionalInstalled } from './optional.js';\n"]}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Real text embeddings through `ruvector-onnx-embeddings-wasm` (all-MiniLM-L6-v2, 384-d).
3
+ *
4
+ * Packaging note: ruvector-onnx-embeddings-wasm 0.1.0-0.1.2 declares
5
+ * `"type": "module"` but ships wasm-bindgen's CommonJS (nodejs target) glue,
6
+ * which assigns `module.exports`. `import()` therefore throws
7
+ * "module is not defined in ES module scope", and `require()` fails the same
8
+ * way because Node treats the file as ESM. We compile the glue explicitly as
9
+ * CommonJS. If a future release ships real ESM, plain `import()` is used.
10
+ *
11
+ * Model: the WASM runtime cannot load the quantized ONNX graph agentic-flow's
12
+ * OptimizedEmbedder uses by default (it fails on an Unsqueeze node), so this
13
+ * uses the full-precision Xenova/all-MiniLM-L6-v2 model (~91 MB) plus its
14
+ * tokenizer.json. Both live in the same model directory OptimizedEmbedder uses
15
+ * (`~/.agentic-flow/models`, override with `AGENTIC_FLOW_MODEL_DIR`); the ONNX
16
+ * file name matches OptimizedEmbedder's `all-MiniLM-L6-v2-full` registry entry,
17
+ * so either component can reuse the other's download.
18
+ *
19
+ * Downloads happen on first use unless any of these is set:
20
+ * `AGENTIC_FLOW_OFFLINE=1`, `HF_HUB_OFFLINE=1`, `AGENTIC_FLOW_EMBEDDINGS_DOWNLOAD=0`.
21
+ * Nothing here writes to stdout (the MCP stdio server owns it).
22
+ */
23
+ export declare const ONNX_WASM_PACKAGE = "ruvector-onnx-embeddings-wasm";
24
+ export declare const ONNX_WASM_DIMENSION = 384;
25
+ interface WasmEmbedderHandle {
26
+ embedOne(text: string): Float32Array;
27
+ dimension(): number;
28
+ }
29
+ export interface OnnxWasmModule {
30
+ WasmEmbedder: new (modelBytes: Uint8Array, tokenizerJson: string) => WasmEmbedderHandle;
31
+ cosineSimilarity(a: Float32Array, b: Float32Array): number;
32
+ version(): string;
33
+ }
34
+ /** Load the WASM glue (see the packaging note above), or null when absent. */
35
+ export declare function loadOnnxWasmModule(): Promise<OnnxWasmModule | null>;
36
+ export declare function onnxWasmModelDir(): string;
37
+ export declare function onnxWasmDownloadAllowed(): boolean;
38
+ /** Whether model + tokenizer are already on disk (no network needed). */
39
+ export declare function onnxWasmModelCached(dir?: string): boolean;
40
+ /** A loaded all-MiniLM-L6-v2 embedder. `embed` is async to match other embedders. */
41
+ export declare class OnnxWasmTextEmbedder {
42
+ private readonly handle;
43
+ readonly dimension: number;
44
+ readonly source: "onnx-wasm";
45
+ private constructor();
46
+ /** Build an embedder, or null when the package or the model is unavailable. */
47
+ static create(options?: {
48
+ modelDir?: string;
49
+ }): Promise<OnnxWasmTextEmbedder | null>;
50
+ embedSync(text: string): Float32Array;
51
+ embed(text: string): Promise<Float32Array>;
52
+ embedBatch(texts: string[]): Promise<Float32Array[]>;
53
+ }
54
+ /** Process-wide embedder (loaded once), or null. */
55
+ export declare function getOnnxWasmEmbedder(): Promise<OnnxWasmTextEmbedder | null>;
56
+ /** Test hook. */
57
+ export declare function _resetOnnxWasmForTests(): void;
58
+ export {};
59
+ //# sourceMappingURL=onnx-wasm-embedder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onnx-wasm-embedder.d.ts","sourceRoot":"","sources":["../../src/integrations/onnx-wasm-embedder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAQH,eAAO,MAAM,iBAAiB,kCAAkC,CAAC;AACjE,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAOvC,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAAC;IACrC,SAAS,IAAI,MAAM,CAAC;CACrB;AACD,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,KAAK,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,KAAK,kBAAkB,CAAC;IACxF,gBAAgB,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IAC3D,OAAO,IAAI,MAAM,CAAC;CACnB;AAID,8EAA8E;AAC9E,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAsBnE;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,uBAAuB,IAAI,OAAO,CAQjD;AAED,yEAAyE;AACzE,wBAAgB,mBAAmB,CAAC,GAAG,SAAqB,GAAG,OAAO,CAErE;AAqBD,qFAAqF;AACrF,qBAAa,oBAAoB;IAIX,OAAO,CAAC,QAAQ,CAAC,MAAM;IAH3C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAG,WAAW,CAAU;IAEvC,OAAO;IAIP,+EAA+E;WAClE,MAAM,CAAC,OAAO,GAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAiB9F,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY;IAI/B,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAI1C,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;CAG3D;AAID,oDAAoD;AACpD,wBAAgB,mBAAmB,IAAI,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAG1E;AAED,iBAAiB;AACjB,wBAAgB,sBAAsB,IAAI,IAAI,CAG7C"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Real text embeddings through `ruvector-onnx-embeddings-wasm` (all-MiniLM-L6-v2, 384-d).
3
+ *
4
+ * Packaging note: ruvector-onnx-embeddings-wasm 0.1.0-0.1.2 declares
5
+ * `"type": "module"` but ships wasm-bindgen's CommonJS (nodejs target) glue,
6
+ * which assigns `module.exports`. `import()` therefore throws
7
+ * "module is not defined in ES module scope", and `require()` fails the same
8
+ * way because Node treats the file as ESM. We compile the glue explicitly as
9
+ * CommonJS. If a future release ships real ESM, plain `import()` is used.
10
+ *
11
+ * Model: the WASM runtime cannot load the quantized ONNX graph agentic-flow's
12
+ * OptimizedEmbedder uses by default (it fails on an Unsqueeze node), so this
13
+ * uses the full-precision Xenova/all-MiniLM-L6-v2 model (~91 MB) plus its
14
+ * tokenizer.json. Both live in the same model directory OptimizedEmbedder uses
15
+ * (`~/.agentic-flow/models`, override with `AGENTIC_FLOW_MODEL_DIR`); the ONNX
16
+ * file name matches OptimizedEmbedder's `all-MiniLM-L6-v2-full` registry entry,
17
+ * so either component can reuse the other's download.
18
+ *
19
+ * Downloads happen on first use unless any of these is set:
20
+ * `AGENTIC_FLOW_OFFLINE=1`, `HF_HUB_OFFLINE=1`, `AGENTIC_FLOW_EMBEDDINGS_DOWNLOAD=0`.
21
+ * Nothing here writes to stdout (the MCP stdio server owns it).
22
+ */
23
+ import Module from 'node:module';
24
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
25
+ import { homedir } from 'node:os';
26
+ import { dirname, join } from 'node:path';
27
+ import { resolveOptional } from './optional.js';
28
+ export const ONNX_WASM_PACKAGE = 'ruvector-onnx-embeddings-wasm';
29
+ export const ONNX_WASM_DIMENSION = 384;
30
+ const MODEL_FILE = 'all-MiniLM-L6-v2-full.onnx';
31
+ const TOKENIZER_FILE = 'all-MiniLM-L6-v2.tokenizer.json';
32
+ const MODEL_URL = 'https://huggingface.co/Xenova/all-MiniLM-L6-v2/resolve/main/onnx/model.onnx';
33
+ const TOKENIZER_URL = 'https://huggingface.co/Xenova/all-MiniLM-L6-v2/resolve/main/tokenizer.json';
34
+ let modulePromise = null;
35
+ /** Load the WASM glue (see the packaging note above), or null when absent. */
36
+ export function loadOnnxWasmModule() {
37
+ if (!modulePromise) {
38
+ modulePromise = (async () => {
39
+ const entry = resolveOptional(ONNX_WASM_PACKAGE);
40
+ if (!entry)
41
+ return null;
42
+ try {
43
+ const source = readFileSync(entry, 'utf8');
44
+ if (/\bmodule\.exports\b/.test(source)) {
45
+ const M = Module;
46
+ const mod = new M(entry, null);
47
+ mod.filename = entry;
48
+ mod.paths = M._nodeModulePaths(dirname(entry));
49
+ mod._compile(source, entry);
50
+ return mod.exports;
51
+ }
52
+ return (await import(ONNX_WASM_PACKAGE));
53
+ }
54
+ catch {
55
+ return null;
56
+ }
57
+ })();
58
+ }
59
+ return modulePromise;
60
+ }
61
+ export function onnxWasmModelDir() {
62
+ return process.env.AGENTIC_FLOW_MODEL_DIR || join(homedir(), '.agentic-flow', 'models');
63
+ }
64
+ export function onnxWasmDownloadAllowed() {
65
+ const off = (v) => v === '1' || v === 'true';
66
+ return !(off(process.env.AGENTIC_FLOW_OFFLINE) ||
67
+ off(process.env.HF_HUB_OFFLINE) ||
68
+ process.env.AGENTIC_FLOW_EMBEDDINGS_DOWNLOAD === '0' ||
69
+ process.env.AGENTIC_FLOW_EMBEDDINGS_DOWNLOAD === 'false');
70
+ }
71
+ /** Whether model + tokenizer are already on disk (no network needed). */
72
+ export function onnxWasmModelCached(dir = onnxWasmModelDir()) {
73
+ return existsSync(join(dir, MODEL_FILE)) && existsSync(join(dir, TOKENIZER_FILE));
74
+ }
75
+ async function download(url, target) {
76
+ const res = await fetch(url);
77
+ if (!res.ok)
78
+ throw new Error(`download failed ${res.status} ${res.statusText}: ${url}`);
79
+ const bytes = new Uint8Array(await res.arrayBuffer());
80
+ const tmp = `${target}.${process.pid}.part`;
81
+ writeFileSync(tmp, bytes, { mode: 0o600 });
82
+ renameSync(tmp, target);
83
+ }
84
+ async function ensureModelFiles(dir) {
85
+ if (onnxWasmModelCached(dir))
86
+ return true;
87
+ if (!onnxWasmDownloadAllowed())
88
+ return false;
89
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
90
+ process.stderr.write(`[agentic-flow] downloading all-MiniLM-L6-v2 (~91 MB) to ${dir}\n`);
91
+ if (!existsSync(join(dir, TOKENIZER_FILE)))
92
+ await download(TOKENIZER_URL, join(dir, TOKENIZER_FILE));
93
+ if (!existsSync(join(dir, MODEL_FILE)))
94
+ await download(MODEL_URL, join(dir, MODEL_FILE));
95
+ return true;
96
+ }
97
+ /** A loaded all-MiniLM-L6-v2 embedder. `embed` is async to match other embedders. */
98
+ export class OnnxWasmTextEmbedder {
99
+ handle;
100
+ dimension;
101
+ source = 'onnx-wasm';
102
+ constructor(handle) {
103
+ this.handle = handle;
104
+ this.dimension = handle.dimension();
105
+ }
106
+ /** Build an embedder, or null when the package or the model is unavailable. */
107
+ static async create(options = {}) {
108
+ const mod = await loadOnnxWasmModule();
109
+ if (!mod)
110
+ return null;
111
+ const dir = options.modelDir ?? onnxWasmModelDir();
112
+ try {
113
+ if (!(await ensureModelFiles(dir)))
114
+ return null;
115
+ const handle = new mod.WasmEmbedder(new Uint8Array(readFileSync(join(dir, MODEL_FILE))), readFileSync(join(dir, TOKENIZER_FILE), 'utf8'));
116
+ return new OnnxWasmTextEmbedder(handle);
117
+ }
118
+ catch (err) {
119
+ process.stderr.write(`[agentic-flow] ONNX WASM embedder unavailable: ${err?.message ?? err}\n`);
120
+ return null;
121
+ }
122
+ }
123
+ embedSync(text) {
124
+ return this.handle.embedOne(text);
125
+ }
126
+ async embed(text) {
127
+ return this.handle.embedOne(text);
128
+ }
129
+ async embedBatch(texts) {
130
+ return texts.map((t) => this.handle.embedOne(t));
131
+ }
132
+ }
133
+ let shared = null;
134
+ /** Process-wide embedder (loaded once), or null. */
135
+ export function getOnnxWasmEmbedder() {
136
+ if (!shared)
137
+ shared = OnnxWasmTextEmbedder.create();
138
+ return shared;
139
+ }
140
+ /** Test hook. */
141
+ export function _resetOnnxWasmForTests() {
142
+ shared = null;
143
+ modulePromise = null;
144
+ }
145
+ //# sourceMappingURL=onnx-wasm-embedder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onnx-wasm-embedder.js","sourceRoot":"","sources":["../../src/integrations/onnx-wasm-embedder.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Real text embeddings through `ruvector-onnx-embeddings-wasm` (all-MiniLM-L6-v2, 384-d).\n *\n * Packaging note: ruvector-onnx-embeddings-wasm 0.1.0-0.1.2 declares\n * `\"type\": \"module\"` but ships wasm-bindgen's CommonJS (nodejs target) glue,\n * which assigns `module.exports`. `import()` therefore throws\n * \"module is not defined in ES module scope\", and `require()` fails the same\n * way because Node treats the file as ESM. We compile the glue explicitly as\n * CommonJS. If a future release ships real ESM, plain `import()` is used.\n *\n * Model: the WASM runtime cannot load the quantized ONNX graph agentic-flow's\n * OptimizedEmbedder uses by default (it fails on an Unsqueeze node), so this\n * uses the full-precision Xenova/all-MiniLM-L6-v2 model (~91 MB) plus its\n * tokenizer.json. Both live in the same model directory OptimizedEmbedder uses\n * (`~/.agentic-flow/models`, override with `AGENTIC_FLOW_MODEL_DIR`); the ONNX\n * file name matches OptimizedEmbedder's `all-MiniLM-L6-v2-full` registry entry,\n * so either component can reuse the other's download.\n *\n * Downloads happen on first use unless any of these is set:\n * `AGENTIC_FLOW_OFFLINE=1`, `HF_HUB_OFFLINE=1`, `AGENTIC_FLOW_EMBEDDINGS_DOWNLOAD=0`.\n * Nothing here writes to stdout (the MCP stdio server owns it).\n */\n\nimport Module from 'node:module';\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { resolveOptional } from './optional.js';\n\nexport const ONNX_WASM_PACKAGE = 'ruvector-onnx-embeddings-wasm';\nexport const ONNX_WASM_DIMENSION = 384;\n\nconst MODEL_FILE = 'all-MiniLM-L6-v2-full.onnx';\nconst TOKENIZER_FILE = 'all-MiniLM-L6-v2.tokenizer.json';\nconst MODEL_URL = 'https://huggingface.co/Xenova/all-MiniLM-L6-v2/resolve/main/onnx/model.onnx';\nconst TOKENIZER_URL = 'https://huggingface.co/Xenova/all-MiniLM-L6-v2/resolve/main/tokenizer.json';\n\ninterface WasmEmbedderHandle {\n embedOne(text: string): Float32Array;\n dimension(): number;\n}\nexport interface OnnxWasmModule {\n WasmEmbedder: new (modelBytes: Uint8Array, tokenizerJson: string) => WasmEmbedderHandle;\n cosineSimilarity(a: Float32Array, b: Float32Array): number;\n version(): string;\n}\n\nlet modulePromise: Promise<OnnxWasmModule | null> | null = null;\n\n/** Load the WASM glue (see the packaging note above), or null when absent. */\nexport function loadOnnxWasmModule(): Promise<OnnxWasmModule | null> {\n if (!modulePromise) {\n modulePromise = (async () => {\n const entry = resolveOptional(ONNX_WASM_PACKAGE);\n if (!entry) return null;\n try {\n const source = readFileSync(entry, 'utf8');\n if (/\\bmodule\\.exports\\b/.test(source)) {\n const M = Module as any;\n const mod = new M(entry, null);\n mod.filename = entry;\n mod.paths = M._nodeModulePaths(dirname(entry));\n mod._compile(source, entry);\n return mod.exports as OnnxWasmModule;\n }\n return (await import(ONNX_WASM_PACKAGE)) as unknown as OnnxWasmModule;\n } catch {\n return null;\n }\n })();\n }\n return modulePromise;\n}\n\nexport function onnxWasmModelDir(): string {\n return process.env.AGENTIC_FLOW_MODEL_DIR || join(homedir(), '.agentic-flow', 'models');\n}\n\nexport function onnxWasmDownloadAllowed(): boolean {\n const off = (v: string | undefined) => v === '1' || v === 'true';\n return !(\n off(process.env.AGENTIC_FLOW_OFFLINE) ||\n off(process.env.HF_HUB_OFFLINE) ||\n process.env.AGENTIC_FLOW_EMBEDDINGS_DOWNLOAD === '0' ||\n process.env.AGENTIC_FLOW_EMBEDDINGS_DOWNLOAD === 'false'\n );\n}\n\n/** Whether model + tokenizer are already on disk (no network needed). */\nexport function onnxWasmModelCached(dir = onnxWasmModelDir()): boolean {\n return existsSync(join(dir, MODEL_FILE)) && existsSync(join(dir, TOKENIZER_FILE));\n}\n\nasync function download(url: string, target: string): Promise<void> {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`download failed ${res.status} ${res.statusText}: ${url}`);\n const bytes = new Uint8Array(await res.arrayBuffer());\n const tmp = `${target}.${process.pid}.part`;\n writeFileSync(tmp, bytes, { mode: 0o600 });\n renameSync(tmp, target);\n}\n\nasync function ensureModelFiles(dir: string): Promise<boolean> {\n if (onnxWasmModelCached(dir)) return true;\n if (!onnxWasmDownloadAllowed()) return false;\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n process.stderr.write(`[agentic-flow] downloading all-MiniLM-L6-v2 (~91 MB) to ${dir}\\n`);\n if (!existsSync(join(dir, TOKENIZER_FILE))) await download(TOKENIZER_URL, join(dir, TOKENIZER_FILE));\n if (!existsSync(join(dir, MODEL_FILE))) await download(MODEL_URL, join(dir, MODEL_FILE));\n return true;\n}\n\n/** A loaded all-MiniLM-L6-v2 embedder. `embed` is async to match other embedders. */\nexport class OnnxWasmTextEmbedder {\n readonly dimension: number;\n readonly source = 'onnx-wasm' as const;\n\n private constructor(private readonly handle: WasmEmbedderHandle) {\n this.dimension = handle.dimension();\n }\n\n /** Build an embedder, or null when the package or the model is unavailable. */\n static async create(options: { modelDir?: string } = {}): Promise<OnnxWasmTextEmbedder | null> {\n const mod = await loadOnnxWasmModule();\n if (!mod) return null;\n const dir = options.modelDir ?? onnxWasmModelDir();\n try {\n if (!(await ensureModelFiles(dir))) return null;\n const handle = new mod.WasmEmbedder(\n new Uint8Array(readFileSync(join(dir, MODEL_FILE))),\n readFileSync(join(dir, TOKENIZER_FILE), 'utf8'),\n );\n return new OnnxWasmTextEmbedder(handle);\n } catch (err: any) {\n process.stderr.write(`[agentic-flow] ONNX WASM embedder unavailable: ${err?.message ?? err}\\n`);\n return null;\n }\n }\n\n embedSync(text: string): Float32Array {\n return this.handle.embedOne(text);\n }\n\n async embed(text: string): Promise<Float32Array> {\n return this.handle.embedOne(text);\n }\n\n async embedBatch(texts: string[]): Promise<Float32Array[]> {\n return texts.map((t) => this.handle.embedOne(t));\n }\n}\n\nlet shared: Promise<OnnxWasmTextEmbedder | null> | null = null;\n\n/** Process-wide embedder (loaded once), or null. */\nexport function getOnnxWasmEmbedder(): Promise<OnnxWasmTextEmbedder | null> {\n if (!shared) shared = OnnxWasmTextEmbedder.create();\n return shared;\n}\n\n/** Test hook. */\nexport function _resetOnnxWasmForTests(): void {\n shared = null;\n modulePromise = null;\n}\n"]}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Optional ecosystem packages — one place to load them.
3
+ *
4
+ * Every package loaded here is an `optionalDependency` of agentic-flow: npm
5
+ * installs it by default, but it may be missing (`--omit=optional`, an
6
+ * unsupported platform, a failed native build). Callers therefore always get
7
+ * either the module or `null`, never a throw, and keep a built-in fallback.
8
+ *
9
+ * Two loaders:
10
+ * - `requireOptional` is synchronous (createRequire) for CommonJS packages that
11
+ * must be usable from synchronous code paths (e.g. input validation).
12
+ * - `importOptional` is asynchronous for ESM packages.
13
+ *
14
+ * Results (including "not installed") are cached per specifier.
15
+ */
16
+ /** Synchronously load a CommonJS optional package, or return null. */
17
+ export declare function requireOptional<T = any>(specifier: string): T | null;
18
+ /**
19
+ * Whether a package is installed, without loading it. ESM-only packages whose
20
+ * exports map has no require/default condition (sublinear-time-solver) cannot
21
+ * be require.resolve()d, but that error itself proves the package is there.
22
+ */
23
+ export declare function isOptionalInstalled(specifier: string): boolean;
24
+ /** Asynchronously import an optional package (ESM or CJS), or return null. */
25
+ export declare function importOptional<T = any>(specifier: string, options?: {
26
+ quietStdout?: boolean;
27
+ }): Promise<T | null>;
28
+ /** Why the last load of `specifier` failed, if it did. */
29
+ export declare function optionalLoadError(specifier: string): string | undefined;
30
+ /** Resolve a package's entry file without loading it, or null if absent. */
31
+ export declare function resolveOptional(specifier: string): string | null;
32
+ /**
33
+ * Run `fn` with `console.log`/`console.info` sent to stderr.
34
+ *
35
+ * The MCP stdio server speaks JSON-RPC over stdout, so a dependency that
36
+ * prints a banner (sublinear-time-solver does, from `console.log`) would
37
+ * corrupt the protocol stream. Only the console methods are patched — never
38
+ * `process.stdout.write` — so a protocol frame written by the server while
39
+ * `fn` is pending still reaches stdout.
40
+ */
41
+ export declare function withStdoutToStderr<T>(fn: () => Promise<T> | T): Promise<T>;
42
+ /** Test hook: forget cached load results. */
43
+ export declare function _resetOptionalCache(): void;
44
+ //# sourceMappingURL=optional.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional.d.ts","sourceRoot":"","sources":["../../src/integrations/optional.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAUH,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,CAAC,GAAG,GAAG,EAAE,SAAS,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAWpE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAO9D;AAED,8EAA8E;AAC9E,wBAAsB,cAAc,CAAC,CAAC,GAAG,GAAG,EAC1C,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GACtC,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAenB;AAED,0DAA0D;AAC1D,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEvE;AAED,4EAA4E;AAC5E,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMhE;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAWhF;AAED,6CAA6C;AAC7C,wBAAgB,mBAAmB,IAAI,IAAI,CAG1C"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Optional ecosystem packages — one place to load them.
3
+ *
4
+ * Every package loaded here is an `optionalDependency` of agentic-flow: npm
5
+ * installs it by default, but it may be missing (`--omit=optional`, an
6
+ * unsupported platform, a failed native build). Callers therefore always get
7
+ * either the module or `null`, never a throw, and keep a built-in fallback.
8
+ *
9
+ * Two loaders:
10
+ * - `requireOptional` is synchronous (createRequire) for CommonJS packages that
11
+ * must be usable from synchronous code paths (e.g. input validation).
12
+ * - `importOptional` is asynchronous for ESM packages.
13
+ *
14
+ * Results (including "not installed") are cached per specifier.
15
+ */
16
+ import { createRequire } from 'node:module';
17
+ const nodeRequire = createRequire(import.meta.url);
18
+ const syncCache = new Map();
19
+ const asyncCache = new Map();
20
+ /** Synchronously load a CommonJS optional package, or return null. */
21
+ export function requireOptional(specifier) {
22
+ const cached = syncCache.get(specifier);
23
+ if (cached)
24
+ return cached.mod;
25
+ let entry;
26
+ try {
27
+ entry = { mod: nodeRequire(specifier) };
28
+ }
29
+ catch (err) {
30
+ entry = { mod: null, error: err?.message ?? String(err) };
31
+ }
32
+ syncCache.set(specifier, entry);
33
+ return entry.mod;
34
+ }
35
+ /**
36
+ * Whether a package is installed, without loading it. ESM-only packages whose
37
+ * exports map has no require/default condition (sublinear-time-solver) cannot
38
+ * be require.resolve()d, but that error itself proves the package is there.
39
+ */
40
+ export function isOptionalInstalled(specifier) {
41
+ try {
42
+ nodeRequire.resolve(specifier);
43
+ return true;
44
+ }
45
+ catch (err) {
46
+ return err?.code === 'ERR_PACKAGE_PATH_NOT_EXPORTED';
47
+ }
48
+ }
49
+ /** Asynchronously import an optional package (ESM or CJS), or return null. */
50
+ export async function importOptional(specifier, options = {}) {
51
+ let pending = asyncCache.get(specifier);
52
+ if (!pending) {
53
+ pending = (async () => {
54
+ try {
55
+ const load = () => import(specifier);
56
+ const mod = options.quietStdout ? await withStdoutToStderr(load) : await load();
57
+ return { mod };
58
+ }
59
+ catch (err) {
60
+ return { mod: null, error: err?.message ?? String(err) };
61
+ }
62
+ })();
63
+ asyncCache.set(specifier, pending);
64
+ }
65
+ return (await pending).mod;
66
+ }
67
+ /** Why the last load of `specifier` failed, if it did. */
68
+ export function optionalLoadError(specifier) {
69
+ return syncCache.get(specifier)?.error;
70
+ }
71
+ /** Resolve a package's entry file without loading it, or null if absent. */
72
+ export function resolveOptional(specifier) {
73
+ try {
74
+ return nodeRequire.resolve(specifier);
75
+ }
76
+ catch {
77
+ return null;
78
+ }
79
+ }
80
+ /**
81
+ * Run `fn` with `console.log`/`console.info` sent to stderr.
82
+ *
83
+ * The MCP stdio server speaks JSON-RPC over stdout, so a dependency that
84
+ * prints a banner (sublinear-time-solver does, from `console.log`) would
85
+ * corrupt the protocol stream. Only the console methods are patched — never
86
+ * `process.stdout.write` — so a protocol frame written by the server while
87
+ * `fn` is pending still reaches stdout.
88
+ */
89
+ export async function withStdoutToStderr(fn) {
90
+ const originalLog = console.log;
91
+ const originalInfo = console.info;
92
+ console.log = (...args) => console.error(...args);
93
+ console.info = (...args) => console.error(...args);
94
+ try {
95
+ return await fn();
96
+ }
97
+ finally {
98
+ console.log = originalLog;
99
+ console.info = originalInfo;
100
+ }
101
+ }
102
+ /** Test hook: forget cached load results. */
103
+ export function _resetOptionalCache() {
104
+ syncCache.clear();
105
+ asyncCache.clear();
106
+ }
107
+ //# sourceMappingURL=optional.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional.js","sourceRoot":"","sources":["../../src/integrations/optional.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Optional ecosystem packages — one place to load them.\n *\n * Every package loaded here is an `optionalDependency` of agentic-flow: npm\n * installs it by default, but it may be missing (`--omit=optional`, an\n * unsupported platform, a failed native build). Callers therefore always get\n * either the module or `null`, never a throw, and keep a built-in fallback.\n *\n * Two loaders:\n * - `requireOptional` is synchronous (createRequire) for CommonJS packages that\n * must be usable from synchronous code paths (e.g. input validation).\n * - `importOptional` is asynchronous for ESM packages.\n *\n * Results (including \"not installed\") are cached per specifier.\n */\n\nimport { createRequire } from 'node:module';\n\nconst nodeRequire = createRequire(import.meta.url);\n\ntype CacheEntry = { mod: any | null; error?: string };\nconst syncCache = new Map<string, CacheEntry>();\nconst asyncCache = new Map<string, Promise<CacheEntry>>();\n\n/** Synchronously load a CommonJS optional package, or return null. */\nexport function requireOptional<T = any>(specifier: string): T | null {\n const cached = syncCache.get(specifier);\n if (cached) return cached.mod as T | null;\n let entry: CacheEntry;\n try {\n entry = { mod: nodeRequire(specifier) };\n } catch (err: any) {\n entry = { mod: null, error: err?.message ?? String(err) };\n }\n syncCache.set(specifier, entry);\n return entry.mod as T | null;\n}\n\n/**\n * Whether a package is installed, without loading it. ESM-only packages whose\n * exports map has no require/default condition (sublinear-time-solver) cannot\n * be require.resolve()d, but that error itself proves the package is there.\n */\nexport function isOptionalInstalled(specifier: string): boolean {\n try {\n nodeRequire.resolve(specifier);\n return true;\n } catch (err: any) {\n return err?.code === 'ERR_PACKAGE_PATH_NOT_EXPORTED';\n }\n}\n\n/** Asynchronously import an optional package (ESM or CJS), or return null. */\nexport async function importOptional<T = any>(\n specifier: string,\n options: { quietStdout?: boolean } = {},\n): Promise<T | null> {\n let pending = asyncCache.get(specifier);\n if (!pending) {\n pending = (async (): Promise<CacheEntry> => {\n try {\n const load = () => import(specifier);\n const mod = options.quietStdout ? await withStdoutToStderr(load) : await load();\n return { mod };\n } catch (err: any) {\n return { mod: null, error: err?.message ?? String(err) };\n }\n })();\n asyncCache.set(specifier, pending);\n }\n return (await pending).mod as T | null;\n}\n\n/** Why the last load of `specifier` failed, if it did. */\nexport function optionalLoadError(specifier: string): string | undefined {\n return syncCache.get(specifier)?.error;\n}\n\n/** Resolve a package's entry file without loading it, or null if absent. */\nexport function resolveOptional(specifier: string): string | null {\n try {\n return nodeRequire.resolve(specifier);\n } catch {\n return null;\n }\n}\n\n/**\n * Run `fn` with `console.log`/`console.info` sent to stderr.\n *\n * The MCP stdio server speaks JSON-RPC over stdout, so a dependency that\n * prints a banner (sublinear-time-solver does, from `console.log`) would\n * corrupt the protocol stream. Only the console methods are patched — never\n * `process.stdout.write` — so a protocol frame written by the server while\n * `fn` is pending still reaches stdout.\n */\nexport async function withStdoutToStderr<T>(fn: () => Promise<T> | T): Promise<T> {\n const originalLog = console.log;\n const originalInfo = console.info;\n console.log = (...args: unknown[]) => console.error(...args);\n console.info = (...args: unknown[]) => console.error(...args);\n try {\n return await fn();\n } finally {\n console.log = originalLog;\n console.info = originalInfo;\n }\n}\n\n/** Test hook: forget cached load results. */\nexport function _resetOptionalCache(): void {\n syncCache.clear();\n asyncCache.clear();\n}\n"]}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Prompt-injection screening for task text.
3
+ *
4
+ * Uses the optional `aidefence` package (53 curated patterns across encodings
5
+ * and obfuscation variants) when installed, and a small built-in pattern set
6
+ * otherwise. Only the `aidefence/dist/detection` subpath is loaded: the package
7
+ * root starts an Express server stack, the detection engine has no deps.
8
+ *
9
+ * Policy (env `AGENTIC_FLOW_PROMPT_INJECTION`):
10
+ * - `block` (default): reject `critical` findings, warn on the rest
11
+ * - `strict`: reject `critical` and `high`, warn on the rest
12
+ * - `warn`: never reject, warn on every finding
13
+ * - `off`: do not scan
14
+ *
15
+ * `high` is not rejected by default because legitimate agent prompts often
16
+ * trip it — "You are now a code reviewer…" matches aidefence's role-switch rule.
17
+ */
18
+ export type InjectionSeverity = 'low' | 'medium' | 'high' | 'critical';
19
+ export type InjectionPolicy = 'block' | 'strict' | 'warn' | 'off';
20
+ export interface InjectionThreat {
21
+ id: string;
22
+ type: string;
23
+ severity: InjectionSeverity;
24
+ confidence: number;
25
+ description: string;
26
+ match?: string;
27
+ }
28
+ export interface InjectionScan {
29
+ safe: boolean;
30
+ maxSeverity: InjectionSeverity | null;
31
+ threats: InjectionThreat[];
32
+ /** Which engine produced the result. */
33
+ engine: 'aidefence' | 'builtin' | 'disabled';
34
+ /** What the active policy decided. */
35
+ decision: 'allow' | 'warn' | 'block';
36
+ }
37
+ interface AidefenceDetector {
38
+ detect(text: string): {
39
+ safe: boolean;
40
+ maxSeverity: InjectionSeverity | null;
41
+ threats: Array<InjectionThreat & Record<string, unknown>>;
42
+ };
43
+ }
44
+ export declare function getInjectionPolicy(): InjectionPolicy;
45
+ /** Scan `text` for prompt-injection attempts under the active policy. */
46
+ export declare function scanPromptInjection(text: string, policy?: InjectionPolicy): InjectionScan;
47
+ /** Which engine `scanPromptInjection` will use. */
48
+ export declare function promptInjectionEngine(): 'aidefence' | 'builtin';
49
+ /** Test hook: `null` forces the built-in engine, `undefined` restores auto-detection. */
50
+ export declare function _setInjectionDetectorForTests(d: AidefenceDetector | null | undefined): void;
51
+ export {};
52
+ //# sourceMappingURL=prompt-injection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-injection.d.ts","sourceRoot":"","sources":["../../src/integrations/prompt-injection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;AACvE,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAC;AAElE,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACtC,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,wCAAwC;IACxC,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,UAAU,CAAC;IAC7C,sCAAsC;IACtC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;CACtC;AAED,UAAU,iBAAiB;IACzB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG;QACpB,IAAI,EAAE,OAAO,CAAC;QACd,WAAW,EAAE,iBAAiB,GAAG,IAAI,CAAC;QACtC,OAAO,EAAE,KAAK,CAAC,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;KAC3D,CAAC;CACH;AA2CD,wBAAgB,kBAAkB,IAAI,eAAe,CAKpD;AA0BD,yEAAyE;AACzE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,eAAsC,GAAG,aAAa,CAwB/G;AAED,mDAAmD;AACnD,wBAAgB,qBAAqB,IAAI,WAAW,GAAG,SAAS,CAE/D;AAED,yFAAyF;AACzF,wBAAgB,6BAA6B,CAAC,CAAC,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAE3F"}