@tangle-network/agent-runtime 0.50.0 → 0.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/agent.js +1 -1
  2. package/dist/{chunk-RHW75JW5.js → chunk-47SWANFA.js} +2 -2
  3. package/dist/{chunk-ML4IXGTV.js → chunk-FKHNHUXP.js} +2 -2
  4. package/dist/{chunk-CM2IK7VS.js → chunk-FQH33M5N.js} +13 -4
  5. package/dist/chunk-FQH33M5N.js.map +1 -0
  6. package/dist/chunk-G3RGMA7C.js +361 -0
  7. package/dist/chunk-G3RGMA7C.js.map +1 -0
  8. package/dist/{chunk-NDM5VXZW.js → chunk-HAA4KZUD.js} +7 -5
  9. package/dist/{chunk-NDM5VXZW.js.map → chunk-HAA4KZUD.js.map} +1 -1
  10. package/dist/{chunk-OM3YNZIW.js → chunk-HYG4ISNS.js} +5 -360
  11. package/dist/chunk-HYG4ISNS.js.map +1 -0
  12. package/dist/{chunk-BKAIVNFA.js → chunk-XEI7AIHU.js} +3 -3
  13. package/dist/improvement.d.ts +96 -8
  14. package/dist/improvement.js +191 -9
  15. package/dist/improvement.js.map +1 -1
  16. package/dist/index.js +8 -7
  17. package/dist/index.js.map +1 -1
  18. package/dist/intelligence.d.ts +423 -0
  19. package/dist/intelligence.js +427 -0
  20. package/dist/intelligence.js.map +1 -0
  21. package/dist/loop-runner-bin.js +4 -3
  22. package/dist/loops.js +1 -1
  23. package/dist/mcp/bin.js +5 -4
  24. package/dist/mcp/bin.js.map +1 -1
  25. package/dist/mcp/index.js +6 -5
  26. package/dist/mcp/index.js.map +1 -1
  27. package/dist/platform.d.ts +120 -62
  28. package/dist/platform.js +68 -26
  29. package/dist/platform.js.map +1 -1
  30. package/dist/runtime.js +1 -1
  31. package/dist/workflow.js +1 -1
  32. package/package.json +6 -1
  33. package/dist/chunk-CM2IK7VS.js.map +0 -1
  34. package/dist/chunk-OM3YNZIW.js.map +0 -1
  35. /package/dist/{chunk-RHW75JW5.js.map → chunk-47SWANFA.js.map} +0 -0
  36. /package/dist/{chunk-ML4IXGTV.js.map → chunk-FKHNHUXP.js.map} +0 -0
  37. /package/dist/{chunk-BKAIVNFA.js.map → chunk-XEI7AIHU.js.map} +0 -0
@@ -0,0 +1,427 @@
1
+ import {
2
+ createOtelExporter,
3
+ loopEventToOtelSpan
4
+ } from "./chunk-G3RGMA7C.js";
5
+ import "./chunk-DGUM43GV.js";
6
+
7
+ // src/intelligence/effort.ts
8
+ var presets = {
9
+ off: {
10
+ analysts: false,
11
+ corpus: "off",
12
+ fanout: 1,
13
+ loops: false,
14
+ intelligenceBudgetUsd: 0
15
+ },
16
+ eco: {
17
+ analysts: true,
18
+ corpus: "read",
19
+ fanout: 1,
20
+ loops: false,
21
+ intelligenceBudgetUsd: 0.25
22
+ },
23
+ standard: {
24
+ analysts: true,
25
+ corpus: "read-write",
26
+ fanout: 3,
27
+ loops: true,
28
+ intelligenceBudgetUsd: 2
29
+ },
30
+ thorough: {
31
+ analysts: true,
32
+ corpus: "read-write",
33
+ fanout: 5,
34
+ loops: true,
35
+ intelligenceBudgetUsd: 10
36
+ },
37
+ max: {
38
+ analysts: true,
39
+ corpus: "read-write",
40
+ fanout: 8,
41
+ loops: true,
42
+ intelligenceBudgetUsd: null
43
+ }
44
+ };
45
+ var defaultEffortTier = "standard";
46
+ function resolveEffort(tier, overrides) {
47
+ const preset = presets[tier];
48
+ if (!preset) {
49
+ throw new Error(
50
+ `resolveEffort: unknown effort tier ${JSON.stringify(tier)} (expected one of ${Object.keys(presets).map((t) => `'${t}'`).join(", ")})`
51
+ );
52
+ }
53
+ return { ...preset, ...overrides ?? {} };
54
+ }
55
+ function isIntelligenceOff(settings) {
56
+ return settings.analysts === false && settings.corpus === "off" && settings.fanout <= 1 && settings.loops === false && settings.intelligenceBudgetUsd === 0;
57
+ }
58
+
59
+ // src/intelligence/redact.ts
60
+ var redactedMarker = "[redacted]";
61
+ var secretKeyPattern = /(api[-_]?key|secret|token|password|passwd|authorization|auth|private[-_]?key|credential|access[-_]?key|client[-_]?secret|session[-_]?(id|token)|cookie|bearer)/i;
62
+ var valuePatterns = [
63
+ // Bearer tokens.
64
+ /\bBearer\s+[A-Za-z0-9._\-+/=]{8,}/gi,
65
+ // Provider-style API keys (sk-..., sk-tan-..., pk_live_..., ghp_...).
66
+ /\b(?:sk|pk|rk|ak)[-_][A-Za-z0-9_-]{12,}/g,
67
+ /\bgh[pousr]_[A-Za-z0-9]{20,}/g,
68
+ // AWS access key ids.
69
+ /\bAKIA[0-9A-Z]{16}\b/g,
70
+ // PEM private-key blocks.
71
+ /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g,
72
+ // Email addresses.
73
+ /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g
74
+ ];
75
+ function scrubString(input) {
76
+ let out = input;
77
+ for (const pattern of valuePatterns) {
78
+ out = out.replace(pattern, redactedMarker);
79
+ }
80
+ return out;
81
+ }
82
+ function defaultRedactor(value) {
83
+ return walk(value, /* @__PURE__ */ new WeakSet(), 0);
84
+ }
85
+ var maxDepth = 32;
86
+ function walk(value, seen, depth) {
87
+ if (depth > maxDepth) return "[truncated]";
88
+ if (typeof value === "string") return scrubString(value);
89
+ if (value === null || typeof value !== "object") return value;
90
+ if (seen.has(value)) return "[circular]";
91
+ seen.add(value);
92
+ if (Array.isArray(value)) {
93
+ return value.map((item) => walk(item, seen, depth + 1));
94
+ }
95
+ const out = {};
96
+ for (const [key, v] of Object.entries(value)) {
97
+ if (secretKeyPattern.test(key)) {
98
+ out[key] = redactedMarker;
99
+ continue;
100
+ }
101
+ out[key] = walk(v, seen, depth + 1);
102
+ }
103
+ return out;
104
+ }
105
+ function resolveRedactor(redact) {
106
+ if (redact === false) return (value) => value;
107
+ return redact ?? defaultRedactor;
108
+ }
109
+
110
+ // src/intelligence/delivery.ts
111
+ var defaultPlaneBaseUrl = "https://intelligence.tangle.tools";
112
+ var defaultRefreshMs = 3e5;
113
+ function resolvePlaneBaseUrl(baseUrl) {
114
+ if (baseUrl) return baseUrl.replace(/\/+$/, "");
115
+ if (typeof process !== "undefined" && process.env.TANGLE_INTELLIGENCE_URL) {
116
+ return process.env.TANGLE_INTELLIGENCE_URL.replace(/\/+$/, "");
117
+ }
118
+ return defaultPlaneBaseUrl;
119
+ }
120
+ function resolveApiKey(apiKey) {
121
+ if (apiKey) return apiKey;
122
+ if (typeof process !== "undefined" && process.env.TANGLE_API_KEY)
123
+ return process.env.TANGLE_API_KEY;
124
+ return "";
125
+ }
126
+ async function pullCertified(opts) {
127
+ const doFetch = opts.fetchImpl ?? globalThis.fetch;
128
+ if (!doFetch) return { succeeded: false, error: "no fetch implementation available" };
129
+ const apiKey = resolveApiKey(opts.apiKey);
130
+ if (!apiKey) return { succeeded: false, error: "no apiKey (set TANGLE_API_KEY or opts.apiKey)" };
131
+ const baseUrl = resolvePlaneBaseUrl(opts.baseUrl);
132
+ const url = `${baseUrl}/v1/profiles/${encodeURIComponent(opts.target)}/composed`;
133
+ let res;
134
+ try {
135
+ res = await doFetch(url, { headers: { authorization: `Bearer ${apiKey}` } });
136
+ } catch (err) {
137
+ return {
138
+ succeeded: false,
139
+ error: `pull request failed: ${err instanceof Error ? err.message : String(err)}`
140
+ };
141
+ }
142
+ if (res.status === 404) {
143
+ return {
144
+ succeeded: false,
145
+ error: "no certified artifacts promoted for target yet",
146
+ status: 404
147
+ };
148
+ }
149
+ if (!res.ok) {
150
+ const body = await res.text().catch(() => "");
151
+ return {
152
+ succeeded: false,
153
+ error: `pull ${res.status}: ${body.slice(0, 200)}`,
154
+ status: res.status
155
+ };
156
+ }
157
+ try {
158
+ return { succeeded: true, value: await res.json() };
159
+ } catch (err) {
160
+ return {
161
+ succeeded: false,
162
+ error: `pull response parse failed: ${err instanceof Error ? err.message : String(err)}`
163
+ };
164
+ }
165
+ }
166
+ function composeCertifiedPrompt(base, certified) {
167
+ if (!certified) return base;
168
+ const parts = [];
169
+ if (certified.promptSurface?.surface.trim()) parts.push(certified.promptSurface.surface.trim());
170
+ for (const type of Object.keys(certified.artifacts).sort()) {
171
+ if (type !== "prompt-surface" && type !== "skill") continue;
172
+ const bucket = certified.artifacts[type] ?? [];
173
+ for (const a of [...bucket].sort((x, y) => (x.path ?? "").localeCompare(y.path ?? ""))) {
174
+ if (a.content.trim()) parts.push(a.content.trim());
175
+ }
176
+ }
177
+ if (parts.length === 0) return base;
178
+ return `${base.trim()}
179
+
180
+ ## Certified guidance (Tangle Intelligence)
181
+
182
+ ${parts.join("\n\n")}`;
183
+ }
184
+ function withCertifiedDelivery(agent, config) {
185
+ const client = createIntelligenceClient(config);
186
+ const target = config.target ?? config.project;
187
+ const refreshMs = config.refreshMs ?? defaultRefreshMs;
188
+ let certified = null;
189
+ let lastPullAt = 0;
190
+ let inflight = null;
191
+ async function refresh() {
192
+ if (Date.now() - lastPullAt < refreshMs) return;
193
+ if (inflight) return inflight;
194
+ inflight = (async () => {
195
+ const outcome = await pullCertified({
196
+ target,
197
+ apiKey: config.apiKey,
198
+ baseUrl: config.baseUrl,
199
+ fetchImpl: config.fetchImpl
200
+ });
201
+ lastPullAt = Date.now();
202
+ if (outcome.succeeded) certified = outcome.value;
203
+ })();
204
+ try {
205
+ await inflight;
206
+ } finally {
207
+ inflight = null;
208
+ }
209
+ }
210
+ const wrapped = (async (input) => {
211
+ await refresh();
212
+ const applied = {
213
+ certified,
214
+ composePrompt: (base) => composeCertifiedPrompt(base, certified)
215
+ };
216
+ return client.traceRun(
217
+ { input, labels: { "tangle.certified_version": certified?.promptSurface?.version ?? -1 } },
218
+ async (trace) => {
219
+ const out = await agent(input, applied);
220
+ trace.recordOutput(out);
221
+ return out;
222
+ }
223
+ );
224
+ });
225
+ wrapped.refresh = refresh;
226
+ return wrapped;
227
+ }
228
+
229
+ // src/intelligence/index.ts
230
+ function resolveEffortConfig(effort) {
231
+ if (effort === void 0) return resolveEffort(defaultEffortTier);
232
+ if (typeof effort === "string") return resolveEffort(effort);
233
+ return resolveEffort(effort.tier, effort.overrides);
234
+ }
235
+ function resolveEndpoint(endpoint) {
236
+ if (endpoint) return endpoint;
237
+ if (typeof process === "undefined") return void 0;
238
+ return process.env.INTELLIGENCE_OTLP_ENDPOINT ?? process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
239
+ }
240
+ function freshTraceId() {
241
+ return randomHex(32);
242
+ }
243
+ function freshRunId() {
244
+ return `run-${randomHex(16)}`;
245
+ }
246
+ var previewMaxChars = 4096;
247
+ function previewJson(value) {
248
+ let s;
249
+ if (typeof value === "string") s = value;
250
+ else {
251
+ try {
252
+ s = JSON.stringify(value) ?? String(value);
253
+ } catch {
254
+ s = String(value);
255
+ }
256
+ }
257
+ return s.length > previewMaxChars ? `${s.slice(0, previewMaxChars)}\u2026[truncated]` : s;
258
+ }
259
+ function randomHex(chars) {
260
+ const bytes = new Uint8Array(Math.ceil(chars / 2));
261
+ if (typeof globalThis.crypto?.getRandomValues === "function") {
262
+ globalThis.crypto.getRandomValues(bytes);
263
+ } else {
264
+ for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);
265
+ }
266
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, chars);
267
+ }
268
+ function createIntelligenceClient(config) {
269
+ if (!config.project) {
270
+ throw new Error("createIntelligenceClient: `project` is required");
271
+ }
272
+ const effort = resolveEffortConfig(config.effort);
273
+ const intelligenceOff = isIntelligenceOff(effort);
274
+ const redactor = resolveRedactor(config.redact);
275
+ const apiKey = config.apiKey ?? (typeof process !== "undefined" ? process.env.TANGLE_API_KEY : void 0);
276
+ const endpoint = resolveEndpoint(config.endpoint);
277
+ let exporter;
278
+ let exporterResolved = false;
279
+ function getExporter() {
280
+ if (exporterResolved) return exporter;
281
+ exporterResolved = true;
282
+ if (!endpoint) return void 0;
283
+ exporter = createOtelExporter({
284
+ endpoint,
285
+ headers: apiKey ? { authorization: `Bearer ${apiKey}` } : {},
286
+ serviceName: config.project,
287
+ resourceAttributes: { "tangle.project": config.project }
288
+ });
289
+ return exporter;
290
+ }
291
+ function exportTrace(meta, outcome, output) {
292
+ const ex = getExporter();
293
+ if (!ex) return;
294
+ const labels = {
295
+ project: config.project,
296
+ "tangle.effort.intelligence_off": outcome.intelligenceOff,
297
+ "tangle.usage.inference_usd": outcome.usage.inferenceUsd,
298
+ "tangle.usage.intelligence_usd": outcome.usage.intelligenceUsd,
299
+ ...meta.model ? { "gen_ai.request.model": meta.model } : {},
300
+ ...meta.provider ? { "provider.name": meta.provider } : {},
301
+ ...typeof outcome.success === "boolean" ? { "tangle.outcome.success": outcome.success } : {},
302
+ ...typeof outcome.score === "number" ? { "tangle.outcome.score": outcome.score } : {},
303
+ ...meta.labels ?? {}
304
+ };
305
+ const redactedInput = meta.input !== void 0 ? redactor(meta.input) : void 0;
306
+ const redactedOutput = output !== void 0 ? redactor(output) : void 0;
307
+ if (redactedInput !== void 0) labels["tangle.input"] = previewJson(redactedInput);
308
+ if (redactedOutput !== void 0) labels["tangle.output"] = previewJson(redactedOutput);
309
+ try {
310
+ ex.exportSpan(
311
+ loopEventToOtelSpan(
312
+ {
313
+ kind: "tangle.intelligence.run",
314
+ runId: outcome.runId,
315
+ timestamp: Date.now(),
316
+ payload: labels
317
+ },
318
+ outcome.traceId
319
+ )
320
+ );
321
+ } catch {
322
+ }
323
+ }
324
+ return {
325
+ project: config.project,
326
+ effort,
327
+ async traceRun(meta, fn) {
328
+ const runId = meta.runId ?? freshRunId();
329
+ const traceId = meta.traceId ?? freshTraceId();
330
+ let recordedOutput;
331
+ const usage = { inferenceUsd: 0, intelligenceUsd: 0 };
332
+ let success;
333
+ let score;
334
+ const trace = {
335
+ recordOutput(output) {
336
+ recordedOutput = output;
337
+ },
338
+ recordOutcome(outcome2) {
339
+ if (typeof outcome2.success === "boolean") success = outcome2.success;
340
+ if (typeof outcome2.score === "number") score = outcome2.score;
341
+ if (outcome2.usage) {
342
+ if (typeof outcome2.usage.inferenceUsd === "number") {
343
+ usage.inferenceUsd = outcome2.usage.inferenceUsd;
344
+ }
345
+ if (typeof outcome2.usage.intelligenceUsd === "number") {
346
+ usage.intelligenceUsd = outcome2.usage.intelligenceUsd;
347
+ }
348
+ } else if (typeof outcome2.costUsd === "number") {
349
+ usage.inferenceUsd = outcome2.costUsd;
350
+ }
351
+ }
352
+ };
353
+ const result = await fn(trace);
354
+ if (intelligenceOff) usage.intelligenceUsd = 0;
355
+ const outcome = {
356
+ runId,
357
+ traceId,
358
+ project: config.project,
359
+ effort,
360
+ intelligenceOff,
361
+ ...success !== void 0 ? { success } : {},
362
+ ...score !== void 0 ? { score } : {},
363
+ usage
364
+ };
365
+ exportTrace(meta, outcome, recordedOutput);
366
+ return result;
367
+ },
368
+ doctor() {
369
+ const hasRepo = Boolean(config.repo?.owner && config.repo?.name && config.repo?.baseBranch);
370
+ const hasChecks = Boolean(config.checks && config.checks.length > 0);
371
+ const hasSurfaces = Boolean(config.surfaces && config.surfaces.length > 0);
372
+ const prMissing = [];
373
+ if (!hasChecks) prMissing.push("checks");
374
+ if (!hasSurfaces) prMissing.push("surfaces");
375
+ if (!hasRepo) prMissing.push("repo");
376
+ const recommendMissing = [];
377
+ if (intelligenceOff) recommendMissing.push("effort above off");
378
+ return {
379
+ project: config.project,
380
+ effort,
381
+ exportConfigured: Boolean(endpoint),
382
+ modes: {
383
+ observe: { ready: true, missing: [] },
384
+ recommend: {
385
+ ready: recommendMissing.length === 0,
386
+ missing: recommendMissing
387
+ },
388
+ pr: { ready: prMissing.length === 0, missing: prMissing }
389
+ }
390
+ };
391
+ },
392
+ async flush() {
393
+ const ex = getExporter();
394
+ if (!ex) return;
395
+ try {
396
+ await ex.flush();
397
+ } catch {
398
+ }
399
+ }
400
+ };
401
+ }
402
+ function isClient(value) {
403
+ return typeof value.traceRun === "function";
404
+ }
405
+ function withTangleIntelligence(agent, clientOrConfig) {
406
+ const client = isClient(clientOrConfig) ? clientOrConfig : createIntelligenceClient(clientOrConfig);
407
+ return async (input) => {
408
+ return client.traceRun({ input }, async (trace) => {
409
+ const output = await agent(input);
410
+ trace.recordOutput(output);
411
+ return output;
412
+ });
413
+ };
414
+ }
415
+ export {
416
+ composeCertifiedPrompt,
417
+ createIntelligenceClient,
418
+ defaultEffortTier,
419
+ defaultRedactor,
420
+ isIntelligenceOff,
421
+ pullCertified,
422
+ resolveEffort,
423
+ resolveRedactor,
424
+ withCertifiedDelivery,
425
+ withTangleIntelligence
426
+ };
427
+ //# sourceMappingURL=intelligence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/intelligence/effort.ts","../src/intelligence/redact.ts","../src/intelligence/delivery.ts","../src/intelligence/index.ts"],"sourcesContent":["/**\n * @experimental\n *\n * EffortPolicy — pure data, no execution. Resolves a named tier into a flat\n * settings object the Intelligence wrapper reads to decide WHICH intelligence\n * spawns are admitted. The composer never runs anything; it only describes the\n * shape of intelligence a tier permits.\n *\n * The billing boundary lives one layer above this (the wrapper tags trace usage\n * by class). What this module owns is the single law the OFF tier rests on:\n * `'off'` ⇒ every intelligence knob OFF (analysts:false, corpus:'off',\n * fanout:1, loops:false, intelligenceBudgetUsd:0). At OFF the wrapper runs the\n * agent as pure passthrough and only intelligence-class usage can prove to be\n * zero — there is nothing to spawn.\n */\n\n/** The named effort tiers, lowest to highest. `'off'` is the honest floor\n * below `'eco'`: intelligence fully off, telemetry still best-effort. */\nexport type EffortTier = 'off' | 'eco' | 'standard' | 'thorough' | 'max'\n\n/** Corpus access an intelligence tier permits. `'off'` reads and writes\n * nothing; `'read'` consults the cross-run corpus without contributing;\n * `'read-write'` both consults and accumulates. */\nexport type CorpusAccess = 'off' | 'read' | 'read-write'\n\n/**\n * The flat, resolved settings a tier compiles to. Every field is individually\n * overridable through `resolveEffort`. Pure data — read by the wrapper, never\n * self-executing.\n */\nexport interface EffortSettings {\n /** Whether trace-derived analyst diagnosis may spawn. `false` ⇒ no analyst. */\n analysts: boolean\n /** Cross-run corpus access this tier permits. */\n corpus: CorpusAccess\n /** Parallel candidate width. `1` ⇒ single-shot, no breadth. */\n fanout: number\n /** Whether multi-step improvement loops (refine / fanout-vote) may run. */\n loops: boolean\n /**\n * Ceiling, in USD, for INTELLIGENCE-class spawns only (analysts, corpus,\n * loops) — NOT base inference. `0` refuses every intelligence spawn; `null`\n * means uncapped (the spend lands on the Pareto receipt). Base-stream\n * inference is billed on its own channel and is never constrained here.\n */\n intelligenceBudgetUsd: number | null\n}\n\n/** Per-field overrides applied on top of a tier preset. Any subset of the\n * resolved settings; each provided field wins over the preset. */\nexport type EffortOverrides = Partial<EffortSettings>\n\nconst presets: Readonly<Record<EffortTier, Readonly<EffortSettings>>> = {\n off: {\n analysts: false,\n corpus: 'off',\n fanout: 1,\n loops: false,\n intelligenceBudgetUsd: 0,\n },\n eco: {\n analysts: true,\n corpus: 'read',\n fanout: 1,\n loops: false,\n intelligenceBudgetUsd: 0.25,\n },\n standard: {\n analysts: true,\n corpus: 'read-write',\n fanout: 3,\n loops: true,\n intelligenceBudgetUsd: 2,\n },\n thorough: {\n analysts: true,\n corpus: 'read-write',\n fanout: 5,\n loops: true,\n intelligenceBudgetUsd: 10,\n },\n max: {\n analysts: true,\n corpus: 'read-write',\n fanout: 8,\n loops: true,\n intelligenceBudgetUsd: null,\n },\n}\n\n/** The default tier when a client declares no effort. `'standard'` turns\n * intelligence on with sensible knobs; opt down to `'off'`/`'eco'` or up to\n * `'thorough'`/`'max'`. */\nexport const defaultEffortTier: EffortTier = 'standard'\n\n/**\n * Compile a named tier (plus optional per-field overrides) into the flat\n * `EffortSettings` the wrapper reads. Pure: same inputs → same object, no I/O,\n * no execution. Fails loud on an unknown tier rather than silently defaulting —\n * a typo'd tier must not quietly grant or deny intelligence.\n *\n * Invariant preserved for the billing floor: `resolveEffort('off')` always\n * yields `intelligenceBudgetUsd: 0` with every intelligence knob off UNLESS the\n * caller explicitly overrides a field — overriding off is an opt-in the caller\n * owns, not a default the composer leaks.\n */\nexport function resolveEffort(tier: EffortTier, overrides?: EffortOverrides): EffortSettings {\n const preset = presets[tier]\n if (!preset) {\n throw new Error(\n `resolveEffort: unknown effort tier ${JSON.stringify(tier)} (expected one of ${(\n Object.keys(presets) as EffortTier[]\n )\n .map((t) => `'${t}'`)\n .join(', ')})`,\n )\n }\n return { ...preset, ...(overrides ?? {}) }\n}\n\n/**\n * True when these settings admit NO intelligence spawn — the passthrough\n * predicate the wrapper branches on. Every intelligence axis must be off:\n * analysts disabled, corpus off, no breadth, no loops, and a zero intelligence\n * budget. A caller who overrides any one of these back on is no longer at the\n * OFF floor and the wrapper treats them as an intelligence-enabled run.\n */\nexport function isIntelligenceOff(settings: EffortSettings): boolean {\n return (\n settings.analysts === false &&\n settings.corpus === 'off' &&\n settings.fanout <= 1 &&\n settings.loops === false &&\n settings.intelligenceBudgetUsd === 0\n )\n}\n","/**\n * @experimental\n *\n * Redaction for Intelligence trace export. The trace carries the customer's\n * real input/output; before any of it leaves the process it passes through a\n * `Redactor`. The default scrubs the obvious leak classes (API keys, bearer\n * tokens, emails, private keys) from strings and walks nested objects/arrays,\n * but a customer with domain-specific PII supplies their own `redact` hook.\n *\n * This is intentionally narrower than `src/sanitize.ts` (which redacts the\n * runtime's *event envelope* field-by-field): here the value is opaque\n * customer payload, so the scrub is value-shaped, not schema-shaped.\n */\n\n/** A redactor maps an arbitrary trace value to a safe-to-export value. Pure;\n * must not throw on cyclic input (the default tolerates cycles). */\nexport type Redactor = (value: unknown) => unknown\n\nconst redactedMarker = '[redacted]'\n\n/** Secret-bearing key names: when an object key matches, its value is fully\n * replaced regardless of the value's own content. Lowercased compare. */\nconst secretKeyPattern =\n /(api[-_]?key|secret|token|password|passwd|authorization|auth|private[-_]?key|credential|access[-_]?key|client[-_]?secret|session[-_]?(id|token)|cookie|bearer)/i\n\n/** In-value secret/PII patterns scrubbed from any string, regardless of key. */\nconst valuePatterns: ReadonlyArray<RegExp> = [\n // Bearer tokens.\n /\\bBearer\\s+[A-Za-z0-9._\\-+/=]{8,}/gi,\n // Provider-style API keys (sk-..., sk-tan-..., pk_live_..., ghp_...).\n /\\b(?:sk|pk|rk|ak)[-_][A-Za-z0-9_-]{12,}/g,\n /\\bgh[pousr]_[A-Za-z0-9]{20,}/g,\n // AWS access key ids.\n /\\bAKIA[0-9A-Z]{16}\\b/g,\n // PEM private-key blocks.\n /-----BEGIN [A-Z ]*PRIVATE KEY-----[\\s\\S]*?-----END [A-Z ]*PRIVATE KEY-----/g,\n // Email addresses.\n /\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}\\b/g,\n]\n\n/** Scrub a single string of in-value secret/PII patterns. */\nfunction scrubString(input: string): string {\n let out = input\n for (const pattern of valuePatterns) {\n out = out.replace(pattern, redactedMarker)\n }\n return out\n}\n\n/**\n * The built-in redactor. Walks objects and arrays; replaces values under\n * secret-bearing keys wholesale; scrubs in-value patterns from every string.\n * Cycle-safe (a seen-set short-circuits self-referential payloads to\n * `'[circular]'`), depth-bounded, and total — never throws on customer input.\n */\nexport function defaultRedactor(value: unknown): unknown {\n return walk(value, new WeakSet(), 0)\n}\n\nconst maxDepth = 32\n\nfunction walk(value: unknown, seen: WeakSet<object>, depth: number): unknown {\n if (depth > maxDepth) return '[truncated]'\n if (typeof value === 'string') return scrubString(value)\n if (value === null || typeof value !== 'object') return value\n if (seen.has(value)) return '[circular]'\n seen.add(value)\n\n if (Array.isArray(value)) {\n return value.map((item) => walk(item, seen, depth + 1))\n }\n\n const out: Record<string, unknown> = {}\n for (const [key, v] of Object.entries(value as Record<string, unknown>)) {\n if (secretKeyPattern.test(key)) {\n out[key] = redactedMarker\n continue\n }\n out[key] = walk(v, seen, depth + 1)\n }\n return out\n}\n\n/**\n * Resolve the redactor a client uses. A caller-supplied hook replaces the\n * default entirely (the customer owns their PII rules); absent one, the\n * built-in `defaultRedactor` runs. Returning `false` is the explicit opt-out —\n * NO redaction, for a caller who has already sanitized upstream and wants raw\n * fidelity. Opt-out is loud (an explicit `false`), never a silent default.\n */\nexport function resolveRedactor(redact: Redactor | false | undefined): Redactor {\n if (redact === false) return (value) => value\n return redact ?? defaultRedactor\n}\n","/**\n * @experimental\n *\n * Tangle Intelligence — the DELIVERY half of the loop (pull-by-default).\n *\n * The sibling Observe layer (`./index`) sends traces UP to the plane. This\n * module pulls certified artifacts DOWN: it reads the tenant's promoted,\n * gate-certified profile from the deployed Intelligence plane and folds it into\n * the running agent's prompt — so an approved improvement actually reaches the\n * agent. This is \"shipping intelligence to people's agents\", pull-by-default;\n * the push/Gated-PR opt-in composes on top of this.\n *\n * Pull contract (deployed plane): GET /v1/profiles/:target/composed →\n * { target, generatedAt, promptSurface: {surface,surfaceHash,version,lift}|null,\n * artifacts: { <artifactType>: [{path,content,contentHash,version,lift,promotedAt}] } }\n * Auth: Bearer <apiKey> (the one TANGLE_API_KEY shared by router + sandbox +\n * intelligence), resolved to a tenant by platform-api's key-verify S2S contract.\n *\n * import { withCertifiedDelivery } from '@tangle-network/agent-runtime/intelligence'\n *\n * export const agent = withCertifiedDelivery(\n * async (input, applied) => myAgent(input, { systemPrompt: applied.composePrompt(BASE) }),\n * { project: 'support-agent', target: 'support-agent' },\n * )\n */\n\nimport { createIntelligenceClient, type IntelligenceConfig } from './index'\n\nconst defaultPlaneBaseUrl = 'https://intelligence.tangle.tools'\nconst defaultRefreshMs = 300_000\n\n/** A promoted, certified artifact (one entry in the composed profile). */\nexport interface CertifiedArtifact {\n path: string | null\n content: string\n contentHash: string\n version: number | null\n /** Held-out gate lift attached at certification, e.g. \"+3.1pp\" — never a\n * within-run claim. `null` when the promotion carried no lift record. */\n lift: string | null\n promotedAt: string\n}\n\n/** The active promoted prompt surface for a target. */\nexport interface CertifiedPromptSurface {\n surface: string\n surfaceHash: string\n version: number | null\n lift: string | null\n}\n\n/** The composed certified profile — exactly the shape the plane's\n * `GET /v1/profiles/:target/composed` returns. */\nexport interface CertifiedProfile {\n target: string\n generatedAt: string\n promptSurface: CertifiedPromptSurface | null\n artifacts: Record<string, CertifiedArtifact[]>\n}\n\n/** Typed outcome for the pull — inspect `succeeded` before `value`. A 404\n * (nothing promoted yet) is a normal, non-error `succeeded: false`. */\nexport type PullOutcome =\n | { succeeded: true; value: CertifiedProfile }\n | { succeeded: false; error: string; status?: number }\n\nexport interface PullCertifiedOptions {\n /** The agent target certified artifacts are promoted under. */\n target: string\n /** Bearer key. Defaults to `process.env.TANGLE_API_KEY`. */\n apiKey?: string\n /** Plane base URL. Defaults to `process.env.TANGLE_INTELLIGENCE_URL` then\n * `https://intelligence.tangle.tools`. */\n baseUrl?: string\n /** fetch impl (tests / non-global-fetch runtimes). Defaults to global fetch. */\n fetchImpl?: typeof fetch\n}\n\nfunction resolvePlaneBaseUrl(baseUrl: string | undefined): string {\n if (baseUrl) return baseUrl.replace(/\\/+$/, '')\n if (typeof process !== 'undefined' && process.env.TANGLE_INTELLIGENCE_URL) {\n return process.env.TANGLE_INTELLIGENCE_URL.replace(/\\/+$/, '')\n }\n return defaultPlaneBaseUrl\n}\n\nfunction resolveApiKey(apiKey: string | undefined): string {\n if (apiKey) return apiKey\n if (typeof process !== 'undefined' && process.env.TANGLE_API_KEY)\n return process.env.TANGLE_API_KEY\n return ''\n}\n\n/**\n * Pull the certified composed profile for a target. Fail-closed: a network\n * error or a non-2xx returns a typed `succeeded: false` (never throws), so a\n * caller can run on its base surface when Intelligence is unreachable. A 404 is\n * the normal \"nothing promoted yet\" signal, carried as `status: 404`.\n */\nexport async function pullCertified(opts: PullCertifiedOptions): Promise<PullOutcome> {\n const doFetch = opts.fetchImpl ?? (globalThis.fetch as typeof fetch | undefined)\n if (!doFetch) return { succeeded: false, error: 'no fetch implementation available' }\n const apiKey = resolveApiKey(opts.apiKey)\n if (!apiKey) return { succeeded: false, error: 'no apiKey (set TANGLE_API_KEY or opts.apiKey)' }\n const baseUrl = resolvePlaneBaseUrl(opts.baseUrl)\n const url = `${baseUrl}/v1/profiles/${encodeURIComponent(opts.target)}/composed`\n let res: Response\n try {\n res = await doFetch(url, { headers: { authorization: `Bearer ${apiKey}` } })\n } catch (err) {\n return {\n succeeded: false,\n error: `pull request failed: ${err instanceof Error ? err.message : String(err)}`,\n }\n }\n if (res.status === 404) {\n return {\n succeeded: false,\n error: 'no certified artifacts promoted for target yet',\n status: 404,\n }\n }\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n return {\n succeeded: false,\n error: `pull ${res.status}: ${body.slice(0, 200)}`,\n status: res.status,\n }\n }\n try {\n return { succeeded: true, value: (await res.json()) as CertifiedProfile }\n } catch (err) {\n return {\n succeeded: false,\n error: `pull response parse failed: ${err instanceof Error ? err.message : String(err)}`,\n }\n }\n}\n\n/**\n * Fold the certified prompt surface (and any certified `prompt-surface` /\n * `skill` artifacts) into a base system prompt under a marked section, so the\n * deployed agent prompt == base + the gate-certified additions. Order is stable\n * (prompt surface first, then artifacts by type then path) so the same profile\n * renders byte-identically each call. Returns `base` unchanged when there is no\n * usable certified content.\n */\nexport function composeCertifiedPrompt(base: string, certified: CertifiedProfile | null): string {\n if (!certified) return base\n const parts: string[] = []\n if (certified.promptSurface?.surface.trim()) parts.push(certified.promptSurface.surface.trim())\n for (const type of Object.keys(certified.artifacts).sort()) {\n if (type !== 'prompt-surface' && type !== 'skill') continue\n const bucket = certified.artifacts[type] ?? []\n for (const a of [...bucket].sort((x, y) => (x.path ?? '').localeCompare(y.path ?? ''))) {\n if (a.content.trim()) parts.push(a.content.trim())\n }\n }\n if (parts.length === 0) return base\n return `${base.trim()}\\n\\n## Certified guidance (Tangle Intelligence)\\n\\n${parts.join('\\n\\n')}`\n}\n\n/** What the delivery wrapper hands the agent each run. */\nexport interface AppliedIntelligence {\n /** The certified profile in effect (null when none promoted / pull failed —\n * fail-closed: the agent runs on its base surface). */\n certified: CertifiedProfile | null\n /** Fold the certified prompt surface into a base system prompt. */\n composePrompt(base: string): string\n}\n\n/** An agent wrapped by {@link withCertifiedDelivery}: receives the input plus\n * the certified intelligence delivered for this run. */\nexport type DeliveredAgent<I, O> = (input: I, applied: AppliedIntelligence) => Promise<O>\n\n/** Delivery config = the Observe config plus the pull target + refresh cadence. */\nexport interface DeliveryConfig extends IntelligenceConfig {\n /** Pull target. Defaults to `project`. */\n target?: string\n /** Plane base URL for the pull (NOT the OTLP `endpoint`). Defaults to\n * `TANGLE_INTELLIGENCE_URL` then `https://intelligence.tangle.tools`. */\n baseUrl?: string\n /** Min interval between certified-profile pulls. Default 5m. */\n refreshMs?: number\n /** fetch impl for the pull (tests). Defaults to global fetch. */\n fetchImpl?: typeof fetch\n}\n\n/**\n * Wrap an agent so it (a) Observes each run via the shipped Observe client and\n * (b) RECEIVES the tenant's certified artifacts pulled from the deployed plane.\n * The certified profile is cached and refreshed at most every `refreshMs`; a\n * failed pull is fail-closed — the agent runs on its base surface and never\n * breaks because Intelligence is unreachable. When the plane promotes a new\n * gate-certified surface, the next refresh delivers it to the running agent.\n */\nexport function withCertifiedDelivery<I, O>(\n agent: DeliveredAgent<I, O>,\n config: DeliveryConfig,\n): ((input: I) => Promise<O>) & { refresh(): Promise<void> } {\n const client = createIntelligenceClient(config)\n const target = config.target ?? config.project\n const refreshMs = config.refreshMs ?? defaultRefreshMs\n let certified: CertifiedProfile | null = null\n let lastPullAt = 0\n let inflight: Promise<void> | null = null\n\n async function refresh(): Promise<void> {\n if (Date.now() - lastPullAt < refreshMs) return\n if (inflight) return inflight\n inflight = (async () => {\n const outcome = await pullCertified({\n target,\n apiKey: config.apiKey,\n baseUrl: config.baseUrl,\n fetchImpl: config.fetchImpl,\n })\n lastPullAt = Date.now()\n // Only replace the cache on a real pull; a 404/error keeps the last-known\n // certified profile (or null) — fail-closed, never wipe a good surface.\n if (outcome.succeeded) certified = outcome.value\n })()\n try {\n await inflight\n } finally {\n inflight = null\n }\n }\n\n const wrapped = (async (input: I): Promise<O> => {\n await refresh()\n const applied: AppliedIntelligence = {\n certified,\n composePrompt: (base: string) => composeCertifiedPrompt(base, certified),\n }\n return client.traceRun(\n { input, labels: { 'tangle.certified_version': certified?.promptSurface?.version ?? -1 } },\n async (trace) => {\n const out = await agent(input, applied)\n trace.recordOutput(out)\n return out\n },\n )\n }) as ((input: I) => Promise<O>) & { refresh(): Promise<void> }\n wrapped.refresh = refresh\n return wrapped\n}\n","/**\n * @experimental\n *\n * Tangle Intelligence SDK — the Observe + Mode-0 product layer.\n *\n * A thin, best-effort wrapper over the shipped trace-export substrate\n * (`createOtelExporter` in `../otel-export`). It does exactly two things in\n * this slice:\n *\n * 1. OBSERVE — wrap a generic agent and export one trace span per call to\n * Tangle Intelligence, swallowing every export failure so a live agent\n * never fails because Intelligence is down.\n * 2. MODE 0 / OFF — at `effort: 'off'`, run the agent as PURE PASSTHROUGH\n * (zero intelligence spawns) with best-effort telemetry still on. The\n * exported trace tags usage by class `{ inferenceUsd, intelligenceUsd }`,\n * and at OFF `intelligenceUsd` is provably `0` — the mechanism that proves\n * an OFF customer paid inference-only.\n *\n * Behavior-changing intelligence (analyst steer, candidate promotion, loops)\n * is a LATER phase and is NOT built here. This wrapper only Observes and passes\n * through; there is no abort path, so the only fail-soft surface is the\n * telemetry export.\n */\n\nimport { createOtelExporter, loopEventToOtelSpan, type OtelExporter } from '../otel-export'\nimport {\n defaultEffortTier,\n type EffortOverrides,\n type EffortSettings,\n type EffortTier,\n isIntelligenceOff,\n resolveEffort,\n} from './effort'\nimport { type Redactor, resolveRedactor } from './redact'\n\nexport type {\n AppliedIntelligence,\n CertifiedArtifact,\n CertifiedProfile,\n CertifiedPromptSurface,\n DeliveredAgent,\n DeliveryConfig,\n PullCertifiedOptions,\n PullOutcome,\n} from './delivery'\nexport { composeCertifiedPrompt, pullCertified, withCertifiedDelivery } from './delivery'\nexport type {\n CorpusAccess,\n EffortOverrides,\n EffortSettings,\n EffortTier,\n} from './effort'\nexport {\n defaultEffortTier,\n isIntelligenceOff,\n resolveEffort,\n} from './effort'\nexport type { Redactor } from './redact'\nexport { defaultRedactor, resolveRedactor } from './redact'\n\n/** Usage class for billing. Base-stream tokens bill `'inference'`; every\n * intelligence spawn (analyst, corpus, loop) bills `'intelligence'`. The\n * billing line falls on the spawn line. */\nexport type UsageClass = 'inference' | 'intelligence'\n\n/**\n * The per-class cost split carried by every trace and outcome. `off` ⇒\n * `intelligenceUsd: 0` by construction — there is no intelligence spawn to\n * bill. This is a classification on the trace, NOT a budget-pool split.\n */\nexport interface UsageSplit {\n /** Base-stream (model) spend in USD. */\n inferenceUsd: number\n /** Intelligence-spawn spend in USD. Provably `0` at the OFF tier. */\n intelligenceUsd: number\n}\n\n/** Repo coordinates a product may declare for the (later) Gated-PR mode. The\n * Observe slice only records their PRESENCE for `doctor()`; it never touches\n * the repo. */\nexport interface RepoConfig {\n owner: string\n name: string\n baseBranch: string\n}\n\n/** Client configuration. `project` + `apiKey` are the Observe minimum; the\n * rest tune effort, endpoint, redaction, and (for `doctor()` readiness)\n * declare the surfaces/checks/repo a later PR mode would need. */\nexport interface IntelligenceConfig {\n /** Stable project id — the tenant dimension every trace is tagged with. */\n project: string\n /** Bearer key for the Intelligence ingest. Reads `TANGLE_API_KEY` when omitted. */\n apiKey?: string\n /** Effort tier (default `'standard'`) plus optional per-field overrides. */\n effort?: EffortTier | { tier: EffortTier; overrides?: EffortOverrides }\n /**\n * OTLP ingest base. The underlying exporter appends `/v1/traces`, so point\n * this at the OTLP route (e.g. `https://intelligence.tangle.tools/v1/otlp`).\n * Reads `INTELLIGENCE_OTLP_ENDPOINT` then `OTEL_EXPORTER_OTLP_ENDPOINT` when\n * omitted; absent all three, export is a no-op (best-effort by construction).\n */\n endpoint?: string\n /**\n * Redaction hook run over every exported input/output. A function replaces\n * the default scrubber; `false` opts out entirely (raw fidelity, caller has\n * sanitized upstream); omitted ⇒ the built-in `defaultRedactor`.\n */\n redact?: Redactor | false\n /** Mutable surfaces a later PR mode would edit. Recorded for `doctor()` only. */\n surfaces?: string[]\n /** Verification checks a later PR mode would gate on. Recorded for `doctor()` only. */\n checks?: string[]\n /** Repo access a later PR mode would need. Recorded for `doctor()` only. */\n repo?: RepoConfig\n}\n\n/** Metadata describing one traced run. `runId`/`traceId` default to fresh ids. */\nexport interface TraceMeta {\n /** The run's input — exported through the redactor. */\n input?: unknown\n /** Stable run id. Defaults to a fresh id. */\n runId?: string\n /** 32-hex trace id. Defaults to a fresh id. */\n traceId?: string\n /** Model id, when known — stamped on the span. */\n model?: string\n /** Provider name, when known — stamped on the span. */\n provider?: string\n /** Arbitrary extra labels (string/number/boolean) stamped on the span. */\n labels?: Record<string, string | number | boolean>\n}\n\n/**\n * The trace handle a `traceRun` body records into. `recordOutput` captures the\n * agent's result (redacted on export); `recordOutcome` captures the scored\n * outcome + the `{ inferenceUsd, intelligenceUsd }` split. Both are optional —\n * an un-recorded run still exports a span with whatever was set.\n */\nexport interface TraceHandle {\n /** Capture the run's output. Exported through the redactor. */\n recordOutput(output: unknown): void\n /**\n * Capture the run's outcome. `usage` defaults to inference-only\n * (`intelligenceUsd: 0`) — the OFF baseline; an intelligence-enabled run\n * fills `intelligenceUsd` itself. `costUsd`, when given without a split, is\n * treated as pure inference.\n */\n recordOutcome(outcome: {\n success?: boolean\n score?: number\n costUsd?: number\n usage?: Partial<UsageSplit>\n }): void\n}\n\n/** The resolved outcome of one traced run, surfaced on the export span and\n * available to the caller for downstream billing assertions. */\nexport interface TraceOutcome {\n runId: string\n traceId: string\n project: string\n /** The resolved effort settings this run executed under. */\n effort: EffortSettings\n /** True when this run ran as pure passthrough (the OFF floor). */\n intelligenceOff: boolean\n success?: boolean\n score?: number\n /** Per-class billing split. `intelligenceUsd` is `0` at the OFF tier. */\n usage: UsageSplit\n}\n\n/** The Observe-mode Intelligence client. */\nexport interface IntelligenceClient {\n /** The resolved project id. */\n readonly project: string\n /** The resolved effort settings. */\n readonly effort: EffortSettings\n /**\n * Run `fn` under a trace, export one span best-effort, and return whatever\n * `fn` returns. Telemetry-export failures are swallowed; an error THROWN by\n * `fn` propagates to the caller (the agent's own failures are not masked).\n */\n traceRun<T>(meta: TraceMeta, fn: (trace: TraceHandle) => Promise<T>): Promise<T>\n /**\n * Network-free readiness report: which adoption modes are reachable given\n * this config. Observe is always reachable; Recommend needs outcomes; PR\n * needs checks + surfaces + repo.\n */\n doctor(): DoctorReport\n /** Flush any pending export spans. Best-effort; resolves even if export fails. */\n flush(): Promise<void>\n}\n\n/** One mode's readiness verdict. */\nexport interface ModeReadiness {\n ready: boolean\n /** Inputs this mode still needs, when not ready. Empty when ready. */\n missing: string[]\n}\n\n/** The `doctor()` readiness report — Mode-readiness without any network call. */\nexport interface DoctorReport {\n project: string\n effort: EffortSettings\n /** True when an OTLP endpoint is configured (export will actually ship). */\n exportConfigured: boolean\n modes: {\n observe: ModeReadiness\n recommend: ModeReadiness\n pr: ModeReadiness\n }\n}\n\nfunction resolveEffortConfig(effort: IntelligenceConfig['effort']): EffortSettings {\n if (effort === undefined) return resolveEffort(defaultEffortTier)\n if (typeof effort === 'string') return resolveEffort(effort)\n return resolveEffort(effort.tier, effort.overrides)\n}\n\nfunction resolveEndpoint(endpoint: string | undefined): string | undefined {\n if (endpoint) return endpoint\n if (typeof process === 'undefined') return undefined\n return process.env.INTELLIGENCE_OTLP_ENDPOINT ?? process.env.OTEL_EXPORTER_OTLP_ENDPOINT\n}\n\nfunction freshTraceId(): string {\n return randomHex(32)\n}\n\nfunction freshRunId(): string {\n return `run-${randomHex(16)}`\n}\n\n/** Serialize a redacted value to a bounded string for a span attribute.\n * `loopEventToOtelSpan` only stamps string/number/boolean payload fields, so a\n * structured input/output must be flattened here. Bounded to keep span\n * attributes small; the full payload is the consumer's own store, not the span. */\nconst previewMaxChars = 4096\nfunction previewJson(value: unknown): string {\n let s: string\n if (typeof value === 'string') s = value\n else {\n try {\n s = JSON.stringify(value) ?? String(value)\n } catch {\n s = String(value)\n }\n }\n return s.length > previewMaxChars ? `${s.slice(0, previewMaxChars)}…[truncated]` : s\n}\n\nfunction randomHex(chars: number): string {\n const bytes = new Uint8Array(Math.ceil(chars / 2))\n if (typeof globalThis.crypto?.getRandomValues === 'function') {\n globalThis.crypto.getRandomValues(bytes)\n } else {\n for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256)\n }\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n .slice(0, chars)\n}\n\n/**\n * Create an Observe-mode Intelligence client. Resolves effort, endpoint, and\n * redactor up front; the exporter is built lazily and is `undefined` when no\n * endpoint is configured (export becomes a no-op — best-effort by\n * construction).\n */\nexport function createIntelligenceClient(config: IntelligenceConfig): IntelligenceClient {\n if (!config.project) {\n throw new Error('createIntelligenceClient: `project` is required')\n }\n const effort = resolveEffortConfig(config.effort)\n const intelligenceOff = isIntelligenceOff(effort)\n const redactor = resolveRedactor(config.redact)\n const apiKey =\n config.apiKey ?? (typeof process !== 'undefined' ? process.env.TANGLE_API_KEY : undefined)\n const endpoint = resolveEndpoint(config.endpoint)\n\n // Built lazily: a client with no endpoint never allocates an exporter timer.\n let exporter: OtelExporter | undefined\n let exporterResolved = false\n function getExporter(): OtelExporter | undefined {\n if (exporterResolved) return exporter\n exporterResolved = true\n if (!endpoint) return undefined\n exporter = createOtelExporter({\n endpoint,\n headers: apiKey ? { authorization: `Bearer ${apiKey}` } : {},\n serviceName: config.project,\n resourceAttributes: { 'tangle.project': config.project },\n })\n return exporter\n }\n\n function exportTrace(meta: TraceMeta, outcome: TraceOutcome, output: unknown): void {\n const ex = getExporter()\n if (!ex) return\n const labels: Record<string, string | number | boolean> = {\n project: config.project,\n 'tangle.effort.intelligence_off': outcome.intelligenceOff,\n 'tangle.usage.inference_usd': outcome.usage.inferenceUsd,\n 'tangle.usage.intelligence_usd': outcome.usage.intelligenceUsd,\n ...(meta.model ? { 'gen_ai.request.model': meta.model } : {}),\n ...(meta.provider ? { 'provider.name': meta.provider } : {}),\n ...(typeof outcome.success === 'boolean'\n ? { 'tangle.outcome.success': outcome.success }\n : {}),\n ...(typeof outcome.score === 'number' ? { 'tangle.outcome.score': outcome.score } : {}),\n ...(meta.labels ?? {}),\n }\n const redactedInput = meta.input !== undefined ? redactor(meta.input) : undefined\n const redactedOutput = output !== undefined ? redactor(output) : undefined\n if (redactedInput !== undefined) labels['tangle.input'] = previewJson(redactedInput)\n if (redactedOutput !== undefined) labels['tangle.output'] = previewJson(redactedOutput)\n try {\n ex.exportSpan(\n loopEventToOtelSpan(\n {\n kind: 'tangle.intelligence.run',\n runId: outcome.runId,\n timestamp: Date.now(),\n payload: labels,\n },\n outcome.traceId,\n ),\n )\n } catch {\n // Best-effort — telemetry export must never fail the agent's turn.\n }\n }\n\n return {\n project: config.project,\n effort,\n\n async traceRun<T>(meta: TraceMeta, fn: (trace: TraceHandle) => Promise<T>): Promise<T> {\n const runId = meta.runId ?? freshRunId()\n const traceId = meta.traceId ?? freshTraceId()\n let recordedOutput: unknown\n // Default split: inference-only. At OFF this is provably the whole bill.\n const usage: UsageSplit = { inferenceUsd: 0, intelligenceUsd: 0 }\n let success: boolean | undefined\n let score: number | undefined\n\n const trace: TraceHandle = {\n recordOutput(output: unknown): void {\n recordedOutput = output\n },\n recordOutcome(outcome): void {\n if (typeof outcome.success === 'boolean') success = outcome.success\n if (typeof outcome.score === 'number') score = outcome.score\n if (outcome.usage) {\n if (typeof outcome.usage.inferenceUsd === 'number') {\n usage.inferenceUsd = outcome.usage.inferenceUsd\n }\n if (typeof outcome.usage.intelligenceUsd === 'number') {\n usage.intelligenceUsd = outcome.usage.intelligenceUsd\n }\n } else if (typeof outcome.costUsd === 'number') {\n // A bare cost with no split is pure inference (the base stream).\n usage.inferenceUsd = outcome.costUsd\n }\n },\n }\n\n // The OFF floor is a HARD invariant, not a default: no intelligence spawn\n // can occur in this Observe slice, so intelligence-class spend is zero.\n // We clamp on export rather than trust the caller, so the billing proof\n // holds even if a caller mis-records an outcome at OFF.\n const result = await fn(trace)\n if (intelligenceOff) usage.intelligenceUsd = 0\n\n const outcome: TraceOutcome = {\n runId,\n traceId,\n project: config.project,\n effort,\n intelligenceOff,\n ...(success !== undefined ? { success } : {}),\n ...(score !== undefined ? { score } : {}),\n usage,\n }\n exportTrace(meta, outcome, recordedOutput)\n return result\n },\n\n doctor(): DoctorReport {\n const hasRepo = Boolean(config.repo?.owner && config.repo?.name && config.repo?.baseBranch)\n const hasChecks = Boolean(config.checks && config.checks.length > 0)\n const hasSurfaces = Boolean(config.surfaces && config.surfaces.length > 0)\n\n const prMissing: string[] = []\n if (!hasChecks) prMissing.push('checks')\n if (!hasSurfaces) prMissing.push('surfaces')\n if (!hasRepo) prMissing.push('repo')\n\n // Recommend needs real outcomes to cluster. In the Observe slice the only\n // outcome source is `recordOutcome`; we can't introspect future calls, so\n // readiness reflects that outcome capture is WIRED (the API exists),\n // gated on the client emitting them — surfaced as the honest dependency.\n const recommendMissing: string[] = []\n if (intelligenceOff) recommendMissing.push('effort above off')\n\n return {\n project: config.project,\n effort,\n exportConfigured: Boolean(endpoint),\n modes: {\n observe: { ready: true, missing: [] },\n recommend: {\n ready: recommendMissing.length === 0,\n missing: recommendMissing,\n },\n pr: { ready: prMissing.length === 0, missing: prMissing },\n },\n }\n },\n\n async flush(): Promise<void> {\n const ex = getExporter()\n if (!ex) return\n try {\n await ex.flush()\n } catch {\n // Best-effort — a flush failure must not surface to the caller.\n }\n },\n }\n}\n\n/** A generic agent: one async input → output. The shape `withTangleIntelligence`\n * preserves exactly. */\nexport type Agent<TInput, TOutput> = (input: TInput) => Promise<TOutput>\n\n/** Either a built client or the config to build one. */\nexport type ClientOrConfig = IntelligenceClient | IntelligenceConfig\n\nfunction isClient(value: ClientOrConfig): value is IntelligenceClient {\n return typeof (value as IntelligenceClient).traceRun === 'function'\n}\n\n/**\n * Wrap a generic `agent` with best-effort Observe-mode tracing, returning the\n * SAME shape. Each call runs the agent under a trace and exports one span; an\n * export failure is swallowed (the live agent never fails because Intelligence\n * is down) but an error from the agent itself propagates unchanged.\n *\n * At `effort: 'off'` this is pure passthrough plus best-effort telemetry —\n * zero intelligence spawns, `intelligenceUsd: 0` on the trace.\n */\nexport function withTangleIntelligence<TInput, TOutput>(\n agent: Agent<TInput, TOutput>,\n clientOrConfig: ClientOrConfig,\n): Agent<TInput, TOutput> {\n const client = isClient(clientOrConfig)\n ? clientOrConfig\n : createIntelligenceClient(clientOrConfig)\n\n return async (input: TInput): Promise<TOutput> => {\n return client.traceRun({ input }, async (trace) => {\n const output = await agent(input)\n trace.recordOutput(output)\n return output\n })\n }\n}\n"],"mappings":"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","names":["outcome"]}
@@ -2,12 +2,13 @@
2
2
  import {
3
3
  parseLoopRunnerArgv,
4
4
  runLoopRunnerCli
5
- } from "./chunk-BKAIVNFA.js";
5
+ } from "./chunk-XEI7AIHU.js";
6
6
  import "./chunk-FNMGYYSS.js";
7
- import "./chunk-OM3YNZIW.js";
7
+ import "./chunk-HYG4ISNS.js";
8
8
  import "./chunk-KADIJAD4.js";
9
9
  import "./chunk-HNUXAZIJ.js";
10
- import "./chunk-CM2IK7VS.js";
10
+ import "./chunk-G3RGMA7C.js";
11
+ import "./chunk-FQH33M5N.js";
11
12
  import "./chunk-GSUO5QS6.js";
12
13
  import "./chunk-DGUM43GV.js";
13
14
  export {
package/dist/loops.js CHANGED
@@ -85,7 +85,7 @@ import {
85
85
  trajectoryReport,
86
86
  verify,
87
87
  widen
88
- } from "./chunk-CM2IK7VS.js";
88
+ } from "./chunk-FQH33M5N.js";
89
89
  import {
90
90
  extractLlmCallEvent,
91
91
  mapSandboxEvent
package/dist/mcp/bin.js CHANGED
@@ -4,12 +4,12 @@ import {
4
4
  createPropagatingTraceEmitter,
5
5
  detectExecutor,
6
6
  readTraceContextFromEnv
7
- } from "../chunk-NDM5VXZW.js";
7
+ } from "../chunk-HAA4KZUD.js";
8
8
  import "../chunk-WIR4HOOJ.js";
9
9
  import {
10
10
  DelegationTaskQueue,
11
11
  FileDelegationStore
12
- } from "../chunk-RHW75JW5.js";
12
+ } from "../chunk-47SWANFA.js";
13
13
  import {
14
14
  coderTaskFromArgs,
15
15
  composeLoopTraceEmitters,
@@ -20,14 +20,15 @@ import {
20
20
  parseDetachedSessionRef,
21
21
  runDetachedTurn,
22
22
  settleDetachedCoderTurn
23
- } from "../chunk-OM3YNZIW.js";
23
+ } from "../chunk-HYG4ISNS.js";
24
24
  import {
25
25
  coderProfile
26
26
  } from "../chunk-KADIJAD4.js";
27
27
  import "../chunk-GLR25NG7.js";
28
+ import "../chunk-G3RGMA7C.js";
28
29
  import {
29
30
  runLoop
30
- } from "../chunk-CM2IK7VS.js";
31
+ } from "../chunk-FQH33M5N.js";
31
32
  import "../chunk-GSUO5QS6.js";
32
33
  import "../chunk-DGUM43GV.js";
33
34