agentic-flow 3.0.0 → 3.1.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/.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/.claude/statusline.mjs +22 -5
- package/CHANGELOG.md +23 -0
- package/README.md +68 -71
- package/dist/.tsbuildinfo +1 -1
- package/dist/cli/commands/hooks.d.ts.map +1 -1
- package/dist/cli/commands/hooks.js +17 -17
- package/dist/cli/commands/hooks.js.map +1 -1
- package/dist/cli/commands/init.d.ts +2 -5
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +2 -15
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/swarm.d.ts.map +1 -1
- package/dist/cli/commands/swarm.js +3 -2
- package/dist/cli/commands/swarm.js.map +1 -1
- package/dist/proxy/anthropic-to-gemini.d.ts.map +1 -1
- package/dist/proxy/anthropic-to-gemini.js +10 -14
- package/dist/proxy/anthropic-to-gemini.js.map +1 -1
- package/dist/proxy/anthropic-to-openrouter.d.ts.map +1 -1
- package/dist/proxy/anthropic-to-openrouter.js +6 -25
- package/dist/proxy/anthropic-to-openrouter.js.map +1 -1
- package/dist/proxy/anthropic-to-requesty.d.ts.map +1 -1
- package/dist/proxy/anthropic-to-requesty.js +8 -10
- package/dist/proxy/anthropic-to-requesty.js.map +1 -1
- package/dist/proxy/sse-lines.d.ts +9 -0
- package/dist/proxy/sse-lines.d.ts.map +1 -0
- package/dist/proxy/sse-lines.js +37 -0
- package/dist/proxy/sse-lines.js.map +1 -0
- package/dist/reasoningbank/index.d.ts +2 -1
- package/dist/reasoningbank/index.d.ts.map +1 -1
- package/dist/reasoningbank/index.js +1 -1
- package/dist/reasoningbank/index.js.map +1 -1
- package/dist/reasoningbank/utils/embeddings.d.ts +17 -0
- package/dist/reasoningbank/utils/embeddings.d.ts.map +1 -1
- package/dist/reasoningbank/utils/embeddings.js +48 -17
- package/dist/reasoningbank/utils/embeddings.js.map +1 -1
- package/dist/utils/package-version.d.ts +9 -0
- package/dist/utils/package-version.d.ts.map +1 -0
- package/dist/utils/package-version.js +39 -0
- package/dist/utils/package-version.js.map +1 -0
- package/docs/docker-tests/TEST-V1.7.8.Dockerfile +2 -2
- package/docs/docker-tests/TEST-V1.7.9-NODE20.Dockerfile +2 -2
- package/docs/docker-tests/TEST-V1.7.9.Dockerfile +2 -2
- package/docs/guides/CLAUDE-CODE-INTEGRATION.md +25 -8
- package/docs/guides/PROXY-ARCHITECTURE-AND-EXTENSION.md +22 -9
- package/docs/guides/STANDALONE_PROXY_GUIDE.md +16 -6
- package/docs/integrations/FASTMCP_CLI_INTEGRATION.md +1 -1
- package/docs/plans/requesty/02-architecture.md +5 -6
- package/docs/plans/requesty/03-implementation-phases.md +3 -4
- package/docs/plans/requesty/05-migration-guide.md +2 -2
- package/package.json +1 -1
- package/scripts/validate-providers.sh +7 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-lines.d.ts","sourceRoot":"","sources":["../../src/proxy/sse-lines.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,2BAA2B,CAAC,UAAU,CAAC,EAC/C,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAC/B,OAAO,CAAC,MAAM,CAAC,CAoBjB;AAED,iEAAiE;AACjE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAE/C"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Shared SSE reader for the translation proxies.
|
|
2
|
+
//
|
|
3
|
+
// A network read can end anywhere: inside a data: line, or inside a multi-byte
|
|
4
|
+
// UTF-8 character. Decoding each read on its own and splitting on '\n' drops
|
|
5
|
+
// the split line and corrupts the character. This reader decodes with
|
|
6
|
+
// {stream:true} and holds back a partial line until its newline arrives.
|
|
7
|
+
/**
|
|
8
|
+
* Read `reader` to the end, calling `onLines` with text made only of complete
|
|
9
|
+
* lines (each ending in '\n'), then once more with any unterminated tail.
|
|
10
|
+
* Returns the number of reads.
|
|
11
|
+
*/
|
|
12
|
+
export async function forEachSseLines(reader, onLines) {
|
|
13
|
+
const decoder = new TextDecoder();
|
|
14
|
+
let pending = '';
|
|
15
|
+
let reads = 0;
|
|
16
|
+
while (true) {
|
|
17
|
+
const { done, value } = await reader.read();
|
|
18
|
+
if (done)
|
|
19
|
+
break;
|
|
20
|
+
reads++;
|
|
21
|
+
pending += decoder.decode(value, { stream: true });
|
|
22
|
+
const lastNewline = pending.lastIndexOf('\n');
|
|
23
|
+
if (lastNewline === -1)
|
|
24
|
+
continue;
|
|
25
|
+
onLines(pending.slice(0, lastNewline + 1));
|
|
26
|
+
pending = pending.slice(lastNewline + 1);
|
|
27
|
+
}
|
|
28
|
+
pending += decoder.decode();
|
|
29
|
+
if (pending.trim())
|
|
30
|
+
onLines(pending);
|
|
31
|
+
return reads;
|
|
32
|
+
}
|
|
33
|
+
/** Non-empty lines of `text`, with any trailing '\r' removed. */
|
|
34
|
+
export function sseLines(text) {
|
|
35
|
+
return text.split('\n').map(line => line.replace(/\r$/, '')).filter(line => line.trim());
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=sse-lines.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-lines.js","sourceRoot":"","sources":["../../src/proxy/sse-lines.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,+EAA+E;AAC/E,6EAA6E;AAC7E,sEAAsE;AACtE,yEAAyE;AAEzE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAA+C,EAC/C,OAAgC;IAEhC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QAC5C,IAAI,IAAI;YAAE,MAAM;QAChB,KAAK,EAAE,CAAC;QAER,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,WAAW,KAAK,CAAC,CAAC;YAAE,SAAS;QACjC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3C,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAC5B,IAAI,OAAO,CAAC,IAAI,EAAE;QAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;AAC3F,CAAC","sourcesContent":["// Shared SSE reader for the translation proxies.\n//\n// A network read can end anywhere: inside a data: line, or inside a multi-byte\n// UTF-8 character. Decoding each read on its own and splitting on '\\n' drops\n// the split line and corrupts the character. This reader decodes with\n// {stream:true} and holds back a partial line until its newline arrives.\n\n/**\n * Read `reader` to the end, calling `onLines` with text made only of complete\n * lines (each ending in '\\n'), then once more with any unterminated tail.\n * Returns the number of reads.\n */\nexport async function forEachSseLines(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n onLines: (lines: string) => void\n): Promise<number> {\n const decoder = new TextDecoder();\n let pending = '';\n let reads = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n reads++;\n\n pending += decoder.decode(value, { stream: true });\n const lastNewline = pending.lastIndexOf('\\n');\n if (lastNewline === -1) continue;\n onLines(pending.slice(0, lastNewline + 1));\n pending = pending.slice(lastNewline + 1);\n }\n\n pending += decoder.decode();\n if (pending.trim()) onLines(pending);\n return reads;\n}\n\n/** Non-empty lines of `text`, with any trailing '\\r' removed. */\nexport function sseLines(text: string): string[] {\n return text.split('\\n').map(line => line.replace(/\\r$/, '')).filter(line => line.trim());\n}\n"]}
|
|
@@ -21,7 +21,8 @@ export { consolidate, shouldConsolidate } from './core/consolidate.js';
|
|
|
21
21
|
export type { ConsolidationResult } from './core/consolidate.js';
|
|
22
22
|
export { mattsParallel, mattsSequential } from './core/matts.js';
|
|
23
23
|
export type { MattsResult } from './core/matts.js';
|
|
24
|
-
export { computeEmbedding, clearEmbeddingCache, isSemanticEmbedding } from './utils/embeddings.js';
|
|
24
|
+
export { computeEmbedding, clearEmbeddingCache, isSemanticEmbedding, getEmbeddingKind, resetEmbeddingBackend, } from './utils/embeddings.js';
|
|
25
|
+
export type { EmbeddingKind } from './utils/embeddings.js';
|
|
25
26
|
export { mmrSelection, cosineSimilarity } from './utils/mmr.js';
|
|
26
27
|
export { scrubPII, containsPII, scrubMemory } from './utils/pii-scrubber.js';
|
|
27
28
|
export { loadConfig } from './utils/config.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/reasoningbank/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,mCAAmC,CAAC;AAG3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,mBAAmB,IAAI,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACvF,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG7E,OAAO,EACL,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC/E,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACvE,YAAY,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAEjE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACjE,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/reasoningbank/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,mCAAmC,CAAC;AAG3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,mBAAmB,IAAI,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACvF,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG7E,OAAO,EACL,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC/E,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACvE,YAAY,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAEjE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACjE,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG/C,OAAO,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACtC,OAAO,EAAE,EAAE,EAAE,CAAC;AACd,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,QAAQ,EACR,gBAAgB,EAChB,UAAU,EACV,cAAc,EACf,MAAM,gBAAgB,CAAC;AASxB,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CA0BhD;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;CAC9C,GAAG,OAAO,CAAC;IACV,OAAO,EAAE,GAAG,CAAC;IACb,YAAY,EAAE,GAAG,EAAE,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC,CA6BD;AAED,eAAO,MAAM,OAAO,UAAU,CAAC;AAC/B,eAAO,MAAM,SAAS,wCAAwC,CAAC"}
|
|
@@ -18,7 +18,7 @@ export { judgeTrajectory } from './core/judge.js';
|
|
|
18
18
|
export { distillMemories } from './core/distill.js';
|
|
19
19
|
export { consolidate, shouldConsolidate } from './core/consolidate.js';
|
|
20
20
|
export { mattsParallel, mattsSequential } from './core/matts.js';
|
|
21
|
-
export { computeEmbedding, clearEmbeddingCache, isSemanticEmbedding } from './utils/embeddings.js';
|
|
21
|
+
export { computeEmbedding, clearEmbeddingCache, isSemanticEmbedding, getEmbeddingKind, resetEmbeddingBackend, } from './utils/embeddings.js';
|
|
22
22
|
export { mmrSelection, cosineSimilarity } from './utils/mmr.js';
|
|
23
23
|
export { scrubPII, containsPII, scrubMemory } from './utils/pii-scrubber.js';
|
|
24
24
|
export { loadConfig } from './utils/config.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/reasoningbank/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,yDAAyD;AACzD,OAAO,mCAAmC,CAAC;AAE3C,gDAAgD;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,mBAAmB,IAAI,aAAa,EAAE,MAAM,oBAAoB,CAAC,CAAE,6BAA6B;AACzG,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAI3D,mDAAmD;AACnD,OAAO,EACL,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAEjB,mEAAmE;AACnE,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAG/E,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGlD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAGvE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGjE,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/reasoningbank/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ReasoningBank - Closed-loop memory system for AI agents\n * Based on arXiv:2509.25140 (Google DeepMind)\n *\n * @since v1.7.0 - Integrated AgentDB for optimal performance\n */\n\n// Apply AgentDB runtime patch before any AgentDB imports\nimport '../utils/agentdb-runtime-patch.js';\n\n// New hybrid backend (recommended for new code)\nexport { HybridReasoningBank } from './HybridBackend.js';\nexport { HybridReasoningBank as ReasoningBank } from './HybridBackend.js'; // Alias for backwards compat\nexport { AdvancedMemorySystem } from './AdvancedMemory.js';\nexport type { PatternData, RetrievalOptions, CausalInsight } from './HybridBackend.js';\nexport type { FailureAnalysis, SkillComposition } from './AdvancedMemory.js';\n\n// Re-export AgentDB controllers for advanced usage\nexport {\n ReflexionMemory,\n SkillLibrary,\n CausalMemoryGraph,\n CausalRecall,\n NightlyLearner,\n EmbeddingService\n} from 'agentdb';\n\n// Original ReasoningBank implementations (backwards compatibility)\nexport { retrieveMemories, formatMemoriesForPrompt } from './core/retrieve.js';\nexport type { RetrievedMemory } from './core/retrieve.js';\n\nexport { judgeTrajectory } from './core/judge.js';\nexport type { Verdict } from './core/judge.js';\n\nexport { distillMemories } from './core/distill.js';\nexport type { DistilledMemory } from './core/distill.js';\n\nexport { consolidate, shouldConsolidate } from './core/consolidate.js';\nexport type { ConsolidationResult } from './core/consolidate.js';\n\nexport { mattsParallel, mattsSequential } from './core/matts.js';\nexport type { MattsResult } from './core/matts.js';\n\nexport {\n computeEmbedding,\n clearEmbeddingCache,\n isSemanticEmbedding,\n getEmbeddingKind,\n resetEmbeddingBackend,\n} from './utils/embeddings.js';\nexport type { EmbeddingKind } from './utils/embeddings.js';\nexport { mmrSelection, cosineSimilarity } from './utils/mmr.js';\nexport { scrubPII, containsPII, scrubMemory } from './utils/pii-scrubber.js';\nexport { loadConfig } from './utils/config.js';\n\n// Re-export database utilities\nimport * as db from './db/queries.js';\nexport { db };\nexport type {\n ReasoningMemory,\n PatternEmbedding,\n PatternLink,\n TaskTrajectory,\n MattsRun,\n ConsolidationRun,\n Trajectory,\n TrajectoryStep\n} from './db/schema.js';\n\n// Original functions (backwards compatibility)\nimport { loadConfig } from './utils/config.js';\nimport { retrieveMemories } from './core/retrieve.js';\nimport { judgeTrajectory } from './core/judge.js';\nimport { distillMemories } from './core/distill.js';\nimport { shouldConsolidate as shouldCons, consolidate as cons } from './core/consolidate.js';\n\nexport async function initialize(): Promise<void> {\n const config = loadConfig();\n console.error('[ReasoningBank] Initializing...');\n console.error('[ReasoningBank] Enabled: true (initializing...)');\n console.error(`[ReasoningBank] Database: ${process.env.CLAUDE_FLOW_DB_PATH || '.swarm/memory.db'}`);\n console.error(`[ReasoningBank] Embeddings: ${config.embeddings.provider}`);\n console.error(`[ReasoningBank] Retrieval k: ${config.retrieve.k}`);\n\n try {\n await db.runMigrations();\n console.error(`[ReasoningBank] Database migrated successfully`);\n } catch (error) {\n console.error('[ReasoningBank] Migration error:', error);\n throw new Error('ReasoningBank initialization failed: could not run migrations');\n }\n\n try {\n const dbConn = db.getDb();\n const tables = dbConn.prepare(\"SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'pattern%'\").all();\n console.error(`[ReasoningBank] Database OK: ${tables.length} tables found`);\n } catch (error) {\n console.error('[ReasoningBank] Database error:', error);\n throw new Error('ReasoningBank initialization failed: database not accessible');\n }\n\n console.error('[ReasoningBank] Initialization complete');\n}\n\nexport async function runTask(options: {\n taskId: string;\n agentId: string;\n query: string;\n domain?: string;\n executeFn: (memories: any[]) => Promise<any>;\n}): Promise<{\n verdict: any;\n usedMemories: any[];\n newMemories: string[];\n consolidated: boolean;\n}> {\n console.error(`[ReasoningBank] Running task: ${options.taskId}`);\n const memories = await retrieveMemories(options.query, {\n domain: options.domain,\n agent: options.agentId\n });\n console.error(`[ReasoningBank] Retrieved ${memories.length} memories`);\n const trajectory = await options.executeFn(memories);\n const verdict = await judgeTrajectory(trajectory, options.query);\n console.error(`[ReasoningBank] Verdict: ${verdict.label} (${verdict.confidence})`);\n // Close the loop: the memories this task used share its outcome.\n db.applyOutcomeToMemories(\n memories.map(m => m.id),\n verdict.label === 'Success',\n verdict.confidence\n );\n const newMemories = await distillMemories(trajectory, verdict, options.query, {\n taskId: options.taskId,\n agentId: options.agentId,\n domain: options.domain\n });\n console.error(`[ReasoningBank] Distilled ${newMemories.length} new memories`);\n let consolidated = false;\n if (shouldCons()) {\n console.error('[ReasoningBank] Running consolidation...');\n await cons();\n consolidated = true;\n }\n return { verdict, usedMemories: memories, newMemories, consolidated };\n}\n\nexport const VERSION = '1.7.1';\nexport const PAPER_URL = 'https://arxiv.org/html/2509.25140v1';\n"]}
|
|
@@ -5,6 +5,12 @@
|
|
|
5
5
|
* Logs go to stderr so that stdout stays clean for callers that pipe
|
|
6
6
|
* structured output (CLIs, MCP stdio servers).
|
|
7
7
|
*/
|
|
8
|
+
/**
|
|
9
|
+
* The space every vector in this process belongs to. Set by the first
|
|
10
|
+
* embedding and kept until resetEmbeddingBackend(): model vectors and hash
|
|
11
|
+
* vectors are not comparable, so a process never mixes them (issue #246).
|
|
12
|
+
*/
|
|
13
|
+
export type EmbeddingKind = 'local' | 'hash';
|
|
8
14
|
/**
|
|
9
15
|
* True when embeddings come from the transformer model; false when they come
|
|
10
16
|
* from the deterministic hash fallback, whose vectors carry no semantic
|
|
@@ -12,6 +18,17 @@
|
|
|
12
18
|
* model.
|
|
13
19
|
*/
|
|
14
20
|
export declare function isSemanticEmbedding(): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* The space this process's embeddings are in, or null before the first one.
|
|
23
|
+
* Vectors of different kinds must never be compared.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getEmbeddingKind(): EmbeddingKind | null;
|
|
26
|
+
/**
|
|
27
|
+
* Forget the backend choice and the cache, so the next embedding tries to load
|
|
28
|
+
* the model again. Vectors produced before the reset may be in a different
|
|
29
|
+
* space from those produced after it; re-embed anything you keep.
|
|
30
|
+
*/
|
|
31
|
+
export declare function resetEmbeddingBackend(): void;
|
|
15
32
|
/**
|
|
16
33
|
* Compute embedding for text using local model
|
|
17
34
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../../../src/reasoningbank/utils/embeddings.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../../../src/reasoningbank/utils/embeddings.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAyBH;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;AAyE7C;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,GAAG,IAAI,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAK5C;AAkBD;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA4B1E;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CA6CpF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AA+CD;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C"}
|
|
@@ -24,6 +24,7 @@ const CACHE_MAX_ENTRIES = 1000;
|
|
|
24
24
|
const BATCH_CHUNK_SIZE = 32;
|
|
25
25
|
let embeddingPipeline = null;
|
|
26
26
|
let initializationPromise = null;
|
|
27
|
+
let embeddingKind = null;
|
|
27
28
|
const embeddingCache = new Map();
|
|
28
29
|
function cacheGet(key) {
|
|
29
30
|
const entry = embeddingCache.get(key);
|
|
@@ -72,8 +73,9 @@ async function initializeEmbeddings() {
|
|
|
72
73
|
catch (error) {
|
|
73
74
|
console.error('[Embeddings] Failed to initialize:', error?.message || error);
|
|
74
75
|
console.error('[Embeddings] Falling back to hash-based embeddings (not semantic)');
|
|
75
|
-
//
|
|
76
|
-
|
|
76
|
+
// No automatic retry: a later successful load would put new vectors in a
|
|
77
|
+
// different space from the hash vectors already handed out. Call
|
|
78
|
+
// resetEmbeddingBackend() to try the model again.
|
|
77
79
|
}
|
|
78
80
|
})();
|
|
79
81
|
return initializationPromise;
|
|
@@ -85,20 +87,50 @@ async function initializeEmbeddings() {
|
|
|
85
87
|
* model.
|
|
86
88
|
*/
|
|
87
89
|
export function isSemanticEmbedding() {
|
|
88
|
-
return embeddingPipeline !== null;
|
|
90
|
+
return embeddingKind === 'local' || (embeddingKind === null && embeddingPipeline !== null);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The space this process's embeddings are in, or null before the first one.
|
|
94
|
+
* Vectors of different kinds must never be compared.
|
|
95
|
+
*/
|
|
96
|
+
export function getEmbeddingKind() {
|
|
97
|
+
return embeddingKind;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Forget the backend choice and the cache, so the next embedding tries to load
|
|
101
|
+
* the model again. Vectors produced before the reset may be in a different
|
|
102
|
+
* space from those produced after it; re-embed anything you keep.
|
|
103
|
+
*/
|
|
104
|
+
export function resetEmbeddingBackend() {
|
|
105
|
+
embeddingPipeline = null;
|
|
106
|
+
initializationPromise = null;
|
|
107
|
+
embeddingKind = null;
|
|
108
|
+
embeddingCache.clear();
|
|
109
|
+
}
|
|
110
|
+
/** Fix the process to one space on first use; refuse to switch afterwards. */
|
|
111
|
+
function commitKind(kind) {
|
|
112
|
+
if (embeddingKind === null)
|
|
113
|
+
embeddingKind = kind;
|
|
114
|
+
else if (embeddingKind !== kind) {
|
|
115
|
+
throw new Error(`[Embeddings] refusing to produce a ${kind} vector: this process already embeds with ${embeddingKind}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function modelFailure(error) {
|
|
119
|
+
return new Error(`[Embeddings] model failed (${error?.message || error}); not substituting a hash vector, which would not be comparable with the model vectors already produced`);
|
|
89
120
|
}
|
|
90
121
|
/**
|
|
91
122
|
* Compute embedding for text using local model
|
|
92
123
|
*/
|
|
93
124
|
export async function computeEmbedding(text) {
|
|
94
|
-
const cached = cacheGet(
|
|
125
|
+
const cached = cacheGet(text);
|
|
95
126
|
if (cached)
|
|
96
127
|
return cached;
|
|
97
|
-
//
|
|
98
|
-
|
|
128
|
+
// A process already in the hash space stays there; don't load the model.
|
|
129
|
+
if (embeddingKind !== 'hash')
|
|
130
|
+
await initializeEmbeddings();
|
|
99
131
|
let embedding;
|
|
100
|
-
let kind = 'local';
|
|
101
132
|
if (embeddingPipeline) {
|
|
133
|
+
commitKind('local');
|
|
102
134
|
try {
|
|
103
135
|
const output = await embeddingPipeline(text, {
|
|
104
136
|
pooling: 'mean',
|
|
@@ -108,16 +140,15 @@ export async function computeEmbedding(text) {
|
|
|
108
140
|
}
|
|
109
141
|
catch (error) {
|
|
110
142
|
console.error('[Embeddings] Generation failed:', error?.message || error);
|
|
111
|
-
|
|
112
|
-
kind = 'hash';
|
|
143
|
+
throw modelFailure(error);
|
|
113
144
|
}
|
|
114
145
|
}
|
|
115
146
|
else {
|
|
147
|
+
commitKind('hash');
|
|
116
148
|
const dims = loadConfig()?.embeddings?.dimensions || MODEL_DIMS;
|
|
117
149
|
embedding = hashEmbed(text, dims);
|
|
118
|
-
kind = 'hash';
|
|
119
150
|
}
|
|
120
|
-
cacheSet(
|
|
151
|
+
cacheSet(text, embedding, cacheTtlSeconds());
|
|
121
152
|
return embedding;
|
|
122
153
|
}
|
|
123
154
|
/**
|
|
@@ -125,14 +156,16 @@ export async function computeEmbedding(text) {
|
|
|
125
156
|
* per chunk of texts rather than one call per text.
|
|
126
157
|
*/
|
|
127
158
|
export async function computeEmbeddingBatch(texts) {
|
|
128
|
-
|
|
159
|
+
if (embeddingKind !== 'hash')
|
|
160
|
+
await initializeEmbeddings();
|
|
129
161
|
if (!embeddingPipeline) {
|
|
130
162
|
return Promise.all(texts.map(text => computeEmbedding(text)));
|
|
131
163
|
}
|
|
164
|
+
commitKind('local');
|
|
132
165
|
const results = new Array(texts.length);
|
|
133
166
|
const missing = new Map(); // text -> result indices
|
|
134
167
|
texts.forEach((text, i) => {
|
|
135
|
-
const cached = cacheGet(
|
|
168
|
+
const cached = cacheGet(text);
|
|
136
169
|
if (cached) {
|
|
137
170
|
results[i] = cached;
|
|
138
171
|
return;
|
|
@@ -148,7 +181,6 @@ export async function computeEmbeddingBatch(texts) {
|
|
|
148
181
|
for (let start = 0; start < uniqueTexts.length; start += BATCH_CHUNK_SIZE) {
|
|
149
182
|
const chunk = uniqueTexts.slice(start, start + BATCH_CHUNK_SIZE);
|
|
150
183
|
let vectors;
|
|
151
|
-
let kind = 'local';
|
|
152
184
|
try {
|
|
153
185
|
const output = await embeddingPipeline(chunk, { pooling: 'mean', normalize: true });
|
|
154
186
|
const dims = output.dims[output.dims.length - 1];
|
|
@@ -157,11 +189,10 @@ export async function computeEmbeddingBatch(texts) {
|
|
|
157
189
|
}
|
|
158
190
|
catch (error) {
|
|
159
191
|
console.error('[Embeddings] Batch generation failed:', error?.message || error);
|
|
160
|
-
|
|
161
|
-
kind = 'hash';
|
|
192
|
+
throw modelFailure(error);
|
|
162
193
|
}
|
|
163
194
|
chunk.forEach((text, j) => {
|
|
164
|
-
cacheSet(
|
|
195
|
+
cacheSet(text, vectors[j], ttl);
|
|
165
196
|
for (const i of missing.get(text))
|
|
166
197
|
results[i] = vectors[j];
|
|
167
198
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../../../src/reasoningbank/utils/embeddings.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Embedding generation for semantic similarity\n * Uses local transformers.js - no API key required!\n *\n * Logs go to stderr so that stdout stays clean for callers that pipe\n * structured output (CLIs, MCP stdio servers).\n */\n\nimport { pipeline, env } from '@huggingface/transformers';\nimport { loadConfig } from './config.js';\n\n// Configure transformers.js to use WASM backend only (avoid ONNX runtime issues)\n// The native ONNX runtime causes \"DefaultLogger not registered\" errors in Node.js\nenv.backends.onnx.wasm.proxy = false; // Disable ONNX runtime proxy\nenv.backends.onnx.wasm.numThreads = 1; // Single thread for stability\n\nconst MODEL_ID = 'Xenova/all-MiniLM-L6-v2';\nconst MODEL_DIMS = 384;\nconst CACHE_MAX_ENTRIES = 1000;\n// Texts per pipeline call in computeEmbeddingBatch. Bounds padding waste and\n// peak memory when a batch mixes short and long texts.\n//\n// The q8 model quantizes activations dynamically with one scale per tensor, so\n// a batched vector depends slightly on its batch-mates: cosine vs. the same\n// text embedded alone is ~0.99 (min ~0.985 measured). fp32 weights are exact\n// but slower for single texts and change every stored vector.\nconst BATCH_CHUNK_SIZE = 32;\n\nlet embeddingPipeline: any = null;\nlet initializationPromise: Promise<void> | null = null;\n\n/**\n * LRU cache with lazy TTL expiry. No timers: an expired entry is dropped when\n * it is next read, so the cache never keeps the event loop alive.\n */\ninterface CacheEntry {\n vector: Float32Array;\n expiresAt: number;\n}\nconst embeddingCache = new Map<string, CacheEntry>();\n\nfunction cacheGet(key: string): Float32Array | undefined {\n const entry = embeddingCache.get(key);\n if (!entry) return undefined;\n embeddingCache.delete(key);\n if (entry.expiresAt <= Date.now()) return undefined;\n embeddingCache.set(key, entry); // move to most-recently-used\n return entry.vector;\n}\n\nfunction cacheSet(key: string, vector: Float32Array, ttlSeconds: number): void {\n embeddingCache.delete(key);\n embeddingCache.set(key, { vector, expiresAt: Date.now() + ttlSeconds * 1000 });\n while (embeddingCache.size > CACHE_MAX_ENTRIES) {\n const oldest = embeddingCache.keys().next().value;\n if (oldest === undefined) break;\n embeddingCache.delete(oldest);\n }\n}\n\nfunction cacheTtlSeconds(): number {\n return loadConfig()?.embeddings?.cache_ttl_seconds || 3600;\n}\n\n/**\n * Initialize the embedding pipeline (lazy load)\n * RACE CONDITION FIX: Use promise-based initialization instead of busy-wait\n */\nasync function initializeEmbeddings(): Promise<void> {\n // Already initialized\n if (embeddingPipeline) return;\n\n // Initialization in progress - await existing promise\n if (initializationPromise) {\n return initializationPromise;\n }\n\n // RACE CONDITION FIX: Create promise for concurrent callers to await\n initializationPromise = (async () => {\n console.error(`[Embeddings] Initializing local embedding model (${MODEL_ID})...`);\n console.error('[Embeddings] First run will download ~23MB model...');\n\n try {\n embeddingPipeline = await pipeline(\n 'feature-extraction',\n MODEL_ID,\n { dtype: 'q8' } // quantized weights\n );\n console.error(`[Embeddings] Local model ready! (${MODEL_DIMS} dimensions)`);\n } catch (error: any) {\n console.error('[Embeddings] Failed to initialize:', error?.message || error);\n console.error('[Embeddings] Falling back to hash-based embeddings (not semantic)');\n // Reset promise so retry is possible\n initializationPromise = null;\n }\n })();\n\n return initializationPromise;\n}\n\n/**\n * True when embeddings come from the transformer model; false when they come\n * from the deterministic hash fallback, whose vectors carry no semantic\n * similarity. Returns false until the first embedding call has initialized the\n * model.\n */\nexport function isSemanticEmbedding(): boolean {\n return embeddingPipeline !== null;\n}\n\n/**\n * Compute embedding for text using local model\n */\nexport async function computeEmbedding(text: string): Promise<Float32Array> {\n const cached = cacheGet(`local:${text}`) ?? cacheGet(`hash:${text}`);\n if (cached) return cached;\n\n // Initialize if needed\n await initializeEmbeddings();\n\n let embedding: Float32Array;\n let kind: 'local' | 'hash' = 'local';\n\n if (embeddingPipeline) {\n try {\n const output = await embeddingPipeline(text, {\n pooling: 'mean',\n normalize: true\n });\n embedding = new Float32Array(output.data);\n } catch (error: any) {\n console.error('[Embeddings] Generation failed:', error?.message || error);\n embedding = hashEmbed(text, MODEL_DIMS);\n kind = 'hash';\n }\n } else {\n const dims = loadConfig()?.embeddings?.dimensions || MODEL_DIMS;\n embedding = hashEmbed(text, dims);\n kind = 'hash';\n }\n\n cacheSet(`${kind}:${text}`, embedding, cacheTtlSeconds());\n return embedding;\n}\n\n/**\n * Batch compute embeddings. Cache misses are embedded with one pipeline call\n * per chunk of texts rather than one call per text.\n */\nexport async function computeEmbeddingBatch(texts: string[]): Promise<Float32Array[]> {\n await initializeEmbeddings();\n if (!embeddingPipeline) {\n return Promise.all(texts.map(text => computeEmbedding(text)));\n }\n\n const results: Float32Array[] = new Array(texts.length);\n const missing = new Map<string, number[]>(); // text -> result indices\n\n texts.forEach((text, i) => {\n const cached = cacheGet(`local:${text}`);\n if (cached) {\n results[i] = cached;\n return;\n }\n const indices = missing.get(text);\n if (indices) indices.push(i);\n else missing.set(text, [i]);\n });\n\n const ttl = cacheTtlSeconds();\n const uniqueTexts = Array.from(missing.keys());\n\n for (let start = 0; start < uniqueTexts.length; start += BATCH_CHUNK_SIZE) {\n const chunk = uniqueTexts.slice(start, start + BATCH_CHUNK_SIZE);\n let vectors: Float32Array[];\n let kind: 'local' | 'hash' = 'local';\n\n try {\n const output = await embeddingPipeline(chunk, { pooling: 'mean', normalize: true });\n const dims = output.dims[output.dims.length - 1];\n const data = output.data as Float32Array;\n vectors = chunk.map((_, j) => new Float32Array(data.subarray(j * dims, (j + 1) * dims)));\n } catch (error: any) {\n console.error('[Embeddings] Batch generation failed:', error?.message || error);\n vectors = chunk.map(text => hashEmbed(text, MODEL_DIMS));\n kind = 'hash';\n }\n\n chunk.forEach((text, j) => {\n cacheSet(`${kind}:${text}`, vectors[j], ttl);\n for (const i of missing.get(text)!) results[i] = vectors[j];\n });\n }\n\n return results;\n}\n\n/**\n * Get embedding dimensions\n */\nexport function getEmbeddingDimensions(): number {\n return MODEL_DIMS; // all-MiniLM-L6-v2 uses 384 dimensions\n}\n\n/**\n * Deterministic hash-based embedding (fallback)\n */\nfunction hashEmbed(text: string, dims: number): Float32Array {\n const hash = simpleHash(text);\n const vec = new Float32Array(dims);\n\n // Generate deterministic pseudo-random vector from hash\n for (let i = 0; i < dims; i++) {\n vec[i] = Math.sin(hash * (i + 1) * 0.01) + Math.cos(hash * i * 0.02);\n }\n\n return normalize(vec);\n}\n\n/**\n * Simple string hash function\n */\nfunction simpleHash(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) - hash) + str.charCodeAt(i);\n hash |= 0;\n }\n return Math.abs(hash);\n}\n\n/**\n * Normalize vector to unit length\n */\nfunction normalize(vec: Float32Array): Float32Array {\n let mag = 0;\n for (let i = 0; i < vec.length; i++) {\n mag += vec[i] * vec[i];\n }\n mag = Math.sqrt(mag);\n\n if (mag === 0) return vec;\n\n for (let i = 0; i < vec.length; i++) {\n vec[i] /= mag;\n }\n return vec;\n}\n\n/**\n * Clear embedding cache\n */\nexport function clearEmbeddingCache(): void {\n embeddingCache.clear();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../../../src/reasoningbank/utils/embeddings.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Embedding generation for semantic similarity\n * Uses local transformers.js - no API key required!\n *\n * Logs go to stderr so that stdout stays clean for callers that pipe\n * structured output (CLIs, MCP stdio servers).\n */\n\nimport { pipeline, env } from '@huggingface/transformers';\nimport { loadConfig } from './config.js';\n\n// Configure transformers.js to use WASM backend only (avoid ONNX runtime issues)\n// The native ONNX runtime causes \"DefaultLogger not registered\" errors in Node.js\nenv.backends.onnx.wasm.proxy = false; // Disable ONNX runtime proxy\nenv.backends.onnx.wasm.numThreads = 1; // Single thread for stability\n\nconst MODEL_ID = 'Xenova/all-MiniLM-L6-v2';\nconst MODEL_DIMS = 384;\nconst CACHE_MAX_ENTRIES = 1000;\n// Texts per pipeline call in computeEmbeddingBatch. Bounds padding waste and\n// peak memory when a batch mixes short and long texts.\n//\n// The q8 model quantizes activations dynamically with one scale per tensor, so\n// a batched vector depends slightly on its batch-mates: cosine vs. the same\n// text embedded alone is ~0.99 (min ~0.985 measured). fp32 weights are exact\n// but slower for single texts and change every stored vector.\nconst BATCH_CHUNK_SIZE = 32;\n\nlet embeddingPipeline: any = null;\nlet initializationPromise: Promise<void> | null = null;\n\n/**\n * The space every vector in this process belongs to. Set by the first\n * embedding and kept until resetEmbeddingBackend(): model vectors and hash\n * vectors are not comparable, so a process never mixes them (issue #246).\n */\nexport type EmbeddingKind = 'local' | 'hash';\nlet embeddingKind: EmbeddingKind | null = null;\n\n/**\n * LRU cache with lazy TTL expiry. No timers: an expired entry is dropped when\n * it is next read, so the cache never keeps the event loop alive.\n */\ninterface CacheEntry {\n vector: Float32Array;\n expiresAt: number;\n}\nconst embeddingCache = new Map<string, CacheEntry>();\n\nfunction cacheGet(key: string): Float32Array | undefined {\n const entry = embeddingCache.get(key);\n if (!entry) return undefined;\n embeddingCache.delete(key);\n if (entry.expiresAt <= Date.now()) return undefined;\n embeddingCache.set(key, entry); // move to most-recently-used\n return entry.vector;\n}\n\nfunction cacheSet(key: string, vector: Float32Array, ttlSeconds: number): void {\n embeddingCache.delete(key);\n embeddingCache.set(key, { vector, expiresAt: Date.now() + ttlSeconds * 1000 });\n while (embeddingCache.size > CACHE_MAX_ENTRIES) {\n const oldest = embeddingCache.keys().next().value;\n if (oldest === undefined) break;\n embeddingCache.delete(oldest);\n }\n}\n\nfunction cacheTtlSeconds(): number {\n return loadConfig()?.embeddings?.cache_ttl_seconds || 3600;\n}\n\n/**\n * Initialize the embedding pipeline (lazy load)\n * RACE CONDITION FIX: Use promise-based initialization instead of busy-wait\n */\nasync function initializeEmbeddings(): Promise<void> {\n // Already initialized\n if (embeddingPipeline) return;\n\n // Initialization in progress - await existing promise\n if (initializationPromise) {\n return initializationPromise;\n }\n\n // RACE CONDITION FIX: Create promise for concurrent callers to await\n initializationPromise = (async () => {\n console.error(`[Embeddings] Initializing local embedding model (${MODEL_ID})...`);\n console.error('[Embeddings] First run will download ~23MB model...');\n\n try {\n embeddingPipeline = await pipeline(\n 'feature-extraction',\n MODEL_ID,\n { dtype: 'q8' } // quantized weights\n );\n console.error(`[Embeddings] Local model ready! (${MODEL_DIMS} dimensions)`);\n } catch (error: any) {\n console.error('[Embeddings] Failed to initialize:', error?.message || error);\n console.error('[Embeddings] Falling back to hash-based embeddings (not semantic)');\n // No automatic retry: a later successful load would put new vectors in a\n // different space from the hash vectors already handed out. Call\n // resetEmbeddingBackend() to try the model again.\n }\n })();\n\n return initializationPromise;\n}\n\n/**\n * True when embeddings come from the transformer model; false when they come\n * from the deterministic hash fallback, whose vectors carry no semantic\n * similarity. Returns false until the first embedding call has initialized the\n * model.\n */\nexport function isSemanticEmbedding(): boolean {\n return embeddingKind === 'local' || (embeddingKind === null && embeddingPipeline !== null);\n}\n\n/**\n * The space this process's embeddings are in, or null before the first one.\n * Vectors of different kinds must never be compared.\n */\nexport function getEmbeddingKind(): EmbeddingKind | null {\n return embeddingKind;\n}\n\n/**\n * Forget the backend choice and the cache, so the next embedding tries to load\n * the model again. Vectors produced before the reset may be in a different\n * space from those produced after it; re-embed anything you keep.\n */\nexport function resetEmbeddingBackend(): void {\n embeddingPipeline = null;\n initializationPromise = null;\n embeddingKind = null;\n embeddingCache.clear();\n}\n\n/** Fix the process to one space on first use; refuse to switch afterwards. */\nfunction commitKind(kind: EmbeddingKind): void {\n if (embeddingKind === null) embeddingKind = kind;\n else if (embeddingKind !== kind) {\n throw new Error(\n `[Embeddings] refusing to produce a ${kind} vector: this process already embeds with ${embeddingKind}`\n );\n }\n}\n\nfunction modelFailure(error: any): Error {\n return new Error(\n `[Embeddings] model failed (${error?.message || error}); not substituting a hash vector, which would not be comparable with the model vectors already produced`\n );\n}\n\n/**\n * Compute embedding for text using local model\n */\nexport async function computeEmbedding(text: string): Promise<Float32Array> {\n const cached = cacheGet(text);\n if (cached) return cached;\n\n // A process already in the hash space stays there; don't load the model.\n if (embeddingKind !== 'hash') await initializeEmbeddings();\n\n let embedding: Float32Array;\n if (embeddingPipeline) {\n commitKind('local');\n try {\n const output = await embeddingPipeline(text, {\n pooling: 'mean',\n normalize: true\n });\n embedding = new Float32Array(output.data);\n } catch (error: any) {\n console.error('[Embeddings] Generation failed:', error?.message || error);\n throw modelFailure(error);\n }\n } else {\n commitKind('hash');\n const dims = loadConfig()?.embeddings?.dimensions || MODEL_DIMS;\n embedding = hashEmbed(text, dims);\n }\n\n cacheSet(text, embedding, cacheTtlSeconds());\n return embedding;\n}\n\n/**\n * Batch compute embeddings. Cache misses are embedded with one pipeline call\n * per chunk of texts rather than one call per text.\n */\nexport async function computeEmbeddingBatch(texts: string[]): Promise<Float32Array[]> {\n if (embeddingKind !== 'hash') await initializeEmbeddings();\n if (!embeddingPipeline) {\n return Promise.all(texts.map(text => computeEmbedding(text)));\n }\n commitKind('local');\n\n const results: Float32Array[] = new Array(texts.length);\n const missing = new Map<string, number[]>(); // text -> result indices\n\n texts.forEach((text, i) => {\n const cached = cacheGet(text);\n if (cached) {\n results[i] = cached;\n return;\n }\n const indices = missing.get(text);\n if (indices) indices.push(i);\n else missing.set(text, [i]);\n });\n\n const ttl = cacheTtlSeconds();\n const uniqueTexts = Array.from(missing.keys());\n\n for (let start = 0; start < uniqueTexts.length; start += BATCH_CHUNK_SIZE) {\n const chunk = uniqueTexts.slice(start, start + BATCH_CHUNK_SIZE);\n let vectors: Float32Array[];\n\n try {\n const output = await embeddingPipeline(chunk, { pooling: 'mean', normalize: true });\n const dims = output.dims[output.dims.length - 1];\n const data = output.data as Float32Array;\n vectors = chunk.map((_, j) => new Float32Array(data.subarray(j * dims, (j + 1) * dims)));\n } catch (error: any) {\n console.error('[Embeddings] Batch generation failed:', error?.message || error);\n throw modelFailure(error);\n }\n\n chunk.forEach((text, j) => {\n cacheSet(text, vectors[j], ttl);\n for (const i of missing.get(text)!) results[i] = vectors[j];\n });\n }\n\n return results;\n}\n\n/**\n * Get embedding dimensions\n */\nexport function getEmbeddingDimensions(): number {\n return MODEL_DIMS; // all-MiniLM-L6-v2 uses 384 dimensions\n}\n\n/**\n * Deterministic hash-based embedding (fallback)\n */\nfunction hashEmbed(text: string, dims: number): Float32Array {\n const hash = simpleHash(text);\n const vec = new Float32Array(dims);\n\n // Generate deterministic pseudo-random vector from hash\n for (let i = 0; i < dims; i++) {\n vec[i] = Math.sin(hash * (i + 1) * 0.01) + Math.cos(hash * i * 0.02);\n }\n\n return normalize(vec);\n}\n\n/**\n * Simple string hash function\n */\nfunction simpleHash(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) - hash) + str.charCodeAt(i);\n hash |= 0;\n }\n return Math.abs(hash);\n}\n\n/**\n * Normalize vector to unit length\n */\nfunction normalize(vec: Float32Array): Float32Array {\n let mag = 0;\n for (let i = 0; i < vec.length; i++) {\n mag += vec[i] * vec[i];\n }\n mag = Math.sqrt(mag);\n\n if (mag === 0) return vec;\n\n for (let i = 0; i < vec.length; i++) {\n vec[i] /= mag;\n }\n return vec;\n}\n\n/**\n * Clear embedding cache\n */\nexport function clearEmbeddingCache(): void {\n embeddingCache.clear();\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version from this package's package.json, found by walking up from this
|
|
3
|
+
* file (src/utils under tsx, dist/utils when built). Throws if it is missing,
|
|
4
|
+
* which only happens in a broken install, rather than falling back to a tag.
|
|
5
|
+
*/
|
|
6
|
+
export declare function readPackageVersion(): string;
|
|
7
|
+
/** `agentic-flow@<installed version>`, for npx commands. */
|
|
8
|
+
export declare function packageSpec(): string;
|
|
9
|
+
//# sourceMappingURL=package-version.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-version.d.ts","sourceRoot":"","sources":["../../src/utils/package-version.ts"],"names":[],"mappings":"AAYA;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAgB3C;AAED,4DAA4D;AAC5D,wBAAgB,WAAW,IAAI,MAAM,CAEpC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// The installed agentic-flow version, for commands we write or print.
|
|
2
|
+
//
|
|
3
|
+
// Generated hooks, statuslines and help text run `npx agentic-flow@<this>`,
|
|
4
|
+
// never a dist-tag: @alpha still resolves to the deprecated March 3.0.0-alpha
|
|
5
|
+
// line, and @latest changes under an installed project without notice.
|
|
6
|
+
import * as fs from 'fs';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
const VERSION_RE = /^\d+\.\d+\.\d+[\w.+-]*$/;
|
|
10
|
+
let cached;
|
|
11
|
+
/**
|
|
12
|
+
* Version from this package's package.json, found by walking up from this
|
|
13
|
+
* file (src/utils under tsx, dist/utils when built). Throws if it is missing,
|
|
14
|
+
* which only happens in a broken install, rather than falling back to a tag.
|
|
15
|
+
*/
|
|
16
|
+
export function readPackageVersion() {
|
|
17
|
+
if (cached)
|
|
18
|
+
return cached;
|
|
19
|
+
let dir = path.dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
for (;;) {
|
|
21
|
+
const file = path.join(dir, 'package.json');
|
|
22
|
+
if (fs.existsSync(file)) {
|
|
23
|
+
const pkg = JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
24
|
+
if (pkg.name === 'agentic-flow' && typeof pkg.version === 'string' && VERSION_RE.test(pkg.version)) {
|
|
25
|
+
cached = pkg.version;
|
|
26
|
+
return cached;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const parent = path.dirname(dir);
|
|
30
|
+
if (parent === dir)
|
|
31
|
+
throw new Error('agentic-flow: cannot find its own package.json to pin the version');
|
|
32
|
+
dir = parent;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** `agentic-flow@<installed version>`, for npx commands. */
|
|
36
|
+
export function packageSpec() {
|
|
37
|
+
return `agentic-flow@${readPackageVersion()}`;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=package-version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-version.js","sourceRoot":"","sources":["../../src/utils/package-version.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,uEAAuE;AACvE,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,UAAU,GAAG,yBAAyB,CAAC;AAC7C,IAAI,MAA0B,CAAC;AAE/B;;;;GAIG;AACH,MAAM,UAAU,kBAAkB;IAChC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACvD,SAAS,CAAC;QACR,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAC5C,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;YACvD,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBACnG,MAAM,GAAG,GAAG,CAAC,OAAiB,CAAC;gBAC/B,OAAO,MAAM,CAAC;YAChB,CAAC;QACH,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;QACzG,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,WAAW;IACzB,OAAO,gBAAgB,kBAAkB,EAAE,EAAE,CAAC;AAChD,CAAC","sourcesContent":["// The installed agentic-flow version, for commands we write or print.\n//\n// Generated hooks, statuslines and help text run `npx agentic-flow@<this>`,\n// never a dist-tag: @alpha still resolves to the deprecated March 3.0.0-alpha\n// line, and @latest changes under an installed project without notice.\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { fileURLToPath } from 'url';\n\nconst VERSION_RE = /^\\d+\\.\\d+\\.\\d+[\\w.+-]*$/;\nlet cached: string | undefined;\n\n/**\n * Version from this package's package.json, found by walking up from this\n * file (src/utils under tsx, dist/utils when built). Throws if it is missing,\n * which only happens in a broken install, rather than falling back to a tag.\n */\nexport function readPackageVersion(): string {\n if (cached) return cached;\n let dir = path.dirname(fileURLToPath(import.meta.url));\n for (;;) {\n const file = path.join(dir, 'package.json');\n if (fs.existsSync(file)) {\n const pkg = JSON.parse(fs.readFileSync(file, 'utf-8'));\n if (pkg.name === 'agentic-flow' && typeof pkg.version === 'string' && VERSION_RE.test(pkg.version)) {\n cached = pkg.version as string;\n return cached;\n }\n }\n const parent = path.dirname(dir);\n if (parent === dir) throw new Error('agentic-flow: cannot find its own package.json to pin the version');\n dir = parent;\n }\n}\n\n/** `agentic-flow@<installed version>`, for npx commands. */\nexport function packageSpec(): string {\n return `agentic-flow@${readPackageVersion()}`;\n}\n"]}
|
|
@@ -6,8 +6,8 @@ RUN apk add --no-cache python3 make g++ sqlite sqlite-dev
|
|
|
6
6
|
WORKDIR /test
|
|
7
7
|
|
|
8
8
|
RUN echo "========================================" && \
|
|
9
|
-
echo "Testing npx agentic-flow@
|
|
9
|
+
echo "Testing npx agentic-flow@1.7.8" && \
|
|
10
10
|
echo "========================================" && \
|
|
11
|
-
npx agentic-flow@
|
|
11
|
+
npx agentic-flow@1.7.8 --version 2>&1 | head -20
|
|
12
12
|
|
|
13
13
|
CMD ["echo", "✅ Test complete"]
|
|
@@ -6,8 +6,8 @@ RUN apk add --no-cache python3 make g++ sqlite sqlite-dev
|
|
|
6
6
|
WORKDIR /test
|
|
7
7
|
|
|
8
8
|
RUN echo "========================================" && \
|
|
9
|
-
echo "Testing npx agentic-flow@
|
|
9
|
+
echo "Testing npx agentic-flow@1.7.9 with Node 20" && \
|
|
10
10
|
echo "========================================" && \
|
|
11
|
-
npx agentic-flow@
|
|
11
|
+
npx agentic-flow@1.7.9 --version 2>&1
|
|
12
12
|
|
|
13
13
|
CMD ["echo", "✅ Test complete"]
|
|
@@ -6,9 +6,9 @@ RUN apk add --no-cache python3 make g++ sqlite sqlite-dev
|
|
|
6
6
|
WORKDIR /test
|
|
7
7
|
|
|
8
8
|
RUN echo "========================================" && \
|
|
9
|
-
echo "Testing npx agentic-flow@
|
|
9
|
+
echo "Testing npx agentic-flow@1.7.9" && \
|
|
10
10
|
echo "Expecting v1.7.9 with better-sqlite3 v11.x" && \
|
|
11
11
|
echo "========================================" && \
|
|
12
|
-
npx agentic-flow@
|
|
12
|
+
npx agentic-flow@1.7.9 --version 2>&1 | head -20
|
|
13
13
|
|
|
14
14
|
CMD ["echo", "✅ Test complete"]
|
|
@@ -31,18 +31,29 @@ This command:
|
|
|
31
31
|
|
|
32
32
|
**Terminal 1 - Start Proxy:**
|
|
33
33
|
```bash
|
|
34
|
+
export OPENROUTER_API_KEY=sk-or-v1-...
|
|
34
35
|
npx agentic-flow proxy --provider openrouter --port 3000
|
|
36
|
+
# Prints: export ANTHROPIC_API_KEY=sk-ant-proxy-... (a new token every run)
|
|
35
37
|
```
|
|
36
38
|
|
|
37
39
|
**Terminal 2 - Use Claude Code:**
|
|
38
40
|
```bash
|
|
39
41
|
# Inline environment variables (cleanest native approach)
|
|
40
42
|
ANTHROPIC_BASE_URL=http://localhost:3000 \
|
|
41
|
-
ANTHROPIC_API_KEY=
|
|
42
|
-
OPENROUTER_API_KEY=$OPENROUTER_API_KEY \
|
|
43
|
+
ANTHROPIC_API_KEY='<token printed by the proxy>' \
|
|
43
44
|
claude "Write a Python function to sort a list"
|
|
44
45
|
```
|
|
45
46
|
|
|
47
|
+
The provider key stays with the proxy; Claude Code only needs the proxy token.
|
|
48
|
+
|
|
49
|
+
**Authentication (3.0.0+).** The proxy binds `127.0.0.1` and rejects any
|
|
50
|
+
`/v1/messages` request without its token, so nobody else on your network can
|
|
51
|
+
spend your provider key. On start it prints a random per-run token; pass it as
|
|
52
|
+
`ANTHROPIC_API_KEY` (sent as `x-api-key`) or as `Authorization: Bearer`. To
|
|
53
|
+
keep the same token across restarts, set `AGENTIC_FLOW_PROXY_TOKEN` before
|
|
54
|
+
starting the proxy and use that value. `AGENTIC_FLOW_PROXY_HOST` changes the
|
|
55
|
+
bind address; only widen it on a network you trust. `/health` needs no token.
|
|
56
|
+
|
|
46
57
|
---
|
|
47
58
|
|
|
48
59
|
### Option 3: Bash Wrapper Script
|
|
@@ -232,8 +243,7 @@ npx agentic-flow claude-code \
|
|
|
232
243
|
4. **Wrapper spawns Claude Code with env:**
|
|
233
244
|
```bash
|
|
234
245
|
ANTHROPIC_BASE_URL=http://localhost:3000
|
|
235
|
-
ANTHROPIC_API_KEY
|
|
236
|
-
OPENROUTER_API_KEY=sk-or-v1-xxxxx
|
|
246
|
+
ANTHROPIC_API_KEY=<the proxy's per-run token>
|
|
237
247
|
claude "task"
|
|
238
248
|
```
|
|
239
249
|
|
|
@@ -309,7 +319,7 @@ VERBOSE=true npx agentic-flow proxy --provider openrouter
|
|
|
309
319
|
# In another terminal, test with curl
|
|
310
320
|
curl -X POST http://localhost:3000/v1/messages \
|
|
311
321
|
-H "Content-Type: application/json" \
|
|
312
|
-
-H "x-api-key:
|
|
322
|
+
-H "x-api-key: <token printed by the proxy>" \
|
|
313
323
|
-d '{"model":"claude-3-5-sonnet-20241022","messages":[{"role":"user","content":"hello"}],"max_tokens":100}'
|
|
314
324
|
```
|
|
315
325
|
|
|
@@ -361,14 +371,21 @@ proxy.start(3000);
|
|
|
361
371
|
|
|
362
372
|
### Environment Variable Presets
|
|
363
373
|
|
|
364
|
-
Create `~/.agentic-flow-presets
|
|
374
|
+
Create `~/.agentic-flow-presets`. The proxies require a token, so give each
|
|
375
|
+
one a fixed token with `AGENTIC_FLOW_PROXY_TOKEN` when you start it and reuse
|
|
376
|
+
it here:
|
|
365
377
|
|
|
366
378
|
```bash
|
|
379
|
+
# Start the proxies with a stable token, e.g.
|
|
380
|
+
# AGENTIC_FLOW_PROXY_TOKEN=$AF_PROXY_TOKEN npx agentic-flow proxy --provider openrouter --port 3000
|
|
381
|
+
# AGENTIC_FLOW_PROXY_TOKEN=$AF_PROXY_TOKEN npx agentic-flow proxy --provider gemini --port 3001
|
|
382
|
+
export AF_PROXY_TOKEN="sk-ant-proxy-$(openssl rand -hex 32)"
|
|
383
|
+
|
|
367
384
|
# OpenRouter preset
|
|
368
|
-
alias claude-openrouter='ANTHROPIC_BASE_URL=http://localhost:3000 ANTHROPIC_API_KEY
|
|
385
|
+
alias claude-openrouter='ANTHROPIC_BASE_URL=http://localhost:3000 ANTHROPIC_API_KEY=$AF_PROXY_TOKEN claude'
|
|
369
386
|
|
|
370
387
|
# Gemini preset
|
|
371
|
-
alias claude-gemini='ANTHROPIC_BASE_URL=http://localhost:3001 ANTHROPIC_API_KEY
|
|
388
|
+
alias claude-gemini='ANTHROPIC_BASE_URL=http://localhost:3001 ANTHROPIC_API_KEY=$AF_PROXY_TOKEN claude'
|
|
372
389
|
|
|
373
390
|
# Usage
|
|
374
391
|
claude-openrouter "Write code"
|