@warlock.js/ai 4.8.0 → 4.8.1
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/CHANGELOG.md +6 -0
- package/cjs/index.cjs +1 -1
- package/cjs/{src-DTlN47aO.cjs → src-5ze7nVpa.cjs} +5 -3
- package/cjs/src-5ze7nVpa.cjs.map +1 -0
- package/cjs/{src-DBn2_pbG.cjs → src-DTQ4KgBu.cjs} +1 -1
- package/esm/ai.mjs +1 -0
- package/esm/ai.mjs.map +1 -1
- package/esm/config.d.mts.map +1 -1
- package/esm/config.mjs +5 -1
- package/esm/config.mjs.map +1 -1
- package/esm/index.mjs +1 -0
- package/esm/memory/index.mjs +3 -0
- package/esm/skills/store/procedural-skill-store.mjs +1 -0
- package/esm/skills/store/procedural-skill-store.mjs.map +1 -1
- package/package.json +3 -3
- package/cjs/src-DTlN47aO.cjs.map +0 -1
|
@@ -25,6 +25,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
25
25
|
}) : target, mod));
|
|
26
26
|
|
|
27
27
|
//#endregion
|
|
28
|
-
require('./src-
|
|
28
|
+
require('./src-5ze7nVpa.cjs');
|
|
29
29
|
let _warlock_js_logger = require("@warlock.js/logger");
|
|
30
30
|
require("openai");
|
package/esm/ai.mjs
CHANGED
|
@@ -7,6 +7,7 @@ import { forTool } from "./middleware/helpers/for-tool.mjs";
|
|
|
7
7
|
import { tool } from "./tool/tool.mjs";
|
|
8
8
|
import { skills } from "./skills/skills.mjs";
|
|
9
9
|
import { memory } from "./memory/memory.mjs";
|
|
10
|
+
import "./memory/index.mjs";
|
|
10
11
|
import "./skills/index.mjs";
|
|
11
12
|
import { agent } from "./agent/agent.mjs";
|
|
12
13
|
import { spawnSubAgent } from "./agent/spawn-sub-agent.mjs";
|
package/esm/ai.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai.mjs","names":["checkpointMemory","checkpointPg","checkpointRedis","snapshotMemory","snapshotPg","snapshotRedis","guardrailSuite"],"sources":["../../../../../../@warlock.js/ai/src/ai.ts"],"sourcesContent":["import { agent } from \"./agent/agent\";\nimport { batch } from \"./batch\";\nimport { streamObject } from \"./object-stream\";\nimport { serve } from \"./serve\";\nimport {\n checkpointMemory,\n checkpointPg,\n checkpointRedis,\n} from \"./checkpoint\";\nimport { setAIConfig } from \"./config\";\nimport { dataset, evalScorers } from \"./eval\";\nimport { humanApproval } from \"./human/human-approval\";\nimport { human } from \"./human/register\";\nimport { image } from \"./image\";\nimport { speech } from \"./speech\";\nimport {\n audioFromBuffer,\n audioFromFile,\n audioMediaTypeForFilename,\n transcribe,\n} from \"./transcribe\";\nimport { resume } from \"./human/resume\";\nimport {\n interruptMemory,\n interruptPg,\n interruptRedis,\n} from \"./human/stores\";\nimport { guardrail as guardrailSuite } from \"./guard/guardrail\";\nimport { budget, readBudgetFallbackSignal } from \"./middleware/builtins/budget\";\nimport { memory } from \"./memory\";\nimport { guardrail } from \"./middleware/builtins/guardrail\";\nimport { semanticCache } from \"./middleware/builtins/semantic-cache\";\nimport { composeMiddleware, forTool } from \"./middleware/helpers\";\nimport { mockRouter } from \"./mock\";\nimport { fallbackModel } from \"./model\";\nimport { orchestrator } from \"./orchestrator\";\nimport { planner } from \"./planner\";\nimport { defaultPromptsManager } from \"./prompts/prompts-manager\";\nimport {\n bm25Rank,\n cacheVectorStore,\n chunk,\n hybridRank,\n keywordReranker,\n llmReranker,\n loadHtml,\n loadPdf,\n loadText,\n loadWeb,\n multiQuery,\n pgVectorStore,\n rag,\n reciprocalRankFusion,\n vectorLiteral,\n} from \"./rag\";\nimport { spawnSubAgent } from \"./agent/spawn-sub-agent\";\nimport { skills } from \"./skills\";\nimport { prompt } from \"./prompt\";\nimport { vcr } from \"./vcr\";\nimport { snapshotMemory, snapshotPg, snapshotRedis } from \"./snapshot\";\nimport { fanOut, router } from \"./supervisor\";\nimport { supervisor } from \"./supervisor/supervisor\";\nimport { team } from \"./team/team\";\nimport { instruction } from \"./system-prompt/instruction\";\nimport { persona } from \"./system-prompt/persona\";\nimport { systemPrompt } from \"./system-prompt/system-prompt\";\nimport { tool } from \"./tool/tool\";\nimport { step } from \"./workflow/step\";\nimport { workflow } from \"./workflow/workflow\";\n\n/**\n * The shape of the top-level `ai` namespace. Declared as an `interface` (not an\n * inferred `const` type) so satellite packages can attach their verb via\n * `declare module \"@warlock.js/ai\" { interface Ai { … } }` — e.g. `ai.workspace`,\n * `ai.tools`, `ai.mcp`, `ai.human`. The runtime object below is asserted to this\n * type; a satellite assigns its member on import.\n */\nexport interface Ai {\n config: typeof setAIConfig;\n tool: typeof tool;\n agent: typeof agent;\n systemPrompt: typeof systemPrompt;\n persona: typeof persona;\n instruction: typeof instruction;\n workflow: typeof workflow;\n step: typeof step;\n supervisor: typeof supervisor;\n team: typeof team;\n orchestrator: typeof orchestrator;\n memory: typeof memory;\n skills: typeof skills;\n planner: typeof planner;\n rag: typeof rag & {\n keywordReranker: typeof keywordReranker;\n llmReranker: typeof llmReranker;\n chunk: typeof chunk;\n cacheVectorStore: typeof cacheVectorStore;\n pgVectorStore: typeof pgVectorStore;\n vectorLiteral: typeof vectorLiteral;\n loadText: typeof loadText;\n loadHtml: typeof loadHtml;\n loadWeb: typeof loadWeb;\n loadPdf: typeof loadPdf;\n bm25Rank: typeof bm25Rank;\n reciprocalRankFusion: typeof reciprocalRankFusion;\n hybridRank: typeof hybridRank;\n multiQuery: typeof multiQuery;\n };\n spawnSubAgent: typeof spawnSubAgent;\n router: typeof router;\n fanOut: typeof fanOut;\n batch: typeof batch;\n /** Structured-output streaming — partial-object snapshots + a strict final parse (A1). */\n streamObject: typeof streamObject;\n /** Serve an executable as an SSE HTTP endpoint — production serving primitive (A3). */\n serve: typeof serve;\n /**\n * Generate images from a text prompt — the image-output verb of the\n * output-modality track (Theme I). Wraps an `ImageModelContract` (from\n * `openai.image(...)` / `google.image(...)`) in the uniform\n * never-throws `{ data, error, usage, report }` envelope with cost-truth\n * and observability.\n */\n image: typeof image;\n /** Text-to-speech (TTS) — the audio-output verb of the modality track (Theme I). */\n speech: typeof speech;\n /** Speech-to-text (STT / transcription) — the audio-input verb of the modality track (Theme I). */\n transcribe: typeof transcribe;\n /** Read an audio file from disk → `AudioInput` for `ai.transcribe` (non-AI file plumbing). */\n audioFromFile: typeof audioFromFile;\n /** Package raw audio bytes → `AudioInput` for `ai.transcribe`. */\n audioFromBuffer: typeof audioFromBuffer;\n /** Resolve the audio media type from a filename's extension. */\n audioMediaTypeForFilename: typeof audioMediaTypeForFilename;\n fallbackModel: typeof fallbackModel;\n eval: typeof evalScorers;\n dataset: typeof dataset;\n prompt: typeof prompt;\n /**\n * Process-wide registry of named, versioned `systemPrompt(...)` builders,\n * keyed by `name@version`. A `systemPrompt(input, { name })` (or any\n * `.meta({ name })` rename) auto-registers here; `ai.prompts.get(name)` /\n * `.resolve(name)` reads them back, and `systemPrompt().merge(name)` folds a\n * registered prompt into a new one.\n */\n prompts: ReturnType<typeof defaultPromptsManager>;\n vcr: typeof vcr;\n mockRouter: typeof mockRouter;\n middleware: {\n budget: typeof budget;\n guardrail: typeof guardrail;\n semanticCache: typeof semanticCache;\n compose: typeof composeMiddleware;\n forTool: typeof forTool;\n readBudgetFallbackSignal: typeof readBudgetFallbackSignal;\n };\n checkpoint: {\n memory: typeof checkpointMemory;\n pg: typeof checkpointPg;\n redis: typeof checkpointRedis;\n };\n snapshot: {\n memory: typeof snapshotMemory;\n pg: typeof snapshotPg;\n redis: typeof snapshotRedis;\n };\n /**\n * Human-in-the-loop tool approval (interrupt / resume).\n *\n * - `human.approval(options)` — the `tool.before` approval-gate middleware.\n * - `human.resume(id, decision, options)` — out-of-process durable resume.\n * - `human.interrupt.{memory,pg,redis}()` — durable {@link InterruptStore}\n * factories (memory ships real; pg/redis are lazy optional peers).\n */\n human: {\n approval: typeof humanApproval;\n resume: typeof resume;\n interrupt: {\n memory: typeof interruptMemory;\n pg: typeof interruptPg;\n redis: typeof interruptRedis;\n };\n };\n /**\n * Content-intelligence guardrail. `ai.guardrail(options)` builds a composed\n * input / output / tool middleware; `ai.guardrail.{pii,topic,injection,moderation}`\n * are the built-in detector factories.\n */\n guardrail: typeof guardrailSuite;\n}\n\n/**\n * Top-level `ai` namespace — holds built-in factories and user-registered SDK adapters.\n *\n * Factories:\n * - `ai.tool(...)` — wrap an async function with a schema-validated input.\n * - `ai.agent(...)` — build an executable agent from model + tools + prompt.\n * - `ai.systemPrompt(...)` — compose a layered persona + instructions prompt.\n * - `ai.persona(text)` — reusable persona block (can be passed to `systemPrompt`).\n * - `ai.instruction(text)` — reusable instruction block (can be passed to `systemPrompt`).\n * - `ai.orchestrator(...)` — session-state manager wrapped around a supervisor (durable session, drift detection, resume, commands).\n * - `ai.memory(...)` — build an agent-memory store with WORKING (in-run scratch) and SEMANTIC (cache-driver `.similar()` recall) tiers.\n * - `ai.skills(...)` — build a runtime skills library (always-injected metadata catalog + on-demand loadSkill tool).\n * - `ai.planner(...)` — build an executable that generates an ordered plan over registered capabilities, then runs it step-by-step.\n * - `ai.spawnSubAgent(spec)` — thin wrapper that builds a fresh one-shot `agent()` with an optional per-task `budget` and runs the task once. A general primitive (not planner-specific).\n * - `ai.router(...)` — build a supervisor-compatible routing agent from named intents.\n * - `ai.fanOut(unit, count)` — spread one agent/workflow into N intent entries for voting / self-consistency.\n * - `ai.batch(executable, items, opts?)` — run any executable over a dataset with bounded concurrency + per-item retry.\n * - `ai.fallbackModel(models, opts?)` — wrap an ordered model list that fails over to the next on transient provider errors.\n * - `ai.eval.{exact,contains,predicate,judge}(...)` — built-in scorer factories for `agent.eval(...)`.\n * - `ai.mockRouter(decisions, opts?)` — deterministic supervisor `route` callback for tests.\n * - `ai.checkpoint.{memory,pg,redis}()` — durable orchestrator session checkpoint stores.\n * - `ai.snapshot.{memory,pg,redis}()` — supervisor-run snapshot stores for `iterate: true` resume.\n * - `ai.human.approval(...)` / `ai.human.resume(...)` / `ai.human.interrupt.{memory,pg,redis}()` — human-in-the-loop tool approval (interrupt / resume).\n * - `ai.guardrail(options)` + `ai.guardrail.{pii,topic,injection,moderation}(...)` — content-intelligence guardrails (moderation / PII / injection / topic).\n * - `ai.openai.model(...)` / `ai.anthropic.model(...)` / ... once the adapter SDK is registered.\n *\n * @example\n * const alex = ai.persona(\"You are Alex, a TypeScript expert.\");\n * const replyIn = ai.instruction(\"Respond in {{language|English}}.\");\n *\n * const prompt = ai.systemPrompt().persona(alex).instruction(replyIn);\n *\n * const myAgent = ai.agent({\n * model: ai.openai.model({ name: \"gpt-4o\" }),\n * systemPrompt: prompt,\n * tools: [myTool],\n * });\n *\n * const result = await myAgent.execute(\"What is the weather in Cairo?\", {\n * placeholders: { language: \"Arabic\" },\n * });\n */\nexport const ai = {\n config: setAIConfig,\n tool,\n agent,\n systemPrompt,\n persona,\n instruction,\n workflow,\n step,\n supervisor,\n team,\n orchestrator,\n memory,\n skills,\n planner,\n rag: Object.assign(rag, {\n keywordReranker,\n llmReranker,\n chunk,\n cacheVectorStore,\n pgVectorStore,\n vectorLiteral,\n loadText,\n loadHtml,\n loadWeb,\n loadPdf,\n bm25Rank,\n reciprocalRankFusion,\n hybridRank,\n multiQuery,\n }),\n spawnSubAgent,\n router,\n fanOut,\n batch,\n streamObject,\n serve,\n image,\n speech,\n transcribe,\n audioFromFile,\n audioFromBuffer,\n audioMediaTypeForFilename,\n fallbackModel,\n eval: evalScorers,\n dataset,\n prompt,\n prompts: defaultPromptsManager(),\n vcr,\n mockRouter,\n middleware: {\n budget,\n guardrail,\n semanticCache,\n compose: composeMiddleware,\n forTool,\n readBudgetFallbackSignal,\n },\n checkpoint: {\n memory: checkpointMemory,\n pg: checkpointPg,\n redis: checkpointRedis,\n },\n snapshot: {\n memory: snapshotMemory,\n pg: snapshotPg,\n redis: snapshotRedis,\n },\n human,\n guardrail: guardrailSuite,\n // Asserted (not `: Ai`) so a consumer build that augments `Ai` with a\n // satellite verb (e.g. `workspace`) doesn't flag this literal as missing it.\n} as Ai;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyOA,MAAa,KAAK;CAChB,QAAQ;CACR;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,KAAK,OAAO,OAAO,KAAK;EACtB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CACD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,MAAM;CACN;CACA;CACA,SAAS,sBAAsB;CAC/B;CACA;CACA,YAAY;EACV;EACA;EACA;EACA,SAAS;EACT;EACA;CACF;CACA,YAAY;EACV,QAAQA;EACJC;EACGC;CACT;CACA,UAAU;EACR,QAAQC;EACR,IAAIC;EACJ,OAAOC;CACT;CACA;CACA,WAAWC;AAGb"}
|
|
1
|
+
{"version":3,"file":"ai.mjs","names":["checkpointMemory","checkpointPg","checkpointRedis","snapshotMemory","snapshotPg","snapshotRedis","guardrailSuite"],"sources":["../../../../../../@warlock.js/ai/src/ai.ts"],"sourcesContent":["import { agent } from \"./agent/agent\";\nimport { batch } from \"./batch\";\nimport { streamObject } from \"./object-stream\";\nimport { serve } from \"./serve\";\nimport {\n checkpointMemory,\n checkpointPg,\n checkpointRedis,\n} from \"./checkpoint\";\nimport { setAIConfig } from \"./config\";\nimport { dataset, evalScorers } from \"./eval\";\nimport { humanApproval } from \"./human/human-approval\";\nimport { human } from \"./human/register\";\nimport { image } from \"./image\";\nimport { speech } from \"./speech\";\nimport {\n audioFromBuffer,\n audioFromFile,\n audioMediaTypeForFilename,\n transcribe,\n} from \"./transcribe\";\nimport { resume } from \"./human/resume\";\nimport {\n interruptMemory,\n interruptPg,\n interruptRedis,\n} from \"./human/stores\";\nimport { guardrail as guardrailSuite } from \"./guard/guardrail\";\nimport { budget, readBudgetFallbackSignal } from \"./middleware/builtins/budget\";\nimport { memory } from \"./memory\";\nimport { guardrail } from \"./middleware/builtins/guardrail\";\nimport { semanticCache } from \"./middleware/builtins/semantic-cache\";\nimport { composeMiddleware, forTool } from \"./middleware/helpers\";\nimport { mockRouter } from \"./mock\";\nimport { fallbackModel } from \"./model\";\nimport { orchestrator } from \"./orchestrator\";\nimport { planner } from \"./planner\";\nimport { defaultPromptsManager } from \"./prompts/prompts-manager\";\nimport {\n bm25Rank,\n cacheVectorStore,\n chunk,\n hybridRank,\n keywordReranker,\n llmReranker,\n loadHtml,\n loadPdf,\n loadText,\n loadWeb,\n multiQuery,\n pgVectorStore,\n rag,\n reciprocalRankFusion,\n vectorLiteral,\n} from \"./rag\";\nimport { spawnSubAgent } from \"./agent/spawn-sub-agent\";\nimport { skills } from \"./skills\";\nimport { prompt } from \"./prompt\";\nimport { vcr } from \"./vcr\";\nimport { snapshotMemory, snapshotPg, snapshotRedis } from \"./snapshot\";\nimport { fanOut, router } from \"./supervisor\";\nimport { supervisor } from \"./supervisor/supervisor\";\nimport { team } from \"./team/team\";\nimport { instruction } from \"./system-prompt/instruction\";\nimport { persona } from \"./system-prompt/persona\";\nimport { systemPrompt } from \"./system-prompt/system-prompt\";\nimport { tool } from \"./tool/tool\";\nimport { step } from \"./workflow/step\";\nimport { workflow } from \"./workflow/workflow\";\n\n/**\n * The shape of the top-level `ai` namespace. Declared as an `interface` (not an\n * inferred `const` type) so satellite packages can attach their verb via\n * `declare module \"@warlock.js/ai\" { interface Ai { … } }` — e.g. `ai.workspace`,\n * `ai.tools`, `ai.mcp`, `ai.human`. The runtime object below is asserted to this\n * type; a satellite assigns its member on import.\n */\nexport interface Ai {\n config: typeof setAIConfig;\n tool: typeof tool;\n agent: typeof agent;\n systemPrompt: typeof systemPrompt;\n persona: typeof persona;\n instruction: typeof instruction;\n workflow: typeof workflow;\n step: typeof step;\n supervisor: typeof supervisor;\n team: typeof team;\n orchestrator: typeof orchestrator;\n memory: typeof memory;\n skills: typeof skills;\n planner: typeof planner;\n rag: typeof rag & {\n keywordReranker: typeof keywordReranker;\n llmReranker: typeof llmReranker;\n chunk: typeof chunk;\n cacheVectorStore: typeof cacheVectorStore;\n pgVectorStore: typeof pgVectorStore;\n vectorLiteral: typeof vectorLiteral;\n loadText: typeof loadText;\n loadHtml: typeof loadHtml;\n loadWeb: typeof loadWeb;\n loadPdf: typeof loadPdf;\n bm25Rank: typeof bm25Rank;\n reciprocalRankFusion: typeof reciprocalRankFusion;\n hybridRank: typeof hybridRank;\n multiQuery: typeof multiQuery;\n };\n spawnSubAgent: typeof spawnSubAgent;\n router: typeof router;\n fanOut: typeof fanOut;\n batch: typeof batch;\n /** Structured-output streaming — partial-object snapshots + a strict final parse (A1). */\n streamObject: typeof streamObject;\n /** Serve an executable as an SSE HTTP endpoint — production serving primitive (A3). */\n serve: typeof serve;\n /**\n * Generate images from a text prompt — the image-output verb of the\n * output-modality track (Theme I). Wraps an `ImageModelContract` (from\n * `openai.image(...)` / `google.image(...)`) in the uniform\n * never-throws `{ data, error, usage, report }` envelope with cost-truth\n * and observability.\n */\n image: typeof image;\n /** Text-to-speech (TTS) — the audio-output verb of the modality track (Theme I). */\n speech: typeof speech;\n /** Speech-to-text (STT / transcription) — the audio-input verb of the modality track (Theme I). */\n transcribe: typeof transcribe;\n /** Read an audio file from disk → `AudioInput` for `ai.transcribe` (non-AI file plumbing). */\n audioFromFile: typeof audioFromFile;\n /** Package raw audio bytes → `AudioInput` for `ai.transcribe`. */\n audioFromBuffer: typeof audioFromBuffer;\n /** Resolve the audio media type from a filename's extension. */\n audioMediaTypeForFilename: typeof audioMediaTypeForFilename;\n fallbackModel: typeof fallbackModel;\n eval: typeof evalScorers;\n dataset: typeof dataset;\n prompt: typeof prompt;\n /**\n * Process-wide registry of named, versioned `systemPrompt(...)` builders,\n * keyed by `name@version`. A `systemPrompt(input, { name })` (or any\n * `.meta({ name })` rename) auto-registers here; `ai.prompts.get(name)` /\n * `.resolve(name)` reads them back, and `systemPrompt().merge(name)` folds a\n * registered prompt into a new one.\n */\n prompts: ReturnType<typeof defaultPromptsManager>;\n vcr: typeof vcr;\n mockRouter: typeof mockRouter;\n middleware: {\n budget: typeof budget;\n guardrail: typeof guardrail;\n semanticCache: typeof semanticCache;\n compose: typeof composeMiddleware;\n forTool: typeof forTool;\n readBudgetFallbackSignal: typeof readBudgetFallbackSignal;\n };\n checkpoint: {\n memory: typeof checkpointMemory;\n pg: typeof checkpointPg;\n redis: typeof checkpointRedis;\n };\n snapshot: {\n memory: typeof snapshotMemory;\n pg: typeof snapshotPg;\n redis: typeof snapshotRedis;\n };\n /**\n * Human-in-the-loop tool approval (interrupt / resume).\n *\n * - `human.approval(options)` — the `tool.before` approval-gate middleware.\n * - `human.resume(id, decision, options)` — out-of-process durable resume.\n * - `human.interrupt.{memory,pg,redis}()` — durable {@link InterruptStore}\n * factories (memory ships real; pg/redis are lazy optional peers).\n */\n human: {\n approval: typeof humanApproval;\n resume: typeof resume;\n interrupt: {\n memory: typeof interruptMemory;\n pg: typeof interruptPg;\n redis: typeof interruptRedis;\n };\n };\n /**\n * Content-intelligence guardrail. `ai.guardrail(options)` builds a composed\n * input / output / tool middleware; `ai.guardrail.{pii,topic,injection,moderation}`\n * are the built-in detector factories.\n */\n guardrail: typeof guardrailSuite;\n}\n\n/**\n * Top-level `ai` namespace — holds built-in factories and user-registered SDK adapters.\n *\n * Factories:\n * - `ai.tool(...)` — wrap an async function with a schema-validated input.\n * - `ai.agent(...)` — build an executable agent from model + tools + prompt.\n * - `ai.systemPrompt(...)` — compose a layered persona + instructions prompt.\n * - `ai.persona(text)` — reusable persona block (can be passed to `systemPrompt`).\n * - `ai.instruction(text)` — reusable instruction block (can be passed to `systemPrompt`).\n * - `ai.orchestrator(...)` — session-state manager wrapped around a supervisor (durable session, drift detection, resume, commands).\n * - `ai.memory(...)` — build an agent-memory store with WORKING (in-run scratch) and SEMANTIC (cache-driver `.similar()` recall) tiers.\n * - `ai.skills(...)` — build a runtime skills library (always-injected metadata catalog + on-demand loadSkill tool).\n * - `ai.planner(...)` — build an executable that generates an ordered plan over registered capabilities, then runs it step-by-step.\n * - `ai.spawnSubAgent(spec)` — thin wrapper that builds a fresh one-shot `agent()` with an optional per-task `budget` and runs the task once. A general primitive (not planner-specific).\n * - `ai.router(...)` — build a supervisor-compatible routing agent from named intents.\n * - `ai.fanOut(unit, count)` — spread one agent/workflow into N intent entries for voting / self-consistency.\n * - `ai.batch(executable, items, opts?)` — run any executable over a dataset with bounded concurrency + per-item retry.\n * - `ai.fallbackModel(models, opts?)` — wrap an ordered model list that fails over to the next on transient provider errors.\n * - `ai.eval.{exact,contains,predicate,judge}(...)` — built-in scorer factories for `agent.eval(...)`.\n * - `ai.mockRouter(decisions, opts?)` — deterministic supervisor `route` callback for tests.\n * - `ai.checkpoint.{memory,pg,redis}()` — durable orchestrator session checkpoint stores.\n * - `ai.snapshot.{memory,pg,redis}()` — supervisor-run snapshot stores for `iterate: true` resume.\n * - `ai.human.approval(...)` / `ai.human.resume(...)` / `ai.human.interrupt.{memory,pg,redis}()` — human-in-the-loop tool approval (interrupt / resume).\n * - `ai.guardrail(options)` + `ai.guardrail.{pii,topic,injection,moderation}(...)` — content-intelligence guardrails (moderation / PII / injection / topic).\n * - `ai.openai.model(...)` / `ai.anthropic.model(...)` / ... once the adapter SDK is registered.\n *\n * @example\n * const alex = ai.persona(\"You are Alex, a TypeScript expert.\");\n * const replyIn = ai.instruction(\"Respond in {{language|English}}.\");\n *\n * const prompt = ai.systemPrompt().persona(alex).instruction(replyIn);\n *\n * const myAgent = ai.agent({\n * model: ai.openai.model({ name: \"gpt-4o\" }),\n * systemPrompt: prompt,\n * tools: [myTool],\n * });\n *\n * const result = await myAgent.execute(\"What is the weather in Cairo?\", {\n * placeholders: { language: \"Arabic\" },\n * });\n */\nexport const ai = {\n config: setAIConfig,\n tool,\n agent,\n systemPrompt,\n persona,\n instruction,\n workflow,\n step,\n supervisor,\n team,\n orchestrator,\n memory,\n skills,\n planner,\n rag: Object.assign(rag, {\n keywordReranker,\n llmReranker,\n chunk,\n cacheVectorStore,\n pgVectorStore,\n vectorLiteral,\n loadText,\n loadHtml,\n loadWeb,\n loadPdf,\n bm25Rank,\n reciprocalRankFusion,\n hybridRank,\n multiQuery,\n }),\n spawnSubAgent,\n router,\n fanOut,\n batch,\n streamObject,\n serve,\n image,\n speech,\n transcribe,\n audioFromFile,\n audioFromBuffer,\n audioMediaTypeForFilename,\n fallbackModel,\n eval: evalScorers,\n dataset,\n prompt,\n prompts: defaultPromptsManager(),\n vcr,\n mockRouter,\n middleware: {\n budget,\n guardrail,\n semanticCache,\n compose: composeMiddleware,\n forTool,\n readBudgetFallbackSignal,\n },\n checkpoint: {\n memory: checkpointMemory,\n pg: checkpointPg,\n redis: checkpointRedis,\n },\n snapshot: {\n memory: snapshotMemory,\n pg: snapshotPg,\n redis: snapshotRedis,\n },\n human,\n guardrail: guardrailSuite,\n // Asserted (not `: Ai`) so a consumer build that augments `Ai` with a\n // satellite verb (e.g. `workspace`) doesn't flag this literal as missing it.\n} as Ai;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyOA,MAAa,KAAK;CAChB,QAAQ;CACR;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,KAAK,OAAO,OAAO,KAAK;EACtB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CACD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,MAAM;CACN;CACA;CACA,SAAS,sBAAsB;CAC/B;CACA;CACA,YAAY;EACV;EACA;EACA;EACA,SAAS;EACT;EACA;CACF;CACA,YAAY;EACV,QAAQA;EACJC;EACGC;CACT;CACA,UAAU;EACR,QAAQC;EACR,IAAIC;EACJ,OAAOC;CACT;CACA;CACA,WAAWC;AAGb"}
|
package/esm/config.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.mts","names":[],"sources":["../../../../../../@warlock.js/ai/src/config.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"config.d.mts","names":[],"sources":["../../../../../../@warlock.js/ai/src/config.ts"],"mappings":";;;;;;;AA2CA;;;;;;;;;;;;;;;AAoDsC;AACrC;;;;AAKsC;AAoBvC;;;;AAAwD;AAmBxD;;;;;;;;;;UAjGiB,QAAA;EAiGwC;;AAAQ;AAuBjE;;;;AAAuC;AAYvC;;;;AAAkD;AAUlD;;;;AAAgE;AAUhE;;;;AAA4D;EAhI1D,YAAA,GAAe,WAAA;;;;;;;;;;;;;EAcf,sBAAA,GAAyB,eAAA;;;;;;;;;;;;;EAczB,oBAAA,GAAuB,aAAA;AAAA;;KAMpB,cAAA,IAAkB,MAAgB,EAAR,QAAQ;;;;;;;;;;;;;;;;;iBAoBvB,eAAA,CAAgB,QAAwB,EAAd,cAAc;;;;;;;;;;;;;;;;iBAmBxC,WAAA,CAAY,OAAA,EAAS,OAAA,CAAQ,QAAA,IAAY,QAAA;;;;;;iBAuBzC,WAAA,IAAe,QAAQ;;;;;;;;;iBAYvB,mBAAA,IAAuB,WAAW;;;;;;;iBAUlC,6BAAA,IAAiC,eAAe;;;;;;;iBAUhD,2BAAA,IAA+B,aAAa"}
|
package/esm/config.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { log } from "@warlock.js/logger";
|
|
2
|
+
|
|
1
3
|
//#region ../@warlock.js/ai/src/config.ts
|
|
2
4
|
const aiConfig = {};
|
|
3
5
|
const configListeners = [];
|
|
@@ -40,7 +42,9 @@ function setAIConfig(partial) {
|
|
|
40
42
|
const snapshot = { ...aiConfig };
|
|
41
43
|
for (const listener of configListeners) try {
|
|
42
44
|
listener(snapshot);
|
|
43
|
-
} catch {
|
|
45
|
+
} catch (error) {
|
|
46
|
+
log.error("ai", "configListener", error);
|
|
47
|
+
}
|
|
44
48
|
return snapshot;
|
|
45
49
|
}
|
|
46
50
|
/**
|
package/esm/config.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.mjs","names":[],"sources":["../../../../../../@warlock.js/ai/src/config.ts"],"sourcesContent":["import type { CacheDriver } from \"@warlock.js/cache\";\nimport type { CheckpointStore } from \"./contracts/orchestrator/checkpoint-store.contract\";\nimport type { SnapshotStore } from \"./contracts/orchestrator/snapshot-store.contract\";\n\n/**\n * Process-wide `@warlock.js/ai` configuration. **Intentionally tiny.**\n * Lives here only for genuinely cross-cutting defaults that would\n * otherwise force users to wire the same value into every consumer.\n *\n * **What lives here.** A field earns a slot only when it satisfies\n * all three:\n * 1. Multiple unrelated consumers need the same value.\n * 2. The value is infrastructure (drivers, clients, pools), not\n * behavior (kill-switches, mode flags).\n * 3. Per-call override doesn't make sense for the use case.\n *\n * **What does NOT live here.** Logger config (use\n * `@warlock.js/logger` directly). Per-primitive feature flags\n * (live on the relevant config type). Anything that's really one\n * consumer's concern (lives on that consumer).\n *\n * Phase 3.2 deliberately removed the previous `configureAI()` bag\n * because it was growing unbounded. Treat new fields here with the\n * same suspicion.\n *\n * **Augmentable.** Declared as an `interface` (not a `type` alias) so\n * observability/tooling packages can attach their own opaque config slot\n * via declaration merging WITHOUT core importing them — keeping core\n * dependency-free. For example `@warlock.js/ai-panoptic` adds a\n * `panoptic?` field:\n *\n * ```ts\n * declare module \"@warlock.js/ai\" {\n * interface AIConfig {\n * panoptic?: PanopticConfig;\n * }\n * }\n * ```\n *\n * `setAIConfig` stores the whole object via `Object.assign`, so any\n * augmented field is preserved even though core never reads it.\n */\nexport interface AIConfig {\n /**\n * Default `@warlock.js/cache` driver for cache-backed consumers that\n * didn't supply their own `store` — currently the `semanticCache`\n * middleware's vector store. Declaring it once here removes the\n * repetition across middleware declarations.\n *\n * NOT the snapshot-persistence fallback anymore. Supervisor /\n * workflow / orchestrator resume snapshots resolve through\n * {@link AIConfig.defaultSnapshotStore} (a {@link SnapshotStore}),\n * never this driver.\n *\n * Per-declaration overrides (`semanticCache({ store })`) win when\n * supplied. Set this once at app boot, *after* you've constructed\n * your driver.\n *\n * @example\n * import { cache } from \"@warlock.js/cache\";\n * import { ai } from \"@warlock.js/ai\";\n *\n * ai.config({\n * defaultStore: cache.driver(\"redis\", { client: redisClient }),\n * });\n */\n defaultStore?: CacheDriver<any, any>;\n\n /**\n * Default {@link CheckpointStore} for every orchestrator that didn't\n * supply its own `checkpointStore` (orchestrator.md §15.2). Holds\n * durable session state — `state`, `turn_index`, drift `signature`,\n * compaction locks. Per-orchestrator `checkpointStore` wins when\n * supplied. Set once at app boot.\n *\n * @example\n * import { ai } from \"@warlock.js/ai\";\n *\n * ai.config({ defaultCheckpointStore: ai.checkpoint.memory() });\n */\n defaultCheckpointStore?: CheckpointStore;\n\n /**\n * Default {@link SnapshotStore} for every orchestrator that didn't\n * supply its own `snapshotStore` (orchestrator.md §15.2). Holds the\n * internal supervisor run state used to resume an interrupted\n * `iterate: true` turn. Per-orchestrator `snapshotStore` wins when\n * supplied. Set once at app boot.\n *\n * @example\n * import { ai } from \"@warlock.js/ai\";\n *\n * ai.config({ defaultSnapshotStore: ai.snapshot.memory() });\n */\n defaultSnapshotStore?: SnapshotStore;\n};\n\nconst aiConfig: AIConfig = {};\n\n/** A listener notified after every `setAIConfig` merge. */\ntype ConfigListener = (config: AIConfig) => void;\n\nconst configListeners: ConfigListener[] = [];\n\n/**\n * Subscribe to config changes. The listener fires after every\n * {@link setAIConfig} merge with a fresh snapshot of the full config —\n * the seam observability/tooling packages use to react when their\n * augmented slot (e.g. `panoptic`) is set, WITHOUT core importing them.\n *\n * Mirrors the dependency-inversion of the `Observer` registry: core\n * exposes the structural hook; the tool subscribes on its side-effect\n * import. To also catch config that was applied *before* the subscription,\n * read {@link getAIConfig} once right after subscribing.\n *\n * @example\n * import { onConfigApplied, getAIConfig } from \"@warlock.js/ai\";\n * onConfigApplied((config) => applyPanopticConfig(config.panoptic));\n * applyPanopticConfig(getAIConfig().panoptic); // catch pre-set config\n */\nexport function onConfigApplied(listener: ConfigListener): void {\n configListeners.push(listener);\n}\n\n/**\n * Set or extend process-wide AI configuration. Merges over existing\n * values — fields not present in `partial` keep whatever was set\n * before (or stay unset). Call once at app boot, before constructing\n * any agent / supervisor / middleware that should pick up the\n * defaults.\n *\n * Returns the merged config so callers can verify what landed.\n *\n * @example\n * import { cache } from \"@warlock.js/cache\";\n * import { ai } from \"@warlock.js/ai\";\n *\n * ai.config({ defaultStore: cache.driver(\"redis\", { client }) });\n */\nexport function setAIConfig(partial: Partial<AIConfig>): AIConfig {\n Object.assign(aiConfig, partial);\n const snapshot = { ...aiConfig };\n\n // Notify subscribers (e.g. panoptic) after the merge. Errors are\n // swallowed so a misbehaving listener never breaks config application,\n // mirroring the observer / onUsage swallow-on-throw discipline.\n for (const listener of configListeners) {\n try {\n listener(snapshot);\n } catch {\n
|
|
1
|
+
{"version":3,"file":"config.mjs","names":[],"sources":["../../../../../../@warlock.js/ai/src/config.ts"],"sourcesContent":["import type { CacheDriver } from \"@warlock.js/cache\";\nimport { log } from \"@warlock.js/logger\";\nimport type { CheckpointStore } from \"./contracts/orchestrator/checkpoint-store.contract\";\nimport type { SnapshotStore } from \"./contracts/orchestrator/snapshot-store.contract\";\n\n/**\n * Process-wide `@warlock.js/ai` configuration. **Intentionally tiny.**\n * Lives here only for genuinely cross-cutting defaults that would\n * otherwise force users to wire the same value into every consumer.\n *\n * **What lives here.** A field earns a slot only when it satisfies\n * all three:\n * 1. Multiple unrelated consumers need the same value.\n * 2. The value is infrastructure (drivers, clients, pools), not\n * behavior (kill-switches, mode flags).\n * 3. Per-call override doesn't make sense for the use case.\n *\n * **What does NOT live here.** Logger config (use\n * `@warlock.js/logger` directly). Per-primitive feature flags\n * (live on the relevant config type). Anything that's really one\n * consumer's concern (lives on that consumer).\n *\n * Phase 3.2 deliberately removed the previous `configureAI()` bag\n * because it was growing unbounded. Treat new fields here with the\n * same suspicion.\n *\n * **Augmentable.** Declared as an `interface` (not a `type` alias) so\n * observability/tooling packages can attach their own opaque config slot\n * via declaration merging WITHOUT core importing them — keeping core\n * dependency-free. For example `@warlock.js/ai-panoptic` adds a\n * `panoptic?` field:\n *\n * ```ts\n * declare module \"@warlock.js/ai\" {\n * interface AIConfig {\n * panoptic?: PanopticConfig;\n * }\n * }\n * ```\n *\n * `setAIConfig` stores the whole object via `Object.assign`, so any\n * augmented field is preserved even though core never reads it.\n */\nexport interface AIConfig {\n /**\n * Default `@warlock.js/cache` driver for cache-backed consumers that\n * didn't supply their own `store` — currently the `semanticCache`\n * middleware's vector store. Declaring it once here removes the\n * repetition across middleware declarations.\n *\n * NOT the snapshot-persistence fallback anymore. Supervisor /\n * workflow / orchestrator resume snapshots resolve through\n * {@link AIConfig.defaultSnapshotStore} (a {@link SnapshotStore}),\n * never this driver.\n *\n * Per-declaration overrides (`semanticCache({ store })`) win when\n * supplied. Set this once at app boot, *after* you've constructed\n * your driver.\n *\n * @example\n * import { cache } from \"@warlock.js/cache\";\n * import { ai } from \"@warlock.js/ai\";\n *\n * ai.config({\n * defaultStore: cache.driver(\"redis\", { client: redisClient }),\n * });\n */\n defaultStore?: CacheDriver<any, any>;\n\n /**\n * Default {@link CheckpointStore} for every orchestrator that didn't\n * supply its own `checkpointStore` (orchestrator.md §15.2). Holds\n * durable session state — `state`, `turn_index`, drift `signature`,\n * compaction locks. Per-orchestrator `checkpointStore` wins when\n * supplied. Set once at app boot.\n *\n * @example\n * import { ai } from \"@warlock.js/ai\";\n *\n * ai.config({ defaultCheckpointStore: ai.checkpoint.memory() });\n */\n defaultCheckpointStore?: CheckpointStore;\n\n /**\n * Default {@link SnapshotStore} for every orchestrator that didn't\n * supply its own `snapshotStore` (orchestrator.md §15.2). Holds the\n * internal supervisor run state used to resume an interrupted\n * `iterate: true` turn. Per-orchestrator `snapshotStore` wins when\n * supplied. Set once at app boot.\n *\n * @example\n * import { ai } from \"@warlock.js/ai\";\n *\n * ai.config({ defaultSnapshotStore: ai.snapshot.memory() });\n */\n defaultSnapshotStore?: SnapshotStore;\n};\n\nconst aiConfig: AIConfig = {};\n\n/** A listener notified after every `setAIConfig` merge. */\ntype ConfigListener = (config: AIConfig) => void;\n\nconst configListeners: ConfigListener[] = [];\n\n/**\n * Subscribe to config changes. The listener fires after every\n * {@link setAIConfig} merge with a fresh snapshot of the full config —\n * the seam observability/tooling packages use to react when their\n * augmented slot (e.g. `panoptic`) is set, WITHOUT core importing them.\n *\n * Mirrors the dependency-inversion of the `Observer` registry: core\n * exposes the structural hook; the tool subscribes on its side-effect\n * import. To also catch config that was applied *before* the subscription,\n * read {@link getAIConfig} once right after subscribing.\n *\n * @example\n * import { onConfigApplied, getAIConfig } from \"@warlock.js/ai\";\n * onConfigApplied((config) => applyPanopticConfig(config.panoptic));\n * applyPanopticConfig(getAIConfig().panoptic); // catch pre-set config\n */\nexport function onConfigApplied(listener: ConfigListener): void {\n configListeners.push(listener);\n}\n\n/**\n * Set or extend process-wide AI configuration. Merges over existing\n * values — fields not present in `partial` keep whatever was set\n * before (or stay unset). Call once at app boot, before constructing\n * any agent / supervisor / middleware that should pick up the\n * defaults.\n *\n * Returns the merged config so callers can verify what landed.\n *\n * @example\n * import { cache } from \"@warlock.js/cache\";\n * import { ai } from \"@warlock.js/ai\";\n *\n * ai.config({ defaultStore: cache.driver(\"redis\", { client }) });\n */\nexport function setAIConfig(partial: Partial<AIConfig>): AIConfig {\n Object.assign(aiConfig, partial);\n const snapshot = { ...aiConfig };\n\n // Notify subscribers (e.g. panoptic) after the merge. Errors are\n // swallowed so a misbehaving listener never breaks config application,\n // mirroring the observer / onUsage swallow-on-throw discipline.\n for (const listener of configListeners) {\n try {\n listener(snapshot);\n } catch (error) {\n log.error(\"ai\", \"configListener\", error as Error);\n }\n }\n\n return snapshot;\n}\n\n/**\n * Read the current AI config snapshot. Returns a shallow copy so\n * callers can't accidentally mutate the source of truth. Used\n * internally by consumers to resolve their `defaultStore` fallback.\n */\nexport function getAIConfig(): AIConfig {\n return { ...aiConfig };\n}\n\n/**\n * Resolve the effective `@warlock.js/cache` driver for a cache-backed\n * consumer that didn't receive an explicit one. Returns the global\n * `defaultStore` if set, otherwise `undefined`. The semantic-cache\n * middleware treats `undefined` as fatal and throws. Snapshot\n * persistence no longer consults this — it resolves through\n * {@link resolveDefaultSnapshotStore}.\n */\nexport function resolveDefaultStore(): CacheDriver<any, any> | undefined {\n return aiConfig.defaultStore;\n}\n\n/**\n * Resolve the global default {@link CheckpointStore} for an\n * orchestrator that didn't receive an explicit `checkpointStore`.\n * Returns `undefined` when none is configured — the orchestrator\n * factory decides whether that's fatal.\n */\nexport function resolveDefaultCheckpointStore(): CheckpointStore | undefined {\n return aiConfig.defaultCheckpointStore;\n}\n\n/**\n * Resolve the global default {@link SnapshotStore} for an orchestrator\n * that didn't receive an explicit `snapshotStore`. Returns `undefined`\n * when none is configured — the orchestrator factory decides whether\n * that's fatal (it is, when `iterate: true`).\n */\nexport function resolveDefaultSnapshotStore(): SnapshotStore | undefined {\n return aiConfig.defaultSnapshotStore;\n}\n"],"mappings":";;;AAkGA,MAAM,WAAqB,CAAC;AAK5B,MAAM,kBAAoC,CAAC;;;;;;;;;;;;;;;;;AAkB3C,SAAgB,gBAAgB,UAAgC;CAC9D,gBAAgB,KAAK,QAAQ;AAC/B;;;;;;;;;;;;;;;;AAiBA,SAAgB,YAAY,SAAsC;CAChE,OAAO,OAAO,UAAU,OAAO;CAC/B,MAAM,WAAW,EAAE,GAAG,SAAS;CAK/B,KAAK,MAAM,YAAY,iBACrB,IAAI;EACF,SAAS,QAAQ;CACnB,SAAS,OAAO;EACd,IAAI,MAAM,MAAM,kBAAkB,KAAc;CAClD;CAGF,OAAO;AACT;;;;;;AAOA,SAAgB,cAAwB;CACtC,OAAO,EAAE,GAAG,SAAS;AACvB;;;;;;;;;AAUA,SAAgB,sBAAyD;CACvE,OAAO,SAAS;AAClB;;;;;;;AAQA,SAAgB,gCAA6D;CAC3E,OAAO,SAAS;AAClB;;;;;;;AAQA,SAAgB,8BAAyD;CACvE,OAAO,SAAS;AAClB"}
|
package/esm/index.mjs
CHANGED
|
@@ -78,6 +78,7 @@ import { resolveSource } from "./skills/sources/index.mjs";
|
|
|
78
78
|
import { skills } from "./skills/skills.mjs";
|
|
79
79
|
import { MockSkillsStore } from "./skills/store/mock-skills-store.mjs";
|
|
80
80
|
import { memory as memory$2 } from "./memory/memory.mjs";
|
|
81
|
+
import "./memory/index.mjs";
|
|
81
82
|
import { proceduralSkillStore } from "./skills/store/procedural-skill-store.mjs";
|
|
82
83
|
import { runReviewGate } from "./skills/review-gate.mjs";
|
|
83
84
|
import "./skills/index.mjs";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"procedural-skill-store.mjs","names":[],"sources":["../../../../../../../../@warlock.js/ai/src/skills/store/procedural-skill-store.ts"],"sourcesContent":["import type { MemoryContract } from \"../../contracts/memory/memory.contract\";\nimport type { ProceduralMemoryConfig } from \"../../contracts/memory/memory-config.type\";\nimport { memory } from \"../../memory\";\nimport type {\n SkillCatalogEntry,\n SkillRecord,\n} from \"../contracts/skill-record.type\";\nimport type { SkillsStoreContract } from \"../contracts/skills-store.contract\";\n\n/**\n * Metadata a procedural memory carries to round-trip a skill. `recall()`\n * surfaces `metadata` verbatim, so the skill's identity (name, version,\n * provenance, description, tags) rides here while the procedure body lives\n * in the memory's `text`.\n */\ntype ProceduralSkillMeta = {\n /** Marks the record as a skill (vs. a plain procedure) so `list` can scope. */\n skill: true;\n /** Skill name — the catalog key (also the memory `id`). */\n name: string;\n /** Provenance flag round-tripped onto the SkillRecord. */\n type: \"candidate\" | \"promoted\";\n /** Catalog line. */\n description: string;\n /** Monotonic version — bumped on promote. */\n version: number;\n /** Optional scope tags. */\n tags?: string[];\n};\n\n/** A recalled skill entry — the procedure body plus its skill metadata. */\ntype ProceduralSkillEntry = { body: string; meta: ProceduralSkillMeta };\n\nconst RECALL_K = 1000;\n\n/**\n * {@link SkillsStoreContract} backed by the procedural memory tier\n * (`ai.memory({ procedural })`). **The unification** the design calls for:\n * \"promote a proven procedural memory to a named skill\" and \"save a\n * self-authored skill\" are the SAME machinery — one store, two entry\n * points. No fifth `MemoryTier` is added; the existing `\"procedural\"` tier\n * is reused verbatim.\n *\n * - `saveCandidate` ⇒ `memory.remember({ tier: \"procedural\", metadata: { type: \"candidate\" } })`.\n * - `promote` ⇒ re-remembers the same id with `type: \"promoted\"` and\n * `version + 1`, which the procedural tier reinforces (increments `uses`).\n * - `list` / `load` map `memory.recall(..., { tier: \"procedural\" })` ⇒\n * `RecalledMemory[]` ⇒ `SkillCatalogEntry[]` / `SkillRecord`, filtering\n * out inert candidates so they can never be catalogued or injected.\n *\n * @example\n * const store = proceduralSkillStore({ embedder, store: cacheDriver });\n * const lib = skills({ name: \"learned\", sources: [{ type: \"store\", store }], review: gate });\n */\nexport function proceduralSkillStore(\n config: ProceduralMemoryConfig & { name?: string; recallQuery?: string },\n): SkillsStoreContract {\n const store: MemoryContract = memory({\n name: config.name ?? \"skills.procedural\",\n working: false,\n defaultTier: \"procedural\",\n procedural: {\n embedder: config.embedder,\n store: config.store,\n namespace: config.namespace,\n reinforcementWeight: config.reinforcementWeight,\n },\n });\n\n // The procedural tier recalls by similarity to a query; for a full\n // catalog listing we recall against a broad seed with a large `k` and a\n // zero floor so every stored skill comes back.\n const recallQuery = config.recallQuery ?? \"skill procedure how-to\";\n\n const recallAll = async (): Promise<ProceduralSkillEntry[]> => {\n const hits = await store.recall(recallQuery, {\n tier: \"procedural\",\n k: RECALL_K,\n threshold: 0,\n });\n\n return hits\n .map((hit) => ({ body: hit.text, meta: hit.metadata as ProceduralSkillMeta | undefined }))\n .filter((entry): entry is ProceduralSkillEntry => Boolean(entry.meta?.skill));\n };\n\n return {\n async list(scope?: { tags?: string[] }): Promise<SkillCatalogEntry[]> {\n const all = await recallAll();\n const wanted = scope?.tags;\n\n return all\n .filter((entry) => entry.meta.type !== \"candidate\")\n .filter((entry) => intersects(entry.meta.tags, wanted))\n .map((entry) => toCatalogEntry(entry.meta));\n },\n async load(name: string, version?: number): Promise<SkillRecord | undefined> {\n const all = await recallAll();\n const match = all.find((entry) => entry.meta.name === name);\n\n if (!match || match.meta.type === \"candidate\") {\n return undefined;\n }\n\n if (version !== undefined && match.meta.version !== version) {\n return undefined;\n }\n\n return toRecord(match.body, match.meta);\n },\n async saveCandidate(record: Omit<SkillRecord, \"version\" | \"type\">): Promise<SkillRecord> {\n const meta: ProceduralSkillMeta = {\n skill: true,\n name: record.name,\n type: \"candidate\",\n description: record.description,\n version: 0,\n tags: record.tags,\n };\n\n await store.remember({\n id: record.name,\n text: record.body,\n tier: \"procedural\",\n metadata: meta,\n });\n\n return { ...record, version: 0, type: \"candidate\" };\n },\n async promote(name: string): Promise<SkillRecord> {\n const all = await recallAll();\n const match = all.find((entry) => entry.meta.name === name);\n\n if (!match) {\n throw new Error(`proceduralSkillStore.promote: no skill named \"${name}\" to promote`);\n }\n\n const meta: ProceduralSkillMeta = {\n ...match.meta,\n type: \"promoted\",\n version: match.meta.version + 1,\n };\n\n // Re-remembering the same id reinforces (uses++) AND flips the\n // metadata — the procedural tier's reinforcement IS the promotion.\n await store.remember({\n id: name,\n text: match.body,\n tier: \"procedural\",\n metadata: meta,\n });\n\n return toRecord(match.body, meta);\n },\n };\n}\n\nfunction toCatalogEntry(meta: ProceduralSkillMeta): SkillCatalogEntry {\n return {\n name: meta.name,\n description: meta.description,\n version: meta.version,\n tags: meta.tags,\n type: meta.type,\n };\n}\n\nfunction toRecord(body: string, meta: ProceduralSkillMeta): SkillRecord {\n return {\n name: meta.name,\n description: meta.description,\n version: meta.version,\n body,\n tags: meta.tags,\n type: meta.type,\n };\n}\n\nfunction intersects(recordTags: string[] | undefined, wanted: string[] | undefined): boolean {\n if (!wanted || wanted.length === 0) {\n return true;\n }\n\n if (!recordTags || recordTags.length === 0) {\n return false;\n }\n\n return recordTags.some((tag) => wanted.includes(tag));\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"procedural-skill-store.mjs","names":[],"sources":["../../../../../../../../@warlock.js/ai/src/skills/store/procedural-skill-store.ts"],"sourcesContent":["import type { MemoryContract } from \"../../contracts/memory/memory.contract\";\nimport type { ProceduralMemoryConfig } from \"../../contracts/memory/memory-config.type\";\nimport { memory } from \"../../memory\";\nimport type {\n SkillCatalogEntry,\n SkillRecord,\n} from \"../contracts/skill-record.type\";\nimport type { SkillsStoreContract } from \"../contracts/skills-store.contract\";\n\n/**\n * Metadata a procedural memory carries to round-trip a skill. `recall()`\n * surfaces `metadata` verbatim, so the skill's identity (name, version,\n * provenance, description, tags) rides here while the procedure body lives\n * in the memory's `text`.\n */\ntype ProceduralSkillMeta = {\n /** Marks the record as a skill (vs. a plain procedure) so `list` can scope. */\n skill: true;\n /** Skill name — the catalog key (also the memory `id`). */\n name: string;\n /** Provenance flag round-tripped onto the SkillRecord. */\n type: \"candidate\" | \"promoted\";\n /** Catalog line. */\n description: string;\n /** Monotonic version — bumped on promote. */\n version: number;\n /** Optional scope tags. */\n tags?: string[];\n};\n\n/** A recalled skill entry — the procedure body plus its skill metadata. */\ntype ProceduralSkillEntry = { body: string; meta: ProceduralSkillMeta };\n\nconst RECALL_K = 1000;\n\n/**\n * {@link SkillsStoreContract} backed by the procedural memory tier\n * (`ai.memory({ procedural })`). **The unification** the design calls for:\n * \"promote a proven procedural memory to a named skill\" and \"save a\n * self-authored skill\" are the SAME machinery — one store, two entry\n * points. No fifth `MemoryTier` is added; the existing `\"procedural\"` tier\n * is reused verbatim.\n *\n * - `saveCandidate` ⇒ `memory.remember({ tier: \"procedural\", metadata: { type: \"candidate\" } })`.\n * - `promote` ⇒ re-remembers the same id with `type: \"promoted\"` and\n * `version + 1`, which the procedural tier reinforces (increments `uses`).\n * - `list` / `load` map `memory.recall(..., { tier: \"procedural\" })` ⇒\n * `RecalledMemory[]` ⇒ `SkillCatalogEntry[]` / `SkillRecord`, filtering\n * out inert candidates so they can never be catalogued or injected.\n *\n * @example\n * const store = proceduralSkillStore({ embedder, store: cacheDriver });\n * const lib = skills({ name: \"learned\", sources: [{ type: \"store\", store }], review: gate });\n */\nexport function proceduralSkillStore(\n config: ProceduralMemoryConfig & { name?: string; recallQuery?: string },\n): SkillsStoreContract {\n const store: MemoryContract = memory({\n name: config.name ?? \"skills.procedural\",\n working: false,\n defaultTier: \"procedural\",\n procedural: {\n embedder: config.embedder,\n store: config.store,\n namespace: config.namespace,\n reinforcementWeight: config.reinforcementWeight,\n },\n });\n\n // The procedural tier recalls by similarity to a query; for a full\n // catalog listing we recall against a broad seed with a large `k` and a\n // zero floor so every stored skill comes back.\n const recallQuery = config.recallQuery ?? \"skill procedure how-to\";\n\n const recallAll = async (): Promise<ProceduralSkillEntry[]> => {\n const hits = await store.recall(recallQuery, {\n tier: \"procedural\",\n k: RECALL_K,\n threshold: 0,\n });\n\n return hits\n .map((hit) => ({ body: hit.text, meta: hit.metadata as ProceduralSkillMeta | undefined }))\n .filter((entry): entry is ProceduralSkillEntry => Boolean(entry.meta?.skill));\n };\n\n return {\n async list(scope?: { tags?: string[] }): Promise<SkillCatalogEntry[]> {\n const all = await recallAll();\n const wanted = scope?.tags;\n\n return all\n .filter((entry) => entry.meta.type !== \"candidate\")\n .filter((entry) => intersects(entry.meta.tags, wanted))\n .map((entry) => toCatalogEntry(entry.meta));\n },\n async load(name: string, version?: number): Promise<SkillRecord | undefined> {\n const all = await recallAll();\n const match = all.find((entry) => entry.meta.name === name);\n\n if (!match || match.meta.type === \"candidate\") {\n return undefined;\n }\n\n if (version !== undefined && match.meta.version !== version) {\n return undefined;\n }\n\n return toRecord(match.body, match.meta);\n },\n async saveCandidate(record: Omit<SkillRecord, \"version\" | \"type\">): Promise<SkillRecord> {\n const meta: ProceduralSkillMeta = {\n skill: true,\n name: record.name,\n type: \"candidate\",\n description: record.description,\n version: 0,\n tags: record.tags,\n };\n\n await store.remember({\n id: record.name,\n text: record.body,\n tier: \"procedural\",\n metadata: meta,\n });\n\n return { ...record, version: 0, type: \"candidate\" };\n },\n async promote(name: string): Promise<SkillRecord> {\n const all = await recallAll();\n const match = all.find((entry) => entry.meta.name === name);\n\n if (!match) {\n throw new Error(`proceduralSkillStore.promote: no skill named \"${name}\" to promote`);\n }\n\n const meta: ProceduralSkillMeta = {\n ...match.meta,\n type: \"promoted\",\n version: match.meta.version + 1,\n };\n\n // Re-remembering the same id reinforces (uses++) AND flips the\n // metadata — the procedural tier's reinforcement IS the promotion.\n await store.remember({\n id: name,\n text: match.body,\n tier: \"procedural\",\n metadata: meta,\n });\n\n return toRecord(match.body, meta);\n },\n };\n}\n\nfunction toCatalogEntry(meta: ProceduralSkillMeta): SkillCatalogEntry {\n return {\n name: meta.name,\n description: meta.description,\n version: meta.version,\n tags: meta.tags,\n type: meta.type,\n };\n}\n\nfunction toRecord(body: string, meta: ProceduralSkillMeta): SkillRecord {\n return {\n name: meta.name,\n description: meta.description,\n version: meta.version,\n body,\n tags: meta.tags,\n type: meta.type,\n };\n}\n\nfunction intersects(recordTags: string[] | undefined, wanted: string[] | undefined): boolean {\n if (!wanted || wanted.length === 0) {\n return true;\n }\n\n if (!recordTags || recordTags.length === 0) {\n return false;\n }\n\n return recordTags.some((tag) => wanted.includes(tag));\n}\n"],"mappings":";;;;AAiCA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;AAqBjB,SAAgB,qBACd,QACqB;CACrB,MAAM,QAAwB,OAAO;EACnC,MAAM,OAAO,QAAQ;EACrB,SAAS;EACT,aAAa;EACb,YAAY;GACV,UAAU,OAAO;GACjB,OAAO,OAAO;GACd,WAAW,OAAO;GAClB,qBAAqB,OAAO;EAC9B;CACF,CAAC;CAKD,MAAM,cAAc,OAAO,eAAe;CAE1C,MAAM,YAAY,YAA6C;EAO7D,QAAO,MANY,MAAM,OAAO,aAAa;GAC3C,MAAM;GACN,GAAG;GACH,WAAW;EACb,CAAC,EAEU,CACR,KAAK,SAAS;GAAE,MAAM,IAAI;GAAM,MAAM,IAAI;EAA4C,EAAE,CAAC,CACzF,QAAQ,UAAyC,QAAQ,MAAM,MAAM,KAAK,CAAC;CAChF;CAEA,OAAO;EACL,MAAM,KAAK,OAA2D;GACpE,MAAM,MAAM,MAAM,UAAU;GAC5B,MAAM,SAAS,OAAO;GAEtB,OAAO,IACJ,QAAQ,UAAU,MAAM,KAAK,SAAS,WAAW,CAAC,CAClD,QAAQ,UAAU,WAAW,MAAM,KAAK,MAAM,MAAM,CAAC,CAAC,CACtD,KAAK,UAAU,eAAe,MAAM,IAAI,CAAC;EAC9C;EACA,MAAM,KAAK,MAAc,SAAoD;GAE3E,MAAM,SAAQ,MADI,UAAU,EACX,CAAC,MAAM,UAAU,MAAM,KAAK,SAAS,IAAI;GAE1D,IAAI,CAAC,SAAS,MAAM,KAAK,SAAS,aAChC;GAGF,IAAI,YAAY,UAAa,MAAM,KAAK,YAAY,SAClD;GAGF,OAAO,SAAS,MAAM,MAAM,MAAM,IAAI;EACxC;EACA,MAAM,cAAc,QAAqE;GACvF,MAAM,OAA4B;IAChC,OAAO;IACP,MAAM,OAAO;IACb,MAAM;IACN,aAAa,OAAO;IACpB,SAAS;IACT,MAAM,OAAO;GACf;GAEA,MAAM,MAAM,SAAS;IACnB,IAAI,OAAO;IACX,MAAM,OAAO;IACb,MAAM;IACN,UAAU;GACZ,CAAC;GAED,OAAO;IAAE,GAAG;IAAQ,SAAS;IAAG,MAAM;GAAY;EACpD;EACA,MAAM,QAAQ,MAAoC;GAEhD,MAAM,SAAQ,MADI,UAAU,EACX,CAAC,MAAM,UAAU,MAAM,KAAK,SAAS,IAAI;GAE1D,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,iDAAiD,KAAK,aAAa;GAGrF,MAAM,OAA4B;IAChC,GAAG,MAAM;IACT,MAAM;IACN,SAAS,MAAM,KAAK,UAAU;GAChC;GAIA,MAAM,MAAM,SAAS;IACnB,IAAI;IACJ,MAAM,MAAM;IACZ,MAAM;IACN,UAAU;GACZ,CAAC;GAED,OAAO,SAAS,MAAM,MAAM,IAAI;EAClC;CACF;AACF;AAEA,SAAS,eAAe,MAA8C;CACpE,OAAO;EACL,MAAM,KAAK;EACX,aAAa,KAAK;EAClB,SAAS,KAAK;EACd,MAAM,KAAK;EACX,MAAM,KAAK;CACb;AACF;AAEA,SAAS,SAAS,MAAc,MAAwC;CACtE,OAAO;EACL,MAAM,KAAK;EACX,aAAa,KAAK;EAClB,SAAS,KAAK;EACd;EACA,MAAM,KAAK;EACX,MAAM,KAAK;CACb;AACF;AAEA,SAAS,WAAW,YAAkC,QAAuC;CAC3F,IAAI,CAAC,UAAU,OAAO,WAAW,GAC/B,OAAO;CAGT,IAAI,CAAC,cAAc,WAAW,WAAW,GACvC,OAAO;CAGT,OAAO,WAAW,MAAM,QAAQ,OAAO,SAAS,GAAG,CAAC;AACtD"}
|
package/package.json
CHANGED
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
"@standard-schema/spec": "^1.0.0"
|
|
16
16
|
},
|
|
17
17
|
"peerDependencies": {
|
|
18
|
-
"@warlock.js/cache": "4.8.
|
|
19
|
-
"@warlock.js/logger": "4.8.
|
|
18
|
+
"@warlock.js/cache": "4.8.1",
|
|
19
|
+
"@warlock.js/logger": "4.8.1",
|
|
20
20
|
"langfuse": "*",
|
|
21
21
|
"openai": "*",
|
|
22
22
|
"pg": "*",
|
|
23
23
|
"redis": "*"
|
|
24
24
|
},
|
|
25
|
-
"version": "4.8.
|
|
25
|
+
"version": "4.8.1",
|
|
26
26
|
"main": "./cjs/index.cjs",
|
|
27
27
|
"module": "./esm/index.mjs",
|
|
28
28
|
"types": "./esm/index.d.mts",
|