@xandreed/core 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +5 -0
  3. package/dist/domain/agent-failure.entity.d.ts +12 -0
  4. package/dist/domain/agent-failure.entity.functions.d.ts +5 -0
  5. package/dist/domain/agent-failure.entity.functions.js +8 -0
  6. package/dist/domain/agent-failure.entity.js +8 -0
  7. package/dist/domain/failure.entity.d.ts +12 -0
  8. package/dist/domain/failure.entity.functions.d.ts +3 -0
  9. package/dist/domain/failure.entity.functions.js +1 -0
  10. package/dist/domain/failure.entity.js +5 -0
  11. package/dist/domain/loop-event.entity.d.ts +94 -0
  12. package/dist/domain/loop-event.entity.js +0 -0
  13. package/dist/domain/message.entity.d.ts +227 -0
  14. package/dist/domain/message.entity.js +51 -0
  15. package/dist/domain/model-call-policy.entity.d.ts +12 -0
  16. package/dist/domain/model-call-policy.entity.js +5 -0
  17. package/dist/domain/model-catalog.entity.d.ts +10 -0
  18. package/dist/domain/model-catalog.entity.js +7 -0
  19. package/dist/domain/model-selection.entity.d.ts +24 -0
  20. package/dist/domain/model-selection.entity.functions.d.ts +5 -0
  21. package/dist/domain/model-selection.entity.functions.js +9 -0
  22. package/dist/domain/model-selection.entity.js +8 -0
  23. package/dist/domain/prompt-provenance.entity.d.ts +11 -0
  24. package/dist/domain/prompt-provenance.entity.js +8 -0
  25. package/dist/domain/token-usage.entity.d.ts +9 -0
  26. package/dist/domain/token-usage.entity.functions.d.ts +3 -0
  27. package/dist/domain/token-usage.entity.functions.js +11 -0
  28. package/dist/domain/token-usage.entity.js +7 -0
  29. package/dist/harness/capability.entity.d.ts +61 -0
  30. package/dist/harness/capability.entity.functions.d.ts +6 -0
  31. package/dist/harness/capability.entity.functions.js +10 -0
  32. package/dist/harness/capability.entity.js +26 -0
  33. package/dist/harness/capability.test.d.ts +1 -0
  34. package/dist/harness/config.entity.d.ts +48 -0
  35. package/dist/harness/config.entity.functions.d.ts +3 -0
  36. package/dist/harness/config.entity.functions.js +1 -0
  37. package/dist/harness/config.entity.js +18 -0
  38. package/dist/harness/plugin.adapter.d.ts +18 -0
  39. package/dist/harness/plugin.adapter.js +13 -0
  40. package/dist/harness/plugin.entity.d.ts +25 -0
  41. package/dist/harness/plugin.entity.js +9 -0
  42. package/dist/harness/session.entity.d.ts +33 -0
  43. package/dist/harness/session.entity.js +25 -0
  44. package/dist/index.d.ts +51 -0
  45. package/dist/index.js +99 -0
  46. package/dist/loop/cacheKey.d.ts +13 -0
  47. package/dist/loop/cacheKey.js +2 -0
  48. package/dist/loop/mapping.d.ts +79 -0
  49. package/dist/loop/mapping.js +154 -0
  50. package/dist/loop/mapping.test.d.ts +1 -0
  51. package/dist/loop/modelPolicy.d.ts +21 -0
  52. package/dist/loop/modelPolicy.js +2 -0
  53. package/dist/loop/promptProvenance.d.ts +8 -0
  54. package/dist/loop/promptProvenance.js +2 -0
  55. package/dist/loop/stepContext.d.ts +3 -0
  56. package/dist/loop/stepContext.js +2 -0
  57. package/dist/loop/streamFold.d.ts +31 -0
  58. package/dist/loop/streamFold.js +58 -0
  59. package/dist/loop/streamFold.test.d.ts +1 -0
  60. package/dist/mcp/bridge.d.ts +51 -0
  61. package/dist/mcp/bridge.js +70 -0
  62. package/dist/mcp/bridge.test.d.ts +1 -0
  63. package/dist/ports/auth-store.port.d.ts +50 -0
  64. package/dist/ports/auth-store.port.js +18 -0
  65. package/dist/ports/capability.port.d.ts +15 -0
  66. package/dist/ports/capability.port.js +7 -0
  67. package/dist/ports/conversation-store.port.d.ts +250 -0
  68. package/dist/ports/conversation-store.port.js +36 -0
  69. package/dist/ports/file-system.port.d.ts +26 -0
  70. package/dist/ports/file-system.port.js +10 -0
  71. package/dist/ports/harness.port.d.ts +106 -0
  72. package/dist/ports/harness.port.js +31 -0
  73. package/dist/ports/mcp-client.port.d.ts +74 -0
  74. package/dist/ports/mcp-client.port.js +24 -0
  75. package/dist/ports/model-catalog.port.d.ts +10 -0
  76. package/dist/ports/model-catalog.port.js +4 -0
  77. package/dist/ports/settings-store.port.d.ts +85 -0
  78. package/dist/ports/settings-store.port.js +36 -0
  79. package/dist/ports/shell.port.d.ts +44 -0
  80. package/dist/ports/shell.port.js +16 -0
  81. package/dist/ports/utility-llm.port.d.ts +48 -0
  82. package/dist/ports/utility-llm.port.js +16 -0
  83. package/dist/session/chassis.d.ts +59 -0
  84. package/dist/session/chassis.js +27 -0
  85. package/dist/session/chassis.test.d.ts +1 -0
  86. package/dist/spec/SpecDoc.d.ts +162 -0
  87. package/dist/spec/SpecDoc.js +59 -0
  88. package/dist/spec/codec.d.ts +30 -0
  89. package/dist/spec/codec.js +123 -0
  90. package/dist/spec/codec.test.d.ts +1 -0
  91. package/dist/spec/frontmatter.d.ts +16 -0
  92. package/dist/spec/frontmatter.js +25 -0
  93. package/dist/util/json.d.ts +19 -0
  94. package/dist/util/json.js +15 -0
  95. package/package.json +30 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Xand Reed
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # @xandreed/core
2
+
3
+ Efferent composable agent framework, 0.3.0. Bun on Linux.
4
+
5
+ Documentation: https://github.com/xandreeddev/efferent
@@ -0,0 +1,12 @@
1
+ import { Schema } from "effect";
2
+ /** Stable, serializable failure context shared by products and evaluations. */
3
+ export declare const AgentFailureCategory: Schema.Literal<["authentication", "authorization", "rate-limit", "timeout", "transport", "protocol", "validation", "tool", "persistence", "unknown"]>;
4
+ export type AgentFailureCategory = typeof AgentFailureCategory.Type;
5
+ export declare const AgentFailure: Schema.Struct<{
6
+ code: typeof Schema.String;
7
+ category: Schema.Literal<["authentication", "authorization", "rate-limit", "timeout", "transport", "protocol", "validation", "tool", "persistence", "unknown"]>;
8
+ stage: typeof Schema.String;
9
+ message: typeof Schema.String;
10
+ retryable: typeof Schema.Boolean;
11
+ }>;
12
+ export type AgentFailure = typeof AgentFailure.Type;
@@ -0,0 +1,5 @@
1
+ import type { AgentFailure } from "./agent-failure.entity.js";
2
+ /** Classify adapter/runtime defects without exposing provider-specific types. */
3
+ export declare const toAgentFailure: (error: unknown, stage: string) => AgentFailure;
4
+ /** Preserve a returned tool failure as structured context for hosts/evals. */
5
+ export declare const toolResultFailure: (result: unknown, toolName: string) => AgentFailure;
@@ -0,0 +1,8 @@
1
+ const record = (value) => typeof value === "object" && value !== null ? value : {}, text = (value) => typeof value === "string" && value.trim().length > 0 ? value : void 0, numeric = (value) => typeof value === "number" && Number.isFinite(value) ? value : void 0;
2
+ export const toAgentFailure = (error, stage) => {
3
+ const value = record(error), response = record(value.response), tag = text(value._tag) ?? (error instanceof Error ? error.name : void 0) ?? "UnknownError", status = numeric(response.status) ?? numeric(value.status), message = text(value.description) ?? (error instanceof Error ? error.message : void 0) ?? String(error), unavailable = /model .* is not available to .*subscription/i.test(message), unsupported = /model .* (?:is )?not supported/i.test(message), terminalQuota = /CreditsError|insufficient (?:balance|credits)|usage limit|quota exhausted/i.test(message), category = unavailable || unsupported ? "validation" : terminalQuota ? "rate-limit" : /timeout/i.test(tag) || /timed? out/i.test(message) ? "timeout" : /AuthError/i.test(tag) || status === 401 ? "authentication" : status === 403 ? "authorization" : status === 429 ? "rate-limit" : /Malformed|Parse|Decode/i.test(tag) || status !== void 0 && status >= 400 && status < 500 ? "protocol" : /Http|Request|Response|Network|Socket|Fetch/i.test(tag) || status !== void 0 && status >= 500 ? "transport" : "unknown";
4
+ return { code: unavailable ? "ModelUnavailable" : unsupported ? "ModelUnsupported" : status === void 0 ? tag : `${tag}:${status}`, category, stage, message, retryable: category === "timeout" || category === "rate-limit" && !terminalQuota || category === "transport" };
5
+ }, toolResultFailure = (result, toolName) => {
6
+ const value = record(result), code = text(value.error) ?? "ToolFailure", message = text(value.message) ?? JSON.stringify(result), category = /Rejected|Incomplete|Invalid|TooMany|TooLarge/i.test(code) ? "validation" : /Store/i.test(code) ? "persistence" : "tool";
7
+ return { code, category, stage: `tool:${toolName}`, message, retryable: category === "persistence" };
8
+ };
@@ -0,0 +1,8 @@
1
+ import { Schema } from "effect";
2
+ export const AgentFailureCategory = Schema.Literal("authentication", "authorization", "rate-limit", "timeout", "transport", "protocol", "validation", "tool", "persistence", "unknown"), AgentFailure = Schema.Struct({
3
+ code: Schema.String,
4
+ category: AgentFailureCategory,
5
+ stage: Schema.String,
6
+ message: Schema.String,
7
+ retryable: Schema.Boolean
8
+ });
@@ -0,0 +1,12 @@
1
+ import { Schema } from "effect";
2
+ /**
3
+ * The shared tool-failure shape every engine toolkit uses with
4
+ * `failureMode: "return"`: a handler failure is returned to the model as
5
+ * data — `{ error, message }` — never thrown, never a dead turn. The
6
+ * `message` says exactly what to fix; the model corrects in the same run.
7
+ */
8
+ export declare const Failure: Schema.Struct<{
9
+ error: typeof Schema.String;
10
+ message: typeof Schema.String;
11
+ }>;
12
+ export type Failure = typeof Failure.Type;
@@ -0,0 +1,3 @@
1
+ import type { Failure } from "./failure.entity.js";
2
+ /** Project an arbitrary defect into the model-readable failure shape. */
3
+ export declare const toFailure: (error: unknown) => Failure;
@@ -0,0 +1 @@
1
+ export const toFailure = (error) => error instanceof Error ? { error: error.name, message: error.message } : { error: "Error", message: String(error) };
@@ -0,0 +1,5 @@
1
+ import { Schema } from "effect";
2
+ export const Failure = Schema.Struct({
3
+ error: Schema.String,
4
+ message: Schema.String
5
+ });
@@ -0,0 +1,94 @@
1
+ import type { TokenUsage } from "./token-usage.entity.js";
2
+ import type { AgentFailure } from "./agent-failure.entity.js";
3
+ /**
4
+ * The loop's event vocabulary — everything a driver needs to render a run
5
+ * live. ONE union, ONE optional sink (`onEvent`), instead of a record of
6
+ * optional callbacks: the session chassis pumps these onto its ledger and a
7
+ * product extends the vocabulary with its own `{ type: ... }` events.
8
+ *
9
+ * Discriminated on `type` (not `_tag`) so product events compose naturally
10
+ * (`type SessionEvent = LoopEvent | { type: "math_render"; ... }`).
11
+ */
12
+ export interface ToolCallSummary {
13
+ readonly id: string;
14
+ readonly toolName: string;
15
+ readonly args: unknown;
16
+ }
17
+ export type LoopEvent = {
18
+ readonly type: "turn_start";
19
+ readonly turnIndex: number;
20
+ } | {
21
+ readonly type: "turn_end";
22
+ readonly turnIndex: number;
23
+ readonly status: "completed" | "failed" | "cancelled";
24
+ }
25
+ /**
26
+ * One streamed content increment, TRANSIENT by design: it exists only for
27
+ * live rendering, is never ledgered or replayed, and every fact it carries
28
+ * is restated by the turn's `assistant_message` (the sole finalizer —
29
+ * position/usage ride only there). `id` scopes deltas to one content chunk
30
+ * within the turn (a turn can hold several, e.g. reasoning then text).
31
+ */
32
+ | {
33
+ readonly type: "assistant_delta";
34
+ readonly turnIndex: number;
35
+ /** `tool-params` deltas carry the tool call's streamed ARGUMENT text —
36
+ * they exist for incremental admission (a session may act on a
37
+ * complete argument prefix before the call settles) and are noise to
38
+ * plain text renderers, which should drop the channel. */
39
+ readonly channel: "text" | "reasoning" | "tool-params";
40
+ readonly id: string;
41
+ readonly delta: string;
42
+ /** The tool being called — present on `tool-params` deltas only. */
43
+ readonly toolName?: string;
44
+ } | {
45
+ readonly type: "assistant_message";
46
+ readonly turnIndex: number;
47
+ readonly text: string;
48
+ readonly reasoning: string;
49
+ /** The resolved `provider:modelId` that produced this message. */
50
+ readonly model?: string;
51
+ readonly toolCalls: ReadonlyArray<ToolCallSummary>;
52
+ readonly usage: TokenUsage;
53
+ /** The assistant message's absolute store position, when persisted —
54
+ * the durable identity a UI keys its rail block on. */
55
+ readonly position?: number;
56
+ } | {
57
+ readonly type: "tool_start";
58
+ readonly turnIndex: number;
59
+ readonly toolCallId: string;
60
+ readonly toolName: string;
61
+ readonly args: unknown;
62
+ } | {
63
+ readonly type: "tool_end";
64
+ readonly turnIndex: number;
65
+ readonly toolCallId: string;
66
+ readonly toolName: string;
67
+ readonly args: unknown;
68
+ readonly ok: boolean;
69
+ readonly result: unknown;
70
+ }
71
+ /** The mid-run fold: the buffer outgrew the healthy context range and the
72
+ * older turns were replaced by a handoff summary — `kept` verbatim
73
+ * messages survive after it. A load-side rewrite; nothing is deleted. */
74
+ | {
75
+ readonly type: "compaction";
76
+ readonly turnIndex: number;
77
+ readonly tokens: number;
78
+ readonly kept: number;
79
+ } | {
80
+ readonly type: "agent_end";
81
+ readonly outcome: "ok" | "partial";
82
+ readonly reason: "completed" | "step-cap" | "degenerate-loop";
83
+ readonly finalText: string;
84
+ }
85
+ /** A turn crashed outside the model's control (provider failure after
86
+ * retries, a defect). Published by the chassis, part of the vocabulary so
87
+ * every driver renders failures the same way. */
88
+ | {
89
+ readonly type: "error";
90
+ /** Human-readable presentation text. */
91
+ readonly message: string;
92
+ /** Machine-readable context retained by stores, hosts, and evals. */
93
+ readonly failure?: AgentFailure;
94
+ };
File without changes
@@ -0,0 +1,227 @@
1
+ import { Schema } from "effect";
2
+ /**
3
+ * The persisted conversation vocabulary — a stable, provider-agnostic shape
4
+ * the loop appends to and the store persists verbatim. `providerOptions` is
5
+ * an opaque blob that round-trips provider-private fields (e.g. Gemini's
6
+ * `thought_signature` on a reasoning part) without the engine inspecting them.
7
+ */
8
+ export declare const ConversationId: Schema.brand<typeof Schema.UUID, "ConversationId">;
9
+ export type ConversationId = typeof ConversationId.Type;
10
+ /** A tool call's pairing key — the provider's id, or the loop's deterministic
11
+ * `<turnIndex>:<toolName>:<ordinal>` mint when the provider omits one. */
12
+ export declare const ToolCallId: Schema.brand<typeof Schema.String, "ToolCallId">;
13
+ export type ToolCallId = typeof ToolCallId.Type;
14
+ declare const Checkpoint_base: Schema.Class<Checkpoint, {
15
+ conversationId: Schema.brand<typeof Schema.UUID, "ConversationId">;
16
+ /** The absolute message position this fold covers (inclusive). */
17
+ messagePosition: typeof Schema.Number;
18
+ summary: typeof Schema.String;
19
+ createdAt: typeof Schema.Number;
20
+ }, Schema.Struct.Encoded<{
21
+ conversationId: Schema.brand<typeof Schema.UUID, "ConversationId">;
22
+ /** The absolute message position this fold covers (inclusive). */
23
+ messagePosition: typeof Schema.Number;
24
+ summary: typeof Schema.String;
25
+ createdAt: typeof Schema.Number;
26
+ }>, never, {
27
+ readonly conversationId: string & import("effect/Brand").Brand<"ConversationId">;
28
+ } & {
29
+ readonly messagePosition: number;
30
+ } & {
31
+ readonly summary: string;
32
+ } & {
33
+ readonly createdAt: number;
34
+ }, {}, {}>;
35
+ export declare class Checkpoint extends Checkpoint_base {
36
+ }
37
+ export declare const TextPart: Schema.Struct<{
38
+ type: Schema.Literal<["text"]>;
39
+ text: typeof Schema.String;
40
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
41
+ }>;
42
+ export type TextPart = typeof TextPart.Type;
43
+ export declare const ReasoningPart: Schema.Struct<{
44
+ type: Schema.Literal<["reasoning"]>;
45
+ text: typeof Schema.String;
46
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
47
+ }>;
48
+ export type ReasoningPart = typeof ReasoningPart.Type;
49
+ export declare const ToolCallPart: Schema.Struct<{
50
+ type: Schema.Literal<["tool-call"]>;
51
+ toolCallId: Schema.brand<typeof Schema.String, "ToolCallId">;
52
+ toolName: typeof Schema.String;
53
+ input: typeof Schema.Unknown;
54
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
55
+ providerExecuted: Schema.optional<typeof Schema.Boolean>;
56
+ }>;
57
+ export type ToolCallPart = typeof ToolCallPart.Type;
58
+ export declare const ToolResultPart: Schema.Struct<{
59
+ type: Schema.Literal<["tool-result"]>;
60
+ toolCallId: Schema.brand<typeof Schema.String, "ToolCallId">;
61
+ toolName: typeof Schema.String;
62
+ output: typeof Schema.Unknown;
63
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
64
+ isError: Schema.optional<typeof Schema.Boolean>;
65
+ }>;
66
+ export type ToolResultPart = typeof ToolResultPart.Type;
67
+ export declare const UserMessage: Schema.Struct<{
68
+ role: Schema.Literal<["user"]>;
69
+ content: typeof Schema.String;
70
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
71
+ }>;
72
+ export type UserMessage = typeof UserMessage.Type;
73
+ export declare const AssistantMessage: Schema.Struct<{
74
+ role: Schema.Literal<["assistant"]>;
75
+ content: Schema.Array$<Schema.Union<[Schema.Struct<{
76
+ type: Schema.Literal<["text"]>;
77
+ text: typeof Schema.String;
78
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
79
+ }>, Schema.Struct<{
80
+ type: Schema.Literal<["reasoning"]>;
81
+ text: typeof Schema.String;
82
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
83
+ }>, Schema.Struct<{
84
+ type: Schema.Literal<["tool-call"]>;
85
+ toolCallId: Schema.brand<typeof Schema.String, "ToolCallId">;
86
+ toolName: typeof Schema.String;
87
+ input: typeof Schema.Unknown;
88
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
89
+ providerExecuted: Schema.optional<typeof Schema.Boolean>;
90
+ }>]>>;
91
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
92
+ }>;
93
+ export type AssistantMessage = typeof AssistantMessage.Type;
94
+ export declare const ToolMessage: Schema.Struct<{
95
+ role: Schema.Literal<["tool"]>;
96
+ content: Schema.Array$<Schema.Struct<{
97
+ type: Schema.Literal<["tool-result"]>;
98
+ toolCallId: Schema.brand<typeof Schema.String, "ToolCallId">;
99
+ toolName: typeof Schema.String;
100
+ output: typeof Schema.Unknown;
101
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
102
+ isError: Schema.optional<typeof Schema.Boolean>;
103
+ }>>;
104
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
105
+ }>;
106
+ export type ToolMessage = typeof ToolMessage.Type;
107
+ /** The single conversation unit — persisted as-is, one row per entry. */
108
+ export declare const AgentMessage: Schema.Union<[Schema.Struct<{
109
+ role: Schema.Literal<["user"]>;
110
+ content: typeof Schema.String;
111
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
112
+ }>, Schema.Struct<{
113
+ role: Schema.Literal<["assistant"]>;
114
+ content: Schema.Array$<Schema.Union<[Schema.Struct<{
115
+ type: Schema.Literal<["text"]>;
116
+ text: typeof Schema.String;
117
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
118
+ }>, Schema.Struct<{
119
+ type: Schema.Literal<["reasoning"]>;
120
+ text: typeof Schema.String;
121
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
122
+ }>, Schema.Struct<{
123
+ type: Schema.Literal<["tool-call"]>;
124
+ toolCallId: Schema.brand<typeof Schema.String, "ToolCallId">;
125
+ toolName: typeof Schema.String;
126
+ input: typeof Schema.Unknown;
127
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
128
+ providerExecuted: Schema.optional<typeof Schema.Boolean>;
129
+ }>]>>;
130
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
131
+ }>, Schema.Struct<{
132
+ role: Schema.Literal<["tool"]>;
133
+ content: Schema.Array$<Schema.Struct<{
134
+ type: Schema.Literal<["tool-result"]>;
135
+ toolCallId: Schema.brand<typeof Schema.String, "ToolCallId">;
136
+ toolName: typeof Schema.String;
137
+ output: typeof Schema.Unknown;
138
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
139
+ isError: Schema.optional<typeof Schema.Boolean>;
140
+ }>>;
141
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
142
+ }>]>;
143
+ export type AgentMessage = typeof AgentMessage.Type;
144
+ /**
145
+ * Result of one agent run. `newTail` is exactly what the loop APPENDED —
146
+ * including synthetic correctives it injected itself. Persist `newTail`;
147
+ * never reconstruct it by index arithmetic on `messages`.
148
+ */
149
+ export declare const AgentResult: Schema.Struct<{
150
+ finalText: typeof Schema.String;
151
+ messages: Schema.Array$<Schema.Union<[Schema.Struct<{
152
+ role: Schema.Literal<["user"]>;
153
+ content: typeof Schema.String;
154
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
155
+ }>, Schema.Struct<{
156
+ role: Schema.Literal<["assistant"]>;
157
+ content: Schema.Array$<Schema.Union<[Schema.Struct<{
158
+ type: Schema.Literal<["text"]>;
159
+ text: typeof Schema.String;
160
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
161
+ }>, Schema.Struct<{
162
+ type: Schema.Literal<["reasoning"]>;
163
+ text: typeof Schema.String;
164
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
165
+ }>, Schema.Struct<{
166
+ type: Schema.Literal<["tool-call"]>;
167
+ toolCallId: Schema.brand<typeof Schema.String, "ToolCallId">;
168
+ toolName: typeof Schema.String;
169
+ input: typeof Schema.Unknown;
170
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
171
+ providerExecuted: Schema.optional<typeof Schema.Boolean>;
172
+ }>]>>;
173
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
174
+ }>, Schema.Struct<{
175
+ role: Schema.Literal<["tool"]>;
176
+ content: Schema.Array$<Schema.Struct<{
177
+ type: Schema.Literal<["tool-result"]>;
178
+ toolCallId: Schema.brand<typeof Schema.String, "ToolCallId">;
179
+ toolName: typeof Schema.String;
180
+ output: typeof Schema.Unknown;
181
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
182
+ isError: Schema.optional<typeof Schema.Boolean>;
183
+ }>>;
184
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
185
+ }>]>>;
186
+ newTail: Schema.Array$<Schema.Union<[Schema.Struct<{
187
+ role: Schema.Literal<["user"]>;
188
+ content: typeof Schema.String;
189
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
190
+ }>, Schema.Struct<{
191
+ role: Schema.Literal<["assistant"]>;
192
+ content: Schema.Array$<Schema.Union<[Schema.Struct<{
193
+ type: Schema.Literal<["text"]>;
194
+ text: typeof Schema.String;
195
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
196
+ }>, Schema.Struct<{
197
+ type: Schema.Literal<["reasoning"]>;
198
+ text: typeof Schema.String;
199
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
200
+ }>, Schema.Struct<{
201
+ type: Schema.Literal<["tool-call"]>;
202
+ toolCallId: Schema.brand<typeof Schema.String, "ToolCallId">;
203
+ toolName: typeof Schema.String;
204
+ input: typeof Schema.Unknown;
205
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
206
+ providerExecuted: Schema.optional<typeof Schema.Boolean>;
207
+ }>]>>;
208
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
209
+ }>, Schema.Struct<{
210
+ role: Schema.Literal<["tool"]>;
211
+ content: Schema.Array$<Schema.Struct<{
212
+ type: Schema.Literal<["tool-result"]>;
213
+ toolCallId: Schema.brand<typeof Schema.String, "ToolCallId">;
214
+ toolName: typeof Schema.String;
215
+ output: typeof Schema.Unknown;
216
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
217
+ isError: Schema.optional<typeof Schema.Boolean>;
218
+ }>>;
219
+ providerOptions: Schema.optional<typeof Schema.Unknown>;
220
+ }>]>>;
221
+ /** "ok" — the model finished on its own; "partial" — the step cap or the
222
+ * degenerate-loop breaker stopped it, so `finalText` is NOT a deliverable. */
223
+ outcome: Schema.Literal<["ok", "partial"]>;
224
+ reason: Schema.Literal<["completed", "step-cap", "degenerate-loop"]>;
225
+ }>;
226
+ export type AgentResult = typeof AgentResult.Type;
227
+ export {};
@@ -0,0 +1,51 @@
1
+ import { Schema } from "effect";
2
+ export const ConversationId = Schema.UUID.pipe(Schema.brand("ConversationId")), ToolCallId = Schema.String.pipe(Schema.brand("ToolCallId"));
3
+
4
+ export class Checkpoint extends Schema.Class("Checkpoint")({
5
+ conversationId: ConversationId,
6
+ messagePosition: Schema.Number,
7
+ summary: Schema.String,
8
+ createdAt: Schema.Number
9
+ }) {
10
+ }
11
+ export const TextPart = Schema.Struct({
12
+ type: Schema.Literal("text"),
13
+ text: Schema.String,
14
+ providerOptions: Schema.optional(Schema.Unknown)
15
+ }), ReasoningPart = Schema.Struct({
16
+ type: Schema.Literal("reasoning"),
17
+ text: Schema.String,
18
+ providerOptions: Schema.optional(Schema.Unknown)
19
+ }), ToolCallPart = Schema.Struct({
20
+ type: Schema.Literal("tool-call"),
21
+ toolCallId: ToolCallId,
22
+ toolName: Schema.String,
23
+ input: Schema.Unknown,
24
+ providerOptions: Schema.optional(Schema.Unknown),
25
+ providerExecuted: Schema.optional(Schema.Boolean)
26
+ }), ToolResultPart = Schema.Struct({
27
+ type: Schema.Literal("tool-result"),
28
+ toolCallId: ToolCallId,
29
+ toolName: Schema.String,
30
+ output: Schema.Unknown,
31
+ providerOptions: Schema.optional(Schema.Unknown),
32
+ isError: Schema.optional(Schema.Boolean)
33
+ }), UserMessage = Schema.Struct({
34
+ role: Schema.Literal("user"),
35
+ content: Schema.String,
36
+ providerOptions: Schema.optional(Schema.Unknown)
37
+ }), AssistantMessage = Schema.Struct({
38
+ role: Schema.Literal("assistant"),
39
+ content: Schema.Array(Schema.Union(TextPart, ReasoningPart, ToolCallPart)),
40
+ providerOptions: Schema.optional(Schema.Unknown)
41
+ }), ToolMessage = Schema.Struct({
42
+ role: Schema.Literal("tool"),
43
+ content: Schema.Array(ToolResultPart),
44
+ providerOptions: Schema.optional(Schema.Unknown)
45
+ }), AgentMessage = Schema.Union(UserMessage, AssistantMessage, ToolMessage), AgentResult = Schema.Struct({
46
+ finalText: Schema.String,
47
+ messages: Schema.Array(AgentMessage),
48
+ newTail: Schema.Array(AgentMessage),
49
+ outcome: Schema.Literal("ok", "partial"),
50
+ reason: Schema.Literal("completed", "step-cap", "degenerate-loop")
51
+ });
@@ -0,0 +1,12 @@
1
+ import { Schema } from "effect";
2
+ /** `none` skips reasoning entirely — live-probed 2026-07-16 on the codex
3
+ * subscription dialect (accepted, reasoning_tokens 0); `minimal` was
4
+ * REJECTED there and stays out of the vocabulary. Non-codex adapters clamp
5
+ * `none` to their nearest supported value. */
6
+ export declare const ReasoningEffort: Schema.Literal<["none", "low", "medium", "high", "xhigh", "max"]>;
7
+ export type ReasoningEffort = typeof ReasoningEffort.Type;
8
+ export declare const ModelCallPolicy: Schema.Struct<{
9
+ effort: Schema.Literal<["none", "low", "medium", "high", "xhigh", "max"]>;
10
+ maxOutputTokens: Schema.optional<typeof Schema.Number>;
11
+ }>;
12
+ export type ModelCallPolicy = typeof ModelCallPolicy.Type;
@@ -0,0 +1,5 @@
1
+ import { Schema } from "effect";
2
+ export const ReasoningEffort = Schema.Literal("none", "low", "medium", "high", "xhigh", "max"), ModelCallPolicy = Schema.Struct({
3
+ effort: ReasoningEffort,
4
+ maxOutputTokens: Schema.optional(Schema.Number)
5
+ });
@@ -0,0 +1,10 @@
1
+ import { Schema } from "effect";
2
+ /** A selectable model exposed by one configured provider adapter. */
3
+ export declare const ModelCatalogEntry: Schema.Struct<{
4
+ selection: typeof Schema.String;
5
+ /** Human-facing route name. `selection` remains the stable persisted id. */
6
+ label: Schema.optional<typeof Schema.String>;
7
+ provider: typeof Schema.String;
8
+ credential: Schema.Literal<["api_key", "oauth", "local"]>;
9
+ }>;
10
+ export type ModelCatalogEntry = typeof ModelCatalogEntry.Type;
@@ -0,0 +1,7 @@
1
+ import { Schema } from "effect";
2
+ export const ModelCatalogEntry = Schema.Struct({
3
+ selection: Schema.String,
4
+ label: Schema.optional(Schema.String),
5
+ provider: Schema.String,
6
+ credential: Schema.Literal("api_key", "oauth", "local")
7
+ });
@@ -0,0 +1,24 @@
1
+ import { Schema } from "effect";
2
+ /**
3
+ * A model selection is `"<provider>:<modelId>"` — the human's choice, persisted
4
+ * in settings. The engine treats the provider as an opaque id; which providers
5
+ * exist (and how to build their clients) is the providers package's knowledge.
6
+ */
7
+ export declare const ProviderId: Schema.brand<typeof Schema.String, "ProviderId">;
8
+ export type ProviderId = typeof ProviderId.Type;
9
+ export declare const ModelId: Schema.brand<typeof Schema.String, "ModelId">;
10
+ export type ModelId = typeof ModelId.Type;
11
+ declare const ModelSelection_base: Schema.Class<ModelSelection, {
12
+ provider: Schema.brand<typeof Schema.String, "ProviderId">;
13
+ modelId: Schema.brand<typeof Schema.String, "ModelId">;
14
+ }, Schema.Struct.Encoded<{
15
+ provider: Schema.brand<typeof Schema.String, "ProviderId">;
16
+ modelId: Schema.brand<typeof Schema.String, "ModelId">;
17
+ }>, never, {
18
+ readonly provider: string & import("effect/Brand").Brand<"ProviderId">;
19
+ } & {
20
+ readonly modelId: string & import("effect/Brand").Brand<"ModelId">;
21
+ }, {}, {}>;
22
+ export declare class ModelSelection extends ModelSelection_base {
23
+ }
24
+ export {};
@@ -0,0 +1,5 @@
1
+ import { Option } from "effect";
2
+ import { ModelSelection } from "./model-selection.entity.js";
3
+ /** Parse `"<provider>:<modelId>"`; model ids may themselves contain `:`. */
4
+ export declare const parseModelSelection: (value: string) => Option.Option<ModelSelection>;
5
+ export declare const formatModelSelection: (selection: ModelSelection) => string;
@@ -0,0 +1,9 @@
1
+ import { Option } from "effect";
2
+ import { ModelId, ModelSelection, ProviderId } from "./model-selection.entity.js";
3
+ export const parseModelSelection = (value) => {
4
+ const at = value.indexOf(":"), provider = at > 0 ? value.slice(0, at) : "", modelId = at > 0 ? value.slice(at + 1) : "";
5
+ return provider.length > 0 && modelId.length > 0 ? Option.some(new ModelSelection({
6
+ provider: ProviderId.make(provider),
7
+ modelId: ModelId.make(modelId)
8
+ })) : Option.none();
9
+ }, formatModelSelection = (selection) => `${selection.provider}:${selection.modelId}`;
@@ -0,0 +1,8 @@
1
+ import { Schema } from "effect";
2
+ export const ProviderId = Schema.String.pipe(Schema.brand("ProviderId")), ModelId = Schema.String.pipe(Schema.brand("ModelId"));
3
+
4
+ export class ModelSelection extends Schema.Class("ModelSelection")({
5
+ provider: ProviderId,
6
+ modelId: ModelId
7
+ }) {
8
+ }
@@ -0,0 +1,11 @@
1
+ import { Schema } from "effect";
2
+ export declare const PromptId: Schema.brand<typeof Schema.NonEmptyTrimmedString, "PromptId">;
3
+ /** Metadata accompanies a native @effect/ai Prompt; it never replaces its messages. */
4
+ export declare const PromptProvenance: Schema.Struct<{
5
+ id: Schema.brand<typeof Schema.NonEmptyTrimmedString, "PromptId">;
6
+ version: typeof Schema.NonEmptyTrimmedString;
7
+ variant: typeof Schema.NonEmptyTrimmedString;
8
+ modelOverride: Schema.OptionFromNullOr<typeof Schema.String>;
9
+ hash: typeof Schema.NonEmptyTrimmedString;
10
+ }>;
11
+ export type PromptProvenance = typeof PromptProvenance.Type;
@@ -0,0 +1,8 @@
1
+ import { Schema } from "effect";
2
+ export const PromptId = Schema.NonEmptyTrimmedString.pipe(Schema.brand("PromptId")), PromptProvenance = Schema.Struct({
3
+ id: PromptId,
4
+ version: Schema.NonEmptyTrimmedString,
5
+ variant: Schema.NonEmptyTrimmedString,
6
+ modelOverride: Schema.OptionFromNullOr(Schema.String),
7
+ hash: Schema.NonEmptyTrimmedString
8
+ });
@@ -0,0 +1,9 @@
1
+ import { Schema } from "effect";
2
+ /** Billed tokens for one model call (or a sum of them). */
3
+ export declare const TokenUsage: Schema.Struct<{
4
+ inputTokens: typeof Schema.Number;
5
+ outputTokens: typeof Schema.Number;
6
+ totalTokens: typeof Schema.Number;
7
+ cacheReadTokens: typeof Schema.Number;
8
+ }>;
9
+ export type TokenUsage = typeof TokenUsage.Type;
@@ -0,0 +1,3 @@
1
+ import type { TokenUsage } from "./token-usage.entity.js";
2
+ export declare const zeroUsage: TokenUsage;
3
+ export declare const addUsage: (a: TokenUsage, b: TokenUsage) => TokenUsage;
@@ -0,0 +1,11 @@
1
+ export const zeroUsage = {
2
+ inputTokens: 0,
3
+ outputTokens: 0,
4
+ totalTokens: 0,
5
+ cacheReadTokens: 0
6
+ }, addUsage = (a, b) => ({
7
+ inputTokens: a.inputTokens + b.inputTokens,
8
+ outputTokens: a.outputTokens + b.outputTokens,
9
+ totalTokens: a.totalTokens + b.totalTokens,
10
+ cacheReadTokens: a.cacheReadTokens + b.cacheReadTokens
11
+ });
@@ -0,0 +1,7 @@
1
+ import { Schema } from "effect";
2
+ export const TokenUsage = Schema.Struct({
3
+ inputTokens: Schema.Number,
4
+ outputTokens: Schema.Number,
5
+ totalTokens: Schema.Number,
6
+ cacheReadTokens: Schema.Number
7
+ });