@tangle-network/agent-app 0.1.3 → 0.1.4
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/dist/chunk-5RV6CAHZ.js +137 -0
- package/dist/chunk-5RV6CAHZ.js.map +1 -0
- package/dist/{chunk-7P6VIHI4.js → chunk-AQ2BOPOQ.js} +8 -2
- package/dist/{chunk-7P6VIHI4.js.map → chunk-AQ2BOPOQ.js.map} +1 -1
- package/dist/chunk-EEPJGZJW.js +102 -0
- package/dist/chunk-EEPJGZJW.js.map +1 -0
- package/dist/chunk-EZXN67KE.js +318 -0
- package/dist/chunk-EZXN67KE.js.map +1 -0
- package/dist/config/index.d.ts +367 -0
- package/dist/config/index.js +9 -0
- package/dist/config/index.js.map +1 -0
- package/dist/delegation/index.d.ts +16 -1
- package/dist/delegation/index.js +5 -3
- package/dist/index.d.ts +7 -2
- package/dist/index.js +39 -5
- package/dist/knowledge-loop/index.d.ts +208 -0
- package/dist/knowledge-loop/index.js +11 -0
- package/dist/knowledge-loop/index.js.map +1 -0
- package/dist/model-BOP69mVu.d.ts +35 -0
- package/dist/preset-cloudflare/index.d.ts +244 -0
- package/dist/preset-cloudflare/index.js +23 -0
- package/dist/preset-cloudflare/index.js.map +1 -0
- package/dist/runtime/index.d.ts +2 -35
- package/package.json +31 -5
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// src/config/index.ts
|
|
2
|
+
function defineAgentApp(config) {
|
|
3
|
+
return config;
|
|
4
|
+
}
|
|
5
|
+
var agentAppConfigJsonSchema = {
|
|
6
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
7
|
+
$id: "https://tangle.tools/schemas/agent-app-config.json",
|
|
8
|
+
title: "AgentAppConfig",
|
|
9
|
+
description: "The declarative domain surface of a Tangle agent product.",
|
|
10
|
+
type: "object",
|
|
11
|
+
additionalProperties: false,
|
|
12
|
+
required: ["identity", "taxonomy", "knowledge", "integrations"],
|
|
13
|
+
properties: {
|
|
14
|
+
identity: {
|
|
15
|
+
type: "object",
|
|
16
|
+
additionalProperties: false,
|
|
17
|
+
required: ["name", "persona"],
|
|
18
|
+
properties: {
|
|
19
|
+
name: { type: "string", description: "Product/agent name." },
|
|
20
|
+
persona: { type: "string", description: "One-paragraph persona \u2014 the system-prompt spine." },
|
|
21
|
+
systemPromptFragments: {
|
|
22
|
+
type: "array",
|
|
23
|
+
items: { type: "string" },
|
|
24
|
+
description: "Verbatim system-prompt fragments appended after the persona, in order."
|
|
25
|
+
},
|
|
26
|
+
disclaimers: {
|
|
27
|
+
type: "object",
|
|
28
|
+
additionalProperties: { type: "string" },
|
|
29
|
+
description: "Named disclaimers keyed by stable id; values are literal text."
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
taxonomy: {
|
|
34
|
+
type: "object",
|
|
35
|
+
additionalProperties: false,
|
|
36
|
+
required: ["proposalTypes", "regulatedTypes"],
|
|
37
|
+
properties: {
|
|
38
|
+
proposalTypes: {
|
|
39
|
+
type: "array",
|
|
40
|
+
items: { type: "string" },
|
|
41
|
+
description: "Closed allow-list of proposal types the product can emit."
|
|
42
|
+
},
|
|
43
|
+
regulatedTypes: {
|
|
44
|
+
type: "array",
|
|
45
|
+
items: { type: "string" },
|
|
46
|
+
description: "Subset of proposalTypes that is approval-gated (certified-human required)."
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
knowledge: {
|
|
51
|
+
type: "object",
|
|
52
|
+
additionalProperties: false,
|
|
53
|
+
required: ["sources", "requirements"],
|
|
54
|
+
properties: {
|
|
55
|
+
sources: {
|
|
56
|
+
type: "array",
|
|
57
|
+
description: "Sources the acquisition loop may draw on.",
|
|
58
|
+
items: {
|
|
59
|
+
type: "object",
|
|
60
|
+
additionalProperties: false,
|
|
61
|
+
required: ["uri"],
|
|
62
|
+
properties: {
|
|
63
|
+
uri: { type: "string", description: "Where the source lives (opaque to agent-app)." },
|
|
64
|
+
kind: { type: "string", description: "Optional source classifier (web/vault/regulation/\u2026)." }
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
requirements: {
|
|
69
|
+
type: "array",
|
|
70
|
+
description: "Declarative KnowledgeRequirementSpec[] (../knowledge) that gate the loop.",
|
|
71
|
+
items: { type: "object", additionalProperties: true }
|
|
72
|
+
},
|
|
73
|
+
loop: {
|
|
74
|
+
type: "object",
|
|
75
|
+
additionalProperties: false,
|
|
76
|
+
description: "Acquisition-loop config.",
|
|
77
|
+
properties: {
|
|
78
|
+
goal: { type: "string", description: "Acquisition goal in natural language." },
|
|
79
|
+
minConfidence: {
|
|
80
|
+
type: "number",
|
|
81
|
+
minimum: 0,
|
|
82
|
+
maximum: 1,
|
|
83
|
+
description: "Minimum aggregate confidence the loop must reach."
|
|
84
|
+
},
|
|
85
|
+
freshness: { type: "string", description: "How fresh acquired knowledge must be." }
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
integrations: {
|
|
91
|
+
type: "object",
|
|
92
|
+
additionalProperties: false,
|
|
93
|
+
required: ["enabled"],
|
|
94
|
+
properties: {
|
|
95
|
+
enabled: {
|
|
96
|
+
type: "array",
|
|
97
|
+
items: { type: "string" },
|
|
98
|
+
description: "Enabled agent-integrations catalog kinds."
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
ui: {
|
|
103
|
+
type: "object",
|
|
104
|
+
additionalProperties: false,
|
|
105
|
+
description: "UI capability flags.",
|
|
106
|
+
properties: {
|
|
107
|
+
generatedUi: { type: "boolean", description: "Whether the agent may emit generated UI." }
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
delegation: {
|
|
111
|
+
type: "object",
|
|
112
|
+
additionalProperties: false,
|
|
113
|
+
description: "Background-agent / delegated-loop capability (sandbox path).",
|
|
114
|
+
properties: {
|
|
115
|
+
enabled: { type: "boolean", description: "Whether the agent may spawn delegate_research/delegate_code loops." }
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
model: {
|
|
119
|
+
type: "object",
|
|
120
|
+
additionalProperties: false,
|
|
121
|
+
description: "Resolved TangleModelConfig (../runtime). Omit to resolve from env.",
|
|
122
|
+
required: ["provider", "model", "apiKey", "baseUrl"],
|
|
123
|
+
properties: {
|
|
124
|
+
provider: { type: "string", enum: ["openai-compat", "anthropic"] },
|
|
125
|
+
model: { type: "string" },
|
|
126
|
+
apiKey: { type: "string" },
|
|
127
|
+
baseUrl: { type: "string" }
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export {
|
|
134
|
+
defineAgentApp,
|
|
135
|
+
agentAppConfigJsonSchema
|
|
136
|
+
};
|
|
137
|
+
//# sourceMappingURL=chunk-5RV6CAHZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/config/index.ts"],"sourcesContent":["/**\n * `@tangle-network/agent-app/config` — the typed `AgentAppConfig` contract.\n *\n * This is the single declarative DATA surface a coding agent fills to stand up a\n * new agent product. Everything an agent product otherwise hand-rolls as\n * imperative wiring — who the agent is, which proposal types exist and which are\n * approval-gated, what knowledge the control loop requires, which integrations\n * are connectable, how the model resolves — is expressed here as plain data the\n * rest of agent-app's modules consume through their typed seams:\n *\n * - `identity` → the system-prompt + disclaimer surface the chat pipeline reads.\n * - `taxonomy` → which `submit_proposal` types the `./tools` side channel\n * accepts, and which the approval queue treats as regulated\n * (certified-human-gated).\n * - `knowledge` → the `./knowledge` requirement specs that gate the loop, plus\n * the acquisition-loop goal/threshold the researcher pursues.\n * - `integrations` → which `@tangle-network/agent-integrations` catalog kinds the\n * product enables.\n * - `ui` → whether the agent may emit generated UI (`render_ui`).\n * - `model` → the `./runtime` `TangleModelConfig` (or null to resolve from env).\n *\n * Layering: this module is the CONTRACT only — pure types + an identity helper.\n * It introduces no behavior and no engine dependency; it REUSES the existing\n * `KnowledgeRequirementSpec`/`SatisfiedByRule` (from `../knowledge`) and\n * `TangleModelConfig` (from `../runtime`) rather than redefining them, so the\n * config a product authors is the exact shape those modules already consume.\n * Steps that build the composer/loader read this file as the schema floor.\n */\n\nimport type {\n KnowledgeRequirementSpec,\n SatisfiedByRule,\n} from '../knowledge/index'\nimport type { TangleModelConfig } from '../runtime/index'\n\n// Re-export the borrowed types so a config author has a single import surface\n// (`@tangle-network/agent-app/config`) and never has to reach into `../knowledge`\n// or `../runtime` to spell out a field's type. These are the SAME types the\n// knowledge gate and runtime model resolver consume — not parallel copies.\nexport type { KnowledgeRequirementSpec, SatisfiedByRule, TangleModelConfig }\n\n/**\n * Who the agent is, as data. Composed into the chat pipeline's system prompt;\n * never baked into agent-app (a domain value, per the layering contract).\n */\nexport interface AgentIdentityConfig {\n /** Product/agent name, e.g. `\"WinFinance Ops Partner\"`. Shown to the user and\n * available to the system-prompt builder. */\n name: string\n /** One-paragraph persona statement — the agent's role, voice, and remit. The\n * spine of the system prompt. */\n persona: string\n /** Additional system-prompt fragments appended verbatim after the persona\n * (standing workflows, hard rules, tone). Order is preserved. Optional. */\n systemPromptFragments?: string[]\n /** Named disclaimers the product surfaces (e.g. a regulatory human-in-the-loop\n * notice). Keyed by a stable id (`compliance`, `not-advice`, …) so the chat\n * pipeline / UI can select one by name. Values are the literal text. Optional. */\n disclaimers?: Record<string, string>\n}\n\n/**\n * The proposal taxonomy, as data. `proposalTypes` is the closed set of\n * `submit_proposal` types the `./tools` side channel accepts; `regulatedTypes`\n * is the subset that is approval-gated — the executor refuses to run one without\n * a certified human approver. `regulatedTypes` MUST be a subset of\n * `proposalTypes` (validated by the loader step; not enforced at the type level).\n */\nexport interface AgentTaxonomyConfig {\n /** Every proposal type this product can emit, e.g.\n * `['propose_swap', 'contact_lead', 'policy_change']`. The closed allow-list\n * the tool layer validates a `submit_proposal` call against. */\n proposalTypes: string[]\n /** The subset of `proposalTypes` that is regulated → cannot execute without a\n * certified-human approver. The approval executor reads this to decide which\n * proposals are fail-loud certified-gated. */\n regulatedTypes: string[]\n}\n\n/** A knowledge source the acquisition loop / researcher may draw on. */\nexport interface KnowledgeSourceSpec {\n /** Where the source lives — a URL, a `vault://` path, an integration ref, etc.\n * Opaque to agent-app; the consumer's loader resolves it. */\n uri: string\n /** Optional source classifier the researcher uses to pick a fetch strategy,\n * e.g. `'web'`, `'vault'`, `'regulation'`, `'integration'`. Free-form. */\n kind?: string\n}\n\n/**\n * The knowledge-acquisition loop config — the goal the researcher pursues and\n * the gate it must clear before the loop is considered satisfied. All optional;\n * a product with only static requirement specs omits it.\n */\nexport interface KnowledgeLoopConfig {\n /** The acquisition goal in natural language, e.g.\n * `\"ground every quoted premium against a real policy record\"`. */\n goal?: string\n /** The minimum aggregate confidence [0, 1] the loop must reach to pass its\n * gate. The runtime control loop blocks below this. Default decided by the\n * consumer's loop wiring when omitted. */\n minConfidence?: number\n /** How fresh acquired knowledge must be, e.g. `'static'`, `'7d'`, `'session'`.\n * Free-form; the consumer's loop interprets it. */\n freshness?: string\n}\n\n/**\n * The knowledge surface, as data. `sources` are what the researcher may read;\n * `requirements` are the declarative `./knowledge` specs that gate the control\n * loop (reused verbatim — the same `KnowledgeRequirementSpec` the gate scores);\n * `loop` configures the acquisition pass.\n */\nexport interface AgentKnowledgeConfig {\n /** Sources the acquisition loop / researcher may draw on. */\n sources: KnowledgeSourceSpec[]\n /** The declarative requirement specs that gate the loop. Reuses\n * `KnowledgeRequirementSpec` from `../knowledge` — `buildKnowledgeRequirements`\n * + `deriveSignals` consume these directly. */\n requirements: KnowledgeRequirementSpec[]\n /** Optional acquisition-loop config (goal + confidence gate + freshness). */\n loop?: KnowledgeLoopConfig\n}\n\n/**\n * Which integrations the product enables, as data. `enabled` lists\n * `@tangle-network/agent-integrations` catalog kinds the product connects\n * (e.g. `['shurens', 'lead-crm', 'whatsapp']`); the integration hub resolves\n * each to a connector. Strings, not connector objects — agent-app bakes no\n * catalog value.\n */\nexport interface AgentIntegrationsConfig {\n /** Catalog kinds this product enables. */\n enabled: string[]\n}\n\n/** UI capability flags, as data. */\nexport interface AgentUiConfig {\n /** Whether the agent may emit generated UI (the `render_ui` / OpenUI side\n * channel). When false/omitted, the tool layer can omit/refuse the tool.\n * Default behavior decided by the consumer; omit to leave unset. */\n generatedUi?: boolean\n}\n\n/** Background-agent / delegated-loop capability, as data. */\nexport interface AgentDelegationConfig {\n /** When true, the app's own agent may spawn `delegate_research` /\n * `delegate_code` loops that run to completion in their OWN sandbox and\n * return the artifact (the `../delegation` driven-loop MCP). Sandbox-path\n * ONLY — the browser/edge path ignores it. Wired via the existing\n * `buildDelegationMcpServer`; never reimplemented. */\n enabled?: boolean\n}\n\n/**\n * The declarative domain surface of a Tangle agent product.\n *\n * A coding agent fills THIS object and nothing else to define a product's\n * identity, proposal taxonomy, knowledge gate, integrations, UI capability, and\n * model. Every field is DATA consumed by an agent-app module through its typed\n * seam — no field is behavior. Author it through {@link defineAgentApp} for\n * autocomplete and a single import.\n */\nexport interface AgentAppConfig {\n /** Who the agent is — name, persona, system-prompt fragments, disclaimers. */\n identity: AgentIdentityConfig\n /** Proposal types + which are regulated/approval-gated. */\n taxonomy: AgentTaxonomyConfig\n /** Knowledge sources, requirement specs (the loop gate), and loop config. */\n knowledge: AgentKnowledgeConfig\n /** Enabled integration catalog kinds. */\n integrations: AgentIntegrationsConfig\n /** UI capability flags. Optional. */\n ui?: AgentUiConfig\n /** Background-agent / delegated-loop capability (sandbox path). Optional. */\n delegation?: AgentDelegationConfig\n /** The resolved model config (`../runtime`'s `TangleModelConfig`). Omit to\n * resolve from env at boot via `resolveTangleModelConfig`. */\n model?: TangleModelConfig\n}\n\n/**\n * Identity helper: returns its argument unchanged, but anchors inference so a\n * coding agent authoring a config gets full autocomplete + type-checking from a\n * single import. The canonical way to declare a product config:\n *\n * ```ts\n * import { defineAgentApp } from '@tangle-network/agent-app/config'\n *\n * export const config = defineAgentApp({\n * identity: { name: 'WinFinance', persona: '…' },\n * taxonomy: { proposalTypes: ['propose_swap'], regulatedTypes: ['propose_swap'] },\n * knowledge: { sources: [], requirements: [] },\n * integrations: { enabled: ['shurens'] },\n * })\n * ```\n */\nexport function defineAgentApp<const T extends AgentAppConfig>(config: T): T {\n return config\n}\n\n/**\n * Machine-readable JSON Schema (draft 2020-12) for {@link AgentAppConfig}.\n *\n * The schema FLOOR a non-TypeScript coding agent (or a config validator/UI) reads\n * to know the shape without parsing the `.d.ts`. Kept in lockstep with the\n * interfaces above by the config test, which asserts the documented fields are\n * present. `KnowledgeRequirementSpec`'s full sub-shape is intentionally left\n * `additionalProperties: true` here — its authoritative definition lives in\n * `../knowledge`; this floor pins only the fields the config contract owns.\n */\nexport const agentAppConfigJsonSchema = {\n $schema: 'https://json-schema.org/draft/2020-12/schema',\n $id: 'https://tangle.tools/schemas/agent-app-config.json',\n title: 'AgentAppConfig',\n description: 'The declarative domain surface of a Tangle agent product.',\n type: 'object',\n additionalProperties: false,\n required: ['identity', 'taxonomy', 'knowledge', 'integrations'],\n properties: {\n identity: {\n type: 'object',\n additionalProperties: false,\n required: ['name', 'persona'],\n properties: {\n name: { type: 'string', description: 'Product/agent name.' },\n persona: { type: 'string', description: 'One-paragraph persona — the system-prompt spine.' },\n systemPromptFragments: {\n type: 'array',\n items: { type: 'string' },\n description: 'Verbatim system-prompt fragments appended after the persona, in order.',\n },\n disclaimers: {\n type: 'object',\n additionalProperties: { type: 'string' },\n description: 'Named disclaimers keyed by stable id; values are literal text.',\n },\n },\n },\n taxonomy: {\n type: 'object',\n additionalProperties: false,\n required: ['proposalTypes', 'regulatedTypes'],\n properties: {\n proposalTypes: {\n type: 'array',\n items: { type: 'string' },\n description: 'Closed allow-list of proposal types the product can emit.',\n },\n regulatedTypes: {\n type: 'array',\n items: { type: 'string' },\n description: 'Subset of proposalTypes that is approval-gated (certified-human required).',\n },\n },\n },\n knowledge: {\n type: 'object',\n additionalProperties: false,\n required: ['sources', 'requirements'],\n properties: {\n sources: {\n type: 'array',\n description: 'Sources the acquisition loop may draw on.',\n items: {\n type: 'object',\n additionalProperties: false,\n required: ['uri'],\n properties: {\n uri: { type: 'string', description: 'Where the source lives (opaque to agent-app).' },\n kind: { type: 'string', description: 'Optional source classifier (web/vault/regulation/…).' },\n },\n },\n },\n requirements: {\n type: 'array',\n description: \"Declarative KnowledgeRequirementSpec[] (../knowledge) that gate the loop.\",\n items: { type: 'object', additionalProperties: true },\n },\n loop: {\n type: 'object',\n additionalProperties: false,\n description: 'Acquisition-loop config.',\n properties: {\n goal: { type: 'string', description: 'Acquisition goal in natural language.' },\n minConfidence: {\n type: 'number',\n minimum: 0,\n maximum: 1,\n description: 'Minimum aggregate confidence the loop must reach.',\n },\n freshness: { type: 'string', description: 'How fresh acquired knowledge must be.' },\n },\n },\n },\n },\n integrations: {\n type: 'object',\n additionalProperties: false,\n required: ['enabled'],\n properties: {\n enabled: {\n type: 'array',\n items: { type: 'string' },\n description: 'Enabled agent-integrations catalog kinds.',\n },\n },\n },\n ui: {\n type: 'object',\n additionalProperties: false,\n description: 'UI capability flags.',\n properties: {\n generatedUi: { type: 'boolean', description: 'Whether the agent may emit generated UI.' },\n },\n },\n delegation: {\n type: 'object',\n additionalProperties: false,\n description: 'Background-agent / delegated-loop capability (sandbox path).',\n properties: {\n enabled: { type: 'boolean', description: 'Whether the agent may spawn delegate_research/delegate_code loops.' },\n },\n },\n model: {\n type: 'object',\n additionalProperties: false,\n description: \"Resolved TangleModelConfig (../runtime). Omit to resolve from env.\",\n required: ['provider', 'model', 'apiKey', 'baseUrl'],\n properties: {\n provider: { type: 'string', enum: ['openai-compat', 'anthropic'] },\n model: { type: 'string' },\n apiKey: { type: 'string' },\n baseUrl: { type: 'string' },\n },\n },\n },\n} as const\n"],"mappings":"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","names":[]}
|
|
@@ -24,10 +24,16 @@ function buildDelegationMcpServer(opts) {
|
|
|
24
24
|
metadata: { surface: "delegation:dispatch", tools: DELEGATION_TOOLS }
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
+
function delegationMcpForConfig(config, opts) {
|
|
28
|
+
if (!config.delegation?.enabled) return {};
|
|
29
|
+
const server = buildDelegationMcpServer(opts);
|
|
30
|
+
return server ? { [DELEGATION_MCP_SERVER_KEY]: server } : {};
|
|
31
|
+
}
|
|
27
32
|
|
|
28
33
|
export {
|
|
29
34
|
DELEGATION_MCP_SERVER_KEY,
|
|
30
35
|
DELEGATION_TOOLS,
|
|
31
|
-
buildDelegationMcpServer
|
|
36
|
+
buildDelegationMcpServer,
|
|
37
|
+
delegationMcpForConfig
|
|
32
38
|
};
|
|
33
|
-
//# sourceMappingURL=chunk-
|
|
39
|
+
//# sourceMappingURL=chunk-AQ2BOPOQ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/delegation/index.ts"],"sourcesContent":["/**\n * Delegated looped work — the agent-runtime \"driven loop\" MCP.\n *\n * For multi-step research or document generation, the agent dispatches a loop\n * that runs to completion in its OWN sandbox (via @tangle-network/agent-runtime's\n * stdio MCP, executed in the agent-driver) and returns the artifact. This is\n * how an app's main agent \"programs / delegates\" without doing long mechanical\n * work inline. It is an OPTIONAL module — an app opts in by spreading the\n * server into its profile's `mcp` map.\n *\n * The shape is the portable `AgentProfileMcpServer` the sandbox SDK accepts\n * (transport: 'stdio' → the orchestrator derives `{ type:'local', command }`).\n * Kept structural here so this package needs no sandbox-SDK dependency.\n */\n\nexport const DELEGATION_MCP_SERVER_KEY = 'agent-runtime-delegation'\n\nexport const DELEGATION_TOOLS = [\n 'delegate_code',\n 'delegate_research',\n 'delegate_feedback',\n 'delegation_status',\n 'delegation_history',\n] as const\n\n/** The stdio MCP server entry — structurally an `AgentProfileMcpServer`. */\nexport interface DelegationMcpServer {\n transport: 'stdio'\n command: string\n args: string[]\n env: Record<string, string>\n enabled: true\n metadata: { surface: string; tools: readonly string[] }\n}\n\nexport interface BuildDelegationOptions {\n /** Platform API key the delegated loop authenticates with (required — the\n * loop runs in its own sandbox and bills against this key). Omit/empty →\n * returns undefined (fail-closed: no key, no delegation). */\n apiKey?: string\n /** Extra env to forward into the delegated loop (sandbox base URL, OTel trace\n * propagation, etc.). Only defined values are forwarded. */\n forwardEnv?: Record<string, string | undefined>\n /** npm spec for the runtime MCP. Defaults to the published agent-runtime. */\n packageSpec?: string\n}\n\n/**\n * Build the delegation MCP server entry, keyed under\n * {@link DELEGATION_MCP_SERVER_KEY}, or `undefined` when no platform API key is\n * available. Spread the result into the profile's `mcp` map:\n *\n * const delegation = buildDelegationMcpServer({ apiKey: env.TANGLE_API_KEY, forwardEnv: env })\n * const mcp = { ...(delegation ? { [DELEGATION_MCP_SERVER_KEY]: delegation } : {}) }\n */\nexport function buildDelegationMcpServer(opts: BuildDelegationOptions): DelegationMcpServer | undefined {\n if (!opts.apiKey) return undefined\n const env: Record<string, string> = { TANGLE_API_KEY: opts.apiKey }\n const forward = opts.forwardEnv ?? {}\n for (const key of ['SANDBOX_BASE_URL', 'OTEL_EXPORTER_OTLP_ENDPOINT', 'OTEL_EXPORTER_OTLP_HEADERS', 'TRACE_ID', 'PARENT_SPAN_ID']) {\n const value = forward[key]\n if (value) env[key] = value\n }\n return {\n transport: 'stdio',\n command: 'npx',\n args: ['-y', opts.packageSpec ?? '@tangle-network/agent-runtime', 'mcp'],\n env,\n enabled: true,\n metadata: { surface: 'delegation:dispatch', tools: DELEGATION_TOOLS },\n }\n}\n"],"mappings":";AAeO,IAAM,4BAA4B;AAElC,IAAM,mBAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAgCO,SAAS,yBAAyB,MAA+D;AACtG,MAAI,CAAC,KAAK,OAAQ,QAAO;AACzB,QAAM,MAA8B,EAAE,gBAAgB,KAAK,OAAO;AAClE,QAAM,UAAU,KAAK,cAAc,CAAC;AACpC,aAAW,OAAO,CAAC,oBAAoB,+BAA+B,8BAA8B,YAAY,gBAAgB,GAAG;AACjI,UAAM,QAAQ,QAAQ,GAAG;AACzB,QAAI,MAAO,KAAI,GAAG,IAAI;AAAA,EACxB;AACA,SAAO;AAAA,IACL,WAAW;AAAA,IACX,SAAS;AAAA,IACT,MAAM,CAAC,MAAM,KAAK,eAAe,iCAAiC,KAAK;AAAA,IACvE;AAAA,IACA,SAAS;AAAA,IACT,UAAU,EAAE,SAAS,uBAAuB,OAAO,iBAAiB;AAAA,EACtE;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/delegation/index.ts"],"sourcesContent":["/**\n * Delegated looped work — the agent-runtime \"driven loop\" MCP.\n *\n * For multi-step research or document generation, the agent dispatches a loop\n * that runs to completion in its OWN sandbox (via @tangle-network/agent-runtime's\n * stdio MCP, executed in the agent-driver) and returns the artifact. This is\n * how an app's main agent \"programs / delegates\" without doing long mechanical\n * work inline. It is an OPTIONAL module — an app opts in by spreading the\n * server into its profile's `mcp` map.\n *\n * The shape is the portable `AgentProfileMcpServer` the sandbox SDK accepts\n * (transport: 'stdio' → the orchestrator derives `{ type:'local', command }`).\n * Kept structural here so this package needs no sandbox-SDK dependency.\n */\n\nexport const DELEGATION_MCP_SERVER_KEY = 'agent-runtime-delegation'\n\nexport const DELEGATION_TOOLS = [\n 'delegate_code',\n 'delegate_research',\n 'delegate_feedback',\n 'delegation_status',\n 'delegation_history',\n] as const\n\n/** The stdio MCP server entry — structurally an `AgentProfileMcpServer`. */\nexport interface DelegationMcpServer {\n transport: 'stdio'\n command: string\n args: string[]\n env: Record<string, string>\n enabled: true\n metadata: { surface: string; tools: readonly string[] }\n}\n\nexport interface BuildDelegationOptions {\n /** Platform API key the delegated loop authenticates with (required — the\n * loop runs in its own sandbox and bills against this key). Omit/empty →\n * returns undefined (fail-closed: no key, no delegation). */\n apiKey?: string\n /** Extra env to forward into the delegated loop (sandbox base URL, OTel trace\n * propagation, etc.). Only defined values are forwarded. */\n forwardEnv?: Record<string, string | undefined>\n /** npm spec for the runtime MCP. Defaults to the published agent-runtime. */\n packageSpec?: string\n}\n\n/**\n * Build the delegation MCP server entry, keyed under\n * {@link DELEGATION_MCP_SERVER_KEY}, or `undefined` when no platform API key is\n * available. Spread the result into the profile's `mcp` map:\n *\n * const delegation = buildDelegationMcpServer({ apiKey: env.TANGLE_API_KEY, forwardEnv: env })\n * const mcp = { ...(delegation ? { [DELEGATION_MCP_SERVER_KEY]: delegation } : {}) }\n */\nexport function buildDelegationMcpServer(opts: BuildDelegationOptions): DelegationMcpServer | undefined {\n if (!opts.apiKey) return undefined\n const env: Record<string, string> = { TANGLE_API_KEY: opts.apiKey }\n const forward = opts.forwardEnv ?? {}\n for (const key of ['SANDBOX_BASE_URL', 'OTEL_EXPORTER_OTLP_ENDPOINT', 'OTEL_EXPORTER_OTLP_HEADERS', 'TRACE_ID', 'PARENT_SPAN_ID']) {\n const value = forward[key]\n if (value) env[key] = value\n }\n return {\n transport: 'stdio',\n command: 'npx',\n args: ['-y', opts.packageSpec ?? '@tangle-network/agent-runtime', 'mcp'],\n env,\n enabled: true,\n metadata: { surface: 'delegation:dispatch', tools: DELEGATION_TOOLS },\n }\n}\n\n/**\n * Config-driven wiring: returns the delegation MCP entry keyed under\n * {@link DELEGATION_MCP_SERVER_KEY} when the product's `config.delegation.enabled`\n * is true (and a platform key is available), else an empty object. Spread the\n * result directly into the sandbox profile's `mcp` map — this is the seam\n * `agent.config.delegation` flows through, so a coding agent toggles background\n * agents/loops by flipping one boolean, never by wiring the MCP by hand.\n *\n * const mcp = { ...rest, ...delegationMcpForConfig(config, { apiKey: env.TANGLE_API_KEY, forwardEnv: env }) }\n */\nexport function delegationMcpForConfig(\n config: { delegation?: { enabled?: boolean } },\n opts: BuildDelegationOptions,\n): Record<string, DelegationMcpServer> {\n if (!config.delegation?.enabled) return {}\n const server = buildDelegationMcpServer(opts)\n return server ? { [DELEGATION_MCP_SERVER_KEY]: server } : {}\n}\n"],"mappings":";AAeO,IAAM,4BAA4B;AAElC,IAAM,mBAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAgCO,SAAS,yBAAyB,MAA+D;AACtG,MAAI,CAAC,KAAK,OAAQ,QAAO;AACzB,QAAM,MAA8B,EAAE,gBAAgB,KAAK,OAAO;AAClE,QAAM,UAAU,KAAK,cAAc,CAAC;AACpC,aAAW,OAAO,CAAC,oBAAoB,+BAA+B,8BAA8B,YAAY,gBAAgB,GAAG;AACjI,UAAM,QAAQ,QAAQ,GAAG;AACzB,QAAI,MAAO,KAAI,GAAG,IAAI;AAAA,EACxB;AACA,SAAO;AAAA,IACL,WAAW;AAAA,IACX,SAAS;AAAA,IACT,MAAM,CAAC,MAAM,KAAK,eAAe,iCAAiC,KAAK;AAAA,IACvE;AAAA,IACA,SAAS;AAAA,IACT,UAAU,EAAE,SAAS,uBAAuB,OAAO,iBAAiB;AAAA,EACtE;AACF;AAYO,SAAS,uBACd,QACA,MACqC;AACrC,MAAI,CAAC,OAAO,YAAY,QAAS,QAAO,CAAC;AACzC,QAAM,SAAS,yBAAyB,IAAI;AAC5C,SAAO,SAAS,EAAE,CAAC,yBAAyB,GAAG,OAAO,IAAI,CAAC;AAC7D;","names":[]}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// src/knowledge-loop/index.ts
|
|
2
|
+
import {
|
|
3
|
+
runKnowledgeResearchLoop,
|
|
4
|
+
textSourceAdapter
|
|
5
|
+
} from "@tangle-network/agent-knowledge";
|
|
6
|
+
var DEFAULT_MIN_CONFIDENCE = 0.7;
|
|
7
|
+
var DEFAULT_GOAL = "Acquire and ground the knowledge this product requires.";
|
|
8
|
+
function reviewCandidate(candidate, minConfidence) {
|
|
9
|
+
if (!candidate.proposalText) {
|
|
10
|
+
return {
|
|
11
|
+
accepted: true,
|
|
12
|
+
reason: "no-proposal",
|
|
13
|
+
confidence: candidate.confidence ?? 1,
|
|
14
|
+
minConfidence
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
const confidence = candidate.confidence ?? 0;
|
|
18
|
+
if (confidence >= minConfidence) {
|
|
19
|
+
return {
|
|
20
|
+
accepted: true,
|
|
21
|
+
reason: `confidence ${confidence.toFixed(2)} >= minConfidence ${minConfidence.toFixed(2)}`,
|
|
22
|
+
confidence,
|
|
23
|
+
minConfidence
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
accepted: false,
|
|
28
|
+
reason: `confidence ${confidence.toFixed(2)} < minConfidence ${minConfidence.toFixed(2)}`,
|
|
29
|
+
confidence,
|
|
30
|
+
minConfidence
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function createReviewerDecider(propose) {
|
|
34
|
+
return async (input) => {
|
|
35
|
+
const candidate = await propose(input);
|
|
36
|
+
const verdict = reviewCandidate(candidate, input.minConfidence);
|
|
37
|
+
return { candidate, verdict };
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function toResearchDecision(decision) {
|
|
41
|
+
const { candidate, verdict } = decision;
|
|
42
|
+
return {
|
|
43
|
+
notes: candidate.notes,
|
|
44
|
+
sourcePaths: candidate.sourcePaths,
|
|
45
|
+
sourceTexts: candidate.sourceTexts,
|
|
46
|
+
proposalText: verdict.accepted ? candidate.proposalText : void 0,
|
|
47
|
+
done: candidate.done,
|
|
48
|
+
metadata: {
|
|
49
|
+
...candidate.metadata ?? {},
|
|
50
|
+
gate: verdict
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
var noopDecider = (input) => ({
|
|
55
|
+
candidate: { done: true, notes: "no decider supplied; nothing proposed" },
|
|
56
|
+
verdict: {
|
|
57
|
+
accepted: true,
|
|
58
|
+
reason: "no-proposal",
|
|
59
|
+
confidence: 1,
|
|
60
|
+
minConfidence: input.minConfidence
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
function createKnowledgeLoop(knowledge, deps) {
|
|
64
|
+
const goal = knowledge.loop?.goal ?? deps.defaultGoal ?? DEFAULT_GOAL;
|
|
65
|
+
const minConfidence = knowledge.loop?.minConfidence ?? deps.defaultMinConfidence ?? DEFAULT_MIN_CONFIDENCE;
|
|
66
|
+
const freshness = knowledge.loop?.freshness;
|
|
67
|
+
const adapters = [...deps.adapters ?? [], textSourceAdapter];
|
|
68
|
+
const decide = deps.decide ?? noopDecider;
|
|
69
|
+
const run = () => runKnowledgeResearchLoop({
|
|
70
|
+
root: deps.root,
|
|
71
|
+
goal,
|
|
72
|
+
maxIterations: deps.maxIterations,
|
|
73
|
+
actor: deps.actor,
|
|
74
|
+
signal: deps.signal,
|
|
75
|
+
onStep: deps.onStep,
|
|
76
|
+
sourceOptions: { adapters },
|
|
77
|
+
async step(context) {
|
|
78
|
+
const decision = await decide({
|
|
79
|
+
context,
|
|
80
|
+
goal,
|
|
81
|
+
minConfidence,
|
|
82
|
+
freshness,
|
|
83
|
+
sources: knowledge.sources,
|
|
84
|
+
driver: deps.driver
|
|
85
|
+
});
|
|
86
|
+
return toResearchDecision(decision);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
return {
|
|
90
|
+
run,
|
|
91
|
+
goal,
|
|
92
|
+
minConfidence,
|
|
93
|
+
adapters
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export {
|
|
98
|
+
reviewCandidate,
|
|
99
|
+
createReviewerDecider,
|
|
100
|
+
createKnowledgeLoop
|
|
101
|
+
};
|
|
102
|
+
//# sourceMappingURL=chunk-EEPJGZJW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/knowledge-loop/index.ts"],"sourcesContent":["/**\n * `@tangle-network/agent-app/knowledge-loop` — wire the declarative\n * `AgentKnowledgeConfig` to a running, source-grounded, eval-gated knowledge\n * acquisition loop.\n *\n * This module does NOT implement a loop. `@tangle-network/agent-knowledge`\n * already ships `runKnowledgeResearchLoop` — the source-grounded,\n * propose-don't-apply primitive (sources become immutable records first; only\n * accepted `---FILE: knowledge/...---` write blocks are applied; lint +\n * validation + optional readiness gate every iteration). It is pluggable on two\n * seams: a `SourceAdapter[]` (how raw bytes/text become curated source records —\n * text by default, audio/video/image adapters added by the consumer) and a\n * `step` decider (the per-iteration policy: an agentic judge, a sandbox run, or\n * a deterministic gate — the loop deliberately bakes none).\n *\n * `createKnowledgeLoop(config.knowledge, deps)` is the thin mapper between the\n * two:\n *\n * - `config.knowledge.sources` → adapter selection. The text adapter is the\n * default; `deps.adapters` is the multimodal seam (prepend an audio/video/\n * image `SourceAdapter` and the loop ingests that media). agent-app bakes no\n * media handler — it's a parameter.\n * - `config.knowledge.loop` → `runKnowledgeResearchLoop` options. `goal` maps\n * to the loop goal, `minConfidence` to the gate threshold, `freshness` is\n * threaded to the decider so a per-source-freshness policy can read it.\n * - `deps.decide` → the pluggable gate. DEFAULT is a reviewer policy\n * (agent-knowledge's propose-don't-apply posture): a candidate carrying\n * confidence below `minConfidence` is gated OUT (its proposal text is\n * dropped — sources are still recorded, because grounding is never the thing\n * we gate); at/above threshold it is accepted and the loop applies the write\n * blocks. Swap in an agentic judge or a sandbox run by passing your own\n * `decide`.\n * - `deps.driver` → the agent-runtime turn driver (this repo's `../runtime`\n * `runAppToolLoop` seam, or any compatible driver) the decider invokes for\n * the loop's agent turns. Optional; a deterministic / sandbox decider needs\n * no model turns and omits it.\n *\n * Layering: agent-knowledge and agent-runtime are PEER dependencies, never\n * bundled. This module imports only TYPES + the loop entry from agent-knowledge\n * and stays substrate-free behind the `decide` / `driver` / `adapters` seams.\n */\n\nimport type {\n AddSourceTextInput,\n KnowledgeResearchLoopContext,\n KnowledgeResearchLoopDecision,\n KnowledgeResearchLoopResult,\n RunKnowledgeResearchLoopOptions,\n SourceAdapter,\n} from '@tangle-network/agent-knowledge'\nimport {\n runKnowledgeResearchLoop,\n textSourceAdapter,\n} from '@tangle-network/agent-knowledge'\nimport type { AgentKnowledgeConfig, KnowledgeSourceSpec } from '../config/index'\n\n/**\n * A research candidate the decider evaluates before the loop applies it. This is\n * the propose-don't-apply unit: notes + the sources discovered this iteration +\n * the proposed write blocks, each carrying a confidence the gate scores against\n * the configured `minConfidence`.\n */\nexport interface KnowledgeCandidate {\n /** Human-readable research transcript for this iteration. */\n notes?: string\n /**\n * Textual source artifacts to register as immutable sources BEFORE any\n * proposal is applied. Recording these is grounding, not the gated step — a\n * rejected candidate still keeps its sources (so the next iteration is better\n * grounded). The decider may not strip these.\n */\n sourceTexts?: AddSourceTextInput[]\n /** Local files to register as immutable sources (same grounding posture). */\n sourcePaths?: string[]\n /**\n * Safe-write-protocol text (`---FILE: knowledge/...---` blocks). This IS the\n * gated step: the default decider drops it when `confidence < minConfidence`.\n */\n proposalText?: string\n /**\n * Aggregate confidence in this candidate's proposal, in [0, 1]. The default\n * reviewer gate compares this to `minConfidence`. A candidate with no\n * `proposalText` needs no confidence (nothing is gated).\n */\n confidence?: number\n /** The researcher's signal that the goal is met; ends the loop. */\n done?: boolean\n metadata?: Record<string, unknown>\n}\n\n/** The verdict a gate returns for one candidate. */\nexport interface KnowledgeGateVerdict {\n /** Whether the candidate's proposal is accepted (applied) or gated out. */\n accepted: boolean\n /** Why — surfaced in the decision metadata for audit. */\n reason: string\n /** The confidence the gate scored (echoed for telemetry). */\n confidence: number\n /** The threshold it was scored against. */\n minConfidence: number\n}\n\n/**\n * The pluggable acquisition policy. Given the loop context (current index, lint,\n * validation, freshness target, the driver), produce a candidate AND a gate\n * verdict on it. This is the seam an agentic judge or a sandbox run plugs into;\n * the default {@link createReviewerDecider} is a confidence gate.\n */\nexport interface KnowledgeDecider {\n (input: KnowledgeDeciderInput): Promise<KnowledgeDecision> | KnowledgeDecision\n}\n\nexport interface KnowledgeDeciderInput {\n /** The agent-knowledge loop context for this iteration. */\n context: KnowledgeResearchLoopContext\n /** The acquisition goal (from `config.loop.goal` or a deps fallback). */\n goal: string\n /** The confidence threshold a proposal must clear to be applied. */\n minConfidence: number\n /** The freshness target (`config.loop.freshness`), if set. */\n freshness?: string\n /** The configured sources, for a decider that fetches/selects among them. */\n sources: KnowledgeSourceSpec[]\n /** The agent-runtime turn driver, if one was supplied to the loop. */\n driver?: KnowledgeLoopDriver\n}\n\nexport interface KnowledgeDecision {\n /** The candidate the policy produced (may be empty to end the loop). */\n candidate: KnowledgeCandidate\n /** The gate's verdict on the candidate's proposal. */\n verdict: KnowledgeGateVerdict\n}\n\n/**\n * The agent-runtime turn driver seam. This is exactly `../runtime`'s\n * `runAppToolLoop` shape (a bounded, awaitable tool-driving turn loop over a\n * model). Typed structurally so a decider can drive the loop's agent turns\n * without this module importing the runtime engine. A deterministic / sandbox\n * decider may omit it.\n */\nexport interface KnowledgeLoopDriver {\n (opts: {\n systemPrompt: string\n userMessage: string\n }): Promise<{ finalText: string }>\n}\n\nexport interface CreateKnowledgeLoopDeps {\n /**\n * The knowledge-base root the loop reads/writes (an agent-knowledge layout).\n * Required — agent-knowledge owns disk; agent-app owns only the wiring.\n */\n root: string\n /**\n * The per-iteration policy. Defaults to {@link createReviewerDecider} keyed on\n * the config's `minConfidence`. Pass your own to use an agentic judge or a\n * sandbox run.\n */\n decide?: KnowledgeDecider\n /**\n * Extra source adapters (audio/video/image/PDF/...). The text adapter is\n * always present as the fallback; these are tried first so a multimodal\n * source is claimed by its adapter. This is the multimodal seam.\n */\n adapters?: SourceAdapter[]\n /** The agent-runtime turn driver for the loop's agent turns. */\n driver?: KnowledgeLoopDriver\n /**\n * Fallback goal when `config.loop.goal` is unset. agent-knowledge requires a\n * goal; this keeps the loop runnable for a config with only requirement specs.\n */\n defaultGoal?: string\n /** Default confidence threshold when `config.loop.minConfidence` is unset. */\n defaultMinConfidence?: number\n /** Max research iterations (forwarded to agent-knowledge). Default 3. */\n maxIterations?: number\n /** Actor stamped on the loop's knowledge events. */\n actor?: string\n /** Abort the loop. */\n signal?: AbortSignal\n /** Per-step hook (forwarded to agent-knowledge's `onStep`). */\n onStep?: RunKnowledgeResearchLoopOptions['onStep']\n}\n\n/** The handle `createKnowledgeLoop` returns. */\nexport interface KnowledgeLoop {\n /** Run the acquisition loop to completion and return the agent-knowledge result. */\n run(): Promise<KnowledgeResearchLoopResult>\n /** The resolved goal the loop pursues. */\n readonly goal: string\n /** The resolved confidence gate threshold. */\n readonly minConfidence: number\n /** The adapters the loop uses (consumer extras first, text last). */\n readonly adapters: SourceAdapter[]\n}\n\nconst DEFAULT_MIN_CONFIDENCE = 0.7\nconst DEFAULT_GOAL = 'Acquire and ground the knowledge this product requires.'\n\n/**\n * The default gate — agent-knowledge's propose-don't-apply reviewer posture as a\n * confidence threshold. A candidate's `proposalText` is applied only when its\n * `confidence` is at/above `minConfidence`; otherwise the proposal is gated out\n * (sources are still recorded). A candidate with no `proposalText` is trivially\n * accepted (nothing to gate). This is the floor policy; swap in an agentic judge\n * or a sandbox-run decider via `deps.decide` for richer review.\n */\nexport function reviewCandidate(\n candidate: KnowledgeCandidate,\n minConfidence: number,\n): KnowledgeGateVerdict {\n if (!candidate.proposalText) {\n return {\n accepted: true,\n reason: 'no-proposal',\n confidence: candidate.confidence ?? 1,\n minConfidence,\n }\n }\n const confidence = candidate.confidence ?? 0\n if (confidence >= minConfidence) {\n return {\n accepted: true,\n reason: `confidence ${confidence.toFixed(2)} >= minConfidence ${minConfidence.toFixed(2)}`,\n confidence,\n minConfidence,\n }\n }\n return {\n accepted: false,\n reason: `confidence ${confidence.toFixed(2)} < minConfidence ${minConfidence.toFixed(2)}`,\n confidence,\n minConfidence,\n }\n}\n\n/**\n * Wrap a candidate-producing policy in the default reviewer gate. The policy\n * decides WHAT to propose (notes, sources, proposalText, confidence); the gate\n * decides whether the proposal is APPLIED. Use this when you have a proposer but\n * want the standard confidence gate; pass a full {@link KnowledgeDecider} to\n * `deps.decide` to own the gate too.\n */\nexport function createReviewerDecider(\n propose: (\n input: KnowledgeDeciderInput,\n ) => Promise<KnowledgeCandidate> | KnowledgeCandidate,\n): KnowledgeDecider {\n return async (input) => {\n const candidate = await propose(input)\n const verdict = reviewCandidate(candidate, input.minConfidence)\n return { candidate, verdict }\n }\n}\n\n/**\n * Apply a gate verdict to a candidate, producing the agent-knowledge decision.\n * Grounding (sources) always passes through; the gated `proposalText` is dropped\n * when the verdict rejects it. The verdict is recorded in `metadata.gate` so the\n * loop's event stream carries the audit trail.\n */\nfunction toResearchDecision(decision: KnowledgeDecision): KnowledgeResearchLoopDecision {\n const { candidate, verdict } = decision\n return {\n notes: candidate.notes,\n sourcePaths: candidate.sourcePaths,\n sourceTexts: candidate.sourceTexts,\n proposalText: verdict.accepted ? candidate.proposalText : undefined,\n done: candidate.done,\n metadata: {\n ...(candidate.metadata ?? {}),\n gate: verdict,\n },\n }\n}\n\n/**\n * The do-nothing default policy: when no `decide` is supplied, the loop runs\n * with a proposer that proposes nothing and ends immediately. A real product\n * supplies a proposer (agentic judge, sandbox run, or deterministic) via\n * `deps.decide`; this keeps `createKnowledgeLoop` total for a config that only\n * declares sources/requirements without a wired researcher yet.\n */\nconst noopDecider: KnowledgeDecider = (input) => ({\n candidate: { done: true, notes: 'no decider supplied; nothing proposed' },\n verdict: {\n accepted: true,\n reason: 'no-proposal',\n confidence: 1,\n minConfidence: input.minConfidence,\n },\n})\n\n/**\n * Build a runnable knowledge-acquisition loop from the product's\n * `AgentKnowledgeConfig` and a small set of seams. Maps config → agent-knowledge\n * `runKnowledgeResearchLoop` options; never reimplements the loop.\n */\nexport function createKnowledgeLoop(\n knowledge: AgentKnowledgeConfig,\n deps: CreateKnowledgeLoopDeps,\n): KnowledgeLoop {\n const goal = knowledge.loop?.goal ?? deps.defaultGoal ?? DEFAULT_GOAL\n const minConfidence =\n knowledge.loop?.minConfidence ?? deps.defaultMinConfidence ?? DEFAULT_MIN_CONFIDENCE\n const freshness = knowledge.loop?.freshness\n\n // Multimodal seam: consumer adapters are tried first; the text adapter is the\n // always-present fallback (it claims text/.md/.txt/.json/.csv). A config\n // source whose media an extra adapter claims is ingested by that adapter.\n const adapters: SourceAdapter[] = [...(deps.adapters ?? []), textSourceAdapter]\n\n const decide = deps.decide ?? noopDecider\n\n const run = (): Promise<KnowledgeResearchLoopResult> =>\n runKnowledgeResearchLoop({\n root: deps.root,\n goal,\n maxIterations: deps.maxIterations,\n actor: deps.actor,\n signal: deps.signal,\n onStep: deps.onStep,\n sourceOptions: { adapters },\n async step(context) {\n const decision = await decide({\n context,\n goal,\n minConfidence,\n freshness,\n sources: knowledge.sources,\n driver: deps.driver,\n })\n return toResearchDecision(decision)\n },\n })\n\n return {\n run,\n goal,\n minConfidence,\n adapters,\n }\n}\n"],"mappings":";AAkDA;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAgJP,IAAM,yBAAyB;AAC/B,IAAM,eAAe;AAUd,SAAS,gBACd,WACA,eACsB;AACtB,MAAI,CAAC,UAAU,cAAc;AAC3B,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,YAAY,UAAU,cAAc;AAAA,MACpC;AAAA,IACF;AAAA,EACF;AACA,QAAM,aAAa,UAAU,cAAc;AAC3C,MAAI,cAAc,eAAe;AAC/B,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ,cAAc,WAAW,QAAQ,CAAC,CAAC,qBAAqB,cAAc,QAAQ,CAAC,CAAC;AAAA,MACxF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,QAAQ,cAAc,WAAW,QAAQ,CAAC,CAAC,oBAAoB,cAAc,QAAQ,CAAC,CAAC;AAAA,IACvF;AAAA,IACA;AAAA,EACF;AACF;AASO,SAAS,sBACd,SAGkB;AAClB,SAAO,OAAO,UAAU;AACtB,UAAM,YAAY,MAAM,QAAQ,KAAK;AACrC,UAAM,UAAU,gBAAgB,WAAW,MAAM,aAAa;AAC9D,WAAO,EAAE,WAAW,QAAQ;AAAA,EAC9B;AACF;AAQA,SAAS,mBAAmB,UAA4D;AACtF,QAAM,EAAE,WAAW,QAAQ,IAAI;AAC/B,SAAO;AAAA,IACL,OAAO,UAAU;AAAA,IACjB,aAAa,UAAU;AAAA,IACvB,aAAa,UAAU;AAAA,IACvB,cAAc,QAAQ,WAAW,UAAU,eAAe;AAAA,IAC1D,MAAM,UAAU;AAAA,IAChB,UAAU;AAAA,MACR,GAAI,UAAU,YAAY,CAAC;AAAA,MAC3B,MAAM;AAAA,IACR;AAAA,EACF;AACF;AASA,IAAM,cAAgC,CAAC,WAAW;AAAA,EAChD,WAAW,EAAE,MAAM,MAAM,OAAO,wCAAwC;AAAA,EACxE,SAAS;AAAA,IACP,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,eAAe,MAAM;AAAA,EACvB;AACF;AAOO,SAAS,oBACd,WACA,MACe;AACf,QAAM,OAAO,UAAU,MAAM,QAAQ,KAAK,eAAe;AACzD,QAAM,gBACJ,UAAU,MAAM,iBAAiB,KAAK,wBAAwB;AAChE,QAAM,YAAY,UAAU,MAAM;AAKlC,QAAM,WAA4B,CAAC,GAAI,KAAK,YAAY,CAAC,GAAI,iBAAiB;AAE9E,QAAM,SAAS,KAAK,UAAU;AAE9B,QAAM,MAAM,MACV,yBAAyB;AAAA,IACvB,MAAM,KAAK;AAAA,IACX;AAAA,IACA,eAAe,KAAK;AAAA,IACpB,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK;AAAA,IACb,QAAQ,KAAK;AAAA,IACb,eAAe,EAAE,SAAS;AAAA,IAC1B,MAAM,KAAK,SAAS;AAClB,YAAM,WAAW,MAAM,OAAO;AAAA,QAC5B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,UAAU;AAAA,QACnB,QAAQ,KAAK;AAAA,MACf,CAAC;AACD,aAAO,mBAAmB,QAAQ;AAAA,IACpC;AAAA,EACF,CAAC;AAEH,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|