@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,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transport events — `docs/04-durable-runtime-and-hitl.md`.
|
|
3
|
+
*
|
|
4
|
+
* Transports map these to GraphQL subscriptions, SSE or another channel without
|
|
5
|
+
* changing runtime semantics. Events carry a monotonic sequence per run so a client
|
|
6
|
+
* can resume from a cursor after reconnecting.
|
|
7
|
+
*/
|
|
8
|
+
export const RUN_EVENT_TYPES = [
|
|
9
|
+
"run.queued",
|
|
10
|
+
"run.started",
|
|
11
|
+
"run.checkpointed",
|
|
12
|
+
"run.completed",
|
|
13
|
+
"run.failed",
|
|
14
|
+
"run.cancelled",
|
|
15
|
+
"run.retry-pending",
|
|
16
|
+
"part.added",
|
|
17
|
+
"part.updated",
|
|
18
|
+
"tool.started",
|
|
19
|
+
"tool.completed",
|
|
20
|
+
"tool.failed",
|
|
21
|
+
"question.requested",
|
|
22
|
+
"question.answered",
|
|
23
|
+
"approval.requested",
|
|
24
|
+
"approval.decided",
|
|
25
|
+
"usage.updated",
|
|
26
|
+
"context.compacted",
|
|
27
|
+
];
|
|
28
|
+
export const EMPTY_RUN_STREAM_STATE = {
|
|
29
|
+
parts: [],
|
|
30
|
+
pendingToolCalls: [],
|
|
31
|
+
usage: { inputTokens: 0, outputTokens: 0, costMinorUnits: 0 },
|
|
32
|
+
sequence: 0,
|
|
33
|
+
terminal: false,
|
|
34
|
+
};
|
|
35
|
+
/** Fold one event into the projection. Pure; ignores events with a sequence already folded. */
|
|
36
|
+
export const reduceRunEvent = (state, event) => {
|
|
37
|
+
if (event.sequence <= state.sequence && state.sequence > 0)
|
|
38
|
+
return state; // idempotent replay
|
|
39
|
+
const base = {
|
|
40
|
+
...state,
|
|
41
|
+
sequence: event.sequence,
|
|
42
|
+
lastEventType: event.type,
|
|
43
|
+
// Any forward progress clears a pending retry banner.
|
|
44
|
+
...(event.type === "run.retry-pending" ? {} : { retry: undefined }),
|
|
45
|
+
};
|
|
46
|
+
switch (event.type) {
|
|
47
|
+
case "part.added":
|
|
48
|
+
return { ...base, parts: [...state.parts, event.part] };
|
|
49
|
+
case "part.updated": {
|
|
50
|
+
const exists = state.parts.some((p) => p.id === event.part.id);
|
|
51
|
+
return {
|
|
52
|
+
...base,
|
|
53
|
+
parts: exists
|
|
54
|
+
? state.parts.map((p) => (p.id === event.part.id ? event.part : p))
|
|
55
|
+
: [...state.parts, event.part],
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
case "tool.started":
|
|
59
|
+
return {
|
|
60
|
+
...base,
|
|
61
|
+
pendingToolCalls: [
|
|
62
|
+
...state.pendingToolCalls,
|
|
63
|
+
{ toolCallId: event.toolCallId, toolName: event.toolName, startedAt: event.occurredAt },
|
|
64
|
+
],
|
|
65
|
+
};
|
|
66
|
+
case "tool.completed":
|
|
67
|
+
case "tool.failed":
|
|
68
|
+
return { ...base, pendingToolCalls: state.pendingToolCalls.filter((t) => t.toolCallId !== event.toolCallId) };
|
|
69
|
+
case "usage.updated":
|
|
70
|
+
return {
|
|
71
|
+
...base,
|
|
72
|
+
usage: {
|
|
73
|
+
inputTokens: state.usage.inputTokens + event.inputTokens,
|
|
74
|
+
outputTokens: state.usage.outputTokens + event.outputTokens,
|
|
75
|
+
costMinorUnits: state.usage.costMinorUnits + (event.costMinorUnits ?? 0),
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
case "run.retry-pending":
|
|
79
|
+
return {
|
|
80
|
+
...base,
|
|
81
|
+
retry: { attempt: event.attempt, maxAttempts: event.maxAttempts, nextAttemptAt: event.nextAttemptAt },
|
|
82
|
+
};
|
|
83
|
+
case "run.failed":
|
|
84
|
+
return { ...base, error: event.error, terminal: true };
|
|
85
|
+
case "run.completed":
|
|
86
|
+
case "run.cancelled":
|
|
87
|
+
return { ...base, terminal: true };
|
|
88
|
+
default:
|
|
89
|
+
return base;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
/** Project a full (or partial) event sequence into `RunStreamState`. */
|
|
93
|
+
export const reduceRunEvents = (events, initial = EMPTY_RUN_STREAM_STATE) => {
|
|
94
|
+
let state = initial;
|
|
95
|
+
for (const event of events)
|
|
96
|
+
state = reduceRunEvent(state, event);
|
|
97
|
+
return state;
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Branded identifiers.
|
|
3
|
+
*
|
|
4
|
+
* Every durable record in `docs/02-core-and-persistence.md` gets a distinct ID type so
|
|
5
|
+
* a run ID can never be passed where a conversation ID is expected.
|
|
6
|
+
*/
|
|
7
|
+
declare const brand: unique symbol;
|
|
8
|
+
/**
|
|
9
|
+
* Exported so a downstream package can mint its own IDs with the same mechanism rather than a second,
|
|
10
|
+
* incompatible one. `asId` is generic over this, so an integration package's `PostDraftId` gets the
|
|
11
|
+
* same "cannot be passed where another ID is expected" guarantee the platform's own IDs have.
|
|
12
|
+
*/
|
|
13
|
+
export type Branded<T, B extends string> = T & {
|
|
14
|
+
readonly [brand]: B;
|
|
15
|
+
};
|
|
16
|
+
export type TenantId = Branded<string, "TenantId">;
|
|
17
|
+
export type PrincipalId = Branded<string, "PrincipalId">;
|
|
18
|
+
export type MembershipId = Branded<string, "MembershipId">;
|
|
19
|
+
export type RoleId = Branded<string, "RoleId">;
|
|
20
|
+
export type RequestId = Branded<string, "RequestId">;
|
|
21
|
+
export type AgentId = Branded<string, "AgentId">;
|
|
22
|
+
export type SkillId = Branded<string, "SkillId">;
|
|
23
|
+
export type ConversationId = Branded<string, "ConversationId">;
|
|
24
|
+
export type RunId = Branded<string, "RunId">;
|
|
25
|
+
export type MessageId = Branded<string, "MessageId">;
|
|
26
|
+
export type MessagePartId = Branded<string, "MessagePartId">;
|
|
27
|
+
export type CheckpointId = Branded<string, "CheckpointId">;
|
|
28
|
+
export type InteractionId = Branded<string, "InteractionId">;
|
|
29
|
+
export type ApprovalGrantId = Branded<string, "ApprovalGrantId">;
|
|
30
|
+
export type UsageEventId = Branded<string, "UsageEventId">;
|
|
31
|
+
export type EvaluationCaseId = Branded<string, "EvaluationCaseId">;
|
|
32
|
+
export type EvaluationRunId = Branded<string, "EvaluationRunId">;
|
|
33
|
+
export type FileId = Branded<string, "FileId">;
|
|
34
|
+
export type FileVersionId = Branded<string, "FileVersionId">;
|
|
35
|
+
export type KnowledgeCollectionId = Branded<string, "KnowledgeCollectionId">;
|
|
36
|
+
export type KnowledgeSourceId = Branded<string, "KnowledgeSourceId">;
|
|
37
|
+
export type KnowledgeChunkId = Branded<string, "KnowledgeChunkId">;
|
|
38
|
+
export type ArtifactId = Branded<string, "ArtifactId">;
|
|
39
|
+
export type ArtifactVersionId = Branded<string, "ArtifactVersionId">;
|
|
40
|
+
export type ToolCallId = Branded<string, "ToolCallId">;
|
|
41
|
+
export type BlobRef = Branded<string, "BlobRef">;
|
|
42
|
+
export type AuditEventId = Branded<string, "AuditEventId">;
|
|
43
|
+
/** Opaque cursor for the stable pagination every list method uses. */
|
|
44
|
+
export type Cursor = Branded<string, "Cursor">;
|
|
45
|
+
/**
|
|
46
|
+
* Casts a raw string to a branded ID. Reserved for boundaries that have already
|
|
47
|
+
* validated the value — adapters reading a database row, or a resolver that has
|
|
48
|
+
* authenticated the caller. Never call this on model-generated input.
|
|
49
|
+
*/
|
|
50
|
+
export declare const asId: <T extends Branded<string, string>>(value: string) => T;
|
|
51
|
+
export {};
|
|
52
|
+
//# sourceMappingURL=ids.d.ts.map
|
package/dist/core/ids.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Branded identifiers.
|
|
3
|
+
*
|
|
4
|
+
* Every durable record in `docs/02-core-and-persistence.md` gets a distinct ID type so
|
|
5
|
+
* a run ID can never be passed where a conversation ID is expected.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Casts a raw string to a branded ID. Reserved for boundaries that have already
|
|
9
|
+
* validated the value — adapters reading a database row, or a resolver that has
|
|
10
|
+
* authenticated the caller. Never call this on model-generated input.
|
|
11
|
+
*/
|
|
12
|
+
export const asId = (value) => value;
|
|
13
|
+
//# sourceMappingURL=ids.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./ids.js";
|
|
2
|
+
export * from "./tokens.js";
|
|
3
|
+
export * from "./context.js";
|
|
4
|
+
export * from "./content-parts.js";
|
|
5
|
+
export * from "./errors.js";
|
|
6
|
+
export * from "./events.js";
|
|
7
|
+
export * from "./validation.js";
|
|
8
|
+
export * from "./env.js";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./ids.js";
|
|
2
|
+
export * from "./tokens.js";
|
|
3
|
+
export * from "./context.js";
|
|
4
|
+
export * from "./content-parts.js";
|
|
5
|
+
export * from "./errors.js";
|
|
6
|
+
export * from "./events.js";
|
|
7
|
+
export * from "./validation.js";
|
|
8
|
+
export * from "./env.js";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The token estimate, in one place (#135).
|
|
3
|
+
*
|
|
4
|
+
* Five copies of `Math.ceil(text.length / 4)` had accumulated — in `files/context.ts`, `knowledge/chunking.ts`,
|
|
5
|
+
* `context/compaction.ts`, `usage/recorder.ts` and `principal-memory/index.ts`. Two of them exported the same
|
|
6
|
+
* name, which is what surfaced it: the package barrel refused to re-export both, the same collision
|
|
7
|
+
* `DEFAULT_SESSION_STATE_MAX_BYTES` caused before #97 moved it to its port.
|
|
8
|
+
*
|
|
9
|
+
* They agreed by coincidence rather than by construction, and the coincidence mattered: a chunk sized against
|
|
10
|
+
* one estimate and budgeted against a different one is a chunk that does not fit the budget it was measured
|
|
11
|
+
* for. One definition, in the lowest layer, so agreement is structural.
|
|
12
|
+
*
|
|
13
|
+
* **Deliberately not a real tokeniser.** A tokeniser is a dependency, it is model-specific, and it is wrong the
|
|
14
|
+
* moment the model changes. Every caller here uses the estimate to size something — a chunk boundary, a budget
|
|
15
|
+
* bucket, a cost projection — where being 10% out moves a boundary rather than breaking anything. Where an
|
|
16
|
+
* exact count matters, the provider's own reported usage is authoritative and this is not consulted.
|
|
17
|
+
*/
|
|
18
|
+
/** Characters over four — the industry rule of thumb for English text with a BPE tokeniser. */
|
|
19
|
+
export declare const CHARS_PER_TOKEN = 4;
|
|
20
|
+
/** An estimate of how many tokens `text` occupies. Never negative, never fractional. */
|
|
21
|
+
export declare const estimateTokens: (text: string) => number;
|
|
22
|
+
//# sourceMappingURL=tokens.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The token estimate, in one place (#135).
|
|
3
|
+
*
|
|
4
|
+
* Five copies of `Math.ceil(text.length / 4)` had accumulated — in `files/context.ts`, `knowledge/chunking.ts`,
|
|
5
|
+
* `context/compaction.ts`, `usage/recorder.ts` and `principal-memory/index.ts`. Two of them exported the same
|
|
6
|
+
* name, which is what surfaced it: the package barrel refused to re-export both, the same collision
|
|
7
|
+
* `DEFAULT_SESSION_STATE_MAX_BYTES` caused before #97 moved it to its port.
|
|
8
|
+
*
|
|
9
|
+
* They agreed by coincidence rather than by construction, and the coincidence mattered: a chunk sized against
|
|
10
|
+
* one estimate and budgeted against a different one is a chunk that does not fit the budget it was measured
|
|
11
|
+
* for. One definition, in the lowest layer, so agreement is structural.
|
|
12
|
+
*
|
|
13
|
+
* **Deliberately not a real tokeniser.** A tokeniser is a dependency, it is model-specific, and it is wrong the
|
|
14
|
+
* moment the model changes. Every caller here uses the estimate to size something — a chunk boundary, a budget
|
|
15
|
+
* bucket, a cost projection — where being 10% out moves a boundary rather than breaking anything. Where an
|
|
16
|
+
* exact count matters, the provider's own reported usage is authoritative and this is not consulted.
|
|
17
|
+
*/
|
|
18
|
+
/** Characters over four — the industry rule of thumb for English text with a BPE tokeniser. */
|
|
19
|
+
export const CHARS_PER_TOKEN = 4;
|
|
20
|
+
/** An estimate of how many tokens `text` occupies. Never negative, never fractional. */
|
|
21
|
+
export const estimateTokens = (text) => Math.ceil(text.length / CHARS_PER_TOKEN);
|
|
22
|
+
//# sourceMappingURL=tokens.js.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime validation for the core wire contracts — `docs/02-core-and-persistence.md`.
|
|
3
|
+
*
|
|
4
|
+
* Every message part is JSON-runtime validated and carries a `schemaVersion`. `providerMetadata`
|
|
5
|
+
* is namespaced and **non-authoritative**: it is preserved on round-trip but never participates
|
|
6
|
+
* in discrimination or any branching — a part's `type` is the only source of truth.
|
|
7
|
+
*/
|
|
8
|
+
import type { ExecutionContext } from "./context.js";
|
|
9
|
+
import type { MessagePart } from "./content-parts.js";
|
|
10
|
+
import { type RunEvent } from "./events.js";
|
|
11
|
+
/**
|
|
12
|
+
* The most a reference part's provider bag may hold (#130).
|
|
13
|
+
*
|
|
14
|
+
* Small on purpose. `providerMetadata` is `Record<string, unknown>`, which is exactly the shape a base64
|
|
15
|
+
* payload fits into — and a file part carrying its own content would satisfy every other rule in this file
|
|
16
|
+
* while breaking the one that matters. 2 KiB is room for a provider's ids and flags and no room for a
|
|
17
|
+
* document.
|
|
18
|
+
*/
|
|
19
|
+
export declare const MAX_REFERENCE_METADATA_BYTES = 2048;
|
|
20
|
+
/**
|
|
21
|
+
* The longest excerpt a citation may carry (#137).
|
|
22
|
+
*
|
|
23
|
+
* A citation is evidence for a claim, not a copy of the source. Unbounded, it becomes a way to store a document
|
|
24
|
+
* inside a message — bypassing every limit that applies to documents — and a transcript whose size grows with
|
|
25
|
+
* the corpus. 2000 characters is several paragraphs: far more than a claim needs and far less than a document.
|
|
26
|
+
*/
|
|
27
|
+
export declare const MAX_CITATION_EXCERPT = 2000;
|
|
28
|
+
/** Validate an unknown JSON value into a typed message part, or throw `invalid_input`. */
|
|
29
|
+
export declare const parseMessagePart: (value: unknown) => MessagePart;
|
|
30
|
+
/** JSON-safe wire form. `parseMessagePart(serializeMessagePart(x))` round-trips to `x`. */
|
|
31
|
+
export declare const serializeMessagePart: (part: MessagePart) => unknown;
|
|
32
|
+
export declare const parseExecutionContext: (value: unknown) => ExecutionContext;
|
|
33
|
+
export declare const parseRunEvent: (value: unknown) => RunEvent;
|
|
34
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime validation for the core wire contracts — `docs/02-core-and-persistence.md`.
|
|
3
|
+
*
|
|
4
|
+
* Every message part is JSON-runtime validated and carries a `schemaVersion`. `providerMetadata`
|
|
5
|
+
* is namespaced and **non-authoritative**: it is preserved on round-trip but never participates
|
|
6
|
+
* in discrimination or any branching — a part's `type` is the only source of truth.
|
|
7
|
+
*/
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
import { AgentPlatformError, ERROR_CODES } from "./errors.js";
|
|
10
|
+
import { RUN_EVENT_TYPES } from "./events.js";
|
|
11
|
+
const idString = z.string().min(1);
|
|
12
|
+
const providerMetadata = z.record(z.string(), z.unknown()).optional();
|
|
13
|
+
/**
|
|
14
|
+
* The most a reference part's provider bag may hold (#130).
|
|
15
|
+
*
|
|
16
|
+
* Small on purpose. `providerMetadata` is `Record<string, unknown>`, which is exactly the shape a base64
|
|
17
|
+
* payload fits into — and a file part carrying its own content would satisfy every other rule in this file
|
|
18
|
+
* while breaking the one that matters. 2 KiB is room for a provider's ids and flags and no room for a
|
|
19
|
+
* document.
|
|
20
|
+
*/
|
|
21
|
+
export const MAX_REFERENCE_METADATA_BYTES = 2048;
|
|
22
|
+
/**
|
|
23
|
+
* The longest excerpt a citation may carry (#137).
|
|
24
|
+
*
|
|
25
|
+
* A citation is evidence for a claim, not a copy of the source. Unbounded, it becomes a way to store a document
|
|
26
|
+
* inside a message — bypassing every limit that applies to documents — and a transcript whose size grows with
|
|
27
|
+
* the corpus. 2000 characters is several paragraphs: far more than a claim needs and far less than a document.
|
|
28
|
+
*/
|
|
29
|
+
export const MAX_CITATION_EXCERPT = 2000;
|
|
30
|
+
/** A `data:` URI is bytes wearing a string's clothes, so it is refused wherever it appears in the bag. */
|
|
31
|
+
const carriesInlineData = (value) => typeof value === "string"
|
|
32
|
+
? /^\s*data:[^,]*,/i.test(value)
|
|
33
|
+
: Array.isArray(value)
|
|
34
|
+
? value.some(carriesInlineData)
|
|
35
|
+
: typeof value === "object" && value !== null
|
|
36
|
+
? Object.values(value).some(carriesInlineData)
|
|
37
|
+
: false;
|
|
38
|
+
/**
|
|
39
|
+
* `providerMetadata` for a part that must stay a reference.
|
|
40
|
+
*
|
|
41
|
+
* Two checks rather than one, because they fail differently: a size cap catches bulk however it is encoded,
|
|
42
|
+
* and the `data:` check catches a small payload that would slip under the cap — a 1 KB inline image is still
|
|
43
|
+
* content in a part that promises not to carry any.
|
|
44
|
+
*/
|
|
45
|
+
const referenceMetadata = z
|
|
46
|
+
.record(z.string(), z.unknown())
|
|
47
|
+
.refine((bag) => JSON.stringify(bag).length <= MAX_REFERENCE_METADATA_BYTES, {
|
|
48
|
+
message: `providerMetadata on a reference part must be at most ${MAX_REFERENCE_METADATA_BYTES} bytes; file contents are referenced, not inlined`,
|
|
49
|
+
})
|
|
50
|
+
.refine((bag) => !carriesInlineData(bag), {
|
|
51
|
+
message: "providerMetadata on a reference part must not contain a data: URI; file contents are referenced, not inlined",
|
|
52
|
+
})
|
|
53
|
+
.optional();
|
|
54
|
+
/** Fields on every part. `providerMetadata` is optional and never authoritative. */
|
|
55
|
+
const base = {
|
|
56
|
+
id: idString,
|
|
57
|
+
schemaVersion: z.number().int().nonnegative(),
|
|
58
|
+
createdAt: z.string().min(1),
|
|
59
|
+
providerMetadata,
|
|
60
|
+
};
|
|
61
|
+
const platformErrorSchema = z.object({
|
|
62
|
+
code: z.enum([...ERROR_CODES]),
|
|
63
|
+
message: z.string(),
|
|
64
|
+
retryable: z.boolean(),
|
|
65
|
+
details: z.record(z.string(), z.unknown()).optional(),
|
|
66
|
+
retryAfterMs: z.number().optional(),
|
|
67
|
+
});
|
|
68
|
+
const messagePartSchema = z.discriminatedUnion("type", [
|
|
69
|
+
z.object({ ...base, type: z.literal("text"), text: z.string() }),
|
|
70
|
+
z.object({ ...base, type: z.literal("reasoning"), text: z.string(), redacted: z.boolean().optional() }),
|
|
71
|
+
z.object({ ...base, type: z.literal("tool-call"), toolCallId: idString, toolName: z.string(), input: z.unknown() }),
|
|
72
|
+
z.object({
|
|
73
|
+
...base, type: z.literal("tool-result"), toolCallId: idString, toolName: z.string(),
|
|
74
|
+
output: z.unknown().optional(), spilledOutputRef: idString.optional(), truncated: z.boolean(),
|
|
75
|
+
}),
|
|
76
|
+
z.object({
|
|
77
|
+
...base, type: z.literal("question"), interactionId: idString,
|
|
78
|
+
questions: z.array(z.object({ key: z.string(), prompt: z.string(), options: z.array(z.string()).optional() })),
|
|
79
|
+
answeredAt: z.string().optional(),
|
|
80
|
+
}),
|
|
81
|
+
z.object({
|
|
82
|
+
...base, type: z.literal("approval"), interactionId: idString, toolName: z.string(),
|
|
83
|
+
summary: z.string(), riskCategory: z.string(), decidedAt: z.string().optional(),
|
|
84
|
+
}),
|
|
85
|
+
// #130. A reference, and structurally incapable of being anything else: no field holds content, and
|
|
86
|
+
// `referenceMetadata` refuses the two ways bytes could arrive anyway — a `data:` URI, or a payload smuggled
|
|
87
|
+
// into the non-authoritative provider bag. Governing principle 6 is a property of the schema here rather
|
|
88
|
+
// than a rule the assembler has to enforce downstream.
|
|
89
|
+
z.object({
|
|
90
|
+
...base, type: z.literal("file"), providerMetadata: referenceMetadata,
|
|
91
|
+
fileId: idString, filename: z.string(), mediaType: z.string(), byteSize: z.number().int().nonnegative(),
|
|
92
|
+
}),
|
|
93
|
+
z.object({
|
|
94
|
+
...base, type: z.literal("image"), providerMetadata: referenceMetadata,
|
|
95
|
+
fileId: idString, mediaType: z.string(), width: z.number().optional(), height: z.number().optional(),
|
|
96
|
+
altText: z.string().optional(),
|
|
97
|
+
}),
|
|
98
|
+
// #137. `excerpt` has a length cap because a citation is *evidence* for a claim, not a copy of the source:
|
|
99
|
+
// unbounded, it becomes a way to store a document inside a message and bypass every limit on documents.
|
|
100
|
+
z.object({
|
|
101
|
+
...base,
|
|
102
|
+
type: z.literal("citation"),
|
|
103
|
+
origin: z.discriminatedUnion("kind", [
|
|
104
|
+
z.object({
|
|
105
|
+
kind: z.literal("retrieval"),
|
|
106
|
+
sourceType: z.enum(["file", "artifact", "message", "external"]),
|
|
107
|
+
sourceId: idString,
|
|
108
|
+
chunkId: idString,
|
|
109
|
+
chunkIndex: z.number().int().nonnegative(),
|
|
110
|
+
locator: z.string().optional(),
|
|
111
|
+
}),
|
|
112
|
+
z.object({
|
|
113
|
+
kind: z.literal("web"),
|
|
114
|
+
// Absolute, and http(s) only. A `data:` or `file:` citation is not a source anyone can open, and a
|
|
115
|
+
// relative URL resolves against whatever page happens to render it.
|
|
116
|
+
url: z.string().url().refine((u) => /^https?:\/\//i.test(u), {
|
|
117
|
+
message: "a web citation's url must be http or https",
|
|
118
|
+
}),
|
|
119
|
+
title: z.string().optional(),
|
|
120
|
+
}),
|
|
121
|
+
]),
|
|
122
|
+
excerpt: z.string().min(1).max(MAX_CITATION_EXCERPT),
|
|
123
|
+
retrievedAt: z.string(),
|
|
124
|
+
supports: z.array(idString),
|
|
125
|
+
charRange: z
|
|
126
|
+
.object({ start: z.number().int().nonnegative(), end: z.number().int().nonnegative() })
|
|
127
|
+
// An inverted range is a bug that would silently produce an empty highlight, which reads as "the passage
|
|
128
|
+
// is not in the source".
|
|
129
|
+
.refine((r) => r.end > r.start, { message: "charRange.end must be greater than charRange.start" })
|
|
130
|
+
.optional(),
|
|
131
|
+
}),
|
|
132
|
+
z.object({ ...base, type: z.literal("source"), sourceId: z.string(), title: z.string(), url: z.string().optional() }),
|
|
133
|
+
z.object({ ...base, type: z.literal("artifact"), artifactId: idString, versionId: idString, title: z.string() }),
|
|
134
|
+
z.object({ ...base, type: z.literal("status"), status: z.string(), detail: z.string().optional() }),
|
|
135
|
+
z.object({ ...base, type: z.literal("error"), error: platformErrorSchema }),
|
|
136
|
+
]);
|
|
137
|
+
const executionContextSchema = z.object({
|
|
138
|
+
tenantId: idString,
|
|
139
|
+
principalId: idString,
|
|
140
|
+
membershipId: z.string().optional(),
|
|
141
|
+
roleIds: z.array(z.string()),
|
|
142
|
+
locale: z.string(),
|
|
143
|
+
timezone: z.string(),
|
|
144
|
+
conversationId: z.string().optional(),
|
|
145
|
+
runId: z.string().optional(),
|
|
146
|
+
requestId: idString,
|
|
147
|
+
});
|
|
148
|
+
const runEventSchema = z.object({
|
|
149
|
+
type: z.enum([...RUN_EVENT_TYPES]),
|
|
150
|
+
runId: idString,
|
|
151
|
+
sequence: z.number().int().nonnegative(),
|
|
152
|
+
occurredAt: z.string().min(1),
|
|
153
|
+
}).passthrough();
|
|
154
|
+
const fail = (what, error) => {
|
|
155
|
+
throw new AgentPlatformError({
|
|
156
|
+
code: "invalid_input",
|
|
157
|
+
message: `Invalid ${what}: ${error.issues.map((i) => `${i.path.join(".")} ${i.message}`).join("; ")}`,
|
|
158
|
+
retryable: false,
|
|
159
|
+
});
|
|
160
|
+
};
|
|
161
|
+
/** Validate an unknown JSON value into a typed message part, or throw `invalid_input`. */
|
|
162
|
+
export const parseMessagePart = (value) => {
|
|
163
|
+
const r = messagePartSchema.safeParse(value);
|
|
164
|
+
return r.success ? r.data : fail("message part", r.error);
|
|
165
|
+
};
|
|
166
|
+
/** JSON-safe wire form. `parseMessagePart(serializeMessagePart(x))` round-trips to `x`. */
|
|
167
|
+
export const serializeMessagePart = (part) => JSON.parse(JSON.stringify(part));
|
|
168
|
+
export const parseExecutionContext = (value) => {
|
|
169
|
+
const r = executionContextSchema.safeParse(value);
|
|
170
|
+
return r.success ? r.data : fail("execution context", r.error);
|
|
171
|
+
};
|
|
172
|
+
export const parseRunEvent = (value) => {
|
|
173
|
+
const r = runEventSchema.safeParse(value);
|
|
174
|
+
return r.success ? r.data : fail("run event", r.error);
|
|
175
|
+
};
|
|
176
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The extraction pipeline (#131).
|
|
3
|
+
*
|
|
4
|
+
* The parsers do the reading; this decides *when*, *within what bounds*, and *what is recorded when it goes
|
|
5
|
+
* wrong* — which is the part that makes extraction safe to run on a shared worker tier.
|
|
6
|
+
*
|
|
7
|
+
* Four properties, each answering an AC:
|
|
8
|
+
*
|
|
9
|
+
* - **It never throws for a document problem** (AC-4). Every outcome is recorded on the file: `extracted` with
|
|
10
|
+
* a reference, or `failed` with a typed reason and a sentence the user reads. An extractor that threw would
|
|
11
|
+
* leave the file looking unextracted, which is indistinguishable from "not got round to it yet" — and the
|
|
12
|
+
* user would see an empty document rather than a reason.
|
|
13
|
+
* - **It is bounded in every dimension a document can grow** (AC-3): bytes read, pages, extracted text,
|
|
14
|
+
* blocks, and wall clock. The timeout is enforced *here* rather than trusted to the parser, because a
|
|
15
|
+
* parser stuck in a loop is exactly the case a parser-side check does not catch.
|
|
16
|
+
* - **It is enqueued, not awaited** (AC-2). `requestExtraction` puts a job on the queue and returns; an
|
|
17
|
+
* enqueue failure marks the file `pending` and is reported, never propagated — an attachment that uploaded
|
|
18
|
+
* fine must not fail because the extraction queue was briefly unreachable.
|
|
19
|
+
* - **The result is stored by reference and read in windows** (AC-6). The `ExtractedDocument` goes to
|
|
20
|
+
* `BlobStore` and the file carries the ref. Nothing loads it into context; `read_document` reads a bounded
|
|
21
|
+
* window, exactly as #130 established for the raw bytes.
|
|
22
|
+
*/
|
|
23
|
+
import type { ExecutionContext } from "../core/context.js";
|
|
24
|
+
import type { FileId, TenantId } from "../core/ids.js";
|
|
25
|
+
import type { BlobStore, FileContentStore, FileExtraction, FileMetadataStore } from "../persistence/index.js";
|
|
26
|
+
import { type DocumentParser, type ExtractedDocument, type ExtractionDispatcher, type ExtractionJob, type ExtractionLimits } from "./index.js";
|
|
27
|
+
export type ExtractionServiceDeps = {
|
|
28
|
+
readonly metadata: FileMetadataStore;
|
|
29
|
+
readonly content: FileContentStore;
|
|
30
|
+
/** Where the extracted document goes. `BlobStore` stores JSON, which is what an `ExtractedDocument` is. */
|
|
31
|
+
readonly blobs: BlobStore;
|
|
32
|
+
readonly parsers: readonly DocumentParser[];
|
|
33
|
+
/**
|
|
34
|
+
* Parsers to try when the primary one reports `no-text-layer` (#132).
|
|
35
|
+
*
|
|
36
|
+
* Keyed by media type like `parsers`, and separate because the dispatch table holds one parser per type:
|
|
37
|
+
* both the text-layer PDF parser and the OCR one claim `application/pdf`. This is where #131's insistence
|
|
38
|
+
* that `no-text-layer` be its own reason becomes load-bearing — the fallback triggers on exactly that
|
|
39
|
+
* answer and on nothing else. An encrypted or malformed document is *not* retried through OCR, because
|
|
40
|
+
* OCR will not decrypt it and the second attempt would cost money to reach the same conclusion.
|
|
41
|
+
*/
|
|
42
|
+
readonly fallbackParsers?: readonly DocumentParser[];
|
|
43
|
+
/**
|
|
44
|
+
* Bills a vision or OCR call (#132, AC-4).
|
|
45
|
+
*
|
|
46
|
+
* A callback rather than a `UsageRecorder`, so `documents` does not depend on `usage`. The pipeline knows
|
|
47
|
+
* *when* a priced operation happened; what it costs is the caller's pricing model.
|
|
48
|
+
*/
|
|
49
|
+
readonly onPricedOperation?: (input: {
|
|
50
|
+
readonly tenantId: TenantId;
|
|
51
|
+
readonly fileId: FileId;
|
|
52
|
+
readonly usage: PricedExtractionUsage;
|
|
53
|
+
}) => Promise<void>;
|
|
54
|
+
readonly limits?: ExtractionLimits;
|
|
55
|
+
readonly clock?: () => string;
|
|
56
|
+
/**
|
|
57
|
+
* The queue. Optional, and its absence means extraction runs only when something calls `extract` directly.
|
|
58
|
+
*
|
|
59
|
+
* Optional rather than required because a single-process deployment is a real configuration, and requiring a
|
|
60
|
+
* queue there would mean standing up Redis to attach a text file. What is *not* optional is that `upload`
|
|
61
|
+
* never blocks on extraction — that holds either way.
|
|
62
|
+
*/
|
|
63
|
+
readonly dispatcher?: ExtractionDispatcher;
|
|
64
|
+
readonly log?: (message: string, detail?: Readonly<Record<string, unknown>>) => void;
|
|
65
|
+
};
|
|
66
|
+
/** What a priced extraction step consumed. Vision calls are the expensive kind, so they are reported. */
|
|
67
|
+
export type PricedExtractionUsage = {
|
|
68
|
+
readonly kind: "vision" | "ocr";
|
|
69
|
+
readonly modelId: string;
|
|
70
|
+
readonly inputTokens: number;
|
|
71
|
+
readonly outputTokens: number;
|
|
72
|
+
readonly cachedInputTokens: number;
|
|
73
|
+
};
|
|
74
|
+
export declare const createExtractionService: (deps: ExtractionServiceDeps) => {
|
|
75
|
+
limits: ExtractionLimits;
|
|
76
|
+
/** Types this pipeline can read at all. Exposed so an upload path can decide not to enqueue at all. */
|
|
77
|
+
supportedMediaTypes(): readonly string[];
|
|
78
|
+
/**
|
|
79
|
+
* Ask for extraction, without waiting for it — AC-2.
|
|
80
|
+
*
|
|
81
|
+
* Marks the file `pending` first, then enqueues. That order matters: the reverse would let a worker pick
|
|
82
|
+
* the job up, extract, and record its outcome *before* this function overwrote it with `pending`, losing a
|
|
83
|
+
* completed extraction to a race that only shows up under load.
|
|
84
|
+
*/
|
|
85
|
+
requestExtraction(context: {
|
|
86
|
+
readonly tenantId: TenantId;
|
|
87
|
+
}, id: FileId, mediaType: string): Promise<{
|
|
88
|
+
readonly enqueued: boolean;
|
|
89
|
+
readonly state: FileExtraction["state"];
|
|
90
|
+
}>;
|
|
91
|
+
/**
|
|
92
|
+
* Do the extraction. Called by the worker, and directly by a single-process host.
|
|
93
|
+
*
|
|
94
|
+
* Returns the record it wrote rather than throwing, for every document-shaped problem. The only throw is
|
|
95
|
+
* for a *file* that is not there, which is a caller error rather than a document one.
|
|
96
|
+
*/
|
|
97
|
+
extract(job: ExtractionJob): Promise<FileExtraction>;
|
|
98
|
+
/** The extracted document, or null when there is none to read. */
|
|
99
|
+
getExtracted(context: ExecutionContext, id: FileId): Promise<{
|
|
100
|
+
readonly document: ExtractedDocument | null;
|
|
101
|
+
readonly extraction?: FileExtraction;
|
|
102
|
+
}>;
|
|
103
|
+
/**
|
|
104
|
+
* Re-enqueue extractions that never finished.
|
|
105
|
+
*
|
|
106
|
+
* Two shapes, and both are silent without this: a `pending` file whose enqueue was lost, and a `running`
|
|
107
|
+
* file whose worker died. Both are re-requested rather than repaired — the pipeline is idempotent, so
|
|
108
|
+
* running it again is the repair.
|
|
109
|
+
*/
|
|
110
|
+
sweepStuckExtractions(context: {
|
|
111
|
+
readonly tenantId: TenantId;
|
|
112
|
+
}, input: {
|
|
113
|
+
readonly olderThan: string;
|
|
114
|
+
readonly limit: number;
|
|
115
|
+
}): Promise<{
|
|
116
|
+
readonly requeued: number;
|
|
117
|
+
readonly states: Readonly<Record<string, number>>;
|
|
118
|
+
}>;
|
|
119
|
+
};
|
|
120
|
+
export type ExtractionService = ReturnType<typeof createExtractionService>;
|
|
121
|
+
//# sourceMappingURL=extraction.d.ts.map
|