effect-agent 0.1.0-beta.144 → 0.1.0-beta.148

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.
Files changed (81) hide show
  1. package/dist/{Admin-CQMppCcy.d.mts → Admin-BzPfXvzC.d.mts} +37 -22
  2. package/dist/Agent-1DMSO_Fl.mjs.map +1 -1
  3. package/dist/{Agent-BWhD4Dvu.d.mts → Agent-Cjd_ZveM.d.mts} +7 -3
  4. package/dist/{AgentRuntime-xeCUXutN.mjs → AgentRuntime-D8U9gl9Q.mjs} +23 -18
  5. package/dist/AgentRuntime-D8U9gl9Q.mjs.map +1 -0
  6. package/dist/{AgentRuntime-B4kIzmSF.d.mts → AgentRuntime-DZdgNcBk.d.mts} +5 -5
  7. package/dist/{DurableAgentRuntime-D8GI66mP.mjs → DurableAgentRuntime-N5Meflyt.mjs} +70 -42
  8. package/dist/DurableAgentRuntime-N5Meflyt.mjs.map +1 -0
  9. package/dist/{EventSource-w9PonN9X.d.mts → EventSource-DJW_1kPY.d.mts} +2 -2
  10. package/dist/{Messaging-Dnmk31yq.d.mts → Messaging-ccQURKCf.d.mts} +3 -3
  11. package/dist/{MessagingHost-CajpPDPG.d.mts → MessagingHost-D04wE-7W.d.mts} +2 -2
  12. package/dist/{Output-DhtWbBcw.d.mts → Output-CFD1CPfU.d.mts} +2 -2
  13. package/dist/{PreparedInputAdmission-BfcLy_k4.d.mts → PreparedInputAdmission-CNRSDoYu.d.mts} +3 -3
  14. package/dist/{RunOptions-IlEXLG5F.d.mts → RunOptions-Cy7CjrjS.d.mts} +2 -2
  15. package/dist/{Subagent-8RzJkqJ9.mjs → Subagent-hG9lJ7tJ.mjs} +2 -2
  16. package/dist/{Subagent-8RzJkqJ9.mjs.map → Subagent-hG9lJ7tJ.mjs.map} +1 -1
  17. package/dist/{Subagent-Cl8D1mFM.d.mts → Subagent-zS6prSK6.d.mts} +5 -5
  18. package/dist/{SubagentHost-B6f4PBC2.d.mts → SubagentHost-C-4A7tA2.d.mts} +2 -2
  19. package/dist/{Subscription-ClkC4_T0.d.mts → Subscription-C279AjM6.d.mts} +2 -2
  20. package/dist/{SubscriptionInput-CMjEKL1z.d.mts → SubscriptionInput-7R-Xrpxd.d.mts} +2 -2
  21. package/dist/capabilities/Commands.d.mts +1 -1
  22. package/dist/capabilities/Messaging.d.mts +1 -1
  23. package/dist/capabilities/RunHooks.d.mts +1 -1
  24. package/dist/capabilities/Subagent.d.mts +1 -1
  25. package/dist/capabilities/Subagent.mjs +1 -1
  26. package/dist/core/Agent.d.mts +1 -1
  27. package/dist/durable/Admin.d.mts +1 -1
  28. package/dist/durable/AgentRegistration.d.mts +1 -1
  29. package/dist/durable/Certification.d.mts +1 -1
  30. package/dist/durable/CommittedActivity.d.mts +1 -1
  31. package/dist/durable/DurableAgentRuntime.d.mts +1 -1
  32. package/dist/durable/DurableAgentRuntime.mjs +1 -1
  33. package/dist/durable/EventSource.d.mts +1 -1
  34. package/dist/durable/GitHubWorkflowSource.d.mts +3 -3
  35. package/dist/durable/LifecyclePublication.d.mts +2 -2
  36. package/dist/durable/LifecyclePublication.mjs +32 -12
  37. package/dist/durable/LifecyclePublication.mjs.map +1 -1
  38. package/dist/durable/MessageDelivery.d.mts +41 -41
  39. package/dist/durable/MessageDeliveryStoreConformance.d.mts +39 -39
  40. package/dist/durable/PersistentHistory.d.mts +1 -1
  41. package/dist/durable/PreparedInputAdmission.d.mts +1 -1
  42. package/dist/durable/Recovery.d.mts +1 -1
  43. package/dist/durable/RunJournal.d.mts +1 -1
  44. package/dist/durable/Scheduling.d.mts +1 -1
  45. package/dist/durable/SubmissionLedger.d.mts +1 -1
  46. package/dist/durable/SubmissionLedgerConformance.d.mts +1 -1
  47. package/dist/durable/SubmissionStatus.d.mts +1 -1
  48. package/dist/durable/Subscription.d.mts +1 -1
  49. package/dist/durable/SubscriptionInput.d.mts +1 -1
  50. package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
  51. package/dist/durable/SubscriptionTools.d.mts +2 -2
  52. package/dist/durable/SubscriptionTransition.d.mts +1 -1
  53. package/dist/durable/Subscriptions.d.mts +5 -5
  54. package/dist/durable/ThreadContextHistory.d.mts +1 -1
  55. package/dist/durable/ThreadInvariants.d.mts +1 -1
  56. package/dist/durable/ThreadProjectionMaintenance.d.mts +1 -1
  57. package/dist/durable/ThreadStore.d.mts +1 -1
  58. package/dist/durable/ThreadStoreConformance.d.mts +1 -1
  59. package/dist/durable/WorkerHost.d.mts +25 -5
  60. package/dist/durable/WorkerHost.mjs.map +1 -1
  61. package/dist/engine/AgentRuntime.d.mts +1 -1
  62. package/dist/engine/AgentRuntime.mjs +1 -1
  63. package/dist/engine/MessagingHost.d.mts +1 -1
  64. package/dist/engine/Output.d.mts +1 -1
  65. package/dist/engine/Output.mjs +1 -1
  66. package/dist/engine/RunOptions.d.mts +1 -1
  67. package/dist/engine/SubagentHost.d.mts +1 -1
  68. package/dist/index.d.mts +13 -13
  69. package/dist/index.mjs +3 -3
  70. package/dist/{output-contract-CANJJGA5.mjs → output-contract-DS-S8mTv.mjs} +46 -10
  71. package/dist/{output-contract-CANJJGA5.mjs.map → output-contract-DS-S8mTv.mjs.map} +1 -1
  72. package/package.json +1 -1
  73. package/src/core/Agent.ts +6 -2
  74. package/src/durable/DurableAgentRuntime.ts +50 -58
  75. package/src/durable/LifecyclePublication.ts +79 -25
  76. package/src/durable/WorkerHost.ts +23 -1
  77. package/src/durable/internal/worker-host.ts +169 -17
  78. package/src/engine/internal/agent-runtime.ts +80 -18
  79. package/src/engine/internal/output-contract.ts +67 -8
  80. package/dist/AgentRuntime-xeCUXutN.mjs.map +0 -1
  81. package/dist/DurableAgentRuntime-D8GI66mP.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"output-contract-CANJJGA5.mjs","names":[],"sources":["../src/engine/internal/output-contract.ts"],"sourcesContent":["import { Schema } from \"effect\";\nimport { Prompt, Tool } from \"effect/unstable/ai\";\n\nimport type * as Agent from \"../../core/Agent.ts\";\n\nconst outputFormatAnnotation = \"@effect-agent/engine/Output/format\";\n\n/**\n * Declare ordinary assistant text as an Agent's final-output wire format. Apply this to the\n * complete output Schema after composing transformations. Its encoded type must be string;\n * decoding, checks, transformations, and service requirements remain owned by that Schema.\n * Text is preserved verbatim, including whitespace, quotes, and an empty reply when allowed.\n * Required completion Tools still take precedence. Unmarked Schemas use JSON final output.\n *\n * @example\n * ```ts\n * output: Output.text(Schema.String.check(Schema.isMaxLength(20_000)))\n * ```\n */\nexport const textOutput = <S extends Schema.Top & { readonly Encoded: string }>(\n schema: S,\n): S[\"Rebuild\"] => schema.annotate({ [outputFormatAnnotation]: \"text\" });\n\nexport const isTextOutput = (schema: Schema.Top): boolean =>\n Schema.resolveAnnotations(schema)?.[outputFormatAnnotation] === \"text\";\n\n/**\n * Model-visible final-output contract (RUN-028).\n *\n * For ordinary text completion, the interpreter's only output-conformance\n * point is `decodeFinalOutput`, which validates the final text after the\n * model has already finished. This module renders that Schema's wire contract\n * with the same Effect AI derivation the providers use for Tool parameters\n * and states it as one framework-owned system message on every model request.\n * A required completion Tool instead gets a native-tool directive: its Tool\n * parameter Schema is already carried by the provider request, and ordinary\n * final text is not an allowed completion path.\n *\n * The contract is a per-request projection of the immutable definition —\n * exactly like the Tool schemas the request already carries. It is inserted\n * at model-request materialization (after context preparation) and never\n * into official history, so canonical records, run events, and the committed\n * DN/DC golden are unchanged.\n *\n */\n\n/** Rendering outcome for one definition's output Schema. */\ntype OutputContract =\n | {\n readonly _tag: \"rendered\";\n /** The complete system-message text: directive plus the derived JSON Schema. */\n readonly message: string;\n readonly part: Prompt.SystemMessage;\n }\n | {\n readonly _tag: \"unrenderable\";\n /** Why Effect AI's JSON-Schema derivation rejected the output Schema. */\n readonly reason: string;\n };\n\nconst contractDirective = (definition: Agent.AnyDefinition): string =>\n definition.completion === undefined\n ? \"Final output contract: when the task is complete, the final assistant message must be only \" +\n \"JSON that is valid against this JSON Schema — no prose, no Markdown code fences, nothing \" +\n \"before or after the JSON.\"\n : `Final output contract: when the task is complete without calling the \"${definition.completion.tool}\" completion Tool, the final assistant message must be only ` +\n \"JSON that is valid against this JSON Schema — no prose, no Markdown code fences, nothing \" +\n `before or after the JSON. When calling the \"${definition.completion.tool}\" completion Tool, never place this private Agent output JSON in any Tool argument; follow the Tool's parameter schema instead. Call it as the sole application Tool Call, after receiving any other needed application Tool results. Completed provider Tool results may accompany it. The engine projects the successful completion Tool result into the Agent output.`;\n\nconst requiredCompletionDirective = (tool: string, hasAlternatives: boolean): string =>\n `Final output contract: ${hasAlternatives ? \"otherwise complete\" : \"complete only\"} by calling the required completion Tool ${JSON.stringify(tool)} ` +\n \"as the sole application Tool Call in its batch. Completed provider Tool results may accompany it. Do not emit an ordinary final assistant text answer. \" +\n \"The Tool's canonical parameters and successful result are projected and validated as the Agent output.\";\n\n/**\n * Render the model-visible final-output contract for one definition. The\n * derivation and message identity are stable for an immutable definition.\n * An output Schema the Effect AI derivation cannot represent is reported as\n * `unrenderable`; the caller falls back to the prior behavior — the contract\n * is guidance, and a Schema that decodes but does not render must not become\n * a new failure mode.\n */\nconst rendered = (message: string): OutputContract => ({\n _tag: \"rendered\",\n message,\n part: Prompt.makeMessage(\"system\", { content: message }),\n});\n\nconst renderOutputSchemaContract = (definition: Agent.AnyDefinition): OutputContract => {\n if (definition.completion?.required === true) {\n return rendered(\n requiredCompletionDirective(\n definition.completion.tool,\n (definition.completionFromTools?.length ?? 0) > 0,\n ),\n );\n }\n if (isTextOutput(definition.output)) {\n return rendered(\n \"Final output contract: write the final reply as ordinary assistant text, without JSON wrapping. \" +\n \"An empty reply is valid only when allowed by the output Schema and the task instructions.\" +\n (definition.completion === undefined\n ? \"\"\n : ` When calling the \"${definition.completion.tool}\" completion Tool, follow its parameter schema instead and call it as the sole application Tool Call, after receiving any other needed application Tool results; completed provider Tool results may accompany it; the engine projects its successful result into the Agent output.`),\n );\n }\n try {\n const jsonSchema = Tool.getJsonSchemaFromSchema(definition.output);\n\n return rendered(\n `${contractDirective(definition)}\\n\\n${JSON.stringify(jsonSchema, undefined, 2)}`,\n );\n } catch (cause) {\n return {\n _tag: \"unrenderable\",\n reason: cause instanceof Error ? cause.message : String(cause),\n };\n }\n};\n\n// Native incremental-response tracking recognizes message objects, not rendered text.\n// Weak keys retain neither discarded definitions nor their Schema graphs.\nconst outputContracts = new WeakMap<Agent.AnyDefinition, OutputContract>();\n\nexport const outputSchemaContract = (definition: Agent.AnyDefinition): OutputContract => {\n const cached = outputContracts.get(definition);\n\n if (cached !== undefined) return cached;\n const base = renderOutputSchemaContract(definition);\n const alternatives = definition.completionFromTools ?? [];\n\n const contract =\n base._tag === \"rendered\" && alternatives.length > 0\n ? rendered(\n `The following action Tools may complete the Run from their successful canonical result: ${alternatives.map((declaration) => JSON.stringify(declaration.tool)).join(\", \")}. ` +\n \"Call such a Tool as the sole application Tool Call, following its parameter schema. Completed provider Tool results may accompany it. It may complete the Run only when it satisfies the whole request. \" +\n \"An incomplete or pending result continues the Run. These actions are unavailable during finalization after budget exhaustion.\\n\\n\" +\n base.message,\n )\n : base;\n\n outputContracts.set(definition, contract);\n\n return contract;\n};\n\nconst sameSystemMessage = Schema.toEquivalence(Prompt.SystemMessage);\n\n/**\n * Project system instructions and the output contract into one leading block.\n * Repeated Runs append instructions to canonical history; letting those copies\n * move the contract breaks the preceding user/tool prefix used by provider caches.\n * Keep the last occurrence of each equivalent system message, preserving the\n * precedence of distinct instructions and their native provider options.\n *\n * This runs after preparation and compaction. Canonical messages, protected\n * instruction/input spans and compaction coverage retain their original positions.\n * Conversation order and message identities are unchanged. A single system block\n * also prevents Anthropic's last-system-group conversion from discarding earlier\n * application instructions or the output contract.\n */\nexport const prepareModelPrompt = (\n prompt: Prompt.Prompt,\n contract: Prompt.SystemMessage | undefined,\n): Prompt.Prompt => {\n const systems: Array<Prompt.SystemMessage> = [];\n const conversation: Array<Prompt.Message> = [];\n const seen = new Map<string, Array<Prompt.SystemMessage>>();\n\n for (let index = prompt.content.length - 1; index >= 0; index -= 1) {\n const message = prompt.content[index];\n\n if (message === undefined) continue;\n if (message.role !== \"system\") {\n conversation.push(message);\n continue;\n }\n const variants = seen.get(message.content);\n\n if (variants?.some((previous) => sameSystemMessage(previous, message))) continue;\n if (variants === undefined) seen.set(message.content, [message]);\n else variants.push(message);\n systems.push(message);\n }\n\n return Prompt.fromMessages([\n ...systems.reverse(),\n ...(contract === undefined ? [] : [contract]),\n ...conversation.reverse(),\n ]);\n};\n"],"mappings":";;;AAKA,MAAM,yBAAyB;;;;;;;;;;;;;AAc/B,MAAa,cACX,WACiB,OAAO,SAAS,GAAG,yBAAyB,OAAO,CAAC;AAEvE,MAAa,gBAAgB,WAC3B,OAAO,mBAAmB,MAAM,CAAC,GAAG,4BAA4B;AAoClE,MAAM,qBAAqB,eACzB,WAAW,eAAe,KAAA,IACtB,kNAGA,yEAAyE,WAAW,WAAW,KAAK,mMAErD,WAAW,WAAW,KAAK;AAEhF,MAAM,+BAA+B,MAAc,oBACjD,0BAA0B,kBAAkB,uBAAuB,gBAAgB,2CAA2C,KAAK,UAAU,IAAI,EAAE;;;;;;;;;AAYrJ,MAAM,YAAY,aAAqC;CACrD,MAAM;CACN;CACA,MAAM,OAAO,YAAY,UAAU,EAAE,SAAS,QAAQ,CAAC;AACzD;AAEA,MAAM,8BAA8B,eAAoD;CACtF,IAAI,WAAW,YAAY,aAAa,MACtC,OAAO,SACL,4BACE,WAAW,WAAW,OACrB,WAAW,qBAAqB,UAAU,KAAK,CAClD,CACF;CAEF,IAAI,aAAa,WAAW,MAAM,GAChC,OAAO,SACL,+LAEG,WAAW,eAAe,KAAA,IACvB,KACA,sBAAsB,WAAW,WAAW,KAAK,qRACzD;CAEF,IAAI;EACF,MAAM,aAAa,KAAK,wBAAwB,WAAW,MAAM;EAEjE,OAAO,SACL,GAAG,kBAAkB,UAAU,EAAE,MAAM,KAAK,UAAU,YAAY,KAAA,GAAW,CAAC,GAChF;CACF,SAAS,OAAO;EACd,OAAO;GACL,MAAM;GACN,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EAC/D;CACF;AACF;AAIA,MAAM,kCAAkB,IAAI,QAA6C;AAEzE,MAAa,wBAAwB,eAAoD;CACvF,MAAM,SAAS,gBAAgB,IAAI,UAAU;CAE7C,IAAI,WAAW,KAAA,GAAW,OAAO;CACjC,MAAM,OAAO,2BAA2B,UAAU;CAClD,MAAM,eAAe,WAAW,uBAAuB,CAAC;CAExD,MAAM,WACJ,KAAK,SAAS,cAAc,aAAa,SAAS,IAC9C,SACE,2FAA2F,aAAa,KAAK,gBAAgB,KAAK,UAAU,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE;;IAGxK,KAAK,OACT,IACA;CAEN,gBAAgB,IAAI,YAAY,QAAQ;CAExC,OAAO;AACT;AAEA,MAAM,oBAAoB,OAAO,cAAc,OAAO,aAAa;;;;;;;;;;;;;;AAenE,MAAa,sBACX,QACA,aACkB;CAClB,MAAM,UAAuC,CAAC;CAC9C,MAAM,eAAsC,CAAC;CAC7C,MAAM,uBAAO,IAAI,IAAyC;CAE1D,KAAK,IAAI,QAAQ,OAAO,QAAQ,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG;EAClE,MAAM,UAAU,OAAO,QAAQ;EAE/B,IAAI,YAAY,KAAA,GAAW;EAC3B,IAAI,QAAQ,SAAS,UAAU;GAC7B,aAAa,KAAK,OAAO;GACzB;EACF;EACA,MAAM,WAAW,KAAK,IAAI,QAAQ,OAAO;EAEzC,IAAI,UAAU,MAAM,aAAa,kBAAkB,UAAU,OAAO,CAAC,GAAG;EACxE,IAAI,aAAa,KAAA,GAAW,KAAK,IAAI,QAAQ,SAAS,CAAC,OAAO,CAAC;OAC1D,SAAS,KAAK,OAAO;EAC1B,QAAQ,KAAK,OAAO;CACtB;CAEA,OAAO,OAAO,aAAa;EACzB,GAAG,QAAQ,QAAQ;EACnB,GAAI,aAAa,KAAA,IAAY,CAAC,IAAI,CAAC,QAAQ;EAC3C,GAAG,aAAa,QAAQ;CAC1B,CAAC;AACH"}
1
+ {"version":3,"file":"output-contract-DS-S8mTv.mjs","names":[],"sources":["../src/engine/internal/output-contract.ts"],"sourcesContent":["import { Schema } from \"effect\";\nimport { Prompt, Tool } from \"effect/unstable/ai\";\n\nimport type * as Agent from \"../../core/Agent.ts\";\n\nconst outputFormatAnnotation = \"@effect-agent/engine/Output/format\";\n\n/**\n * Declare ordinary assistant text as an Agent's final-output wire format. Apply this to the\n * complete output Schema after composing transformations. Its encoded type must be string;\n * decoding, checks, transformations, and service requirements remain owned by that Schema.\n * Text is preserved verbatim, including whitespace, quotes, and an empty reply when allowed.\n * Required completion Tools still take precedence. Unmarked Schemas use JSON final output.\n *\n * @example\n * ```ts\n * output: Output.text(Schema.String.check(Schema.isMaxLength(20_000)))\n * ```\n */\nexport const textOutput = <S extends Schema.Top & { readonly Encoded: string }>(\n schema: S,\n): S[\"Rebuild\"] => schema.annotate({ [outputFormatAnnotation]: \"text\" });\n\nexport const isTextOutput = (schema: Schema.Top): boolean =>\n Schema.resolveAnnotations(schema)?.[outputFormatAnnotation] === \"text\";\n\n/**\n * Model-visible final-output contract (RUN-028).\n *\n * For ordinary text completion, the interpreter's only output-conformance\n * point is `decodeFinalOutput`, which validates the final text after the\n * model has already finished. This module renders that Schema's wire contract\n * with the same Effect AI derivation the providers use for Tool parameters\n * and states it as one framework-owned system message on every model request.\n * A required completion Tool instead gets a native-tool directive: its Tool\n * parameter Schema is already carried by the provider request, and ordinary\n * final text is not an allowed completion path.\n *\n * The contract is a per-request projection of the immutable definition —\n * exactly like the Tool schemas the request already carries. It is inserted\n * at model-request materialization (after context preparation) and never\n * into official history, so canonical records, run events, and the committed\n * DN/DC golden are unchanged.\n *\n */\n\n/** Rendering outcome for one definition's output Schema. */\ntype OutputContract =\n | {\n readonly _tag: \"rendered\";\n /** The complete system-message text: directive plus the derived JSON Schema. */\n readonly message: string;\n readonly part: Prompt.SystemMessage;\n }\n | {\n readonly _tag: \"unrenderable\";\n /** Why Effect AI's JSON-Schema derivation rejected the output Schema. */\n readonly reason: string;\n };\n\nconst contractDirective = (definition: Agent.AnyDefinition): string =>\n definition.completion === undefined\n ? \"Final output contract: when the task is complete, the final assistant message must be only \" +\n \"JSON that is valid against this JSON Schema — no prose, no Markdown code fences, nothing \" +\n \"before or after the JSON.\"\n : `Final output contract: when the task is complete without calling the \"${definition.completion.tool}\" completion Tool, the final assistant message must be only ` +\n \"JSON that is valid against this JSON Schema — no prose, no Markdown code fences, nothing \" +\n `before or after the JSON. When calling the \"${definition.completion.tool}\" completion Tool, never place this private Agent output JSON in any Tool argument; follow the Tool's parameter schema instead. Call it as the sole application Tool Call, after receiving any other needed application Tool results. Completed provider Tool results may accompany it. The engine projects the successful completion Tool result into the Agent output.`;\n\nconst requiredCompletionDirective = (tool: string, hasAlternatives: boolean): string =>\n `Final output contract: ${hasAlternatives ? \"otherwise complete\" : \"complete only\"} by calling the required completion Tool ${JSON.stringify(tool)} ` +\n \"as the sole application Tool Call in its batch. Completed provider Tool results may accompany it. Do not emit an ordinary final assistant text answer. \" +\n \"The Tool's canonical parameters and successful result are projected and validated as the Agent output.\";\n\n/**\n * Render the model-visible final-output contract for one definition. The\n * derivation and message identity are stable for an immutable definition.\n * An output Schema the Effect AI derivation cannot represent is reported as\n * `unrenderable`; the caller falls back to the prior behavior — the contract\n * is guidance, and a Schema that decodes but does not render must not become\n * a new failure mode.\n */\nconst rendered = (message: string): OutputContract => ({\n _tag: \"rendered\",\n message,\n part: Prompt.makeMessage(\"system\", { content: message }),\n});\n\nconst renderOutputSchemaContract = (definition: Agent.AnyDefinition): OutputContract => {\n if (definition.completion?.required === true) {\n return rendered(\n requiredCompletionDirective(\n definition.completion.tool,\n (definition.completionFromTools?.length ?? 0) > 0,\n ),\n );\n }\n if (isTextOutput(definition.output)) {\n return rendered(\n \"Final output contract: write the final reply as ordinary assistant text, without JSON wrapping. \" +\n \"An empty reply is valid only when allowed by the output Schema and the task instructions.\" +\n (definition.completion === undefined\n ? \"\"\n : ` When calling the \"${definition.completion.tool}\" completion Tool, follow its parameter schema instead and call it as the sole application Tool Call, after receiving any other needed application Tool results; completed provider Tool results may accompany it; the engine projects its successful result into the Agent output.`),\n );\n }\n try {\n const jsonSchema = Tool.getJsonSchemaFromSchema(definition.output);\n\n return rendered(\n `${contractDirective(definition)}\\n\\n${JSON.stringify(jsonSchema, undefined, 2)}`,\n );\n } catch (cause) {\n return {\n _tag: \"unrenderable\",\n reason: cause instanceof Error ? cause.message : String(cause),\n };\n }\n};\n\n// Native incremental-response tracking recognizes message objects, not rendered text.\n// Weak keys retain neither discarded definitions nor their Schema graphs.\nconst outputContracts = new WeakMap<Agent.AnyDefinition, OutputContract>();\n\nexport const outputSchemaContract = (definition: Agent.AnyDefinition): OutputContract => {\n const cached = outputContracts.get(definition);\n\n if (cached !== undefined) return cached;\n const base = renderOutputSchemaContract(definition);\n const alternatives = definition.completionFromTools ?? [];\n\n const contract =\n base._tag === \"rendered\" && alternatives.length > 0\n ? rendered(\n `The following action Tools may complete the Run from their successful canonical result: ${alternatives.map((declaration) => JSON.stringify(declaration.tool)).join(\", \")}. ` +\n \"Call such a Tool as the sole application Tool Call, following its parameter schema. Completed provider Tool results may accompany it. It may complete the Run only when it satisfies the whole request. \" +\n \"An incomplete or pending result continues the Run. These actions are unavailable during finalization after budget exhaustion.\\n\\n\" +\n base.message,\n )\n : base;\n\n outputContracts.set(definition, contract);\n\n return contract;\n};\n\nconst sameSystemMessage = Schema.toEquivalence(Prompt.SystemMessage);\n\n/**\n * Keep supported system instructions in conversation order so changing late guidance\n * cannot invalidate the preceding user/tool cache prefix. Omit an exact repeat\n * only when no distinct system instruction intervened; returning to an earlier\n * instruction after a different one must preserve the new directive's precedence.\n * Anchor the immutable output contract after the initial system block.\n * Restore leading static instructions for caller-supplied conversation-only history.\n *\n * This runs after preparation and compaction. Canonical messages, protected\n * instruction/input spans and compaction coverage retain their original positions.\n * Adapters without this capability retain the grouped-system projection: keep the\n * last equivalent instruction with its native options, then the contract and\n * conversation. This prevents older Anthropic adapters from discarding system groups.\n */\nexport const prepareModelPrompt = (\n prompt: Prompt.Prompt,\n contract: Prompt.SystemMessage | undefined,\n systemMessagesInHistory: boolean,\n staticInstructions: Prompt.RawInput | undefined,\n): Prompt.Prompt => {\n if (systemMessagesInHistory) {\n const content: Array<Prompt.Message> = [];\n let lastSystem: Prompt.SystemMessage | undefined;\n let ordered = prompt.content;\n\n if (staticInstructions !== undefined) {\n const firstConversation = prompt.content.findIndex((message) => message.role !== \"system\");\n\n const leading = prompt.content.slice(\n 0,\n firstConversation === -1 ? prompt.content.length : firstConversation,\n );\n\n const restored: Array<Prompt.Message> = [];\n\n const instructions =\n typeof staticInstructions === \"string\"\n ? [Prompt.systemMessage({ content: staticInstructions })]\n : Prompt.make(staticInstructions).content;\n\n for (const message of instructions) {\n if (message.role !== \"system\") break;\n if (\n leading.some(\n (candidate) => candidate.role === \"system\" && sameSystemMessage(candidate, message),\n )\n )\n break;\n\n const original = prompt.content.find(\n (candidate) => candidate.role === \"system\" && sameSystemMessage(candidate, message),\n );\n\n if (original === undefined) break;\n restored.push(original);\n }\n if (restored.length > 0)\n ordered = [...leading, ...restored, ...prompt.content.slice(leading.length)];\n }\n\n for (const message of ordered) {\n if (message.role === \"system\") {\n if (lastSystem !== undefined && sameSystemMessage(lastSystem, message)) continue;\n lastSystem = message;\n }\n content.push(message);\n }\n if (contract !== undefined) {\n const firstConversation = content.findIndex((message) => message.role !== \"system\");\n\n content.splice(firstConversation === -1 ? content.length : firstConversation, 0, contract);\n }\n\n return Prompt.fromMessages(content);\n }\n\n const systems: Array<Prompt.SystemMessage> = [];\n const conversation: Array<Prompt.Message> = [];\n const seen = new Map<string, Array<Prompt.SystemMessage>>();\n\n for (let index = prompt.content.length - 1; index >= 0; index -= 1) {\n const message = prompt.content[index];\n\n if (message === undefined) continue;\n if (message.role !== \"system\") {\n conversation.push(message);\n continue;\n }\n const variants = seen.get(message.content);\n\n if (variants?.some((previous) => sameSystemMessage(previous, message))) continue;\n if (variants === undefined) seen.set(message.content, [message]);\n else variants.push(message);\n systems.push(message);\n }\n\n return Prompt.fromMessages([\n ...systems.reverse(),\n ...(contract === undefined ? [] : [contract]),\n ...conversation.reverse(),\n ]);\n};\n"],"mappings":";;;AAKA,MAAM,yBAAyB;;;;;;;;;;;;;AAc/B,MAAa,cACX,WACiB,OAAO,SAAS,GAAG,yBAAyB,OAAO,CAAC;AAEvE,MAAa,gBAAgB,WAC3B,OAAO,mBAAmB,MAAM,CAAC,GAAG,4BAA4B;AAoClE,MAAM,qBAAqB,eACzB,WAAW,eAAe,KAAA,IACtB,kNAGA,yEAAyE,WAAW,WAAW,KAAK,mMAErD,WAAW,WAAW,KAAK;AAEhF,MAAM,+BAA+B,MAAc,oBACjD,0BAA0B,kBAAkB,uBAAuB,gBAAgB,2CAA2C,KAAK,UAAU,IAAI,EAAE;;;;;;;;;AAYrJ,MAAM,YAAY,aAAqC;CACrD,MAAM;CACN;CACA,MAAM,OAAO,YAAY,UAAU,EAAE,SAAS,QAAQ,CAAC;AACzD;AAEA,MAAM,8BAA8B,eAAoD;CACtF,IAAI,WAAW,YAAY,aAAa,MACtC,OAAO,SACL,4BACE,WAAW,WAAW,OACrB,WAAW,qBAAqB,UAAU,KAAK,CAClD,CACF;CAEF,IAAI,aAAa,WAAW,MAAM,GAChC,OAAO,SACL,+LAEG,WAAW,eAAe,KAAA,IACvB,KACA,sBAAsB,WAAW,WAAW,KAAK,qRACzD;CAEF,IAAI;EACF,MAAM,aAAa,KAAK,wBAAwB,WAAW,MAAM;EAEjE,OAAO,SACL,GAAG,kBAAkB,UAAU,EAAE,MAAM,KAAK,UAAU,YAAY,KAAA,GAAW,CAAC,GAChF;CACF,SAAS,OAAO;EACd,OAAO;GACL,MAAM;GACN,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EAC/D;CACF;AACF;AAIA,MAAM,kCAAkB,IAAI,QAA6C;AAEzE,MAAa,wBAAwB,eAAoD;CACvF,MAAM,SAAS,gBAAgB,IAAI,UAAU;CAE7C,IAAI,WAAW,KAAA,GAAW,OAAO;CACjC,MAAM,OAAO,2BAA2B,UAAU;CAClD,MAAM,eAAe,WAAW,uBAAuB,CAAC;CAExD,MAAM,WACJ,KAAK,SAAS,cAAc,aAAa,SAAS,IAC9C,SACE,2FAA2F,aAAa,KAAK,gBAAgB,KAAK,UAAU,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE;;IAGxK,KAAK,OACT,IACA;CAEN,gBAAgB,IAAI,YAAY,QAAQ;CAExC,OAAO;AACT;AAEA,MAAM,oBAAoB,OAAO,cAAc,OAAO,aAAa;;;;;;;;;;;;;;;AAgBnE,MAAa,sBACX,QACA,UACA,yBACA,uBACkB;CAClB,IAAI,yBAAyB;EAC3B,MAAM,UAAiC,CAAC;EACxC,IAAI;EACJ,IAAI,UAAU,OAAO;EAErB,IAAI,uBAAuB,KAAA,GAAW;GACpC,MAAM,oBAAoB,OAAO,QAAQ,WAAW,YAAY,QAAQ,SAAS,QAAQ;GAEzF,MAAM,UAAU,OAAO,QAAQ,MAC7B,GACA,sBAAsB,KAAK,OAAO,QAAQ,SAAS,iBACrD;GAEA,MAAM,WAAkC,CAAC;GAEzC,MAAM,eACJ,OAAO,uBAAuB,WAC1B,CAAC,OAAO,cAAc,EAAE,SAAS,mBAAmB,CAAC,CAAC,IACtD,OAAO,KAAK,kBAAkB,CAAC,CAAC;GAEtC,KAAK,MAAM,WAAW,cAAc;IAClC,IAAI,QAAQ,SAAS,UAAU;IAC/B,IACE,QAAQ,MACL,cAAc,UAAU,SAAS,YAAY,kBAAkB,WAAW,OAAO,CACpF,GAEA;IAEF,MAAM,WAAW,OAAO,QAAQ,MAC7B,cAAc,UAAU,SAAS,YAAY,kBAAkB,WAAW,OAAO,CACpF;IAEA,IAAI,aAAa,KAAA,GAAW;IAC5B,SAAS,KAAK,QAAQ;GACxB;GACA,IAAI,SAAS,SAAS,GACpB,UAAU;IAAC,GAAG;IAAS,GAAG;IAAU,GAAG,OAAO,QAAQ,MAAM,QAAQ,MAAM;GAAC;EAC/E;EAEA,KAAK,MAAM,WAAW,SAAS;GAC7B,IAAI,QAAQ,SAAS,UAAU;IAC7B,IAAI,eAAe,KAAA,KAAa,kBAAkB,YAAY,OAAO,GAAG;IACxE,aAAa;GACf;GACA,QAAQ,KAAK,OAAO;EACtB;EACA,IAAI,aAAa,KAAA,GAAW;GAC1B,MAAM,oBAAoB,QAAQ,WAAW,YAAY,QAAQ,SAAS,QAAQ;GAElF,QAAQ,OAAO,sBAAsB,KAAK,QAAQ,SAAS,mBAAmB,GAAG,QAAQ;EAC3F;EAEA,OAAO,OAAO,aAAa,OAAO;CACpC;CAEA,MAAM,UAAuC,CAAC;CAC9C,MAAM,eAAsC,CAAC;CAC7C,MAAM,uBAAO,IAAI,IAAyC;CAE1D,KAAK,IAAI,QAAQ,OAAO,QAAQ,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG;EAClE,MAAM,UAAU,OAAO,QAAQ;EAE/B,IAAI,YAAY,KAAA,GAAW;EAC3B,IAAI,QAAQ,SAAS,UAAU;GAC7B,aAAa,KAAK,OAAO;GACzB;EACF;EACA,MAAM,WAAW,KAAK,IAAI,QAAQ,OAAO;EAEzC,IAAI,UAAU,MAAM,aAAa,kBAAkB,UAAU,OAAO,CAAC,GAAG;EACxE,IAAI,aAAa,KAAA,GAAW,KAAK,IAAI,QAAQ,SAAS,CAAC,OAAO,CAAC;OAC1D,SAAS,KAAK,OAAO;EAC1B,QAAQ,KAAK,OAAO;CACtB;CAEA,OAAO,OAAO,aAAa;EACzB,GAAG,QAAQ,QAAQ;EACnB,GAAI,aAAa,KAAA,IAAY,CAAC,IAAI,CAAC,QAAQ;EAC3C,GAAG,aAAa,QAAQ;CAC1B,CAAC;AACH"}
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"effect-agent","version":"0.1.0-beta.144","devDependencies":{"@effect/platform-node":"4.0.0-rc.117","@effect/vitest":"4.0.0-rc.117","effect":"4.0.0-rc.117","typescript":"7.0.2","vite-plus":"0.3.3"},"peerDependencies":{"effect":"^4.0.0-rc.117"},"exports":{".":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"./activity-store":{"types":"./dist/durable/ActivityStore.d.mts","default":"./dist/durable/ActivityStore.mjs"},"./admin":{"types":"./dist/durable/Admin.d.mts","default":"./dist/durable/Admin.mjs"},"./agent":{"types":"./dist/core/Agent.d.mts","default":"./dist/core/Agent.mjs"},"./agent-error":{"types":"./dist/core/AgentError.d.mts","default":"./dist/core/AgentError.mjs"},"./agent-policy":{"types":"./dist/core/AgentPolicy.d.mts","default":"./dist/core/AgentPolicy.mjs"},"./agent-registration":{"types":"./dist/durable/AgentRegistration.d.mts","default":"./dist/durable/AgentRegistration.mjs"},"./agent-runtime":{"types":"./dist/engine/AgentRuntime.d.mts","default":"./dist/engine/AgentRuntime.mjs"},"./agent-updates":{"types":"./dist/core/AgentUpdates.d.mts","default":"./dist/core/AgentUpdates.mjs"},"./approval":{"types":"./dist/capabilities/Approval.d.mts","default":"./dist/capabilities/Approval.mjs"},"./budget":{"types":"./dist/capabilities/Budget.d.mts","default":"./dist/capabilities/Budget.mjs"},"./code-executor":{"types":"./dist/sandbox/CodeExecutor.d.mts","default":"./dist/sandbox/CodeExecutor.mjs"},"./code-mode":{"types":"./dist/capabilities/CodeMode.d.mts","default":"./dist/capabilities/CodeMode.mjs"},"./commands":{"types":"./dist/capabilities/Commands.d.mts","default":"./dist/capabilities/Commands.mjs"},"./committed-activity":{"types":"./dist/durable/CommittedActivity.d.mts","default":"./dist/durable/CommittedActivity.mjs"},"./compaction":{"types":"./dist/engine/Compaction.d.mts","default":"./dist/engine/Compaction.mjs"},"./context-compactor":{"types":"./dist/engine/ContextCompactor.d.mts","default":"./dist/engine/ContextCompactor.mjs"},"./context-history":{"types":"./dist/engine/ContextHistory.d.mts","default":"./dist/engine/ContextHistory.mjs"},"./context-tools":{"types":"./dist/capabilities/ContextTools.d.mts","default":"./dist/capabilities/ContextTools.mjs"},"./context-window":{"types":"./dist/engine/ContextWindow.d.mts","default":"./dist/engine/ContextWindow.mjs"},"./digest":{"types":"./dist/durable/Digest.d.mts","default":"./dist/durable/Digest.mjs"},"./durable-agent-runtime":{"types":"./dist/durable/DurableAgentRuntime.d.mts","default":"./dist/durable/DurableAgentRuntime.mjs"},"./durable-failpoint":{"types":"./dist/durable/DurableFailpoint.d.mts","default":"./dist/durable/DurableFailpoint.mjs"},"./durable-step":{"types":"./dist/engine/DurableStep.d.mts","default":"./dist/engine/DurableStep.mjs"},"./event-source":{"types":"./dist/durable/EventSource.d.mts","default":"./dist/durable/EventSource.mjs"},"./failure-diagnostic":{"types":"./dist/core/FailureDiagnostic.d.mts","default":"./dist/core/FailureDiagnostic.mjs"},"./git-hub-workflow-source":{"types":"./dist/durable/GitHubWorkflowSource.d.mts","default":"./dist/durable/GitHubWorkflowSource.mjs"},"./id-generator":{"types":"./dist/core/IdGenerator.d.mts","default":"./dist/core/IdGenerator.mjs"},"./identifiers":{"types":"./dist/core/Identifiers.d.mts","default":"./dist/core/Identifiers.mjs"},"./in-memory":{"types":"./dist/InMemory.d.mts","default":"./dist/InMemory.mjs"},"./interactive-browser":{"types":"./dist/sandbox/InteractiveBrowser.d.mts","default":"./dist/sandbox/InteractiveBrowser.mjs"},"./mcp":{"types":"./dist/capabilities/Mcp.d.mts","default":"./dist/capabilities/Mcp.mjs"},"./mcp-client":{"types":"./dist/capabilities/McpClient.d.mts","default":"./dist/capabilities/McpClient.mjs"},"./memory":{"types":"./dist/core/Memory.d.mts","default":"./dist/core/Memory.mjs"},"./memory-namespace":{"types":"./dist/core/MemoryNamespace.d.mts","default":"./dist/core/MemoryNamespace.mjs"},"./memory-notes":{"types":"./dist/capabilities/MemoryNotes.d.mts","default":"./dist/capabilities/MemoryNotes.mjs"},"./memory-reference":{"types":"./dist/core/MemoryReference.d.mts","default":"./dist/core/MemoryReference.mjs"},"./memory-revalidation":{"types":"./dist/core/MemoryRevalidation.d.mts","default":"./dist/core/MemoryRevalidation.mjs"},"./memory-store":{"types":"./dist/core/MemoryStore.d.mts","default":"./dist/core/MemoryStore.mjs"},"./message-delivery":{"types":"./dist/durable/MessageDelivery.d.mts","default":"./dist/durable/MessageDelivery.mjs"},"./messaging":{"types":"./dist/capabilities/Messaging.d.mts","default":"./dist/capabilities/Messaging.mjs"},"./messaging-host":{"types":"./dist/engine/MessagingHost.d.mts","default":"./dist/engine/MessagingHost.mjs"},"./model-context":{"types":"./dist/capabilities/ModelContext.d.mts","default":"./dist/capabilities/ModelContext.mjs"},"./operation-authorizer":{"types":"./dist/durable/OperationAuthorizer.d.mts","default":"./dist/durable/OperationAuthorizer.mjs"},"./output":{"types":"./dist/engine/Output.d.mts","default":"./dist/engine/Output.mjs"},"./page-capture":{"types":"./dist/sandbox/PageCapture.d.mts","default":"./dist/sandbox/PageCapture.mjs"},"./page-crawl":{"types":"./dist/sandbox/PageCrawl.d.mts","default":"./dist/sandbox/PageCrawl.mjs"},"./page-screenshot":{"types":"./dist/sandbox/PageScreenshot.d.mts","default":"./dist/sandbox/PageScreenshot.mjs"},"./persistent-history":{"types":"./dist/durable/PersistentHistory.d.mts","default":"./dist/durable/PersistentHistory.mjs"},"./prepared-input-admission":{"types":"./dist/durable/PreparedInputAdmission.d.mts","default":"./dist/durable/PreparedInputAdmission.mjs"},"./receipt":{"types":"./dist/core/Receipt.d.mts","default":"./dist/core/Receipt.mjs"},"./records":{"types":"./dist/durable/Records.d.mts","default":"./dist/durable/Records.mjs"},"./recovery":{"types":"./dist/durable/Recovery.d.mts","default":"./dist/durable/Recovery.mjs"},"./redaction":{"types":"./dist/capabilities/Redaction.d.mts","default":"./dist/capabilities/Redaction.mjs"},"./remembering":{"types":"./dist/capabilities/Remembering.d.mts","default":"./dist/capabilities/Remembering.mjs"},"./remembering-store":{"types":"./dist/core/RememberingStore.d.mts","default":"./dist/core/RememberingStore.mjs"},"./run-event":{"types":"./dist/core/RunEvent.d.mts","default":"./dist/core/RunEvent.mjs"},"./run-event-sink":{"types":"./dist/engine/RunEventSink.d.mts","default":"./dist/engine/RunEventSink.mjs"},"./run-hooks":{"types":"./dist/capabilities/RunHooks.d.mts","default":"./dist/capabilities/RunHooks.mjs"},"./run-journal":{"types":"./dist/durable/RunJournal.d.mts","default":"./dist/durable/RunJournal.mjs"},"./run-options":{"types":"./dist/engine/RunOptions.d.mts","default":"./dist/engine/RunOptions.mjs"},"./run-policy-usage":{"types":"./dist/core/RunPolicyUsage.d.mts","default":"./dist/core/RunPolicyUsage.mjs"},"./sandbox":{"types":"./dist/sandbox/Sandbox.d.mts","default":"./dist/sandbox/Sandbox.mjs"},"./schedule":{"types":"./dist/durable/Schedule.d.mts","default":"./dist/durable/Schedule.mjs"},"./schedule-transition":{"types":"./dist/durable/ScheduleTransition.d.mts","default":"./dist/durable/ScheduleTransition.mjs"},"./scheduling":{"types":"./dist/durable/Scheduling.d.mts","default":"./dist/durable/Scheduling.mjs"},"./semantic-memory":{"types":"./dist/capabilities/SemanticMemory.d.mts","default":"./dist/capabilities/SemanticMemory.mjs"},"./semantic-memory-index":{"types":"./dist/core/SemanticMemoryIndex.d.mts","default":"./dist/core/SemanticMemoryIndex.mjs"},"./semantic-memory-revalidation":{"types":"./dist/core/SemanticMemoryRevalidation.d.mts","default":"./dist/core/SemanticMemoryRevalidation.mjs"},"./sql-memory-store":{"types":"./dist/durable/SqlMemoryStore.d.mts","default":"./dist/durable/SqlMemoryStore.mjs"},"./subagent":{"types":"./dist/capabilities/Subagent.d.mts","default":"./dist/capabilities/Subagent.mjs"},"./subagent-contract":{"types":"./dist/core/SubagentContract.d.mts","default":"./dist/core/SubagentContract.mjs"},"./subagent-host":{"types":"./dist/engine/SubagentHost.d.mts","default":"./dist/engine/SubagentHost.mjs"},"./subagent-reservations":{"types":"./dist/capabilities/SubagentReservations.d.mts","default":"./dist/capabilities/SubagentReservations.mjs"},"./submission-ledger":{"types":"./dist/durable/SubmissionLedger.d.mts","default":"./dist/durable/SubmissionLedger.mjs"},"./submission-status":{"types":"./dist/durable/SubmissionStatus.d.mts","default":"./dist/durable/SubmissionStatus.mjs"},"./subscription":{"types":"./dist/durable/Subscription.d.mts","default":"./dist/durable/Subscription.mjs"},"./subscription-input":{"types":"./dist/durable/SubscriptionInput.d.mts","default":"./dist/durable/SubscriptionInput.mjs"},"./subscription-tools":{"types":"./dist/durable/SubscriptionTools.d.mts","default":"./dist/durable/SubscriptionTools.mjs"},"./subscription-transition":{"types":"./dist/durable/SubscriptionTransition.d.mts","default":"./dist/durable/SubscriptionTransition.mjs"},"./subscriptions":{"types":"./dist/durable/Subscriptions.d.mts","default":"./dist/durable/Subscriptions.mjs"},"./testing/certification":{"types":"./dist/durable/Certification.d.mts","default":"./dist/durable/Certification.mjs"},"./testing/durable-failpoint-test-control":{"types":"./dist/durable/DurableFailpointTestControl.d.mts","default":"./dist/durable/DurableFailpointTestControl.mjs"},"./testing/message-delivery-store-conformance":{"types":"./dist/durable/MessageDeliveryStoreConformance.d.mts","default":"./dist/durable/MessageDeliveryStoreConformance.mjs"},"./testing/schedule-store-conformance":{"types":"./dist/durable/ScheduleStoreConformance.d.mts","default":"./dist/durable/ScheduleStoreConformance.mjs"},"./testing/submission-ledger-conformance":{"types":"./dist/durable/SubmissionLedgerConformance.d.mts","default":"./dist/durable/SubmissionLedgerConformance.mjs"},"./testing/subscription-store-conformance":{"types":"./dist/durable/SubscriptionStoreConformance.d.mts","default":"./dist/durable/SubscriptionStoreConformance.mjs"},"./testing/thread-store-conformance":{"types":"./dist/durable/ThreadStoreConformance.d.mts","default":"./dist/durable/ThreadStoreConformance.mjs"},"./thread":{"types":"./dist/core/Thread.d.mts","default":"./dist/core/Thread.mjs"},"./thread-context-history":{"types":"./dist/durable/ThreadContextHistory.d.mts","default":"./dist/durable/ThreadContextHistory.mjs"},"./thread-context-history-projection":{"types":"./dist/durable/ThreadContextHistoryProjection.d.mts","default":"./dist/durable/ThreadContextHistoryProjection.mjs"},"./thread-history":{"types":"./dist/engine/ThreadHistory.d.mts","default":"./dist/engine/ThreadHistory.mjs"},"./thread-invariants":{"types":"./dist/durable/ThreadInvariants.d.mts","default":"./dist/durable/ThreadInvariants.mjs"},"./thread-projection":{"types":"./dist/durable/ThreadProjection.d.mts","default":"./dist/durable/ThreadProjection.mjs"},"./thread-projection-maintenance":{"types":"./dist/durable/ThreadProjectionMaintenance.d.mts","default":"./dist/durable/ThreadProjectionMaintenance.mjs"},"./thread-store":{"types":"./dist/durable/ThreadStore.d.mts","default":"./dist/durable/ThreadStore.mjs"},"./tool-broker":{"types":"./dist/engine/ToolBroker.d.mts","default":"./dist/engine/ToolBroker.mjs"},"./tool-discovery":{"types":"./dist/capabilities/ToolDiscovery.d.mts","default":"./dist/capabilities/ToolDiscovery.mjs"},"./tool-exposure":{"types":"./dist/ToolExposure.d.mts","default":"./dist/ToolExposure.mjs"},"./tool-reconciler":{"types":"./dist/durable/ToolReconciler.d.mts","default":"./dist/durable/ToolReconciler.mjs"},"./tool-result":{"types":"./dist/core/ToolResult.d.mts","default":"./dist/core/ToolResult.mjs"},"./usage":{"types":"./dist/core/Usage.d.mts","default":"./dist/core/Usage.mjs"},"./wake-scheduler":{"types":"./dist/durable/WakeScheduler.d.mts","default":"./dist/durable/WakeScheduler.mjs"},"./web-capture":{"types":"./dist/capabilities/WebCapture.d.mts","default":"./dist/capabilities/WebCapture.mjs"},"./web-search":{"types":"./dist/capabilities/WebSearch.d.mts","default":"./dist/capabilities/WebSearch.mjs"},"./worker":{"types":"./dist/core/Worker.d.mts","default":"./dist/core/Worker.mjs"},"./worker-host":{"types":"./dist/durable/WorkerHost.d.mts","default":"./dist/durable/WorkerHost.mjs"},"./lifecycle-publication":{"types":"./dist/durable/LifecyclePublication.d.mts","default":"./dist/durable/LifecyclePublication.mjs"}},"description":"Effect-native agents, execution, subagents, and sandbox contracts in one tree-shakeable package.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/danieljvdm/effect-agent.git","directory":"packages/effect-agent"},"files":["dist","src"],"type":"module","sideEffects":[],"publishConfig":{"access":"public"},"scripts":{"build":"vp pack","check":"tsc --noEmit -p tsconfig.json","test":"vp test --passWithNoTests"}}
1
+ {"name":"effect-agent","version":"0.1.0-beta.148","devDependencies":{"@effect/platform-node":"4.0.0-rc.117","@effect/vitest":"4.0.0-rc.117","effect":"4.0.0-rc.117","typescript":"7.0.2","vite-plus":"0.3.3"},"peerDependencies":{"effect":"^4.0.0-rc.117"},"exports":{".":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"./activity-store":{"types":"./dist/durable/ActivityStore.d.mts","default":"./dist/durable/ActivityStore.mjs"},"./admin":{"types":"./dist/durable/Admin.d.mts","default":"./dist/durable/Admin.mjs"},"./agent":{"types":"./dist/core/Agent.d.mts","default":"./dist/core/Agent.mjs"},"./agent-error":{"types":"./dist/core/AgentError.d.mts","default":"./dist/core/AgentError.mjs"},"./agent-policy":{"types":"./dist/core/AgentPolicy.d.mts","default":"./dist/core/AgentPolicy.mjs"},"./agent-registration":{"types":"./dist/durable/AgentRegistration.d.mts","default":"./dist/durable/AgentRegistration.mjs"},"./agent-runtime":{"types":"./dist/engine/AgentRuntime.d.mts","default":"./dist/engine/AgentRuntime.mjs"},"./agent-updates":{"types":"./dist/core/AgentUpdates.d.mts","default":"./dist/core/AgentUpdates.mjs"},"./approval":{"types":"./dist/capabilities/Approval.d.mts","default":"./dist/capabilities/Approval.mjs"},"./budget":{"types":"./dist/capabilities/Budget.d.mts","default":"./dist/capabilities/Budget.mjs"},"./code-executor":{"types":"./dist/sandbox/CodeExecutor.d.mts","default":"./dist/sandbox/CodeExecutor.mjs"},"./code-mode":{"types":"./dist/capabilities/CodeMode.d.mts","default":"./dist/capabilities/CodeMode.mjs"},"./commands":{"types":"./dist/capabilities/Commands.d.mts","default":"./dist/capabilities/Commands.mjs"},"./committed-activity":{"types":"./dist/durable/CommittedActivity.d.mts","default":"./dist/durable/CommittedActivity.mjs"},"./compaction":{"types":"./dist/engine/Compaction.d.mts","default":"./dist/engine/Compaction.mjs"},"./context-compactor":{"types":"./dist/engine/ContextCompactor.d.mts","default":"./dist/engine/ContextCompactor.mjs"},"./context-history":{"types":"./dist/engine/ContextHistory.d.mts","default":"./dist/engine/ContextHistory.mjs"},"./context-tools":{"types":"./dist/capabilities/ContextTools.d.mts","default":"./dist/capabilities/ContextTools.mjs"},"./context-window":{"types":"./dist/engine/ContextWindow.d.mts","default":"./dist/engine/ContextWindow.mjs"},"./digest":{"types":"./dist/durable/Digest.d.mts","default":"./dist/durable/Digest.mjs"},"./durable-agent-runtime":{"types":"./dist/durable/DurableAgentRuntime.d.mts","default":"./dist/durable/DurableAgentRuntime.mjs"},"./durable-failpoint":{"types":"./dist/durable/DurableFailpoint.d.mts","default":"./dist/durable/DurableFailpoint.mjs"},"./durable-step":{"types":"./dist/engine/DurableStep.d.mts","default":"./dist/engine/DurableStep.mjs"},"./event-source":{"types":"./dist/durable/EventSource.d.mts","default":"./dist/durable/EventSource.mjs"},"./failure-diagnostic":{"types":"./dist/core/FailureDiagnostic.d.mts","default":"./dist/core/FailureDiagnostic.mjs"},"./git-hub-workflow-source":{"types":"./dist/durable/GitHubWorkflowSource.d.mts","default":"./dist/durable/GitHubWorkflowSource.mjs"},"./id-generator":{"types":"./dist/core/IdGenerator.d.mts","default":"./dist/core/IdGenerator.mjs"},"./identifiers":{"types":"./dist/core/Identifiers.d.mts","default":"./dist/core/Identifiers.mjs"},"./in-memory":{"types":"./dist/InMemory.d.mts","default":"./dist/InMemory.mjs"},"./interactive-browser":{"types":"./dist/sandbox/InteractiveBrowser.d.mts","default":"./dist/sandbox/InteractiveBrowser.mjs"},"./mcp":{"types":"./dist/capabilities/Mcp.d.mts","default":"./dist/capabilities/Mcp.mjs"},"./mcp-client":{"types":"./dist/capabilities/McpClient.d.mts","default":"./dist/capabilities/McpClient.mjs"},"./memory":{"types":"./dist/core/Memory.d.mts","default":"./dist/core/Memory.mjs"},"./memory-namespace":{"types":"./dist/core/MemoryNamespace.d.mts","default":"./dist/core/MemoryNamespace.mjs"},"./memory-notes":{"types":"./dist/capabilities/MemoryNotes.d.mts","default":"./dist/capabilities/MemoryNotes.mjs"},"./memory-reference":{"types":"./dist/core/MemoryReference.d.mts","default":"./dist/core/MemoryReference.mjs"},"./memory-revalidation":{"types":"./dist/core/MemoryRevalidation.d.mts","default":"./dist/core/MemoryRevalidation.mjs"},"./memory-store":{"types":"./dist/core/MemoryStore.d.mts","default":"./dist/core/MemoryStore.mjs"},"./message-delivery":{"types":"./dist/durable/MessageDelivery.d.mts","default":"./dist/durable/MessageDelivery.mjs"},"./messaging":{"types":"./dist/capabilities/Messaging.d.mts","default":"./dist/capabilities/Messaging.mjs"},"./messaging-host":{"types":"./dist/engine/MessagingHost.d.mts","default":"./dist/engine/MessagingHost.mjs"},"./model-context":{"types":"./dist/capabilities/ModelContext.d.mts","default":"./dist/capabilities/ModelContext.mjs"},"./operation-authorizer":{"types":"./dist/durable/OperationAuthorizer.d.mts","default":"./dist/durable/OperationAuthorizer.mjs"},"./output":{"types":"./dist/engine/Output.d.mts","default":"./dist/engine/Output.mjs"},"./page-capture":{"types":"./dist/sandbox/PageCapture.d.mts","default":"./dist/sandbox/PageCapture.mjs"},"./page-crawl":{"types":"./dist/sandbox/PageCrawl.d.mts","default":"./dist/sandbox/PageCrawl.mjs"},"./page-screenshot":{"types":"./dist/sandbox/PageScreenshot.d.mts","default":"./dist/sandbox/PageScreenshot.mjs"},"./persistent-history":{"types":"./dist/durable/PersistentHistory.d.mts","default":"./dist/durable/PersistentHistory.mjs"},"./prepared-input-admission":{"types":"./dist/durable/PreparedInputAdmission.d.mts","default":"./dist/durable/PreparedInputAdmission.mjs"},"./receipt":{"types":"./dist/core/Receipt.d.mts","default":"./dist/core/Receipt.mjs"},"./records":{"types":"./dist/durable/Records.d.mts","default":"./dist/durable/Records.mjs"},"./recovery":{"types":"./dist/durable/Recovery.d.mts","default":"./dist/durable/Recovery.mjs"},"./redaction":{"types":"./dist/capabilities/Redaction.d.mts","default":"./dist/capabilities/Redaction.mjs"},"./remembering":{"types":"./dist/capabilities/Remembering.d.mts","default":"./dist/capabilities/Remembering.mjs"},"./remembering-store":{"types":"./dist/core/RememberingStore.d.mts","default":"./dist/core/RememberingStore.mjs"},"./run-event":{"types":"./dist/core/RunEvent.d.mts","default":"./dist/core/RunEvent.mjs"},"./run-event-sink":{"types":"./dist/engine/RunEventSink.d.mts","default":"./dist/engine/RunEventSink.mjs"},"./run-hooks":{"types":"./dist/capabilities/RunHooks.d.mts","default":"./dist/capabilities/RunHooks.mjs"},"./run-journal":{"types":"./dist/durable/RunJournal.d.mts","default":"./dist/durable/RunJournal.mjs"},"./run-options":{"types":"./dist/engine/RunOptions.d.mts","default":"./dist/engine/RunOptions.mjs"},"./run-policy-usage":{"types":"./dist/core/RunPolicyUsage.d.mts","default":"./dist/core/RunPolicyUsage.mjs"},"./sandbox":{"types":"./dist/sandbox/Sandbox.d.mts","default":"./dist/sandbox/Sandbox.mjs"},"./schedule":{"types":"./dist/durable/Schedule.d.mts","default":"./dist/durable/Schedule.mjs"},"./schedule-transition":{"types":"./dist/durable/ScheduleTransition.d.mts","default":"./dist/durable/ScheduleTransition.mjs"},"./scheduling":{"types":"./dist/durable/Scheduling.d.mts","default":"./dist/durable/Scheduling.mjs"},"./semantic-memory":{"types":"./dist/capabilities/SemanticMemory.d.mts","default":"./dist/capabilities/SemanticMemory.mjs"},"./semantic-memory-index":{"types":"./dist/core/SemanticMemoryIndex.d.mts","default":"./dist/core/SemanticMemoryIndex.mjs"},"./semantic-memory-revalidation":{"types":"./dist/core/SemanticMemoryRevalidation.d.mts","default":"./dist/core/SemanticMemoryRevalidation.mjs"},"./sql-memory-store":{"types":"./dist/durable/SqlMemoryStore.d.mts","default":"./dist/durable/SqlMemoryStore.mjs"},"./subagent":{"types":"./dist/capabilities/Subagent.d.mts","default":"./dist/capabilities/Subagent.mjs"},"./subagent-contract":{"types":"./dist/core/SubagentContract.d.mts","default":"./dist/core/SubagentContract.mjs"},"./subagent-host":{"types":"./dist/engine/SubagentHost.d.mts","default":"./dist/engine/SubagentHost.mjs"},"./subagent-reservations":{"types":"./dist/capabilities/SubagentReservations.d.mts","default":"./dist/capabilities/SubagentReservations.mjs"},"./submission-ledger":{"types":"./dist/durable/SubmissionLedger.d.mts","default":"./dist/durable/SubmissionLedger.mjs"},"./submission-status":{"types":"./dist/durable/SubmissionStatus.d.mts","default":"./dist/durable/SubmissionStatus.mjs"},"./subscription":{"types":"./dist/durable/Subscription.d.mts","default":"./dist/durable/Subscription.mjs"},"./subscription-input":{"types":"./dist/durable/SubscriptionInput.d.mts","default":"./dist/durable/SubscriptionInput.mjs"},"./subscription-tools":{"types":"./dist/durable/SubscriptionTools.d.mts","default":"./dist/durable/SubscriptionTools.mjs"},"./subscription-transition":{"types":"./dist/durable/SubscriptionTransition.d.mts","default":"./dist/durable/SubscriptionTransition.mjs"},"./subscriptions":{"types":"./dist/durable/Subscriptions.d.mts","default":"./dist/durable/Subscriptions.mjs"},"./testing/certification":{"types":"./dist/durable/Certification.d.mts","default":"./dist/durable/Certification.mjs"},"./testing/durable-failpoint-test-control":{"types":"./dist/durable/DurableFailpointTestControl.d.mts","default":"./dist/durable/DurableFailpointTestControl.mjs"},"./testing/message-delivery-store-conformance":{"types":"./dist/durable/MessageDeliveryStoreConformance.d.mts","default":"./dist/durable/MessageDeliveryStoreConformance.mjs"},"./testing/schedule-store-conformance":{"types":"./dist/durable/ScheduleStoreConformance.d.mts","default":"./dist/durable/ScheduleStoreConformance.mjs"},"./testing/submission-ledger-conformance":{"types":"./dist/durable/SubmissionLedgerConformance.d.mts","default":"./dist/durable/SubmissionLedgerConformance.mjs"},"./testing/subscription-store-conformance":{"types":"./dist/durable/SubscriptionStoreConformance.d.mts","default":"./dist/durable/SubscriptionStoreConformance.mjs"},"./testing/thread-store-conformance":{"types":"./dist/durable/ThreadStoreConformance.d.mts","default":"./dist/durable/ThreadStoreConformance.mjs"},"./thread":{"types":"./dist/core/Thread.d.mts","default":"./dist/core/Thread.mjs"},"./thread-context-history":{"types":"./dist/durable/ThreadContextHistory.d.mts","default":"./dist/durable/ThreadContextHistory.mjs"},"./thread-context-history-projection":{"types":"./dist/durable/ThreadContextHistoryProjection.d.mts","default":"./dist/durable/ThreadContextHistoryProjection.mjs"},"./thread-history":{"types":"./dist/engine/ThreadHistory.d.mts","default":"./dist/engine/ThreadHistory.mjs"},"./thread-invariants":{"types":"./dist/durable/ThreadInvariants.d.mts","default":"./dist/durable/ThreadInvariants.mjs"},"./thread-projection":{"types":"./dist/durable/ThreadProjection.d.mts","default":"./dist/durable/ThreadProjection.mjs"},"./thread-projection-maintenance":{"types":"./dist/durable/ThreadProjectionMaintenance.d.mts","default":"./dist/durable/ThreadProjectionMaintenance.mjs"},"./thread-store":{"types":"./dist/durable/ThreadStore.d.mts","default":"./dist/durable/ThreadStore.mjs"},"./tool-broker":{"types":"./dist/engine/ToolBroker.d.mts","default":"./dist/engine/ToolBroker.mjs"},"./tool-discovery":{"types":"./dist/capabilities/ToolDiscovery.d.mts","default":"./dist/capabilities/ToolDiscovery.mjs"},"./tool-exposure":{"types":"./dist/ToolExposure.d.mts","default":"./dist/ToolExposure.mjs"},"./tool-reconciler":{"types":"./dist/durable/ToolReconciler.d.mts","default":"./dist/durable/ToolReconciler.mjs"},"./tool-result":{"types":"./dist/core/ToolResult.d.mts","default":"./dist/core/ToolResult.mjs"},"./usage":{"types":"./dist/core/Usage.d.mts","default":"./dist/core/Usage.mjs"},"./wake-scheduler":{"types":"./dist/durable/WakeScheduler.d.mts","default":"./dist/durable/WakeScheduler.mjs"},"./web-capture":{"types":"./dist/capabilities/WebCapture.d.mts","default":"./dist/capabilities/WebCapture.mjs"},"./web-search":{"types":"./dist/capabilities/WebSearch.d.mts","default":"./dist/capabilities/WebSearch.mjs"},"./worker":{"types":"./dist/core/Worker.d.mts","default":"./dist/core/Worker.mjs"},"./worker-host":{"types":"./dist/durable/WorkerHost.d.mts","default":"./dist/durable/WorkerHost.mjs"},"./lifecycle-publication":{"types":"./dist/durable/LifecyclePublication.d.mts","default":"./dist/durable/LifecyclePublication.mjs"}},"description":"Effect-native agents, execution, subagents, and sandbox contracts in one tree-shakeable package.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/danieljvdm/effect-agent.git","directory":"packages/effect-agent"},"files":["dist","src"],"type":"module","sideEffects":[],"publishConfig":{"access":"public"},"scripts":{"build":"vp pack","check":"tsc --noEmit -p tsconfig.json","test":"vp test --passWithNoTests"}}
package/src/core/Agent.ts CHANGED
@@ -152,8 +152,12 @@ export interface Definition<
152
152
  /** Canonical schema used to decode the final model output. */
153
153
  readonly output: OutputSchema;
154
154
  /**
155
- * Evaluated once while preparing each Run. Outgoing system messages form a leading block;
156
- * exact repeats (including provider options) keep their last occurrence. Stored history is unchanged.
155
+ * Evaluated once while preparing each Run. OpenAI, xAI and native adapters advertising support
156
+ * preserve chronological system messages, omitting exact repeats only when no distinct system
157
+ * instruction intervenes. The actual selected model determines support on each call. Other
158
+ * adapters group systems first and keep the last exact repeat, including provider options;
159
+ * Anthropic requires an upstream adapter with mid-conversation system-message support.
160
+ * Stored history is unchanged.
157
161
  */
158
162
  readonly instructions: Instructions;
159
163
  /** Optional projection from decoded input to model-visible native Effect AI prompt content. */
@@ -1266,20 +1266,6 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
1266
1266
  const submissionScheduling = yield* SubmissionScheduling;
1267
1267
  const store = yield* ThreadStore;
1268
1268
 
1269
- const publicationPending = (threadId: ThreadId) =>
1270
- store.lifecyclePublications === undefined
1271
- ? Effect.succeed(false)
1272
- : store.lifecyclePublications.pendingDeadlineFor(threadId).pipe(
1273
- Effect.map(Option.isSome),
1274
- Effect.mapError((cause) =>
1275
- ThreadStoreError.make({
1276
- operation: "read lifecycle publication gate",
1277
- message: "Native lifecycle publication state is unavailable",
1278
- cause,
1279
- }),
1280
- ),
1281
- );
1282
-
1283
1269
  const wake = yield* WakeScheduler;
1284
1270
  const failpoint = yield* DurableRuntimeFailpoint;
1285
1271
  const config = yield* DurableRuntimeConfig;
@@ -4625,7 +4611,6 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
4625
4611
  Effect.gen(function* () {
4626
4612
  const submissionId = submission.submissionId;
4627
4613
 
4628
- if (yield* publicationPending(submission.threadId)) return { _tag: "yielded" as const };
4629
4614
  const runId = runIdForSubmission(submissionId);
4630
4615
  const boundaries: Array<JournalBoundary> = [];
4631
4616
 
@@ -6251,17 +6236,16 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
6251
6236
  return yield* renderInputPrompt(inputPrompt, decodedInput, encodedInput);
6252
6237
  });
6253
6238
 
6254
- const yieldForPublication = Effect.gen(function* () {
6255
- const pending = yield* Effect.exit(publicationPending(submission.threadId));
6256
-
6257
- if (Exit.isSuccess(pending) && !pending.value) return;
6258
- // A completed plain-text response may not yet have reached beforeTurn. Retain it
6259
- // before either a publication wait or its failed state read closes the Attempt.
6260
- yield* recordHalt(commitPendingTurn);
6261
- if (Exit.isFailure(pending)) return yield* recordHalt(Effect.failCause(pending.cause));
6262
- yield* Deferred.succeed(yieldSignal, undefined);
6239
+ // Empty successful drains leave Tool results and RunCompleted in one batch.
6240
+ // A join or interrupted continuation must still retain already returned results.
6241
+ const preserveToolResults = Effect.gen(function* () {
6242
+ const state = yield* Ref.get(stateRef);
6263
6243
 
6264
- return yield* Effect.never;
6244
+ if (
6245
+ state.pendingTurn !== undefined &&
6246
+ knownIds.has(modelResponseRecordId(runId, state.pendingTurn.turn))
6247
+ )
6248
+ yield* commitPendingTurn;
6265
6249
  });
6266
6250
 
6267
6251
  const input: RunInputHook<
@@ -6270,26 +6254,15 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
6270
6254
  > = {
6271
6255
  drain: (policy) =>
6272
6256
  Effect.gen(function* () {
6273
- const state = yield* Ref.get(stateRef);
6274
-
6275
- // A completed Tool batch has returned its outcomes before this steering seam.
6276
- // Persist them before a host ledger read can halt the Attempt and make those
6277
- // ordinary calls appear unknown. A no-tool response still belongs to its later
6278
- // continuation or atomic RunCompleted commit.
6279
- if (
6280
- state.pendingTurn !== undefined &&
6281
- knownIds.has(modelResponseRecordId(runId, state.pendingTurn.turn))
6282
- )
6283
- yield* recordHalt(commitPendingTurn);
6284
-
6285
- yield* yieldForPublication;
6286
-
6287
6257
  const joinedInputs = yield* recordHalt(
6288
6258
  Effect.gen(function* () {
6289
6259
  const limit = policy === "one" ? 1 : MAX_JOIN_DRAIN;
6290
6260
 
6291
- const joinedInputs: Array<Pick<UserInputRecorded, "input" | "messageAdmission">> =
6292
- [];
6261
+ const joinedInputs: Array<
6262
+ Pick<UserInputRecorded, "input" | "messageAdmission"> & {
6263
+ readonly rendered?: Prompt.RawInput;
6264
+ }
6265
+ > = [];
6293
6266
 
6294
6267
  if (joinBacklog === undefined) {
6295
6268
  const hostSnapshot = yield* ledger.loadRecoverySnapshot(
@@ -6331,6 +6304,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
6331
6304
  const payload = existing.record.payload;
6332
6305
 
6333
6306
  if (payload._tag !== "UserInputRecorded") continue;
6307
+ yield* preserveToolResults;
6334
6308
  joinedInputs.push(payload);
6335
6309
  }
6336
6310
  if (joinedInputs.length < limit) {
@@ -6362,6 +6336,28 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
6362
6336
  );
6363
6337
  continue;
6364
6338
  }
6339
+
6340
+ const payload = {
6341
+ input: claim.inputPayload,
6342
+ ...(claimSnapshot.submission.messageAdmission === undefined
6343
+ ? {}
6344
+ : { messageAdmission: claimSnapshot.submission.messageAdmission }),
6345
+ };
6346
+
6347
+ const rendered = yield* Effect.result(renderJoinedInput(payload));
6348
+
6349
+ if (Result.isFailure(rendered)) {
6350
+ // The rejecting input gets its own Run and normal typed failure.
6351
+ // Leave it and the unconsumed suffix ready, preserving queue order
6352
+ // and preventing one invalid prompt from failing unrelated receipts.
6353
+ for (const remaining of claims.slice(claims.indexOf(claim))) {
6354
+ yield* ledger.revertJoining(
6355
+ RevertJoiningRequest.make({ submissionId: remaining.submissionId }),
6356
+ );
6357
+ }
6358
+ break;
6359
+ }
6360
+ yield* preserveToolResults;
6365
6361
  const recordId = submissionInputRecordId(claim.submissionId);
6366
6362
  let sequence: CanonicalSequence;
6367
6363
  const existing = joinedInputEnvelopes.get(claim.submissionId);
@@ -6410,24 +6406,23 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
6410
6406
  );
6411
6407
  deliveredJoinInputs.add(claim.submissionId);
6412
6408
  joinedInputs.push({
6413
- input: claim.inputPayload,
6414
- ...(claimSnapshot.submission.messageAdmission === undefined
6415
- ? {}
6416
- : { messageAdmission: claimSnapshot.submission.messageAdmission }),
6409
+ ...payload,
6410
+ rendered: rendered.success,
6417
6411
  });
6418
6412
  }
6419
6413
  }
6420
6414
 
6421
6415
  return joinedInputs;
6422
- }),
6416
+ }).pipe(
6417
+ Effect.onExit((exit) => (Exit.isFailure(exit) ? preserveToolResults : Effect.void)),
6418
+ ),
6423
6419
  );
6424
6420
 
6425
- // Appending a canonical joined input may retain a new publication. Its native
6426
- // receipt remains successful; recovery reattaches it after acknowledgement.
6427
- yield* yieldForPublication;
6428
-
6429
6421
  return yield* Effect.forEach(joinedInputs, (joinedInput) =>
6430
- renderJoinedInput(joinedInput).pipe(
6422
+ (joinedInput.rendered === undefined
6423
+ ? renderJoinedInput(joinedInput)
6424
+ : Effect.succeed(joinedInput.rendered)
6425
+ ).pipe(
6431
6426
  Effect.map((input): RunInputCommand => ({
6432
6427
  kind: "steering",
6433
6428
  input,
@@ -7047,8 +7042,8 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
7047
7042
  history: pending === undefined ? journal.historyBefore : resumeProjection.historyBefore,
7048
7043
  onHistory,
7049
7044
  input,
7050
- // Worker corrections drain together at safe seams, bounded by MAX_JOIN_DRAIN.
7051
- commandDrainPolicy: submission.workerAdmission === undefined ? "one" : "all",
7045
+ // Ready corrections share the next model Turn, bounded by MAX_JOIN_DRAIN.
7046
+ commandDrainPolicy: "all",
7052
7047
  ...(journal.committedTurns > 0 || Schema.is(FrameworkMessage)(submission.messageAdmission)
7053
7048
  ? { retainedInput: submission.inputPayload }
7054
7049
  : {}),
@@ -7108,7 +7103,6 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
7108
7103
  // Preparation may resolve the next Model from canonical Tool results or invoke
7109
7104
  // a compaction Model. Publish the completed Turn before either can observe it.
7110
7105
  yield* recordHalt(commitPendingTurn);
7111
- yield* yieldForPublication;
7112
7106
 
7113
7107
  if (
7114
7108
  yieldAfter !== undefined &&
@@ -7642,6 +7636,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
7642
7636
  }),
7643
7637
  ),
7644
7638
  ).pipe(
7639
+ Effect.onExit((exit) => (Exit.hasInterrupts(exit) ? preserveToolResults : Effect.void)),
7645
7640
  // Retain while the Attempt's services, claim renewal and abort watcher are still live.
7646
7641
  // A failed retention halts the coordinator; it is not a failed Tool or a safe suspension.
7647
7642
  Effect.tapCause((cause) =>
@@ -7692,9 +7687,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
7692
7687
  const execution = Effect.raceFirst(consume, Effect.raceFirst(abortWatcher, renewal));
7693
7688
 
7694
7689
  const raced = (
7695
- yieldAfter === undefined &&
7696
- submissionScheduling.yieldTo === undefined &&
7697
- store.lifecyclePublications === undefined
7690
+ yieldAfter === undefined && submissionScheduling.yieldTo === undefined
7698
7691
  ? execution
7699
7692
  : Effect.raceFirst(
7700
7693
  execution,
@@ -8572,7 +8565,6 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
8572
8565
 
8573
8566
  const attempt = Effect.scoped(
8574
8567
  Effect.gen(function* () {
8575
- if (yield* publicationPending(threadId)) return Option.none();
8576
8568
  const claimed = yield* acquireClaim(threadId, handoff);
8577
8569
 
8578
8570
  if (Option.isNone(claimed)) return Option.none();
@@ -1,4 +1,4 @@
1
- import { Clock, Context, Crypto, Effect, Layer, Option, Schema, type Scope } from "effect";
1
+ import { Cause, Clock, Context, Crypto, Effect, Layer, Option, Schema, type Scope } from "effect";
2
2
 
3
3
  import { SubmissionId, ThreadId } from "../core/Identifiers.ts";
4
4
  import { Receipt } from "../core/Receipt.ts";
@@ -122,37 +122,70 @@ export class LifecyclePublicationError extends Schema.TaggedError<LifecyclePubli
122
122
  },
123
123
  ) {}
124
124
 
125
- /** Native recovery state, not a second application record or launch queue. */
125
+ /** Bound both retained facts and the immutable admission evidence resolved before dispatch. */
126
+ export const lifecyclePublicationBatchMaxFacts = 8;
127
+
128
+ /** One owner's bounded pending prefix, strictly ordered by its durable ordinals. */
129
+ export const LifecyclePublicationBatch = Schema.NonEmptyArray(LifecyclePublication).check(
130
+ Schema.isMaxLength(lifecyclePublicationBatchMaxFacts),
131
+ Schema.makeFilter(
132
+ (facts) =>
133
+ facts.every((fact, index) => {
134
+ const previous = facts[index - 1];
135
+
136
+ return (
137
+ fact.ownerThreadId === facts[0].ownerThreadId &&
138
+ (previous === undefined || fact.ordinal > previous.ordinal)
139
+ );
140
+ }),
141
+ { expected: "One owner with strictly increasing publication ordinals" },
142
+ ),
143
+ );
144
+
145
+ export type LifecyclePublicationBatch = typeof LifecyclePublicationBatch.Type;
146
+
147
+ /** Native recovery state, independent of Attempts. Hosts serialize drains per storage owner. */
126
148
  export interface LifecyclePublicationStorage {
149
+ /** Select up to `limit` due owners, with a bounded pending prefix for each selected owner. */
127
150
  readonly pending: (
128
151
  nowMillis: number,
129
152
  limit: number,
130
- ) => Effect.Effect<ReadonlyArray<LifecyclePublication>, LifecyclePublicationError>;
153
+ ) => Effect.Effect<ReadonlyArray<LifecyclePublicationBatch>, LifecyclePublicationError>;
154
+ /** Atomically acknowledge the exact batch, retaining its identities and fingerprints. */
131
155
  readonly acknowledge: (
132
- publication: LifecyclePublication,
133
- ) => Effect.Effect<void, LifecyclePublicationError>;
134
- readonly defer: (
135
- publication: LifecyclePublication,
136
- untilMillis: number,
156
+ publications: LifecyclePublicationBatch,
137
157
  ) => Effect.Effect<void, LifecyclePublicationError>;
158
+ /**
159
+ * Claim a due owner batch and persist its retry before dispatch. Eight automatic attempts;
160
+ * 1s exponential backoff capped at 60s, after the dispatch timeout. The final attempt parks
161
+ * the payload before dispatch so process loss cannot renew its budget. False means not due.
162
+ */
163
+ readonly claim: (
164
+ publications: LifecyclePublicationBatch,
165
+ nowMillis: number,
166
+ timeoutMillis: number,
167
+ ) => Effect.Effect<boolean, LifecyclePublicationError>;
138
168
  readonly pendingDeadline: Effect.Effect<Option.Option<number>, LifecyclePublicationError>;
139
- /** Earliest retained owner obligation, including deferred facts that still gate execution. */
140
- readonly pendingDeadlineFor: (
169
+ /** Explicit operator retry after repairing a parked owner's destination. */
170
+ readonly retryParked: (
141
171
  ownerThreadId: ThreadId,
142
- ) => Effect.Effect<Option.Option<number>, LifecyclePublicationError>;
172
+ nowMillis: number,
173
+ ) => Effect.Effect<void, LifecyclePublicationError>;
143
174
  }
144
175
 
145
176
  /**
146
- * Publish an idempotent domain command, including its authorization, exact receipt and delivery
147
- * intent. Return only after that command commits. Treat private input/update/result fields as
148
- * private; the application must select its declared public fields. Revocation/deletion is an
149
- * acknowledged domain decision, not an indefinitely retryable infrastructure failure.
177
+ * Publish one owner's ordered batch in one idempotent host transaction, including authorization,
178
+ * records, receipts and delivery intents. Larger backlogs continue in later batches.
179
+ * Return only after the entire batch commits. Retries
180
+ * may include already committed identities plus later facts; deduplicate each fact's `id`.
181
+ * Private input/update/result fields remain private; select declared public fields explicitly.
182
+ * Revocation/deletion is an acknowledged domain decision, not an infrastructure retry.
150
183
  */
151
184
  export class LifecyclePublicationHandler extends Context.Service<
152
185
  LifecyclePublicationHandler,
153
186
  {
154
187
  readonly publish: (
155
- publication: LifecyclePublication,
188
+ publications: LifecyclePublicationBatch,
156
189
  ) => Effect.Effect<void, LifecyclePublicationError, Scope.Scope>;
157
190
  }
158
191
  >()("@effect-agent/thread/LifecyclePublicationHandler") {}
@@ -218,7 +251,8 @@ const withSource = Effect.fn("LifecyclePublication.withSource")(
218
251
 
219
252
  /**
220
253
  * One finite wave for the host's existing maintenance coordinator. Persist the next deadline
221
- * before dispatch, so interruption and process loss retain the same fact without another timer.
254
+ * before dispatch, so interruption and process loss retain the same facts without another timer.
255
+ * Finish independent owner batches before surfacing failures; interruption stops the wave.
222
256
  * Acknowledgements are exact and idempotent. No producer or external Tool is re-executed here.
223
257
  */
224
258
  export const drainLifecyclePublications = Effect.fn("LifecyclePublication.drain")(function* (
@@ -229,16 +263,36 @@ export const drainLifecyclePublications = Effect.fn("LifecyclePublication.drain"
229
263
  const handler = yield* LifecyclePublicationHandler;
230
264
  const pending = yield* storage.pending(yield* Clock.currentTimeMillis, limit);
231
265
 
232
- for (const publication of pending) {
233
- yield* storage.defer(publication, (yield* Clock.currentTimeMillis) + timeoutMillis);
234
- yield* Effect.scoped(withSource(publication).pipe(Effect.flatMap(handler.publish))).pipe(
235
- Effect.timeoutOrElse({
236
- duration: timeoutMillis,
237
- orElse: () => LifecyclePublicationError.make({ reason: "unavailable" }),
238
- }),
266
+ let failures: Cause.Cause<LifecyclePublicationError> = Cause.empty;
267
+
268
+ for (const batch of pending) {
269
+ yield* Effect.gen(function* () {
270
+ if (!(yield* storage.claim(batch, yield* Clock.currentTimeMillis, timeoutMillis))) return;
271
+ yield* Effect.scoped(
272
+ Effect.gen(function* () {
273
+ const publications = yield* Effect.forEach(batch, withSource);
274
+
275
+ yield* handler.publish(publications);
276
+ }),
277
+ ).pipe(
278
+ Effect.timeoutOrElse({
279
+ duration: timeoutMillis,
280
+ orElse: () => LifecyclePublicationError.make({ reason: "unavailable" }),
281
+ }),
282
+ );
283
+ yield* storage.acknowledge(batch);
284
+ }).pipe(
285
+ Effect.catchCauseIf(
286
+ (cause) => !Cause.hasInterrupts(cause),
287
+ (cause) => {
288
+ failures = Cause.combine(failures, cause);
289
+
290
+ return Effect.void;
291
+ },
292
+ ),
239
293
  );
240
- yield* storage.acknowledge(publication);
241
294
  }
295
+ if (failures.reasons.length > 0) return yield* Effect.failCause(failures);
242
296
 
243
297
  return pending.length;
244
298
  });
@@ -2,10 +2,11 @@ import { Context, Effect, Option, Schema } from "effect";
2
2
 
3
3
  import type * as Agent from "../core/Agent.ts";
4
4
  import type { AgentPolicy } from "../core/AgentPolicy.ts";
5
- import type { SubmissionId, ThreadId } from "../core/Identifiers.ts";
5
+ import type { AgentId, SubmissionId, ThreadId } from "../core/Identifiers.ts";
6
6
  import type { SubagentBudgetReservation } from "../core/SubagentContract.ts";
7
7
  import { WorkerError, type WorkerRef, type WorkerSource } from "../core/Worker.ts";
8
8
  import type {
9
+ CanonicalSequence,
9
10
  DefinitionDigests,
10
11
  Digest,
11
12
  PersistedJson,
@@ -14,6 +15,24 @@ import type {
14
15
  } from "./Records.ts";
15
16
  import type { Principal, SubmissionSnapshot } from "./SubmissionLedger.ts";
16
17
 
18
+ /**
19
+ * One successful start authorization at an exact source tail. This host-created hint is
20
+ * available only during that start's preparation and synchronous admission; it is never
21
+ * persisted or transported. Hooks may reuse their admission decision, but must retain
22
+ * current access checks at commit boundaries. A retry or changed tail gets no old grant.
23
+ */
24
+ export interface WorkerStartAdmission {
25
+ readonly sourceThreadId: ThreadId;
26
+ readonly sourceSubmissionId?: SubmissionId;
27
+ readonly requestedPrincipal: Principal;
28
+ readonly principal: Principal;
29
+ readonly targetAgentId: AgentId;
30
+ readonly continuationOf?: WorkerContinuation;
31
+ readonly access: "send";
32
+ readonly tailSequence: CanonicalSequence;
33
+ readonly tailDigest: Digest;
34
+ }
35
+
17
36
  /** Host-verified source input; absence never means the latest input in the Thread. */
18
37
  export interface WorkerPolicySource {
19
38
  readonly threadId: ThreadId;
@@ -30,6 +49,7 @@ export type WorkerPolicyTarget = {
30
49
  } & (
31
50
  | {
32
51
  readonly _tag: "InitialInput";
52
+ readonly admission?: WorkerStartAdmission;
33
53
  readonly continuationOf?: WorkerContinuation;
34
54
  readonly sourceSubmission?: SubmissionSnapshot;
35
55
  readonly input: PersistedJson;
@@ -136,6 +156,7 @@ export const WorkerHostConfig = Context.Reference<WorkerHostLimits>(
136
156
  * identifiers alone never confer any of them.
137
157
  */
138
158
  export interface WorkerHostAuthorizationRequest {
159
+ readonly admission?: WorkerStartAdmission;
139
160
  readonly sourceThreadId: ThreadId;
140
161
  /** An explicitly selected owner input; authorize this locator as well as the Thread. */
141
162
  readonly sourceSubmissionId?: SubmissionId;
@@ -170,6 +191,7 @@ export const WorkerHostAuthorizer = Context.Reference<{
170
191
  export const WorkerBudgetAuthorizer = Context.Reference<{
171
192
  readonly authorize: (request: {
172
193
  readonly source: WorkerSource;
194
+ readonly admission?: WorkerStartAdmission;
173
195
  readonly principal: Principal;
174
196
  readonly worker: WorkerRef;
175
197
  readonly continuationOf?: WorkerContinuation;