@yielded/agent 0.1.0-beta.173 → 0.1.0-beta.175
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/dist/{Admin-BX9ns28E.d.mts → Admin-Qa3I1oA5.d.mts} +61 -21
- package/dist/{Agent-9aBoIi74.d.mts → Agent-B39jRnFv.d.mts} +2 -2
- package/dist/{Agent-0WvBWWbM.mjs → Agent-BiRbr73L.mjs} +7 -6
- package/dist/Agent-BiRbr73L.mjs.map +1 -0
- package/dist/{AgentRuntime-BfP14534.d.mts → AgentRuntime-CHDyRbSf.d.mts} +12 -12
- package/dist/{AgentRuntime-CQ-qcETl.mjs → AgentRuntime-DaDKMasp.mjs} +290 -273
- package/dist/AgentRuntime-DaDKMasp.mjs.map +1 -0
- package/dist/{Digest-DCuPlhNk.mjs → Digest-C3EODOee.mjs} +42 -15
- package/dist/Digest-C3EODOee.mjs.map +1 -0
- package/dist/{DurableAgentRuntime-BAmSkWYr.mjs → DurableAgentRuntime-CPlw5_7e.mjs} +1557 -1458
- package/dist/DurableAgentRuntime-CPlw5_7e.mjs.map +1 -0
- package/dist/{EventSource-BwliwQz9.d.mts → EventSource-BTu68yDW.d.mts} +2 -2
- package/dist/InMemory.d.mts +2 -2
- package/dist/{MessageDelivery-B943ebI_.d.mts → MessageDelivery-DjAZJ4Fd.d.mts} +42 -42
- package/dist/{Messaging-C_6OOg_s.d.mts → Messaging-SVu6rWV8.d.mts} +12 -6
- package/dist/{MessagingHost-B8oKM7AC.d.mts → MessagingHost-C6SOAcoG.d.mts} +2 -2
- package/dist/{MessagingHost-CRUK4JBi.mjs → MessagingHost-CZCyrnvJ.mjs} +27 -26
- package/dist/MessagingHost-CZCyrnvJ.mjs.map +1 -0
- package/dist/{Output-Dsx6k52t.d.mts → Output-CRamN1Fy.d.mts} +2 -2
- package/dist/{PreparedInputAdmission-CxSJSiTl.d.mts → PreparedInputAdmission-wgY4JMZY.d.mts} +3 -3
- package/dist/{Records-BiuJDWNe.mjs → Records-DzL4Kbtw.mjs} +2 -2
- package/dist/{Records-BiuJDWNe.mjs.map → Records-DzL4Kbtw.mjs.map} +1 -1
- package/dist/{RunContinuation-FHM7XPjq.d.mts → RunContinuation-3jB5pULC.d.mts} +13 -7
- package/dist/{RunContinuation-DHYNAQFi.mjs → RunContinuation-BiyKJK32.mjs} +173 -82
- package/dist/RunContinuation-BiyKJK32.mjs.map +1 -0
- package/dist/{RunJournal-kfKVxJj7.mjs → RunJournal-CPMKcfd0.mjs} +106 -73
- package/dist/RunJournal-CPMKcfd0.mjs.map +1 -0
- package/dist/{RunOptions-D8zxFIrZ.d.mts → RunOptions-Be77lKVZ.d.mts} +2 -2
- package/dist/{RunStorage-uqPxps09.mjs → RunStorage-CzutHJBE.mjs} +10 -6
- package/dist/RunStorage-CzutHJBE.mjs.map +1 -0
- package/dist/{Scheduling-CVyfXlBR.mjs → Scheduling-07_dsGED.mjs} +12 -12
- package/dist/Scheduling-07_dsGED.mjs.map +1 -0
- package/dist/{Subagent-vpffemql.mjs → Subagent-CexndZSp.mjs} +53 -40
- package/dist/Subagent-CexndZSp.mjs.map +1 -0
- package/dist/{Subagent-E6tvd7-k.d.mts → Subagent-xhN_aD1r.d.mts} +20 -9
- package/dist/{SubagentHost-B6w2m-SI.d.mts → SubagentHost-D1xBgn9g.d.mts} +2 -2
- package/dist/{Subscription-DONig54Q.d.mts → Subscription-DmIHlOJK.d.mts} +2 -2
- package/dist/{SubscriptionInput-mJIRxWJM.d.mts → SubscriptionInput-DgcQhvbe.d.mts} +2 -2
- package/dist/{Thread-dk-QiNml.d.mts → Thread-DzdJAY4J.d.mts} +4 -3
- package/dist/{ThreadHistory-ByxS8HU1.d.mts → ThreadHistory-KPPBJLJb.d.mts} +12 -2
- package/dist/{ThreadImport-DckUMEqJ.mjs → ThreadImport-CjlG57vH.mjs} +9 -9
- package/dist/ThreadImport-CjlG57vH.mjs.map +1 -0
- package/dist/{ThreadImport-DpHxjBrA.d.mts → ThreadImport-DP-vOk2F.d.mts} +5 -5
- package/dist/{ThreadStore-CEekRa80.mjs → ThreadStore-EuUilthA.mjs} +162 -85
- package/dist/ThreadStore-EuUilthA.mjs.map +1 -0
- package/dist/{ThreadTransfer-B4gTQLIl.mjs → ThreadTransfer-DB_zsrtJ.mjs} +4 -4
- package/dist/{ThreadTransfer-B4gTQLIl.mjs.map → ThreadTransfer-DB_zsrtJ.mjs.map} +1 -1
- package/dist/{WorkerAdmission-DFVbbVh2.mjs → WorkerAdmission-eBeXt_mu.mjs} +5 -5
- package/dist/{WorkerAdmission-DFVbbVh2.mjs.map → WorkerAdmission-eBeXt_mu.mjs.map} +1 -1
- package/dist/{agent-registration-ByMZ_cK5.mjs → agent-registration-a6QYaG3h.mjs} +70 -57
- package/dist/agent-registration-a6QYaG3h.mjs.map +1 -0
- package/dist/capabilities/Approval.mjs +2 -2
- package/dist/capabilities/Approval.mjs.map +1 -1
- package/dist/capabilities/BrowserUse.d.mts +102 -1867
- package/dist/capabilities/BrowserUse.mjs +74 -798
- package/dist/capabilities/BrowserUse.mjs.map +1 -1
- package/dist/capabilities/Budget.mjs +3 -1
- package/dist/capabilities/Budget.mjs.map +1 -1
- package/dist/capabilities/CodeMode.d.mts +1 -1
- package/dist/capabilities/CodeMode.mjs +16 -9
- package/dist/capabilities/CodeMode.mjs.map +1 -1
- package/dist/capabilities/Commands.d.mts +1 -1
- package/dist/capabilities/McpClient.mjs +1 -1
- package/dist/capabilities/McpClient.mjs.map +1 -1
- package/dist/capabilities/Messaging.d.mts +1 -1
- package/dist/capabilities/Messaging.mjs +5 -5
- package/dist/capabilities/Messaging.mjs.map +1 -1
- package/dist/capabilities/ModelContext.d.mts +1 -1
- package/dist/capabilities/ModelContext.mjs +7 -5
- package/dist/capabilities/ModelContext.mjs.map +1 -1
- package/dist/capabilities/Redaction.mjs +49 -19
- package/dist/capabilities/Redaction.mjs.map +1 -1
- package/dist/capabilities/RunHooks.d.mts +2 -2
- package/dist/capabilities/RunHooks.mjs +1 -1
- package/dist/capabilities/RunHooks.mjs.map +1 -1
- package/dist/capabilities/Subagent.d.mts +1 -1
- package/dist/capabilities/Subagent.mjs +1 -1
- package/dist/capabilities/SubagentReservations.mjs +3 -1
- package/dist/capabilities/SubagentReservations.mjs.map +1 -1
- package/dist/capabilities/WebCapture.mjs.map +1 -1
- package/dist/capabilities/WebSearch.mjs +7 -7
- package/dist/capabilities/WebSearch.mjs.map +1 -1
- package/dist/core/Agent.d.mts +1 -1
- package/dist/core/Agent.mjs +1 -1
- package/dist/core/AgentUpdates.mjs +8 -8
- package/dist/core/AgentUpdates.mjs.map +1 -1
- package/dist/core/Thread.d.mts +2 -2
- package/dist/core/Thread.mjs +6 -4
- package/dist/core/Thread.mjs.map +1 -1
- package/dist/core/Usage.mjs +2 -2
- package/dist/core/Usage.mjs.map +1 -1
- package/dist/durable/ActivityStore.mjs +1 -1
- package/dist/durable/Admin.d.mts +1 -1
- package/dist/durable/Admin.mjs +1 -1
- package/dist/durable/AgentRegistration.d.mts +1 -1
- package/dist/durable/AgentRegistration.mjs +1 -1
- package/dist/durable/Certification.d.mts +1 -1
- package/dist/durable/CommittedActivity.d.mts +1 -1
- package/dist/durable/CommittedActivity.mjs +3 -3
- package/dist/durable/Digest.mjs +1 -1
- package/dist/durable/DurableAgentRuntime.d.mts +1 -1
- package/dist/durable/DurableAgentRuntime.mjs +2 -2
- package/dist/durable/EventSource.d.mts +1 -1
- package/dist/durable/EventSource.mjs +7 -7
- package/dist/durable/EventSource.mjs.map +1 -1
- package/dist/durable/GitHubWorkflowSource.d.mts +3 -3
- package/dist/durable/LifecyclePublication.d.mts +1 -1
- package/dist/durable/LifecyclePublication.mjs +2 -2
- package/dist/durable/MessageDelivery.d.mts +1 -1
- package/dist/durable/MessageDelivery.mjs +2 -2
- package/dist/durable/MessageDeliveryStoreConformance.d.mts +40 -40
- package/dist/durable/MessageDeliveryStoreConformance.mjs +2 -2
- package/dist/durable/PersistentHistory.d.mts +2 -2
- package/dist/durable/PersistentHistory.mjs +4 -4
- package/dist/durable/PreparedInputAdmission.d.mts +1 -1
- package/dist/durable/RecordFormat.mjs +3 -3
- package/dist/durable/RecordFormat.mjs.map +1 -1
- package/dist/durable/Records.mjs +1 -1
- package/dist/durable/Recovery.d.mts +1 -1
- package/dist/durable/Recovery.mjs +1 -1
- package/dist/durable/RunContinuation.d.mts +2 -2
- package/dist/durable/RunContinuation.mjs +3 -3
- package/dist/durable/RunJournal.d.mts +2 -2
- package/dist/durable/RunJournal.mjs +2 -2
- package/dist/durable/RunStorage.d.mts +1 -1
- package/dist/durable/RunStorage.mjs +1 -1
- package/dist/durable/Schedule.mjs +1 -1
- package/dist/durable/ScheduleStoreConformance.mjs +1 -1
- package/dist/durable/ScheduleTransition.mjs +1 -1
- package/dist/durable/Scheduling.d.mts +1 -1
- package/dist/durable/Scheduling.mjs +1 -1
- package/dist/durable/SettlementPublisher.d.mts +1 -1
- package/dist/durable/SettlementPublisher.mjs +3 -3
- package/dist/durable/SqlMemoryStore.mjs +5 -3
- package/dist/durable/SqlMemoryStore.mjs.map +1 -1
- package/dist/durable/SubmissionLedger.d.mts +1 -1
- package/dist/durable/SubmissionLedger.mjs +11 -3
- package/dist/durable/SubmissionLedger.mjs.map +1 -1
- package/dist/durable/SubmissionLedgerConformance.d.mts +1 -1
- package/dist/durable/SubmissionLedgerConformance.mjs +6 -6
- package/dist/durable/SubmissionStatus.d.mts +1 -1
- package/dist/durable/Subscription.d.mts +1 -1
- package/dist/durable/Subscription.mjs +2 -2
- package/dist/durable/SubscriptionInput.d.mts +1 -1
- package/dist/durable/SubscriptionInput.mjs +4 -4
- package/dist/durable/SubscriptionInput.mjs.map +1 -1
- package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
- package/dist/durable/SubscriptionStoreConformance.mjs +3 -3
- package/dist/durable/SubscriptionStoreConformance.mjs.map +1 -1
- package/dist/durable/SubscriptionTools.d.mts +2 -2
- package/dist/durable/SubscriptionTransition.d.mts +1 -1
- package/dist/durable/SubscriptionTransition.mjs +1 -1
- package/dist/durable/Subscriptions.d.mts +5 -5
- package/dist/durable/Subscriptions.mjs +3 -3
- package/dist/durable/Subscriptions.mjs.map +1 -1
- package/dist/durable/ThreadArchiveRange.d.mts +1 -1
- package/dist/durable/ThreadArchiveRange.mjs +1 -1
- package/dist/durable/ThreadContextHistory.d.mts +1 -1
- package/dist/durable/ThreadContextHistory.mjs +2 -2
- package/dist/durable/ThreadContextHistoryProjection.mjs +1 -1
- package/dist/durable/ThreadImport.d.mts +1 -1
- package/dist/durable/ThreadImport.mjs +1 -1
- package/dist/durable/ThreadInvariants.d.mts +3 -3
- package/dist/durable/ThreadInvariants.mjs +5 -5
- package/dist/durable/ThreadInvariants.mjs.map +1 -1
- package/dist/durable/ThreadProjection.mjs +1 -1
- package/dist/durable/ThreadProjectionMaintenance.d.mts +1 -1
- package/dist/durable/ThreadReader.d.mts +1 -1
- package/dist/durable/ThreadReader.mjs +1 -1
- package/dist/durable/ThreadStore.d.mts +1 -1
- package/dist/durable/ThreadStore.mjs +2 -2
- package/dist/durable/ThreadStoreConformance.d.mts +1 -1
- package/dist/durable/ThreadStoreConformance.mjs +4 -4
- package/dist/durable/ThreadTransfer.d.mts +1 -1
- package/dist/durable/ThreadTransfer.mjs +1 -1
- package/dist/durable/ThreadWork.d.mts +2 -2
- package/dist/durable/ThreadWork.mjs +12 -6
- package/dist/durable/ThreadWork.mjs.map +1 -1
- package/dist/durable/ToolReconciler.mjs +1 -1
- package/dist/durable/WakeScheduler.mjs +23 -39
- package/dist/durable/WakeScheduler.mjs.map +1 -1
- package/dist/durable/WorkerAdmission.d.mts +1 -1
- package/dist/durable/WorkerAdmission.mjs +1 -1
- package/dist/durable/WorkerHost.d.mts +2 -2
- package/dist/engine/AgentRuntime.d.mts +1 -1
- package/dist/engine/AgentRuntime.mjs +1 -1
- package/dist/engine/MessagingHost.d.mts +1 -1
- package/dist/engine/MessagingHost.mjs +1 -1
- package/dist/engine/Output.d.mts +1 -1
- package/dist/engine/Output.mjs +1 -1
- package/dist/engine/RunOptions.d.mts +1 -1
- package/dist/engine/SubagentHost.d.mts +1 -1
- package/dist/engine/ThreadHistory.d.mts +1 -1
- package/dist/engine/ThreadHistory.mjs +3 -2
- package/dist/engine/ThreadHistory.mjs.map +1 -1
- package/dist/index.d.mts +21 -21
- package/dist/index.mjs +16 -16
- package/dist/{output-contract-CMIhu4Cw.mjs → output-contract-DCnLYCdp.mjs} +12 -15
- package/dist/{output-contract-CMIhu4Cw.mjs.map → output-contract-DCnLYCdp.mjs.map} +1 -1
- package/dist/{run-context-reader-OcsZr4bk.d.mts → run-context-reader-DVhJZ1Qe.d.mts} +2 -2
- package/package.json +1 -1
- package/src/capabilities/Approval.ts +58 -60
- package/src/capabilities/BrowserUse.ts +89 -944
- package/src/capabilities/Budget.ts +8 -1
- package/src/capabilities/CodeMode.ts +57 -33
- package/src/capabilities/McpClient.ts +2 -2
- package/src/capabilities/Messaging.ts +51 -55
- package/src/capabilities/ModelContext.ts +5 -2
- package/src/capabilities/Redaction.ts +64 -34
- package/src/capabilities/RunHooks.ts +52 -55
- package/src/capabilities/Subagent.ts +33 -33
- package/src/capabilities/SubagentReservations.ts +9 -1
- package/src/capabilities/WebCapture.ts +6 -0
- package/src/capabilities/WebSearch.ts +10 -7
- package/src/capabilities/internal/subagent-background.ts +202 -158
- package/src/core/Agent.ts +11 -6
- package/src/core/AgentUpdates.ts +8 -8
- package/src/core/Thread.ts +142 -146
- package/src/core/Usage.ts +7 -8
- package/src/core/internal/agent-updates.ts +1 -0
- package/src/durable/DurableAgentRuntime.ts +1024 -829
- package/src/durable/EventSource.ts +15 -9
- package/src/durable/RecordFormat.ts +5 -3
- package/src/durable/RunContinuation.ts +316 -113
- package/src/durable/RunJournal.ts +106 -114
- package/src/durable/RunStorage.ts +129 -124
- package/src/durable/Scheduling.ts +639 -651
- package/src/durable/SqlMemoryStore.ts +8 -6
- package/src/durable/SubmissionLedger.ts +11 -0
- package/src/durable/SubscriptionInput.ts +5 -3
- package/src/durable/SubscriptionStoreConformance.ts +23 -23
- package/src/durable/Subscriptions.ts +18 -19
- package/src/durable/ThreadImport.ts +18 -19
- package/src/durable/ThreadInvariants.ts +2 -1
- package/src/durable/ThreadStore.ts +217 -111
- package/src/durable/ThreadWork.ts +11 -2
- package/src/durable/WakeScheduler.ts +34 -66
- package/src/durable/internal/StorageOwner.ts +10 -4
- package/src/durable/internal/agent-registration.ts +96 -89
- package/src/durable/internal/canonical-json.ts +61 -20
- package/src/durable/internal/prompt-history-cache.ts +13 -4
- package/src/durable/internal/record-encoding.ts +120 -64
- package/src/durable/internal/schedule-time.ts +6 -6
- package/src/durable/internal/usage-totals.ts +35 -0
- package/src/durable/internal/worker-host.ts +69 -74
- package/src/engine/MessagingHost.ts +4 -2
- package/src/engine/ThreadHistory.ts +47 -48
- package/src/engine/internal/agent-runtime.ts +1298 -1217
- package/src/engine/internal/output-contract.ts +15 -15
- package/src/engine/internal/primitive-delta.ts +2 -3
- package/src/engine/internal/provisional-text.ts +12 -10
- package/src/engine/internal/tool-exposure.ts +22 -18
- package/src/engine/internal/tool-telemetry.ts +15 -12
- package/dist/Agent-0WvBWWbM.mjs.map +0 -1
- package/dist/AgentRuntime-CQ-qcETl.mjs.map +0 -1
- package/dist/Digest-DCuPlhNk.mjs.map +0 -1
- package/dist/DurableAgentRuntime-BAmSkWYr.mjs.map +0 -1
- package/dist/MessagingHost-CRUK4JBi.mjs.map +0 -1
- package/dist/RunContinuation-DHYNAQFi.mjs.map +0 -1
- package/dist/RunJournal-kfKVxJj7.mjs.map +0 -1
- package/dist/RunStorage-uqPxps09.mjs.map +0 -1
- package/dist/Scheduling-CVyfXlBR.mjs.map +0 -1
- package/dist/Subagent-vpffemql.mjs.map +0 -1
- package/dist/ThreadImport-DckUMEqJ.mjs.map +0 -1
- package/dist/ThreadStore-CEekRa80.mjs.map +0 -1
- package/dist/agent-registration-ByMZ_cK5.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Messaging.mjs","names":[],"sources":["../../src/capabilities/Messaging.ts"],"sourcesContent":["import { Crypto, Effect, Option, Schema } from \"effect\";\nimport { Tool, Toolkit } from \"effect/ai\";\nimport { Hex } from \"effect/encoding\";\n\nimport type { AnyDefinition } from \"../core/Agent.ts\";\nimport {\n InboxPage,\n MessageRef,\n MessageStatus,\n MessagingError,\n PeerName,\n} from \"../core/Messaging.ts\";\nimport { IdempotencyKey } from \"../core/Receipt.ts\";\nimport { WorkerOperationTool } from \"../core/SubagentContract.ts\";\nimport { MessagingHost } from \"../engine/MessagingHost.ts\";\nimport { utf8Bytes } from \"./internal/utf8.ts\";\n\nexport * from \"../core/Messaging.ts\";\n\n/** A fixed host route and its destination-owned input Schema. Construction acquires no resources. */\nexport interface Peer<Name extends string, Input extends Schema.Top> {\n readonly name: Name;\n readonly target: AnyDefinition & { readonly input: Input };\n}\n\nexport const peer = <const Name extends string, Input extends Schema.Top>(\n name: Name,\n options: { readonly target: AnyDefinition & { readonly input: Input } },\n): Peer<Name, Input> => {\n Schema.decodeSync(PeerName)(name);\n\n return Object.freeze({ name, target: options.target });\n};\n\nconst host: Effect.Effect<MessagingHost[\"Service\"], MessagingError, MessagingHost> =\n Effect.serviceOption(MessagingHost).pipe(\n Effect.flatMap((value) =>\n Option.isSome(value)\n ? Effect.succeed(value.value)\n : MessagingError.make({ operation: \"context\", reason: \"unavailable\" }),\n ),\n );\n\nconst dispatch = <Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n input: Input[\"Type\"],\n options: { readonly idempotencyKey: IdempotencyKey; readonly inReplyTo?: MessageRef },\n operation: \"send\" | \"reply\",\n) =>\n Effect.gen(function* () {\n const service = yield* host;\n const invalid = () => MessagingError.make({ operation, reason: \"invalid-input\" });\n\n const idempotencyKey = yield* Schema.decodeEffect(IdempotencyKey)(options.idempotencyKey).pipe(\n Effect.mapError(invalid),\n );\n\n const encodedInput = yield* Schema.encodeEffect(declaration.target.input)(input).pipe(\n Effect.mapError(invalid),\n );\n\n const inReplyTo =\n options.inReplyTo === undefined\n ? undefined\n : yield* Schema.decodeEffect(MessageRef)(options.inReplyTo).pipe(Effect.mapError(invalid));\n\n const request = {\n ...declaration,\n encodedInput,\n idempotencyKey,\n ...(inReplyTo === undefined ? {} : { inReplyTo }),\n };\n\n const result =\n operation === \"reply\"\n ? inReplyTo === undefined\n ? yield* invalid()\n : yield* service.reply({ ...request, inReplyTo })\n : yield* service.send(request);\n\n return yield* Schema.decodeEffect(MessageStatus)(result).pipe(\n Effect.mapError(() => MessagingError.make({ operation, reason: \"corrupt\" })),\n );\n });\n\n/** Retain a durable message. Its status distinguishes outbound retention from destination acceptance. */\nexport const send = <Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n input: Input[\"Type\"],\n options: { readonly idempotencyKey: IdempotencyKey; readonly inReplyTo?: MessageRef },\n) => dispatch(declaration, input, options, \"send\");\n\n/** Reply to an authenticated inbound message; return routing still requires independent send authority. */\nexport const reply = <Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n inReplyTo: MessageRef,\n input: Input[\"Type\"],\n options: { readonly idempotencyKey: IdempotencyKey },\n) => dispatch(declaration, input, { ...options, inReplyTo }, \"reply\");\n\n/** Return bounded provenance for messages from this peer, without granting permission to reply. */\nexport const inbox = <Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n options: { readonly after?: number; readonly limit?: number } = {},\n) =>\n Effect.gen(function* () {\n const service = yield* host;\n\n return yield* service.inbox({ ...declaration, ...options, limit: options.limit ?? 20 });\n });\n\nexport const inspect = <Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n message: MessageRef,\n) =>\n Effect.gen(function* () {\n const service = yield* host;\n\n return yield* service.inspect({ ...declaration, message });\n });\n\n/** Explicitly renew a parked delivery's bounded retry budget, retaining its complete frozen envelope. */\nexport const retry = <Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n message: MessageRef,\n) =>\n Effect.gen(function* () {\n const service = yield* host;\n\n return yield* service.retry({ ...declaration, message });\n });\n\nconst modelKey = Effect.fnUntraced(function* () {\n const source = yield* (yield* host).context;\n\n if (source._tag !== \"tool\")\n return yield* MessagingError.make({ operation: \"send\", reason: \"denied\" });\n const crypto = yield* Crypto.Crypto;\n\n const digest = yield* crypto\n .digest(\"SHA-256\", utf8Bytes(JSON.stringify(source)))\n .pipe(Effect.mapError(() => MessagingError.make({ operation: \"send\", reason: \"unavailable\" })));\n\n return Schema.decodeSync(IdempotencyKey)(`peer-tool:${Hex.encode(digest)}`);\n});\n\nconst native = <\n const Name extends string,\n Parameters extends Schema.Top,\n Success extends Schema.Top,\n R,\n>(\n name: Name,\n parameters: Parameters,\n success: Success,\n description: string,\n handler: (\n parameters: Parameters[\"Type\"],\n ) => Effect.Effect<Success[\"Type\"], MessagingError, R | MessagingHost | Crypto.Crypto>,\n) => {\n const tool = Tool.make(name, { parameters, success, failure: MessagingError, description })\n .annotate(WorkerOperationTool, true)\n .addDependency(MessagingHost)\n .addDependency(Crypto.Crypto);\n\n const toolkit = Toolkit.make(tool);\n\n const build = Effect.gen(function* () {\n const captured = yield* Effect.context<Exclude<R, MessagingHost | Crypto.Crypto>>();\n\n const invoke = Effect.fnUntraced(function* (value: Parameters[\"Type\"]) {\n const service = yield* host;\n const crypto = yield* Crypto.Crypto;\n\n return yield* handler(value).pipe(\n Effect.provideService(MessagingHost, service),\n Effect.provideService(Crypto.Crypto, crypto),\n Effect.provide(captured),\n );\n });\n\n // The computed single key is precisely the native Tool's literal name.\n return { [name]: invoke } as unknown as Toolkit.HandlersFrom<typeof toolkit.tools>;\n });\n\n return { tool, toolkit, layer: toolkit.toLayer(build) };\n};\n\n/** Install only the native operations chosen by the host; schemas come from the Peer declaration. */\nexport const sendTool = <const Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n) =>\n native(\n `${declaration.name}_send` as const,\n declaration.target.input,\n MessageStatus,\n `Send input to ${declaration.name} through its authorized durable route.`,\n (input) =>\n Effect.gen(function* () {\n return yield* send(declaration, input, { idempotencyKey: yield* modelKey() });\n }),\n );\n\nexport const replyTool = <const Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n) => {\n const inputSchema: Schema.Codec<\n Input[\"Type\"],\n Input[\"Encoded\"],\n Input[\"DecodingServices\"],\n Input[\"EncodingServices\"]\n > = declaration.target.input;\n\n return native(\n `${declaration.name}_reply` as const,\n Schema.Struct({ inReplyTo: MessageRef, input: inputSchema }),\n MessageStatus,\n `Reply to a recorded inbound message from ${declaration.name}.`,\n ({ inReplyTo, input }) =>\n Effect.gen(function* () {\n return yield* reply(declaration, inReplyTo, input, { idempotencyKey: yield* modelKey() });\n }),\n );\n};\n\nexport const inboxTool = <const Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n) =>\n native(\n `${declaration.name}_inbox` as const,\n Schema.Struct({\n after: Schema.optionalKey(Schema.Natural),\n limit: Schema.optionalKey(\n Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(100)),\n ),\n }),\n InboxPage,\n `Read a bounded page of message provenance from ${declaration.name}.`,\n (options) => inbox(declaration, options),\n );\n\nexport const inspectTool = <const Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n) =>\n native(\n `${declaration.name}_message_status` as const,\n Schema.Struct({ message: MessageRef }),\n MessageStatus,\n `Inspect delivery status of a message sent to ${declaration.name}.`,\n ({ message }) => inspect(declaration, message),\n );\n\nexport const retryTool = <const Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n) =>\n native(\n `${declaration.name}_retry_message` as const,\n Schema.Struct({ message: MessageRef }),\n MessageStatus,\n `Renew bounded automatic retries for a parked message to ${declaration.name}.`,\n ({ message }) => retry(declaration, message),\n );\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Messaging.mjs","names":[],"sources":["../../src/capabilities/Messaging.ts"],"sourcesContent":["import { Crypto, Effect, Option, Schema } from \"effect\";\nimport { Tool, Toolkit } from \"effect/ai\";\nimport { Hex } from \"effect/encoding\";\n\nimport type { AnyDefinition } from \"../core/Agent.ts\";\nimport {\n InboxPage,\n MessageRef,\n MessageStatus,\n MessagingError,\n PeerName,\n} from \"../core/Messaging.ts\";\nimport { IdempotencyKey } from \"../core/Receipt.ts\";\nimport { WorkerOperationTool } from \"../core/SubagentContract.ts\";\nimport { MessagingHost } from \"../engine/MessagingHost.ts\";\nimport { utf8Bytes } from \"./internal/utf8.ts\";\n\nexport * from \"../core/Messaging.ts\";\n\n/** A fixed host route and its destination-owned input Schema. Construction acquires no resources. */\nexport interface Peer<Name extends string, Input extends Schema.Top> {\n readonly name: Name;\n readonly target: AnyDefinition & { readonly input: Input };\n}\n\nexport const peer = <const Name extends string, Input extends Schema.Top>(\n name: Name,\n options: { readonly target: AnyDefinition & { readonly input: Input } },\n): Peer<Name, Input> => {\n Schema.decodeSync(PeerName)(name);\n\n return Object.freeze({ name, target: options.target });\n};\n\nconst host: Effect.Effect<MessagingHost[\"Service\"], MessagingError, MessagingHost> =\n Effect.serviceOption(MessagingHost).pipe(\n Effect.flatMap((value) =>\n Option.isSome(value)\n ? Effect.succeed(value.value)\n : MessagingError.make({ operation: \"context\", reason: \"unavailable\" }),\n ),\n );\n\nconst dispatch = Effect.fnUntraced(function* <Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n input: Input[\"Type\"],\n options: { readonly idempotencyKey: IdempotencyKey; readonly inReplyTo?: MessageRef },\n operation: \"send\" | \"reply\",\n) {\n const service = yield* host;\n const invalid = () => MessagingError.make({ operation, reason: \"invalid-input\" });\n\n const idempotencyKey = yield* Schema.decodeEffect(IdempotencyKey)(options.idempotencyKey).pipe(\n Effect.mapError(invalid),\n );\n\n const encodedInput = yield* Schema.encodeEffect(declaration.target.input)(input).pipe(\n Effect.mapError(invalid),\n );\n\n const inReplyTo =\n options.inReplyTo === undefined\n ? undefined\n : yield* Schema.decodeEffect(MessageRef)(options.inReplyTo).pipe(Effect.mapError(invalid));\n\n const request = {\n ...declaration,\n encodedInput,\n idempotencyKey,\n ...(inReplyTo === undefined ? {} : { inReplyTo }),\n };\n\n const result =\n operation === \"reply\"\n ? inReplyTo === undefined\n ? yield* invalid()\n : yield* service.reply({ ...request, inReplyTo })\n : yield* service.send(request);\n\n return yield* Schema.decodeEffect(MessageStatus)(result).pipe(\n Effect.mapError(() => MessagingError.make({ operation, reason: \"corrupt\" })),\n );\n});\n\n/** Retain a durable message. Its status distinguishes outbound retention from destination acceptance. */\nexport const send = <Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n input: Input[\"Type\"],\n options: { readonly idempotencyKey: IdempotencyKey; readonly inReplyTo?: MessageRef },\n) => dispatch(declaration, input, options, \"send\");\n\n/** Reply to an authenticated inbound message; return routing still requires independent send authority. */\nexport const reply = <Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n inReplyTo: MessageRef,\n input: Input[\"Type\"],\n options: { readonly idempotencyKey: IdempotencyKey },\n) => dispatch(declaration, input, { ...options, inReplyTo }, \"reply\");\n\n/** Return bounded provenance for messages from this peer, without granting permission to reply. */\nexport const inbox = Effect.fnUntraced(function* <Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n options: { readonly after?: number; readonly limit?: number } = {},\n) {\n const service = yield* host;\n\n return yield* service.inbox({ ...declaration, ...options, limit: options.limit ?? 20 });\n});\n\nexport const inspect = Effect.fnUntraced(function* <Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n message: MessageRef,\n) {\n const service = yield* host;\n\n return yield* service.inspect({ ...declaration, message });\n});\n\n/** Explicitly renew a parked delivery's bounded retry budget, retaining its complete frozen envelope. */\nexport const retry = Effect.fnUntraced(function* <Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n message: MessageRef,\n) {\n const service = yield* host;\n\n return yield* service.retry({ ...declaration, message });\n});\n\nconst modelKey = Effect.fnUntraced(function* () {\n const source = yield* (yield* host).context;\n\n if (source._tag !== \"tool\")\n return yield* MessagingError.make({ operation: \"send\", reason: \"denied\" });\n const crypto = yield* Crypto.Crypto;\n\n const digest = yield* crypto\n .digest(\"SHA-256\", utf8Bytes(JSON.stringify(source)))\n .pipe(Effect.mapError(() => MessagingError.make({ operation: \"send\", reason: \"unavailable\" })));\n\n return Schema.decodeSync(IdempotencyKey)(`peer-tool:${Hex.encode(digest)}`);\n});\n\nconst native = <\n const Name extends string,\n Parameters extends Schema.Top,\n Success extends Schema.Top,\n R,\n>(\n name: Name,\n parameters: Parameters,\n success: Success,\n description: string,\n handler: (\n parameters: Parameters[\"Type\"],\n ) => Effect.Effect<Success[\"Type\"], MessagingError, R | MessagingHost | Crypto.Crypto>,\n) => {\n const tool = Tool.make(name, { parameters, success, failure: MessagingError, description })\n .annotate(WorkerOperationTool, true)\n .addDependency(MessagingHost)\n .addDependency(Crypto.Crypto);\n\n const toolkit = Toolkit.make(tool);\n\n const build = Effect.gen(function* () {\n const captured = yield* Effect.context<Exclude<R, MessagingHost | Crypto.Crypto>>();\n\n const invoke = Effect.fnUntraced(function* (value: Parameters[\"Type\"]) {\n const service = yield* host;\n const crypto = yield* Crypto.Crypto;\n\n return yield* handler(value).pipe(\n Effect.provideService(MessagingHost, service),\n Effect.provideService(Crypto.Crypto, crypto),\n Effect.provide(captured),\n );\n });\n\n // The computed single key is precisely the native Tool's literal name.\n return { [name]: invoke } as unknown as Toolkit.HandlersFrom<typeof toolkit.tools>;\n });\n\n return { tool, toolkit, layer: toolkit.toLayer(build) };\n};\n\n/** Install only the native operations chosen by the host; schemas come from the Peer declaration. */\nexport const sendTool = <const Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n) =>\n native(\n `${declaration.name}_send` as const,\n declaration.target.input,\n MessageStatus,\n `Send input to ${declaration.name} through its authorized durable route.`,\n (input) =>\n Effect.gen(function* () {\n return yield* send(declaration, input, { idempotencyKey: yield* modelKey() });\n }),\n );\n\nexport const replyTool = <const Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n) => {\n const inputSchema: Schema.Codec<\n Input[\"Type\"],\n Input[\"Encoded\"],\n Input[\"DecodingServices\"],\n Input[\"EncodingServices\"]\n > = declaration.target.input;\n\n return native(\n `${declaration.name}_reply` as const,\n Schema.Struct({ inReplyTo: MessageRef, input: inputSchema }),\n MessageStatus,\n `Reply to a recorded inbound message from ${declaration.name}.`,\n ({ inReplyTo, input }) =>\n Effect.gen(function* () {\n return yield* reply(declaration, inReplyTo, input, { idempotencyKey: yield* modelKey() });\n }),\n );\n};\n\nexport const inboxTool = <const Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n) =>\n native(\n `${declaration.name}_inbox` as const,\n Schema.Struct({\n after: Schema.optionalKey(Schema.Natural),\n limit: Schema.optionalKey(\n Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(100)),\n ),\n }),\n InboxPage,\n `Read a bounded page of message provenance from ${declaration.name}.`,\n (options) => inbox(declaration, options),\n );\n\nexport const inspectTool = <const Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n) =>\n native(\n `${declaration.name}_message_status` as const,\n Schema.Struct({ message: MessageRef }),\n MessageStatus,\n `Inspect delivery status of a message sent to ${declaration.name}.`,\n ({ message }) => inspect(declaration, message),\n );\n\nexport const retryTool = <const Name extends string, Input extends Schema.Top>(\n declaration: Peer<Name, Input>,\n) =>\n native(\n `${declaration.name}_retry_message` as const,\n Schema.Struct({ message: MessageRef }),\n MessageStatus,\n `Renew bounded automatic retries for a parked message to ${declaration.name}.`,\n ({ message }) => retry(declaration, message),\n );\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as Thread } from "../Thread-
|
|
1
|
+
import { n as Thread } from "../Thread-DzdJAY4J.mjs";
|
|
2
2
|
import { Crypto, Effect, Schema } from "effect";
|
|
3
3
|
declare namespace ModelContext_d_exports {
|
|
4
4
|
export { CompactionArtifact, CompactionDigestError, ContextLimitExceeded, ContextTransform, ContextTransformError, InvalidCompactionArtifact, ModelContextMessage, PreparedModelContext, RetainedFact, applyCompaction, digestCompactionSource, prepareModelContext };
|
|
@@ -105,11 +105,13 @@ const validateModelView = (messages, transformId) => {
|
|
|
105
105
|
})) : Effect.succeed(messages);
|
|
106
106
|
};
|
|
107
107
|
/** Apply transforms in declaration order, always restoring the original source snapshot. */
|
|
108
|
-
const prepareModelContext = (snapshot, transforms) =>
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
108
|
+
const prepareModelContext = (snapshot, transforms) => {
|
|
109
|
+
return (transforms ?? []).reduce((messages, transform) => messages.pipe(Effect.flatMap(transform.apply), Effect.flatMap((transformed) => validateModelView(transformed, transform.id))), Effect.succeed(asModelMessages(snapshot))).pipe(Effect.map((messages) => PreparedModelContext.make({
|
|
110
|
+
source: snapshot,
|
|
111
|
+
messages,
|
|
112
|
+
compactions: []
|
|
113
|
+
})));
|
|
114
|
+
};
|
|
113
115
|
const exactSourceRange = (snapshot, coversFrom, coversThrough) => {
|
|
114
116
|
if (coversFrom > coversThrough || coversThrough >= snapshot.nextSequence) return Effect.fail(InvalidCompactionArtifact.make({ message: "Compaction artifact covers an invalid source range" }));
|
|
115
117
|
const selected = snapshot.messages.filter((message) => message.sequence >= coversFrom && message.sequence <= coversThrough);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ModelContext.mjs","names":["ThreadSnapshot"],"sources":["../../src/capabilities/ModelContext.ts"],"sourcesContent":["import { Crypto, Effect, Schema } from \"effect\";\nimport type { Prompt } from \"effect/ai\";\nimport { Hex } from \"effect/encoding\";\n\nimport { ThreadId } from \"../core/Identifiers.ts\";\nimport { utf8ByteLength } from \"../core/internal/utf8.ts\";\nimport { ThreadMessage, Thread as ThreadSnapshot, ThreadText } from \"../core/Thread.ts\";\n\nconst MAX_CONTEXT_MESSAGES = 1_024;\nconst MAX_CONTEXT_MESSAGE_BYTES = 4 * 1024 * 1024;\nconst MAX_SOURCE_SEQUENCES = 1_024;\nconst MAX_RETAINED_FACTS = 256;\nconst MAX_RETAINED_FACT_BYTES = 1024 * 1024;\nconst MAX_COMPACTIONS = 16;\n\nconst SourceSequences = Schema.Array(Schema.Natural).check(\n Schema.isMaxLength(MAX_SOURCE_SEQUENCES),\n);\n\n/** A model-context message derived from, but never replacing, source history. */\nexport class ModelContextMessage extends Schema.Class<ModelContextMessage>(\n \"@effect-agent/capabilities/ModelContextMessage\",\n)({\n role: Schema.Literals([\"system\", \"user\", \"assistant\", \"tool\"]),\n content: ThreadText,\n sourceSequences: SourceSequences,\n}) {}\n\n/** A fact retained explicitly by compaction, independent of the generated prose summary. */\nexport class RetainedFact extends Schema.Class<RetainedFact>(\n \"@effect-agent/capabilities/RetainedFact\",\n)({\n fact: Schema.String.check(Schema.isMaxLength(4 * 1024)),\n sourceSequences: SourceSequences,\n}) {}\n\nconst ModelContextMessages = Schema.Array(ModelContextMessage)\n .check(Schema.isMaxLength(MAX_CONTEXT_MESSAGES))\n .pipe(\n Schema.refine(\n (messages): messages is ReadonlyArray<ModelContextMessage> =>\n messages.reduce((total, message) => total + utf8ByteLength(message.content), 0) <=\n MAX_CONTEXT_MESSAGE_BYTES,\n { expected: `model context totaling at most ${MAX_CONTEXT_MESSAGE_BYTES} UTF-8 bytes` },\n ),\n );\n\nconst RetainedFacts = Schema.Array(RetainedFact)\n .check(Schema.isMaxLength(MAX_RETAINED_FACTS))\n .pipe(\n Schema.refine(\n (facts): facts is ReadonlyArray<RetainedFact> =>\n facts.reduce((total, retained) => total + utf8ByteLength(retained.fact), 0) <=\n MAX_RETAINED_FACT_BYTES,\n { expected: `retained facts totaling at most ${MAX_RETAINED_FACT_BYTES} UTF-8 bytes` },\n ),\n );\n\nconst SourceDigest = Schema.String.check(Schema.isPattern(/^sha256:[a-f0-9]{64}$/));\n\n/** Versioned, replayable artifact that covers a prefix or middle range without deleting source. */\nexport class CompactionArtifact extends Schema.Class<CompactionArtifact>(\n \"@effect-agent/capabilities/CompactionArtifact\",\n)({\n version: Schema.Literal(1),\n threadId: ThreadId,\n coversFrom: Schema.Natural,\n coversThrough: Schema.Natural,\n summary: ModelContextMessage,\n retainedFacts: RetainedFacts,\n tokenEstimate: Schema.Natural,\n sourceDigest: SourceDigest,\n compactorVersion: Schema.NonEmptyString,\n}) {}\n\n/** Context exposed to a model, with source history kept intact for audit and reconstruction. */\nexport class PreparedModelContext extends Schema.Class<PreparedModelContext>(\n \"@effect-agent/capabilities/PreparedModelContext\",\n)({\n source: ThreadSnapshot,\n messages: ModelContextMessages,\n compactions: Schema.Array(CompactionArtifact).check(Schema.isMaxLength(MAX_COMPACTIONS)),\n}) {}\n\n/** Transform failure is named and bounded so model context preparation has a closed error channel. */\nexport class ContextTransformError extends Schema.TaggedError<ContextTransformError>()(\n \"ContextTransformError\",\n { transformId: Schema.NonEmptyString, message: Schema.String },\n) {}\n\n/** Source encoding or hashing failed before an artifact could be trusted. */\nexport class CompactionDigestError extends Schema.TaggedError<CompactionDigestError>()(\n \"CompactionDigestError\",\n { message: Schema.String },\n) {}\n\n/** Compaction artifacts that do not bind to the exact source range are rejected before use. */\nexport class InvalidCompactionArtifact extends Schema.TaggedError<InvalidCompactionArtifact>()(\n \"InvalidCompactionArtifact\",\n { message: Schema.String },\n) {}\n\n/** A transform or compaction exceeded the finite model-view collection bounds. */\nexport class ContextLimitExceeded extends Schema.TaggedError<ContextLimitExceeded>()(\n \"ContextLimitExceeded\",\n {\n limit: Schema.Literals([\"messages\", \"message-bytes\", \"compactions\"]),\n limitValue: Schema.Natural,\n observedValue: Schema.Natural,\n },\n) {}\n\n/**\n * Ordered context transform. It receives and returns only the model-visible\n * message view, making replacement of the authoritative source impossible.\n * Required services remain visible in prepareModelContext; expected failures\n * are translated by the transform into ContextTransformError.\n */\nexport interface ContextTransform<Requirements = never> {\n readonly id: string;\n readonly version: string;\n readonly apply: (\n messages: ReadonlyArray<ModelContextMessage>,\n ) => Effect.Effect<ReadonlyArray<ModelContextMessage>, ContextTransformError, Requirements>;\n}\n\nconst messageText = (message: Prompt.Message): string => {\n if (message.role === \"system\") return message.content;\n\n const content = message.content\n .map((part) => {\n if (part.type === \"text\" || part.type === \"reasoning\") return part.text;\n\n return `[${part.type}]`;\n })\n .join(\"\\n\");\n\n return content.slice(0, 64 * 1024);\n};\n\nconst asModelMessages = (snapshot: ThreadSnapshot): ReadonlyArray<ModelContextMessage> =>\n snapshot.messages.map((entry) =>\n ModelContextMessage.make({\n role: entry.message.role,\n content: messageText(entry.message),\n sourceSequences: [entry.sequence],\n }),\n );\n\nconst validateModelView = (\n messages: ReadonlyArray<ModelContextMessage>,\n transformId: string,\n): Effect.Effect<ReadonlyArray<ModelContextMessage>, ContextTransformError> => {\n if (messages.length > MAX_CONTEXT_MESSAGES) {\n return Effect.fail(\n ContextTransformError.make({\n transformId,\n message: `Transform produced ${messages.length} messages; maximum is ${MAX_CONTEXT_MESSAGES}`,\n }),\n );\n }\n const bytes = messages.reduce((total, message) => total + utf8ByteLength(message.content), 0);\n\n return bytes > MAX_CONTEXT_MESSAGE_BYTES\n ? Effect.fail(\n ContextTransformError.make({\n transformId,\n message: `Transform produced ${bytes} UTF-8 bytes; maximum is ${MAX_CONTEXT_MESSAGE_BYTES}`,\n }),\n )\n : Effect.succeed(messages);\n};\n\n/** Apply transforms in declaration order, always restoring the original source snapshot. */\nexport const prepareModelContext = <\n const Requirements extends ReadonlyArray<unknown> = readonly [],\n>(\n snapshot: ThreadSnapshot,\n transforms?: { readonly [Index in keyof Requirements]: ContextTransform<Requirements[Index]> },\n): Effect.Effect<PreparedModelContext, ContextTransformError, Requirements[number]> =>\n (transforms ?? [])\n .reduce<\n Effect.Effect<ReadonlyArray<ModelContextMessage>, ContextTransformError, Requirements[number]>\n >(\n (messages, transform) =>\n messages.pipe(\n Effect.flatMap(transform.apply),\n Effect.flatMap((transformed) => validateModelView(transformed, transform.id)),\n ),\n Effect.succeed(asModelMessages(snapshot)),\n )\n .pipe(\n Effect.map((messages) =>\n PreparedModelContext.make({\n source: snapshot,\n messages,\n compactions: [],\n }),\n ),\n );\n\nconst exactSourceRange = (\n snapshot: ThreadSnapshot,\n coversFrom: number,\n coversThrough: number,\n): Effect.Effect<ReadonlyArray<ThreadMessage>, InvalidCompactionArtifact> => {\n if (coversFrom > coversThrough || coversThrough >= snapshot.nextSequence) {\n return Effect.fail(\n InvalidCompactionArtifact.make({\n message: \"Compaction artifact covers an invalid source range\",\n }),\n );\n }\n\n const selected = snapshot.messages.filter(\n (message) => message.sequence >= coversFrom && message.sequence <= coversThrough,\n );\n\n const expectedCount = coversThrough - coversFrom + 1;\n\n if (\n selected.length !== expectedCount ||\n selected[0]?.sequence !== coversFrom ||\n selected[selected.length - 1]?.sequence !== coversThrough\n ) {\n return Effect.fail(\n InvalidCompactionArtifact.make({\n message: \"Compaction source range is not contiguous in authoritative history\",\n }),\n );\n }\n\n return Effect.succeed(selected);\n};\n\nconst utf8Bytes = (value: string): Uint8Array => {\n const hex = Hex.encode(value);\n const bytes = new Uint8Array(hex.length / 2);\n\n for (let index = 0; index < bytes.length; index += 1) {\n bytes[index] = Number.parseInt(hex.slice(index * 2, index * 2 + 2), 16);\n }\n\n return bytes;\n};\n\n/** Compute a cryptographic digest over the canonical encoded exact source range. */\nexport const digestCompactionSource = Effect.fnUntraced(function* (\n snapshot: ThreadSnapshot,\n coversFrom: number,\n coversThrough: number,\n) {\n const selected = yield* exactSourceRange(snapshot, coversFrom, coversThrough);\n\n const encoded = yield* Schema.encodeEffect(Schema.Array(ThreadMessage))(selected).pipe(\n Effect.mapError((error) =>\n CompactionDigestError.make({\n message: `Could not encode compaction source: ${error.message}`,\n }),\n ),\n );\n\n const crypto = yield* Crypto.Crypto;\n\n const digest = yield* crypto.digest(\"SHA-256\", utf8Bytes(JSON.stringify(encoded))).pipe(\n Effect.mapError((error) =>\n CompactionDigestError.make({\n message: `Could not digest compaction source: ${error.message}`,\n }),\n ),\n );\n\n return `sha256:${Hex.encode(digest)}`;\n});\n\n/**\n * Replace only the model-view messages fully covered by the artifact range\n * with its summary. The digest is recomputed against the exact source slice\n * before the artifact can influence context. Messages that are not fully\n * covered — including transform-synthesized messages without provenance and\n * messages whose provenance only partially overlaps the range — remain\n * visible, and the summary is inserted before the first message derived\n * entirely from later source.\n */\nexport const applyCompaction = Effect.fnUntraced(function* (\n context: PreparedModelContext,\n artifact: CompactionArtifact,\n) {\n if (artifact.threadId !== context.source.threadId) {\n return yield* InvalidCompactionArtifact.make({\n message: \"Compaction artifact belongs to another Thread\",\n });\n }\n\n const actualDigest = yield* digestCompactionSource(\n context.source,\n artifact.coversFrom,\n artifact.coversThrough,\n );\n\n if (actualDigest !== artifact.sourceDigest) {\n return yield* InvalidCompactionArtifact.make({\n message: \"Compaction source digest does not match authoritative history\",\n });\n }\n\n const provenanceInRange = (sequences: ReadonlyArray<number>): boolean =>\n sequences.length > 0 &&\n sequences.every(\n (sequence) => sequence >= artifact.coversFrom && sequence <= artifact.coversThrough,\n );\n\n if (\n !provenanceInRange(artifact.summary.sourceSequences) ||\n artifact.retainedFacts.some((fact) => !provenanceInRange(fact.sourceSequences))\n ) {\n return yield* InvalidCompactionArtifact.make({\n message: \"Compaction summary or retained-fact provenance falls outside its covered range\",\n });\n }\n if (context.compactions.length >= MAX_COMPACTIONS) {\n return yield* ContextLimitExceeded.make({\n limit: \"compactions\",\n limitValue: MAX_COMPACTIONS,\n observedValue: context.compactions.length + 1,\n });\n }\n\n const fullyCovered = (message: ModelContextMessage): boolean =>\n message.sourceSequences.length > 0 &&\n message.sourceSequences.every(\n (sequence) => sequence >= artifact.coversFrom && sequence <= artifact.coversThrough,\n );\n\n const kept = context.messages.filter((message) => !fullyCovered(message));\n\n const summaryAt = kept.findIndex(\n (message) =>\n message.sourceSequences.length > 0 &&\n message.sourceSequences.every((sequence) => sequence > artifact.coversThrough),\n );\n\n const messages = yield* validateModelView(\n summaryAt === -1\n ? [...kept, artifact.summary]\n : [...kept.slice(0, summaryAt), artifact.summary, ...kept.slice(summaryAt)],\n `compaction:${artifact.compactorVersion}`,\n );\n\n return PreparedModelContext.make({\n source: context.source,\n messages,\n compactions: [...context.compactions, artifact],\n });\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ModelContext.mjs","names":["ThreadSnapshot"],"sources":["../../src/capabilities/ModelContext.ts"],"sourcesContent":["import { Crypto, Effect, Schema } from \"effect\";\nimport type { Prompt } from \"effect/ai\";\nimport { Hex } from \"effect/encoding\";\n\nimport { ThreadId } from \"../core/Identifiers.ts\";\nimport { utf8ByteLength } from \"../core/internal/utf8.ts\";\nimport { ThreadMessage, Thread as ThreadSnapshot, ThreadText } from \"../core/Thread.ts\";\n\nconst MAX_CONTEXT_MESSAGES = 1_024;\nconst MAX_CONTEXT_MESSAGE_BYTES = 4 * 1024 * 1024;\nconst MAX_SOURCE_SEQUENCES = 1_024;\nconst MAX_RETAINED_FACTS = 256;\nconst MAX_RETAINED_FACT_BYTES = 1024 * 1024;\nconst MAX_COMPACTIONS = 16;\n\nconst SourceSequences = Schema.Array(Schema.Natural).check(\n Schema.isMaxLength(MAX_SOURCE_SEQUENCES),\n);\n\n/** A model-context message derived from, but never replacing, source history. */\nexport class ModelContextMessage extends Schema.Class<ModelContextMessage>(\n \"@effect-agent/capabilities/ModelContextMessage\",\n)({\n role: Schema.Literals([\"system\", \"user\", \"assistant\", \"tool\"]),\n content: ThreadText,\n sourceSequences: SourceSequences,\n}) {}\n\n/** A fact retained explicitly by compaction, independent of the generated prose summary. */\nexport class RetainedFact extends Schema.Class<RetainedFact>(\n \"@effect-agent/capabilities/RetainedFact\",\n)({\n fact: Schema.String.check(Schema.isMaxLength(4 * 1024)),\n sourceSequences: SourceSequences,\n}) {}\n\nconst ModelContextMessages = Schema.Array(ModelContextMessage)\n .check(Schema.isMaxLength(MAX_CONTEXT_MESSAGES))\n .pipe(\n Schema.refine(\n (messages): messages is ReadonlyArray<ModelContextMessage> =>\n messages.reduce((total, message) => total + utf8ByteLength(message.content), 0) <=\n MAX_CONTEXT_MESSAGE_BYTES,\n { expected: `model context totaling at most ${MAX_CONTEXT_MESSAGE_BYTES} UTF-8 bytes` },\n ),\n );\n\nconst RetainedFacts = Schema.Array(RetainedFact)\n .check(Schema.isMaxLength(MAX_RETAINED_FACTS))\n .pipe(\n Schema.refine(\n (facts): facts is ReadonlyArray<RetainedFact> =>\n facts.reduce((total, retained) => total + utf8ByteLength(retained.fact), 0) <=\n MAX_RETAINED_FACT_BYTES,\n { expected: `retained facts totaling at most ${MAX_RETAINED_FACT_BYTES} UTF-8 bytes` },\n ),\n );\n\nconst SourceDigest = Schema.String.check(Schema.isPattern(/^sha256:[a-f0-9]{64}$/));\n\n/** Versioned, replayable artifact that covers a prefix or middle range without deleting source. */\nexport class CompactionArtifact extends Schema.Class<CompactionArtifact>(\n \"@effect-agent/capabilities/CompactionArtifact\",\n)({\n version: Schema.Literal(1),\n threadId: ThreadId,\n coversFrom: Schema.Natural,\n coversThrough: Schema.Natural,\n summary: ModelContextMessage,\n retainedFacts: RetainedFacts,\n tokenEstimate: Schema.Natural,\n sourceDigest: SourceDigest,\n compactorVersion: Schema.NonEmptyString,\n}) {}\n\n/** Context exposed to a model, with source history kept intact for audit and reconstruction. */\nexport class PreparedModelContext extends Schema.Class<PreparedModelContext>(\n \"@effect-agent/capabilities/PreparedModelContext\",\n)({\n source: ThreadSnapshot,\n messages: ModelContextMessages,\n compactions: Schema.Array(CompactionArtifact).check(Schema.isMaxLength(MAX_COMPACTIONS)),\n}) {}\n\n/** Transform failure is named and bounded so model context preparation has a closed error channel. */\nexport class ContextTransformError extends Schema.TaggedError<ContextTransformError>()(\n \"ContextTransformError\",\n { transformId: Schema.NonEmptyString, message: Schema.String },\n) {}\n\n/** Source encoding or hashing failed before an artifact could be trusted. */\nexport class CompactionDigestError extends Schema.TaggedError<CompactionDigestError>()(\n \"CompactionDigestError\",\n { message: Schema.String },\n) {}\n\n/** Compaction artifacts that do not bind to the exact source range are rejected before use. */\nexport class InvalidCompactionArtifact extends Schema.TaggedError<InvalidCompactionArtifact>()(\n \"InvalidCompactionArtifact\",\n { message: Schema.String },\n) {}\n\n/** A transform or compaction exceeded the finite model-view collection bounds. */\nexport class ContextLimitExceeded extends Schema.TaggedError<ContextLimitExceeded>()(\n \"ContextLimitExceeded\",\n {\n limit: Schema.Literals([\"messages\", \"message-bytes\", \"compactions\"]),\n limitValue: Schema.Natural,\n observedValue: Schema.Natural,\n },\n) {}\n\n/**\n * Ordered context transform. It receives and returns only the model-visible\n * message view, making replacement of the authoritative source impossible.\n * Required services remain visible in prepareModelContext; expected failures\n * are translated by the transform into ContextTransformError.\n */\nexport interface ContextTransform<Requirements = never> {\n readonly id: string;\n readonly version: string;\n readonly apply: (\n messages: ReadonlyArray<ModelContextMessage>,\n ) => Effect.Effect<ReadonlyArray<ModelContextMessage>, ContextTransformError, Requirements>;\n}\n\nconst messageText = (message: Prompt.Message): string => {\n if (message.role === \"system\") return message.content;\n\n const content = message.content\n .map((part) => {\n if (part.type === \"text\" || part.type === \"reasoning\") return part.text;\n\n return `[${part.type}]`;\n })\n .join(\"\\n\");\n\n return content.slice(0, 64 * 1024);\n};\n\nconst asModelMessages = (snapshot: ThreadSnapshot): ReadonlyArray<ModelContextMessage> =>\n snapshot.messages.map((entry) =>\n ModelContextMessage.make({\n role: entry.message.role,\n content: messageText(entry.message),\n sourceSequences: [entry.sequence],\n }),\n );\n\nconst validateModelView = (\n messages: ReadonlyArray<ModelContextMessage>,\n transformId: string,\n): Effect.Effect<ReadonlyArray<ModelContextMessage>, ContextTransformError> => {\n if (messages.length > MAX_CONTEXT_MESSAGES) {\n return Effect.fail(\n ContextTransformError.make({\n transformId,\n message: `Transform produced ${messages.length} messages; maximum is ${MAX_CONTEXT_MESSAGES}`,\n }),\n );\n }\n const bytes = messages.reduce((total, message) => total + utf8ByteLength(message.content), 0);\n\n return bytes > MAX_CONTEXT_MESSAGE_BYTES\n ? Effect.fail(\n ContextTransformError.make({\n transformId,\n message: `Transform produced ${bytes} UTF-8 bytes; maximum is ${MAX_CONTEXT_MESSAGE_BYTES}`,\n }),\n )\n : Effect.succeed(messages);\n};\n\n/** Apply transforms in declaration order, always restoring the original source snapshot. */\nexport const prepareModelContext = <\n const Requirements extends ReadonlyArray<unknown> = readonly [],\n>(\n snapshot: ThreadSnapshot,\n transforms?: { readonly [Index in keyof Requirements]: ContextTransform<Requirements[Index]> },\n): Effect.Effect<PreparedModelContext, ContextTransformError, Requirements[number]> => {\n const declared: ReadonlyArray<ContextTransform<Requirements[number]>> = transforms ?? [];\n\n return declared\n .reduce<\n Effect.Effect<ReadonlyArray<ModelContextMessage>, ContextTransformError, Requirements[number]>\n >(\n (messages, transform) =>\n messages.pipe(\n Effect.flatMap(transform.apply),\n Effect.flatMap((transformed) => validateModelView(transformed, transform.id)),\n ),\n Effect.succeed(asModelMessages(snapshot)),\n )\n .pipe(\n Effect.map((messages) =>\n PreparedModelContext.make({\n source: snapshot,\n messages,\n compactions: [],\n }),\n ),\n );\n};\n\nconst exactSourceRange = (\n snapshot: ThreadSnapshot,\n coversFrom: number,\n coversThrough: number,\n): Effect.Effect<ReadonlyArray<ThreadMessage>, InvalidCompactionArtifact> => {\n if (coversFrom > coversThrough || coversThrough >= snapshot.nextSequence) {\n return Effect.fail(\n InvalidCompactionArtifact.make({\n message: \"Compaction artifact covers an invalid source range\",\n }),\n );\n }\n\n const selected = snapshot.messages.filter(\n (message) => message.sequence >= coversFrom && message.sequence <= coversThrough,\n );\n\n const expectedCount = coversThrough - coversFrom + 1;\n\n if (\n selected.length !== expectedCount ||\n selected[0]?.sequence !== coversFrom ||\n selected[selected.length - 1]?.sequence !== coversThrough\n ) {\n return Effect.fail(\n InvalidCompactionArtifact.make({\n message: \"Compaction source range is not contiguous in authoritative history\",\n }),\n );\n }\n\n return Effect.succeed(selected);\n};\n\nconst utf8Bytes = (value: string): Uint8Array => {\n const hex = Hex.encode(value);\n const bytes = new Uint8Array(hex.length / 2);\n\n for (let index = 0; index < bytes.length; index += 1) {\n bytes[index] = Number.parseInt(hex.slice(index * 2, index * 2 + 2), 16);\n }\n\n return bytes;\n};\n\n/** Compute a cryptographic digest over the canonical encoded exact source range. */\nexport const digestCompactionSource = Effect.fnUntraced(function* (\n snapshot: ThreadSnapshot,\n coversFrom: number,\n coversThrough: number,\n) {\n const selected = yield* exactSourceRange(snapshot, coversFrom, coversThrough);\n\n const encoded = yield* Schema.encodeEffect(Schema.Array(ThreadMessage))(selected).pipe(\n Effect.mapError((error) =>\n CompactionDigestError.make({\n message: `Could not encode compaction source: ${error.message}`,\n }),\n ),\n );\n\n const crypto = yield* Crypto.Crypto;\n\n const digest = yield* crypto.digest(\"SHA-256\", utf8Bytes(JSON.stringify(encoded))).pipe(\n Effect.mapError((error) =>\n CompactionDigestError.make({\n message: `Could not digest compaction source: ${error.message}`,\n }),\n ),\n );\n\n return `sha256:${Hex.encode(digest)}`;\n});\n\n/**\n * Replace only the model-view messages fully covered by the artifact range\n * with its summary. The digest is recomputed against the exact source slice\n * before the artifact can influence context. Messages that are not fully\n * covered — including transform-synthesized messages without provenance and\n * messages whose provenance only partially overlaps the range — remain\n * visible, and the summary is inserted before the first message derived\n * entirely from later source.\n */\nexport const applyCompaction = Effect.fnUntraced(function* (\n context: PreparedModelContext,\n artifact: CompactionArtifact,\n) {\n if (artifact.threadId !== context.source.threadId) {\n return yield* InvalidCompactionArtifact.make({\n message: \"Compaction artifact belongs to another Thread\",\n });\n }\n\n const actualDigest = yield* digestCompactionSource(\n context.source,\n artifact.coversFrom,\n artifact.coversThrough,\n );\n\n if (actualDigest !== artifact.sourceDigest) {\n return yield* InvalidCompactionArtifact.make({\n message: \"Compaction source digest does not match authoritative history\",\n });\n }\n\n const provenanceInRange = (sequences: ReadonlyArray<number>): boolean =>\n sequences.length > 0 &&\n sequences.every(\n (sequence) => sequence >= artifact.coversFrom && sequence <= artifact.coversThrough,\n );\n\n if (\n !provenanceInRange(artifact.summary.sourceSequences) ||\n artifact.retainedFacts.some((fact) => !provenanceInRange(fact.sourceSequences))\n ) {\n return yield* InvalidCompactionArtifact.make({\n message: \"Compaction summary or retained-fact provenance falls outside its covered range\",\n });\n }\n if (context.compactions.length >= MAX_COMPACTIONS) {\n return yield* ContextLimitExceeded.make({\n limit: \"compactions\",\n limitValue: MAX_COMPACTIONS,\n observedValue: context.compactions.length + 1,\n });\n }\n\n const fullyCovered = (message: ModelContextMessage): boolean =>\n message.sourceSequences.length > 0 &&\n message.sourceSequences.every(\n (sequence) => sequence >= artifact.coversFrom && sequence <= artifact.coversThrough,\n );\n\n const kept = context.messages.filter((message) => !fullyCovered(message));\n\n const summaryAt = kept.findIndex(\n (message) =>\n message.sourceSequences.length > 0 &&\n message.sourceSequences.every((sequence) => sequence > artifact.coversThrough),\n );\n\n const messages = yield* validateModelView(\n summaryAt === -1\n ? [...kept, artifact.summary]\n : [...kept.slice(0, summaryAt), artifact.summary, ...kept.slice(summaryAt)],\n `compaction:${artifact.compactorVersion}`,\n );\n\n return PreparedModelContext.make({\n source: context.source,\n messages,\n compactions: [...context.compactions, artifact],\n });\n});\n"],"mappings":"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"}
|
|
@@ -26,20 +26,52 @@ var RedactionError = class extends Schema.TaggedError()("RedactionError", {
|
|
|
26
26
|
}) {};
|
|
27
27
|
/** Redaction owns the boundary from decoded Tool values to bounded audit/model previews. */
|
|
28
28
|
var Redactor = class extends Context.Service()("@effect-agent/capabilities/Redactor") {};
|
|
29
|
-
const
|
|
30
|
-
|
|
29
|
+
const encodingFailure = () => RedactionError.make({
|
|
30
|
+
reason: "encoding-failed",
|
|
31
|
+
message: "Could not encode the structurally redacted preview"
|
|
32
|
+
});
|
|
33
|
+
const redactValue = Effect.fnUntraced(function* (value, depth, counter) {
|
|
34
|
+
if (depth > MAX_REDACTION_DEPTH) return yield* RedactionError.make({
|
|
31
35
|
reason: "input-too-deep",
|
|
32
36
|
message: `Decoded value exceeds redaction depth ${MAX_REDACTION_DEPTH}`
|
|
33
37
|
});
|
|
34
38
|
counter.nodes += 1;
|
|
35
|
-
if (counter.nodes > MAX_REDACTION_NODES)
|
|
39
|
+
if (counter.nodes > MAX_REDACTION_NODES) return yield* RedactionError.make({
|
|
36
40
|
reason: "input-too-large",
|
|
37
41
|
message: `Decoded value exceeds redaction node count ${MAX_REDACTION_NODES}`
|
|
38
42
|
});
|
|
39
|
-
|
|
40
|
-
|
|
43
|
+
const collection = yield* Effect.try({
|
|
44
|
+
try: () => {
|
|
45
|
+
if (Array.isArray(value)) {
|
|
46
|
+
const redacted = [];
|
|
47
|
+
redacted.length = value.length;
|
|
48
|
+
return {
|
|
49
|
+
_tag: "Array",
|
|
50
|
+
values: value,
|
|
51
|
+
redacted
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return value !== null && typeof value === "object" ? {
|
|
55
|
+
_tag: "Object",
|
|
56
|
+
entries: Object.entries(value)
|
|
57
|
+
} : void 0;
|
|
58
|
+
},
|
|
59
|
+
catch: encodingFailure
|
|
60
|
+
});
|
|
61
|
+
if (collection?._tag === "Array") {
|
|
62
|
+
const { redacted } = collection;
|
|
63
|
+
for (let index = 0; index < redacted.length; index += 1) {
|
|
64
|
+
const item = yield* Effect.try({
|
|
65
|
+
try: () => index in collection.values ? { value: collection.values[index] } : void 0,
|
|
66
|
+
catch: encodingFailure
|
|
67
|
+
});
|
|
68
|
+
if (item !== void 0) redacted[index] = yield* redactValue(item.value, depth + 1, counter);
|
|
69
|
+
}
|
|
70
|
+
return redacted;
|
|
71
|
+
}
|
|
72
|
+
if (collection?._tag === "Object") {
|
|
41
73
|
const redacted = {};
|
|
42
|
-
for (const [key, item] of
|
|
74
|
+
for (const [key, item] of collection.entries) redacted[key] = yield* redactValue(item, depth + 1, counter);
|
|
43
75
|
return redacted;
|
|
44
76
|
}
|
|
45
77
|
if (value === null) return "[REDACTED:null]";
|
|
@@ -47,7 +79,7 @@ const redactValue = (value, depth, counter) => {
|
|
|
47
79
|
if (typeof value === "number") return "[REDACTED:number]";
|
|
48
80
|
if (typeof value === "boolean") return "[REDACTED:boolean]";
|
|
49
81
|
return "[REDACTED:unsupported]";
|
|
50
|
-
};
|
|
82
|
+
});
|
|
51
83
|
const truncateUtf8 = (value, maxBytes) => {
|
|
52
84
|
if (utf8ByteLength(value) <= maxBytes) return value;
|
|
53
85
|
const suffix = "…";
|
|
@@ -85,19 +117,17 @@ const redactedTranscript = (events) => Effect.gen(function* () {
|
|
|
85
117
|
* scalar types, so an ordinary field such as `note` cannot bypass redaction.
|
|
86
118
|
* Tool-specific Layers may expose explicitly reviewed fields instead.
|
|
87
119
|
*/
|
|
88
|
-
const StructuralRedactorLive = Layer.succeed(Redactor)({ redact: (decodedValue)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
120
|
+
const StructuralRedactorLive = Layer.succeed(Redactor)({ redact: Effect.fnUntraced(function* (decodedValue) {
|
|
121
|
+
const structurallyRedacted = yield* redactValue(decodedValue, 0, { nodes: 0 });
|
|
122
|
+
const preview = yield* Effect.try({
|
|
123
|
+
try: () => truncateUtf8(JSON.stringify(structurallyRedacted), MAX_REDACTED_PREVIEW_BYTES),
|
|
124
|
+
catch: encodingFailure
|
|
125
|
+
});
|
|
126
|
+
return yield* Schema.decodeEffect(RedactedPreview)(preview).pipe(Effect.mapError(() => RedactionError.make({
|
|
94
127
|
reason: "encoding-failed",
|
|
95
|
-
message: "
|
|
96
|
-
})
|
|
97
|
-
})
|
|
98
|
-
reason: "encoding-failed",
|
|
99
|
-
message: "Redacted preview did not satisfy its bounded schema"
|
|
100
|
-
}))))) });
|
|
128
|
+
message: "Redacted preview did not satisfy its bounded schema"
|
|
129
|
+
})));
|
|
130
|
+
}) });
|
|
101
131
|
//#endregion
|
|
102
132
|
export { RedactedPreview, RedactionError, Redactor, StructuralRedactorLive, redactedTranscript, Redaction_exports as t };
|
|
103
133
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Redaction.mjs","names":[],"sources":["../../src/capabilities/Redaction.ts"],"sourcesContent":["import { Context, Effect, Layer, Schema } from \"effect\";\n\nimport { utf8ByteLength } from \"../core/internal/utf8.ts\";\nimport { RunEvent } from \"../core/RunEvent.ts\";\n\nconst MAX_REDACTED_PREVIEW_BYTES = 8 * 1024;\nconst MAX_REDACTION_NODES = 4_096;\nconst MAX_REDACTION_DEPTH = 16;\n\n/** Branded evidence that a preview passed through the configured structural Redactor. */\nexport const RedactedPreview = Schema.String.pipe(\n Schema.refine((value): value is string => utf8ByteLength(value) <= MAX_REDACTED_PREVIEW_BYTES, {\n expected: `redacted preview of at most ${MAX_REDACTED_PREVIEW_BYTES} UTF-8 bytes`,\n }),\n Schema.brand(\"@effect-agent/capabilities/RedactedPreview\"),\n);\n\nexport type RedactedPreview = typeof RedactedPreview.Type;\n\n/** Structural redaction failed closed rather than returning unreviewed caller text. */\nexport class RedactionError extends Schema.TaggedError<RedactionError>()(\"RedactionError\", {\n reason: Schema.Literals([\"input-too-deep\", \"input-too-large\", \"encoding-failed\"]),\n message: Schema.String,\n}) {}\n\n/** Redaction owns the boundary from decoded Tool values to bounded audit/model previews. */\nexport class Redactor extends Context.Service<\n Redactor,\n {\n readonly redact: (decodedValue: unknown) => Effect.Effect<RedactedPreview, RedactionError>;\n }\n>()(\"@effect-agent/capabilities/Redactor\") {}\n\ninterface RedactionCounter {\n nodes: number;\n}\n\nconst redactValue = (value: unknown
|
|
1
|
+
{"version":3,"file":"Redaction.mjs","names":[],"sources":["../../src/capabilities/Redaction.ts"],"sourcesContent":["import { Context, Effect, Layer, Schema } from \"effect\";\n\nimport { utf8ByteLength } from \"../core/internal/utf8.ts\";\nimport { RunEvent } from \"../core/RunEvent.ts\";\n\nconst MAX_REDACTED_PREVIEW_BYTES = 8 * 1024;\nconst MAX_REDACTION_NODES = 4_096;\nconst MAX_REDACTION_DEPTH = 16;\n\n/** Branded evidence that a preview passed through the configured structural Redactor. */\nexport const RedactedPreview = Schema.String.pipe(\n Schema.refine((value): value is string => utf8ByteLength(value) <= MAX_REDACTED_PREVIEW_BYTES, {\n expected: `redacted preview of at most ${MAX_REDACTED_PREVIEW_BYTES} UTF-8 bytes`,\n }),\n Schema.brand(\"@effect-agent/capabilities/RedactedPreview\"),\n);\n\nexport type RedactedPreview = typeof RedactedPreview.Type;\n\n/** Structural redaction failed closed rather than returning unreviewed caller text. */\nexport class RedactionError extends Schema.TaggedError<RedactionError>()(\"RedactionError\", {\n reason: Schema.Literals([\"input-too-deep\", \"input-too-large\", \"encoding-failed\"]),\n message: Schema.String,\n}) {}\n\n/** Redaction owns the boundary from decoded Tool values to bounded audit/model previews. */\nexport class Redactor extends Context.Service<\n Redactor,\n {\n readonly redact: (decodedValue: unknown) => Effect.Effect<RedactedPreview, RedactionError>;\n }\n>()(\"@effect-agent/capabilities/Redactor\") {}\n\ninterface RedactionCounter {\n nodes: number;\n}\n\nconst encodingFailure = () =>\n RedactionError.make({\n reason: \"encoding-failed\",\n message: \"Could not encode the structurally redacted preview\",\n });\n\nconst redactValue = Effect.fnUntraced(function* (\n value: unknown,\n depth: number,\n counter: RedactionCounter,\n): Effect.fn.Return<Schema.Json, RedactionError> {\n if (depth > MAX_REDACTION_DEPTH) {\n return yield* RedactionError.make({\n reason: \"input-too-deep\",\n message: `Decoded value exceeds redaction depth ${MAX_REDACTION_DEPTH}`,\n });\n }\n counter.nodes += 1;\n if (counter.nodes > MAX_REDACTION_NODES) {\n return yield* RedactionError.make({\n reason: \"input-too-large\",\n message: `Decoded value exceeds redaction node count ${MAX_REDACTION_NODES}`,\n });\n }\n\n const collection = yield* Effect.try({\n try: () => {\n if (Array.isArray(value)) {\n const redacted: Array<Schema.Json> = [];\n\n redacted.length = value.length;\n\n return { _tag: \"Array\" as const, values: value, redacted };\n }\n\n return value !== null && typeof value === \"object\"\n ? { _tag: \"Object\" as const, entries: Object.entries(value) }\n : undefined;\n },\n catch: encodingFailure,\n });\n\n if (collection?._tag === \"Array\") {\n const { redacted } = collection;\n\n for (let index = 0; index < redacted.length; index += 1) {\n const item = yield* Effect.try({\n try: () => (index in collection.values ? { value: collection.values[index] } : undefined),\n catch: encodingFailure,\n });\n\n if (item !== undefined) redacted[index] = yield* redactValue(item.value, depth + 1, counter);\n }\n\n return redacted;\n }\n if (collection?._tag === \"Object\") {\n const redacted: Record<string, Schema.Json> = {};\n\n for (const [key, item] of collection.entries) {\n redacted[key] = yield* redactValue(item, depth + 1, counter);\n }\n\n return redacted;\n }\n // The default policy is deliberately type-aware and fail-closed: it preserves\n // object/array shape for reviewer context but never copies a decoded scalar,\n // regardless of its field name. Applications that need visible values provide\n // a Tool-specific Redactor after validating those values against that Tool's\n // input Schema.\n if (value === null) return \"[REDACTED:null]\";\n if (typeof value === \"string\") return \"[REDACTED:string]\";\n if (typeof value === \"number\") return \"[REDACTED:number]\";\n if (typeof value === \"boolean\") return \"[REDACTED:boolean]\";\n\n return \"[REDACTED:unsupported]\";\n});\n\nconst truncateUtf8 = (value: string, maxBytes: number): string => {\n if (utf8ByteLength(value) <= maxBytes) {\n return value;\n }\n const suffix = \"…\";\n const suffixBytes = utf8ByteLength(suffix);\n let output = \"\";\n let bytes = 0;\n\n for (const character of value) {\n const characterBytes = utf8ByteLength(character);\n\n if (bytes + characterBytes + suffixBytes > maxBytes) {\n break;\n }\n output += character;\n bytes += characterBytes;\n }\n\n return `${output}${suffix}`;\n};\n\nconst encodeRunEvent = Schema.encodeEffect(RunEvent);\n\n/**\n * One composed step from live Run Events to structurally redacted transcript lines\n * (P7 WP7 friction fix; SEC-008/testing.md §12 \"structurally redacted\" live transcripts):\n * Schema-encode each event through the canonical `RunEvent` union, then pass the encoded\n * value through the configured `Redactor` — so the safe path is the short path and no live\n * suite hand-assembles (or accidentally skips) the encode→redact pair. Engine-constructed\n * events always encode, so an encode failure is a defect, never a silent omission.\n */\nexport const redactedTranscript = (\n events: Iterable<RunEvent>,\n): Effect.Effect<ReadonlyArray<RedactedPreview>, RedactionError, Redactor> =>\n Effect.gen(function* () {\n const redactor = yield* Redactor;\n const lines: Array<RedactedPreview> = [];\n\n for (const event of events) {\n const encoded = yield* encodeRunEvent(event).pipe(Effect.orDie);\n\n lines.push(yield* redactor.redact(encoded));\n }\n\n return lines;\n });\n\n/**\n * Default structural implementation. It exposes only collection shape and\n * scalar types, so an ordinary field such as `note` cannot bypass redaction.\n * Tool-specific Layers may expose explicitly reviewed fields instead.\n */\nexport const StructuralRedactorLive = Layer.succeed(Redactor)({\n redact: Effect.fnUntraced(function* (decodedValue) {\n const structurallyRedacted = yield* redactValue(decodedValue, 0, { nodes: 0 });\n\n const preview = yield* Effect.try({\n try: () => truncateUtf8(JSON.stringify(structurallyRedacted), MAX_REDACTED_PREVIEW_BYTES),\n catch: encodingFailure,\n });\n\n return yield* Schema.decodeEffect(RedactedPreview)(preview).pipe(\n Effect.mapError(() =>\n RedactionError.make({\n reason: \"encoding-failed\",\n message: \"Redacted preview did not satisfy its bounded schema\",\n }),\n ),\n );\n }),\n});\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { c as ThreadLimitExceeded, d as ThreadOwnershipError, i as ThreadEncodingError, s as ThreadHistoryDiverged, t as Store, u as ThreadNotFound } from "../Thread-
|
|
1
|
+
import { c as ThreadLimitExceeded, d as ThreadOwnershipError, i as ThreadEncodingError, s as ThreadHistoryDiverged, t as Store, u as ThreadNotFound } from "../Thread-DzdJAY4J.mjs";
|
|
2
2
|
import { RedactionError, Redactor } from "./Redaction.mjs";
|
|
3
3
|
import { ApprovalAudit, ApprovalAuditLimitExceeded, ApprovalDecisionMismatch, ApprovalRequestDraft, ApprovalResolver, ApprovalResolverError } from "./Approval.mjs";
|
|
4
4
|
import { BudgetExceeded, UsageBudgetNode } from "./Budget.mjs";
|
|
5
|
-
import { M as RunOptions, R as RunSchedulingHook, _ as RunBudgetHook, b as RunContextHook, g as RunApprovalRequest, h as RunApprovalHook, j as RunInputHook, w as RunContextRequest } from "../RunOptions-
|
|
5
|
+
import { M as RunOptions, R as RunSchedulingHook, _ as RunBudgetHook, b as RunContextHook, g as RunApprovalRequest, h as RunApprovalHook, j as RunInputHook, w as RunContextRequest } from "../RunOptions-Be77lKVZ.mjs";
|
|
6
6
|
import { RunCommandQueue } from "./Commands.mjs";
|
|
7
7
|
import { Effect, Schema } from "effect";
|
|
8
8
|
import { Prompt } from "effect/ai";
|
|
@@ -29,7 +29,7 @@ const toRunInputHook = (queue) => ({
|
|
|
29
29
|
end: () => queue.shutdown
|
|
30
30
|
});
|
|
31
31
|
/** Adapt native Effect AI approval parts through structural redaction, audit, and timeout policy. */
|
|
32
|
-
const toRunApprovalHook = (policy) => ({ request:
|
|
32
|
+
const toRunApprovalHook = (policy) => ({ request: Effect.fnUntraced(function* (engineRequest) {
|
|
33
33
|
const validatedPolicy = yield* Schema.decodeEffect(RunApprovalAdapterPolicySchema)(policy).pipe(Effect.mapError((error) => ApprovalAdapterError.make({ message: `Approval adapter policy is invalid: ${error.message}` })));
|
|
34
34
|
const now = yield* Clock.currentTimeMillis;
|
|
35
35
|
const metadata = yield* Effect.try({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RunHooks.mjs","names":["ConversationStore"],"sources":["../../src/capabilities/RunHooks.ts"],"sourcesContent":["import { Clock, DateTime, Effect, Schema } from \"effect\";\nimport type { Prompt } from \"effect/ai\";\n\nimport {\n type ThreadEncodingError,\n type ThreadHistoryDiverged,\n type ThreadLimitExceeded,\n type ThreadNotFound,\n type ThreadOwnershipError,\n toPrompt,\n Store as ConversationStore,\n} from \"../core/Thread.ts\";\nimport {\n type PreparedRunContext,\n type RunApprovalDecision,\n type RunApprovalHook,\n type RunApprovalRequest,\n type RunBudgetHook,\n type RunContextHook,\n type RunContextRequest,\n type RunInputHook,\n type RunOptions,\n type RunSchedulingHook,\n} from \"../engine/RunOptions.ts\";\nimport {\n type ApprovalAudit,\n type ApprovalAuditLimitExceeded,\n type ApprovalDecisionMismatch,\n ApprovalRequestDraft,\n type ApprovalResolver,\n type ApprovalResolverError,\n makeApprovalRequest,\n requestApproval,\n} from \"./Approval.ts\";\nimport { type BudgetExceeded, UsageDelta, type UsageBudgetNode } from \"./Budget.ts\";\nimport type { RunCommandQueue } from \"./Commands.ts\";\nimport type { RedactionError, Redactor } from \"./Redaction.ts\";\n\n/** Capability policy could not be normalized into the bounded approval request Schema. */\nexport class ApprovalAdapterError extends Schema.TaggedError<ApprovalAdapterError>()(\n \"ApprovalAdapterError\",\n { message: Schema.String },\n) {}\n\n/** Engine usage data did not satisfy the non-negative budget delta Schema. */\nexport class BudgetAdapterError extends Schema.TaggedError<BudgetAdapterError>()(\n \"BudgetAdapterError\",\n { message: Schema.String },\n) {}\n\n/** Adapt the richer audited FIFO commands to the engine's safe-seam input hook. */\nexport const toRunInputHook = (queue: RunCommandQueue): RunInputHook<never, never> => ({\n drain: (policy) =>\n queue.drain(policy).pipe(\n Effect.map((commands) =>\n commands.map((command) => ({\n kind: command._tag === \"SteeringCommand\" ? (\"steering\" as const) : (\"follow-up\" as const),\n input: command.content,\n })),\n ),\n ),\n end: () => queue.shutdown,\n});\n\n/** Explicit policy needed to turn a native Effect AI approval request into an audit request. */\nexport interface RunApprovalAdapterPolicy {\n readonly expiresInMillis: number;\n readonly risk: ApprovalRequestDraft[\"risk\"];\n readonly denial: ApprovalRequestDraft[\"denial\"];\n readonly actionSummary: (request: RunApprovalRequest) => string;\n readonly resourceTargets: (request: RunApprovalRequest) => ReadonlyArray<string>;\n}\n\n/** Adapt native Effect AI approval parts through structural redaction, audit, and timeout policy. */\nexport const toRunApprovalHook = (\n policy: RunApprovalAdapterPolicy,\n): RunApprovalHook<\n | ApprovalResolverError\n | ApprovalAuditLimitExceeded\n | ApprovalDecisionMismatch\n | ApprovalAdapterError\n | RedactionError,\n ApprovalResolver | ApprovalAudit | Redactor\n> => ({\n request: (engineRequest) =>\n Effect.gen(function* () {\n const validatedPolicy = yield* Schema.decodeEffect(RunApprovalAdapterPolicySchema)(\n policy,\n ).pipe(\n Effect.mapError((error) =>\n ApprovalAdapterError.make({\n message: `Approval adapter policy is invalid: ${error.message}`,\n }),\n ),\n );\n\n const now = yield* Clock.currentTimeMillis;\n\n const metadata = yield* Effect.try({\n try: () => ({\n actionSummary: policy.actionSummary(engineRequest),\n resourceTargets: policy.resourceTargets(engineRequest),\n }),\n catch: () =>\n ApprovalAdapterError.make({\n message: \"Approval policy failed while describing the native Tool request\",\n }),\n });\n\n const draft = yield* Schema.decodeEffect(ApprovalRequestDraft)({\n requestId: engineRequest.request.approvalId,\n runId: engineRequest.runId,\n threadId: engineRequest.threadId,\n toolCallId: engineRequest.toolCallId,\n toolName: engineRequest.toolName,\n actionSummary: metadata.actionSummary,\n resourceTargets: metadata.resourceTargets,\n risk: validatedPolicy.risk,\n expiresAt: DateTime.formatIso(\n DateTime.toUtc(DateTime.makeUnsafe(now + validatedPolicy.expiresInMillis)),\n ),\n denial: validatedPolicy.denial,\n }).pipe(\n Effect.mapError((error) =>\n ApprovalAdapterError.make({\n message: `Approval adapter policy is invalid: ${error.message}`,\n }),\n ),\n );\n\n const request = yield* makeApprovalRequest(draft, engineRequest.parameters);\n const decision = yield* requestApproval(request);\n\n if (decision._tag === \"ApprovalApproved\") {\n return { _tag: \"approved\" as const };\n }\n if (decision.timedOut && request.denial === \"recoverable\") {\n return {\n _tag: \"unresolved\" as const,\n reason: decision.reason,\n };\n }\n\n return {\n _tag: \"denied\" as const,\n reason: decision.reason,\n };\n }),\n});\n\n/**\n * Durable variant of `toRunApprovalHook` (P5 plan §2.6): the durable coordinator consults this\n * delegate for policy-AUTO decisions only, after its recorded-decision lookup misses. It reuses\n * the exact P2 approval stack — `ApprovalRequestDraft` policy metadata, structural redaction,\n * audit sink, expiry/timeout policy — but differs in two durable-specific ways:\n *\n * 1. The capability services (`ApprovalResolver | ApprovalAudit | Redactor`) are captured up\n * front, so the returned hook is `RunApprovalHook<never, never>` — the shape the\n * coordinator's `DurableApprovalResolver` reference accepts without leaking capability\n * requirements into the durable runtime Layer.\n * 2. It FAILS CLOSED into `unresolved`: any adapter, audit, redaction, or resolver failure\n * defers the decision to the durable suspension + `resolveApproval` path instead of\n * approving, denying, or crashing the Attempt on a transient policy fault. Explicit\n * policy denials (including the P2 timeout-denial for `denial: \"terminal\"`) still deny.\n */\nexport const toDurableRunApprovalHook = Effect.fnUntraced(function* (\n policy: RunApprovalAdapterPolicy,\n): Effect.fn.Return<\n RunApprovalHook<never, never>,\n never,\n ApprovalResolver | ApprovalAudit | Redactor\n> {\n const services = yield* Effect.context<ApprovalResolver | ApprovalAudit | Redactor>();\n const hook = toRunApprovalHook(policy);\n\n return {\n request: (request) =>\n hook.request(request).pipe(\n Effect.provideContext(services),\n Effect.catch((error) =>\n Effect.succeed<RunApprovalDecision>({\n _tag: \"unresolved\",\n reason: `Approval delegation failed (${error._tag}); the decision defers to the durable resolveApproval path`,\n }),\n ),\n ),\n };\n});\n\n/** Adapt one hierarchical budget node to the engine's usage accounting seam. */\nexport const toRunBudgetHook = (\n budget: UsageBudgetNode,\n): RunBudgetHook<BudgetExceeded | BudgetAdapterError, never> => ({\n guard: budget.guard,\n consume: (delta) =>\n Schema.decodeEffect(UsageDelta)({\n modelCalls: delta.modelCalls,\n inputTokens: delta.inputTokens,\n outputTokens: delta.outputTokens,\n cacheReadInputTokens: Math.max(0, delta.usage.inputTokens.cacheRead ?? 0),\n cacheWriteInputTokens: Math.max(0, delta.usage.inputTokens.cacheWrite ?? 0),\n toolCalls: delta.toolCalls,\n costMicrousd: delta.costMicrousd,\n }).pipe(\n Effect.mapError((error) =>\n BudgetAdapterError.make({\n message: `Engine usage delta is invalid: ${error.message}`,\n }),\n ),\n Effect.flatMap((usage) => budget.consume(usage)),\n Effect.asVoid,\n ),\n});\n\nexport type ThreadAdapterError =\n | ThreadNotFound\n | ThreadLimitExceeded\n | ThreadEncodingError\n | ThreadHistoryDiverged\n | ThreadOwnershipError;\n\n/**\n * Advanced integration for an existing Thread.Store snapshot. Ordinary Runs automatically\n * retain history through ThreadHistory.layer; use this helper only for explicit snapshot hooks.\n * Share that Layer's Thread.Store owner. PersistentHistory rejects these competing hooks.\n * The snapshot is explicit initial Prompt data. Each inline onHistory call immediately records\n * its append-only suffix, including updates from Runs that later fail or are interrupted. Writes\n * already made remain in the snapshot. Callback errors stop the Run as ThreadAdapterError;\n * snapshot lookup can fail with ThreadNotFound or ThreadOwnershipError before execution.\n * Construct scoped hooks inside InMemory.scoped; captured callbacks retain that owner.\n * Native Effect AI parts and provider options are preserved without a role/text projection.\n * For retaining only successful Runs, provide ThreadHistory through PersistentHistory.layer\n * with a memory or SQLite store instead. This adapter does not provide durable recovery.\n */\nexport const toRunThreadOptions = Effect.fnUntraced(function* (\n threadId: import(\"../core/Identifiers.ts\").ThreadId,\n runId: import(\"../core/Identifiers.ts\").RunId,\n): Effect.fn.Return<\n Pick<RunOptions<ThreadAdapterError>, \"threadId\" | \"history\" | \"onHistory\">,\n ThreadNotFound | ThreadOwnershipError,\n ConversationStore\n> {\n const threads = yield* ConversationStore;\n const snapshot = yield* threads.snapshot(threadId);\n\n return {\n threadId,\n history: toPrompt(snapshot),\n onHistory: (history) => threads.recordHistory(threadId, runId, history).pipe(Effect.asVoid),\n };\n});\n\n/** Prompt transform used by the adapter; the engine retains the authoritative source separately. */\nexport interface EnginePromptTransform<Error = never, Requirements = never> {\n readonly prepare: (\n source: Prompt.Prompt,\n request: RunContextRequest,\n ) => Effect.Effect<Prompt.Prompt, Error, Requirements>;\n}\n\n/** Adapt a prompt-only context transform without granting it authority over engine source history. */\nexport const toRunContextHook = <Error, Requirements>(\n transform: EnginePromptTransform<Error, Requirements>,\n): RunContextHook<Error, Requirements> => ({\n prepare: (request): Effect.Effect<PreparedRunContext, Error, Requirements> =>\n transform.prepare(request.source, request).pipe(Effect.map((prompt) => ({ prompt }))),\n});\n\n/** Scheduling values are structurally aligned and only reduce finite concurrency. */\nexport const toRunSchedulingHook = (\n runOverride: RunSchedulingHook[\"runOverride\"],\n toolRequiresSequential?: (toolName: string) => boolean,\n): RunSchedulingHook => ({\n runOverride,\n ...(toolRequiresSequential === undefined ? {} : { toolRequiresSequential }),\n});\n\n/** Validate policy configuration at adapter construction boundaries. */\nexport const RunApprovalAdapterPolicySchema = Schema.Struct({\n expiresInMillis: Schema.Int.check(Schema.isGreaterThan(0)),\n risk: Schema.Literals([\"low\", \"medium\", \"high\", \"critical\"]),\n denial: Schema.Literals([\"terminal\", \"recoverable\"]),\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RunHooks.mjs","names":["ConversationStore"],"sources":["../../src/capabilities/RunHooks.ts"],"sourcesContent":["import { Clock, DateTime, Effect, Schema } from \"effect\";\nimport type { Prompt } from \"effect/ai\";\n\nimport {\n type ThreadEncodingError,\n type ThreadHistoryDiverged,\n type ThreadLimitExceeded,\n type ThreadNotFound,\n type ThreadOwnershipError,\n toPrompt,\n Store as ConversationStore,\n} from \"../core/Thread.ts\";\nimport {\n type PreparedRunContext,\n type RunApprovalDecision,\n type RunApprovalHook,\n type RunApprovalRequest,\n type RunBudgetHook,\n type RunContextHook,\n type RunContextRequest,\n type RunInputHook,\n type RunOptions,\n type RunSchedulingHook,\n} from \"../engine/RunOptions.ts\";\nimport {\n type ApprovalAudit,\n type ApprovalAuditLimitExceeded,\n type ApprovalDecisionMismatch,\n ApprovalRequestDraft,\n type ApprovalResolver,\n type ApprovalResolverError,\n makeApprovalRequest,\n requestApproval,\n} from \"./Approval.ts\";\nimport { type BudgetExceeded, UsageDelta, type UsageBudgetNode } from \"./Budget.ts\";\nimport type { RunCommandQueue } from \"./Commands.ts\";\nimport type { RedactionError, Redactor } from \"./Redaction.ts\";\n\n/** Capability policy could not be normalized into the bounded approval request Schema. */\nexport class ApprovalAdapterError extends Schema.TaggedError<ApprovalAdapterError>()(\n \"ApprovalAdapterError\",\n { message: Schema.String },\n) {}\n\n/** Engine usage data did not satisfy the non-negative budget delta Schema. */\nexport class BudgetAdapterError extends Schema.TaggedError<BudgetAdapterError>()(\n \"BudgetAdapterError\",\n { message: Schema.String },\n) {}\n\n/** Adapt the richer audited FIFO commands to the engine's safe-seam input hook. */\nexport const toRunInputHook = (queue: RunCommandQueue): RunInputHook<never, never> => ({\n drain: (policy) =>\n queue.drain(policy).pipe(\n Effect.map((commands) =>\n commands.map((command) => ({\n kind: command._tag === \"SteeringCommand\" ? (\"steering\" as const) : (\"follow-up\" as const),\n input: command.content,\n })),\n ),\n ),\n end: () => queue.shutdown,\n});\n\n/** Explicit policy needed to turn a native Effect AI approval request into an audit request. */\nexport interface RunApprovalAdapterPolicy {\n readonly expiresInMillis: number;\n readonly risk: ApprovalRequestDraft[\"risk\"];\n readonly denial: ApprovalRequestDraft[\"denial\"];\n readonly actionSummary: (request: RunApprovalRequest) => string;\n readonly resourceTargets: (request: RunApprovalRequest) => ReadonlyArray<string>;\n}\n\n/** Adapt native Effect AI approval parts through structural redaction, audit, and timeout policy. */\nexport const toRunApprovalHook = (\n policy: RunApprovalAdapterPolicy,\n): RunApprovalHook<\n | ApprovalResolverError\n | ApprovalAuditLimitExceeded\n | ApprovalDecisionMismatch\n | ApprovalAdapterError\n | RedactionError,\n ApprovalResolver | ApprovalAudit | Redactor\n> => ({\n request: Effect.fnUntraced(function* (engineRequest) {\n const validatedPolicy = yield* Schema.decodeEffect(RunApprovalAdapterPolicySchema)(policy).pipe(\n Effect.mapError((error) =>\n ApprovalAdapterError.make({\n message: `Approval adapter policy is invalid: ${error.message}`,\n }),\n ),\n );\n\n const now = yield* Clock.currentTimeMillis;\n\n const metadata = yield* Effect.try({\n try: () => ({\n actionSummary: policy.actionSummary(engineRequest),\n resourceTargets: policy.resourceTargets(engineRequest),\n }),\n catch: () =>\n ApprovalAdapterError.make({\n message: \"Approval policy failed while describing the native Tool request\",\n }),\n });\n\n const draft = yield* Schema.decodeEffect(ApprovalRequestDraft)({\n requestId: engineRequest.request.approvalId,\n runId: engineRequest.runId,\n threadId: engineRequest.threadId,\n toolCallId: engineRequest.toolCallId,\n toolName: engineRequest.toolName,\n actionSummary: metadata.actionSummary,\n resourceTargets: metadata.resourceTargets,\n risk: validatedPolicy.risk,\n expiresAt: DateTime.formatIso(\n DateTime.toUtc(DateTime.makeUnsafe(now + validatedPolicy.expiresInMillis)),\n ),\n denial: validatedPolicy.denial,\n }).pipe(\n Effect.mapError((error) =>\n ApprovalAdapterError.make({\n message: `Approval adapter policy is invalid: ${error.message}`,\n }),\n ),\n );\n\n const request = yield* makeApprovalRequest(draft, engineRequest.parameters);\n const decision = yield* requestApproval(request);\n\n if (decision._tag === \"ApprovalApproved\") {\n return { _tag: \"approved\" as const };\n }\n if (decision.timedOut && request.denial === \"recoverable\") {\n return {\n _tag: \"unresolved\" as const,\n reason: decision.reason,\n };\n }\n\n return {\n _tag: \"denied\" as const,\n reason: decision.reason,\n };\n }),\n});\n\n/**\n * Durable variant of `toRunApprovalHook` (P5 plan §2.6): the durable coordinator consults this\n * delegate for policy-AUTO decisions only, after its recorded-decision lookup misses. It reuses\n * the exact P2 approval stack — `ApprovalRequestDraft` policy metadata, structural redaction,\n * audit sink, expiry/timeout policy — but differs in two durable-specific ways:\n *\n * 1. The capability services (`ApprovalResolver | ApprovalAudit | Redactor`) are captured up\n * front, so the returned hook is `RunApprovalHook<never, never>` — the shape the\n * coordinator's `DurableApprovalResolver` reference accepts without leaking capability\n * requirements into the durable runtime Layer.\n * 2. It FAILS CLOSED into `unresolved`: any adapter, audit, redaction, or resolver failure\n * defers the decision to the durable suspension + `resolveApproval` path instead of\n * approving, denying, or crashing the Attempt on a transient policy fault. Explicit\n * policy denials (including the P2 timeout-denial for `denial: \"terminal\"`) still deny.\n */\nexport const toDurableRunApprovalHook = Effect.fnUntraced(function* (\n policy: RunApprovalAdapterPolicy,\n): Effect.fn.Return<\n RunApprovalHook<never, never>,\n never,\n ApprovalResolver | ApprovalAudit | Redactor\n> {\n const services = yield* Effect.context<ApprovalResolver | ApprovalAudit | Redactor>();\n const hook = toRunApprovalHook(policy);\n\n return {\n request: (request) =>\n hook.request(request).pipe(\n Effect.provideContext(services),\n Effect.catch((error) =>\n Effect.succeed<RunApprovalDecision>({\n _tag: \"unresolved\",\n reason: `Approval delegation failed (${error._tag}); the decision defers to the durable resolveApproval path`,\n }),\n ),\n ),\n };\n});\n\n/** Adapt one hierarchical budget node to the engine's usage accounting seam. */\nexport const toRunBudgetHook = (\n budget: UsageBudgetNode,\n): RunBudgetHook<BudgetExceeded | BudgetAdapterError, never> => ({\n guard: budget.guard,\n consume: (delta) =>\n Schema.decodeEffect(UsageDelta)({\n modelCalls: delta.modelCalls,\n inputTokens: delta.inputTokens,\n outputTokens: delta.outputTokens,\n cacheReadInputTokens: Math.max(0, delta.usage.inputTokens.cacheRead ?? 0),\n cacheWriteInputTokens: Math.max(0, delta.usage.inputTokens.cacheWrite ?? 0),\n toolCalls: delta.toolCalls,\n costMicrousd: delta.costMicrousd,\n }).pipe(\n Effect.mapError((error) =>\n BudgetAdapterError.make({\n message: `Engine usage delta is invalid: ${error.message}`,\n }),\n ),\n Effect.flatMap((usage) => budget.consume(usage)),\n Effect.asVoid,\n ),\n});\n\nexport type ThreadAdapterError =\n | ThreadNotFound\n | ThreadLimitExceeded\n | ThreadEncodingError\n | ThreadHistoryDiverged\n | ThreadOwnershipError;\n\n/**\n * Advanced integration for an existing Thread.Store snapshot. Ordinary Runs automatically\n * retain history through ThreadHistory.layer; use this helper only for explicit snapshot hooks.\n * Share that Layer's Thread.Store owner. PersistentHistory rejects these competing hooks.\n * The snapshot is explicit initial Prompt data. Each inline onHistory call immediately records\n * its append-only suffix, including updates from Runs that later fail or are interrupted. Writes\n * already made remain in the snapshot. Callback errors stop the Run as ThreadAdapterError;\n * snapshot lookup can fail with ThreadNotFound or ThreadOwnershipError before execution.\n * Construct scoped hooks inside InMemory.scoped; captured callbacks retain that owner.\n * Native Effect AI parts and provider options are preserved without a role/text projection.\n * For retaining only successful Runs, provide ThreadHistory through PersistentHistory.layer\n * with a memory or SQLite store instead. This adapter does not provide durable recovery.\n */\nexport const toRunThreadOptions = Effect.fnUntraced(function* (\n threadId: import(\"../core/Identifiers.ts\").ThreadId,\n runId: import(\"../core/Identifiers.ts\").RunId,\n): Effect.fn.Return<\n Pick<RunOptions<ThreadAdapterError>, \"threadId\" | \"history\" | \"onHistory\">,\n ThreadNotFound | ThreadOwnershipError,\n ConversationStore\n> {\n const threads = yield* ConversationStore;\n const snapshot = yield* threads.snapshot(threadId);\n\n return {\n threadId,\n history: toPrompt(snapshot),\n onHistory: (history) => threads.recordHistory(threadId, runId, history).pipe(Effect.asVoid),\n };\n});\n\n/** Prompt transform used by the adapter; the engine retains the authoritative source separately. */\nexport interface EnginePromptTransform<Error = never, Requirements = never> {\n readonly prepare: (\n source: Prompt.Prompt,\n request: RunContextRequest,\n ) => Effect.Effect<Prompt.Prompt, Error, Requirements>;\n}\n\n/** Adapt a prompt-only context transform without granting it authority over engine source history. */\nexport const toRunContextHook = <Error, Requirements>(\n transform: EnginePromptTransform<Error, Requirements>,\n): RunContextHook<Error, Requirements> => ({\n prepare: (request): Effect.Effect<PreparedRunContext, Error, Requirements> =>\n transform.prepare(request.source, request).pipe(Effect.map((prompt) => ({ prompt }))),\n});\n\n/** Scheduling values are structurally aligned and only reduce finite concurrency. */\nexport const toRunSchedulingHook = (\n runOverride: RunSchedulingHook[\"runOverride\"],\n toolRequiresSequential?: (toolName: string) => boolean,\n): RunSchedulingHook => ({\n runOverride,\n ...(toolRequiresSequential === undefined ? {} : { toolRequiresSequential }),\n});\n\n/** Validate policy configuration at adapter construction boundaries. */\nexport const RunApprovalAdapterPolicySchema = Schema.Struct({\n expiresInMillis: Schema.Int.check(Schema.isGreaterThan(0)),\n risk: Schema.Literals([\"low\", \"medium\", \"high\", \"critical\"]),\n denial: Schema.Literals([\"terminal\", \"recoverable\"]),\n});\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { c as SubagentExecutionFailureClassification, l as SubagentGrant, s as SubagentExecutionFailure } from "../SubagentContract-DdPzxYQj.mjs";
|
|
2
2
|
import { o as WorkerCompletion, p as WorkerReport } from "../Worker-CHRaIsWu.mjs";
|
|
3
|
-
import { A as list, C as BackgroundTools, D as cancel, E as awaitWorker, F as SubagentPolicyInput, I as SubagentPrestartDenied, L as SubagentProjectionFailure, M as start, N as stop, O as followUp, P as SubagentPolicy, R as delegationAllocationFromPolicy, S as BackgroundOptions, T as WorkerObservation, _ as SubagentTools, a as SubagentDelegation, b as layer, c as SubagentFailureMode, d as SubagentResult, f as SubagentResultContext, g as SubagentToolFailure, h as SubagentTool, i as SubagentDefineOptions, j as observe, k as inspect, l as SubagentLayerRequirements, m as SubagentRuntimeOptions, n as SubagentContainedFailure, o as SubagentDurableAccounting, p as SubagentReturnModeFailure, r as SubagentDeclarationOptions, s as SubagentDurableOptions, t as SubagentChildRunFailure, u as SubagentPrepareContext, w as Worker, x as make, y as background, z as delegationCapsFromPolicy } from "../Subagent-
|
|
3
|
+
import { A as list, C as BackgroundTools, D as cancel, E as awaitWorker, F as SubagentPolicyInput, I as SubagentPrestartDenied, L as SubagentProjectionFailure, M as start, N as stop, O as followUp, P as SubagentPolicy, R as delegationAllocationFromPolicy, S as BackgroundOptions, T as WorkerObservation, _ as SubagentTools, a as SubagentDelegation, b as layer, c as SubagentFailureMode, d as SubagentResult, f as SubagentResultContext, g as SubagentToolFailure, h as SubagentTool, i as SubagentDefineOptions, j as observe, k as inspect, l as SubagentLayerRequirements, m as SubagentRuntimeOptions, n as SubagentContainedFailure, o as SubagentDurableAccounting, p as SubagentReturnModeFailure, r as SubagentDeclarationOptions, s as SubagentDurableOptions, t as SubagentChildRunFailure, u as SubagentPrepareContext, w as Worker, x as make, y as background, z as delegationCapsFromPolicy } from "../Subagent-xhN_aD1r.mjs";
|
|
4
4
|
export { type BackgroundOptions, type BackgroundTools, SubagentChildRunFailure, SubagentContainedFailure, SubagentDeclarationOptions, SubagentDefineOptions, SubagentDelegation, SubagentDurableAccounting, SubagentDurableOptions, SubagentExecutionFailure, SubagentExecutionFailureClassification, SubagentFailureMode, SubagentGrant, SubagentLayerRequirements, SubagentPolicy, type SubagentPolicyInput, SubagentPrepareContext, SubagentPrestartDenied, SubagentProjectionFailure, SubagentResult, SubagentResultContext, SubagentReturnModeFailure, SubagentRuntimeOptions, SubagentTool, SubagentToolFailure, SubagentTools, Worker, WorkerCompletion, WorkerObservation, WorkerReport, awaitWorker as await, background, cancel, delegationAllocationFromPolicy, delegationCapsFromPolicy, followUp, inspect, layer, list, make, observe, start, stop };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SubagentExecutionFailure, SubagentExecutionFailureClassification, SubagentGrant } from "../core/SubagentContract.mjs";
|
|
2
2
|
import { o as WorkerCompletion, p as WorkerReport } from "../Worker-DZjdMjZn.mjs";
|
|
3
3
|
import "./SubagentReservations.mjs";
|
|
4
|
-
import { _ as SubagentPolicy, a as layer, b as delegationAllocationFromPolicy, c as WorkerObservation, d as followUp, f as inspect, g as stop, h as start, i as background, l as awaitWorker, m as observe, n as SubagentResult, o as make, p as list, s as Worker, t as SubagentDurableAccounting, u as cancel, v as SubagentPrestartDenied, x as delegationCapsFromPolicy, y as SubagentProjectionFailure } from "../Subagent-
|
|
4
|
+
import { _ as SubagentPolicy, a as layer, b as delegationAllocationFromPolicy, c as WorkerObservation, d as followUp, f as inspect, g as stop, h as start, i as background, l as awaitWorker, m as observe, n as SubagentResult, o as make, p as list, s as Worker, t as SubagentDurableAccounting, u as cancel, v as SubagentPrestartDenied, x as delegationCapsFromPolicy, y as SubagentProjectionFailure } from "../Subagent-CexndZSp.mjs";
|
|
5
5
|
export { SubagentDurableAccounting, SubagentExecutionFailure, SubagentExecutionFailureClassification, SubagentGrant, SubagentPolicy, SubagentPrestartDenied, SubagentProjectionFailure, SubagentResult, Worker, WorkerCompletion, WorkerObservation, WorkerReport, awaitWorker as await, background, cancel, delegationAllocationFromPolicy, delegationCapsFromPolicy, followUp, inspect, layer, list, make, observe, start, stop };
|
|
@@ -188,11 +188,13 @@ const fail = (error) => ({
|
|
|
188
188
|
_tag: "error",
|
|
189
189
|
error
|
|
190
190
|
});
|
|
191
|
+
/** Corrupt internal accounting is a defect, never an expected reservation failure. */
|
|
192
|
+
var ReservationLedgerCorrupt = class extends Schema.TaggedError()("ReservationLedgerCorrupt", { message: Schema.String }) {};
|
|
191
193
|
const resolve = (result) => {
|
|
192
194
|
switch (result._tag) {
|
|
193
195
|
case "ok": return Effect.succeed(result.value);
|
|
194
196
|
case "error": return Effect.fail(result.error);
|
|
195
|
-
case "corrupt": return Effect.die(
|
|
197
|
+
case "corrupt": return Effect.die(ReservationLedgerCorrupt.make({ message: result.message }));
|
|
196
198
|
}
|
|
197
199
|
};
|
|
198
200
|
const sameCaps = (a, b) => a.maxTotalChildInvocations === b.maxTotalChildInvocations && a.maxConcurrentChildren === b.maxConcurrentChildren && a.maxTurns === b.maxTurns && a.maxToolCalls === b.maxToolCalls && a.maxDurationMillis === b.maxDurationMillis && a.maxInputTokens === b.maxInputTokens && a.maxOutputTokens === b.maxOutputTokens && a.maxCostMicrousd === b.maxCostMicrousd && a.maxResultBytes === b.maxResultBytes;
|