Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions docs/api/agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -1568,7 +1568,9 @@ the call site.

> **createSurfaceImprovementAdapter**(`opts`): [`ImprovementAdapter`](analyst-loop.md#improvementadapter)\<[`SurfaceImprovementEdit`](#surfaceimprovementedit)\>

Defined in: [agent/improvement-adapter.ts:129](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/improvement-adapter.ts#L129)
Defined in: [agent/improvement-adapter.ts:130](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/improvement-adapter.ts#L130)

The substrate-default `ImprovementAdapter`: resolve each finding's subject to a real surface path, LLM-draft a unified-diff patch, then auto-apply or open a PR.

#### Parameters

Expand Down Expand Up @@ -1729,7 +1731,9 @@ it's the whole point.

> **validateSurfaces**(`surfaces`, `repoRoot`): readonly [`SurfaceValidationIssue`](#surfacevalidationissue)[]

Defined in: [agent/surfaces.ts:197](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L197)
Defined in: [agent/surfaces.ts:198](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L198)

Validate an `AgentSurfaces` map on disk — missing paths fail loud at `defineAgent` time instead of silently skipping self-improvement edits.

#### Parameters

Expand All @@ -1751,7 +1755,7 @@ readonly [`SurfaceValidationIssue`](#surfacevalidationissue)[]

> **renderSurfaceIssues**(`issues`, `repoRoot`): `string`

Defined in: [agent/surfaces.ts:245](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L245)
Defined in: [agent/surfaces.ts:246](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L246)

#### Parameters

Expand Down
2 changes: 1 addition & 1 deletion docs/api/analyst-loop.md
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,7 @@ Forwarded verbatim from `AnalystRegistry.runStream`.

> **iterationsToTraceStore**\<`Task`, `Output`\>(`iterations`, `budgets?`): `TraceAnalysisStore`

Defined in: [analyst-loop/iterations-to-trace-store.ts:213](https://github.com/tangle-network/agent-runtime/blob/main/src/analyst-loop/iterations-to-trace-store.ts#L213)
Defined in: [analyst-loop/iterations-to-trace-store.ts:214](https://github.com/tangle-network/agent-runtime/blob/main/src/analyst-loop/iterations-to-trace-store.ts#L214)

Build an in-memory `TraceAnalysisStore` over a loop round's iterations. Fail-loud on an
empty round — there is nothing for an analyst to read, and a silent empty store would
Expand Down
1,065 changes: 533 additions & 532 deletions docs/api/index.md

Large diffs are not rendered by default.

418 changes: 209 additions & 209 deletions docs/api/intelligence.md

Large diffs are not rendered by default.

1,140 changes: 571 additions & 569 deletions docs/api/mcp.md

Large diffs are not rendered by default.

627 changes: 106 additions & 521 deletions docs/api/primitive-catalog.md

Large diffs are not rendered by default.

286 changes: 144 additions & 142 deletions docs/api/profiles.md

Large diffs are not rendered by default.

1,712 changes: 878 additions & 834 deletions docs/api/runtime.md

Large diffs are not rendered by default.

58 changes: 56 additions & 2 deletions scripts/gen-primitive-catalog.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,21 @@
// Wired into `pnpm run docs:api` (runs after TypeDoc) and gated by
// scripts/check-docs-freshness.mjs (regenerates + diffs — a new live export absent from
// the committed catalog is a RED BUILD). Never hand-edit docs/api/primitive-catalog.md.
//
// Row policy — every VISIBLE table row must be informative:
// - Documented entries (any kind) get a table row.
// - Undocumented interface/type entries collapse into one per-section
// "Undocumented supporting types" paragraph (names stay backticked, so they remain
// greppable and the freshness gate still proves their existence).
// - Undocumented function/class/const entries keep a visible blank row AND are counted
// against `maxUndocumentedCallables` below — a RATCHET: the ceiling is the current
// count, so new callables must ship with a TSDoc summary and the number only falls.
// After backfilling summaries, lower the constant to the new count.
//
// TSDoc position rule the extractor imposes: the summary line goes BEFORE any block tag.
// A doc block whose first content line is `@experimental`/`@stable` reads as ALL tag
// content to the TS compiler — getDocumentationComment returns empty and the catalog row
// renders blank. Tags go at the END of the block.

import { existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
import { createRequire } from 'node:module'
Expand Down Expand Up @@ -249,6 +264,16 @@ const extracted = extractModules(allModules.map((m) => m.specifier))
const bySpecifier = new Map()
for (let i = 0; i < allModules.length; i++) bySpecifier.set(allModules[i].specifier, extracted[i])

// ─────────────────────────────────────────────────────────────────────────────
// Ratchet: undocumented callables may only DECREASE. Undocumented interface/type
// entries collapse out of the table (see renderSection), but a blank function/class/
// const row is a reach-for primitive with no summary — visible shame, capped here.
// The ceiling is the exact current count; when a backfill lowers the real number,
// lower the constant to match. Exceeding it (a new undocumented callable) exits 1.

const maxUndocumentedCallables = 108
const ratchetKinds = new Set(['function', 'class', 'const'])

// ─────────────────────────────────────────────────────────────────────────────
// Render.

Expand All @@ -265,6 +290,10 @@ function entriesFor(mod) {
function renderSection(mod, importLabel) {
const entries = entriesFor(mod)
if (!entries.length) return ''
// Undocumented interface/type entries collapse into a compact paragraph below the
// table; everything else (documented entries + undocumented callables) stays a row.
const collapsed = entries.filter((e) => !e.summary && (e.kind === 'interface' || e.kind === 'type'))
const rows = entries.filter((e) => !collapsed.includes(e))
const lines = [
`### ${mod.label}`,
'',
Expand All @@ -273,18 +302,42 @@ function renderSection(mod, importLabel) {
'| Symbol | Kind | Summary |',
'|---|---|---|',
]
for (const e of entries) {
for (const e of rows) {
lines.push(
`| \`${e.name}\` | ${e.kind} | ${e.summary || '_(no summary — add a TSDoc line at the declaration)_'} |`,
)
}
if (collapsed.length) {
lines.push('')
lines.push(
`**Undocumented supporting types** (add a TSDoc line at the declaration to earn a table row): ${collapsed
.map((e) => `\`${e.name}\``)
.join(', ')}.`,
)
}
lines.push('')
return lines.join('\n')
}

const importLabelOf = (basePackage, subpath) =>
subpath === '.' ? basePackage : `${basePackage}/${subpath.replace(/^\.\//, '')}`

const undocumentedCallables = []
for (const mod of allModules) {
for (const e of entriesFor(mod)) {
if (!e.summary && ratchetKinds.has(e.kind)) undocumentedCallables.push(`${e.name} (${e.kind}, ${mod.specifier})`)
}
}
if (undocumentedCallables.length > maxUndocumentedCallables) {
console.error(
`primitive-catalog: ${undocumentedCallables.length} undocumented function/class/const exports exceed the ` +
`ratchet ceiling of ${maxUndocumentedCallables}. Add a TSDoc summary line at each new declaration ` +
'(summary BEFORE any @tag — a tag-first block reads as blank). Undocumented callables:\n ' +
undocumentedCallables.join('\n '),
)
process.exit(1)
}

const out = []
out.push('<!--')
out.push(' GENERATED — do not edit. Run `pnpm run docs:api` to regenerate.')
Expand Down Expand Up @@ -345,5 +398,6 @@ const total =
console.error(
`primitive-catalog: wrote docs/api/primitive-catalog.md — ${ownModules.length} own subpaths + ` +
`${substrateModules.length} substrate surfaces, ${total} catalogued symbols ` +
`(agent-runtime@${pkg.version}, agent-eval@${substrateVersion}).`,
`(agent-runtime@${pkg.version}, agent-eval@${substrateVersion}); ` +
`${undocumentedCallables.length}/${maxUndocumentedCallables} undocumented callables (ratchet).`,
)
1 change: 1 addition & 0 deletions src/agent/improvement-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ const DEFAULT_CREATE_KINDS: ReadonlyArray<FindingSubject['kind']> = [
'new-tool',
]

/** The substrate-default `ImprovementAdapter`: resolve each finding's subject to a real surface path, LLM-draft a unified-diff patch, then auto-apply or open a PR. */
export function createSurfaceImprovementAdapter(
opts: CreateSurfaceImprovementAdapterOpts,
): ImprovementAdapter<SurfaceImprovementEdit> {
Expand Down
1 change: 1 addition & 0 deletions src/agent/surfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ export interface SurfaceValidationIssue {
reason: 'missing' | 'not-directory' | 'not-file'
}

/** Validate an `AgentSurfaces` map on disk — missing paths fail loud at `defineAgent` time instead of silently skipping self-improvement edits. */
export function validateSurfaces(
surfaces: AgentSurfaces,
repoRoot: string,
Expand Down
3 changes: 2 additions & 1 deletion src/analyst-loop/iterations-to-trace-store.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/**
* @experimental
*
* The read seam that closes the autonomous loop: project a round's `Iteration[]`
* (each carrying its raw `SandboxEvent[]`) into an in-memory `TraceAnalysisStore`, the
Expand All @@ -12,6 +11,8 @@
* steers on. Projection is best-effort over the FLAT SandboxEvent shape (no per-event
* lineage yet — that's the richer-trace gap); it never fabricates — an errored iteration
* surfaces a real ERROR span carrying the real message.
*
* @experimental
*/

import {
Expand Down
3 changes: 2 additions & 1 deletion src/audit/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/**
* @experimental
*
* `agent-runtime/src/audit` — pure I/O helpers for UI-audit workspaces.
*
Expand All @@ -8,6 +7,8 @@
* can persist a workspace, regardless of whether the findings came from
* the in-process auditor client, a sandbox-SDK harness, or a hand-curated
* import.
*
* @experimental
*/

export type {
Expand Down
3 changes: 2 additions & 1 deletion src/audit/issue-writer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/**
* @experimental
*
* UI-audit issue writer — pure I/O. Takes a workspace dir + `UiFinding[]`
* and emits:
Expand All @@ -14,6 +13,8 @@
* The writer is deterministic, idempotent for `appendFindings()`, and
* never invokes an LLM. It assigns the next monotonic id to a finding the
* caller did not pre-id.
*
* @experimental
*/

import { promises as fs } from 'node:fs'
Expand Down
6 changes: 4 additions & 2 deletions src/backends.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/**
* @stable
*
* Backend factories for `runAgentTaskStream`. Three shapes ship in core:
*
Expand All @@ -10,6 +9,8 @@
* Adapters stay thin: domain repos own auth, model selection, and the concrete
* tool surface. The factories handle session creation, stream normalization,
* and graceful end-of-stream signalling.
*
* @stable
*/

import { BackendTransportError } from './errors'
Expand Down Expand Up @@ -170,7 +171,6 @@ function sleep(ms: number, signal?: AbortSignal): Promise<void> {
}

/**
* @stable
*
* OpenAI-compat streaming backend. Routes `runAgentTaskStream` through any
* `POST /chat/completions` endpoint that speaks OpenAI's SSE protocol —
Expand Down Expand Up @@ -202,6 +202,8 @@ function sleep(ms: number, signal?: AbortSignal): Promise<void> {
* `final.error` onto their `RunRecord.error` — silently treating an empty
* `finalText` as "agent produced nothing" hides credit exhaustion, auth
* failure, and upstream outages.
*
* @stable
*/
export function createOpenAICompatibleBackend<
TInput extends AgentBackendInput = AgentBackendInput,
Expand Down
3 changes: 2 additions & 1 deletion src/conversation/call-policy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/**
* @stable
*
* Per-call resilience policy for participant backends: deadline, retry with
* backoff, and a circuit breaker. Each policy is applied *around* a single
Expand All @@ -11,6 +10,8 @@
* leaking sockets. Retries replay the same logical turn (same `turnId`) so
* any caching gateway can dedupe. Circuit breakers are *per participant*: A's
* failures don't open B's breaker.
*
* @stable
*/

/** Pure judgment of whether an error is worth retrying. Defaults: TimeoutError, AbortError, fetch-level network errors. */
Expand Down
3 changes: 2 additions & 1 deletion src/conversation/conversation-backend.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/**
* @stable
*
* Wrap a `Conversation` so it satisfies `AgentExecutionBackend`. The result is
* an addressable "single agent" whose internal behavior is an N-party
Expand All @@ -11,6 +10,8 @@
* callers see one `text_delta` per inner turn (the turn's full text), tagged
* with `[speaker] ` prefix so the outer transcript stays attributable. The
* conversation's `conversation_end` halt reason rides on a `final` event.
*
* @stable
*/

import { newRuntimeSession, nowIso } from '../sessions'
Expand Down
3 changes: 2 additions & 1 deletion src/conversation/define-conversation.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
/**
* @stable
*
* Declarative constructor for a multi-agent `Conversation`. Validates inputs
* fail-loud at definition time (duplicate participant names, alternate order
* with ≠2 participants, non-positive `maxTurns`) so misconfiguration is caught
* before `runConversation` is called and not buried inside a streaming run.
*
* @stable
*/

import { ValidationError } from '../errors'
Expand Down
3 changes: 2 additions & 1 deletion src/conversation/headers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/**
* @stable
*
* Cross-gateway forwarding headers — the wire-level contract that makes
* agent-to-agent communication composable across organizational boundaries.
Expand All @@ -13,6 +12,8 @@
* rules so both sides agree.
*
* Full protocol: `docs/agent-bus-protocol.md`.
*
* @stable
*/

/** Standard names — lowercased so Headers maps interop on every runtime. */
Expand Down
3 changes: 2 additions & 1 deletion src/conversation/journal-sql.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/**
* @stable
*
* Durable conversation journal backed by any SQL store. Adapter-agnostic by
* design: callers wire a `SqlAdapter` against their driver of choice (D1,
Expand Down Expand Up @@ -33,6 +32,8 @@
* }
* const journal = new SqlConversationJournal(pg)
* await journal.migrate()
*
* @stable
*/

import type { ConversationJournal, ConversationJournalEntry } from './journal'
Expand Down
3 changes: 2 additions & 1 deletion src/conversation/journal.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/**
* @stable
*
* Durable conversation transcript — survives a driver process crash mid-run.
* The runner journals every committed turn before yielding `turn_end`, so a
Expand All @@ -12,6 +11,8 @@
* is ~30 lines. The in-memory adapter is the default for tests and scratch.
* The file adapter (JSONL on disk) is the default-durable choice when no
* upstream store is wired.
*
* @stable
*/

import type { ConversationTurn, HaltReason } from './types'
Expand Down
4 changes: 3 additions & 1 deletion src/conversation/run-conversation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/**
* @stable
*
* Conversation orchestrator. Drives N participants in turn through their own
* `AgentExecutionBackend`s, aggregating per-turn text + usage, enforcing
Expand Down Expand Up @@ -27,6 +26,8 @@
* Credit cap is enforced *between turns*, not mid-stream: a turn that
* overshoots the cap completes, the cap then halts the conversation before
* the next turn.
*
* @stable
*/

import type { KnowledgeReadinessReport } from '@tangle-network/agent-eval'
Expand Down Expand Up @@ -79,6 +80,7 @@ export async function runConversation(
return result
}

/** Streaming conversation orchestrator: drives N participants in turn through their own backends, enforcing `maxTurns` / `maxCreditsCents` / `haltOn`, yielding per-event stream markers. */
export async function* runConversationStream(
conversation: Conversation,
options: RunConversationOptions,
Expand Down
3 changes: 2 additions & 1 deletion src/conversation/turn-id.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/**
* @stable
*
* Deterministic turn identifier. Stable across retries of the same logical
* turn so backends (and any caching gateway in between) can dedupe on it.
Expand All @@ -9,6 +8,8 @@
* Shape: `${runId}.t${index}.${speakerSlug}` — readable in logs, sortable by
* turn index, attributable to a speaker. Slugify keeps the speaker portion
* URL-safe so it can ride in HTTP headers without escaping.
*
* @stable
*/

export function turnId(runId: string, index: number, speaker: string): string {
Expand Down
3 changes: 2 additions & 1 deletion src/conversation/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/**
* @stable
*
* Public types for multi-agent conversations. A `Conversation` is two-or-more
* participants taking turns through their own `AgentExecutionBackend`s, driven
Expand All @@ -9,6 +8,8 @@
* in-process iterable, local cli-bridge, sandbox, router, or a remote
* agent-gateway — so the same `runConversation` call drives same-machine,
* same-cloud, and cross-cloud orchestration without code change.
*
* @stable
*/

import type { AgentExecutionBackend } from '../types'
Expand Down
3 changes: 2 additions & 1 deletion src/durable/spawn-journal.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/**
* @experimental
*
* Event-sourced spawn journal for the recursive execution atom (build steps 3 + 7).
*
Expand All @@ -17,6 +16,8 @@
* each settlement — NOT wall-clock. `replaySpawnTree` sorts strictly by `seq` before
* touching the blob store, so the order in which rehydration `get`s resolve can never
* reorder the replayed `Settled[]`; the result is identical regardless of blob latency.
*
* @experimental
*/

import { createHash } from 'node:crypto'
Expand Down
Loading
Loading