@tangle-network/agent-app 0.27.2 → 0.28.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 (98) hide show
  1. package/dist/DesignCanvas-AOIVN3SJ.js +12 -0
  2. package/dist/DesignCanvasEditor-TN7CWUJW.js +13 -0
  3. package/dist/{TimelineEditor-JDG54OBP.js → TimelineEditor-Z7C6BFP5.js} +2 -2
  4. package/dist/{apply-Cp8c3K9D.d.ts → apply-Gk4raT2j.d.ts} +3 -1
  5. package/dist/{chunk-AFDROJ64.js → chunk-2QI7XV2T.js} +1 -1
  6. package/dist/chunk-2QI7XV2T.js.map +1 -0
  7. package/dist/{chunk-LUE4HO5C.js → chunk-4IQMTTNE.js} +10 -10
  8. package/dist/chunk-4IQMTTNE.js.map +1 -0
  9. package/dist/{chunk-HABVCJJT.js → chunk-7I37CO5D.js} +271 -404
  10. package/dist/chunk-7I37CO5D.js.map +1 -0
  11. package/dist/{chunk-5RT6KY4G.js → chunk-GQRL6VNU.js} +1 -1
  12. package/dist/chunk-GQRL6VNU.js.map +1 -0
  13. package/dist/{chunk-SCG5JJ4C.js → chunk-HFC4BTWJ.js} +32 -4
  14. package/dist/chunk-HFC4BTWJ.js.map +1 -0
  15. package/dist/{chunk-7QCIYDGC.js → chunk-IOREXWLM.js} +2 -2
  16. package/dist/chunk-J7JNV5BH.js +14 -0
  17. package/dist/chunk-J7JNV5BH.js.map +1 -0
  18. package/dist/{chunk-6UOE5CTA.js → chunk-JT6HHO5P.js} +5 -10
  19. package/dist/chunk-JT6HHO5P.js.map +1 -0
  20. package/dist/{chunk-JZAJE3JL.js → chunk-M2EBUDZ7.js} +19 -5
  21. package/dist/chunk-M2EBUDZ7.js.map +1 -0
  22. package/dist/{chunk-RJ2ZHK5D.js → chunk-S6WS2B32.js} +132 -7
  23. package/dist/chunk-S6WS2B32.js.map +1 -0
  24. package/dist/chunk-SQV7NUEM.js +136 -0
  25. package/dist/chunk-SQV7NUEM.js.map +1 -0
  26. package/dist/chunk-UAKFCMWK.js +1 -0
  27. package/dist/chunk-UAKFCMWK.js.map +1 -0
  28. package/dist/chunk-V5XZKHCL.js +296 -0
  29. package/dist/chunk-V5XZKHCL.js.map +1 -0
  30. package/dist/chunk-XWJXZ6WE.js +604 -0
  31. package/dist/chunk-XWJXZ6WE.js.map +1 -0
  32. package/dist/chunk-Y2SZVW35.js +125 -0
  33. package/dist/chunk-Y2SZVW35.js.map +1 -0
  34. package/dist/{chunk-27LQXQSS.js → chunk-YEWTVDDT.js} +224 -767
  35. package/dist/chunk-YEWTVDDT.js.map +1 -0
  36. package/dist/{chunk-UDXMR3AD.js → chunk-YNALYIQ3.js} +56 -18
  37. package/dist/chunk-YNALYIQ3.js.map +1 -0
  38. package/dist/command-stack-CkjelfK_.d.ts +267 -0
  39. package/dist/design-canvas/drizzle.d.ts +2 -2
  40. package/dist/design-canvas/index.d.ts +7 -6
  41. package/dist/design-canvas/index.js +3 -2
  42. package/dist/design-canvas-react/engine.d.ts +349 -0
  43. package/dist/design-canvas-react/engine.js +86 -0
  44. package/dist/design-canvas-react/engine.js.map +1 -0
  45. package/dist/design-canvas-react/index.d.ts +69 -649
  46. package/dist/design-canvas-react/index.js +84 -173
  47. package/dist/design-canvas-react/index.js.map +1 -1
  48. package/dist/design-canvas-react/lazy.d.ts +6 -0
  49. package/dist/design-canvas-react/lazy.js +9 -0
  50. package/dist/design-canvas-react/lazy.js.map +1 -0
  51. package/dist/{export-presets-Dl5Aa5xj.d.ts → export-presets-DAsU5Wal.d.ts} +2 -143
  52. package/dist/flow-types-Cb_AblZs.d.ts +25 -0
  53. package/dist/index.d.ts +11 -8
  54. package/dist/index.js +21 -8
  55. package/dist/lazy-BHHqS8-j.d.ts +72 -0
  56. package/dist/missions/index.d.ts +12 -0
  57. package/dist/missions/index.js +1 -1
  58. package/dist/{model-BHLN208Z.d.ts → model-BBwyOuWG.d.ts} +3 -1
  59. package/dist/operations-DLIvvD00.d.ts +144 -0
  60. package/dist/platform/index.js +1 -1
  61. package/dist/runtime/index.d.ts +33 -33
  62. package/dist/runtime/index.js +1 -1
  63. package/dist/sequences/index.d.ts +1 -1
  64. package/dist/sequences/index.js +2 -1
  65. package/dist/sequences-react/index.d.ts +15 -1
  66. package/dist/sequences-react/index.js +2 -2
  67. package/dist/{store-CUStmtdH.d.ts → store-CFyxgTlD.d.ts} +1 -1
  68. package/dist/theme/index.d.ts +80 -0
  69. package/dist/theme/index.js +14 -0
  70. package/dist/theme/index.js.map +1 -0
  71. package/dist/theme/tailwind-preset.d.ts +65 -0
  72. package/dist/theme/tailwind-preset.js +33 -0
  73. package/dist/theme/tailwind-preset.js.map +1 -0
  74. package/dist/theme/tokens.css +95 -0
  75. package/dist/trace/index.d.ts +2 -18
  76. package/dist/trace/index.js +2 -2
  77. package/dist/web/index.d.ts +25 -2
  78. package/dist/web/index.js +3 -1
  79. package/dist/web-react/index.d.ts +71 -31
  80. package/dist/web-react/index.js +625 -486
  81. package/dist/web-react/index.js.map +1 -1
  82. package/package.json +28 -3
  83. package/dist/DesignCanvas-73IUJJUP.js +0 -10
  84. package/dist/DesignCanvasEditor-6F2UTOSW.js +0 -9
  85. package/dist/chunk-27LQXQSS.js.map +0 -1
  86. package/dist/chunk-5RT6KY4G.js.map +0 -1
  87. package/dist/chunk-6UOE5CTA.js.map +0 -1
  88. package/dist/chunk-AFDROJ64.js.map +0 -1
  89. package/dist/chunk-HABVCJJT.js.map +0 -1
  90. package/dist/chunk-JZAJE3JL.js.map +0 -1
  91. package/dist/chunk-LUE4HO5C.js.map +0 -1
  92. package/dist/chunk-RJ2ZHK5D.js.map +0 -1
  93. package/dist/chunk-SCG5JJ4C.js.map +0 -1
  94. package/dist/chunk-UDXMR3AD.js.map +0 -1
  95. /package/dist/{DesignCanvas-73IUJJUP.js.map → DesignCanvas-AOIVN3SJ.js.map} +0 -0
  96. /package/dist/{DesignCanvasEditor-6F2UTOSW.js.map → DesignCanvasEditor-TN7CWUJW.js.map} +0 -0
  97. /package/dist/{TimelineEditor-JDG54OBP.js.map → TimelineEditor-Z7C6BFP5.js.map} +0 -0
  98. /package/dist/{chunk-7QCIYDGC.js.map → chunk-IOREXWLM.js.map} +0 -0
@@ -0,0 +1,12 @@
1
+ import {
2
+ DesignCanvas,
3
+ DesignCanvas_default
4
+ } from "./chunk-YEWTVDDT.js";
5
+ import "./chunk-XWJXZ6WE.js";
6
+ import "./chunk-M2EBUDZ7.js";
7
+ import "./chunk-HFC4BTWJ.js";
8
+ export {
9
+ DesignCanvas,
10
+ DesignCanvas_default as default
11
+ };
12
+ //# sourceMappingURL=DesignCanvas-AOIVN3SJ.js.map
@@ -0,0 +1,13 @@
1
+ import {
2
+ DesignCanvasEditor
3
+ } from "./chunk-7I37CO5D.js";
4
+ import "./chunk-YEWTVDDT.js";
5
+ import "./chunk-V5XZKHCL.js";
6
+ import "./chunk-XWJXZ6WE.js";
7
+ import "./chunk-M2EBUDZ7.js";
8
+ import "./chunk-Y2SZVW35.js";
9
+ import "./chunk-HFC4BTWJ.js";
10
+ export {
11
+ DesignCanvasEditor
12
+ };
13
+ //# sourceMappingURL=DesignCanvasEditor-TN7CWUJW.js.map
@@ -2,11 +2,11 @@ import {
2
2
  SEQUENCE_MEDIA_DRAG_TYPE,
3
3
  TimelineEditor,
4
4
  TimelineEditor_default
5
- } from "./chunk-RJ2ZHK5D.js";
5
+ } from "./chunk-S6WS2B32.js";
6
6
  import "./chunk-ZYBWGSAZ.js";
7
7
  export {
8
8
  SEQUENCE_MEDIA_DRAG_TYPE,
9
9
  TimelineEditor,
10
10
  TimelineEditor_default as default
11
11
  };
12
- //# sourceMappingURL=TimelineEditor-JDG54OBP.js.map
12
+ //# sourceMappingURL=TimelineEditor-Z7C6BFP5.js.map
@@ -192,7 +192,9 @@ declare function lastClipEndFrame(timeline: SequenceTimeline): number;
192
192
  /** Media references must be provider URLs or app-served paths. Local sandbox
193
193
  * artifacts (file:, data:, /tmp/, /home/) are rejected because they are
194
194
  * unreachable from the product and signal an agent substituting local ffmpeg
195
- * output for real provider generation. */
195
+ * output for real provider generation. Delegates to the canonical
196
+ * `assertMediaUrl` boundary in `../web` — sequences and design-canvas share ONE
197
+ * rule so the two surfaces cannot drift on what counts as a reachable url. */
196
198
  declare function assertSequenceMediaUrl(url: string): void;
197
199
 
198
200
  /**
@@ -215,4 +215,4 @@ export {
215
215
  stepActivityFlowTrace,
216
216
  composeMissionFlowTrace
217
217
  };
218
- //# sourceMappingURL=chunk-AFDROJ64.js.map
218
+ //# sourceMappingURL=chunk-2QI7XV2T.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/trace/mission-flow.ts"],"sourcesContent":["/**\n * Delegation → FlowSpan converters — render what a mission's delegated agent\n * runs actually did as ONE FlowTrace, drawable by the existing\n * `renderWaterfall` (or any viewer that consumes FlowSpans).\n *\n * Two fidelities, one tree:\n * - COARSE: `delegationActivityToFlowSpans` draws one 'tool' span per\n * delegation from the StepAgentActivity snapshot (startedAt/durationMs) —\n * available live, from the step's journaled lane.\n * - FINE: `loopTraceEventsToFlowSpans` reconstructs agent-runtime's\n * loop → round → iteration hierarchy from the LoopTraceEvent journal a\n * delegation persists. FlowSpans carry no parent ids, so nesting rides the\n * span NAME (`loop ▸ round 0 ▸ iter 1 (coder)`), matching how the ASCII\n * waterfall reads.\n *\n * `composeMissionFlowTrace` lays a whole mission out: one 'pipeline' span per\n * step, each step's delegations beneath it. Pure data transforms — the\n * structural `LoopTraceEventLike` keeps this module free of the optional\n * agent-runtime peer.\n */\n\nimport type { StepAgentActivity } from '../missions/agent-activity'\nimport type { FlowSpan, FlowTrace } from './flow-types'\n\n/** Structural mirror of agent-runtime's `LoopTraceEvent` — same fields, no\n * import, so journals parsed from JSON feed straight in. */\nexport interface LoopTraceEventLike {\n kind: string\n runId: string\n /** Epoch ms. */\n timestamp: number\n payload: object\n}\n\nconst num = (v: unknown): number | undefined =>\n typeof v === 'number' && Number.isFinite(v) ? v : undefined\nconst str = (v: unknown): string | undefined =>\n typeof v === 'string' && v.length > 0 ? v : undefined\nconst rec = (v: unknown): Record<string, unknown> =>\n v && typeof v === 'object' ? (v as Record<string, unknown>) : {}\n\n/** Statuses that mean the delegation is still producing wall time. */\nconst LIVE_DELEGATION_STATUSES = new Set(['pending', 'running'])\n\n/**\n * One 'tool' FlowSpan per delegation, positioned relative to `turnStartMs`\n * (the epoch-ms origin of the trace — usually the step or mission start).\n * A row whose `startedAt` does not parse cannot be placed on a timeline and\n * is omitted from the WATERFALL (it stays in the lane itself). A run without\n * `durationMs` is still in flight: its span extends to `opts.nowMs` when\n * given, else renders as a point — `approx` flags both.\n */\nexport function delegationActivityToFlowSpans(\n activity: StepAgentActivity[],\n turnStartMs: number,\n opts?: { nowMs?: number },\n): FlowSpan[] {\n const spans: FlowSpan[] = []\n for (const run of activity) {\n const startedAt = Date.parse(run.startedAt)\n if (!Number.isFinite(startedAt)) continue\n const startMs = startedAt - turnStartMs\n const live = LIVE_DELEGATION_STATUSES.has(run.status)\n const endMs =\n run.durationMs !== undefined\n ? startMs + run.durationMs\n : live && opts?.nowMs !== undefined\n ? opts.nowMs - turnStartMs\n : startMs\n spans.push({\n kind: 'tool',\n name: `${run.tool} — ${run.detail}`,\n startMs,\n endMs: Math.max(endMs, startMs),\n ...(run.durationMs === undefined ? { approx: true } : {}),\n meta: {\n taskId: run.taskId,\n status: run.status,\n ...(run.costUsd !== undefined ? { costUsd: run.costUsd } : {}),\n ...(run.iteration !== undefined ? { iteration: run.iteration } : {}),\n ...(run.phase !== undefined ? { phase: run.phase } : {}),\n ...(run.traceId !== undefined ? { traceId: run.traceId } : {}),\n ...(run.spanId !== undefined ? { spanId: run.spanId } : {}),\n },\n })\n }\n return spans\n}\n\n/**\n * Reconstruct one delegation's loop → round → iteration tree from its\n * journaled LoopTraceEvents, as FlowSpans relative to `loop.started` (or the\n * first event). Mirrors agent-runtime's `buildLoopOtelSpans` topology:\n * rounds open on `loop.plan` and flush on the next plan / `loop.decision` /\n * `loop.ended`; iterations span `loop.iteration.started` → `.ended`.\n */\nexport function loopTraceEventsToFlowSpans(events: LoopTraceEventLike[]): FlowSpan[] {\n if (events.length === 0) return []\n const ordered = [...events].sort((a, b) => a.timestamp - b.timestamp)\n const started = ordered.find((e) => e.kind === 'loop.started')\n const ended = ordered.find((e) => e.kind === 'loop.ended')\n const origin = started?.timestamp ?? ordered[0]!.timestamp\n const rootEnd = ended?.timestamp ?? ordered[ordered.length - 1]!.timestamp\n const t = (epochMs: number) => epochMs - origin\n\n const spans: FlowSpan[] = []\n const sp = rec(started?.payload)\n const ep = rec(ended?.payload)\n spans.push({\n kind: 'pipeline',\n name: 'loop',\n startMs: 0,\n endMs: t(rootEnd),\n meta: {\n runId: ordered[0]!.runId,\n ...(str(sp.driver) !== undefined ? { driver: str(sp.driver) } : {}),\n ...(num(ep.totalCostUsd) !== undefined ? { costUsd: num(ep.totalCostUsd) } : {}),\n ...(num(ep.winnerIterationIndex) !== undefined\n ? { winnerIterationIndex: num(ep.winnerIterationIndex) }\n : {}),\n ...(num(ep.iterations) !== undefined ? { iterations: num(ep.iterations) } : {}),\n },\n })\n\n const iterStart = new Map<number, number>()\n let round: { index: number; startMs: number; meta: Record<string, unknown>; moveKind: string } | undefined\n const flushRound = (endEpochMs: number) => {\n if (!round) return\n spans.push({\n kind: 'pipeline',\n name: `loop ▸ round ${round.index} (${round.moveKind})`,\n startMs: round.startMs,\n endMs: t(endEpochMs),\n meta: round.meta,\n })\n round = undefined\n }\n\n for (const e of ordered) {\n const p = rec(e.payload)\n switch (e.kind) {\n case 'loop.plan': {\n flushRound(e.timestamp)\n const index = num(p.roundIndex) ?? 0\n round = {\n index,\n startMs: t(e.timestamp),\n moveKind: str(p.moveKind) ?? 'unknown',\n meta: {\n roundIndex: index,\n moveKind: str(p.moveKind) ?? 'unknown',\n width: num(p.plannedCount) ?? 0,\n ...(str(p.rationale) !== undefined ? { rationale: str(p.rationale) } : {}),\n ...(num(p.parentIndex) !== undefined ? { parentIndex: num(p.parentIndex) } : {}),\n },\n }\n break\n }\n case 'loop.iteration.started': {\n const idx = num(p.iterationIndex)\n if (idx !== undefined) iterStart.set(idx, e.timestamp)\n break\n }\n case 'loop.iteration.ended': {\n const idx = num(p.iterationIndex) ?? 0\n const startEpoch = iterStart.get(idx) ?? e.timestamp\n const error = str(p.error)\n const verdict = rec(p.verdict)\n const tokens = rec(p.tokenUsage)\n const roundLabel = round ? `round ${round.index} ▸ ` : ''\n spans.push({\n kind: 'model',\n name: `loop ▸ ${roundLabel}iter ${idx} (${str(p.agentRunName) ?? 'agent'})`,\n startMs: t(startEpoch),\n endMs: t(e.timestamp),\n meta: {\n iterationIndex: idx,\n ok: error === undefined,\n ...(error !== undefined ? { error } : {}),\n ...(num(p.costUsd) !== undefined ? { costUsd: num(p.costUsd) } : {}),\n ...(typeof verdict.valid === 'boolean' ? { verdictValid: verdict.valid } : {}),\n ...(num(verdict.score) !== undefined ? { verdictScore: num(verdict.score) } : {}),\n ...(num(tokens.input) !== undefined ? { inputTokens: num(tokens.input) } : {}),\n ...(num(tokens.output) !== undefined ? { outputTokens: num(tokens.output) } : {}),\n },\n })\n break\n }\n case 'loop.decision': {\n if (round) {\n const decision = str(p.decision)\n if (decision !== undefined) round.meta.decision = decision\n flushRound(e.timestamp)\n }\n break\n }\n }\n }\n flushRound(rootEnd)\n return spans\n}\n\n/**\n * A single step's activity lane as its own FlowTrace — what a per-step\n * drill-in renders. Origin defaults to the earliest delegation start so the\n * waterfall begins at the lane's first run.\n */\nexport function stepActivityFlowTrace(\n activity: StepAgentActivity[],\n opts?: { startedAt?: number; nowMs?: number },\n): FlowTrace {\n let origin = opts?.startedAt\n if (origin === undefined) {\n for (const run of activity) {\n const parsed = Date.parse(run.startedAt)\n if (Number.isFinite(parsed) && (origin === undefined || parsed < origin)) origin = parsed\n }\n }\n const spans = delegationActivityToFlowSpans(\n activity,\n origin ?? 0,\n opts?.nowMs !== undefined ? { nowMs: opts.nowMs } : undefined,\n )\n let costUsd: number | undefined\n for (const span of spans) {\n const c = num(rec(span.meta).costUsd)\n if (c !== undefined) costUsd = (costUsd ?? 0) + c\n }\n return {\n spans,\n totalMs: spans.reduce((max, s) => Math.max(max, s.endMs), 0),\n promptTokens: 0,\n completionTokens: 0,\n ...(costUsd !== undefined ? { costUsd } : {}),\n toolCalls: spans.length,\n }\n}\n\nexport interface MissionFlowStep {\n id: string\n intent: string\n status?: string\n /** Epoch ms the step attempt started. Absent → laid out sequentially after\n * the previous step (missions run steps in order), `approx` flagged. */\n startedAt?: number\n durationMs?: number\n}\n\n/**\n * Compose a mission-wide FlowTrace: one 'pipeline' span per step, the step's\n * delegated runs ('tool' spans, from `activity[stepId]`) beneath it. A step\n * span always covers its delegations' extent. Cost is the sum of delegation\n * `costUsd`; token counts are not knowable from the activity lane and stay 0.\n */\nexport function composeMissionFlowTrace(input: {\n steps: MissionFlowStep[]\n /** Delegated-run snapshots keyed by step id (the step's `agentActivity`). */\n activity?: Record<string, StepAgentActivity[]>\n /** Epoch-ms origin. Default: the earliest known step/delegation start. */\n startedAt?: number\n}): FlowTrace {\n const activity = input.activity ?? {}\n\n const startCandidates: number[] = []\n if (input.startedAt !== undefined) startCandidates.push(input.startedAt)\n else {\n for (const step of input.steps) {\n if (step.startedAt !== undefined) startCandidates.push(step.startedAt)\n }\n for (const runs of Object.values(activity)) {\n for (const run of runs) {\n const parsed = Date.parse(run.startedAt)\n if (Number.isFinite(parsed)) startCandidates.push(parsed)\n }\n }\n }\n const origin = startCandidates.length > 0 ? Math.min(...startCandidates) : 0\n\n const spans: FlowSpan[] = []\n let costUsd: number | undefined\n let toolCalls = 0\n let cursorMs = 0\n\n for (const step of input.steps) {\n const inferred = step.startedAt === undefined\n const startMs = inferred ? cursorMs : step.startedAt! - origin\n const runSpans = delegationActivityToFlowSpans(activity[step.id] ?? [], origin)\n const runExtent = runSpans.reduce((max, s) => Math.max(max, s.endMs), startMs)\n const endMs = Math.max(step.durationMs !== undefined ? startMs + step.durationMs : startMs, runExtent)\n\n spans.push({\n kind: 'pipeline',\n name: step.intent,\n startMs,\n endMs,\n ...(inferred || step.durationMs === undefined ? { approx: true } : {}),\n meta: { stepId: step.id, ...(step.status !== undefined ? { status: step.status } : {}) },\n })\n for (const span of runSpans) {\n spans.push({ ...span, name: `${step.intent} ▸ ${span.name}` })\n toolCalls++\n const c = num(rec(span.meta).costUsd)\n if (c !== undefined) costUsd = (costUsd ?? 0) + c\n }\n cursorMs = endMs\n }\n\n return {\n spans,\n totalMs: spans.reduce((max, s) => Math.max(max, s.endMs), 0),\n promptTokens: 0,\n completionTokens: 0,\n ...(costUsd !== undefined ? { costUsd } : {}),\n toolCalls,\n }\n}\n"],"mappings":"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","names":[]}
@@ -248,6 +248,12 @@ async function* streamChatCompletions(doFetch, url, apiKey, body) {
248
248
  }
249
249
  }
250
250
 
251
+ // src/runtime/loop.ts
252
+ import {
253
+ runToolLoop,
254
+ streamToolLoop
255
+ } from "@tangle-network/agent-runtime";
256
+
251
257
  // src/runtime/agent.ts
252
258
  function createAgentRuntime(opts) {
253
259
  if (opts.executeOtherTool && !opts.isOtherExecutableTool) {
@@ -477,12 +483,6 @@ function assertSurfaceOverlay(overlay, label) {
477
483
  }
478
484
  }
479
485
 
480
- // src/runtime/index.ts
481
- import {
482
- runToolLoop,
483
- streamToolLoop
484
- } from "@tangle-network/agent-runtime";
485
-
486
486
  export {
487
487
  normalizeModelId,
488
488
  buildCatalog,
@@ -490,12 +490,12 @@ export {
490
490
  __resetCatalogCache,
491
491
  toLoopEvents,
492
492
  createOpenAICompatStreamTurn,
493
+ runToolLoop,
494
+ streamToolLoop,
493
495
  createAgentRuntime,
494
496
  createCertifiedDelivery,
495
497
  defineSurfaceKind,
496
498
  createSurfaceRegistry,
497
- mergeSurfaceOverlay,
498
- runToolLoop,
499
- streamToolLoop
499
+ mergeSurfaceOverlay
500
500
  };
501
- //# sourceMappingURL=chunk-LUE4HO5C.js.map
501
+ //# sourceMappingURL=chunk-4IQMTTNE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/model-catalog.ts","../src/runtime/openai-stream.ts","../src/runtime/loop.ts","../src/runtime/agent.ts","../src/runtime/certified-delivery.ts","../src/runtime/surface-profile.ts"],"sourcesContent":["/**\n * Model catalogue — computed live from the Tangle Router, never hand-curated.\n * Lifted from tuner-agent so every agent app's model picker shares one\n * filter/dedupe/rank/feature pipeline instead of re-deriving it.\n *\n * The router's /models endpoint returns every routeable model (~200), which is\n * unusable as a picker list: it mixes chat models with TTS/embedding/realtime\n * endpoints, dated snapshots alias their parents, and provider-prefixed ids\n * duplicate canonical ones. This module turns that into a product catalogue:\n *\n * filter (chat-capable, routeable) → dedupe (snapshot/prefix/:free aliases)\n * → rank (provider tier, family, version) → feature (best model per family)\n * → default (env override or first featured)\n *\n * Freshness is automatic: everything is derived from the live router response,\n * so new models surface as soon as the router lists them. The only static\n * knowledge here is slow-moving: provider display order and family name\n * patterns (e.g. \"claude-sonnet-*\", \"gpt-N\"). A new Sonnet or GPT release\n * outranks its predecessor by version comparison with zero code change; only\n * a brand-new *family name* (rare) needs a one-line rule addition.\n */\n\nexport interface RouterModel {\n id: string\n name?: string\n description?: string\n _provider?: string\n pricing?: { prompt?: string | null; completion?: string | null }\n context_length?: number\n architecture?: {\n modality?: string\n input_modalities?: string[]\n output_modalities?: string[]\n }\n supported_parameters?: string[]\n routeability?: {\n status?: string\n routeable?: boolean\n provider?: string\n }\n}\n\nexport interface CatalogModel {\n id: string\n name: string\n provider: string\n description?: string\n contextLength?: number\n pricing?: { prompt?: string; completion?: string }\n supportsTools: boolean\n supportsReasoning: boolean\n featured: boolean\n}\n\nexport interface ModelCatalog {\n defaultModelId: string | null\n fetchedAt: string\n models: CatalogModel[]\n}\n\n/** Display order. Unlisted providers sort after these, alphabetically. */\nconst PROVIDER_TIER: string[] = [\n 'anthropic',\n 'openai',\n 'google',\n 'xai',\n 'deepseek',\n 'moonshotai',\n 'moonshot',\n 'zai',\n 'z-ai',\n 'mistral',\n 'groq',\n 'nvidia',\n 'cohere',\n 'cerebras',\n]\n\n/** Non-chat endpoints that pollute the router list (matched on normalized id). */\nconst EXCLUDED_ID = /(embedding|tts|transcribe|whisper|audio|realtime|image|lyria|sora|dall-e|moderation|content-safety|search-preview|search-api|deep-research)/\n\n/**\n * Featured families, in display order. Each rule surfaces the highest-version\n * routeable model whose normalized id matches. Patterns anchor on the family\n * name and stop before specialty suffixes (codex, nano, lite, …) so the\n * mainline model wins.\n */\nconst FEATURED_RULES: Array<{ providers: string[]; match: RegExp }> = [\n { providers: ['anthropic'], match: /^claude-sonnet-[\\d-]+$/ },\n { providers: ['anthropic'], match: /^claude-opus-[\\d-]+$/ },\n { providers: ['anthropic'], match: /^claude-haiku-[\\d-]+$/ },\n { providers: ['openai'], match: /^gpt-\\d+(\\.\\d+)?$/ },\n { providers: ['openai'], match: /^gpt-\\d+(\\.\\d+)?-mini$/ },\n { providers: ['google'], match: /^gemini-[\\d.]+-pro(-preview)?$/ },\n { providers: ['google'], match: /^gemini-[\\d.]+-flash(-preview)?$/ },\n { providers: ['xai'], match: /^grok-[\\d.]+$/ },\n { providers: ['deepseek'], match: /^deepseek-(chat|v[\\d.]+(-\\w+)?)$/ },\n { providers: ['moonshotai', 'moonshot'], match: /^kimi-k[\\d.]+$/ },\n { providers: ['zai', 'z-ai'], match: /^glm-[\\d.]+$/ },\n { providers: ['mistral'], match: /^mistral-(large|medium)-?[\\d.-]*$/ },\n]\n\n/** Families known to support tool calls even when router metadata omits it\n * (dated snapshots often lack the supported_parameters of their parent). */\nconst TOOL_CAPABLE_FAMILY = /^(claude|gpt-[45]|gpt-oss|o[134]|gemini|grok|deepseek|glm|kimi|mistral|ministral|magistral|command|nemotron|llama)/\n\n/** Strip provider prefix, :free suffix, and trailing date stamps. */\nexport function normalizeModelId(id: string): string {\n let tail = id.split('/').pop() ?? id\n tail = tail.replace(/:free$/, '')\n tail = tail.replace(/-\\d{8}$/, '')\n tail = tail.replace(/-\\d{4}-\\d{2}-\\d{2}$/, '')\n return tail\n}\n\n/** All numeric groups in a normalized id, for version comparison. */\nfunction versionOf(normId: string): number[] {\n return (normId.match(/\\d+/g) ?? []).map(Number)\n}\n\nfunction compareVersions(a: number[], b: number[]): number {\n const len = Math.max(a.length, b.length)\n for (let i = 0; i < len; i++) {\n const d = (a[i] ?? -1) - (b[i] ?? -1)\n if (d !== 0) return d\n }\n return 0\n}\n\n/** Lower = preferred representative for an alias group. */\nfunction aliasPenalty(id: string): number {\n let p = 0\n if (id.includes('/')) p += 4\n if (/-\\d{8}$|-\\d{4}-\\d{2}-\\d{2}$/.test(id.replace(/:free$/, ''))) p += 2\n if (id.endsWith(':free')) p += 1\n return p\n}\n\nfunction providerRank(provider: string): number {\n const i = PROVIDER_TIER.indexOf(provider)\n return i === -1 ? PROVIDER_TIER.length : i\n}\n\nfunction isChatModel(m: RouterModel): boolean {\n const arch = m.architecture\n if (!arch?.input_modalities || !arch?.output_modalities) return true\n return arch.input_modalities.includes('text') && arch.output_modalities.includes('text')\n}\n\nfunction isRouteable(m: RouterModel): boolean {\n return m.routeability?.routeable !== false && m.routeability?.status !== 'unavailable'\n}\n\nfunction familyOf(normId: string): string {\n return normId.replace(/[\\d.]+/g, '').replace(/-+/g, '-').replace(/-$/, '')\n}\n\n/**\n * Pure catalogue pipeline. `preferredDefault` (typically the MODEL_NAME env\n * var) wins when it survives filtering; otherwise the first featured model.\n */\nexport function buildCatalog(raw: RouterModel[], opts?: { preferredDefault?: string }): ModelCatalog {\n // Filter to chat-capable, routeable, non-specialty models\n const candidates = raw.filter(\n (m) => m.id && isRouteable(m) && isChatModel(m) && !EXCLUDED_ID.test(normalizeModelId(m.id)),\n )\n\n // Dedupe alias groups (dated snapshots, provider prefixes, :free variants).\n // Within a group, merge metadata so the representative keeps the richest\n // supported_parameters claim (snapshots often omit what the parent lists).\n const groups = new Map<string, RouterModel[]>()\n for (const m of candidates) {\n const key = `${m._provider ?? ''}::${normalizeModelId(m.id)}`\n const g = groups.get(key)\n if (g) g.push(m)\n else groups.set(key, [m])\n }\n\n const reps: Array<{ model: RouterModel; normId: string; mergedParams: Set<string> }> = []\n for (const group of groups.values()) {\n group.sort((a, b) => aliasPenalty(a.id) - aliasPenalty(b.id) || a.id.length - b.id.length)\n const rep = group[0]!\n const mergedParams = new Set<string>(group.flatMap((m) => m.supported_parameters ?? []))\n reps.push({ model: rep, normId: normalizeModelId(rep.id), mergedParams })\n }\n\n // Featured: best version per family rule, in rule order\n const featuredIds: string[] = []\n for (const rule of FEATURED_RULES) {\n const matches = reps.filter(\n (r) =>\n rule.providers.includes(r.model._provider ?? '') &&\n rule.match.test(r.normId) &&\n !featuredIds.includes(r.model.id),\n )\n if (!matches.length) continue\n matches.sort(\n (a, b) =>\n compareVersions(versionOf(b.normId), versionOf(a.normId)) ||\n Number(a.normId.includes('preview')) - Number(b.normId.includes('preview')) ||\n a.model.id.length - b.model.id.length,\n )\n featuredIds.push(matches[0]!.model.id)\n }\n\n const toCatalogModel = (r: (typeof reps)[number]): CatalogModel => {\n const m = r.model\n const provider = m._provider ?? 'unknown'\n return {\n id: m.id,\n name: m.name ?? m.id,\n provider,\n description: m.description ? m.description.slice(0, 160) : undefined,\n contextLength: m.context_length,\n pricing:\n m.pricing?.prompt || m.pricing?.completion\n ? { prompt: m.pricing.prompt ?? undefined, completion: m.pricing.completion ?? undefined }\n : undefined,\n supportsTools: r.mergedParams.has('tools') || TOOL_CAPABLE_FAMILY.test(r.normId),\n supportsReasoning: r.mergedParams.has('reasoning') || r.mergedParams.has('include_reasoning'),\n featured: featuredIds.includes(m.id),\n }\n }\n\n // Sort: featured first (rule order), then provider tier → family → version desc\n const featured = featuredIds\n .map((id) => reps.find((r) => r.model.id === id)!)\n .map(toCatalogModel)\n const rest = reps\n .filter((r) => !featuredIds.includes(r.model.id))\n .sort((a, b) => {\n const pa = providerRank(a.model._provider ?? '')\n const pb = providerRank(b.model._provider ?? '')\n if (pa !== pb) return pa - pb\n const fa = familyOf(a.normId)\n const fb = familyOf(b.normId)\n if (fa !== fb) return fa.localeCompare(fb)\n return compareVersions(versionOf(b.normId), versionOf(a.normId)) || a.model.id.localeCompare(b.model.id)\n })\n .map(toCatalogModel)\n\n const models = [...featured, ...rest]\n\n const preferred = opts?.preferredDefault\n const defaultModelId =\n (preferred && models.find((m) => m.id === preferred || normalizeModelId(m.id) === normalizeModelId(preferred))?.id) ||\n featured.find((m) => m.supportsTools)?.id ||\n models[0]?.id ||\n null\n\n return { defaultModelId, fetchedAt: new Date().toISOString(), models }\n}\n\n// ── Cached fetch ─────────────────────────────────────────────────────────\n\nconst CATALOG_TTL_MS = 5 * 60 * 1000\n\nlet _cache: { catalog: ModelCatalog; at: number } | null = null\n\n/**\n * Fetch the router model list and build the catalogue, with an in-isolate\n * cache (TTL 5 min). On router failure a stale catalogue is served rather\n * than erroring the picker.\n */\nexport async function fetchModelCatalog(cfg: {\n baseUrl: string\n apiKey: string\n preferredDefault?: string\n}): Promise<ModelCatalog> {\n if (_cache && Date.now() - _cache.at < CATALOG_TTL_MS) {\n return _cache.catalog\n }\n try {\n const res = await fetch(`${cfg.baseUrl}/models`, {\n headers: { Authorization: `Bearer ${cfg.apiKey}` },\n })\n if (!res.ok) throw new Error(`Router /models returned ${res.status}`)\n const data = (await res.json()) as { data?: RouterModel[] }\n const catalog = buildCatalog(data.data ?? [], { preferredDefault: cfg.preferredDefault })\n _cache = { catalog, at: Date.now() }\n return catalog\n } catch (err) {\n if (_cache) return _cache.catalog\n throw err\n }\n}\n\n/** Test-only: clear the catalogue cache. */\nexport function __resetCatalogCache(): void {\n _cache = null\n}\n","/**\n * OpenAI-compatible stream → `LoopEvent` adapter, for NON-sandbox copilots.\n *\n * `streamAppToolLoop` takes a `streamTurn` seam that yields `LoopEvent`s. A\n * sandboxed agent produces those from its container; a browser/edge copilot\n * instead calls a model directly. The Tangle Router, the tcloud SDK, and most\n * providers all speak the OpenAI Chat Completions streaming shape — so the ONE\n * reusable piece is assembling that stream (content deltas + FRAGMENTED\n * tool-call deltas) into `LoopEvent`s. That assembly is the boilerplate every\n * copilot would re-write (and get wrong — OpenAI streams tool-call arguments in\n * pieces across chunks).\n *\n * This does NOT implement an HTTP client beyond a minimal `fetch` + SSE reader\n * (browser/edge/Node-safe, zero deps). For richer transport use the tcloud SDK\n * or the Vercel AI SDK and pipe their stream through {@link toLoopEvents}.\n */\nimport type { LoopEvent, LoopMessage, LoopToolCall } from './loop'\n\n/** Minimal OpenAI Chat Completions streaming chunk (structural — no `openai` dep). */\nexport interface OpenAIStreamChunk {\n choices?: Array<{\n delta?: {\n content?: string | null\n /** Reasoning deltas — DeepSeek/router use `reasoning_content`; some proxies use `thinking`. */\n reasoning_content?: string | null\n thinking?: string | null\n tool_calls?: Array<{\n index: number\n id?: string\n function?: { name?: string; arguments?: string }\n }>\n }\n finish_reason?: string | null\n }>\n /** Final-chunk token accounting (requires `stream_options.include_usage`). */\n usage?: {\n prompt_tokens?: number\n completion_tokens?: number\n } | null\n}\n\ninterface PartialToolCall {\n id?: string\n name: string\n args: string\n}\n\n/**\n * Map an OpenAI-compat streaming chunk iterator to `LoopEvent`s: each content\n * delta → a `text` event; tool-call deltas are accumulated by index across\n * chunks and emitted as one complete `tool_call` event when the stream finishes\n * (arguments JSON-parsed; an empty/garbled args string yields `{}` rather than\n * throwing). Works for the Tangle Router, tcloud, or any OpenAI-compat source.\n */\nexport async function* toLoopEvents(chunks: AsyncIterable<OpenAIStreamChunk>): AsyncIterable<LoopEvent> {\n const calls = new Map<number, PartialToolCall>()\n for await (const chunk of chunks) {\n // Usage rides the final chunk, which has an empty choices array — handle\n // it before the choice guard.\n if (chunk.usage?.prompt_tokens != null || chunk.usage?.completion_tokens != null) {\n yield {\n type: 'usage',\n usage: {\n promptTokens: chunk.usage.prompt_tokens ?? 0,\n completionTokens: chunk.usage.completion_tokens ?? 0,\n },\n }\n }\n const choice = chunk.choices?.[0]\n if (!choice) continue\n const content = choice.delta?.content\n if (content) yield { type: 'text', text: content }\n const reasoning = choice.delta?.reasoning_content ?? choice.delta?.thinking\n if (reasoning) yield { type: 'reasoning', text: reasoning }\n for (const tc of choice.delta?.tool_calls ?? []) {\n const cur = calls.get(tc.index) ?? { name: '', args: '' }\n if (tc.id) cur.id = tc.id\n if (tc.function?.name) cur.name += tc.function.name\n if (tc.function?.arguments) cur.args += tc.function.arguments\n calls.set(tc.index, cur)\n }\n }\n for (const [, c] of [...calls.entries()].sort((a, b) => a[0] - b[0])) {\n if (!c.name) continue\n yield { type: 'tool_call', call: { toolCallId: c.id, toolName: c.name, args: safeParse(c.args) } satisfies LoopToolCall }\n }\n}\n\nfunction safeParse(s: string): Record<string, unknown> {\n if (!s.trim()) return {}\n try {\n const v = JSON.parse(s)\n return v && typeof v === 'object' && !Array.isArray(v) ? (v as Record<string, unknown>) : {}\n } catch {\n return {}\n }\n}\n\nexport interface OpenAICompatStreamTurnOptions {\n /** OpenAI-compat base URL (e.g. the Tangle Router `https://router.tangle.tools/v1`). */\n baseUrl: string\n apiKey: string\n model: string\n /** OpenAI tool definitions — pass `buildAppToolOpenAITools(taxonomy)` so the\n * model can call the app tools. Omit for a tool-free copilot. */\n tools?: unknown[]\n temperature?: number\n fetchImpl?: typeof fetch\n /** Extra body fields (e.g. `max_tokens`). */\n extraBody?: Record<string, unknown>\n}\n\n/**\n * Build a `streamTurn` that calls an OpenAI-compatible `/chat/completions`\n * endpoint (Tangle Router / tcloud / any compat provider) with `stream: true`\n * and yields `LoopEvent`s via {@link toLoopEvents}. Browser/edge/Node-safe —\n * just `fetch` + an SSE reader. Drop straight into `streamAppToolLoop`:\n *\n * const cfg = resolveTangleModelConfig() // or { baseUrl, apiKey, model }\n * streamAppToolLoop({ streamTurn: createOpenAICompatStreamTurn({ ...cfg, tools }), executeToolCall, ... })\n */\nexport function createOpenAICompatStreamTurn(\n opts: OpenAICompatStreamTurnOptions,\n): (messages: LoopMessage[]) => AsyncIterable<LoopEvent> {\n const base = opts.baseUrl.replace(/\\/+$/, '')\n const doFetch = opts.fetchImpl ?? fetch\n return (messages) =>\n toLoopEvents(\n streamChatCompletions(doFetch, `${base}/chat/completions`, opts.apiKey, {\n model: opts.model,\n messages,\n stream: true,\n stream_options: { include_usage: true },\n ...(opts.tools && opts.tools.length > 0 ? { tools: opts.tools } : {}),\n ...(opts.temperature != null ? { temperature: opts.temperature } : {}),\n ...opts.extraBody,\n }),\n )\n}\n\n/** Stream + parse an OpenAI-compat SSE response into chunks. Tolerates `data:`\n * framing, multi-line buffers, and the terminal `[DONE]`. */\nasync function* streamChatCompletions(\n doFetch: typeof fetch,\n url: string,\n apiKey: string,\n body: Record<string, unknown>,\n): AsyncIterable<OpenAIStreamChunk> {\n const res = await doFetch(url, {\n method: 'POST',\n headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json', Accept: 'text/event-stream' },\n body: JSON.stringify(body),\n })\n if (!res.ok || !res.body) {\n const text = res.body ? await res.text().catch(() => '') : ''\n throw new Error(`OpenAI-compat stream failed (HTTP ${res.status})${text ? `: ${text.slice(0, 200)}` : ''}`)\n }\n const reader = res.body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n for (const line of lines) {\n const trimmed = line.trim()\n if (!trimmed.startsWith('data:')) continue\n const data = trimmed.slice(5).trim()\n if (data === '[DONE]') return\n try {\n yield JSON.parse(data) as OpenAIStreamChunk\n } catch {\n /* skip a partial/garbled SSE frame */\n }\n }\n }\n}\n","/**\n * The bounded agent tool-loop — owned by `@tangle-network/agent-runtime`.\n *\n * A model turn may emit tool calls (integration-hub actions, the app tools from\n * `../tools`, delegation). The loop streams a turn, collects the executable tool\n * calls, dispatches each, appends the results to history in OpenAI\n * function-calling shape, and re-runs so the model reads them — bounded by\n * `maxToolTurns`, a wall-clock `deadlineMs`, and a `maxCostUsd` budget.\n *\n * The history shape is the OpenAI function-calling contract: the assistant turn\n * that emitted tool calls is preserved as an `assistant` message carrying its\n * `tool_calls` array, and each result is its own `{ role: 'tool', tool_call_id,\n * content }` message keyed to the call. A strict model (Claude, and any\n * OpenAI-compatible provider that validates tool history) needs this to read its\n * own tool use back; folding results into a `user` message makes such models\n * re-issue the same call in a loop.\n *\n * The loop is substrate-owned (`runToolLoop` / `streamToolLoop`); the app\n * supplies `streamTurn` (wrapping its model endpoint) and `executeToolCall`\n * (routing to its integration + app-tool executors). The app-facing names below\n * are 1:1 aliases of the canonical symbols, kept so this package's consumers and\n * the in-package `createAgentRuntime` read against a single, stable vocabulary.\n *\n * This is the LEAF the runtime barrel and its children both import — keeping the\n * tool-loop vocabulary out of any import cycle. The barrel re-exports it.\n */\n\nexport {\n runToolLoop as runAppToolLoop,\n streamToolLoop as streamAppToolLoop,\n} from '@tangle-network/agent-runtime'\nexport type {\n ToolLoopCall as LoopToolCall,\n ToolLoopAssistantToolCall as LoopAssistantToolCall,\n ToolLoopMessage as LoopMessage,\n ToolLoopEvent,\n ToolLoopStopReason,\n ToolLoopResult,\n RunToolLoopOptions as AppToolLoopOptions,\n StreamToolLoopOptions as StreamAppToolLoopOptions,\n StreamToolLoopYield as StreamLoopYield,\n} from '@tangle-network/agent-runtime'\n\n/**\n * Events the app's OpenAI-compat stream adapter ({@link toLoopEvents}) yields.\n *\n * This is the app's own `Raw` event type for the streaming loop — the canonical\n * `streamToolLoop<Raw>` is generic over it. It widens the substrate's\n * tool-loop event with `reasoning` (DeepSeek/router `reasoning_content` /\n * `thinking` deltas, rendered as thinking sections) and `usage` (per-message\n * token accounting) — neither belongs in the substrate's loop contract, so they\n * stay here. The adapter maps each into the `streamTurn` seam; `text` and\n * `tool_call` drive the loop, `reasoning` / `usage` pass through to the UI.\n */\nexport type LoopEvent =\n | { type: 'text'; text: string }\n | { type: 'reasoning'; text: string }\n | { type: 'tool_call'; call: import('@tangle-network/agent-runtime').ToolLoopCall }\n | { type: 'usage'; usage: { promptTokens: number; completionTokens: number } }\n | { type: 'other'; event: unknown }\n","/**\n * `createAgentRuntime` — the in-process agent core, assembled.\n *\n * The bricks to run an agent turn WITHOUT a sandbox already exist in this\n * package, but a consumer must hand-wire five of them every time: resolve the\n * model config, build the OpenAI tool schemas from the taxonomy, build a\n * `streamTurn` over the model endpoint, build an `executeToolCall` over the\n * product's handlers, and drive `runAppToolLoop` / `streamAppToolLoop` with an\n * `isExecutableTool` predicate. That boilerplate is identical across every\n * sandbox-free surface (an edge/browser copilot, an eval harness, a Node CLI),\n * and getting it subtly wrong — e.g. NOT advertising the tools, so the model\n * never emits a `tool_call` and no side effect ever fires — is exactly the\n * failure that makes a tool-driven agent score zero off-sandbox.\n *\n * This factory bundles those five into one object configured for ONE agent:\n *\n * const runtime = createAgentRuntime({ model, taxonomy, handlers, systemPrompt })\n * const result = await runtime.run(userMessage, { ctx }) // awaitable\n * for await (const y of runtime.stream(userMessage, { ctx })) {…} // streaming\n *\n * The model is advertised the app tools (so it CAN call them); each call is\n * dispatched against the product's `handlers` (so the side effect is real); the\n * `onProduced` hook fires at the real side-effect site (so an eval/UI credits a\n * persisted proposal or artifact). Substrate-free: no `@tangle-network/sandbox`,\n * no Durable Object, no `@tangle-network/agent-runtime` import. The SAME core\n * the Cloudflare Worker runs, runnable anywhere a `fetch` to an OpenAI-compatible\n * endpoint works.\n *\n * Domain stays out: the proposal taxonomy, the handlers, and the system prompt\n * are all injected — the factory knows nothing about insurance, law, tax, etc.\n */\nimport {\n type AppToolHandlers,\n type AppToolContext,\n type AppToolOutcome,\n type AppToolProducedEvent,\n type AppToolTaxonomy,\n} from '../tools/types'\nimport { buildAppToolOpenAITools, isAppToolName } from '../tools/openai'\nimport { createAppToolRuntimeExecutor } from '../tools/runtime'\nimport {\n runAppToolLoop,\n streamAppToolLoop,\n type LoopEvent,\n type LoopMessage,\n type LoopToolCall,\n type StreamLoopYield,\n type ToolLoopEvent,\n type ToolLoopResult,\n} from './loop'\nimport { createOpenAICompatStreamTurn } from './openai-stream'\n\n/** OpenAI-compatible model endpoint (Tangle Router / tcloud / any compat\n * provider). Build from {@link resolveTangleModelConfig} or pass literals. */\nexport interface AgentRuntimeModelConfig {\n baseUrl: string\n apiKey: string\n model: string\n temperature?: number\n fetchImpl?: typeof fetch\n /** Extra request-body fields (e.g. `max_tokens`, a `reasoning` block). */\n extraBody?: Record<string, unknown>\n}\n\n/** The agent's resolved profile surfaces for one turn — the things a delivered\n * / certified `AgentProfile` can change. Profile-WIDE on purpose: certified\n * delivery folds prompt-surface + skills into `systemPrompt` AND can add\n * certified `tool` artifacts to `extraTools` (the model's advertised tools is\n * rebuilt when these change). MCP servers / memory / RAG that materialize as\n * files or servers deliver through the sandbox-provisioning seam, not here. */\nexport interface ResolvedAgentProfile {\n systemPrompt: string\n extraTools: unknown[]\n}\n\nexport interface CreateAgentRuntimeOptions {\n /** The model endpoint the turns stream from. */\n model: AgentRuntimeModelConfig\n /**\n * Optional transform applied to the resolved profile surfaces each turn —\n * the seam for certified-artifact delivery (`createCertifiedDelivery`). It is\n * profile-WIDE (not prompt-only): it returns the effective `systemPrompt` +\n * advertised `extraTools`. Kept generic + injected so this substrate-free core\n * never imports `@tangle-network/agent-runtime`. Fail-closed by contract: an\n * impl that can't reach the plane returns the base surfaces unchanged.\n */\n composeProfile?: (base: ResolvedAgentProfile) => ResolvedAgentProfile | Promise<ResolvedAgentProfile>\n /** The product's proposal taxonomy — advertises `submit_proposal`'s `type`\n * enum to the model and labels the regulated subset on the result. */\n taxonomy: AppToolTaxonomy\n /** Domain handlers persisting each tool to the product's store/vault. */\n handlers: AppToolHandlers\n /** Default agent identity / system prompt. A turn may override it. */\n systemPrompt: string\n /** Runaway-backstop cap. Default 200 — set far above any legitimate workflow.\n * For per-workflow limits use `deadlineMs` or `maxCostUsd` on the loop options. */\n maxToolTurns?: number\n /** Extra OpenAI tool definitions advertised ALONGSIDE the four app tools\n * (e.g. `integration_invoke`). Pair with {@link executeOtherTool}. */\n extraTools?: unknown[]\n /** Execute a tool that is NOT one of the four app tools (e.g. an integration\n * action). Only consulted for names {@link isOtherExecutableTool} accepts. */\n executeOtherTool?: (call: LoopToolCall, ctx: AppToolContext) => Promise<AppToolOutcome>\n /** Which non-app tool names are executable here. Required if {@link executeOtherTool} is set. */\n isOtherExecutableTool?: (toolName: string) => boolean\n}\n\nexport interface AgentTurnOptions {\n /** The trusted per-turn context (who/where the turn runs as). */\n ctx: AppToolContext\n /** Prior conversation turns, in order. */\n priorMessages?: Array<{ role: string; content: string }>\n /** Override the factory's default system prompt for this turn. */\n systemPrompt?: string\n /** Fires at the real side-effect site for each produced proposal/artifact. */\n onProduced?: (event: AppToolProducedEvent) => void\n}\n\nexport interface AgentRuntime {\n /** Run the bounded tool loop to completion; resolve with final text + every\n * executed tool outcome. */\n run(userMessage: string, turn: AgentTurnOptions): Promise<ToolLoopResult>\n /** Stream the bounded tool loop: yields each raw model event and each executed\n * tool result as it happens (for SSE re-emission + telemetry). */\n stream(userMessage: string, turn: AgentTurnOptions): AsyncGenerator<StreamLoopYield<LoopEvent>, void, unknown>\n}\n\n/**\n * Create an in-process agent runtime for one agent. See the module doc for the\n * full rationale; the short version: it advertises the app tools to the model,\n * dispatches each emitted call against `handlers`, and drives the bounded loop —\n * the whole agent core, sandbox-free.\n */\nexport function createAgentRuntime(opts: CreateAgentRuntimeOptions): AgentRuntime {\n if (opts.executeOtherTool && !opts.isOtherExecutableTool) {\n throw new Error('createAgentRuntime: isOtherExecutableTool is required when executeOtherTool is set')\n }\n\n // Tool schemas + the streamTurn are stable across turns — build once. The\n // model MUST be advertised the tools or it never emits a tool_call (the exact\n // failure that scores a tool-driven agent zero off-sandbox).\n const m = opts.model\n const buildStreamTurn = (extraTools: unknown[]) =>\n createOpenAICompatStreamTurn({\n baseUrl: m.baseUrl,\n apiKey: m.apiKey,\n model: m.model,\n tools: [...buildAppToolOpenAITools(opts.taxonomy), ...extraTools],\n temperature: m.temperature,\n fetchImpl: m.fetchImpl,\n extraBody: m.extraBody,\n })\n\n // The advertised tool set is stable across turns UNLESS a delivered profile\n // changes `extraTools` (certified-tool delivery, on the cache-refresh cadence\n // — not per turn). Memoize the streamTurn by the active extraTools identity so\n // it rebuilds only when the certified tools actually change.\n const baseExtraTools = opts.extraTools ?? []\n let activeExtraTools = baseExtraTools\n let activeStreamTurn = buildStreamTurn(baseExtraTools)\n const streamTurnFor = (extraTools: unknown[]) => {\n if (extraTools !== activeExtraTools) {\n activeExtraTools = extraTools\n activeStreamTurn = buildStreamTurn(extraTools)\n }\n return activeStreamTurn\n }\n\n // Resolve the per-turn profile surfaces, applying the optional profile\n // transform (certified-artifact delivery). Profile-wide: system prompt +\n // advertised tools.\n const resolveProfile = async (turn: AgentTurnOptions): Promise<ResolvedAgentProfile> => {\n const base: ResolvedAgentProfile = {\n systemPrompt: turn.systemPrompt ?? opts.systemPrompt,\n extraTools: baseExtraTools,\n }\n return opts.composeProfile ? opts.composeProfile(base) : base\n }\n\n const isExecutableTool = (name: string): boolean =>\n isAppToolName(name) || (opts.isOtherExecutableTool?.(name) ?? false)\n\n const buildExecutor = (turn: AgentTurnOptions) => {\n const appExecutor = createAppToolRuntimeExecutor({\n handlers: opts.handlers,\n taxonomy: opts.taxonomy,\n ctx: turn.ctx,\n onProduced: turn.onProduced,\n })\n return async (call: LoopToolCall): Promise<AppToolOutcome> => {\n if (isAppToolName(call.toolName)) return appExecutor({ toolName: call.toolName, args: call.args })\n if (opts.executeOtherTool && opts.isOtherExecutableTool?.(call.toolName)) {\n return opts.executeOtherTool(call, turn.ctx)\n }\n return { ok: false, code: 'unknown_tool', message: `No executor for tool: ${call.toolName}` }\n }\n }\n\n return {\n async run(userMessage, turn) {\n const profile = await resolveProfile(turn)\n return runAppToolLoop({\n systemPrompt: profile.systemPrompt,\n userMessage,\n priorMessages: turn.priorMessages,\n // The awaitable loop consumes only text + tool_call; the app's UI-only\n // reasoning/usage events ride the substrate's `other` channel.\n streamTurn: narrowToToolLoopEvents(streamTurnFor(profile.extraTools)),\n executeToolCall: buildExecutor(turn),\n isExecutableTool,\n maxToolTurns: opts.maxToolTurns,\n })\n },\n async *stream(userMessage, turn) {\n const profile = await resolveProfile(turn)\n yield* streamAppToolLoop<LoopEvent>({\n systemPrompt: profile.systemPrompt,\n userMessage,\n priorMessages: turn.priorMessages,\n streamTurn: streamTurnFor(profile.extraTools),\n extractText: (ev) => (ev.type === 'text' ? ev.text : ''),\n extractToolCall: (ev) => (ev.type === 'tool_call' ? ev.call : null),\n isExecutableTool,\n executeToolCall: buildExecutor(turn),\n maxToolTurns: opts.maxToolTurns,\n })\n },\n }\n}\n\n/**\n * Adapt the app's rich {@link LoopEvent} stream to the substrate awaitable\n * loop's `ToolLoopEvent` contract. The loop reads only `text` (accumulated into\n * the answer) and `tool_call` (dispatched); the app's UI-only `reasoning` /\n * `usage` events have no awaitable meaning, so they collapse onto the\n * substrate's `other` channel and are ignored by the loop.\n */\nfunction narrowToToolLoopEvents(\n streamTurn: (messages: LoopMessage[]) => AsyncIterable<LoopEvent>,\n): (messages: LoopMessage[]) => AsyncIterable<ToolLoopEvent> {\n return (messages) =>\n (async function* () {\n for await (const ev of streamTurn(messages)) {\n if (ev.type === 'text') yield { type: 'text', text: ev.text }\n else if (ev.type === 'tool_call') yield { type: 'tool_call', call: ev.call }\n else yield { type: 'other', event: ev }\n }\n })()\n}\n","/**\n * `createCertifiedDelivery` — the delivery truck for Tangle Intelligence.\n *\n * Pulls a tenant's CERTIFIED `AgentProfile` from the deployed plane\n * (`GET /v1/profiles/:target/composed`) and applies it to the agent's resolved\n * surfaces each turn, so an approved improvement reaches the running agent with\n * NO redeploy. This is the `composeProfile` transform `createAgentRuntime`\n * accepts — opt-in per product, fail-closed, cached + refreshed.\n *\n * Profile-WIDE by design (not prompt-only): the composed profile carries every\n * promoted artifact type keyed by kind. What's folded where:\n * - `prompt-surface` + `skill` → the system prompt (via `composeCertifiedPrompt`).\n * - `tool` artifacts that carry an OpenAI tool definition → `extraTools`\n * (advertised to the model; the matching executor is supplied by the product\n * via `executeOtherTool`). Until a `tool` artifact carries a runnable def,\n * it is surfaced (see `current()`) but not advertised — advertising a tool\n * with no executor would make the model call into a dead end.\n * - `mcp` / `memory` / `rag` artifacts materialize as servers/files and deliver\n * through the SANDBOX-provisioning seam, not this in-process one. The full\n * certified profile is exposed via `current()` so that seam can consume it.\n *\n * Substrate boundary: THIS module imports `@tangle-network/agent-runtime`; the\n * `createAgentRuntime` core does not (it only consumes the generic transform).\n */\n\nimport {\n composeCertifiedPrompt,\n type CertifiedProfile,\n pullCertified,\n} from '@tangle-network/agent-runtime/intelligence'\nimport type { ResolvedAgentProfile } from './agent'\n\nconst defaultRefreshMs = 300_000\n\nexport interface CertifiedDeliveryConfig {\n /** The tenant target whose certified artifacts to deliver (the agent id). */\n target: string\n /** Bearer for the plane. Reads `TANGLE_API_KEY` when omitted. */\n apiKey?: string\n /** Plane base URL. Reads `TANGLE_INTELLIGENCE_URL` then the public plane. */\n baseUrl?: string\n /** Min interval between certified-profile pulls. Default 5m. */\n refreshMs?: number\n /** fetch impl (tests / non-global-fetch runtimes). */\n fetchImpl?: typeof fetch\n}\n\nexport interface CertifiedDelivery {\n /** The `composeProfile` transform to pass to `createAgentRuntime`. Applies the\n * cached certified profile to the base surfaces; refreshes on the cadence. */\n composeProfile(base: ResolvedAgentProfile): Promise<ResolvedAgentProfile>\n /** Force a pull now (ignores the refresh window). Best-effort. */\n refresh(): Promise<void>\n /** The certified profile currently in effect (null = none promoted / pull\n * failed). Lets the sandbox-provisioning seam deliver the file/server\n * artifact types this in-process seam doesn't. */\n current(): CertifiedProfile | null\n}\n\n/**\n * Build a certified-delivery transform for one agent target. Fail-closed: a pull\n * error or 404 keeps the last-known certified profile (or null), and the agent\n * runs on its base surfaces — it never breaks because Intelligence is down.\n */\nexport function createCertifiedDelivery(config: CertifiedDeliveryConfig): CertifiedDelivery {\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(force = false): Promise<void> {\n if (!force && Date.now() - lastPullAt < refreshMs) return\n if (inflight) return inflight\n inflight = (async () => {\n const outcome = await pullCertified({\n target: config.target,\n apiKey: config.apiKey,\n baseUrl: config.baseUrl,\n fetchImpl: config.fetchImpl,\n })\n lastPullAt = Date.now()\n // Only replace on a real pull; a 404/error keeps the last-known profile.\n if (outcome.succeeded) certified = outcome.value\n })()\n try {\n await inflight\n } finally {\n inflight = null\n }\n }\n\n return {\n async composeProfile(base) {\n await refresh()\n return {\n // prompt-surface + skill fold into the system prompt.\n systemPrompt: composeCertifiedPrompt(base.systemPrompt, certified),\n // Certified `tool` artifacts deliver here once they carry a runnable\n // OpenAI def + the product wires the executor; until then pass through.\n extraTools: base.extraTools,\n }\n },\n refresh: () => refresh(true),\n current: () => certified,\n }\n}\n","/**\n * Surface-scoped profile overlay — the seam letting any product page (a\n * sequence editor, a brief composer, a dataset view) add MCP servers, a prompt\n * addendum, and permission tightening to the workspace agent profile for turns\n * initiated FROM that surface, without the chat orchestrator knowing any\n * surface's specifics. The orchestrator resolves `(kind, ctx)` through a\n * registry the REQUEST HANDLER constructs per request (construction is a Map\n * build — cheap) and merges the result into the base profile it was about to\n * send to the sandbox. Per-request construction is the trust mechanism, not an\n * optimization target: each `build()` closes over server-trusted request state\n * (env bindings, secrets, the AUTHENTICATED user/workspace), which on Workers\n * exists only per request — a startup-built registry would force identity\n * through the untrusted client `ctx`.\n *\n * SECURITY INVARIANT: the surface `kind` and the ids inside `ctx` arrive on\n * the client request and are pure ROUTING data — never trusted content, never\n * identity. Identity comes from the closure (see above). The registered\n * `build()` runs server-side only: it validates the routing ids against the\n * product's access control, then mints its own URLs and capability tokens from\n * server configuration (`buildHttpMcpServer` + `createCapabilityToken` in\n * ../tools). A client can therefore never inject an arbitrary MCP url, header,\n * or token into the agent profile: the overlay's `mcp` values are typed as\n * {@link SurfaceMcpServer} (= the server-built `AppToolMcpServer` entry shape),\n * and only build() constructs them.\n */\n\nimport type { AppToolMcpServer } from '../tools/mcp'\n\n/** Sandbox permission posture values, ranked deny > ask > allow for merging. */\nexport type SurfacePermissionValue = 'allow' | 'ask' | 'deny'\n\n/** The only MCP entry shape an overlay may carry: the server-built bridge\n * entry from ../tools/mcp (transport, url, headers, and capability token all\n * assembled server-side). The alias exists so overlay authors reach for the\n * builders in ../tools rather than hand-rolling `{ url: ctx.url }` shapes\n * that would let request data become a dialable endpoint. */\nexport type SurfaceMcpServer = AppToolMcpServer\n\n/** What one surface contributes to the agent profile for a single turn. */\nexport interface SurfaceOverlay {\n /** MCP servers to mount for this turn, keyed by tool-routing name. Names\n * must not collide with the base profile's — see {@link mergeSurfaceOverlay}. */\n mcp?: Record<string, SurfaceMcpServer>\n /** Appended to the base system-prompt addendum with a blank-line separator. */\n promptAddendum?: string\n /** Per-key posture the surface wants for its turns. Merging is monotone\n * fail-closed: the stricter of base/overlay wins, so a surface can tighten\n * the workspace posture but never relax it. */\n permissions?: Record<string, SurfacePermissionValue>\n}\n\n/**\n * One registered surface kind. `TCtx` is the shape build() expects — a CLAIM\n * about the client payload, not a guarantee: the registry hands build() the\n * request's `ctx` unvalidated, so build() must treat every field as an\n * untrusted id (resolve it through access control that throws on a bad or\n * foreign id) before minting anything from it.\n */\nexport interface SurfaceKindDefinition<TCtx> {\n kind: string\n build: (ctx: TCtx) => SurfaceOverlay | Promise<SurfaceOverlay>\n}\n\n/** The variance-erased form a registry accepts (`build` is contravariant in\n * `TCtx`, so every concrete definition is assignable to this). */\nexport type AnySurfaceKind = SurfaceKindDefinition<never>\n\n/**\n * Declare one surface kind. The `kind` string is the client-visible routing\n * key (e.g. `'sequences'`); `build` is the server-side factory that turns a\n * validated ctx into the overlay for one turn.\n */\nexport function defineSurfaceKind<TCtx>(opts: {\n kind: string\n build: (ctx: TCtx) => SurfaceOverlay | Promise<SurfaceOverlay>\n}): SurfaceKindDefinition<TCtx> {\n if (typeof opts.kind !== 'string' || opts.kind.length === 0 || /\\s/.test(opts.kind)) {\n throw new Error(`surface kind must be a non-empty string without whitespace (got ${JSON.stringify(opts.kind)})`)\n }\n if (typeof opts.build !== 'function') {\n throw new Error(`surface kind '${opts.kind}' requires a build function`)\n }\n return { kind: opts.kind, build: opts.build }\n}\n\nexport interface SurfaceRegistry {\n /** Build the overlay for one turn. Throws on an unknown kind — an unknown\n * surface is a routing bug (client and server registries drifted), and\n * silently returning an empty overlay would strip the surface's tools from\n * the turn with no signal anywhere. Build errors propagate unwrapped. */\n resolve(kind: string, ctx: unknown): Promise<SurfaceOverlay>\n}\n\n/**\n * Assemble the product's surface registry from its registered kinds. Duplicate\n * kinds throw at construction: two builders behind one routing key would make\n * the mounted toolset depend on registration order.\n */\nexport function createSurfaceRegistry(kinds: readonly AnySurfaceKind[]): SurfaceRegistry {\n const byKind = new Map<string, AnySurfaceKind>()\n for (const definition of kinds) {\n if (byKind.has(definition.kind)) {\n throw new Error(`duplicate surface kind '${definition.kind}' — each kind must be registered exactly once`)\n }\n byKind.set(definition.kind, definition)\n }\n\n return {\n async resolve(kind, ctx) {\n const definition = byKind.get(kind)\n if (!definition) {\n const known = [...byKind.keys()].join(', ') || '(none)'\n throw new Error(\n `unknown surface kind '${kind}' — registered kinds: ${known}. ` +\n 'An unknown surface is a routing bug: register the kind via defineSurfaceKind before clients can reference it.',\n )\n }\n // The trust boundary where static ctx typing ends: the request payload is\n // handed to build() as-is, and build() validates it (see SurfaceKindDefinition).\n const overlay = await definition.build(ctx as never)\n assertSurfaceOverlay(overlay, `surface kind '${kind}'`)\n return overlay\n },\n }\n}\n\n/** Base-profile slice the merge reads/writes. Real callers pass their full\n * profile object; every field outside this slice passes through untouched. */\nexport interface SurfaceMergeBase {\n mcp?: Record<string, unknown>\n systemPromptAddendum?: string\n permissions?: Record<string, SurfacePermissionValue>\n}\n\nconst PERMISSION_SEVERITY: Record<SurfacePermissionValue, number> = { allow: 0, ask: 1, deny: 2 }\n\n/**\n * Merge one surface overlay into a base profile, returning a new object\n * (the base is never mutated; untouched nested records are shared by\n * reference).\n *\n * - `mcp`: overlay servers are added under their own names. A name already\n * present on the base THROWS — a collision is two servers claiming one\n * routing name, and renaming either silently would corrupt tool routing for\n * whichever caller expected the original binding.\n * - `systemPromptAddendum`: the overlay's `promptAddendum` appends after a\n * blank-line separator (no separator when the base has no addendum).\n * - `permissions`: per key the STRICTER value wins (deny > ask > allow). A\n * surface can tighten the base posture for its turns; a base 'deny' survives\n * any overlay.\n */\nexport function mergeSurfaceOverlay<TBase extends SurfaceMergeBase>(\n base: TBase,\n overlay: SurfaceOverlay,\n): TBase & SurfaceMergeBase {\n assertSurfaceOverlay(overlay, 'surface overlay')\n const merged: SurfaceMergeBase = { ...base }\n\n if (overlay.mcp && Object.keys(overlay.mcp).length > 0) {\n const baseMcp = base.mcp ?? {}\n const collisions = Object.keys(overlay.mcp).filter((name) => name in baseMcp)\n if (collisions.length > 0) {\n throw new Error(\n `surface overlay MCP name collision: ${collisions.map((n) => `'${n}'`).join(', ')} already exist on the base profile. ` +\n 'Two servers cannot claim one name — give the surface server a distinct name.',\n )\n }\n merged.mcp = { ...baseMcp, ...overlay.mcp }\n }\n\n if (overlay.promptAddendum !== undefined) {\n merged.systemPromptAddendum = base.systemPromptAddendum\n ? `${base.systemPromptAddendum}\\n\\n${overlay.promptAddendum}`\n : overlay.promptAddendum\n }\n\n if (overlay.permissions && Object.keys(overlay.permissions).length > 0) {\n const permissions: Record<string, SurfacePermissionValue> = { ...(base.permissions ?? {}) }\n for (const [key, value] of Object.entries(overlay.permissions)) {\n const existing = permissions[key]\n permissions[key] =\n existing === undefined || PERMISSION_SEVERITY[value] > PERMISSION_SEVERITY[existing] ? value : existing\n }\n merged.permissions = permissions\n }\n\n // merged began as a shallow copy of base; only the three slice fields were\n // replaced, so the intersection type is the true shape.\n return merged as TBase & SurfaceMergeBase\n}\n\n/** Reject overlays a build() (or hand-rolled caller) malformed, with the exact\n * field named: a relative MCP url, a blank addendum, or an off-vocabulary\n * permission would otherwise surface only as an opaque sandbox failure. */\nfunction assertSurfaceOverlay(overlay: SurfaceOverlay, label: string): void {\n if (overlay.promptAddendum !== undefined) {\n if (typeof overlay.promptAddendum !== 'string' || overlay.promptAddendum.trim().length === 0) {\n throw new Error(`${label}: promptAddendum must be a non-blank string when provided`)\n }\n }\n if (overlay.mcp !== undefined) {\n for (const [name, server] of Object.entries(overlay.mcp)) {\n if (name.trim().length === 0) throw new Error(`${label}: MCP server names must be non-empty`)\n if (server.transport !== 'http') {\n throw new Error(`${label}: MCP server '${name}' must use transport 'http' (got ${JSON.stringify((server as { transport?: unknown }).transport)})`)\n }\n let parsed: URL\n try {\n parsed = new URL(server.url)\n } catch {\n throw new Error(`${label}: MCP server '${name}' url must be an absolute URL (got ${JSON.stringify(server.url)})`)\n }\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw new Error(`${label}: MCP server '${name}' url must be http(s) (got ${JSON.stringify(server.url)})`)\n }\n }\n }\n if (overlay.permissions !== undefined) {\n for (const [key, value] of Object.entries(overlay.permissions)) {\n if (!(value in PERMISSION_SEVERITY)) {\n throw new Error(`${label}: permission '${key}' must be 'allow' | 'ask' | 'deny' (got ${JSON.stringify(value)})`)\n }\n }\n }\n}\n"],"mappings":"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","names":[]}