@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,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage and infrastructure ports — `docs/02-core-and-persistence.md`.
|
|
3
|
+
*
|
|
4
|
+
* Small interfaces rather than one database adapter. Every read and write receives
|
|
5
|
+
* `tenantId` explicitly: `findById(id)` is forbidden, `findById({ tenantId, id })` is
|
|
6
|
+
* the shape. Ports never import adapters.
|
|
7
|
+
*
|
|
8
|
+
* Method bodies are intentionally sparse at this stage — each port is filled in as its
|
|
9
|
+
* phase in `docs/08-migration-plan.md` lands, against the shared conformance suite.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* The ceiling on session state, defined here rather than in an adapter (#97). It is a domain limit —
|
|
13
|
+
* session state is bounded working memory, not a document store — and every adapter must enforce the
|
|
14
|
+
* same one. It previously lived in `adapters/memory/sessions.ts`, which made two adapters agreeing on
|
|
15
|
+
* it a coincidence rather than a property.
|
|
16
|
+
*/
|
|
17
|
+
export const DEFAULT_SESSION_STATE_MAX_BYTES = 64 * 1024;
|
|
18
|
+
/**
|
|
19
|
+
* Rollup granularities (#139).
|
|
20
|
+
*
|
|
21
|
+
* Hour, day, week and month, and nothing finer than an hour. A minute bucket multiplies the row count
|
|
22
|
+
* sixty-fold to answer a question nobody asks.
|
|
23
|
+
*
|
|
24
|
+
* Week and month were added by #175, because they are the periods a *person's* allowance is actually expressed
|
|
25
|
+
* in — "500k tokens a month" is a plan, "500k tokens a day" is not. They cannot be derived by summing days
|
|
26
|
+
* either: a month is 28 to 31 days and a week crosses month boundaries, so a caller summing day buckets has to
|
|
27
|
+
* reimplement calendar arithmetic, and two callers doing it differently is two answers to what a month cost.
|
|
28
|
+
*
|
|
29
|
+
* A week starts **Monday**, in UTC, following ISO 8601 — chosen rather than defaulted, because a Sunday start
|
|
30
|
+
* would split a working week across two buckets and every weekly figure would describe half of one week and half
|
|
31
|
+
* of another.
|
|
32
|
+
*/
|
|
33
|
+
export const ROLLUP_PERIODS = ["hour", "day", "week", "month"];
|
|
34
|
+
/**
|
|
35
|
+
* Admin-configured spend limits — #175.
|
|
36
|
+
*
|
|
37
|
+
* `principalId` absent is the **tenant default**; present overrides it for one person. One store rather than
|
|
38
|
+
* two, because "the default" and "an override" are the same kind of fact and resolution is then a single query
|
|
39
|
+
* ordered by specificity rather than two queries and a merge.
|
|
40
|
+
*
|
|
41
|
+
* Every limit is optional and an omitted one is **unbounded**, not zero — matching `QuotaLimits`, and for the
|
|
42
|
+
* reason stated there: a misconfigured quota that blocks everything is an outage, and one that blocks nothing is
|
|
43
|
+
* a bill that the rollups make visible.
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
* A window as one storable string, and back — #181.
|
|
47
|
+
*
|
|
48
|
+
* `usage_limits` keys its unique indexes on this single column, so the two kinds of window have to share one
|
|
49
|
+
* value space. A calendar window is its own period; a rolling one is `rolling:<minutes>`. Both spellings are
|
|
50
|
+
* pinned by the table's CHECK constraint, so a value that would not round-trip cannot be stored in the first
|
|
51
|
+
* place.
|
|
52
|
+
*
|
|
53
|
+
* The codec lives here, beside the type, rather than in each adapter: two adapters spelling a key differently is
|
|
54
|
+
* two stores that cannot read each other's rows, and conformance would pass because each is self-consistent.
|
|
55
|
+
*/
|
|
56
|
+
export const windowKey = (window) => window.kind === "calendar" ? window.period : `rolling:${window.minutes}`;
|
|
57
|
+
/**
|
|
58
|
+
* `null` for anything this does not recognise — a row written by a newer version, or by hand.
|
|
59
|
+
*
|
|
60
|
+
* Null rather than a thrown error or a calendar fallback. A fallback would silently enforce the wrong window,
|
|
61
|
+
* which for a spend limit means either refusing people wrongly or charging them wrongly; null makes the caller
|
|
62
|
+
* decide, and every caller here treats it as "no limit I can honour", which fails towards *not* pretending.
|
|
63
|
+
*/
|
|
64
|
+
export const parseWindowKey = (key) => {
|
|
65
|
+
if (ROLLUP_PERIODS.includes(key))
|
|
66
|
+
return { kind: "calendar", period: key };
|
|
67
|
+
const match = /^rolling:([1-9][0-9]{0,5})$/.exec(key);
|
|
68
|
+
if (match === null)
|
|
69
|
+
return null;
|
|
70
|
+
return { kind: "rolling", minutes: Number(match[1]) };
|
|
71
|
+
};
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
// Artifacts (#133) — REQ-028. Substantial assistant output as a named, versioned thing rather than
|
|
74
|
+
// text buried in a thread.
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
/**
|
|
77
|
+
* What an artifact is.
|
|
78
|
+
*
|
|
79
|
+
* Markdown and structured content first, per `docs/05` → Document writing. Rendered formats — PDF, DOCX — are
|
|
80
|
+
* *exports* of an artifact rather than kinds of one, which is why they are absent here: an artifact exported
|
|
81
|
+
* twice is one artifact, and making PDF a kind would make it two things that drift.
|
|
82
|
+
*/
|
|
83
|
+
export const ARTIFACT_KINDS = ["markdown", "html", "json", "csv", "code", "diagram"];
|
|
84
|
+
/**
|
|
85
|
+
* A rendered export of one artifact version (#134).
|
|
86
|
+
*
|
|
87
|
+
* **Not an artifact version.** #133's versions are versions of the *content*; a PDF is a rendering of one.
|
|
88
|
+
* Making a render a new version would bump `latestVersion` for a reason unrelated to the content, and
|
|
89
|
+
* "the newest version" would stop meaning "the newest thing the assistant wrote". The issue's wording said
|
|
90
|
+
* artifact version; this is the deviation, and the reason.
|
|
91
|
+
*
|
|
92
|
+
* Keyed on `(artifactId, version, format)`, which is what makes "re-downloaded without re-rendering" a
|
|
93
|
+
* constraint rather than a cache someone remembers to check.
|
|
94
|
+
*/
|
|
95
|
+
export const EXPORT_FORMATS = ["pdf", "markdown"];
|
|
96
|
+
export const EXPORT_STATES = ["pending", "rendering", "rendered", "failed"];
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
// Files (`docs/05-knowledge-and-documents.md`, REQ-026). Two ports, not one.
|
|
99
|
+
//
|
|
100
|
+
// `BlobStore` below is `put(value) -> ref` / `get(ref) -> value` — JSON, for spilled tool output. It has
|
|
101
|
+
// no content type, no size and no stream, so it cannot hold a file: bytes through a `jsonb` column means
|
|
102
|
+
// base64, which is the "inject rather than reference" failure the platform forbids everywhere else. #102
|
|
103
|
+
// recorded this in the `0011` migration when it declined to make `blobs` a pointer table.
|
|
104
|
+
//
|
|
105
|
+
// So metadata and bytes are separate ports. They also have genuinely different lifecycles: metadata is
|
|
106
|
+
// transactional and soft-deleted, bytes are eventually deleted by a sweep, and the gap between the two is
|
|
107
|
+
// where orphans live.
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
/**
|
|
110
|
+
* Where a file is in its lifecycle.
|
|
111
|
+
*
|
|
112
|
+
* `pending` exists because an upload is two writes — metadata, then bytes — and the window between them is
|
|
113
|
+
* real. A file stuck in `pending` is metadata with no bytes, which is one of the two orphan directions
|
|
114
|
+
* reconciliation looks for.
|
|
115
|
+
*
|
|
116
|
+
* `deleting` is the same window in reverse: the metadata is gone from the user's view and the bytes are
|
|
117
|
+
* not yet gone from storage. Deleting them in one transaction is not available — object storage does not
|
|
118
|
+
* join a database transaction — so the intermediate state is named rather than pretended away.
|
|
119
|
+
*/
|
|
120
|
+
export const FILE_STATES = ["pending", "stored", "deleting", "deleted"];
|
|
121
|
+
/**
|
|
122
|
+
* What a file records about its derived text (#131).
|
|
123
|
+
*
|
|
124
|
+
* Declared here rather than imported from `documents/`: a store port that depended on the extraction pipeline
|
|
125
|
+
* would make the pipeline a prerequisite for storing a file, and `persistence` is the layer nothing above it
|
|
126
|
+
* gets to reach into.
|
|
127
|
+
*
|
|
128
|
+
* Separate from the file's own `state` on purpose. A file is perfectly `stored` while its extraction has
|
|
129
|
+
* `failed`, and conflating the two would make an unreadable document look like a lost upload.
|
|
130
|
+
*/
|
|
131
|
+
/**
|
|
132
|
+
* Below this, a recognised extraction is flagged rather than presented as certain (#132).
|
|
133
|
+
*
|
|
134
|
+
* Here rather than in `documents/` because two layers interpret the same field and neither may import the
|
|
135
|
+
* other: `documents/vision.ts` sets the flag, and `files/context.ts` marks the reference line so a model
|
|
136
|
+
* choosing between attachments knows before it reads any of them. A copy in each is a copy that drifts, and
|
|
137
|
+
* the port that declares `confidence` is the right place for the number that gives it meaning.
|
|
138
|
+
*
|
|
139
|
+
* 0.7 because that is roughly where OCR stops being "a few wrong characters" and becomes "wrong words" — and
|
|
140
|
+
* a wrong word is worse than a gap, because the sentence still reads.
|
|
141
|
+
*/
|
|
142
|
+
export const LOW_CONFIDENCE_THRESHOLD = 0.7;
|
|
143
|
+
/**
|
|
144
|
+
* Knowledge chunks and the vector index — REQ-029 (#135).
|
|
145
|
+
*
|
|
146
|
+
* Two ports rather than one, because they answer different questions and can be backed by different systems:
|
|
147
|
+
* `KnowledgeStore` owns the *rows* (content, provenance, which embedding produced them) and `VectorIndex` owns
|
|
148
|
+
* the *similarity search*. A deployment on pgvector satisfies both with one table; a deployment on a dedicated
|
|
149
|
+
* vector database satisfies them with two systems, and nothing above this layer changes.
|
|
150
|
+
*
|
|
151
|
+
* **The authorisation subject is on the chunk row.** That is the single most important decision here. The SPEC
|
|
152
|
+
* says filtering happens *inside* the query, and the reason is precise: filtering after retrieval leaks through
|
|
153
|
+
* result counts. Ask for ten chunks, get three back, and you have learned that seven exist that you may not
|
|
154
|
+
* see — and with a few queries, roughly what they are about. So `authSubject` travels with the chunk and every
|
|
155
|
+
* search takes it as a required filter.
|
|
156
|
+
*/
|
|
157
|
+
/**
|
|
158
|
+
* The embedding width every adapter stores.
|
|
159
|
+
*
|
|
160
|
+
* On the port, not in an adapter, for the reason `DEFAULT_SESSION_STATE_MAX_BYTES` is (#97): a vector column has
|
|
161
|
+
* one width and a vector index cannot span widths, so "every adapter agrees on the size" must be a property
|
|
162
|
+
* rather than a coincidence. The reference adapter accepted 768 while pgvector refused it, which is exactly the
|
|
163
|
+
* laxness that turns a production write failure into a passing test.
|
|
164
|
+
*
|
|
165
|
+
* 1536 is OpenAI's `text-embedding-3-small` and `-large` at its default reduction, and Cohere's v3 — the sizes
|
|
166
|
+
* a deployment is most likely to have. Changing it is a **migration**, not a re-index, which is why
|
|
167
|
+
* `EmbeddingModelRef` carries `dimensions` and a mismatch is refused rather than queued for re-embedding.
|
|
168
|
+
*/
|
|
169
|
+
export const EMBEDDING_DIMENSIONS = 1536;
|
|
170
|
+
export const KNOWLEDGE_SOURCE_TYPES = ["file", "artifact", "message", "external"];
|
|
171
|
+
/**
|
|
172
|
+
* The floor above which a vector hit is worth having (#136).
|
|
173
|
+
*
|
|
174
|
+
* 0.5 is orthogonal — see `VectorSearchHit.score` — so anything at or below it shares nothing with the query.
|
|
175
|
+
* 0.55 is comfortably above that and still admits a weak-but-real match. Without a floor, retrieval always
|
|
176
|
+
* returns *something*, and a model handed the least-bad chunk cites it: this constant is what makes an honest
|
|
177
|
+
* empty result possible at all.
|
|
178
|
+
*
|
|
179
|
+
* Deliberately absolute, unlike the fusion floor which is relative to the best hit. They answer different
|
|
180
|
+
* questions — "is this hit any good" and "is this hit much worse than the best" — and one instrument cannot do
|
|
181
|
+
* both: a relative floor can never reject a result set that is uniformly poor, because something is always the
|
|
182
|
+
* best of it.
|
|
183
|
+
*/
|
|
184
|
+
export const SEMANTIC_RELEVANCE_FLOOR = 0.55;
|
|
185
|
+
/**
|
|
186
|
+
* Words a keyword query drops (#136).
|
|
187
|
+
*
|
|
188
|
+
* On the port, like `EMBEDDING_DIMENSIONS`, because both adapters need the same list and a copy in each is a
|
|
189
|
+
* copy that drifts.
|
|
190
|
+
*
|
|
191
|
+
* **Why the query and not the index.** Postgres's `simple` text configuration is chosen deliberately over
|
|
192
|
+
* `english`: `english` stems, and stemming is exactly what destroys `ERR-4021` and `Q3-2026` — the terms
|
|
193
|
+
* keyword retrieval exists to find. But `simple` also keeps stopwords, so `was the site down` matches whichever
|
|
194
|
+
* document says `the` most often. Found by measuring hybrid against semantic-only, where a decoy sharing only
|
|
195
|
+
* `was` and `the` outranked the document that actually answered the question.
|
|
196
|
+
*
|
|
197
|
+
* Stripping them from the *query* keeps identifiers intact in the index while removing the terms that carry no
|
|
198
|
+
* retrieval signal. Small and English-only, which is honest: a deployment in another language needs its own
|
|
199
|
+
* list, and pretending otherwise would be worse than the list being visibly incomplete.
|
|
200
|
+
*/
|
|
201
|
+
export const KEYWORD_STOPWORDS = new Set([
|
|
202
|
+
"a", "about", "all", "also", "an", "and", "any", "are", "as", "at", "be", "been", "but", "by", "can",
|
|
203
|
+
"did", "do", "does", "for", "from", "had", "has", "have", "how", "i", "if", "in", "into", "is", "it",
|
|
204
|
+
"its", "just", "me", "my", "no", "not", "of", "on", "or", "our", "out", "over", "so", "some", "than",
|
|
205
|
+
"that", "the", "their", "them", "then", "there", "these", "they", "this", "to", "up", "us", "was",
|
|
206
|
+
"we", "were", "what", "when", "where", "which", "who", "why", "will", "with", "would", "you", "your",
|
|
207
|
+
]);
|
|
208
|
+
/**
|
|
209
|
+
* A keyword query with its stopwords removed.
|
|
210
|
+
*
|
|
211
|
+
* Returns the empty string when nothing survives, which callers treat as "no query" — a search for `the` is a
|
|
212
|
+
* search for nothing, and returning every document would be the worst possible answer.
|
|
213
|
+
*/
|
|
214
|
+
export const stripStopwords = (query) => (query.toLowerCase().match(/[a-z0-9]+(?:-[a-z0-9]+)*/g) ?? [])
|
|
215
|
+
.filter((term) => !KEYWORD_STOPWORDS.has(term))
|
|
216
|
+
.join(" ");
|
|
217
|
+
export const ADAPTER_CAPABILITIES = [
|
|
218
|
+
"transactions",
|
|
219
|
+
"row-level-security",
|
|
220
|
+
"full-text-search",
|
|
221
|
+
"vector-search",
|
|
222
|
+
"realtime",
|
|
223
|
+
"distributed-locking",
|
|
224
|
+
"durable-jobs",
|
|
225
|
+
];
|
|
226
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User-level (principal) memory — `docs/15` (referenced by REQ-006).
|
|
3
|
+
*
|
|
4
|
+
* Durable working memory scoped to a principal within a tenant: it persists across that principal's
|
|
5
|
+
* conversations, and is never visible to another principal or tenant. Memories are *extracted* from
|
|
6
|
+
* model output through a deterministic, validated, deduplicated step — raw model output is never
|
|
7
|
+
* stored directly. A budgeted context provider retrieves only the relevant entries and tags each
|
|
8
|
+
* with its provenance, so the context inspector can attribute which memories influenced a turn, and
|
|
9
|
+
* so it can never crowd out recent turns or session state (it draws from the user-context bucket).
|
|
10
|
+
*/
|
|
11
|
+
import { AgentPlatformError } from "../core/errors.js";
|
|
12
|
+
import type { ExecutionContext, Page, PageRequest, TenantScope } from "../core/context.js";
|
|
13
|
+
import type { PrincipalId } from "../core/ids.js";
|
|
14
|
+
import type { ContextProvider } from "../context/index.js";
|
|
15
|
+
export type PrincipalMemoryEntry = {
|
|
16
|
+
readonly id: string;
|
|
17
|
+
readonly tenantId: string;
|
|
18
|
+
readonly principalId: string;
|
|
19
|
+
readonly text: string;
|
|
20
|
+
readonly tags: readonly string[];
|
|
21
|
+
/** Higher wins when retrieval is budget-limited. */
|
|
22
|
+
readonly salience: number;
|
|
23
|
+
readonly version: number;
|
|
24
|
+
readonly createdAt: string;
|
|
25
|
+
readonly updatedAt: string;
|
|
26
|
+
/** Set when the user disables the entry; disabled entries are never retrieved for prompts. */
|
|
27
|
+
readonly disabledAt?: string;
|
|
28
|
+
};
|
|
29
|
+
export type MemoryPatch = {
|
|
30
|
+
readonly text?: string;
|
|
31
|
+
readonly tags?: readonly string[];
|
|
32
|
+
readonly salience?: number;
|
|
33
|
+
/** true disables, false re-enables. */
|
|
34
|
+
readonly disabled?: boolean;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Principal-scoped memory. Every method takes `{ tenantId, principalId }` explicitly, so a query can
|
|
38
|
+
* never reach another principal's or tenant's memory. `delete` is a hard delete — a deleted entry
|
|
39
|
+
* cannot resurface in a later prompt.
|
|
40
|
+
*/
|
|
41
|
+
export interface PrincipalMemoryStore {
|
|
42
|
+
put(input: TenantScope & {
|
|
43
|
+
principalId: PrincipalId;
|
|
44
|
+
id?: string;
|
|
45
|
+
text: string;
|
|
46
|
+
tags?: readonly string[];
|
|
47
|
+
salience?: number;
|
|
48
|
+
}): Promise<PrincipalMemoryEntry>;
|
|
49
|
+
get(input: TenantScope & {
|
|
50
|
+
principalId: PrincipalId;
|
|
51
|
+
id: string;
|
|
52
|
+
}): Promise<PrincipalMemoryEntry | null>;
|
|
53
|
+
list(input: TenantScope & {
|
|
54
|
+
principalId: PrincipalId;
|
|
55
|
+
} & PageRequest): Promise<Page<PrincipalMemoryEntry>>;
|
|
56
|
+
update(input: TenantScope & {
|
|
57
|
+
principalId: PrincipalId;
|
|
58
|
+
id: string;
|
|
59
|
+
expectedVersion: number;
|
|
60
|
+
patch: MemoryPatch;
|
|
61
|
+
}): Promise<PrincipalMemoryEntry>;
|
|
62
|
+
delete(input: TenantScope & {
|
|
63
|
+
principalId: PrincipalId;
|
|
64
|
+
id: string;
|
|
65
|
+
}): Promise<void>;
|
|
66
|
+
/** Active (not disabled) entries relevant to `query`, most salient first, capped at `limit`. */
|
|
67
|
+
retrieve(input: TenantScope & {
|
|
68
|
+
principalId: PrincipalId;
|
|
69
|
+
query?: string;
|
|
70
|
+
limit: number;
|
|
71
|
+
}): Promise<readonly PrincipalMemoryEntry[]>;
|
|
72
|
+
}
|
|
73
|
+
export declare const MEMORY_LIMITS: {
|
|
74
|
+
readonly textMaxLength: 1000;
|
|
75
|
+
readonly maxTagsPerEntry: 8;
|
|
76
|
+
};
|
|
77
|
+
export type MemoryCandidate = {
|
|
78
|
+
readonly text: string;
|
|
79
|
+
readonly tags?: readonly string[];
|
|
80
|
+
readonly salience?: number;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* The deterministic gate between model output and durable memory: trims, enforces bounds, and dedupes
|
|
84
|
+
* candidates against each other and existing entries by normalized text. Returns the accepted
|
|
85
|
+
* candidates to commit — so raw model output is never stored, only validated, unique memories.
|
|
86
|
+
*/
|
|
87
|
+
export declare const validateAndDedupe: (candidates: readonly MemoryCandidate[], existing: readonly PrincipalMemoryEntry[]) => readonly MemoryCandidate[];
|
|
88
|
+
/** Commit extracted candidates, skipping duplicates. Returns the entries actually stored. */
|
|
89
|
+
export declare const commitExtractedMemories: (store: PrincipalMemoryStore, input: TenantScope & {
|
|
90
|
+
principalId: PrincipalId;
|
|
91
|
+
candidates: readonly MemoryCandidate[];
|
|
92
|
+
}) => Promise<readonly PrincipalMemoryEntry[]>;
|
|
93
|
+
/**
|
|
94
|
+
* A budgeted context provider over principal memory. Retrieves only relevant, active entries under
|
|
95
|
+
* `maxEntries`, and emits them as `user-context` sections — so they never crowd out recent turns
|
|
96
|
+
* (history bucket) or session state. Each section's provenance carries the entry id for attribution.
|
|
97
|
+
*/
|
|
98
|
+
export declare const createPrincipalMemoryProvider: (config: {
|
|
99
|
+
readonly store: PrincipalMemoryStore;
|
|
100
|
+
readonly maxEntries?: number;
|
|
101
|
+
readonly estimateTokens?: (text: string) => number;
|
|
102
|
+
/** Optional query derived from the turn (e.g. the latest user message) to focus retrieval. */
|
|
103
|
+
readonly queryOf?: (context: ExecutionContext) => string | undefined;
|
|
104
|
+
}) => ContextProvider;
|
|
105
|
+
export declare const memoryConflict: (message: string) => AgentPlatformError;
|
|
106
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User-level (principal) memory — `docs/15` (referenced by REQ-006).
|
|
3
|
+
*
|
|
4
|
+
* Durable working memory scoped to a principal within a tenant: it persists across that principal's
|
|
5
|
+
* conversations, and is never visible to another principal or tenant. Memories are *extracted* from
|
|
6
|
+
* model output through a deterministic, validated, deduplicated step — raw model output is never
|
|
7
|
+
* stored directly. A budgeted context provider retrieves only the relevant entries and tags each
|
|
8
|
+
* with its provenance, so the context inspector can attribute which memories influenced a turn, and
|
|
9
|
+
* so it can never crowd out recent turns or session state (it draws from the user-context bucket).
|
|
10
|
+
*/
|
|
11
|
+
import { AgentPlatformError } from "../core/errors.js";
|
|
12
|
+
import { estimateTokens } from "../core/tokens.js";
|
|
13
|
+
export const MEMORY_LIMITS = { textMaxLength: 1_000, maxTagsPerEntry: 8 };
|
|
14
|
+
const normalize = (text) => text.trim().toLowerCase().replace(/\s+/g, " ");
|
|
15
|
+
/**
|
|
16
|
+
* The deterministic gate between model output and durable memory: trims, enforces bounds, and dedupes
|
|
17
|
+
* candidates against each other and existing entries by normalized text. Returns the accepted
|
|
18
|
+
* candidates to commit — so raw model output is never stored, only validated, unique memories.
|
|
19
|
+
*/
|
|
20
|
+
export const validateAndDedupe = (candidates, existing) => {
|
|
21
|
+
const seen = new Set(existing.map((e) => normalize(e.text)));
|
|
22
|
+
const accepted = [];
|
|
23
|
+
for (const candidate of candidates) {
|
|
24
|
+
const text = candidate.text.trim();
|
|
25
|
+
if (text.length === 0 || text.length > MEMORY_LIMITS.textMaxLength)
|
|
26
|
+
continue;
|
|
27
|
+
const key = normalize(text);
|
|
28
|
+
if (seen.has(key))
|
|
29
|
+
continue; // duplicate of an existing or already-accepted memory
|
|
30
|
+
seen.add(key);
|
|
31
|
+
const tags = (candidate.tags ?? []).slice(0, MEMORY_LIMITS.maxTagsPerEntry);
|
|
32
|
+
accepted.push({ text, tags, ...(candidate.salience === undefined ? {} : { salience: candidate.salience }) });
|
|
33
|
+
}
|
|
34
|
+
return accepted;
|
|
35
|
+
};
|
|
36
|
+
/** Commit extracted candidates, skipping duplicates. Returns the entries actually stored. */
|
|
37
|
+
export const commitExtractedMemories = async (store, input) => {
|
|
38
|
+
const existing = (await store.list({ tenantId: input.tenantId, principalId: input.principalId, limit: 1_000 })).items;
|
|
39
|
+
const accepted = validateAndDedupe(input.candidates, existing);
|
|
40
|
+
const stored = [];
|
|
41
|
+
for (const c of accepted) {
|
|
42
|
+
stored.push(await store.put({
|
|
43
|
+
tenantId: input.tenantId,
|
|
44
|
+
principalId: input.principalId,
|
|
45
|
+
text: c.text,
|
|
46
|
+
...(c.tags ? { tags: c.tags } : {}),
|
|
47
|
+
...(c.salience === undefined ? {} : { salience: c.salience }),
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
return stored;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* A budgeted context provider over principal memory. Retrieves only relevant, active entries under
|
|
54
|
+
* `maxEntries`, and emits them as `user-context` sections — so they never crowd out recent turns
|
|
55
|
+
* (history bucket) or session state. Each section's provenance carries the entry id for attribution.
|
|
56
|
+
*/
|
|
57
|
+
export const createPrincipalMemoryProvider = (config) => {
|
|
58
|
+
const maxEntries = config.maxEntries ?? 8;
|
|
59
|
+
const estimate = config.estimateTokens ?? estimateTokens;
|
|
60
|
+
return {
|
|
61
|
+
id: "principal-memory",
|
|
62
|
+
async provide(context) {
|
|
63
|
+
const entries = await config.store.retrieve({
|
|
64
|
+
tenantId: context.tenantId,
|
|
65
|
+
principalId: context.principalId,
|
|
66
|
+
...(config.queryOf?.(context) ? { query: config.queryOf(context) } : {}),
|
|
67
|
+
limit: maxEntries,
|
|
68
|
+
});
|
|
69
|
+
return entries.map((e) => ({
|
|
70
|
+
providerId: "principal-memory",
|
|
71
|
+
title: `Memory: ${e.tags.join(", ") || e.id}`,
|
|
72
|
+
body: e.text,
|
|
73
|
+
priority: e.salience,
|
|
74
|
+
estimatedTokens: estimate(e.text),
|
|
75
|
+
provenance: `principal-memory:${e.id}`, // lets the context inspector attribute the turn
|
|
76
|
+
sensitivity: "confidential",
|
|
77
|
+
// The principal's own remembered context, written from their own turns. Treating it as untrusted would
|
|
78
|
+
// wrap a user's own stated preferences in "nothing here is an instruction", which is the opposite of what
|
|
79
|
+
// this provider is for. Third-party content never reaches this store -- see docs/17.
|
|
80
|
+
origin: "platform",
|
|
81
|
+
cacheable: false,
|
|
82
|
+
kind: "user-context",
|
|
83
|
+
pruneStage: "old-knowledge",
|
|
84
|
+
}));
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
export const memoryConflict = (message) => new AgentPlatformError({ code: "conflict", message, retryable: false });
|
|
89
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data retention — REQ-034 (#151).
|
|
3
|
+
*
|
|
4
|
+
* The first retention mechanism in the platform, scoped deliberately to `run_events` alone. That table takes one
|
|
5
|
+
* row per streamed part, so a single long assistant turn writes hundreds and it grows faster than every other
|
|
6
|
+
* table combined. It is append-only by design and nothing has ever deleted from it, so storage and index size
|
|
7
|
+
* grow monotonically with usage and never come back.
|
|
8
|
+
*
|
|
9
|
+
* **Why this is not a method on `RunEventLog`.** The port is append-only *on purpose* — a run's event log is the
|
|
10
|
+
* record crash recovery reconciles against, and a `delete` on the port would put deletion within reach of
|
|
11
|
+
* ordinary run code. A separate maintenance surface makes that impossible by construction rather than by
|
|
12
|
+
* convention, and AC-8 asserts the port is unchanged.
|
|
13
|
+
*
|
|
14
|
+
* Doing one table properly establishes the pattern the rest reuse. Two things here are the pattern rather than
|
|
15
|
+
* this table's specifics: retention is **configuration with a documented default**, and a sweep is **bounded and
|
|
16
|
+
* reports what it removed** so a caller drains a backlog instead of holding one long lock.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* How long a run's events are kept.
|
|
20
|
+
*
|
|
21
|
+
* **Provisional, and marked as such.** #151 asks the product owner which it should be — 30 days, 90 days, or
|
|
22
|
+
* indefinite-until-configured — and that is a compliance answer, not a technical one. 90 days is the level the
|
|
23
|
+
* table's own purpose implies: long enough that a customer investigating last quarter's run still has its log,
|
|
24
|
+
* short enough that the largest table in the schema does not grow without bound. Nobody has agreed to it.
|
|
25
|
+
*
|
|
26
|
+
* A deployment overrides it. The default exists so an unconfigured deployment prunes *something* rather than
|
|
27
|
+
* nothing — the failure direction being "an old log was removed" rather than "the disk filled".
|
|
28
|
+
*/
|
|
29
|
+
export declare const DEFAULT_RUN_EVENT_RETENTION_DAYS = 90;
|
|
30
|
+
/**
|
|
31
|
+
* The statuses whose events may be pruned.
|
|
32
|
+
*
|
|
33
|
+
* Terminal only, and this is the safety property AC-2 names. A `running`, `queued`, `waiting-for-*` or
|
|
34
|
+
* `retry-pending` run can still be reconciled against its log — that is precisely what #93/#94 exist to provide
|
|
35
|
+
* — so deleting its events breaks crash recovery for a run that is still alive. Age is irrelevant to that: a
|
|
36
|
+
* run waiting on a human approval for four months is old *and* still needs its log.
|
|
37
|
+
*
|
|
38
|
+
* Written here rather than inlined in SQL so the list has one home, and so a new non-terminal status cannot
|
|
39
|
+
* silently become prunable by not being mentioned.
|
|
40
|
+
*/
|
|
41
|
+
export declare const PRUNABLE_RUN_STATUSES: readonly string[];
|
|
42
|
+
export type PruneRequest = {
|
|
43
|
+
/** Delete events created strictly before this instant. ISO-8601. */
|
|
44
|
+
readonly olderThan: string;
|
|
45
|
+
/**
|
|
46
|
+
* Rows per call. Bounded, because an unbounded `DELETE` over this table takes a long-lived lock and blocks the
|
|
47
|
+
* live appends that are the reason the table exists.
|
|
48
|
+
*/
|
|
49
|
+
readonly limit: number;
|
|
50
|
+
};
|
|
51
|
+
export type PruneResult = {
|
|
52
|
+
/**
|
|
53
|
+
* Rows actually removed.
|
|
54
|
+
*
|
|
55
|
+
* The caller's loop condition. Returning it rather than a boolean is what lets `drain` know whether a full
|
|
56
|
+
* batch means "more to do" — and it is the number an operator needs to see that retention is running at all.
|
|
57
|
+
*/
|
|
58
|
+
readonly deleted: number;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* The maintenance surface. Narrow on purpose: one operation, and nothing that reads or writes a run.
|
|
62
|
+
*/
|
|
63
|
+
export interface RunEventPruner {
|
|
64
|
+
prune(input: PruneRequest): Promise<PruneResult>;
|
|
65
|
+
}
|
|
66
|
+
/** The cutoff for a retention period, from a clock. Exported so a caller does not recompute the arithmetic. */
|
|
67
|
+
export declare const cutoffFor: (input: {
|
|
68
|
+
readonly now: number;
|
|
69
|
+
readonly retentionDays: number;
|
|
70
|
+
}) => string;
|
|
71
|
+
/**
|
|
72
|
+
* Drain a backlog by calling `prune` until it stops removing rows.
|
|
73
|
+
*
|
|
74
|
+
* A helper rather than a loop inside `prune`, because the two have different failure modes: one long call that
|
|
75
|
+
* dies halfway leaves an operator with no idea how far it got, whereas a loop over bounded calls has made
|
|
76
|
+
* durable progress after every iteration.
|
|
77
|
+
*
|
|
78
|
+
* `maxBatches` is a required ceiling, not an optional one. A loop whose termination depends on the database
|
|
79
|
+
* eventually returning zero is a loop that runs forever the day a bug makes `prune` return a positive count
|
|
80
|
+
* without deleting anything — and it would run forever *inside a maintenance job*, where nobody is watching.
|
|
81
|
+
*/
|
|
82
|
+
export declare const drain: (pruner: RunEventPruner, input: PruneRequest & {
|
|
83
|
+
readonly maxBatches: number;
|
|
84
|
+
}) => Promise<{
|
|
85
|
+
readonly deleted: number;
|
|
86
|
+
readonly batches: number;
|
|
87
|
+
readonly drained: boolean;
|
|
88
|
+
}>;
|
|
89
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data retention — REQ-034 (#151).
|
|
3
|
+
*
|
|
4
|
+
* The first retention mechanism in the platform, scoped deliberately to `run_events` alone. That table takes one
|
|
5
|
+
* row per streamed part, so a single long assistant turn writes hundreds and it grows faster than every other
|
|
6
|
+
* table combined. It is append-only by design and nothing has ever deleted from it, so storage and index size
|
|
7
|
+
* grow monotonically with usage and never come back.
|
|
8
|
+
*
|
|
9
|
+
* **Why this is not a method on `RunEventLog`.** The port is append-only *on purpose* — a run's event log is the
|
|
10
|
+
* record crash recovery reconciles against, and a `delete` on the port would put deletion within reach of
|
|
11
|
+
* ordinary run code. A separate maintenance surface makes that impossible by construction rather than by
|
|
12
|
+
* convention, and AC-8 asserts the port is unchanged.
|
|
13
|
+
*
|
|
14
|
+
* Doing one table properly establishes the pattern the rest reuse. Two things here are the pattern rather than
|
|
15
|
+
* this table's specifics: retention is **configuration with a documented default**, and a sweep is **bounded and
|
|
16
|
+
* reports what it removed** so a caller drains a backlog instead of holding one long lock.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* How long a run's events are kept.
|
|
20
|
+
*
|
|
21
|
+
* **Provisional, and marked as such.** #151 asks the product owner which it should be — 30 days, 90 days, or
|
|
22
|
+
* indefinite-until-configured — and that is a compliance answer, not a technical one. 90 days is the level the
|
|
23
|
+
* table's own purpose implies: long enough that a customer investigating last quarter's run still has its log,
|
|
24
|
+
* short enough that the largest table in the schema does not grow without bound. Nobody has agreed to it.
|
|
25
|
+
*
|
|
26
|
+
* A deployment overrides it. The default exists so an unconfigured deployment prunes *something* rather than
|
|
27
|
+
* nothing — the failure direction being "an old log was removed" rather than "the disk filled".
|
|
28
|
+
*/
|
|
29
|
+
export const DEFAULT_RUN_EVENT_RETENTION_DAYS = 90;
|
|
30
|
+
/**
|
|
31
|
+
* The statuses whose events may be pruned.
|
|
32
|
+
*
|
|
33
|
+
* Terminal only, and this is the safety property AC-2 names. A `running`, `queued`, `waiting-for-*` or
|
|
34
|
+
* `retry-pending` run can still be reconciled against its log — that is precisely what #93/#94 exist to provide
|
|
35
|
+
* — so deleting its events breaks crash recovery for a run that is still alive. Age is irrelevant to that: a
|
|
36
|
+
* run waiting on a human approval for four months is old *and* still needs its log.
|
|
37
|
+
*
|
|
38
|
+
* Written here rather than inlined in SQL so the list has one home, and so a new non-terminal status cannot
|
|
39
|
+
* silently become prunable by not being mentioned.
|
|
40
|
+
*/
|
|
41
|
+
export const PRUNABLE_RUN_STATUSES = ["completed", "failed", "cancelled"];
|
|
42
|
+
/** The cutoff for a retention period, from a clock. Exported so a caller does not recompute the arithmetic. */
|
|
43
|
+
export const cutoffFor = (input) => new Date(input.now - input.retentionDays * 86_400_000).toISOString();
|
|
44
|
+
/**
|
|
45
|
+
* Drain a backlog by calling `prune` until it stops removing rows.
|
|
46
|
+
*
|
|
47
|
+
* A helper rather than a loop inside `prune`, because the two have different failure modes: one long call that
|
|
48
|
+
* dies halfway leaves an operator with no idea how far it got, whereas a loop over bounded calls has made
|
|
49
|
+
* durable progress after every iteration.
|
|
50
|
+
*
|
|
51
|
+
* `maxBatches` is a required ceiling, not an optional one. A loop whose termination depends on the database
|
|
52
|
+
* eventually returning zero is a loop that runs forever the day a bug makes `prune` return a positive count
|
|
53
|
+
* without deleting anything — and it would run forever *inside a maintenance job*, where nobody is watching.
|
|
54
|
+
*/
|
|
55
|
+
export const drain = async (pruner, input) => {
|
|
56
|
+
let deleted = 0;
|
|
57
|
+
let batches = 0;
|
|
58
|
+
for (; batches < input.maxBatches; batches += 1) {
|
|
59
|
+
const result = await pruner.prune({ olderThan: input.olderThan, limit: input.limit });
|
|
60
|
+
deleted += result.deleted;
|
|
61
|
+
// A short batch means the backlog is exhausted. Checking the count rather than issuing one more empty call
|
|
62
|
+
// saves a full index scan per drain, which on this table is not free.
|
|
63
|
+
if (result.deleted < input.limit)
|
|
64
|
+
return { deleted, batches: batches + 1, drained: true };
|
|
65
|
+
}
|
|
66
|
+
// `drained: false` says the ceiling was hit, so a caller can log that there is more to do rather than assuming
|
|
67
|
+
// the table is clean. Silence here would look identical to a finished sweep.
|
|
68
|
+
return { deleted, batches, drained: false };
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run checkpoints — `docs/04-durable-runtime-and-hitl.md` → Durable execution.
|
|
3
|
+
*
|
|
4
|
+
* A checkpoint is the durable snapshot the worker writes as a run streams. It is what lets a page
|
|
5
|
+
* refresh lose no output and a crashed worker recover: a new claim reloads the latest checkpoint,
|
|
6
|
+
* finalizes any tool calls that were mid-flight, and continues from there.
|
|
7
|
+
*/
|
|
8
|
+
import type { MessagePart } from "../core/content-parts.js";
|
|
9
|
+
import type { RunId, ToolCallId } from "../core/ids.js";
|
|
10
|
+
/** A tool call the runtime started but has not yet seen complete — reconciled on recovery. */
|
|
11
|
+
export type PendingToolCall = {
|
|
12
|
+
readonly toolCallId: ToolCallId;
|
|
13
|
+
readonly toolName: string;
|
|
14
|
+
readonly startedAt: string;
|
|
15
|
+
};
|
|
16
|
+
/** Running token/cost totals, checkpointed so a recovered run keeps accounting continuity. */
|
|
17
|
+
export type RunUsageTotals = {
|
|
18
|
+
readonly inputTokens: number;
|
|
19
|
+
readonly outputTokens: number;
|
|
20
|
+
readonly costMinorUnits: number;
|
|
21
|
+
};
|
|
22
|
+
export declare const EMPTY_USAGE_TOTALS: RunUsageTotals;
|
|
23
|
+
export type RunCheckpoint = {
|
|
24
|
+
readonly runId: RunId;
|
|
25
|
+
/** Highest event sequence durably persisted. A reconnecting client resumes with `after: sequence`. */
|
|
26
|
+
readonly sequence: number;
|
|
27
|
+
/** Accumulated parts of the assistant message being produced, in order. */
|
|
28
|
+
readonly parts: readonly MessagePart[];
|
|
29
|
+
/** Step index reached in the agent loop, bounded by `ExecutionLimits.maxSteps`. */
|
|
30
|
+
readonly step: number;
|
|
31
|
+
/** Tool calls started but not yet completed. Non-empty after a crash → finalized on recovery. */
|
|
32
|
+
readonly pendingToolCalls: readonly PendingToolCall[];
|
|
33
|
+
readonly usage: RunUsageTotals;
|
|
34
|
+
readonly updatedAt: string;
|
|
35
|
+
};
|
|
36
|
+
export declare const emptyCheckpoint: (runId: RunId, updatedAt: string) => RunCheckpoint;
|
|
37
|
+
//# sourceMappingURL=checkpoint.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run checkpoints — `docs/04-durable-runtime-and-hitl.md` → Durable execution.
|
|
3
|
+
*
|
|
4
|
+
* A checkpoint is the durable snapshot the worker writes as a run streams. It is what lets a page
|
|
5
|
+
* refresh lose no output and a crashed worker recover: a new claim reloads the latest checkpoint,
|
|
6
|
+
* finalizes any tool calls that were mid-flight, and continues from there.
|
|
7
|
+
*/
|
|
8
|
+
export const EMPTY_USAGE_TOTALS = {
|
|
9
|
+
inputTokens: 0,
|
|
10
|
+
outputTokens: 0,
|
|
11
|
+
costMinorUnits: 0,
|
|
12
|
+
};
|
|
13
|
+
export const emptyCheckpoint = (runId, updatedAt) => ({
|
|
14
|
+
runId,
|
|
15
|
+
sequence: 0,
|
|
16
|
+
parts: [],
|
|
17
|
+
step: 0,
|
|
18
|
+
pendingToolCalls: [],
|
|
19
|
+
usage: EMPTY_USAGE_TOTALS,
|
|
20
|
+
updatedAt,
|
|
21
|
+
});
|
|
22
|
+
//# sourceMappingURL=checkpoint.js.map
|