@retinue/agentkit 0.1.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.
- package/LICENSE +22 -0
- package/README.md +310 -0
- package/dist/adapters/bullmq/consumer.d.ts +33 -0
- package/dist/adapters/bullmq/consumer.js +41 -0
- package/dist/adapters/bullmq/dispatcher.d.ts +74 -0
- package/dist/adapters/bullmq/dispatcher.js +160 -0
- package/dist/adapters/bullmq/export.d.ts +31 -0
- package/dist/adapters/bullmq/export.js +53 -0
- package/dist/adapters/bullmq/extraction.d.ts +42 -0
- package/dist/adapters/bullmq/extraction.js +63 -0
- package/dist/adapters/bullmq/index.d.ts +13 -0
- package/dist/adapters/bullmq/index.js +13 -0
- package/dist/adapters/bullmq/lock.d.ts +77 -0
- package/dist/adapters/bullmq/lock.js +126 -0
- package/dist/adapters/bullmq/queue.d.ts +50 -0
- package/dist/adapters/bullmq/queue.js +81 -0
- package/dist/adapters/memory/artifact-exports.d.ts +11 -0
- package/dist/adapters/memory/artifact-exports.js +102 -0
- package/dist/adapters/memory/artifacts.d.ts +15 -0
- package/dist/adapters/memory/artifacts.js +134 -0
- package/dist/adapters/memory/blobs.d.ts +7 -0
- package/dist/adapters/memory/blobs.js +27 -0
- package/dist/adapters/memory/evaluation.d.ts +18 -0
- package/dist/adapters/memory/evaluation.js +148 -0
- package/dist/adapters/memory/files.d.ts +27 -0
- package/dist/adapters/memory/files.js +0 -0
- package/dist/adapters/memory/flows.d.ts +16 -0
- package/dist/adapters/memory/flows.js +117 -0
- package/dist/adapters/memory/hitl.d.ts +9 -0
- package/dist/adapters/memory/hitl.js +130 -0
- package/dist/adapters/memory/idempotency.d.ts +13 -0
- package/dist/adapters/memory/idempotency.js +32 -0
- package/dist/adapters/memory/index.d.ts +39 -0
- package/dist/adapters/memory/index.js +107 -0
- package/dist/adapters/memory/knowledge.d.ts +43 -0
- package/dist/adapters/memory/knowledge.js +248 -0
- package/dist/adapters/memory/mcp.d.ts +9 -0
- package/dist/adapters/memory/mcp.js +37 -0
- package/dist/adapters/memory/message-store.d.ts +17 -0
- package/dist/adapters/memory/message-store.js +70 -0
- package/dist/adapters/memory/principal-memory.d.ts +7 -0
- package/dist/adapters/memory/principal-memory.js +83 -0
- package/dist/adapters/memory/runtime.d.ts +29 -0
- package/dist/adapters/memory/runtime.js +0 -0
- package/dist/adapters/memory/sessions.d.ts +29 -0
- package/dist/adapters/memory/sessions.js +0 -0
- package/dist/adapters/memory/skills.d.ts +10 -0
- package/dist/adapters/memory/skills.js +41 -0
- package/dist/adapters/memory/thread-summary.d.ts +7 -0
- package/dist/adapters/memory/thread-summary.js +29 -0
- package/dist/adapters/memory/usage-limits.d.ts +13 -0
- package/dist/adapters/memory/usage-limits.js +72 -0
- package/dist/adapters/memory/usage.d.ts +16 -0
- package/dist/adapters/memory/usage.js +279 -0
- package/dist/adapters/otel/index.d.ts +111 -0
- package/dist/adapters/otel/index.js +133 -0
- package/dist/adapters/postgres/artifact-exports.d.ts +12 -0
- package/dist/adapters/postgres/artifact-exports.js +117 -0
- package/dist/adapters/postgres/artifacts.d.ts +16 -0
- package/dist/adapters/postgres/artifacts.js +172 -0
- package/dist/adapters/postgres/checkpoint-store.d.ts +16 -0
- package/dist/adapters/postgres/checkpoint-store.js +34 -0
- package/dist/adapters/postgres/config.d.ts +15 -0
- package/dist/adapters/postgres/config.js +187 -0
- package/dist/adapters/postgres/conversation-store.d.ts +4 -0
- package/dist/adapters/postgres/conversation-store.js +82 -0
- package/dist/adapters/postgres/evaluation.d.ts +17 -0
- package/dist/adapters/postgres/evaluation.js +193 -0
- package/dist/adapters/postgres/file-content.d.ts +30 -0
- package/dist/adapters/postgres/file-content.js +111 -0
- package/dist/adapters/postgres/files.d.ts +19 -0
- package/dist/adapters/postgres/files.js +209 -0
- package/dist/adapters/postgres/flows.d.ts +20 -0
- package/dist/adapters/postgres/flows.js +206 -0
- package/dist/adapters/postgres/hitl.d.ts +5 -0
- package/dist/adapters/postgres/hitl.js +247 -0
- package/dist/adapters/postgres/index.d.ts +35 -0
- package/dist/adapters/postgres/index.js +35 -0
- package/dist/adapters/postgres/knowledge.d.ts +48 -0
- package/dist/adapters/postgres/knowledge.js +255 -0
- package/dist/adapters/postgres/memory.d.ts +14 -0
- package/dist/adapters/postgres/memory.js +194 -0
- package/dist/adapters/postgres/message-store.d.ts +11 -0
- package/dist/adapters/postgres/message-store.js +145 -0
- package/dist/adapters/postgres/migrations.d.ts +69 -0
- package/dist/adapters/postgres/migrations.js +1594 -0
- package/dist/adapters/postgres/pg-executor.d.ts +19 -0
- package/dist/adapters/postgres/pg-executor.js +32 -0
- package/dist/adapters/postgres/retention.d.ts +26 -0
- package/dist/adapters/postgres/retention.js +59 -0
- package/dist/adapters/postgres/rollups.d.ts +17 -0
- package/dist/adapters/postgres/rollups.js +267 -0
- package/dist/adapters/postgres/run-coordinator.d.ts +5 -0
- package/dist/adapters/postgres/run-coordinator.js +98 -0
- package/dist/adapters/postgres/run-event-log.d.ts +26 -0
- package/dist/adapters/postgres/run-event-log.js +30 -0
- package/dist/adapters/postgres/run-store.d.ts +4 -0
- package/dist/adapters/postgres/run-store.js +199 -0
- package/dist/adapters/postgres/schema.d.ts +39 -0
- package/dist/adapters/postgres/schema.js +70 -0
- package/dist/adapters/postgres/session-state.d.ts +7 -0
- package/dist/adapters/postgres/session-state.js +99 -0
- package/dist/adapters/postgres/sql.d.ts +8 -0
- package/dist/adapters/postgres/sql.js +2 -0
- package/dist/adapters/postgres/transaction.d.ts +37 -0
- package/dist/adapters/postgres/transaction.js +93 -0
- package/dist/adapters/postgres/unit-of-work.d.ts +18 -0
- package/dist/adapters/postgres/unit-of-work.js +8 -0
- package/dist/adapters/postgres/usage-limits.d.ts +15 -0
- package/dist/adapters/postgres/usage-limits.js +136 -0
- package/dist/adapters/postgres/usage.d.ts +15 -0
- package/dist/adapters/postgres/usage.js +226 -0
- package/dist/adapters/redis/index.d.ts +9 -0
- package/dist/adapters/redis/index.js +9 -0
- package/dist/adapters/redis/realtime.d.ts +74 -0
- package/dist/adapters/redis/realtime.js +112 -0
- package/dist/adapters/supabase/index.d.ts +88 -0
- package/dist/adapters/supabase/index.js +84 -0
- package/dist/adapters/supabase/realtime.d.ts +30 -0
- package/dist/adapters/supabase/realtime.js +53 -0
- package/dist/adapters/supabase/rls.d.ts +99 -0
- package/dist/adapters/supabase/rls.js +216 -0
- package/dist/adapters/supabase/storage.d.ts +50 -0
- package/dist/adapters/supabase/storage.js +207 -0
- package/dist/agents/agent.d.ts +66 -0
- package/dist/agents/agent.js +209 -0
- package/dist/agents/define.d.ts +21 -0
- package/dist/agents/define.js +63 -0
- package/dist/agents/engine.d.ts +98 -0
- package/dist/agents/engine.js +462 -0
- package/dist/agents/index.d.ts +50 -0
- package/dist/agents/index.js +17 -0
- package/dist/artifacts/index.d.ts +114 -0
- package/dist/artifacts/index.js +219 -0
- package/dist/authorization/index.d.ts +76 -0
- package/dist/authorization/index.js +76 -0
- package/dist/capabilities/index.d.ts +120 -0
- package/dist/capabilities/index.js +167 -0
- package/dist/capabilities/runtime.d.ts +89 -0
- package/dist/capabilities/runtime.js +84 -0
- package/dist/citations/index.d.ts +161 -0
- package/dist/citations/index.js +182 -0
- package/dist/context/assembler.d.ts +82 -0
- package/dist/context/assembler.js +129 -0
- package/dist/context/compaction.d.ts +45 -0
- package/dist/context/compaction.js +55 -0
- package/dist/context/index.d.ts +75 -0
- package/dist/context/index.js +17 -0
- package/dist/core/content-parts.d.ts +194 -0
- package/dist/core/content-parts.js +23 -0
- package/dist/core/context.d.ts +51 -0
- package/dist/core/context.js +9 -0
- package/dist/core/env.d.ts +25 -0
- package/dist/core/env.js +41 -0
- package/dist/core/errors.d.ts +30 -0
- package/dist/core/errors.js +65 -0
- package/dist/core/events.d.ts +139 -0
- package/dist/core/events.js +99 -0
- package/dist/core/ids.d.ts +52 -0
- package/dist/core/ids.js +13 -0
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.js +9 -0
- package/dist/core/tokens.d.ts +22 -0
- package/dist/core/tokens.js +22 -0
- package/dist/core/validation.d.ts +34 -0
- package/dist/core/validation.js +176 -0
- package/dist/documents/extraction.d.ts +121 -0
- package/dist/documents/extraction.js +293 -0
- package/dist/documents/index.d.ts +199 -0
- package/dist/documents/index.js +65 -0
- package/dist/documents/parsers/pdf.d.ts +47 -0
- package/dist/documents/parsers/pdf.js +508 -0
- package/dist/documents/parsers/text.d.ts +59 -0
- package/dist/documents/parsers/text.js +325 -0
- package/dist/documents/read-tool.d.ts +52 -0
- package/dist/documents/read-tool.js +109 -0
- package/dist/documents/render.d.ts +29 -0
- package/dist/documents/render.js +59 -0
- package/dist/documents/vision.d.ts +159 -0
- package/dist/documents/vision.js +214 -0
- package/dist/entries/adapters-bullmq.d.ts +8 -0
- package/dist/entries/adapters-bullmq.js +8 -0
- package/dist/entries/adapters-otel.d.ts +13 -0
- package/dist/entries/adapters-otel.js +13 -0
- package/dist/entries/adapters-postgres.d.ts +10 -0
- package/dist/entries/adapters-postgres.js +10 -0
- package/dist/entries/adapters-redis.d.ts +3 -0
- package/dist/entries/adapters-redis.js +3 -0
- package/dist/entries/context.d.ts +20 -0
- package/dist/entries/context.js +20 -0
- package/dist/entries/flows.d.ts +15 -0
- package/dist/entries/flows.js +15 -0
- package/dist/entries/hitl.d.ts +10 -0
- package/dist/entries/hitl.js +10 -0
- package/dist/entries/knowledge.d.ts +18 -0
- package/dist/entries/knowledge.js +19 -0
- package/dist/entries/mcp.d.ts +10 -0
- package/dist/entries/mcp.js +10 -0
- package/dist/entries/observability.d.ts +14 -0
- package/dist/entries/observability.js +16 -0
- package/dist/entries/persistence.d.ts +11 -0
- package/dist/entries/persistence.js +11 -0
- package/dist/entries/providers.d.ts +14 -0
- package/dist/entries/providers.js +14 -0
- package/dist/entries/runtime.d.ts +13 -0
- package/dist/entries/runtime.js +13 -0
- package/dist/entries/server.d.ts +24 -0
- package/dist/entries/server.js +24 -0
- package/dist/entries/tools.d.ts +21 -0
- package/dist/entries/tools.js +21 -0
- package/dist/entries/usage.d.ts +10 -0
- package/dist/entries/usage.js +10 -0
- package/dist/evaluation/gate.d.ts +168 -0
- package/dist/evaluation/gate.js +180 -0
- package/dist/evaluation/graders.d.ts +125 -0
- package/dist/evaluation/graders.js +203 -0
- package/dist/evaluation/index.d.ts +120 -0
- package/dist/evaluation/index.js +183 -0
- package/dist/evaluation/judge.d.ts +75 -0
- package/dist/evaluation/judge.js +111 -0
- package/dist/export/index.d.ts +162 -0
- package/dist/export/index.js +363 -0
- package/dist/export/markdown.d.ts +19 -0
- package/dist/export/markdown.js +29 -0
- package/dist/export/pdf.d.ts +73 -0
- package/dist/export/pdf.js +407 -0
- package/dist/files/context.d.ts +97 -0
- package/dist/files/context.js +185 -0
- package/dist/files/index.d.ts +210 -0
- package/dist/files/index.js +338 -0
- package/dist/files/read-tool.d.ts +81 -0
- package/dist/files/read-tool.js +163 -0
- package/dist/files/turn-parts.d.ts +96 -0
- package/dist/files/turn-parts.js +171 -0
- package/dist/flows/index.d.ts +270 -0
- package/dist/flows/index.js +62 -0
- package/dist/flows/interpreter.d.ts +146 -0
- package/dist/flows/interpreter.js +426 -0
- package/dist/flows/runner.d.ts +145 -0
- package/dist/flows/runner.js +270 -0
- package/dist/graphql/index.d.ts +8 -0
- package/dist/graphql/index.js +8 -0
- package/dist/graphql/resolvers.d.ts +237 -0
- package/dist/graphql/resolvers.js +253 -0
- package/dist/graphql/schema.d.ts +11 -0
- package/dist/graphql/schema.js +258 -0
- package/dist/graphql/sse.d.ts +77 -0
- package/dist/graphql/sse.js +100 -0
- package/dist/hitl/approved-execution.d.ts +127 -0
- package/dist/hitl/approved-execution.js +177 -0
- package/dist/hitl/index.d.ts +79 -0
- package/dist/hitl/index.js +12 -0
- package/dist/hitl/service.d.ts +221 -0
- package/dist/hitl/service.js +268 -0
- package/dist/idempotency/index.d.ts +70 -0
- package/dist/idempotency/index.js +59 -0
- package/dist/index.d.ts +103 -0
- package/dist/index.js +60 -0
- package/dist/knowledge/chunking.d.ts +57 -0
- package/dist/knowledge/chunking.js +158 -0
- package/dist/knowledge/index.d.ts +119 -0
- package/dist/knowledge/index.js +166 -0
- package/dist/knowledge/retrieval.d.ts +146 -0
- package/dist/knowledge/retrieval.js +170 -0
- package/dist/loadtest/harness.d.ts +168 -0
- package/dist/loadtest/harness.js +507 -0
- package/dist/loadtest/index.d.ts +13 -0
- package/dist/loadtest/index.js +13 -0
- package/dist/loadtest/injection.d.ts +89 -0
- package/dist/loadtest/injection.js +147 -0
- package/dist/loadtest/metrics.d.ts +197 -0
- package/dist/loadtest/metrics.js +160 -0
- package/dist/loadtest/runbooks.d.ts +28 -0
- package/dist/loadtest/runbooks.js +159 -0
- package/dist/loadtest/scenario.d.ts +104 -0
- package/dist/loadtest/scenario.js +208 -0
- package/dist/mcp/egress.d.ts +53 -0
- package/dist/mcp/egress.js +115 -0
- package/dist/mcp/index.d.ts +93 -0
- package/dist/mcp/index.js +33 -0
- package/dist/mcp/provider.d.ts +62 -0
- package/dist/mcp/provider.js +0 -0
- package/dist/models/index.d.ts +98 -0
- package/dist/models/index.js +74 -0
- package/dist/models/pricing.d.ts +24 -0
- package/dist/models/pricing.js +37 -0
- package/dist/models/provider-factory.d.ts +31 -0
- package/dist/models/provider-factory.js +67 -0
- package/dist/models/streaming.d.ts +145 -0
- package/dist/models/streaming.js +272 -0
- package/dist/models/vision.d.ts +38 -0
- package/dist/models/vision.js +62 -0
- package/dist/persistence/index.d.ts +1654 -0
- package/dist/persistence/index.js +226 -0
- package/dist/principal-memory/index.d.ts +106 -0
- package/dist/principal-memory/index.js +89 -0
- package/dist/retention/index.d.ts +89 -0
- package/dist/retention/index.js +70 -0
- package/dist/runtime/checkpoint.d.ts +37 -0
- package/dist/runtime/checkpoint.js +22 -0
- package/dist/runtime/index.d.ts +118 -0
- package/dist/runtime/index.js +69 -0
- package/dist/runtime/retry.d.ts +95 -0
- package/dist/runtime/retry.js +126 -0
- package/dist/runtime/serialization.d.ts +85 -0
- package/dist/runtime/serialization.js +95 -0
- package/dist/runtime/streaming.d.ts +54 -0
- package/dist/runtime/streaming.js +115 -0
- package/dist/runtime/worker.d.ts +130 -0
- package/dist/runtime/worker.js +405 -0
- package/dist/security/checklist.d.ts +53 -0
- package/dist/security/checklist.js +204 -0
- package/dist/security/findings.d.ts +56 -0
- package/dist/security/findings.js +168 -0
- package/dist/security/index.d.ts +14 -0
- package/dist/security/index.js +14 -0
- package/dist/security/prompt-safety.d.ts +100 -0
- package/dist/security/prompt-safety.js +133 -0
- package/dist/server/boot.d.ts +32 -0
- package/dist/server/boot.js +36 -0
- package/dist/server/cli-worker.d.ts +37 -0
- package/dist/server/cli-worker.js +151 -0
- package/dist/server/cli.d.ts +27 -0
- package/dist/server/cli.js +74 -0
- package/dist/server/config.d.ts +42 -0
- package/dist/server/config.js +127 -0
- package/dist/server/health.d.ts +59 -0
- package/dist/server/health.js +90 -0
- package/dist/server/host.d.ts +39 -0
- package/dist/server/host.js +124 -0
- package/dist/server/index.d.ts +15 -0
- package/dist/server/index.js +15 -0
- package/dist/server/main.d.ts +16 -0
- package/dist/server/main.js +31 -0
- package/dist/server/sse-route.d.ts +21 -0
- package/dist/server/sse-route.js +282 -0
- package/dist/skills/index.d.ts +67 -0
- package/dist/skills/index.js +31 -0
- package/dist/skills/resolver.d.ts +54 -0
- package/dist/skills/resolver.js +121 -0
- package/dist/teams/index.d.ts +93 -0
- package/dist/teams/index.js +207 -0
- package/dist/telemetry/index.d.ts +157 -0
- package/dist/telemetry/index.js +71 -0
- package/dist/telemetry/instrument.d.ts +108 -0
- package/dist/telemetry/instrument.js +232 -0
- package/dist/telemetry/log-events.d.ts +17 -0
- package/dist/telemetry/log-events.js +58 -0
- package/dist/telemetry/metrics.d.ts +123 -0
- package/dist/telemetry/metrics.js +135 -0
- package/dist/telemetry/noop.d.ts +39 -0
- package/dist/telemetry/noop.js +143 -0
- package/dist/telemetry/redaction.d.ts +64 -0
- package/dist/telemetry/redaction.js +153 -0
- package/dist/telemetry/spans.d.ts +56 -0
- package/dist/telemetry/spans.js +78 -0
- package/dist/telemetry/trace-context.d.ts +55 -0
- package/dist/telemetry/trace-context.js +60 -0
- package/dist/toolkit/compute.d.ts +53 -0
- package/dist/toolkit/compute.js +152 -0
- package/dist/toolkit/data.d.ts +98 -0
- package/dist/toolkit/data.js +235 -0
- package/dist/toolkit/http.d.ts +113 -0
- package/dist/toolkit/http.js +205 -0
- package/dist/toolkit/index.d.ts +21 -0
- package/dist/toolkit/index.js +17 -0
- package/dist/toolkit/web.d.ts +107 -0
- package/dist/toolkit/web.js +147 -0
- package/dist/tools/define.d.ts +25 -0
- package/dist/tools/define.js +45 -0
- package/dist/tools/delegating.d.ts +132 -0
- package/dist/tools/delegating.js +211 -0
- package/dist/tools/index.d.ts +129 -0
- package/dist/tools/index.js +33 -0
- package/dist/tools/library/compute.d.ts +11 -0
- package/dist/tools/library/compute.js +46 -0
- package/dist/tools/library/data.d.ts +16 -0
- package/dist/tools/library/data.js +92 -0
- package/dist/tools/library/http.d.ts +28 -0
- package/dist/tools/library/http.js +71 -0
- package/dist/tools/library/index.d.ts +97 -0
- package/dist/tools/library/index.js +134 -0
- package/dist/tools/library/knowledge.d.ts +39 -0
- package/dist/tools/library/knowledge.js +58 -0
- package/dist/tools/library/web.d.ts +19 -0
- package/dist/tools/library/web.js +65 -0
- package/dist/tools/meta-tools.d.ts +19 -0
- package/dist/tools/meta-tools.js +36 -0
- package/dist/tools/registry.d.ts +146 -0
- package/dist/tools/registry.js +291 -0
- package/dist/usage/index.d.ts +105 -0
- package/dist/usage/index.js +20 -0
- package/dist/usage/quota.d.ts +258 -0
- package/dist/usage/quota.js +510 -0
- package/dist/usage/recorder.d.ts +29 -0
- package/dist/usage/recorder.js +96 -0
- package/dist/usage/rollups.d.ts +121 -0
- package/dist/usage/rollups.js +157 -0
- package/dist/worker/export.d.ts +57 -0
- package/dist/worker/export.js +81 -0
- package/dist/worker/extraction.d.ts +57 -0
- package/dist/worker/extraction.js +84 -0
- package/dist/worker/main.d.ts +103 -0
- package/dist/worker/main.js +159 -0
- package/package.json +187 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Teams — REQ-037 (#186).
|
|
3
|
+
*
|
|
4
|
+
* ## A team compiles to a flow
|
|
5
|
+
*
|
|
6
|
+
* There is no team interpreter. `compileTeam` turns a `TeamDefinition` into a `FlowDefinition`, and the flow
|
|
7
|
+
* interpreter runs it. That is the whole design, and it is what makes #186's acceptance criteria properties rather
|
|
8
|
+
* than features to add:
|
|
9
|
+
*
|
|
10
|
+
* - **AC-2, "the difference is a property of the team rather than two code paths"** — both processes compile to a
|
|
11
|
+
* flow. `sequential` produces a chain of agent steps; `manager-led` produces one agent step whose tools include
|
|
12
|
+
* a delegation tool. The interpreter does not know which it is running.
|
|
13
|
+
* - **AC-4, budgets compose** — a team's budget *is* the compiled flow's budget, checked by the same code that
|
|
14
|
+
* checks a flow's. A member cannot exceed the team's remaining budget because the check is on the execution's
|
|
15
|
+
* spend, and there is one execution.
|
|
16
|
+
* - **AC-5, bounded recursion** — `maxDepth` on the compiled flow, enforced by the interpreter. A → B → A
|
|
17
|
+
* terminates for the same reason a nested subflow does.
|
|
18
|
+
* - **AC-6, one run identity** — one `FlowExecution`, so one `runId`. Each member's steps are attributable inside
|
|
19
|
+
* it through `StepRecord.member`.
|
|
20
|
+
* - **AC-7, HITL inside a team** — a member's question parks the execution exactly as a flow's checkpoint does,
|
|
21
|
+
* because it *is* the same mechanism.
|
|
22
|
+
* - **AC-8, a member failing is modelled** — `onFailure` per step, chosen by the team.
|
|
23
|
+
*
|
|
24
|
+
* Writing a second interpreter would have meant a second answer to each of those, and the second answer is the one
|
|
25
|
+
* that gets a fix late.
|
|
26
|
+
*
|
|
27
|
+
* ## Manager-led is one agent turn with a delegation tool
|
|
28
|
+
*
|
|
29
|
+
* The obvious design is a loop: ask the manager who is next, run them, ask again. The better one is to give the
|
|
30
|
+
* manager a *tool* that runs a member, and let the engine's existing turn loop do the iterating — because #186
|
|
31
|
+
* AC-3 asks that "delegation is a tool call, so it inherits authorization, approval, idempotency and accounting
|
|
32
|
+
* unchanged", and the way to inherit those unchanged is to be a tool call rather than to resemble one.
|
|
33
|
+
*
|
|
34
|
+
* So a delegation is a real entry in the registry. It is authorised like any tool, its result is recorded like any
|
|
35
|
+
* tool's, its cost lands on the run like any tool's, and a retry deduplicates like any tool's.
|
|
36
|
+
*/
|
|
37
|
+
import { AgentPlatformError } from "../core/errors.js";
|
|
38
|
+
import { DEFAULT_MAX_DEPTH } from "../flows/index.js";
|
|
39
|
+
export const DEFAULT_DELEGATION_DEPTH = 3;
|
|
40
|
+
/**
|
|
41
|
+
* The tool a manager calls to hand work to a member.
|
|
42
|
+
*
|
|
43
|
+
* Named once, here, because three things have to agree on it: the compiled flow that puts it in the manager's
|
|
44
|
+
* tool set, the registry entry that implements it, and the guard that stops a member reaching it recursively.
|
|
45
|
+
*/
|
|
46
|
+
export const DELEGATE_TOOL = "delegate_to_member";
|
|
47
|
+
/**
|
|
48
|
+
* Is this team runnable at all?
|
|
49
|
+
*
|
|
50
|
+
* Checked before compiling rather than discovered while running, because every one of these produces a flow that
|
|
51
|
+
* fails at a step rather than a definition that fails to load — and a definition that only fails once someone
|
|
52
|
+
* triggers it is a definition that fails in front of a customer.
|
|
53
|
+
*/
|
|
54
|
+
export const validateTeam = (team) => {
|
|
55
|
+
const problems = [];
|
|
56
|
+
const at = (problem) => problems.push({ team: team.id, problem });
|
|
57
|
+
if (team.members.length === 0)
|
|
58
|
+
at("has no members");
|
|
59
|
+
const names = new Set();
|
|
60
|
+
for (const member of team.members) {
|
|
61
|
+
if (member.name.trim() === "")
|
|
62
|
+
at("has a member with no name");
|
|
63
|
+
if (names.has(member.name))
|
|
64
|
+
at(`has two members named "${member.name}" — a delegation could not say which`);
|
|
65
|
+
names.add(member.name);
|
|
66
|
+
}
|
|
67
|
+
if (team.process === "manager-led") {
|
|
68
|
+
if (team.manager === undefined)
|
|
69
|
+
at("is manager-led with no manager named");
|
|
70
|
+
else if (!names.has(team.manager))
|
|
71
|
+
at(`names "${team.manager}" as manager, which is not one of its members`);
|
|
72
|
+
}
|
|
73
|
+
else if (team.manager !== undefined) {
|
|
74
|
+
// A sequential team with a manager is ambiguous: does the manager run first, last, or not at all? Refusing is
|
|
75
|
+
// better than picking one and being right a third of the time.
|
|
76
|
+
at("is sequential but names a manager — a sequential team has no manager to obey");
|
|
77
|
+
}
|
|
78
|
+
if (team.budget.maxSteps < team.members.length && team.process === "sequential") {
|
|
79
|
+
// A sequential team whose budget cannot reach its last member is a team that always fails at the same place,
|
|
80
|
+
// and the failure would read as a runtime problem rather than a definition one.
|
|
81
|
+
at(`has ${team.members.length} members and a budget of ${team.budget.maxSteps} steps, so its last member can never run`);
|
|
82
|
+
}
|
|
83
|
+
return problems;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Turn a team into the flow that runs it.
|
|
87
|
+
*
|
|
88
|
+
* Pure, so a team's shape can be asserted without executing anything — which matters more than usual here,
|
|
89
|
+
* because the interesting claims are about the *graph* ("a member cannot outspend the team", "delegation is a
|
|
90
|
+
* tool") rather than about behaviour at a step.
|
|
91
|
+
*/
|
|
92
|
+
export const compileTeam = (team) => {
|
|
93
|
+
const problems = validateTeam(team);
|
|
94
|
+
if (problems.length > 0) {
|
|
95
|
+
throw new AgentPlatformError({
|
|
96
|
+
code: "invalid_input",
|
|
97
|
+
message: `team ${team.id} cannot be compiled: ${problems.map((p) => p.problem).join("; ")}`,
|
|
98
|
+
retryable: false,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
const steps = team.process === "sequential" ? sequentialSteps(team) : managerLedSteps(team);
|
|
102
|
+
return {
|
|
103
|
+
id: `team:${team.id}`,
|
|
104
|
+
version: team.version,
|
|
105
|
+
name: team.name,
|
|
106
|
+
description: `Compiled from team ${team.id} (${team.process})`,
|
|
107
|
+
steps,
|
|
108
|
+
start: steps[0].name,
|
|
109
|
+
// The team's budget *is* the flow's. One budget, checked by one piece of code — so "a member cannot exceed
|
|
110
|
+
// the team's remaining budget" needs no separate enforcement.
|
|
111
|
+
budget: team.budget,
|
|
112
|
+
maxDepth: team.maxDelegationDepth ?? DEFAULT_DELEGATION_DEPTH,
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* Each member in turn, each reading the previous one's output.
|
|
117
|
+
*
|
|
118
|
+
* `assignTo` is the member's name, so a later member's prompt can reference `{{$.researcher}}` — which is how one
|
|
119
|
+
* agent's output becomes another's input "inside a single unit of work", and it is readable in the stored state
|
|
120
|
+
* rather than threaded through a closure nobody can inspect.
|
|
121
|
+
*/
|
|
122
|
+
const sequentialSteps = (team) => {
|
|
123
|
+
const steps = team.members.map((member, index) => {
|
|
124
|
+
const next = index + 1 < team.members.length ? team.members[index + 1].name : "team:done";
|
|
125
|
+
return {
|
|
126
|
+
name: member.name,
|
|
127
|
+
kind: "agent",
|
|
128
|
+
agentId: member.agentId,
|
|
129
|
+
...(member.instructions === undefined ? {} : { instructions: member.instructions }),
|
|
130
|
+
/**
|
|
131
|
+
* The task, plus what came before.
|
|
132
|
+
*
|
|
133
|
+
* The first member sees the team's brief; every later one sees the brief *and* the previous member's output.
|
|
134
|
+
* Passing only the previous output would lose the original request by the third member, which is the classic
|
|
135
|
+
* way a chain of agents drifts off the question.
|
|
136
|
+
*/
|
|
137
|
+
prompt: index === 0
|
|
138
|
+
? "{{$.brief}}"
|
|
139
|
+
: `{{$.brief}}\n\nWhat ${team.members[index - 1].name} produced:\n{{$.${team.members[index - 1].name}}}`,
|
|
140
|
+
assignTo: member.name,
|
|
141
|
+
next,
|
|
142
|
+
};
|
|
143
|
+
});
|
|
144
|
+
steps.push({ name: "team:done", kind: "done" });
|
|
145
|
+
return steps;
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* One step: the manager, with a delegation tool.
|
|
149
|
+
*
|
|
150
|
+
* The engine's own turn loop does the iterating, bounded by the agent's execution limits — so there is no
|
|
151
|
+
* hand-written loop here to get wrong, and a delegation is a tool call rather than something shaped like one.
|
|
152
|
+
*/
|
|
153
|
+
const managerLedSteps = (team) => [
|
|
154
|
+
{
|
|
155
|
+
name: team.manager,
|
|
156
|
+
kind: "agent",
|
|
157
|
+
agentId: team.members.find((m) => m.name === team.manager).agentId,
|
|
158
|
+
instructions: managerInstructions(team),
|
|
159
|
+
prompt: "{{$.brief}}",
|
|
160
|
+
assignTo: "result",
|
|
161
|
+
next: "team:done",
|
|
162
|
+
},
|
|
163
|
+
{ name: "team:done", kind: "done" },
|
|
164
|
+
];
|
|
165
|
+
/**
|
|
166
|
+
* What the manager is told about its team.
|
|
167
|
+
*
|
|
168
|
+
* Generated from the definition rather than written by hand, because a manager whose instructions list a member
|
|
169
|
+
* the team no longer has will delegate to it and get a refusal it cannot act on — and that is a definition and a
|
|
170
|
+
* prompt disagreeing, which nothing would catch.
|
|
171
|
+
*/
|
|
172
|
+
export const managerInstructions = (team) => {
|
|
173
|
+
const others = team.members.filter((member) => member.name !== team.manager);
|
|
174
|
+
const roster = others.map((member) => `- ${member.name}: ${member.instructions ?? "no stated speciality"}`).join("\n");
|
|
175
|
+
return [
|
|
176
|
+
`You lead a team. Delegate work with the ${DELEGATE_TOOL} tool; do not do a member's work yourself when one of them is better placed.`,
|
|
177
|
+
"",
|
|
178
|
+
"Your team:",
|
|
179
|
+
roster,
|
|
180
|
+
"",
|
|
181
|
+
`Delegate one task at a time and read the result before deciding what is next. When the work is done, answer directly — do not delegate again to confirm.`,
|
|
182
|
+
].join("\n");
|
|
183
|
+
};
|
|
184
|
+
/**
|
|
185
|
+
* The tools a member may use.
|
|
186
|
+
*
|
|
187
|
+
* An **intersection**, never a union — #186 AC-3's second half: "a delegated agent cannot reach a tool the
|
|
188
|
+
* delegating one could not." A member's `tools` narrows; it cannot widen. Enforced where the set is built rather
|
|
189
|
+
* than checked afterwards, because a check afterwards is a check somebody can forget to call.
|
|
190
|
+
*
|
|
191
|
+
* A member that names a tool the delegating context does not have gets it silently dropped rather than an error:
|
|
192
|
+
* the team is still runnable, and the alternative is a whole team refusing to start because one member's list
|
|
193
|
+
* mentions something a particular caller's role happens to exclude — which would make a team's usability depend
|
|
194
|
+
* on who triggered it.
|
|
195
|
+
*/
|
|
196
|
+
export const memberTools = (input) => {
|
|
197
|
+
const available = new Set(input.available);
|
|
198
|
+
if (input.member.tools === undefined) {
|
|
199
|
+
// No narrowing stated: the member gets what the team has, minus the delegation tool — a member that could
|
|
200
|
+
// delegate would be a manager, and a member delegating back to the manager is the A → B → A this bounds.
|
|
201
|
+
return [...available].filter((tool) => tool !== DELEGATE_TOOL);
|
|
202
|
+
}
|
|
203
|
+
return input.member.tools.filter((tool) => available.has(tool) && tool !== DELEGATE_TOOL);
|
|
204
|
+
};
|
|
205
|
+
/** The brief a team execution starts from, under the key the compiled prompts read. */
|
|
206
|
+
export const teamBrief = (brief) => ({ brief });
|
|
207
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The telemetry port — REQ-033 (#143).
|
|
3
|
+
*
|
|
4
|
+
* A run crosses the API host, the queue and a worker. Without a correlated view, diagnosing a production issue
|
|
5
|
+
* means guessing, so this exists to make one user request one trace.
|
|
6
|
+
*
|
|
7
|
+
* **Ours, not a vendor's.** The port is our own types; `adapters/otel` binds them to OpenTelemetry. Nothing in
|
|
8
|
+
* `src/` outside that adapter imports an OTel package, and a boundary rule (R11) makes that a build failure
|
|
9
|
+
* rather than a convention — the same treatment R3 gives the AI SDK. "Vendor-neutral" is only true if it is
|
|
10
|
+
* enforced: a single convenience import of `@opentelemetry/api` in a hot path is how a platform acquires a
|
|
11
|
+
* vendor, and it is invisible in review.
|
|
12
|
+
*
|
|
13
|
+
* **Shaped for W3C trace context, because that is the interop surface.** The port's identifiers are trace ids,
|
|
14
|
+
* span ids and a `traceparent` string, which is what any collector understands. A bespoke correlation id would
|
|
15
|
+
* work exactly as well until a customer wanted their own tooling to see it.
|
|
16
|
+
*
|
|
17
|
+
* **Absence is a no-op, not a branch.** `NOOP_TELEMETRY` means no call site needs `if (telemetry)`, so an
|
|
18
|
+
* unconfigured deployment loses observability and nothing else. Optional-and-checked would eventually be
|
|
19
|
+
* checked in nineteen places and forgotten in the twentieth.
|
|
20
|
+
*/
|
|
21
|
+
export * from "./trace-context.js";
|
|
22
|
+
export * from "./log-events.js";
|
|
23
|
+
export * from "./redaction.js";
|
|
24
|
+
export * from "./spans.js";
|
|
25
|
+
export * from "./metrics.js";
|
|
26
|
+
export * from "./noop.js";
|
|
27
|
+
export * from "./instrument.js";
|
|
28
|
+
import type { LogEvent } from "./log-events.js";
|
|
29
|
+
import type { TraceFlags } from "./trace-context.js";
|
|
30
|
+
/**
|
|
31
|
+
* The identifiers on every log line and every span — AC-4.
|
|
32
|
+
*
|
|
33
|
+
* Every field is an id. That is the point: this type is what a caller is *allowed* to correlate on, and it
|
|
34
|
+
* contains no room for content. A telemetry context that carried a `message` or a `prompt` would be the
|
|
35
|
+
* redaction hole, and it would be added by someone who needed one line of context in one incident.
|
|
36
|
+
*/
|
|
37
|
+
export type TelemetryContext = {
|
|
38
|
+
readonly tenantId: string;
|
|
39
|
+
readonly conversationId?: string;
|
|
40
|
+
readonly runId?: string;
|
|
41
|
+
readonly principalId?: string;
|
|
42
|
+
/** The inbound request, so a trace can be tied back to an access log entry. */
|
|
43
|
+
readonly requestId?: string;
|
|
44
|
+
};
|
|
45
|
+
export declare const SPAN_KINDS: readonly ["server", "client", "producer", "consumer", "internal"];
|
|
46
|
+
export type SpanKind = (typeof SPAN_KINDS)[number];
|
|
47
|
+
/**
|
|
48
|
+
* A span attribute value.
|
|
49
|
+
*
|
|
50
|
+
* Primitives only, and deliberately not `unknown`. A nested object is where content hides: `{ input: {...} }`
|
|
51
|
+
* on a tool span is one keystroke from being the whole tool input, and no reviewer would notice. A caller that
|
|
52
|
+
* genuinely needs structure has to name each field, which is exactly the friction that keeps prompts out.
|
|
53
|
+
*/
|
|
54
|
+
export type AttributeValue = string | number | boolean;
|
|
55
|
+
export type Attributes = Readonly<Record<string, AttributeValue>>;
|
|
56
|
+
export type SpanStatus = "unset" | "ok" | "error";
|
|
57
|
+
export interface Span {
|
|
58
|
+
/** The span's own context, for propagation into a job payload or an outbound header. */
|
|
59
|
+
readonly context: SpanContext;
|
|
60
|
+
setAttributes(attributes: Attributes): void;
|
|
61
|
+
/**
|
|
62
|
+
* Record a failure on the span.
|
|
63
|
+
*
|
|
64
|
+
* Takes a **code and message**, not an error object. An error's `stack` and `cause` chain routinely carry a
|
|
65
|
+
* URL with a token in it or the argument that caused the throw — #131 found exactly that, a service-role key
|
|
66
|
+
* echoed into an error message and therefore into logs. So the span gets the classified code and a message
|
|
67
|
+
* the caller has taken responsibility for, and the object stays out.
|
|
68
|
+
*/
|
|
69
|
+
recordError(input: {
|
|
70
|
+
readonly code: string;
|
|
71
|
+
readonly message?: string;
|
|
72
|
+
}): void;
|
|
73
|
+
setStatus(status: SpanStatus): void;
|
|
74
|
+
end(): void;
|
|
75
|
+
}
|
|
76
|
+
export type SpanContext = {
|
|
77
|
+
readonly traceId: string;
|
|
78
|
+
readonly spanId: string;
|
|
79
|
+
readonly traceFlags: TraceFlags;
|
|
80
|
+
};
|
|
81
|
+
export type SpanOptions = {
|
|
82
|
+
readonly kind?: SpanKind;
|
|
83
|
+
readonly attributes?: Attributes;
|
|
84
|
+
/**
|
|
85
|
+
* The parent, as a `traceparent` string.
|
|
86
|
+
*
|
|
87
|
+
* A string rather than a span object, because the parent usually arrives *serialized* — out of a job payload
|
|
88
|
+
* or an HTTP header — and a port that took a live span would force every producer to keep one alive across a
|
|
89
|
+
* process boundary, which is the one thing it cannot do.
|
|
90
|
+
*/
|
|
91
|
+
readonly parent?: string;
|
|
92
|
+
};
|
|
93
|
+
export interface Tracer {
|
|
94
|
+
startSpan(name: string, options?: SpanOptions): Span;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Run `fn` inside a span, ending it on both paths and recording a failure.
|
|
98
|
+
*
|
|
99
|
+
* A helper rather than a method on the port, so an adapter cannot get the error path wrong. Every adapter
|
|
100
|
+
* getting `try/finally` right independently is a guarantee that holds until the second adapter.
|
|
101
|
+
*/
|
|
102
|
+
export declare const withSpan: <T>(tracer: Tracer, name: string, options: SpanOptions, fn: (span: Span) => Promise<T>) => Promise<T>;
|
|
103
|
+
/**
|
|
104
|
+
* A classified code for a thrown value, and nothing else.
|
|
105
|
+
*
|
|
106
|
+
* Reads `code` when the platform's own error carries one, and otherwise reports the constructor name. Never the
|
|
107
|
+
* message: this function's whole job is to be the place that refuses to pass one through.
|
|
108
|
+
*/
|
|
109
|
+
export declare const errorCodeOf: (error: unknown) => string;
|
|
110
|
+
export type MetricRecorder = {
|
|
111
|
+
record(value: number, attributes?: Attributes): void;
|
|
112
|
+
};
|
|
113
|
+
export interface Meter {
|
|
114
|
+
/** Monotonic count — requests, errors, runs. */
|
|
115
|
+
counter(name: string, options?: {
|
|
116
|
+
readonly unit?: string;
|
|
117
|
+
readonly description?: string;
|
|
118
|
+
}): MetricRecorder;
|
|
119
|
+
/** A distribution — latency, duration, wait time. Percentiles are the only useful form of these. */
|
|
120
|
+
histogram(name: string, options?: {
|
|
121
|
+
readonly unit?: string;
|
|
122
|
+
readonly description?: string;
|
|
123
|
+
}): MetricRecorder;
|
|
124
|
+
/** A point-in-time value — queue depth. Recorded, not accumulated. */
|
|
125
|
+
gauge(name: string, options?: {
|
|
126
|
+
readonly unit?: string;
|
|
127
|
+
readonly description?: string;
|
|
128
|
+
}): MetricRecorder;
|
|
129
|
+
}
|
|
130
|
+
export declare const LOG_LEVELS: readonly ["debug", "info", "warn", "error"];
|
|
131
|
+
export type LogLevel = (typeof LOG_LEVELS)[number];
|
|
132
|
+
/**
|
|
133
|
+
* A structured log line.
|
|
134
|
+
*
|
|
135
|
+
* `event` is a **closed union of literals**, not free text — see `log-events.ts`. That is the structural half
|
|
136
|
+
* of AC-5: a caller physically cannot put a prompt in the message, because the message is not a string it
|
|
137
|
+
* controls. The redaction allowlist then handles the fields. A denylist over free-text messages would be
|
|
138
|
+
* checking every line forever and losing the one added on a Friday.
|
|
139
|
+
*/
|
|
140
|
+
export type LogRecord = {
|
|
141
|
+
readonly level: LogLevel;
|
|
142
|
+
readonly event: LogEvent;
|
|
143
|
+
readonly context: TelemetryContext;
|
|
144
|
+
readonly fields: Readonly<Record<string, AttributeValue>>;
|
|
145
|
+
readonly at: string;
|
|
146
|
+
};
|
|
147
|
+
export interface Logger {
|
|
148
|
+
log(level: LogLevel, event: LogEvent, fields?: Readonly<Record<string, unknown>>): void;
|
|
149
|
+
/** A logger bound to more context. Correlation ids are set once at a boundary, not repeated per line. */
|
|
150
|
+
child(context: Partial<TelemetryContext>): Logger;
|
|
151
|
+
}
|
|
152
|
+
export type Telemetry = {
|
|
153
|
+
readonly tracer: Tracer;
|
|
154
|
+
readonly meter: Meter;
|
|
155
|
+
readonly logger: Logger;
|
|
156
|
+
};
|
|
157
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The telemetry port — REQ-033 (#143).
|
|
3
|
+
*
|
|
4
|
+
* A run crosses the API host, the queue and a worker. Without a correlated view, diagnosing a production issue
|
|
5
|
+
* means guessing, so this exists to make one user request one trace.
|
|
6
|
+
*
|
|
7
|
+
* **Ours, not a vendor's.** The port is our own types; `adapters/otel` binds them to OpenTelemetry. Nothing in
|
|
8
|
+
* `src/` outside that adapter imports an OTel package, and a boundary rule (R11) makes that a build failure
|
|
9
|
+
* rather than a convention — the same treatment R3 gives the AI SDK. "Vendor-neutral" is only true if it is
|
|
10
|
+
* enforced: a single convenience import of `@opentelemetry/api` in a hot path is how a platform acquires a
|
|
11
|
+
* vendor, and it is invisible in review.
|
|
12
|
+
*
|
|
13
|
+
* **Shaped for W3C trace context, because that is the interop surface.** The port's identifiers are trace ids,
|
|
14
|
+
* span ids and a `traceparent` string, which is what any collector understands. A bespoke correlation id would
|
|
15
|
+
* work exactly as well until a customer wanted their own tooling to see it.
|
|
16
|
+
*
|
|
17
|
+
* **Absence is a no-op, not a branch.** `NOOP_TELEMETRY` means no call site needs `if (telemetry)`, so an
|
|
18
|
+
* unconfigured deployment loses observability and nothing else. Optional-and-checked would eventually be
|
|
19
|
+
* checked in nineteen places and forgotten in the twentieth.
|
|
20
|
+
*/
|
|
21
|
+
export * from "./trace-context.js";
|
|
22
|
+
export * from "./log-events.js";
|
|
23
|
+
export * from "./redaction.js";
|
|
24
|
+
export * from "./spans.js";
|
|
25
|
+
export * from "./metrics.js";
|
|
26
|
+
export * from "./noop.js";
|
|
27
|
+
export * from "./instrument.js";
|
|
28
|
+
export const SPAN_KINDS = ["server", "client", "producer", "consumer", "internal"];
|
|
29
|
+
/**
|
|
30
|
+
* Run `fn` inside a span, ending it on both paths and recording a failure.
|
|
31
|
+
*
|
|
32
|
+
* A helper rather than a method on the port, so an adapter cannot get the error path wrong. Every adapter
|
|
33
|
+
* getting `try/finally` right independently is a guarantee that holds until the second adapter.
|
|
34
|
+
*/
|
|
35
|
+
export const withSpan = async (tracer, name, options, fn) => {
|
|
36
|
+
const span = tracer.startSpan(name, options);
|
|
37
|
+
try {
|
|
38
|
+
const result = await fn(span);
|
|
39
|
+
span.setStatus("ok");
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
// The code only. `String(error)` here would put the message on the span, and an error message is the most
|
|
44
|
+
// common accidental carrier of content — a rejected prompt, a failing SQL statement, a signed URL.
|
|
45
|
+
span.recordError({ code: errorCodeOf(error) });
|
|
46
|
+
span.setStatus("error");
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
span.end();
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* A classified code for a thrown value, and nothing else.
|
|
55
|
+
*
|
|
56
|
+
* Reads `code` when the platform's own error carries one, and otherwise reports the constructor name. Never the
|
|
57
|
+
* message: this function's whole job is to be the place that refuses to pass one through.
|
|
58
|
+
*/
|
|
59
|
+
export const errorCodeOf = (error) => {
|
|
60
|
+
if (typeof error === "object" && error !== null) {
|
|
61
|
+
const code = error.code;
|
|
62
|
+
if (typeof code === "string" && code.length > 0 && code.length <= 64)
|
|
63
|
+
return code;
|
|
64
|
+
const name = error.constructor?.name;
|
|
65
|
+
if (typeof name === "string" && name.length > 0)
|
|
66
|
+
return name;
|
|
67
|
+
}
|
|
68
|
+
return "unknown";
|
|
69
|
+
};
|
|
70
|
+
export const LOG_LEVELS = ["debug", "info", "warn", "error"];
|
|
71
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wiring telemetry to the boundaries — AC-1, AC-2, AC-3.
|
|
3
|
+
*
|
|
4
|
+
* The port is inert on its own. These are the wrappers that put it on the path a run actually takes, and they
|
|
5
|
+
* are **decorators over the existing seams** rather than edits inside them: `instrumentDispatcher` wraps a
|
|
6
|
+
* `JobDispatcher`, `instrumentConsumer` wraps a `JobConsumer`. Two reasons, and the second is the real one.
|
|
7
|
+
*
|
|
8
|
+
* The first is that a deployment without telemetry runs the undecorated object, so telemetry cannot be the
|
|
9
|
+
* reason a run fails.
|
|
10
|
+
*
|
|
11
|
+
* The second is that instrumentation *inside* the dispatcher would put a span around the enqueue and nothing
|
|
12
|
+
* around the wait between enqueue and claim — which is the number a user actually experiences. Wrapping both
|
|
13
|
+
* sides is what makes claim latency measurable at all.
|
|
14
|
+
*/
|
|
15
|
+
import type { JobDispatcher } from "../runtime/index.js";
|
|
16
|
+
import type { JobConsumer } from "../worker/main.js";
|
|
17
|
+
import { type RunMetrics } from "./metrics.js";
|
|
18
|
+
import { type Telemetry } from "./index.js";
|
|
19
|
+
/**
|
|
20
|
+
* What a job carries so the worker can continue the trace — AC-1.
|
|
21
|
+
*
|
|
22
|
+
* `traceparent` is **optional**, and that is a compatibility decision rather than laziness: jobs enqueued before
|
|
23
|
+
* this landed are already on the queue, and a worker that required the field would fail every one of them. A job
|
|
24
|
+
* without it starts a new trace, which is a missing link in one trace rather than a lost run.
|
|
25
|
+
*
|
|
26
|
+
* `enqueuedAt` rides along for the same reason claim latency cannot be measured on one side: the worker needs to
|
|
27
|
+
* know when the producer let go. Taken from the producer's clock, so the number is only as good as clock skew
|
|
28
|
+
* between the two hosts — stated because a negative claim latency in a dashboard is otherwise a mystery.
|
|
29
|
+
*/
|
|
30
|
+
export type TracedJob = {
|
|
31
|
+
readonly traceparent?: string;
|
|
32
|
+
readonly enqueuedAt?: string;
|
|
33
|
+
};
|
|
34
|
+
export type InstrumentedDispatcherDeps = {
|
|
35
|
+
readonly telemetry: Telemetry;
|
|
36
|
+
readonly metrics?: RunMetrics;
|
|
37
|
+
/** Injected so a test can pin it; also what makes claim latency assertable without waiting. */
|
|
38
|
+
readonly now?: () => number;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Wrap a dispatcher so the enqueue is a span and the job carries the trace forward.
|
|
42
|
+
*
|
|
43
|
+
* The traceparent goes down through `enqueueRun`, which #143 widened to accept it. The first version of this
|
|
44
|
+
* remembered the span it had just opened and let the adapter read it back — which is wrong the moment two
|
|
45
|
+
* enqueues overlap, and overlapping enqueues are the normal case, not the edge one. A racy trace link is worse
|
|
46
|
+
* than none: it attributes one tenant's run to another tenant's request.
|
|
47
|
+
*/
|
|
48
|
+
export declare const instrumentDispatcher: (inner: JobDispatcher, deps: InstrumentedDispatcherDeps) => JobDispatcher;
|
|
49
|
+
export type InstrumentedConsumerDeps = InstrumentedDispatcherDeps & {
|
|
50
|
+
/** Which worker process this is. On a log line, so a stuck instance is identifiable. */
|
|
51
|
+
readonly workerId?: string;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Wrap a consumer so each job continues its producer's trace and claim latency is recorded.
|
|
55
|
+
*
|
|
56
|
+
* The handler runs *inside* the claim span, so everything the run does — model calls, tool calls, an approval
|
|
57
|
+
* wait — is a descendant of it and of the original request. That is AC-1: one user request, one trace, across
|
|
58
|
+
* three processes.
|
|
59
|
+
*/
|
|
60
|
+
export declare const instrumentConsumer: (inner: JobConsumer, deps: InstrumentedConsumerDeps) => JobConsumer;
|
|
61
|
+
/**
|
|
62
|
+
* Time a model call — latency, outcome and the model, with no prompt anywhere near it.
|
|
63
|
+
*
|
|
64
|
+
* The attributes are the model id and the outcome. Not the prompt, not the response, not the token *contents* —
|
|
65
|
+
* the counts are on the usage ledger, which is the place designed to hold them and which is tenant-scoped.
|
|
66
|
+
*/
|
|
67
|
+
export declare const instrumentModelCall: <T>(deps: {
|
|
68
|
+
readonly telemetry: Telemetry;
|
|
69
|
+
readonly metrics: RunMetrics;
|
|
70
|
+
readonly now?: () => number;
|
|
71
|
+
}, input: {
|
|
72
|
+
readonly tenantId: string;
|
|
73
|
+
readonly runId?: string;
|
|
74
|
+
readonly modelId: string;
|
|
75
|
+
readonly providerId?: string;
|
|
76
|
+
}, call: () => Promise<T>) => Promise<T>;
|
|
77
|
+
/** Time a tool call. Same shape, and the same deliberate absence of arguments and results. */
|
|
78
|
+
export declare const instrumentToolCall: <T>(deps: {
|
|
79
|
+
readonly telemetry: Telemetry;
|
|
80
|
+
readonly metrics: RunMetrics;
|
|
81
|
+
readonly now?: () => number;
|
|
82
|
+
}, input: {
|
|
83
|
+
readonly tenantId: string;
|
|
84
|
+
readonly runId?: string;
|
|
85
|
+
readonly toolName: string;
|
|
86
|
+
}, call: () => Promise<T>) => Promise<T>;
|
|
87
|
+
/**
|
|
88
|
+
* Record how long a run waited for a human.
|
|
89
|
+
*
|
|
90
|
+
* Not a wrapper, because the wait is not a function call: the run is *suspended*, the process may have exited,
|
|
91
|
+
* and the decision arrives in a different request entirely. So this is called when the decision lands, with both
|
|
92
|
+
* timestamps — the only shape that can measure a wait spanning a deploy.
|
|
93
|
+
*
|
|
94
|
+
* Often the longest span in a trace, and the one that most needs to be visibly *not* the platform's latency.
|
|
95
|
+
*/
|
|
96
|
+
export declare const recordApprovalWait: (deps: {
|
|
97
|
+
readonly telemetry: Telemetry;
|
|
98
|
+
readonly metrics: RunMetrics;
|
|
99
|
+
}, input: {
|
|
100
|
+
readonly tenantId: string;
|
|
101
|
+
readonly runId: string;
|
|
102
|
+
readonly interactionId: string;
|
|
103
|
+
readonly requestedAt: string;
|
|
104
|
+
readonly decidedAt: string;
|
|
105
|
+
readonly decision: string;
|
|
106
|
+
readonly traceparent?: string;
|
|
107
|
+
}) => void;
|
|
108
|
+
//# sourceMappingURL=instrument.d.ts.map
|