@alma-harness/conversation 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +182 -6
- package/dist/index.d.ts +37 -4
- package/dist/index.js +461 -32
- package/dist/index.js.map +1 -1
- package/package.json +13 -13
package/README.md
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# @alma-harness/conversation
|
|
2
2
|
|
|
3
|
-
Governed buffered conversations. Use matching core, execution, loop
|
|
3
|
+
Governed buffered and settled-step streaming conversations. Use matching core, execution, loop
|
|
4
4
|
and single-call packages. `createConversationRunner(config)` composes durable
|
|
5
5
|
session admission, operation roots, governed model steps and final result storage.
|
|
6
|
-
It is
|
|
6
|
+
It is the sole conversation entrypoint; the standalone agent and its legacy
|
|
7
|
+
lease/claim, streaming and financial writers have been removed (spec: retire-legacy-conversation-engine).
|
|
7
8
|
|
|
8
9
|
Supply `step: GovernedStepConfig`, `admissions`, `rootResults`, `sessions`, ordinary
|
|
9
10
|
agent prompt/policy/tools/profiles/hooks/media/recall options, `caps`, `prices`,
|
|
@@ -15,7 +16,98 @@ mappings are trusted host capabilities. Tools use `ConversationTool` and receive
|
|
|
15
16
|
`ConversationToolCtx`, including `models.direct({tier,sensitivity,prompt})` for a
|
|
16
17
|
single tool-free child call, and the narrowing `models.delegate` gateway.
|
|
17
18
|
|
|
18
|
-
`
|
|
19
|
+
`runTurn({scope,sessionId,idempotencyKey,input,intent,trigger?,toolProfile?,signal?})`
|
|
20
|
+
accepts an inline user Msg and a required stable delivery key. It snapshots bounded
|
|
21
|
+
plain JSON before I/O and derives scoped root identity and input/config bindings.
|
|
22
|
+
Retries return original outcomes without renewing deadlines or dispatching again;
|
|
23
|
+
changed content/options/config conflicts. Use immutable media references, not inline
|
|
24
|
+
wire content. Host configuration revisions must cover all behavior, and referenced
|
|
25
|
+
media bytes must remain bound to the original request. Undefined optional object
|
|
26
|
+
fields are omitted; arrays remain ordered. Non-JSON/accessor/cyclic/oversized input
|
|
27
|
+
is rejected before admission. The canonical payload ceiling includes 4 KiB metadata
|
|
28
|
+
overhead in addition to maxInputChars; traversal is bounded at 64 levels/100k nodes.
|
|
29
|
+
|
|
30
|
+
`conversationRootKey(scope,sessionId,idempotencyKey)` lets a host call read without
|
|
31
|
+
loading content. `createConversationDescriptor(config,input,deadlineAt)` is a pure
|
|
32
|
+
helper for explicit hosts interoperating with simple requests. `runTurn` also accepts
|
|
33
|
+
existing explicit input. Its reserved conversation-v1 identities use the same narrow
|
|
34
|
+
clock-race rule: differing proposed deadlines reuse the first descriptor only if all
|
|
35
|
+
other bindings match. This is a trusted-host convention, not proof of hashed content.
|
|
36
|
+
Arbitrary explicit roots keep exact binding semantics. Generic or lost claim ACKs
|
|
37
|
+
never grant ownership. Input signal is execution cancellation, not a socket signal.
|
|
38
|
+
|
|
39
|
+
The legacy `run` method is removed (spec: canonical-conversation-api-cutover).
|
|
40
|
+
Use `runTurn` for both simple and explicit input. It always returns a Promise;
|
|
41
|
+
invalid input rejects that promise and can be handled with `.catch()`. Input
|
|
42
|
+
normalization and snapshot happen immediately during the call, before any await.
|
|
43
|
+
Constructor and `streamTurn` validation remain synchronous.
|
|
44
|
+
`@alma-harness/runtime/memory` and `/postgres` provide storage composition.
|
|
45
|
+
|
|
46
|
+
Canonical APIs first observe the scoped admission and compare original bindings.
|
|
47
|
+
Matching retries never resolve policy again. For unseen work, `policy.resolve`
|
|
48
|
+
must be synchronous, pure and bounded: it receives only a copied RoutingIntent,
|
|
49
|
+
including task. A throw or absent selected client returns
|
|
50
|
+
`{status:"not_admitted",reason:"routing_unavailable"}` before any claim, context,
|
|
51
|
+
hook, provider validation or financial write. A final admission read takes
|
|
52
|
+
precedence if a matching competitor became visible; conflicts still reject.
|
|
53
|
+
Lookup failure or cancellation never claims a routing refusal.
|
|
54
|
+
|
|
55
|
+
This refusal is not durable and describes this invocation, not global absence.
|
|
56
|
+
`read` returns null for an unadmitted key and may observe a later competing claim.
|
|
57
|
+
Fix the configuration with a new configRevision before retrying; do not retry a
|
|
58
|
+
configuration refusal automatically. No receipt or session release is fabricated.
|
|
59
|
+
Successful validation snapshots the complete main choice for all main steps;
|
|
60
|
+
summary/direct/delegate routing remains independent. Post-admission uncertainty
|
|
61
|
+
still retains occupancy, including pre-existing failed admissions.
|
|
62
|
+
|
|
63
|
+
## Settled-step streaming
|
|
64
|
+
|
|
65
|
+
`streamTurn(input)` accepts the same input as `runTurn` and starts the same engine
|
|
66
|
+
eagerly. It returns one async iterator and an independent `result` promise:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
const stream = runner.streamTurn(input);
|
|
70
|
+
try {
|
|
71
|
+
for await (const event of stream) {
|
|
72
|
+
if (event.type === "text") showProgress(event.step, event.text);
|
|
73
|
+
if (event.type === "result") showStatus(event.view.status);
|
|
74
|
+
}
|
|
75
|
+
} catch (error) {
|
|
76
|
+
if (!(error instanceof ConversationStreamResyncError)) throw error;
|
|
77
|
+
// Resynchronize using runner.read(scope, originalRootKey).
|
|
78
|
+
} finally {
|
|
79
|
+
const view = await stream.result; // Worker completion is independent of the reader.
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Import `ConversationStreamResyncError` from this package. Text spans arrive in
|
|
84
|
+
main-step block order only after settlement and fresh authorization; there are no
|
|
85
|
+
provider-token deltas. A preamble may be visible before a later tool failure, cap
|
|
86
|
+
stop or uncertain root. Progress is not final completion and concatenated progress
|
|
87
|
+
is not generally the final reply. Final-message channels should use `runTurn`.
|
|
88
|
+
|
|
89
|
+
Progress tool/provider events contain metadata only; reasoning and child output
|
|
90
|
+
are withheld. Usage events are original main-call receipts; child costs can make
|
|
91
|
+
the final total larger than their sum. The terminal `result` event preserves the
|
|
92
|
+
existing host-facing ConversationView, including authorized tool/provider blocks
|
|
93
|
+
in its reply. Chat renderers select text blocks rather than serializing the envelope.
|
|
94
|
+
Fresh root authorization precedes final delivery and preserves owner/replay flags.
|
|
95
|
+
|
|
96
|
+
Break, return, throw and socket closure detach only the reader. Keep the worker
|
|
97
|
+
alive and await `result` separately; never wire socket close to input.signal.
|
|
98
|
+
Only that execution signal/deadline cancels execution. Detach is not durable
|
|
99
|
+
background scheduling, and uncertain execution still requires reconciliation.
|
|
100
|
+
|
|
101
|
+
Each stream permits one iterator and one pending next. Queues hold references,
|
|
102
|
+
not output, with limits of 128 references and 256 KiB metadata. Overflow, erased/
|
|
103
|
+
expired/denied step output or a failed authorization read detach with typed reasons
|
|
104
|
+
`overflow`, `unavailable`, or `read_failed`. Reconnect through `read`; there is no
|
|
105
|
+
durable intermediate replay. A late first iterator after result settlement receives
|
|
106
|
+
only a freshly authorized final view, unless already overflowed. That view may be
|
|
107
|
+
unavailable after erasure even if the earlier result promise completed. Detached
|
|
108
|
+
iterators cannot reattach, and pending store reads cannot deliver late events.
|
|
109
|
+
|
|
110
|
+
`runTurn({root,intent,loadInput,trigger?,toolProfile?,signal?})` requires the root's
|
|
19
111
|
closed request descriptor. Its configuration/output versions and retention must
|
|
20
112
|
match construction, caps must match, maxCalls may narrow, and the declared root
|
|
21
113
|
sensitivity must equal the intent. The host assigns inputRevision to the complete
|
|
@@ -50,7 +142,8 @@ Provider live smokes, publication and product delivery are separate evidence.
|
|
|
50
142
|
## Completion and reconciliation
|
|
51
143
|
|
|
52
144
|
The result is a status view: completed with a TurnResult, busy with a root key,
|
|
53
|
-
in_progress, reconciliation_required, or
|
|
145
|
+
in_progress, reconciliation_required, unavailable, or a non-durable not_admitted
|
|
146
|
+
routing refusal. `read(scope,key)` rechecks
|
|
54
147
|
admission, closed root, financial completion and authorized final content. It does
|
|
55
148
|
not dispatch, repair effects or load conversation context. Replays retain original
|
|
56
149
|
usage/cost and mark `replayed: true`; do not add them to new spend. Root warnings
|
|
@@ -77,8 +170,8 @@ quiescence before resolution. Use the step runner's recovery APIs for accounting
|
|
|
77
170
|
that does not complete a conversation.
|
|
78
171
|
|
|
79
172
|
Governed output preserves cross-category block order and omits reasoning from the
|
|
80
|
-
reply. Refusal/truncation obey the governed-step output contract.
|
|
81
|
-
|
|
173
|
+
reply. Refusal/truncation obey the governed-step output contract. There is no
|
|
174
|
+
token streaming or automatic reactive context-window retry. Cold-start rotation
|
|
82
175
|
is supported; uncertain provider failures require reconciliation. Batch/routines,
|
|
83
176
|
history import and channel delivery remain separate adoption work.
|
|
84
177
|
|
|
@@ -87,3 +180,86 @@ separate result namespaces, durable replay/erasure and lost append acknowledgeme
|
|
|
87
180
|
No Prumo tour scene is added here: its source budget is nearly full, and the new
|
|
88
181
|
capability's executable acceptance path is packages/conversation/test. A tour
|
|
89
182
|
integration needs a separate budget-preserving scene slice.
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
Tools can use `ctx.models.tryDelegate` to handle structural delegation refusals.
|
|
186
|
+
Returning that exact invocation-local object emits an error tool result while the
|
|
187
|
+
parent continues. A refusal is not evidence that the handler had no effects;
|
|
188
|
+
throwing handlers, failed siblings, outstanding children and persistence failures
|
|
189
|
+
still require reconciliation. The existing `delegate` method retains its throwing
|
|
190
|
+
contract. S5 demonstrates explicit forwarding and settled parent/child accounting.
|
|
191
|
+
|
|
192
|
+
### Safe context rotation
|
|
193
|
+
|
|
194
|
+
Cold rotation is unchanged. Reactive rotation requires a retained, authorized
|
|
195
|
+
Anthropic pre-generation rejection plus its original zero call/root receipts.
|
|
196
|
+
One summary and one replacement main call use new child identities under the
|
|
197
|
+
same root/caps/deadline. Generic errors, ordinary zero usage, contradictory
|
|
198
|
+
content, erased/expired proof, lost acknowledgements and cancellation cannot
|
|
199
|
+
permit continuation. Earlier tools are never replayed. The OpenAI/OpenRouter
|
|
200
|
+
parity exception remains for consolidated maintainer acceptance before cutover
|
|
201
|
+
(spec: safe-context-rejection-rotation).
|
|
202
|
+
|
|
203
|
+
When an attested refusal finishes without another rotation (no policy, no removable
|
|
204
|
+
head, or a second refusal), the view is `completed`, `result.terminalReason` is
|
|
205
|
+
`completed`, `result.stopReason` is `context_window_exceeded`, and
|
|
206
|
+
`result.reply.blocks` is empty. **Hosts must inspect stopReason**, not just the
|
|
207
|
+
completed status: show a context-limit outcome instead of delivering a blank answer
|
|
208
|
+
as success. This replaces the legacy typed, retryable window error. The same admitted
|
|
209
|
+
key replays the original outcome; it does not retry the provider. A new attempt
|
|
210
|
+
requires a deliberate host decision and an appropriate context change. Generic
|
|
211
|
+
provider errors without attestation still require reconciliation.
|
|
212
|
+
|
|
213
|
+
The four product-visible differences (main-only progress usage, unpersisted input
|
|
214
|
+
after a start-hook failure, withheld truncated tool closures, and completed context
|
|
215
|
+
refusal) are enumerated for explicit owner acceptance in the
|
|
216
|
+
[review packet](../../docs/unification-review.md#product-contract-acceptance).
|
|
217
|
+
|
|
218
|
+
Private feature tests exercise volatile context, reasoning persistence and
|
|
219
|
+
parent/delegate request-control isolation through this canonical API. Scripted
|
|
220
|
+
usage remains explicit; missing evidence is never converted into a free call.
|
|
221
|
+
|
|
222
|
+
Deferred and provider-tool integration tests use the same canonical fixture,
|
|
223
|
+
including grant isolation, settled search receipts, pause continuation and
|
|
224
|
+
uncertainty when a search cannot be priced.
|
|
225
|
+
|
|
226
|
+
Media/wire tests also cover explicit lazy inline input, reference-only simple
|
|
227
|
+
input, history replay and truncation suppression with retained receipts.
|
|
228
|
+
|
|
229
|
+
Financial feature tests pin requested versus served tier pricing, root warning
|
|
230
|
+
attribution, sibling blocks and rejection of the removed per-turn override surface.
|
|
231
|
+
|
|
232
|
+
Output/text feature tests preserve tool ceilings and redaction, measured recall,
|
|
233
|
+
Unicode repair for tools, invalid provider-text refusal and owning reply identity.
|
|
234
|
+
|
|
235
|
+
Recall feature tests distinguish normal content gating from source uncertainty,
|
|
236
|
+
pre-admission cancellation and delegate sensitivity, with bounded timeout evidence.
|
|
237
|
+
|
|
238
|
+
Hook-boundary tests preserve request narrowing and shape-only trails, including
|
|
239
|
+
retained uncertainty after sink failure or mutation of frozen hook input.
|
|
240
|
+
|
|
241
|
+
Recall uses the loop's single deadline with lifecycle-guarded source access.
|
|
242
|
+
Cancellation clears the timer even if the source never settles; late source
|
|
243
|
+
results cannot append, dispatch or release uncertain session ownership.
|
|
244
|
+
|
|
245
|
+
Basic engine feature tests cover schema/scope, profiles, nested grants and actual
|
|
246
|
+
root/call correlation. Structural delegation refusals are explicit; execution
|
|
247
|
+
failures retain uncertainty and suppress subsequent host lifecycle effects.
|
|
248
|
+
|
|
249
|
+
Construction rejects missing or noncallable spend readers. Persistent-cap tests
|
|
250
|
+
use original governed receipts and counters, including tenant isolation and
|
|
251
|
+
retained uncertainty when reads or settlement fail.
|
|
252
|
+
|
|
253
|
+
Lifecycle tests pin listener cleanup, frozen registration and awaited audit failures.
|
|
254
|
+
A pre-aborted request is never admitted; a poisoned start hook leaves buffered input
|
|
255
|
+
unpersisted. The final append is one user/assistant batch. Failure views withhold
|
|
256
|
+
private errors and partial replies while original known receipts remain readable.
|
|
257
|
+
|
|
258
|
+
Final integration parity covers complete replay snapshots, daily budget-stop replay,
|
|
259
|
+
no TTL takeover, main-only steps and duration before end hooks, cold summary history,
|
|
260
|
+
and documented settled-stream consumption. The [test ledger](../../docs/legacy-conversation-test-ledger.md)
|
|
261
|
+
maps all remaining legacy cases and their explicitly superseded contracts.
|
|
262
|
+
|
|
263
|
+
Malformed cap configuration rejects with TypeError from the canonical financial
|
|
264
|
+
normalizer, replacing legacy AgentConfigError. Invalid path scope rejects with
|
|
265
|
+
InvalidScopeError before admission. Neither error authorizes execution.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ToolDefinition, ToolCtx, DelegateRequest, DelegateResult, ExecutionResultStore, BudgetCaps, ModelPrice, RoutingIntent, ToolProfileRef, TurnTrigger, Msg, Scope } from '@alma-harness/core';
|
|
2
2
|
import { OperationSessionStore, OperationRootInput } from '@alma-harness/execution';
|
|
3
|
-
import {
|
|
3
|
+
import { LoopConfig } from '@alma-harness/loop/internal';
|
|
4
|
+
import { TurnEvent, TurnResult } from '@alma-harness/loop';
|
|
4
5
|
import { GovernedStepConfig } from '@alma-harness/single-call';
|
|
5
6
|
|
|
6
7
|
interface ConversationToolCtx extends ToolCtx {
|
|
@@ -11,7 +12,7 @@ interface ConversationToolCtx extends ToolCtx {
|
|
|
11
12
|
type ConversationTool = Omit<ToolDefinition, "handler"> & {
|
|
12
13
|
handler(input: unknown, ctx: ConversationToolCtx): Promise<unknown>;
|
|
13
14
|
};
|
|
14
|
-
interface ConversationConfig extends Omit<
|
|
15
|
+
interface ConversationConfig extends Omit<LoopConfig, "clients" | "audit" | "tools"> {
|
|
15
16
|
tools?: ConversationTool[];
|
|
16
17
|
step: GovernedStepConfig;
|
|
17
18
|
admissions: OperationSessionStore;
|
|
@@ -37,7 +38,20 @@ interface ConversationInput {
|
|
|
37
38
|
loadInput(): Promise<Msg>;
|
|
38
39
|
signal?: AbortSignal;
|
|
39
40
|
}
|
|
41
|
+
interface SimpleConversationInput {
|
|
42
|
+
scope: Scope;
|
|
43
|
+
sessionId: string;
|
|
44
|
+
idempotencyKey: string;
|
|
45
|
+
input: Msg;
|
|
46
|
+
intent: RoutingIntent;
|
|
47
|
+
toolProfile?: ToolProfileRef;
|
|
48
|
+
trigger?: TurnTrigger;
|
|
49
|
+
signal?: AbortSignal;
|
|
50
|
+
}
|
|
40
51
|
type ConversationView = {
|
|
52
|
+
status: "not_admitted";
|
|
53
|
+
reason: "routing_unavailable";
|
|
54
|
+
} | {
|
|
41
55
|
status: "completed";
|
|
42
56
|
result: TurnResult;
|
|
43
57
|
replayed: boolean;
|
|
@@ -47,11 +61,30 @@ type ConversationView = {
|
|
|
47
61
|
} | {
|
|
48
62
|
status: "in_progress" | "reconciliation_required" | "unavailable";
|
|
49
63
|
};
|
|
64
|
+
type ConversationEvent = TurnEvent | {
|
|
65
|
+
type: "result";
|
|
66
|
+
view: ConversationView;
|
|
67
|
+
};
|
|
68
|
+
interface ConversationStream extends AsyncIterable<ConversationEvent> {
|
|
69
|
+
readonly result: Promise<ConversationView>;
|
|
70
|
+
[Symbol.asyncIterator](): AsyncIterableIterator<ConversationEvent>;
|
|
71
|
+
}
|
|
50
72
|
interface ConversationRunner {
|
|
51
|
-
|
|
73
|
+
streamTurn(input: SimpleConversationInput | ConversationInput): ConversationStream;
|
|
74
|
+
runTurn(input: SimpleConversationInput | ConversationInput): Promise<ConversationView>;
|
|
52
75
|
read(scope: Scope, rootKey: string): Promise<ConversationView | null>;
|
|
53
76
|
}
|
|
54
77
|
|
|
78
|
+
type ConversationDescriptorConfig = Pick<ConversationConfig, "caps" | "policyVersion" | "configRevision" | "resultContractVersion" | "resultRetentionMs" | "maxCalls" | "maxInputChars" | "runTimeoutMs">;
|
|
79
|
+
declare function conversationRootKey(scope: Scope, sessionId: string, idempotencyKey: string): string;
|
|
80
|
+
/** Pure helper for hosts binding lazy input to the same canonical identity. */
|
|
81
|
+
declare function createConversationDescriptor(c: ConversationDescriptorConfig, input: SimpleConversationInput, deadlineAt: string): OperationRootInput;
|
|
82
|
+
|
|
83
|
+
declare class ConversationStreamResyncError extends Error {
|
|
84
|
+
readonly reason: "overflow" | "unavailable" | "read_failed";
|
|
85
|
+
constructor(reason: "overflow" | "unavailable" | "read_failed");
|
|
86
|
+
}
|
|
87
|
+
|
|
55
88
|
declare function createConversationRunner(value: ConversationConfig): ConversationRunner;
|
|
56
89
|
|
|
57
|
-
export { type ConversationConfig, type ConversationInput, type ConversationRunner, type ConversationTool, type ConversationToolCtx, type ConversationView, createConversationRunner };
|
|
90
|
+
export { type ConversationConfig, type ConversationDescriptorConfig, type ConversationEvent, type ConversationInput, type ConversationRunner, type ConversationStream, ConversationStreamResyncError, type ConversationTool, type ConversationToolCtx, type ConversationView, type SimpleConversationInput, conversationRootKey, createConversationDescriptor, createConversationRunner };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import { equalExecution, ExecutionConflictError, ExecutionResultPolicyError, normalizeExecutionEvidence, settlementIdentifier, settlementScope } from "@alma-harness/core";
|
|
3
|
-
import { normalizeOperationRoot } from "@alma-harness/execution";
|
|
2
|
+
import { equalExecution as equalExecution4, ExecutionConflictError as ExecutionConflictError2, ExecutionResultPolicyError as ExecutionResultPolicyError2, normalizeExecutionEvidence, settlementIdentifier as settlementIdentifier2, settlementScope as settlementScope2 } from "@alma-harness/core";
|
|
3
|
+
import { normalizeOperationRoot as normalizeOperationRoot2 } from "@alma-harness/execution";
|
|
4
4
|
import { createInternals as createInternals2, NO_EMIT, runTurnBody } from "@alma-harness/loop/internal";
|
|
5
5
|
|
|
6
6
|
// src/config.ts
|
|
@@ -8,6 +8,7 @@ import { normalizeBudgetCaps, settlementIdentifier as id } from "@alma-harness/c
|
|
|
8
8
|
import { createInternals } from "@alma-harness/loop/internal";
|
|
9
9
|
import { createGovernedStepRunner } from "@alma-harness/single-call";
|
|
10
10
|
function config(value) {
|
|
11
|
+
if (typeof value.step.spend?.peek !== "function") throw new TypeError("Conversation requires a spend reader");
|
|
11
12
|
if (value.rootResults === value.step.results) throw new TypeError("Conversation results require a separate physical namespace");
|
|
12
13
|
for (const [key, max] of Object.entries({ runTimeoutMs: 3e5, resultRetentionMs: 31536e6, maxCalls: 512, maxInputChars: 64e6 })) {
|
|
13
14
|
const n = value[key];
|
|
@@ -32,27 +33,23 @@ function config(value) {
|
|
|
32
33
|
...value.media ? { media: { ...value.media } } : {}
|
|
33
34
|
};
|
|
34
35
|
createGovernedStepRunner(c.step);
|
|
35
|
-
createInternals(
|
|
36
|
+
createInternals(engineConfig(c));
|
|
36
37
|
return c;
|
|
37
38
|
}
|
|
38
|
-
function
|
|
39
|
-
return { ...c, ...c.tools ? { tools: c.tools } : {}, clients: c.step.clients, audit: c.step.audit
|
|
39
|
+
function engineConfig(c) {
|
|
40
|
+
return { ...c, ...c.tools ? { tools: c.tools } : {}, clients: c.step.clients, audit: c.step.audit };
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
// src/execution.ts
|
|
43
|
-
import { BudgetExceededError, normalizeSpendTotals } from "@alma-harness/core";
|
|
44
|
+
import { BudgetExceededError, equalExecution, normalizeSpendTotals } from "@alma-harness/core";
|
|
44
45
|
import { createGovernedStepRunner as createGovernedStepRunner2 } from "@alma-harness/single-call";
|
|
45
46
|
function ordered(step) {
|
|
46
47
|
return step.order.map((p) => p.type === "text" ? { type: "text", text: step.text.slice(p.start, p.end) } : p.type === "reasoning" ? step.reasoning[p.index] : p.type === "provider_block" ? step.providerBlocks[p.index] : { type: "tool_call", id: step.toolCalls[p.index].id, name: step.toolCalls[p.index].name, input: step.toolCalls[p.index].input });
|
|
47
48
|
}
|
|
48
|
-
function execution(c, root, fence, signal, lifecycle) {
|
|
49
|
+
function execution(c, root, fence, signal, lifecycle, observer) {
|
|
49
50
|
const runner = createGovernedStepRunner2(c.step);
|
|
50
51
|
let sequence = 0, spent = 0;
|
|
51
52
|
const warnings = /* @__PURE__ */ new Set();
|
|
52
|
-
const refuse = async () => {
|
|
53
|
-
lifecycle.poison();
|
|
54
|
-
throw new Error("Legacy charging is forbidden");
|
|
55
|
-
};
|
|
56
53
|
async function preflight() {
|
|
57
54
|
lifecycle.check();
|
|
58
55
|
const configured = Object.entries(root.caps).filter(([, v]) => typeof v === "object" && v.onExceeded === "block");
|
|
@@ -67,7 +64,8 @@ function execution(c, root, fence, signal, lifecycle) {
|
|
|
67
64
|
return {
|
|
68
65
|
...lifecycle,
|
|
69
66
|
turnId: root.id,
|
|
70
|
-
|
|
67
|
+
...observer ? { observedStep: observer.main } : {},
|
|
68
|
+
guard: { preflight, spentUsd: () => spent, capsCrossed: () => [...warnings] },
|
|
71
69
|
async run(request, meta) {
|
|
72
70
|
try {
|
|
73
71
|
lifecycle.check();
|
|
@@ -109,6 +107,7 @@ function execution(c, root, fence, signal, lifecycle) {
|
|
|
109
107
|
if (v.status !== "completed") throw new Error("Model step requires reconciliation");
|
|
110
108
|
spent = Math.max(spent, v.rootReceipt.currentUsd);
|
|
111
109
|
for (const cap of v.rootReceipt.newWarnings) warnings.add(cap);
|
|
110
|
+
if (meta.kind === "main") observer?.bind({ operationKey, callId });
|
|
112
111
|
const usage = v.receipt.receipt.settlement.usage;
|
|
113
112
|
const decision = v.rootReceipt.decisions.find((d) => d.exceeded && d.onExceeded === "block");
|
|
114
113
|
if (v.result.outcome === "blocked" && decision) return {
|
|
@@ -122,6 +121,13 @@ function execution(c, root, fence, signal, lifecycle) {
|
|
|
122
121
|
stop: v.result.stopReason,
|
|
123
122
|
error: new BudgetExceededError(decision.cap, decision.thresholdUsd, decision.currentUsd)
|
|
124
123
|
};
|
|
124
|
+
const evidence = v.record.evidence;
|
|
125
|
+
if (meta.kind === "main" && evidence?.status === "known" && evidence.rejection) {
|
|
126
|
+
const stored = await c.step.results.get(root.scope, callId);
|
|
127
|
+
lifecycle.check();
|
|
128
|
+
if (v.result.outcome !== "refusal" || v.result.stopReason !== "context_window_exceeded" || !equalExecution(v.record.completion, { outcome: "refusal", stopReason: "context_window_exceeded" }) || v.receipt.receipt.settlement.costUsd !== 0 || v.rootReceipt.costUsd !== 0 || !stored || stored.state !== "available" || !equalExecution(stored.result, v.result) || !equalExecution(stored.binding, { scope: root.scope, callId, sessionId: root.sessionId, sensitivity: meta.intent.sensitivity, retentionMs: c.resultRetentionMs })) throw new Error("Context refusal is unavailable");
|
|
129
|
+
return { callId, usage, text: "", toolCalls: [], reasoning: [], providerBlocks: [], blocks: [], stop: v.result.stopReason, contextRejected: true };
|
|
130
|
+
}
|
|
125
131
|
if (meta.kind === "summary" && (v.result.outcome !== "success" || !v.step?.text.trim())) throw new Error("Summary output is unusable");
|
|
126
132
|
if (v.result.outcome === "refusal" || v.result.outcome === "truncated") return { callId, usage, text: "", toolCalls: [], reasoning: [], providerBlocks: [], blocks: [], stop: v.result.stopReason };
|
|
127
133
|
if (!v.step || v.result.outcome !== "success") throw new Error("Model output is unavailable");
|
|
@@ -143,6 +149,405 @@ function execution(c, root, fence, signal, lifecycle) {
|
|
|
143
149
|
};
|
|
144
150
|
}
|
|
145
151
|
|
|
152
|
+
// src/input.ts
|
|
153
|
+
import { createHash } from "crypto";
|
|
154
|
+
import { equalExecution as equalExecution2, ExecutionConflictError, settlementIdentifier, settlementInstant, settlementScope } from "@alma-harness/core";
|
|
155
|
+
import { normalizeOperationRoot } from "@alma-harness/execution";
|
|
156
|
+
var prefix = "conversation-v1:";
|
|
157
|
+
var revisionPrefix = "conversation-input-v1:";
|
|
158
|
+
var hash = (value) => createHash("sha256").update(JSON.stringify(value)).digest("hex");
|
|
159
|
+
var one = (value, choices) => typeof value === "string" && choices.includes(value);
|
|
160
|
+
function invalid() {
|
|
161
|
+
throw new TypeError("Invalid canonical conversation input");
|
|
162
|
+
}
|
|
163
|
+
function fields(value, allowed) {
|
|
164
|
+
if (!value || typeof value !== "object" || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) invalid();
|
|
165
|
+
const entries = Reflect.ownKeys(value).map((k) => {
|
|
166
|
+
const d = Object.getOwnPropertyDescriptor(value, k);
|
|
167
|
+
if (typeof k !== "string" || !d.enumerable || !("value" in d) || allowed && !allowed.includes(k)) invalid();
|
|
168
|
+
return [k, d.value];
|
|
169
|
+
});
|
|
170
|
+
return Object.fromEntries(entries);
|
|
171
|
+
}
|
|
172
|
+
function jsonSnapshot(value, max) {
|
|
173
|
+
let nodes = 0, size = 0;
|
|
174
|
+
const ancestors = /* @__PURE__ */ new Set();
|
|
175
|
+
function add(n) {
|
|
176
|
+
size += n;
|
|
177
|
+
if (size > max) invalid();
|
|
178
|
+
}
|
|
179
|
+
function visit(v, depth) {
|
|
180
|
+
if (++nodes > 1e5 || depth > 64) invalid();
|
|
181
|
+
if (v === null || typeof v === "string" || typeof v === "boolean" || typeof v === "number" && Number.isFinite(v)) {
|
|
182
|
+
if (typeof v === "string" && v.length > max) invalid();
|
|
183
|
+
add(JSON.stringify(v).length);
|
|
184
|
+
return Object.is(v, -0) ? 0 : v;
|
|
185
|
+
}
|
|
186
|
+
if (!v || typeof v !== "object" || ancestors.has(v)) invalid();
|
|
187
|
+
ancestors.add(v);
|
|
188
|
+
try {
|
|
189
|
+
add(2);
|
|
190
|
+
if (Array.isArray(v)) {
|
|
191
|
+
if (v.length > 1e5 || Reflect.ownKeys(v).length !== v.length + 1) invalid();
|
|
192
|
+
return Array.from({ length: v.length }, (_, i) => {
|
|
193
|
+
const d = Object.getOwnPropertyDescriptor(v, String(i));
|
|
194
|
+
if (!d || !("value" in d) || !d.enumerable) invalid();
|
|
195
|
+
if (i) add(1);
|
|
196
|
+
return visit(d.value, depth + 1);
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
const object = fields(v), entries = Object.keys(object).sort().filter((k) => object[k] !== void 0);
|
|
200
|
+
return Object.fromEntries(entries.map((k, i) => {
|
|
201
|
+
if (k.length > max) invalid();
|
|
202
|
+
add(JSON.stringify(k).length + 1 + (i ? 1 : 0));
|
|
203
|
+
return [k, visit(object[k], depth + 1)];
|
|
204
|
+
}));
|
|
205
|
+
} finally {
|
|
206
|
+
ancestors.delete(v);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return visit(value, 0);
|
|
210
|
+
}
|
|
211
|
+
function conversationRootKey(scope, sessionId, idempotencyKey) {
|
|
212
|
+
const s = settlementScope(scope);
|
|
213
|
+
return prefix + hash(["conversation-v1", s.org, s.uid, settlementIdentifier(sessionId), settlementIdentifier(idempotencyKey)]);
|
|
214
|
+
}
|
|
215
|
+
function snapshot(c, input) {
|
|
216
|
+
if (!Number.isSafeInteger(c.maxInputChars) || c.maxInputChars < 1 || c.maxInputChars > 64e6 || !Number.isSafeInteger(c.runTimeoutMs) || c.runTimeoutMs < 1 || c.runTimeoutMs > 3e5) invalid();
|
|
217
|
+
const f = fields(input, ["scope", "sessionId", "idempotencyKey", "input", "intent", "toolProfile", "trigger", "signal"]);
|
|
218
|
+
const data = jsonSnapshot(Object.fromEntries(Object.entries(f).filter(([k]) => k !== "signal")), c.maxInputChars + 4096);
|
|
219
|
+
data.scope = settlementScope(data.scope);
|
|
220
|
+
data.sessionId = settlementIdentifier(data.sessionId);
|
|
221
|
+
data.idempotencyKey = settlementIdentifier(data.idempotencyKey);
|
|
222
|
+
const intent = fields(data.intent, ["tier", "sensitivity", "task"]);
|
|
223
|
+
if (!one(intent.tier, ["mechanical", "standard", "complex"]) || !one(intent.sensitivity, ["public", "internal", "personal", "health"]) || intent.task !== void 0 && (typeof intent.task !== "string" || intent.task.length > 1e3)) invalid();
|
|
224
|
+
if (data.toolProfile !== void 0) settlementIdentifier(data.toolProfile);
|
|
225
|
+
data.trigger ??= "user";
|
|
226
|
+
if (!["user", "routine", "system"].includes(data.trigger)) invalid();
|
|
227
|
+
const message = fields(data.input, ["role", "blocks", "meta"]);
|
|
228
|
+
if (message.role !== "user" || !Array.isArray(message.blocks) || JSON.stringify(message).length > c.maxInputChars) invalid();
|
|
229
|
+
for (const block of message.blocks) validateBlock(block);
|
|
230
|
+
if (message.meta !== void 0) {
|
|
231
|
+
const meta = fields(message.meta, ["at", "channel", "model", "rotation"]);
|
|
232
|
+
settlementInstant(meta.at);
|
|
233
|
+
for (const key of ["channel", "model"]) if (meta[key] !== void 0 && typeof meta[key] !== "string") invalid();
|
|
234
|
+
if (meta.rotation !== void 0) {
|
|
235
|
+
const r = fields(meta.rotation, ["summarized", "keep", "reason"]);
|
|
236
|
+
if (![r.summarized, r.keep].every((n) => Number.isSafeInteger(n) && Number(n) >= 0) || !one(r.reason, ["cold_start", "context_window"])) invalid();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (f.signal !== void 0) {
|
|
240
|
+
if (!(f.signal instanceof AbortSignal)) invalid();
|
|
241
|
+
data.signal = f.signal;
|
|
242
|
+
}
|
|
243
|
+
return data;
|
|
244
|
+
}
|
|
245
|
+
function validateBlock(value) {
|
|
246
|
+
const b = fields(value), strings = (...keys) => {
|
|
247
|
+
for (const k of keys) if (typeof b[k] !== "string") invalid();
|
|
248
|
+
};
|
|
249
|
+
const provider = () => {
|
|
250
|
+
if (!one(b.provider, ["anthropic", "openai", "openrouter"])) invalid();
|
|
251
|
+
};
|
|
252
|
+
switch (b.type) {
|
|
253
|
+
case "text":
|
|
254
|
+
strings("text");
|
|
255
|
+
if (b.origin !== void 0 && b.origin !== "harness") invalid();
|
|
256
|
+
break;
|
|
257
|
+
case "media": {
|
|
258
|
+
if (b.content !== void 0 || !one(b.kind, ["image", "audio", "document"])) invalid();
|
|
259
|
+
const ref = fields(b.ref, ["uri", "contentType", "bytes", "filename"]);
|
|
260
|
+
if (typeof ref.uri !== "string") invalid();
|
|
261
|
+
for (const key of ["contentType", "filename"]) if (ref[key] !== void 0 && typeof ref[key] !== "string") invalid();
|
|
262
|
+
if (ref.bytes !== void 0 && (!Number.isSafeInteger(ref.bytes) || Number(ref.bytes) < 0)) invalid();
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
case "tool_call":
|
|
266
|
+
strings("id", "name");
|
|
267
|
+
if (!("input" in b)) invalid();
|
|
268
|
+
break;
|
|
269
|
+
case "tool_result":
|
|
270
|
+
strings("callId");
|
|
271
|
+
if (!("output" in b) || b.isError !== void 0 && typeof b.isError !== "boolean") invalid();
|
|
272
|
+
break;
|
|
273
|
+
case "reasoning":
|
|
274
|
+
provider();
|
|
275
|
+
if (b.text !== void 0) strings("text");
|
|
276
|
+
break;
|
|
277
|
+
case "provider_tool_call":
|
|
278
|
+
provider();
|
|
279
|
+
strings("id");
|
|
280
|
+
if (b.name !== "web_search" || !("input" in b)) invalid();
|
|
281
|
+
break;
|
|
282
|
+
case "provider_tool_result":
|
|
283
|
+
provider();
|
|
284
|
+
strings("callId");
|
|
285
|
+
if (b.name !== "web_search" || !Array.isArray(b.results)) invalid();
|
|
286
|
+
for (const item of b.results) {
|
|
287
|
+
const r = fields(item);
|
|
288
|
+
if (typeof r.url !== "string" || [r.title, r.pageAge].some((v) => v !== void 0 && typeof v !== "string")) invalid();
|
|
289
|
+
}
|
|
290
|
+
if (b.error !== void 0) strings("error");
|
|
291
|
+
break;
|
|
292
|
+
default:
|
|
293
|
+
invalid();
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
function descriptor(c, i, deadlineAt) {
|
|
297
|
+
const key = conversationRootKey(i.scope, i.sessionId, i.idempotencyKey);
|
|
298
|
+
return normalizeOperationRoot({
|
|
299
|
+
scope: i.scope,
|
|
300
|
+
sessionId: i.sessionId,
|
|
301
|
+
key,
|
|
302
|
+
id: key,
|
|
303
|
+
deadlineAt,
|
|
304
|
+
policyVersion: c.policyVersion,
|
|
305
|
+
caps: c.caps,
|
|
306
|
+
maxCalls: c.maxCalls,
|
|
307
|
+
maxSensitivity: i.intent.sensitivity,
|
|
308
|
+
request: {
|
|
309
|
+
inputRevision: revisionPrefix + hash(["conversation-input-v1", i.input, i.intent, i.toolProfile ?? null, i.trigger, c.runTimeoutMs]),
|
|
310
|
+
configRevision: c.configRevision,
|
|
311
|
+
resultContractVersion: c.resultContractVersion,
|
|
312
|
+
resultRetentionMs: c.resultRetentionMs
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
function createConversationDescriptor(c, input, deadlineAt) {
|
|
317
|
+
return descriptor(c, snapshot(c, input), deadlineAt);
|
|
318
|
+
}
|
|
319
|
+
function normalizeTurnInput(c, value) {
|
|
320
|
+
const f = fields(value);
|
|
321
|
+
if ("root" in f) {
|
|
322
|
+
fields(value, ["root", "intent", "loadInput", "toolProfile", "trigger", "signal"]);
|
|
323
|
+
const root = normalizeOperationRoot(f.root), canonical = root.key.startsWith(prefix);
|
|
324
|
+
if (canonical && (root.id !== root.key || !/^conversation-v1:[a-f0-9]{64}$/.test(root.key) || !/^conversation-input-v1:[a-f0-9]{64}$/.test(root.request?.inputRevision ?? ""))) invalid();
|
|
325
|
+
return { input: { ...f, root }, canonical };
|
|
326
|
+
}
|
|
327
|
+
const i = snapshot(c, value);
|
|
328
|
+
return { canonical: true, input: {
|
|
329
|
+
root: descriptor(c, i, new Date(Date.now() + c.runTimeoutMs).toISOString()),
|
|
330
|
+
intent: i.intent,
|
|
331
|
+
trigger: i.trigger,
|
|
332
|
+
...i.toolProfile !== void 0 ? { toolProfile: i.toolProfile } : {},
|
|
333
|
+
...i.signal ? { signal: i.signal } : {},
|
|
334
|
+
loadInput: async () => i.input
|
|
335
|
+
} };
|
|
336
|
+
}
|
|
337
|
+
async function existingAdmission(store, root, canonical, check) {
|
|
338
|
+
const record = await store.get(root.scope, root.key);
|
|
339
|
+
check();
|
|
340
|
+
if (!record) return null;
|
|
341
|
+
if (!equalExecution2(canonical ? { ...record.input, deadlineAt: root.deadlineAt } : record.input, root)) throw new ExecutionConflictError();
|
|
342
|
+
return { status: "existing", record };
|
|
343
|
+
}
|
|
344
|
+
async function claimCanonical(store, root, check) {
|
|
345
|
+
const old = await existingAdmission(store, root, true, check);
|
|
346
|
+
if (old) return old;
|
|
347
|
+
try {
|
|
348
|
+
return await store.claim(root);
|
|
349
|
+
} catch (e) {
|
|
350
|
+
if (!(e instanceof ExecutionConflictError)) throw e;
|
|
351
|
+
check();
|
|
352
|
+
const saved = await existingAdmission(store, root, true, check);
|
|
353
|
+
if (!saved) throw e;
|
|
354
|
+
return saved;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// src/observation.ts
|
|
359
|
+
import { equalExecution as equalExecution3, ExecutionResultPolicyError } from "@alma-harness/core";
|
|
360
|
+
import { createGovernedStepRunner as createGovernedStepRunner3 } from "@alma-harness/single-call";
|
|
361
|
+
|
|
362
|
+
// src/stream.ts
|
|
363
|
+
var ConversationStreamResyncError = class extends Error {
|
|
364
|
+
constructor(reason) {
|
|
365
|
+
super(`Conversation observer requires resynchronization: ${reason}`);
|
|
366
|
+
this.reason = reason;
|
|
367
|
+
this.name = "ConversationStreamResyncError";
|
|
368
|
+
}
|
|
369
|
+
reason;
|
|
370
|
+
};
|
|
371
|
+
var done = () => ({ done: true, value: void 0 });
|
|
372
|
+
function observerQueue(authorize) {
|
|
373
|
+
let queue = [], bytes = 0, reading = false;
|
|
374
|
+
let attached = false, closed = false, settled = false, generation = 0;
|
|
375
|
+
let failure, failed = false;
|
|
376
|
+
let waiting;
|
|
377
|
+
function detach(error) {
|
|
378
|
+
if (closed) return;
|
|
379
|
+
closed = true;
|
|
380
|
+
generation++;
|
|
381
|
+
queue = [];
|
|
382
|
+
bytes = 0;
|
|
383
|
+
failed = error !== void 0;
|
|
384
|
+
failure = error;
|
|
385
|
+
const w = waiting;
|
|
386
|
+
waiting = void 0;
|
|
387
|
+
if (failed) w?.reject(error);
|
|
388
|
+
else w?.resolve(done());
|
|
389
|
+
}
|
|
390
|
+
function pump() {
|
|
391
|
+
if (!waiting || reading || closed) return;
|
|
392
|
+
const item = queue.shift();
|
|
393
|
+
if (!item) {
|
|
394
|
+
if (settled) detach();
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
reading = true;
|
|
398
|
+
const version = generation;
|
|
399
|
+
void Promise.resolve().then(() => authorize(item.ref)).then((event) => {
|
|
400
|
+
if (closed || version !== generation) return;
|
|
401
|
+
bytes -= item.bytes;
|
|
402
|
+
reading = false;
|
|
403
|
+
const w = waiting;
|
|
404
|
+
waiting = void 0;
|
|
405
|
+
w?.resolve({ done: false, value: event });
|
|
406
|
+
}, (error) => {
|
|
407
|
+
if (closed || version !== generation) return;
|
|
408
|
+
reading = false;
|
|
409
|
+
detach(error instanceof ConversationStreamResyncError ? error : new ConversationStreamResyncError("read_failed"));
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
function push(ref) {
|
|
413
|
+
if (closed) return;
|
|
414
|
+
const size = JSON.stringify(ref).length * 2 + 256;
|
|
415
|
+
if (queue.length + Number(reading) >= 128 || bytes + size > 256 * 1024) {
|
|
416
|
+
detach(new ConversationStreamResyncError("overflow"));
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
queue.push({ ref, bytes: size });
|
|
420
|
+
bytes += size;
|
|
421
|
+
pump();
|
|
422
|
+
}
|
|
423
|
+
const iterator = {
|
|
424
|
+
[Symbol.asyncIterator]() {
|
|
425
|
+
return this;
|
|
426
|
+
},
|
|
427
|
+
next() {
|
|
428
|
+
if (closed) return failed ? Promise.reject(failure) : Promise.resolve(done());
|
|
429
|
+
if (waiting || reading) return Promise.reject(new TypeError("Only one pending observer next is supported"));
|
|
430
|
+
return new Promise((resolve, reject) => {
|
|
431
|
+
waiting = { resolve, reject };
|
|
432
|
+
pump();
|
|
433
|
+
});
|
|
434
|
+
},
|
|
435
|
+
return() {
|
|
436
|
+
detach();
|
|
437
|
+
return Promise.resolve(done());
|
|
438
|
+
},
|
|
439
|
+
throw() {
|
|
440
|
+
detach();
|
|
441
|
+
return Promise.resolve(done());
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
return {
|
|
445
|
+
push,
|
|
446
|
+
active: () => !closed,
|
|
447
|
+
finish(ref) {
|
|
448
|
+
if (closed) return;
|
|
449
|
+
if (!attached) {
|
|
450
|
+
queue = [];
|
|
451
|
+
bytes = 0;
|
|
452
|
+
}
|
|
453
|
+
push(ref);
|
|
454
|
+
settled = true;
|
|
455
|
+
pump();
|
|
456
|
+
},
|
|
457
|
+
fail: detach,
|
|
458
|
+
stream(result) {
|
|
459
|
+
return { result, [Symbol.asyncIterator]() {
|
|
460
|
+
if (attached) throw new TypeError("This conversation stream already has an iterator");
|
|
461
|
+
attached = true;
|
|
462
|
+
return iterator;
|
|
463
|
+
} };
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// src/observation.ts
|
|
469
|
+
var unavailable = () => {
|
|
470
|
+
throw new ConversationStreamResyncError("unavailable");
|
|
471
|
+
};
|
|
472
|
+
function observation(c, root, read) {
|
|
473
|
+
const steps = createGovernedStepRunner3(c.step);
|
|
474
|
+
let current;
|
|
475
|
+
const queue = observerQueue(async (ref) => {
|
|
476
|
+
if (ref.type === "final") {
|
|
477
|
+
if (ref.view.status !== "completed") return { type: "result", view: ref.view };
|
|
478
|
+
const fresh2 = await read(root.scope, root.key) ?? { status: "unavailable" };
|
|
479
|
+
if (fresh2.status !== "completed") return { type: "result", view: fresh2 };
|
|
480
|
+
const result = { ...fresh2.result };
|
|
481
|
+
delete result.replayed;
|
|
482
|
+
if (ref.view.replayed) result.replayed = true;
|
|
483
|
+
return { type: "result", view: { ...fresh2, result, replayed: ref.view.replayed } };
|
|
484
|
+
}
|
|
485
|
+
const fresh = await steps.read({ scope: root.scope, rootKey: root.key, operationKey: ref.operationKey });
|
|
486
|
+
if (!fresh || fresh.status !== "completed" || fresh.record.input.callId !== ref.callId || fresh.record.input.operationKey !== ref.operationKey || !equalExecution3(fresh.record.input.scope, root.scope) || fresh.rootReceipt.rootId !== root.id || fresh.rootReceipt.callId !== ref.callId) return unavailable();
|
|
487
|
+
const source = fresh.receipt.receipt.settlement;
|
|
488
|
+
if (ref.type === "usage") return { type: "usage", step: ref.step, model: structuredClone(fresh.record.input.model), usage: structuredClone(source.usage), costUsd: source.costUsd };
|
|
489
|
+
if (fresh.result.outcome !== "success" || !fresh.step) return unavailable();
|
|
490
|
+
const input = fresh.record.input;
|
|
491
|
+
let stored;
|
|
492
|
+
try {
|
|
493
|
+
stored = await c.step.results.get(root.scope, ref.callId);
|
|
494
|
+
} catch (error) {
|
|
495
|
+
if (error instanceof ExecutionResultPolicyError) return unavailable();
|
|
496
|
+
throw error;
|
|
497
|
+
}
|
|
498
|
+
if (!stored || stored.state !== "available" || !equalExecution3(stored.binding, {
|
|
499
|
+
scope: root.scope,
|
|
500
|
+
callId: ref.callId,
|
|
501
|
+
sessionId: input.sessionId,
|
|
502
|
+
sensitivity: input.intent.sensitivity,
|
|
503
|
+
retentionMs: input.governance.resultRetentionMs
|
|
504
|
+
}) || !equalExecution3(stored.result, fresh.result)) return unavailable();
|
|
505
|
+
const step = fresh.step;
|
|
506
|
+
if (ref.type === "tool_result") {
|
|
507
|
+
const call = step.toolCalls.find((t) => t.id === ref.id);
|
|
508
|
+
if (!call) return unavailable();
|
|
509
|
+
return { type: "tool_result", step: ref.step, id: call.id, name: call.name, isError: ref.isError };
|
|
510
|
+
}
|
|
511
|
+
const position = step.order[ref.index];
|
|
512
|
+
if (!position || position.type === "reasoning") return unavailable();
|
|
513
|
+
if (position.type === "text") return { type: "text", step: ref.step, text: step.text.slice(position.start, position.end).toWellFormed() };
|
|
514
|
+
if (position.type === "tool_call") {
|
|
515
|
+
const call = step.toolCalls[position.index];
|
|
516
|
+
if (!call) return unavailable();
|
|
517
|
+
return { type: "tool_call", step: ref.step, id: call.id, name: call.name };
|
|
518
|
+
}
|
|
519
|
+
const block = step.providerBlocks[position.index];
|
|
520
|
+
if (!block) return unavailable();
|
|
521
|
+
return block.type === "provider_tool_call" ? { type: "provider_tool_call", step: ref.step, id: block.id, name: block.name } : { type: "provider_tool_result", step: ref.step, id: block.callId, name: block.name, results: block.results.length, isError: block.error !== void 0 };
|
|
522
|
+
});
|
|
523
|
+
return {
|
|
524
|
+
bind(key) {
|
|
525
|
+
if (queue.active()) current = key;
|
|
526
|
+
},
|
|
527
|
+
main(step, outcome) {
|
|
528
|
+
if (!current || !queue.active() || current.callId !== outcome.callId) return;
|
|
529
|
+
for (let index = 0; index < outcome.blocks.length && queue.active(); index++)
|
|
530
|
+
if (outcome.blocks[index].type !== "reasoning") queue.push({ ...current, type: "block", step, index });
|
|
531
|
+
queue.push({ ...current, type: "usage", step });
|
|
532
|
+
if (!queue.active()) current = void 0;
|
|
533
|
+
},
|
|
534
|
+
emit(event) {
|
|
535
|
+
if (event.type === "tool_result" && current && queue.active()) queue.push({ ...current, type: "tool_result", step: event.step, id: event.id, isError: event.isError });
|
|
536
|
+
if (!queue.active()) current = void 0;
|
|
537
|
+
},
|
|
538
|
+
start(result) {
|
|
539
|
+
void result.then((view) => {
|
|
540
|
+
current = void 0;
|
|
541
|
+
queue.finish({ type: "final", view: view.status === "completed" ? { status: "completed", replayed: view.replayed } : view });
|
|
542
|
+
}, (error) => {
|
|
543
|
+
current = void 0;
|
|
544
|
+
queue.fail(error);
|
|
545
|
+
});
|
|
546
|
+
return queue.stream(result);
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
|
|
146
551
|
// src/index.ts
|
|
147
552
|
var pending = () => ({ status: "reconciliation_required" });
|
|
148
553
|
var interrupted = () => new Error("Conversation requires reconciliation");
|
|
@@ -150,20 +555,20 @@ function createConversationRunner(value) {
|
|
|
150
555
|
const c = config(value);
|
|
151
556
|
const binding = (root) => ({ scope: root.scope, callId: root.key, sessionId: root.sessionId, sensitivity: root.maxSensitivity, retentionMs: root.request.resultRetentionMs });
|
|
152
557
|
async function read(scope, key) {
|
|
153
|
-
const s =
|
|
558
|
+
const s = settlementScope2(scope), k = settlementIdentifier2(key), a = await c.admissions.get(s, k);
|
|
154
559
|
if (!a) return null;
|
|
155
560
|
if (a.status !== "released") return { status: a.status === "active" && a.input.deadlineAt > (/* @__PURE__ */ new Date()).toISOString() ? "in_progress" : "reconciliation_required" };
|
|
156
561
|
if (a.resolutionId || !a.input.request) return pending();
|
|
157
562
|
const root = await c.step.trees.get(s, k);
|
|
158
|
-
if (!root || root.status !== "closed" || !
|
|
563
|
+
if (!root || root.status !== "closed" || !equalExecution4(root.input, a.input)) return pending();
|
|
159
564
|
let stored;
|
|
160
565
|
try {
|
|
161
566
|
stored = await c.rootResults.get(s, k);
|
|
162
567
|
} catch (e) {
|
|
163
|
-
if (e instanceof
|
|
568
|
+
if (e instanceof ExecutionResultPolicyError2) return { status: "unavailable" };
|
|
164
569
|
throw e;
|
|
165
570
|
}
|
|
166
|
-
if (!stored || stored.state !== "available" || !
|
|
571
|
+
if (!stored || stored.state !== "available" || !equalExecution4(stored.binding, binding(root.input)) || stored.result?.outcome !== "success" || stored.result.output.format !== "json") return { status: "unavailable" };
|
|
167
572
|
const financial = await c.step.accounting.get(s, k);
|
|
168
573
|
if (!financial || financial.reservedCalls !== financial.settledCalls || financial.rootStatus !== "closed") return pending();
|
|
169
574
|
try {
|
|
@@ -176,10 +581,10 @@ function createConversationRunner(value) {
|
|
|
176
581
|
return { status: "unavailable" };
|
|
177
582
|
}
|
|
178
583
|
}
|
|
179
|
-
function run(input) {
|
|
180
|
-
const root =
|
|
584
|
+
function run(input, mode, observer) {
|
|
585
|
+
const root = normalizeOperationRoot2(input.root), req = root.request;
|
|
181
586
|
const opts = { intent: structuredClone(input.intent), ...input.trigger ? { trigger: input.trigger } : {}, ...input.toolProfile ? { toolProfile: input.toolProfile } : {} }, load = input.loadInput, external = input.signal;
|
|
182
|
-
if (!req || req.configRevision !== c.configRevision || req.resultContractVersion !== c.resultContractVersion || req.resultRetentionMs !== c.resultRetentionMs || root.policyVersion !== c.policyVersion || !
|
|
587
|
+
if (!req || req.configRevision !== c.configRevision || req.resultContractVersion !== c.resultContractVersion || req.resultRetentionMs !== c.resultRetentionMs || root.policyVersion !== c.policyVersion || !equalExecution4(root.caps, c.caps) || root.maxCalls > c.maxCalls || root.maxSensitivity !== opts.intent.sensitivity || typeof load !== "function") throw new ExecutionConflictError2();
|
|
183
588
|
const controller = new AbortController();
|
|
184
589
|
let uncertain = false, children = 0, sealed = false, admission;
|
|
185
590
|
const poison = () => {
|
|
@@ -232,7 +637,23 @@ function createConversationRunner(value) {
|
|
|
232
637
|
async function execute() {
|
|
233
638
|
try {
|
|
234
639
|
check();
|
|
235
|
-
|
|
640
|
+
let mainChoice;
|
|
641
|
+
{
|
|
642
|
+
const existing = () => existingAdmission(c.admissions, root, mode === "canonical", check);
|
|
643
|
+
if (await existing()) return await read(root.scope, root.key) ?? pending();
|
|
644
|
+
try {
|
|
645
|
+
mainChoice = structuredClone(c.policy.resolve(structuredClone(opts.intent)));
|
|
646
|
+
if (!Object.hasOwn(c.step.clients, mainChoice.model.provider) || !c.step.clients[mainChoice.model.provider]) mainChoice = void 0;
|
|
647
|
+
} catch {
|
|
648
|
+
mainChoice = void 0;
|
|
649
|
+
}
|
|
650
|
+
check();
|
|
651
|
+
if (!mainChoice) {
|
|
652
|
+
if (await existing()) return await read(root.scope, root.key) ?? pending();
|
|
653
|
+
return { status: "not_admitted", reason: "routing_unavailable" };
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
const a = mode === "canonical" ? await claimCanonical(c.admissions, root, check) : await c.admissions.claim(root);
|
|
236
657
|
if (a.status === "claimed") admission = a.fence;
|
|
237
658
|
check();
|
|
238
659
|
if (a.status === "busy") return { status: "busy", rootKey: a.rootKey };
|
|
@@ -240,14 +661,14 @@ function createConversationRunner(value) {
|
|
|
240
661
|
deadline = setTimeout(abort, Math.max(0, Date.parse(root.deadlineAt) - Date.now()));
|
|
241
662
|
const claim = await c.step.trees.claim(root);
|
|
242
663
|
check();
|
|
243
|
-
if (claim.status !== "claimed" || !
|
|
664
|
+
if (claim.status !== "claimed" || !equalExecution4(claim.record.input, root)) throw interrupted();
|
|
244
665
|
const prepared = await c.rootResults.prepare(binding(root));
|
|
245
666
|
check();
|
|
246
667
|
if (prepared.state !== "pending") throw interrupted();
|
|
247
668
|
const message = structuredClone(await load());
|
|
248
669
|
check();
|
|
249
670
|
if (message.role !== "user" || JSON.stringify(message).length > c.maxInputChars) throw new TypeError("Invalid conversation input");
|
|
250
|
-
const base =
|
|
671
|
+
const base = engineConfig(c), sessionStore = c.sessions;
|
|
251
672
|
const guarded = async (fn) => {
|
|
252
673
|
check();
|
|
253
674
|
try {
|
|
@@ -271,13 +692,10 @@ function createConversationRunner(value) {
|
|
|
271
692
|
}
|
|
272
693
|
}])));
|
|
273
694
|
base.sessions = { ...sessionStore, load: (s, id2) => guarded(() => sessionStore.load(s, id2)), append: (s, id2, msgs) => guarded(() => sessionStore.append(s, id2, msgs)), erase: (s, id2) => sessionStore.erase(s, id2), expireToolTraffic: (s, id2, opts2) => sessionStore.expireToolTraffic(s, id2, opts2) };
|
|
274
|
-
if (c.recall) base.recall = { build: (...args) =>
|
|
275
|
-
const timeout = setTimeout(poison, c.recallTimeoutMs ?? 5e3);
|
|
276
|
-
return guarded(() => c.recall.build(...args)).finally(() => clearTimeout(timeout));
|
|
277
|
-
} };
|
|
695
|
+
if (c.recall) base.recall = { build: (...args) => guarded(() => c.recall.build(...args)) };
|
|
278
696
|
if (c.media?.source) base.media = { ...c.media, source: { load: (...args) => guarded(() => c.media.source.load(...args)) } };
|
|
279
|
-
const runtime = execution(c, root, claim.fence, controller.signal, { check, poison, track });
|
|
280
|
-
const body = await runTurnBody(createInternals2(base
|
|
697
|
+
const runtime = execution(c, root, claim.fence, controller.signal, { check, poison, track, mainChoice }, observer);
|
|
698
|
+
const body = await runTurnBody(createInternals2(base), { scope: root.scope, sessionId: root.sessionId, input: message, ...opts, signal: controller.signal }, observer?.emit ?? NO_EMIT, runtime);
|
|
281
699
|
check();
|
|
282
700
|
if (children !== 0 || !["completed", "budget_exceeded"].includes(body.terminalReason)) throw interrupted();
|
|
283
701
|
const totals = await c.step.accounting.get(root.scope, root.key);
|
|
@@ -290,24 +708,35 @@ function createConversationRunner(value) {
|
|
|
290
708
|
check();
|
|
291
709
|
const final = await c.rootResults.get(root.scope, root.key);
|
|
292
710
|
check();
|
|
293
|
-
if (final?.state !== "available" || !
|
|
711
|
+
if (final?.state !== "available" || !equalExecution4(final.binding, binding(root)) || !equalExecution4(final.result, result)) throw interrupted();
|
|
294
712
|
try {
|
|
295
713
|
await c.admissions.finish(admission);
|
|
296
714
|
} catch {
|
|
297
715
|
const released = await c.admissions.get(root.scope, root.key);
|
|
298
|
-
if (!released || released.status !== "released" || released.resolutionId || !
|
|
716
|
+
if (!released || released.status !== "released" || released.resolutionId || !equalExecution4(released.input, root)) throw interrupted();
|
|
299
717
|
}
|
|
300
718
|
return { status: "completed", result: body, replayed: false };
|
|
301
|
-
} catch {
|
|
719
|
+
} catch (e) {
|
|
720
|
+
if (!admission && e instanceof ExecutionConflictError2) throw e;
|
|
302
721
|
poison();
|
|
303
722
|
await uncertainAdmission();
|
|
304
723
|
return pending();
|
|
305
724
|
}
|
|
306
725
|
}
|
|
307
726
|
}
|
|
308
|
-
return {
|
|
727
|
+
return { read, streamTurn(value2) {
|
|
728
|
+
const normalized = normalizeTurnInput(c, value2);
|
|
729
|
+
const observer = observation(c, normalized.input.root, read);
|
|
730
|
+
return observer.start(run(normalized.input, normalized.canonical ? "canonical" : "exact", observer));
|
|
731
|
+
}, async runTurn(value2) {
|
|
732
|
+
const normalized = normalizeTurnInput(c, value2);
|
|
733
|
+
return run(normalized.input, normalized.canonical ? "canonical" : "exact");
|
|
734
|
+
} };
|
|
309
735
|
}
|
|
310
736
|
export {
|
|
737
|
+
ConversationStreamResyncError,
|
|
738
|
+
conversationRootKey,
|
|
739
|
+
createConversationDescriptor,
|
|
311
740
|
createConversationRunner
|
|
312
741
|
};
|
|
313
742
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/execution.ts"],"sourcesContent":["import { equalExecution, ExecutionConflictError, ExecutionResultPolicyError, normalizeExecutionEvidence, settlementIdentifier, settlementScope, type ExecutionResultRecord, type Scope } from \"@alma-harness/core\";\nimport { normalizeOperationRoot, type OperationRootInput, type OperationSessionFence } from \"@alma-harness/execution\";\nimport { createInternals, NO_EMIT, runTurnBody } from \"@alma-harness/loop/internal\";\nimport type { TurnResult } from \"@alma-harness/loop\";\nimport { agentConfig, config } from \"./config\";\nimport { execution } from \"./execution\";\nimport type { ConversationConfig, ConversationInput, ConversationRunner, ConversationView } from \"./types\";\nexport type { ConversationConfig, ConversationInput, ConversationRunner, ConversationView, ConversationTool, ConversationToolCtx } from \"./types\";\nconst pending = (): ConversationView => ({ status:\"reconciliation_required\" });\nconst interrupted = () => new Error(\"Conversation requires reconciliation\");\nexport function createConversationRunner(value: ConversationConfig): ConversationRunner {\n const c = config(value);\n const binding = (root:OperationRootInput) => ({ scope:root.scope,callId:root.key,sessionId:root.sessionId,sensitivity:root.maxSensitivity,retentionMs:root.request!.resultRetentionMs });\n async function read(scope:Scope, key:string): Promise<ConversationView|null> {\n const s = settlementScope(scope), k = settlementIdentifier(key), a = await c.admissions.get(s,k);\n if (!a) return null;\n if (a.status !== \"released\") return { status:a.status === \"active\" && a.input.deadlineAt > new Date().toISOString() ? \"in_progress\" : \"reconciliation_required\" };\n if (a.resolutionId || !a.input.request) return pending();\n const root = await c.step.trees.get(s,k);\n if (!root || root.status !== \"closed\" || !equalExecution(root.input,a.input)) return pending();\n let stored:ExecutionResultRecord|null;\n try { stored = await c.rootResults.get(s,k); } catch (e) { if (e instanceof ExecutionResultPolicyError) return { status:\"unavailable\" }; throw e; }\n if (!stored || stored.state !== \"available\" || !equalExecution(stored.binding,binding(root.input)) || stored.result?.outcome !== \"success\" || stored.result.output.format !== \"json\") return { status:\"unavailable\" };\n const financial = await c.step.accounting.get(s,k);\n if (!financial || financial.reservedCalls !== financial.settledCalls || financial.rootStatus !== \"closed\") return pending();\n try {\n const data = JSON.parse(stored.result.output.text) as { version:string; rootId:string; contract:string; result:TurnResult };\n const r = data.result;\n if (data.version !== \"governed-conversation-v1\" || data.rootId !== root.input.id || data.contract !== root.input.request!.resultContractVersion || !r || r.turnId !== root.input.id || r.costUsd !== financial.costUsd || ![\"completed\",\"budget_exceeded\"].includes(r.terminalReason) || r.reply?.role !== \"assistant\" || !Array.isArray(r.reply.blocks) || r.reply.blocks.some(b => b.type === \"reasoning\") || !Number.isSafeInteger(r.steps) || r.steps < 0 || !Number.isFinite(r.durationMs) || r.durationMs < 0) return { status:\"unavailable\" };\n normalizeExecutionEvidence({ status:\"known\",usage:r.usage });\n return { status:\"completed\",result:{ ...r,replayed:true },replayed:true };\n } catch { return { status:\"unavailable\" }; }\n }\n function run(input:ConversationInput): Promise<ConversationView> {\n const root = normalizeOperationRoot(input.root), req = root.request;\n const opts = { intent:structuredClone(input.intent),...(input.trigger ? {trigger:input.trigger} : {}),...(input.toolProfile ? {toolProfile:input.toolProfile} : {}) }, load = input.loadInput, external = input.signal;\n if (!req || req.configRevision !== c.configRevision || req.resultContractVersion !== c.resultContractVersion || req.resultRetentionMs !== c.resultRetentionMs || root.policyVersion !== c.policyVersion || !equalExecution(root.caps,c.caps) || root.maxCalls > c.maxCalls || root.maxSensitivity !== opts.intent.sensitivity || typeof load !== \"function\") throw new ExecutionConflictError();\n const controller = new AbortController(); let uncertain = false, children = 0, sealed = false, admission:OperationSessionFence|undefined;\n const poison = () => { uncertain = true; controller.abort(); };\n const check = () => { if (uncertain || sealed || controller.signal.aborted || (admission && Date.now() >= Date.parse(root.deadlineAt))) throw interrupted(); };\n function track<T>(fn:()=>Promise<T>):Promise<T> {\n const p = (async () => { check(); children++; try { return await fn(); } catch (e) { poison(); throw e; } finally { children--; } })();\n void p.catch(() => {}); return p;\n }\n const abort = () => poison();\n const timer = setTimeout(abort,c.runTimeoutMs); let deadline:ReturnType<typeof setTimeout>|undefined;\n const cancelled = new Promise<ConversationView>(resolve => controller.signal.addEventListener(\"abort\",() => resolve(pending()),{once:true}));\n external?.addEventListener(\"abort\",abort,{once:true}); if (external?.aborted) abort();\n const work = execute(); void work.catch(() => {});\n return Promise.race([work,cancelled]).finally(() => { sealed = true; clearTimeout(timer); clearTimeout(deadline); external?.removeEventListener(\"abort\",abort); });\n async function uncertainAdmission() { if (admission) { try { await c.admissions.markUncertain(admission); } catch { /* Occupancy survives this failed acknowledgement. */ } } }\n async function execute():Promise<ConversationView> {\n try {\n check(); const a = await c.admissions.claim(root);\n if (a.status === \"claimed\") admission = a.fence;\n check();\n if (a.status === \"busy\") return { status:\"busy\",rootKey:a.rootKey };\n if (a.status === \"existing\") return (await read(root.scope,root.key)) ?? pending();\n deadline = setTimeout(abort,Math.max(0,Date.parse(root.deadlineAt)-Date.now()));\n const claim = await c.step.trees.claim(root); check();\n if (claim.status !== \"claimed\" || !equalExecution(claim.record.input,root)) throw interrupted();\n const prepared = await c.rootResults.prepare(binding(root)); check();\n if (prepared.state !== \"pending\") throw interrupted();\n const message = structuredClone(await load()); check();\n if (message.role !== \"user\" || JSON.stringify(message).length > c.maxInputChars) throw new TypeError(\"Invalid conversation input\");\n const base = agentConfig(c), sessionStore = c.sessions;\n const guarded = async <T>(fn:()=>Promise<T>):Promise<T> => { check(); try { const result = await fn(); check(); return result; } catch (e) { poison(); throw e; } };\n // Every effect-capable hook and all asynchronous context sources are per-turn closures.\n base.hooks = (base.hooks ?? []).map(h => Object.fromEntries(Object.entries(h).filter(([,fn]) => typeof fn === \"function\").map(([key,fn]) => [key,async (...args:unknown[]) => { check(); try { const r = await (fn as (...a:unknown[])=>unknown)(...args); check(); return r; } catch (e) { poison(); throw e; } }])));\n base.sessions = { ...sessionStore, load:(s,id) => guarded(() => sessionStore.load(s,id)), append:(s,id,msgs) => guarded(() => sessionStore.append(s,id,msgs)), erase:(s,id) => sessionStore.erase(s,id), expireToolTraffic:(s,id,opts) => sessionStore.expireToolTraffic(s,id,opts) };\n if (c.recall) base.recall = { build:(...args) => { const timeout = setTimeout(poison,c.recallTimeoutMs ?? 5000); return guarded(() => c.recall!.build(...args)).finally(() => clearTimeout(timeout)); } };\n if (c.media?.source) base.media = { ...c.media,source:{load:(...args) => guarded(() => c.media!.source!.load(...args))} };\n const runtime = execution(c,root,claim.fence,controller.signal,{check,poison,track});\n const body = await runTurnBody(createInternals(base,true), { scope:root.scope,sessionId:root.sessionId,input:message,...opts,signal:controller.signal },root.caps,NO_EMIT,runtime);\n check();\n if (children !== 0 || ![\"completed\",\"budget_exceeded\"].includes(body.terminalReason)) throw interrupted();\n const totals = await c.step.accounting.get(root.scope,root.key); check();\n if (!totals || totals.reservedCalls !== totals.settledCalls || totals.costUsd !== body.costUsd) throw interrupted();\n await c.step.trees.close(claim.fence); check();\n const result = { outcome:\"success\" as const,stopReason:body.stopReason,output:{format:\"json\" as const,text:JSON.stringify({version:\"governed-conversation-v1\",rootId:root.id,contract:req!.resultContractVersion,result:body})} };\n await c.rootResults.put(root.scope,root.key,result); check();\n const final = await c.rootResults.get(root.scope,root.key); check();\n if (final?.state !== \"available\" || !equalExecution(final.binding,binding(root)) || !equalExecution(final.result,result)) throw interrupted();\n try { await c.admissions.finish(admission!); }\n catch {\n // Finish is attempted only AFTER proven local quiescence and durable writes.\n const released = await c.admissions.get(root.scope,root.key);\n if (!released || released.status !== \"released\" || released.resolutionId || !equalExecution(released.input,root)) throw interrupted();\n }\n return {status:\"completed\",result:body,replayed:false};\n } catch { poison(); await uncertainAdmission(); return pending(); }\n }\n }\n return {run,read};\n}\n","import { normalizeBudgetCaps, settlementIdentifier as id, type ToolDefinition } from \"@alma-harness/core\";\nimport { createInternals } from \"@alma-harness/loop/internal\";\nimport type { AgentConfig } from \"@alma-harness/loop\";\nimport { createGovernedStepRunner } from \"@alma-harness/single-call\";\nimport type { ConversationConfig } from \"./types\";\nexport function config(value: ConversationConfig): ConversationConfig {\n if (value.rootResults === value.step.results) throw new TypeError(\"Conversation results require a separate physical namespace\");\n for (const [key, max] of Object.entries({ runTimeoutMs: 300000, resultRetentionMs: 31536000000, maxCalls: 512, maxInputChars: 64000000 })) {\n const n = value[key as keyof ConversationConfig]; if (!Number.isSafeInteger(n) || Number(n) < 1 || Number(n) > max) throw new TypeError(`Invalid conversation ${key}`);\n }\n for (const n of [value.maxSteps ?? 24, value.maxDelegateDepth ?? 2, value.maxTokens ?? 8192]) if (!Number.isSafeInteger(n) || n < 1) throw new TypeError(\"Invalid conversation technical limit\");\n for (const key of [\"policyVersion\", \"priceVersion\", \"configRevision\", \"resultContractVersion\"] as const) id(value[key]);\n if (!Array.isArray(value.consumers) || value.consumers.length > 16) throw new TypeError(\"Invalid consumers\");\n for (const client of Object.values(value.step.clients)) if (!client || client.dispatchPolicy !== \"single\" || typeof client.validate !== \"function\") throw new TypeError(\"Conversation requires single-dispatch clients\");\n const c = { ...value, caps: normalizeBudgetCaps(value.caps), prices: structuredClone(value.prices), consumers: [...new Set(value.consumers.map(id))].sort(),\n system: structuredClone(value.system), step: { ...value.step, clients: { ...value.step.clients } },\n ...(value.providerTools ? { providerTools: structuredClone(value.providerTools) } : {}),\n ...(value.profiles ? { profiles: structuredClone(value.profiles) } : {}),\n ...(value.tools ? { tools: value.tools.map(t => ({ ...t, ...(t.jsonSchema ? { jsonSchema: structuredClone(t.jsonSchema) } : {}) })) } : {}),\n ...(value.hooks ? { hooks: value.hooks.map(h => ({ ...h })) } : {}),\n ...(value.longContext ? { longContext: { ...value.longContext } } : {}), ...(value.media ? { media: { ...value.media } } : {}) };\n createGovernedStepRunner(c.step);\n createInternals(agentConfig(c), true); // Registry/config errors precede claims.\n return c;\n}\nexport function agentConfig(c: ConversationConfig): AgentConfig {\n // The internal governed dispatch branch supplies the declared extended gateway.\n return { ...c, ...(c.tools ? { tools: c.tools as ToolDefinition[] } : {}), clients: c.step.clients, audit: c.step.audit, budget: { caps: c.caps, prices: c.prices } };\n}\n","import { BudgetExceededError, normalizeSpendTotals, type Block, type BudgetCapName, type ModelRequest } from \"@alma-harness/core\";\nimport type { OperationFence, OperationRootInput } from \"@alma-harness/execution\";\nimport type { StepOutcome, TurnExecution } from \"@alma-harness/loop/internal\";\nimport { createGovernedStepRunner, type GovernedStepOutput } from \"@alma-harness/single-call\";\nimport type { ConversationConfig } from \"./types\";\nexport function ordered(step: GovernedStepOutput): Block[] {\n return step.order.map(p => p.type === \"text\" ? { type: \"text\", text: step.text.slice(p.start,p.end) }\n : p.type === \"reasoning\" ? step.reasoning[p.index]!\n : p.type === \"provider_block\" ? step.providerBlocks[p.index]!\n : { type: \"tool_call\", id: step.toolCalls[p.index]!.id, name: step.toolCalls[p.index]!.name, input: step.toolCalls[p.index]!.input });\n}\nexport function execution(c: ConversationConfig, root: OperationRootInput, fence: OperationFence, signal: AbortSignal,\n lifecycle: Pick<TurnExecution,\"check\"|\"poison\"|\"track\">): TurnExecution {\n const runner = createGovernedStepRunner(c.step); let sequence = 0, spent = 0; const warnings = new Set<BudgetCapName>();\n const refuse = async (): Promise<never> => { lifecycle.poison(); throw new Error(\"Legacy charging is forbidden\"); };\n async function preflight() {\n lifecycle.check();\n const configured = Object.entries(root.caps).filter(([,v]) => typeof v === \"object\" && v.onExceeded === \"block\");\n if (!configured.length) return;\n const totals = configured.some(([k]) => k !== \"perTurnUsd\") ? normalizeSpendTotals(await c.step.spend.peek({ scope: root.scope, sessionId: root.sessionId, at: new Date().toISOString() })) : { sessionUsd:0,tenantDayUsd:0 };\n lifecycle.check();\n for (const [key,cap] of configured) { const usd = key === \"perTurnUsd\" ? spent : key === \"perSessionUsd\" ? totals.sessionUsd : totals.tenantDayUsd;\n if (usd >= (cap as {usd:number}).usd) throw new BudgetExceededError(key as BudgetCapName,(cap as {usd:number}).usd,usd); }\n }\n return { ...lifecycle, turnId: root.id,\n guard: { charge: refuse, chargePriced: refuse, preflight, spentUsd: () => spent, drainCrossings: () => [], capsCrossed: () => [...warnings], accountingError: () => undefined },\n async run(request: ModelRequest, meta): Promise<StepOutcome> {\n try {\n lifecycle.check(); await preflight(); lifecycle.check();\n const slot = String(++sequence), callId = crypto.randomUUID(), operationKey = crypto.randomUUID();\n const controls = { maxTokens: request.maxTokens, ...(request.reasoning ? { reasoning: request.reasoning } : {}), ...(request.cache !== undefined ? { cache: request.cache } : {}), ...(request.temperature !== undefined ? { temperature: request.temperature } : {}) };\n const v = await runner.run({ fence, signal, rationale: meta.rationale,\n call: { slot, kind: meta.kind, ...(meta.parentCallId ? { parentCallId: meta.parentCallId } : {}), execution: {\n scope: root.scope, sessionId: root.sessionId, operationKey, operationId: crypto.randomUUID(), attemptId: crypto.randomUUID(), callId, settlementId: crypto.randomUUID(),\n inputRevision: root.request!.inputRevision, policyVersion: root.policyVersion, outputContractVersion: \"governed-step-v1\", intent: {tier:meta.intent.tier,sensitivity:meta.intent.sensitivity},\n model: request.model, requestedTier: request.serviceTier ?? \"standard\", priceVersion: c.priceVersion,\n prices: c.prices.filter(p => p.model.provider === request.model.provider && p.model.id === request.model.id), controls,\n occurredAt: new Date().toISOString(), deadlineAt: root.deadlineAt, governance: { caps: root.caps, consumers: c.consumers, resultRetentionMs: c.resultRetentionMs } } },\n loadRequest: async () => { lifecycle.check(); return request; } });\n lifecycle.check();\n if (v.status !== \"completed\") throw new Error(\"Model step requires reconciliation\");\n spent = Math.max(spent, v.rootReceipt.currentUsd); for (const cap of v.rootReceipt.newWarnings) warnings.add(cap);\n const usage = v.receipt.receipt.settlement.usage;\n const decision = v.rootReceipt.decisions.find(d => d.exceeded && d.onExceeded === \"block\");\n if (v.result.outcome === \"blocked\" && decision) return { callId, usage, text:\"\", toolCalls:[], reasoning:[], providerBlocks:[], blocks:[], stop: v.result.stopReason,\n error: new BudgetExceededError(decision.cap,decision.thresholdUsd,decision.currentUsd) };\n if (meta.kind === \"summary\" && (v.result.outcome !== \"success\" || !v.step?.text.trim())) throw new Error(\"Summary output is unusable\");\n if (v.result.outcome === \"refusal\" || v.result.outcome === \"truncated\") return { callId,usage,text:\"\",toolCalls:[],reasoning:[],providerBlocks:[],blocks:[],stop:v.result.stopReason };\n if (!v.step || v.result.outcome !== \"success\") throw new Error(\"Model output is unavailable\");\n return { callId, usage, text:v.step.text, stop:v.step.stop, reasoning:v.step.reasoning, providerBlocks:v.step.providerBlocks, blocks:ordered(v.step),\n toolCalls:v.step.toolCalls.map(t => ({ id:t.id,name:t.name,input:t.input, ...(t.malformed ? { malformed:\"Invalid JSON\" } : {}) })) };\n } catch (e) { if (!(e instanceof BudgetExceededError)) lifecycle.poison(); throw e; }\n },\n };\n}\n"],"mappings":";AAAA,SAAS,gBAAgB,wBAAwB,4BAA4B,4BAA4B,sBAAsB,uBAA+D;AAC9L,SAAS,8BAAmF;AAC5F,SAAS,mBAAAA,kBAAiB,SAAS,mBAAmB;;;ACFtD,SAAS,qBAAqB,wBAAwB,UAA+B;AACrF,SAAS,uBAAuB;AAEhC,SAAS,gCAAgC;AAElC,SAAS,OAAO,OAA+C;AACpE,MAAI,MAAM,gBAAgB,MAAM,KAAK,QAAS,OAAM,IAAI,UAAU,4DAA4D;AAC9H,aAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,EAAE,cAAc,KAAQ,mBAAmB,SAAa,UAAU,KAAK,eAAe,KAAS,CAAC,GAAG;AACzI,UAAM,IAAI,MAAM,GAA+B;AAAG,QAAI,CAAC,OAAO,cAAc,CAAC,KAAK,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,IAAK,OAAM,IAAI,UAAU,wBAAwB,GAAG,EAAE;AAAA,EACvK;AACA,aAAW,KAAK,CAAC,MAAM,YAAY,IAAI,MAAM,oBAAoB,GAAG,MAAM,aAAa,IAAI,EAAG,KAAI,CAAC,OAAO,cAAc,CAAC,KAAK,IAAI,EAAG,OAAM,IAAI,UAAU,sCAAsC;AAC/L,aAAW,OAAO,CAAC,iBAAiB,gBAAgB,kBAAkB,uBAAuB,EAAY,IAAG,MAAM,GAAG,CAAC;AACtH,MAAI,CAAC,MAAM,QAAQ,MAAM,SAAS,KAAK,MAAM,UAAU,SAAS,GAAI,OAAM,IAAI,UAAU,mBAAmB;AAC3G,aAAW,UAAU,OAAO,OAAO,MAAM,KAAK,OAAO,EAAG,KAAI,CAAC,UAAU,OAAO,mBAAmB,YAAY,OAAO,OAAO,aAAa,WAAY,OAAM,IAAI,UAAU,+CAA+C;AACvN,QAAM,IAAI;AAAA,IAAE,GAAG;AAAA,IAAO,MAAM,oBAAoB,MAAM,IAAI;AAAA,IAAG,QAAQ,gBAAgB,MAAM,MAAM;AAAA,IAAG,WAAW,CAAC,GAAG,IAAI,IAAI,MAAM,UAAU,IAAI,EAAE,CAAC,CAAC,EAAE,KAAK;AAAA,IACxJ,QAAQ,gBAAgB,MAAM,MAAM;AAAA,IAAG,MAAM,EAAE,GAAG,MAAM,MAAM,SAAS,EAAE,GAAG,MAAM,KAAK,QAAQ,EAAE;AAAA,IACjG,GAAI,MAAM,gBAAgB,EAAE,eAAe,gBAAgB,MAAM,aAAa,EAAE,IAAI,CAAC;AAAA,IACrF,GAAI,MAAM,WAAW,EAAE,UAAU,gBAAgB,MAAM,QAAQ,EAAE,IAAI,CAAC;AAAA,IACtE,GAAI,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAM,IAAI,QAAM,EAAE,GAAG,GAAG,GAAI,EAAE,aAAa,EAAE,YAAY,gBAAgB,EAAE,UAAU,EAAE,IAAI,CAAC,EAAG,EAAE,EAAE,IAAI,CAAC;AAAA,IACzI,GAAI,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAM,IAAI,QAAM,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC;AAAA,IACjE,GAAI,MAAM,cAAc,EAAE,aAAa,EAAE,GAAG,MAAM,YAAY,EAAE,IAAI,CAAC;AAAA,IAAI,GAAI,MAAM,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,EAAE,IAAI,CAAC;AAAA,EAAG;AACjI,2BAAyB,EAAE,IAAI;AAC/B,kBAAgB,YAAY,CAAC,GAAG,IAAI;AACpC,SAAO;AACT;AACO,SAAS,YAAY,GAAoC;AAE9D,SAAO,EAAE,GAAG,GAAG,GAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAA0B,IAAI,CAAC,GAAI,SAAS,EAAE,KAAK,SAAS,OAAO,EAAE,KAAK,OAAO,QAAQ,EAAE,MAAM,EAAE,MAAM,QAAQ,EAAE,OAAO,EAAE;AACtK;;;AC5BA,SAAS,qBAAqB,4BAA+E;AAG7G,SAAS,4BAAAC,iCAAyD;AAE3D,SAAS,QAAQ,MAAmC;AACzD,SAAO,KAAK,MAAM,IAAI,OAAK,EAAE,SAAS,SAAS,EAAE,MAAM,QAAQ,MAAM,KAAK,KAAK,MAAM,EAAE,OAAM,EAAE,GAAG,EAAE,IAChG,EAAE,SAAS,cAAc,KAAK,UAAU,EAAE,KAAK,IAC/C,EAAE,SAAS,mBAAmB,KAAK,eAAe,EAAE,KAAK,IACzD,EAAE,MAAM,aAAa,IAAI,KAAK,UAAU,EAAE,KAAK,EAAG,IAAI,MAAM,KAAK,UAAU,EAAE,KAAK,EAAG,MAAM,OAAO,KAAK,UAAU,EAAE,KAAK,EAAG,MAAM,CAAC;AACxI;AACO,SAAS,UAAU,GAAuB,MAA0B,OAAuB,QAChG,WAAwE;AACxE,QAAM,SAASA,0BAAyB,EAAE,IAAI;AAAG,MAAI,WAAW,GAAG,QAAQ;AAAG,QAAM,WAAW,oBAAI,IAAmB;AACtH,QAAM,SAAS,YAA4B;AAAE,cAAU,OAAO;AAAG,UAAM,IAAI,MAAM,8BAA8B;AAAA,EAAG;AAClH,iBAAe,YAAY;AACzB,cAAU,MAAM;AAChB,UAAM,aAAa,OAAO,QAAQ,KAAK,IAAI,EAAE,OAAO,CAAC,CAAC,EAAC,CAAC,MAAM,OAAO,MAAM,YAAY,EAAE,eAAe,OAAO;AAC/G,QAAI,CAAC,WAAW,OAAQ;AACxB,UAAM,SAAS,WAAW,KAAK,CAAC,CAAC,CAAC,MAAM,MAAM,YAAY,IAAI,qBAAqB,MAAM,EAAE,KAAK,MAAM,KAAK,EAAE,OAAO,KAAK,OAAO,WAAW,KAAK,WAAW,KAAI,oBAAI,KAAK,GAAE,YAAY,EAAE,CAAC,CAAC,IAAI,EAAE,YAAW,GAAE,cAAa,EAAE;AAC5N,cAAU,MAAM;AAChB,eAAW,CAAC,KAAI,GAAG,KAAK,YAAY;AAAE,YAAM,MAAM,QAAQ,eAAe,QAAQ,QAAQ,kBAAkB,OAAO,aAAa,OAAO;AACpI,UAAI,OAAQ,IAAqB,IAAK,OAAM,IAAI,oBAAoB,KAAsB,IAAqB,KAAI,GAAG;AAAA,IAAG;AAAA,EAC7H;AACA,SAAO;AAAA,IAAE,GAAG;AAAA,IAAW,QAAQ,KAAK;AAAA,IAClC,OAAO,EAAE,QAAQ,QAAQ,cAAc,QAAQ,WAAW,UAAU,MAAM,OAAO,gBAAgB,MAAM,CAAC,GAAG,aAAa,MAAM,CAAC,GAAG,QAAQ,GAAG,iBAAiB,MAAM,OAAU;AAAA,IAC9K,MAAM,IAAI,SAAuB,MAA4B;AAC3D,UAAI;AACF,kBAAU,MAAM;AAAG,cAAM,UAAU;AAAG,kBAAU,MAAM;AACtD,cAAM,OAAO,OAAO,EAAE,QAAQ,GAAG,SAAS,OAAO,WAAW,GAAG,eAAe,OAAO,WAAW;AAChG,cAAM,WAAW,EAAE,WAAW,QAAQ,WAAW,GAAI,QAAQ,YAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC,GAAI,GAAI,QAAQ,UAAU,SAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC,GAAI,GAAI,QAAQ,gBAAgB,SAAY,EAAE,aAAa,QAAQ,YAAY,IAAI,CAAC,EAAG;AACtQ,cAAM,IAAI,MAAM,OAAO,IAAI;AAAA,UAAE;AAAA,UAAO;AAAA,UAAQ,WAAW,KAAK;AAAA,UAC1D,MAAM,EAAE,MAAM,MAAM,KAAK,MAAM,GAAI,KAAK,eAAe,EAAE,cAAc,KAAK,aAAa,IAAI,CAAC,GAAI,WAAW;AAAA,YAC3G,OAAO,KAAK;AAAA,YAAO,WAAW,KAAK;AAAA,YAAW;AAAA,YAAc,aAAa,OAAO,WAAW;AAAA,YAAG,WAAW,OAAO,WAAW;AAAA,YAAG;AAAA,YAAQ,cAAc,OAAO,WAAW;AAAA,YACtK,eAAe,KAAK,QAAS;AAAA,YAAe,eAAe,KAAK;AAAA,YAAe,uBAAuB;AAAA,YAAoB,QAAQ,EAAC,MAAK,KAAK,OAAO,MAAK,aAAY,KAAK,OAAO,YAAW;AAAA,YAC5L,OAAO,QAAQ;AAAA,YAAO,eAAe,QAAQ,eAAe;AAAA,YAAY,cAAc,EAAE;AAAA,YACxF,QAAQ,EAAE,OAAO,OAAO,OAAK,EAAE,MAAM,aAAa,QAAQ,MAAM,YAAY,EAAE,MAAM,OAAO,QAAQ,MAAM,EAAE;AAAA,YAAG;AAAA,YAC9G,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,YAAG,YAAY,KAAK;AAAA,YAAY,YAAY,EAAE,MAAM,KAAK,MAAM,WAAW,EAAE,WAAW,mBAAmB,EAAE,kBAAkB;AAAA,UAAE,EAAE;AAAA,UACvK,aAAa,YAAY;AAAE,sBAAU,MAAM;AAAG,mBAAO;AAAA,UAAS;AAAA,QAAE,CAAC;AACnE,kBAAU,MAAM;AAChB,YAAI,EAAE,WAAW,YAAa,OAAM,IAAI,MAAM,oCAAoC;AAClF,gBAAQ,KAAK,IAAI,OAAO,EAAE,YAAY,UAAU;AAAG,mBAAW,OAAO,EAAE,YAAY,YAAa,UAAS,IAAI,GAAG;AAChH,cAAM,QAAQ,EAAE,QAAQ,QAAQ,WAAW;AAC3C,cAAM,WAAW,EAAE,YAAY,UAAU,KAAK,OAAK,EAAE,YAAY,EAAE,eAAe,OAAO;AACzF,YAAI,EAAE,OAAO,YAAY,aAAa,SAAU,QAAO;AAAA,UAAE;AAAA,UAAQ;AAAA,UAAO,MAAK;AAAA,UAAI,WAAU,CAAC;AAAA,UAAG,WAAU,CAAC;AAAA,UAAG,gBAAe,CAAC;AAAA,UAAG,QAAO,CAAC;AAAA,UAAG,MAAM,EAAE,OAAO;AAAA,UACxJ,OAAO,IAAI,oBAAoB,SAAS,KAAI,SAAS,cAAa,SAAS,UAAU;AAAA,QAAE;AACzF,YAAI,KAAK,SAAS,cAAc,EAAE,OAAO,YAAY,aAAa,CAAC,EAAE,MAAM,KAAK,KAAK,GAAI,OAAM,IAAI,MAAM,4BAA4B;AACrI,YAAI,EAAE,OAAO,YAAY,aAAa,EAAE,OAAO,YAAY,YAAa,QAAO,EAAE,QAAO,OAAM,MAAK,IAAG,WAAU,CAAC,GAAE,WAAU,CAAC,GAAE,gBAAe,CAAC,GAAE,QAAO,CAAC,GAAE,MAAK,EAAE,OAAO,WAAW;AACrL,YAAI,CAAC,EAAE,QAAQ,EAAE,OAAO,YAAY,UAAW,OAAM,IAAI,MAAM,6BAA6B;AAC5F,eAAO;AAAA,UAAE;AAAA,UAAQ;AAAA,UAAO,MAAK,EAAE,KAAK;AAAA,UAAM,MAAK,EAAE,KAAK;AAAA,UAAM,WAAU,EAAE,KAAK;AAAA,UAAW,gBAAe,EAAE,KAAK;AAAA,UAAgB,QAAO,QAAQ,EAAE,IAAI;AAAA,UACjJ,WAAU,EAAE,KAAK,UAAU,IAAI,QAAM,EAAE,IAAG,EAAE,IAAG,MAAK,EAAE,MAAK,OAAM,EAAE,OAAO,GAAI,EAAE,YAAY,EAAE,WAAU,eAAe,IAAI,CAAC,EAAG,EAAE;AAAA,QAAE;AAAA,MACvI,SAAS,GAAG;AAAE,YAAI,EAAE,aAAa,qBAAsB,WAAU,OAAO;AAAG,cAAM;AAAA,MAAG;AAAA,IACtF;AAAA,EACF;AACF;;;AF9CA,IAAM,UAAU,OAAyB,EAAE,QAAO,0BAA0B;AAC5E,IAAM,cAAc,MAAM,IAAI,MAAM,sCAAsC;AACnE,SAAS,yBAAyB,OAA+C;AACtF,QAAM,IAAI,OAAO,KAAK;AACtB,QAAM,UAAU,CAAC,UAA6B,EAAE,OAAM,KAAK,OAAM,QAAO,KAAK,KAAI,WAAU,KAAK,WAAU,aAAY,KAAK,gBAAe,aAAY,KAAK,QAAS,kBAAkB;AACtL,iBAAe,KAAK,OAAa,KAA4C;AAC3E,UAAM,IAAI,gBAAgB,KAAK,GAAG,IAAI,qBAAqB,GAAG,GAAG,IAAI,MAAM,EAAE,WAAW,IAAI,GAAE,CAAC;AAC/F,QAAI,CAAC,EAAG,QAAO;AACf,QAAI,EAAE,WAAW,WAAY,QAAO,EAAE,QAAO,EAAE,WAAW,YAAY,EAAE,MAAM,cAAa,oBAAI,KAAK,GAAE,YAAY,IAAI,gBAAgB,0BAA0B;AAChK,QAAI,EAAE,gBAAgB,CAAC,EAAE,MAAM,QAAS,QAAO,QAAQ;AACvD,UAAM,OAAO,MAAM,EAAE,KAAK,MAAM,IAAI,GAAE,CAAC;AACvC,QAAI,CAAC,QAAQ,KAAK,WAAW,YAAY,CAAC,eAAe,KAAK,OAAM,EAAE,KAAK,EAAG,QAAO,QAAQ;AAC7F,QAAI;AACJ,QAAI;AAAE,eAAS,MAAM,EAAE,YAAY,IAAI,GAAE,CAAC;AAAA,IAAG,SAAS,GAAG;AAAE,UAAI,aAAa,2BAA4B,QAAO,EAAE,QAAO,cAAc;AAAG,YAAM;AAAA,IAAG;AAClJ,QAAI,CAAC,UAAU,OAAO,UAAU,eAAe,CAAC,eAAe,OAAO,SAAQ,QAAQ,KAAK,KAAK,CAAC,KAAK,OAAO,QAAQ,YAAY,aAAa,OAAO,OAAO,OAAO,WAAW,OAAQ,QAAO,EAAE,QAAO,cAAc;AACpN,UAAM,YAAY,MAAM,EAAE,KAAK,WAAW,IAAI,GAAE,CAAC;AACjD,QAAI,CAAC,aAAa,UAAU,kBAAkB,UAAU,gBAAgB,UAAU,eAAe,SAAU,QAAO,QAAQ;AAC1H,QAAI;AACF,YAAM,OAAO,KAAK,MAAM,OAAO,OAAO,OAAO,IAAI;AACjD,YAAM,IAAI,KAAK;AACf,UAAI,KAAK,YAAY,8BAA8B,KAAK,WAAW,KAAK,MAAM,MAAM,KAAK,aAAa,KAAK,MAAM,QAAS,yBAAyB,CAAC,KAAK,EAAE,WAAW,KAAK,MAAM,MAAM,EAAE,YAAY,UAAU,WAAW,CAAC,CAAC,aAAY,iBAAiB,EAAE,SAAS,EAAE,cAAc,KAAK,EAAE,OAAO,SAAS,eAAe,CAAC,MAAM,QAAQ,EAAE,MAAM,MAAM,KAAK,EAAE,MAAM,OAAO,KAAK,OAAK,EAAE,SAAS,WAAW,KAAK,CAAC,OAAO,cAAc,EAAE,KAAK,KAAK,EAAE,QAAQ,KAAK,CAAC,OAAO,SAAS,EAAE,UAAU,KAAK,EAAE,aAAa,EAAG,QAAO,EAAE,QAAO,cAAc;AACnhB,iCAA2B,EAAE,QAAO,SAAQ,OAAM,EAAE,MAAM,CAAC;AAC3D,aAAO,EAAE,QAAO,aAAY,QAAO,EAAE,GAAG,GAAE,UAAS,KAAK,GAAE,UAAS,KAAK;AAAA,IAC1E,QAAQ;AAAE,aAAO,EAAE,QAAO,cAAc;AAAA,IAAG;AAAA,EAC7C;AACA,WAAS,IAAI,OAAoD;AAC/D,UAAM,OAAO,uBAAuB,MAAM,IAAI,GAAG,MAAM,KAAK;AAC5D,UAAM,OAAO,EAAE,QAAO,gBAAgB,MAAM,MAAM,GAAE,GAAI,MAAM,UAAU,EAAC,SAAQ,MAAM,QAAO,IAAI,CAAC,GAAG,GAAI,MAAM,cAAc,EAAC,aAAY,MAAM,YAAW,IAAI,CAAC,EAAG,GAAG,OAAO,MAAM,WAAW,WAAW,MAAM;AAChN,QAAI,CAAC,OAAO,IAAI,mBAAmB,EAAE,kBAAkB,IAAI,0BAA0B,EAAE,yBAAyB,IAAI,sBAAsB,EAAE,qBAAqB,KAAK,kBAAkB,EAAE,iBAAiB,CAAC,eAAe,KAAK,MAAK,EAAE,IAAI,KAAK,KAAK,WAAW,EAAE,YAAY,KAAK,mBAAmB,KAAK,OAAO,eAAe,OAAO,SAAS,WAAY,OAAM,IAAI,uBAAuB;AAC9X,UAAM,aAAa,IAAI,gBAAgB;AAAG,QAAI,YAAY,OAAO,WAAW,GAAG,SAAS,OAAO;AAC/F,UAAM,SAAS,MAAM;AAAE,kBAAY;AAAM,iBAAW,MAAM;AAAA,IAAG;AAC7D,UAAM,QAAQ,MAAM;AAAE,UAAI,aAAa,UAAU,WAAW,OAAO,WAAY,aAAa,KAAK,IAAI,KAAK,KAAK,MAAM,KAAK,UAAU,EAAI,OAAM,YAAY;AAAA,IAAG;AAC7J,aAAS,MAAS,IAA8B;AAC9C,YAAM,KAAK,YAAY;AAAE,cAAM;AAAG;AAAY,YAAI;AAAE,iBAAO,MAAM,GAAG;AAAA,QAAG,SAAS,GAAG;AAAE,iBAAO;AAAG,gBAAM;AAAA,QAAG,UAAE;AAAU;AAAA,QAAY;AAAA,MAAE,GAAG;AACrI,WAAK,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAG,aAAO;AAAA,IACjC;AACA,UAAM,QAAQ,MAAM,OAAO;AAC3B,UAAM,QAAQ,WAAW,OAAM,EAAE,YAAY;AAAG,QAAI;AACpD,UAAM,YAAY,IAAI,QAA0B,aAAW,WAAW,OAAO,iBAAiB,SAAQ,MAAM,QAAQ,QAAQ,CAAC,GAAE,EAAC,MAAK,KAAI,CAAC,CAAC;AAC3I,cAAU,iBAAiB,SAAQ,OAAM,EAAC,MAAK,KAAI,CAAC;AAAG,QAAI,UAAU,QAAS,OAAM;AACpF,UAAM,OAAO,QAAQ;AAAG,SAAK,KAAK,MAAM,MAAM;AAAA,IAAC,CAAC;AAChD,WAAO,QAAQ,KAAK,CAAC,MAAK,SAAS,CAAC,EAAE,QAAQ,MAAM;AAAE,eAAS;AAAM,mBAAa,KAAK;AAAG,mBAAa,QAAQ;AAAG,gBAAU,oBAAoB,SAAQ,KAAK;AAAA,IAAG,CAAC;AACjK,mBAAe,qBAAqB;AAAE,UAAI,WAAW;AAAE,YAAI;AAAE,gBAAM,EAAE,WAAW,cAAc,SAAS;AAAA,QAAG,QAAQ;AAAA,QAAwD;AAAA,MAAE;AAAA,IAAE;AAC9K,mBAAe,UAAoC;AACjD,UAAI;AACF,cAAM;AAAG,cAAM,IAAI,MAAM,EAAE,WAAW,MAAM,IAAI;AAChD,YAAI,EAAE,WAAW,UAAW,aAAY,EAAE;AAC1C,cAAM;AACN,YAAI,EAAE,WAAW,OAAQ,QAAO,EAAE,QAAO,QAAO,SAAQ,EAAE,QAAQ;AAClE,YAAI,EAAE,WAAW,WAAY,QAAQ,MAAM,KAAK,KAAK,OAAM,KAAK,GAAG,KAAM,QAAQ;AACjF,mBAAW,WAAW,OAAM,KAAK,IAAI,GAAE,KAAK,MAAM,KAAK,UAAU,IAAE,KAAK,IAAI,CAAC,CAAC;AAC9E,cAAM,QAAQ,MAAM,EAAE,KAAK,MAAM,MAAM,IAAI;AAAG,cAAM;AACpD,YAAI,MAAM,WAAW,aAAa,CAAC,eAAe,MAAM,OAAO,OAAM,IAAI,EAAG,OAAM,YAAY;AAC9F,cAAM,WAAW,MAAM,EAAE,YAAY,QAAQ,QAAQ,IAAI,CAAC;AAAG,cAAM;AACnE,YAAI,SAAS,UAAU,UAAW,OAAM,YAAY;AACpD,cAAM,UAAU,gBAAgB,MAAM,KAAK,CAAC;AAAG,cAAM;AACrD,YAAI,QAAQ,SAAS,UAAU,KAAK,UAAU,OAAO,EAAE,SAAS,EAAE,cAAe,OAAM,IAAI,UAAU,4BAA4B;AACjI,cAAM,OAAO,YAAY,CAAC,GAAG,eAAe,EAAE;AAC9C,cAAM,UAAU,OAAU,OAAiC;AAAE,gBAAM;AAAG,cAAI;AAAE,kBAAMC,UAAS,MAAM,GAAG;AAAG,kBAAM;AAAG,mBAAOA;AAAA,UAAQ,SAAS,GAAG;AAAE,mBAAO;AAAG,kBAAM;AAAA,UAAG;AAAA,QAAE;AAElK,aAAK,SAAS,KAAK,SAAS,CAAC,GAAG,IAAI,OAAK,OAAO,YAAY,OAAO,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,EAAC,EAAE,MAAM,OAAO,OAAO,UAAU,EAAE,IAAI,CAAC,CAAC,KAAI,EAAE,MAAM,CAAC,KAAI,UAAU,SAAmB;AAAE,gBAAM;AAAG,cAAI;AAAE,kBAAM,IAAI,MAAO,GAAiC,GAAG,IAAI;AAAG,kBAAM;AAAG,mBAAO;AAAA,UAAG,SAAS,GAAG;AAAE,mBAAO;AAAG,kBAAM;AAAA,UAAG;AAAA,QAAE,CAAC,CAAC,CAAC,CAAC;AACrT,aAAK,WAAW,EAAE,GAAG,cAAc,MAAK,CAAC,GAAEC,QAAO,QAAQ,MAAM,aAAa,KAAK,GAAEA,GAAE,CAAC,GAAG,QAAO,CAAC,GAAEA,KAAG,SAAS,QAAQ,MAAM,aAAa,OAAO,GAAEA,KAAG,IAAI,CAAC,GAAG,OAAM,CAAC,GAAEA,QAAO,aAAa,MAAM,GAAEA,GAAE,GAAG,mBAAkB,CAAC,GAAEA,KAAGC,UAAS,aAAa,kBAAkB,GAAED,KAAGC,KAAI,EAAE;AACpR,YAAI,EAAE,OAAQ,MAAK,SAAS,EAAE,OAAM,IAAI,SAAS;AAAE,gBAAM,UAAU,WAAW,QAAO,EAAE,mBAAmB,GAAI;AAAG,iBAAO,QAAQ,MAAM,EAAE,OAAQ,MAAM,GAAG,IAAI,CAAC,EAAE,QAAQ,MAAM,aAAa,OAAO,CAAC;AAAA,QAAG,EAAE;AACxM,YAAI,EAAE,OAAO,OAAQ,MAAK,QAAQ,EAAE,GAAG,EAAE,OAAM,QAAO,EAAC,MAAK,IAAI,SAAS,QAAQ,MAAM,EAAE,MAAO,OAAQ,KAAK,GAAG,IAAI,CAAC,EAAC,EAAE;AACxH,cAAM,UAAU,UAAU,GAAE,MAAK,MAAM,OAAM,WAAW,QAAO,EAAC,OAAM,QAAO,MAAK,CAAC;AACnF,cAAM,OAAO,MAAM,YAAYC,iBAAgB,MAAK,IAAI,GAAG,EAAE,OAAM,KAAK,OAAM,WAAU,KAAK,WAAU,OAAM,SAAQ,GAAG,MAAK,QAAO,WAAW,OAAO,GAAE,KAAK,MAAK,SAAQ,OAAO;AACjL,cAAM;AACN,YAAI,aAAa,KAAK,CAAC,CAAC,aAAY,iBAAiB,EAAE,SAAS,KAAK,cAAc,EAAG,OAAM,YAAY;AACxG,cAAM,SAAS,MAAM,EAAE,KAAK,WAAW,IAAI,KAAK,OAAM,KAAK,GAAG;AAAG,cAAM;AACvE,YAAI,CAAC,UAAU,OAAO,kBAAkB,OAAO,gBAAgB,OAAO,YAAY,KAAK,QAAS,OAAM,YAAY;AAClH,cAAM,EAAE,KAAK,MAAM,MAAM,MAAM,KAAK;AAAG,cAAM;AAC7C,cAAM,SAAS,EAAE,SAAQ,WAAmB,YAAW,KAAK,YAAW,QAAO,EAAC,QAAO,QAAgB,MAAK,KAAK,UAAU,EAAC,SAAQ,4BAA2B,QAAO,KAAK,IAAG,UAAS,IAAK,uBAAsB,QAAO,KAAI,CAAC,EAAC,EAAE;AAChO,cAAM,EAAE,YAAY,IAAI,KAAK,OAAM,KAAK,KAAI,MAAM;AAAG,cAAM;AAC3D,cAAM,QAAQ,MAAM,EAAE,YAAY,IAAI,KAAK,OAAM,KAAK,GAAG;AAAG,cAAM;AAClE,YAAI,OAAO,UAAU,eAAe,CAAC,eAAe,MAAM,SAAQ,QAAQ,IAAI,CAAC,KAAK,CAAC,eAAe,MAAM,QAAO,MAAM,EAAG,OAAM,YAAY;AAC5I,YAAI;AAAE,gBAAM,EAAE,WAAW,OAAO,SAAU;AAAA,QAAG,QACvC;AAEJ,gBAAM,WAAW,MAAM,EAAE,WAAW,IAAI,KAAK,OAAM,KAAK,GAAG;AAC3D,cAAI,CAAC,YAAY,SAAS,WAAW,cAAc,SAAS,gBAAgB,CAAC,eAAe,SAAS,OAAM,IAAI,EAAG,OAAM,YAAY;AAAA,QACtI;AACA,eAAO,EAAC,QAAO,aAAY,QAAO,MAAK,UAAS,MAAK;AAAA,MACvD,QAAQ;AAAE,eAAO;AAAG,cAAM,mBAAmB;AAAG,eAAO,QAAQ;AAAA,MAAG;AAAA,IACpE;AAAA,EACF;AACA,SAAO,EAAC,KAAI,KAAI;AAClB;","names":["createInternals","createGovernedStepRunner","result","id","opts","createInternals"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/execution.ts","../src/input.ts","../src/observation.ts","../src/stream.ts"],"sourcesContent":["import { equalExecution, ExecutionConflictError, ExecutionResultPolicyError, normalizeExecutionEvidence, settlementIdentifier, settlementScope, type ExecutionResultRecord, type Scope } from \"@alma-harness/core\";\nimport { normalizeOperationRoot, type OperationRootInput, type OperationSessionFence } from \"@alma-harness/execution\";\nimport { createInternals, NO_EMIT, runTurnBody } from \"@alma-harness/loop/internal\";\nimport type { TurnResult } from \"@alma-harness/loop\";\nimport { engineConfig, config } from \"./config\";\nimport { execution } from \"./execution\";\nimport { claimCanonical, existingAdmission, normalizeTurnInput } from \"./input\";\nimport type { ModelChoice } from \"@alma-harness/core\";\nexport { conversationRootKey, createConversationDescriptor, type ConversationDescriptorConfig } from \"./input\";\nimport type { ConversationConfig, ConversationInput, ConversationRunner, ConversationView } from \"./types\";\nexport type { SimpleConversationInput, ConversationConfig, ConversationInput, ConversationRunner, ConversationView, ConversationTool, ConversationToolCtx } from \"./types\";\nimport { observation, type Observation } from \"./observation\";\nexport { ConversationStreamResyncError } from \"./stream\";\nexport type { ConversationEvent, ConversationStream } from \"./types\";\nconst pending = (): ConversationView => ({ status:\"reconciliation_required\" });\nconst interrupted = () => new Error(\"Conversation requires reconciliation\");\nexport function createConversationRunner(value: ConversationConfig): ConversationRunner {\n const c = config(value);\n const binding = (root:OperationRootInput) => ({ scope:root.scope,callId:root.key,sessionId:root.sessionId,sensitivity:root.maxSensitivity,retentionMs:root.request!.resultRetentionMs });\n async function read(scope:Scope, key:string): Promise<ConversationView|null> {\n const s = settlementScope(scope), k = settlementIdentifier(key), a = await c.admissions.get(s,k);\n if (!a) return null;\n if (a.status !== \"released\") return { status:a.status === \"active\" && a.input.deadlineAt > new Date().toISOString() ? \"in_progress\" : \"reconciliation_required\" };\n if (a.resolutionId || !a.input.request) return pending();\n const root = await c.step.trees.get(s,k);\n if (!root || root.status !== \"closed\" || !equalExecution(root.input,a.input)) return pending();\n let stored:ExecutionResultRecord|null;\n try { stored = await c.rootResults.get(s,k); } catch (e) { if (e instanceof ExecutionResultPolicyError) return { status:\"unavailable\" }; throw e; }\n if (!stored || stored.state !== \"available\" || !equalExecution(stored.binding,binding(root.input)) || stored.result?.outcome !== \"success\" || stored.result.output.format !== \"json\") return { status:\"unavailable\" };\n const financial = await c.step.accounting.get(s,k);\n if (!financial || financial.reservedCalls !== financial.settledCalls || financial.rootStatus !== \"closed\") return pending();\n try {\n const data = JSON.parse(stored.result.output.text) as { version:string; rootId:string; contract:string; result:TurnResult };\n const r = data.result;\n if (data.version !== \"governed-conversation-v1\" || data.rootId !== root.input.id || data.contract !== root.input.request!.resultContractVersion || !r || r.turnId !== root.input.id || r.costUsd !== financial.costUsd || ![\"completed\",\"budget_exceeded\"].includes(r.terminalReason) || r.reply?.role !== \"assistant\" || !Array.isArray(r.reply.blocks) || r.reply.blocks.some(b => b.type === \"reasoning\") || !Number.isSafeInteger(r.steps) || r.steps < 0 || !Number.isFinite(r.durationMs) || r.durationMs < 0) return { status:\"unavailable\" };\n normalizeExecutionEvidence({ status:\"known\",usage:r.usage });\n return { status:\"completed\",result:{ ...r,replayed:true },replayed:true };\n } catch { return { status:\"unavailable\" }; }\n }\n function run(input:ConversationInput, mode: \"exact\" | \"canonical\", observer?: Observation): Promise<ConversationView> {\n const root = normalizeOperationRoot(input.root), req = root.request;\n const opts = { intent:structuredClone(input.intent),...(input.trigger ? {trigger:input.trigger} : {}),...(input.toolProfile ? {toolProfile:input.toolProfile} : {}) }, load = input.loadInput, external = input.signal;\n if (!req || req.configRevision !== c.configRevision || req.resultContractVersion !== c.resultContractVersion || req.resultRetentionMs !== c.resultRetentionMs || root.policyVersion !== c.policyVersion || !equalExecution(root.caps,c.caps) || root.maxCalls > c.maxCalls || root.maxSensitivity !== opts.intent.sensitivity || typeof load !== \"function\") throw new ExecutionConflictError();\n const controller = new AbortController(); let uncertain = false, children = 0, sealed = false, admission:OperationSessionFence|undefined;\n const poison = () => { uncertain = true; controller.abort(); };\n const check = () => { if (uncertain || sealed || controller.signal.aborted || (admission && Date.now() >= Date.parse(root.deadlineAt))) throw interrupted(); };\n function track<T>(fn:()=>Promise<T>):Promise<T> {\n const p = (async () => { check(); children++; try { return await fn(); } catch (e) { poison(); throw e; } finally { children--; } })();\n void p.catch(() => {}); return p;\n }\n const abort = () => poison();\n const timer = setTimeout(abort,c.runTimeoutMs); let deadline:ReturnType<typeof setTimeout>|undefined;\n const cancelled = new Promise<ConversationView>(resolve => controller.signal.addEventListener(\"abort\",() => resolve(pending()),{once:true}));\n external?.addEventListener(\"abort\",abort,{once:true}); if (external?.aborted) abort();\n const work = execute(); void work.catch(() => {});\n return Promise.race([work,cancelled]).finally(() => { sealed = true; clearTimeout(timer); clearTimeout(deadline); external?.removeEventListener(\"abort\",abort); });\n async function uncertainAdmission() { if (admission) { try { await c.admissions.markUncertain(admission); } catch { /* Occupancy survives this failed acknowledgement. */ } } }\n async function execute():Promise<ConversationView> {\n try {\n check();\n let mainChoice: ModelChoice | undefined;\n {\n const existing = () => existingAdmission(c.admissions, root, mode === \"canonical\", check);\n if (await existing()) return (await read(root.scope,root.key)) ?? pending();\n try {\n mainChoice = structuredClone(c.policy.resolve(structuredClone(opts.intent)));\n if (!Object.hasOwn(c.step.clients, mainChoice.model.provider) || !c.step.clients[mainChoice.model.provider]) mainChoice = undefined;\n } catch { mainChoice = undefined; }\n check();\n if (!mainChoice) {\n if (await existing()) return (await read(root.scope,root.key)) ?? pending();\n return { status:\"not_admitted\",reason:\"routing_unavailable\" };\n }\n }\n const a = mode === \"canonical\" ? await claimCanonical(c.admissions, root, check) : await c.admissions.claim(root);\n if (a.status === \"claimed\") admission = a.fence;\n check();\n if (a.status === \"busy\") return { status:\"busy\",rootKey:a.rootKey };\n if (a.status === \"existing\") return (await read(root.scope,root.key)) ?? pending();\n deadline = setTimeout(abort,Math.max(0,Date.parse(root.deadlineAt)-Date.now()));\n const claim = await c.step.trees.claim(root); check();\n if (claim.status !== \"claimed\" || !equalExecution(claim.record.input,root)) throw interrupted();\n const prepared = await c.rootResults.prepare(binding(root)); check();\n if (prepared.state !== \"pending\") throw interrupted();\n const message = structuredClone(await load()); check();\n if (message.role !== \"user\" || JSON.stringify(message).length > c.maxInputChars) throw new TypeError(\"Invalid conversation input\");\n const base = engineConfig(c), sessionStore = c.sessions;\n const guarded = async <T>(fn:()=>Promise<T>):Promise<T> => { check(); try { const result = await fn(); check(); return result; } catch (e) { poison(); throw e; } };\n // Every effect-capable hook and all asynchronous context sources are per-turn closures.\n base.hooks = (base.hooks ?? []).map(h => Object.fromEntries(Object.entries(h).filter(([,fn]) => typeof fn === \"function\").map(([key,fn]) => [key,async (...args:unknown[]) => { check(); try { const r = await (fn as (...a:unknown[])=>unknown)(...args); check(); return r; } catch (e) { poison(); throw e; } }])));\n base.sessions = { ...sessionStore, load:(s,id) => guarded(() => sessionStore.load(s,id)), append:(s,id,msgs) => guarded(() => sessionStore.append(s,id,msgs)), erase:(s,id) => sessionStore.erase(s,id), expireToolTraffic:(s,id,opts) => sessionStore.expireToolTraffic(s,id,opts) };\n // assembleRecall owns the deadline and clears it on abort, even if the source never settles.\n if (c.recall) base.recall = { build:(...args) => guarded(() => c.recall!.build(...args)) };\n if (c.media?.source) base.media = { ...c.media,source:{load:(...args) => guarded(() => c.media!.source!.load(...args))} };\n const runtime = execution(c,root,claim.fence,controller.signal,{check,poison,track,mainChoice},observer);\n const body = await runTurnBody(createInternals(base), { scope:root.scope,sessionId:root.sessionId,input:message,...opts,signal:controller.signal },observer?.emit ?? NO_EMIT,runtime);\n check();\n if (children !== 0 || ![\"completed\",\"budget_exceeded\"].includes(body.terminalReason)) throw interrupted();\n const totals = await c.step.accounting.get(root.scope,root.key); check();\n if (!totals || totals.reservedCalls !== totals.settledCalls || totals.costUsd !== body.costUsd) throw interrupted();\n await c.step.trees.close(claim.fence); check();\n const result = { outcome:\"success\" as const,stopReason:body.stopReason,output:{format:\"json\" as const,text:JSON.stringify({version:\"governed-conversation-v1\",rootId:root.id,contract:req!.resultContractVersion,result:body})} };\n await c.rootResults.put(root.scope,root.key,result); check();\n const final = await c.rootResults.get(root.scope,root.key); check();\n if (final?.state !== \"available\" || !equalExecution(final.binding,binding(root)) || !equalExecution(final.result,result)) throw interrupted();\n try { await c.admissions.finish(admission!); }\n catch {\n // Finish is attempted only AFTER proven local quiescence and durable writes.\n const released = await c.admissions.get(root.scope,root.key);\n if (!released || released.status !== \"released\" || released.resolutionId || !equalExecution(released.input,root)) throw interrupted();\n }\n return {status:\"completed\",result:body,replayed:false};\n } catch (e) {\n if (!admission && e instanceof ExecutionConflictError) throw e;\n poison(); await uncertainAdmission(); return pending();\n }\n }\n }\n return {read,streamTurn(value) {\n const normalized = normalizeTurnInput(c, value);\n const observer = observation(c, normalized.input.root, read);\n return observer.start(run(normalized.input, normalized.canonical ? \"canonical\" : \"exact\", observer));\n },async runTurn(value) {\n const normalized = normalizeTurnInput(c, value);\n return run(normalized.input, normalized.canonical ? \"canonical\" : \"exact\");\n }};\n}\n","import { normalizeBudgetCaps, settlementIdentifier as id, type ToolDefinition } from \"@alma-harness/core\";\nimport { createInternals } from \"@alma-harness/loop/internal\";\nimport type { LoopConfig } from \"@alma-harness/loop/internal\";\nimport { createGovernedStepRunner } from \"@alma-harness/single-call\";\nimport type { ConversationConfig } from \"./types\";\nexport function config(value: ConversationConfig): ConversationConfig {\n if (typeof value.step.spend?.peek !== \"function\") throw new TypeError(\"Conversation requires a spend reader\");\n if (value.rootResults === value.step.results) throw new TypeError(\"Conversation results require a separate physical namespace\");\n for (const [key, max] of Object.entries({ runTimeoutMs: 300000, resultRetentionMs: 31536000000, maxCalls: 512, maxInputChars: 64000000 })) {\n const n = value[key as keyof ConversationConfig]; if (!Number.isSafeInteger(n) || Number(n) < 1 || Number(n) > max) throw new TypeError(`Invalid conversation ${key}`);\n }\n for (const n of [value.maxSteps ?? 24, value.maxDelegateDepth ?? 2, value.maxTokens ?? 8192]) if (!Number.isSafeInteger(n) || n < 1) throw new TypeError(\"Invalid conversation technical limit\");\n for (const key of [\"policyVersion\", \"priceVersion\", \"configRevision\", \"resultContractVersion\"] as const) id(value[key]);\n if (!Array.isArray(value.consumers) || value.consumers.length > 16) throw new TypeError(\"Invalid consumers\");\n for (const client of Object.values(value.step.clients)) if (!client || client.dispatchPolicy !== \"single\" || typeof client.validate !== \"function\") throw new TypeError(\"Conversation requires single-dispatch clients\");\n const c = { ...value, caps: normalizeBudgetCaps(value.caps), prices: structuredClone(value.prices), consumers: [...new Set(value.consumers.map(id))].sort(),\n system: structuredClone(value.system), step: { ...value.step, clients: { ...value.step.clients } },\n ...(value.providerTools ? { providerTools: structuredClone(value.providerTools) } : {}),\n ...(value.profiles ? { profiles: structuredClone(value.profiles) } : {}),\n ...(value.tools ? { tools: value.tools.map(t => ({ ...t, ...(t.jsonSchema ? { jsonSchema: structuredClone(t.jsonSchema) } : {}) })) } : {}),\n ...(value.hooks ? { hooks: value.hooks.map(h => ({ ...h })) } : {}),\n ...(value.longContext ? { longContext: { ...value.longContext } } : {}), ...(value.media ? { media: { ...value.media } } : {}) };\n createGovernedStepRunner(c.step);\n createInternals(engineConfig(c)); // Registry/config errors precede claims.\n return c;\n}\nexport function engineConfig(c: ConversationConfig): LoopConfig {\n // The internal governed dispatch branch supplies the declared extended gateway.\n return { ...c, ...(c.tools ? { tools: c.tools as ToolDefinition[] } : {}), clients: c.step.clients, audit: c.step.audit };\n}\n","import { BudgetExceededError, equalExecution, normalizeSpendTotals, type Block, type BudgetCapName, type ModelRequest } from \"@alma-harness/core\";\nimport type { OperationFence, OperationRootInput } from \"@alma-harness/execution\";\nimport type { StepOutcome, TurnExecution } from \"@alma-harness/loop/internal\";\nimport { createGovernedStepRunner, type GovernedStepOutput } from \"@alma-harness/single-call\";\nimport type { ConversationConfig } from \"./types\";\nimport type { Observation } from \"./observation\";\nexport function ordered(step: GovernedStepOutput): Block[] {\n return step.order.map(p => p.type === \"text\" ? { type: \"text\", text: step.text.slice(p.start,p.end) }\n : p.type === \"reasoning\" ? step.reasoning[p.index]!\n : p.type === \"provider_block\" ? step.providerBlocks[p.index]!\n : { type: \"tool_call\", id: step.toolCalls[p.index]!.id, name: step.toolCalls[p.index]!.name, input: step.toolCalls[p.index]!.input });\n}\nexport function execution(c: ConversationConfig, root: OperationRootInput, fence: OperationFence, signal: AbortSignal,\n lifecycle: Pick<TurnExecution,\"check\"|\"poison\"|\"track\"|\"mainChoice\">, observer?: Observation): TurnExecution {\n const runner = createGovernedStepRunner(c.step); let sequence = 0, spent = 0; const warnings = new Set<BudgetCapName>();\n async function preflight() {\n lifecycle.check();\n const configured = Object.entries(root.caps).filter(([,v]) => typeof v === \"object\" && v.onExceeded === \"block\");\n if (!configured.length) return;\n const totals = configured.some(([k]) => k !== \"perTurnUsd\") ? normalizeSpendTotals(await c.step.spend.peek({ scope: root.scope, sessionId: root.sessionId, at: new Date().toISOString() })) : { sessionUsd:0,tenantDayUsd:0 };\n lifecycle.check();\n for (const [key,cap] of configured) { const usd = key === \"perTurnUsd\" ? spent : key === \"perSessionUsd\" ? totals.sessionUsd : totals.tenantDayUsd;\n if (usd >= (cap as {usd:number}).usd) throw new BudgetExceededError(key as BudgetCapName,(cap as {usd:number}).usd,usd); }\n }\n return { ...lifecycle, turnId: root.id, ...(observer ? { observedStep: observer.main } : {}),\n guard: { preflight, spentUsd: () => spent, capsCrossed: () => [...warnings] },\n async run(request: ModelRequest, meta): Promise<StepOutcome> {\n try {\n lifecycle.check(); await preflight(); lifecycle.check();\n const slot = String(++sequence), callId = crypto.randomUUID(), operationKey = crypto.randomUUID();\n const controls = { maxTokens: request.maxTokens, ...(request.reasoning ? { reasoning: request.reasoning } : {}), ...(request.cache !== undefined ? { cache: request.cache } : {}), ...(request.temperature !== undefined ? { temperature: request.temperature } : {}) };\n const v = await runner.run({ fence, signal, rationale: meta.rationale,\n call: { slot, kind: meta.kind, ...(meta.parentCallId ? { parentCallId: meta.parentCallId } : {}), execution: {\n scope: root.scope, sessionId: root.sessionId, operationKey, operationId: crypto.randomUUID(), attemptId: crypto.randomUUID(), callId, settlementId: crypto.randomUUID(),\n inputRevision: root.request!.inputRevision, policyVersion: root.policyVersion, outputContractVersion: \"governed-step-v1\", intent: {tier:meta.intent.tier,sensitivity:meta.intent.sensitivity},\n model: request.model, requestedTier: request.serviceTier ?? \"standard\", priceVersion: c.priceVersion,\n prices: c.prices.filter(p => p.model.provider === request.model.provider && p.model.id === request.model.id), controls,\n occurredAt: new Date().toISOString(), deadlineAt: root.deadlineAt, governance: { caps: root.caps, consumers: c.consumers, resultRetentionMs: c.resultRetentionMs } } },\n loadRequest: async () => { lifecycle.check(); return request; } });\n lifecycle.check();\n if (v.status !== \"completed\") throw new Error(\"Model step requires reconciliation\");\n spent = Math.max(spent, v.rootReceipt.currentUsd); for (const cap of v.rootReceipt.newWarnings) warnings.add(cap);\n if (meta.kind === \"main\") observer?.bind({operationKey,callId});\n const usage = v.receipt.receipt.settlement.usage;\n const decision = v.rootReceipt.decisions.find(d => d.exceeded && d.onExceeded === \"block\");\n if (v.result.outcome === \"blocked\" && decision) return { callId, usage, text:\"\", toolCalls:[], reasoning:[], providerBlocks:[], blocks:[], stop: v.result.stopReason,\n error: new BudgetExceededError(decision.cap,decision.thresholdUsd,decision.currentUsd) };\n const evidence = v.record.evidence;\n if (meta.kind === \"main\" && evidence?.status === \"known\" && evidence.rejection) {\n const stored = await c.step.results.get(root.scope, callId); lifecycle.check();\n if (v.result.outcome !== \"refusal\" || v.result.stopReason !== \"context_window_exceeded\" ||\n !equalExecution(v.record.completion,{outcome:\"refusal\",stopReason:\"context_window_exceeded\"}) ||\n v.receipt.receipt.settlement.costUsd !== 0 || v.rootReceipt.costUsd !== 0 ||\n !stored || stored.state !== \"available\" || !equalExecution(stored.result,v.result) ||\n !equalExecution(stored.binding,{scope:root.scope,callId,sessionId:root.sessionId,sensitivity:meta.intent.sensitivity,retentionMs:c.resultRetentionMs})) throw new Error(\"Context refusal is unavailable\");\n return {callId,usage,text:\"\",toolCalls:[],reasoning:[],providerBlocks:[],blocks:[],stop:v.result.stopReason,contextRejected:true};\n }\n if (meta.kind === \"summary\" && (v.result.outcome !== \"success\" || !v.step?.text.trim())) throw new Error(\"Summary output is unusable\");\n if (v.result.outcome === \"refusal\" || v.result.outcome === \"truncated\") return { callId,usage,text:\"\",toolCalls:[],reasoning:[],providerBlocks:[],blocks:[],stop:v.result.stopReason };\n if (!v.step || v.result.outcome !== \"success\") throw new Error(\"Model output is unavailable\");\n return { callId, usage, text:v.step.text, stop:v.step.stop, reasoning:v.step.reasoning, providerBlocks:v.step.providerBlocks, blocks:ordered(v.step),\n toolCalls:v.step.toolCalls.map(t => ({ id:t.id,name:t.name,input:t.input, ...(t.malformed ? { malformed:\"Invalid JSON\" } : {}) })) };\n } catch (e) { if (!(e instanceof BudgetExceededError)) lifecycle.poison(); throw e; }\n },\n };\n}\n","import { createHash } from \"node:crypto\";\nimport { equalExecution, ExecutionConflictError, settlementIdentifier, settlementInstant, settlementScope, type Msg, type Scope } from \"@alma-harness/core\";\nimport { normalizeOperationRoot, type OperationRootInput, type OperationSessionClaim, type OperationSessionStore } from \"@alma-harness/execution\";\nimport type { ConversationConfig, ConversationInput, SimpleConversationInput } from \"./types\";\nexport type ConversationDescriptorConfig = Pick<ConversationConfig, \"caps\" | \"policyVersion\" | \"configRevision\" | \"resultContractVersion\" | \"resultRetentionMs\" | \"maxCalls\" | \"maxInputChars\" | \"runTimeoutMs\">;\nconst prefix = \"conversation-v1:\", revisionPrefix = \"conversation-input-v1:\";\nconst hash = (value: unknown) => createHash(\"sha256\").update(JSON.stringify(value)).digest(\"hex\");\nconst one = (value: unknown, choices: readonly string[]): boolean => typeof value === \"string\" && choices.includes(value);\nfunction invalid(): never { throw new TypeError(\"Invalid canonical conversation input\"); }\n\n/** Inspect descriptors before reading values: accessors must not run during normalization. */\nfunction fields(value: unknown, allowed?: readonly string[]): Record<string, unknown> {\n if (!value || typeof value !== \"object\" || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) invalid();\n const entries = Reflect.ownKeys(value).map(k => {\n const d = Object.getOwnPropertyDescriptor(value, k)!;\n if (typeof k !== \"string\" || !d.enumerable || !(\"value\" in d) || (allowed && !allowed.includes(k))) invalid();\n return [k, d.value] as const;\n });\n return Object.fromEntries(entries);\n}\n/** Canonical JSON only; limits apply while traversing, not after cloning an unbounded graph. */\nfunction jsonSnapshot(value: unknown, max: number): unknown {\n let nodes = 0, size = 0; const ancestors = new Set<object>();\n function add(n: number) { size += n; if (size > max) invalid(); }\n function visit(v: unknown, depth: number): unknown {\n if (++nodes > 100_000 || depth > 64) invalid();\n if (v === null || typeof v === \"string\" || typeof v === \"boolean\" || (typeof v === \"number\" && Number.isFinite(v))) {\n if (typeof v === \"string\" && v.length > max) invalid();\n add(JSON.stringify(v).length); return Object.is(v, -0) ? 0 : v;\n }\n if (!v || typeof v !== \"object\" || ancestors.has(v)) invalid();\n ancestors.add(v);\n try {\n add(2);\n if (Array.isArray(v)) {\n if (v.length > 100_000 || Reflect.ownKeys(v).length !== v.length + 1) invalid();\n return Array.from({ length: v.length }, (_, i) => {\n const d = Object.getOwnPropertyDescriptor(v, String(i));\n if (!d || !(\"value\" in d) || !d.enumerable) invalid();\n if (i) add(1); return visit(d.value, depth + 1);\n });\n }\n const object = fields(v), entries = Object.keys(object).sort().filter(k => object[k] !== undefined);\n return Object.fromEntries(entries.map((k, i) => {\n if (k.length > max) invalid(); add(JSON.stringify(k).length + 1 + (i ? 1 : 0));\n return [k, visit(object[k], depth + 1)];\n }));\n } finally { ancestors.delete(v); }\n }\n return visit(value, 0);\n}\nexport function conversationRootKey(scope: Scope, sessionId: string, idempotencyKey: string): string {\n const s = settlementScope(scope);\n return prefix + hash([\"conversation-v1\", s.org, s.uid, settlementIdentifier(sessionId), settlementIdentifier(idempotencyKey)]);\n}\nfunction snapshot(c: ConversationDescriptorConfig, input: SimpleConversationInput): SimpleConversationInput {\n if (!Number.isSafeInteger(c.maxInputChars) || c.maxInputChars < 1 || c.maxInputChars > 64_000_000 || !Number.isSafeInteger(c.runTimeoutMs) || c.runTimeoutMs < 1 || c.runTimeoutMs > 300_000) invalid();\n const f = fields(input, [\"scope\", \"sessionId\", \"idempotencyKey\", \"input\", \"intent\", \"toolProfile\", \"trigger\", \"signal\"]);\n const data = jsonSnapshot(Object.fromEntries(Object.entries(f).filter(([k]) => k !== \"signal\")), c.maxInputChars + 4096) as SimpleConversationInput;\n data.scope = settlementScope(data.scope); data.sessionId = settlementIdentifier(data.sessionId); data.idempotencyKey = settlementIdentifier(data.idempotencyKey);\n const intent = fields(data.intent, [\"tier\", \"sensitivity\", \"task\"]);\n if (!one(intent.tier, [\"mechanical\", \"standard\", \"complex\"]) || !one(intent.sensitivity, [\"public\", \"internal\", \"personal\", \"health\"]) || (intent.task !== undefined && (typeof intent.task !== \"string\" || intent.task.length > 1000))) invalid();\n if (data.toolProfile !== undefined) settlementIdentifier(data.toolProfile);\n data.trigger ??= \"user\"; if (![\"user\", \"routine\", \"system\"].includes(data.trigger)) invalid();\n const message = fields(data.input, [\"role\", \"blocks\", \"meta\"]);\n if (message.role !== \"user\" || !Array.isArray(message.blocks) || JSON.stringify(message).length > c.maxInputChars) invalid();\n for (const block of message.blocks) validateBlock(block);\n if (message.meta !== undefined) {\n const meta = fields(message.meta, [\"at\", \"channel\", \"model\", \"rotation\"]);\n settlementInstant(meta.at);\n for (const key of [\"channel\", \"model\"]) if (meta[key] !== undefined && typeof meta[key] !== \"string\") invalid();\n if (meta.rotation !== undefined) {\n const r = fields(meta.rotation, [\"summarized\", \"keep\", \"reason\"]);\n if (![r.summarized, r.keep].every(n => Number.isSafeInteger(n) && Number(n) >= 0) || !one(r.reason, [\"cold_start\", \"context_window\"])) invalid();\n }\n }\n if (f.signal !== undefined) {\n if (!(f.signal instanceof AbortSignal)) invalid(); data.signal = f.signal;\n }\n return data;\n}\nfunction validateBlock(value: unknown): void {\n const b = fields(value), strings = (...keys: string[]) => { for (const k of keys) if (typeof b[k] !== \"string\") invalid(); };\n const provider = () => { if (!one(b.provider, [\"anthropic\", \"openai\", \"openrouter\"])) invalid(); };\n switch (b.type) {\n case \"text\": strings(\"text\"); if (b.origin !== undefined && b.origin !== \"harness\") invalid(); break;\n case \"media\": {\n if (b.content !== undefined || !one(b.kind, [\"image\", \"audio\", \"document\"])) invalid();\n const ref = fields(b.ref, [\"uri\", \"contentType\", \"bytes\", \"filename\"]);\n if (typeof ref.uri !== \"string\") invalid();\n for (const key of [\"contentType\", \"filename\"]) if (ref[key] !== undefined && typeof ref[key] !== \"string\") invalid();\n if (ref.bytes !== undefined && (!Number.isSafeInteger(ref.bytes) || Number(ref.bytes) < 0)) invalid();\n break;\n }\n case \"tool_call\": strings(\"id\", \"name\"); if (!(\"input\" in b)) invalid(); break;\n case \"tool_result\": strings(\"callId\"); if (!(\"output\" in b) || (b.isError !== undefined && typeof b.isError !== \"boolean\")) invalid(); break;\n case \"reasoning\": provider(); if (b.text !== undefined) strings(\"text\"); break;\n case \"provider_tool_call\": provider(); strings(\"id\"); if (b.name !== \"web_search\" || !(\"input\" in b)) invalid(); break;\n case \"provider_tool_result\":\n provider(); strings(\"callId\"); if (b.name !== \"web_search\" || !Array.isArray(b.results)) invalid();\n for (const item of b.results) { const r = fields(item); if (typeof r.url !== \"string\" || [r.title, r.pageAge].some(v => v !== undefined && typeof v !== \"string\")) invalid(); }\n if (b.error !== undefined) strings(\"error\"); break;\n default: invalid();\n }\n}\nfunction descriptor(c: ConversationDescriptorConfig, i: SimpleConversationInput, deadlineAt: string): OperationRootInput {\n const key = conversationRootKey(i.scope, i.sessionId, i.idempotencyKey);\n return normalizeOperationRoot({ scope: i.scope, sessionId: i.sessionId, key, id: key, deadlineAt,\n policyVersion: c.policyVersion, caps: c.caps, maxCalls: c.maxCalls, maxSensitivity: i.intent.sensitivity,\n request: { inputRevision: revisionPrefix + hash([\"conversation-input-v1\", i.input, i.intent, i.toolProfile ?? null, i.trigger, c.runTimeoutMs]),\n configRevision: c.configRevision, resultContractVersion: c.resultContractVersion, resultRetentionMs: c.resultRetentionMs } });\n}\n/** Pure helper for hosts binding lazy input to the same canonical identity. */\nexport function createConversationDescriptor(c: ConversationDescriptorConfig, input: SimpleConversationInput, deadlineAt: string): OperationRootInput {\n return descriptor(c, snapshot(c, input), deadlineAt);\n}\nexport function normalizeTurnInput(c: ConversationDescriptorConfig, value: SimpleConversationInput | ConversationInput): { input: ConversationInput; canonical: boolean } {\n const f = fields(value);\n if (\"root\" in f) {\n fields(value, [\"root\", \"intent\", \"loadInput\", \"toolProfile\", \"trigger\", \"signal\"]);\n const root = normalizeOperationRoot(f.root), canonical = root.key.startsWith(prefix);\n if (canonical && (root.id !== root.key || !/^conversation-v1:[a-f0-9]{64}$/.test(root.key) || !/^conversation-input-v1:[a-f0-9]{64}$/.test(root.request?.inputRevision ?? \"\"))) invalid();\n return { input: { ...(f as unknown as ConversationInput), root }, canonical };\n }\n const i = snapshot(c, value as SimpleConversationInput);\n return { canonical: true, input: { root: descriptor(c, i, new Date(Date.now() + c.runTimeoutMs).toISOString()), intent: i.intent,\n trigger: i.trigger!, ...(i.toolProfile !== undefined ? { toolProfile: i.toolProfile } : {}), ...(i.signal ? { signal: i.signal } : {}),\n loadInput: async (): Promise<Msg> => i.input } };\n}\n/** Exact store claims stay unchanged; a race loser never obtains or reconstructs a fence. */\nexport async function existingAdmission(store: OperationSessionStore, root: OperationRootInput, canonical: boolean, check: () => void): Promise<Extract<OperationSessionClaim, {status:\"existing\"}> | null> {\n const record = await store.get(root.scope, root.key); check();\n if (!record) return null;\n if (!equalExecution(canonical ? { ...record.input, deadlineAt: root.deadlineAt } : record.input, root)) throw new ExecutionConflictError();\n return { status: \"existing\", record };\n}\nexport async function claimCanonical(store: OperationSessionStore, root: OperationRootInput, check: () => void): Promise<OperationSessionClaim> {\n const old = await existingAdmission(store, root, true, check);\n if (old) return old;\n try { return await store.claim(root); }\n catch (e) {\n if (!(e instanceof ExecutionConflictError)) throw e;\n check(); const saved = await existingAdmission(store, root, true, check);\n if (!saved) throw e;\n return saved;\n }\n}\n","import { equalExecution, ExecutionResultPolicyError, type Scope } from \"@alma-harness/core\";\nimport type { OperationRootInput } from \"@alma-harness/execution\";\nimport type { StepOutcome } from \"@alma-harness/loop/internal\";\nimport type { TurnEvent } from \"@alma-harness/loop\";\nimport { createGovernedStepRunner } from \"@alma-harness/single-call\";\nimport type { ConversationConfig, ConversationView } from \"./types\";\nimport { ConversationStreamResyncError, observerQueue } from \"./stream\";\ntype Key = { operationKey: string; callId: string };\ntype Ref = { type: \"final\"; view: Exclude<ConversationView, {status:\"completed\"}> | {status:\"completed\";replayed:boolean} }\n | (Key & { type: \"block\" | \"usage\"; step: number; index?: number })\n | (Key & { type: \"tool_result\"; step: number; id: string; isError: boolean });\nconst unavailable = (): never => { throw new ConversationStreamResyncError(\"unavailable\"); };\n/** One main call's identity, never a retained step payload or user callback. */\nexport function observation(c: ConversationConfig, root: OperationRootInput, read: (scope: Scope, key: string) => Promise<ConversationView | null>) {\n const steps = createGovernedStepRunner(c.step);\n let current: Key | undefined;\n const queue = observerQueue<Ref>(async ref => {\n if (ref.type === \"final\") {\n if (ref.view.status !== \"completed\") return { type: \"result\", view: ref.view };\n const fresh = await read(root.scope, root.key) ?? {status:\"unavailable\" as const};\n if (fresh.status !== \"completed\") return {type:\"result\",view:fresh};\n const result = { ...fresh.result }; delete result.replayed;\n if (ref.view.replayed) result.replayed = true;\n return {type:\"result\",view:{...fresh,result,replayed:ref.view.replayed}};\n }\n const fresh = await steps.read({scope:root.scope,rootKey:root.key,operationKey:ref.operationKey});\n if (!fresh || fresh.status !== \"completed\" || fresh.record.input.callId !== ref.callId ||\n fresh.record.input.operationKey !== ref.operationKey || !equalExecution(fresh.record.input.scope,root.scope) ||\n fresh.rootReceipt.rootId !== root.id || fresh.rootReceipt.callId !== ref.callId) return unavailable();\n const source = fresh.receipt.receipt.settlement;\n if (ref.type === \"usage\") return {type:\"usage\",step:ref.step,model:structuredClone(fresh.record.input.model),usage:structuredClone(source.usage),costUsd:source.costUsd};\n if (fresh.result.outcome !== \"success\" || !fresh.step) return unavailable();\n // The step reader establishes financial lineage; bind the final content read too.\n // Do not let an adapter return another call's otherwise valid envelope.\n const input = fresh.record.input;\n let stored;\n try { stored = await c.step.results.get(root.scope, ref.callId); }\n catch(error) { if(error instanceof ExecutionResultPolicyError)return unavailable();throw error; }\n if(!stored || stored.state!==\"available\" || !equalExecution(stored.binding, {\n scope:root.scope,callId:ref.callId,sessionId:input.sessionId,sensitivity:input.intent.sensitivity,\n retentionMs:input.governance!.resultRetentionMs,\n }) || !equalExecution(stored.result,fresh.result))return unavailable();\n const step = fresh.step;\n if (ref.type === \"tool_result\") {\n const call = step.toolCalls.find(t=>t.id===ref.id); if (!call) return unavailable();\n return {type:\"tool_result\",step:ref.step,id:call.id,name:call.name,isError:ref.isError};\n }\n const position=step.order[ref.index!];if(!position || position.type===\"reasoning\")return unavailable();\n if(position.type===\"text\")return {type:\"text\",step:ref.step,text:step.text.slice(position.start,position.end).toWellFormed()};\n if (position.type === \"tool_call\") {\n const call=step.toolCalls[position.index]; if(!call)return unavailable();\n return {type:\"tool_call\",step:ref.step,id:call.id,name:call.name};\n }\n const block=step.providerBlocks[position.index]; if(!block)return unavailable();\n return block.type === \"provider_tool_call\" ? {type:\"provider_tool_call\",step:ref.step,id:block.id,name:block.name}\n : {type:\"provider_tool_result\",step:ref.step,id:block.callId,name:block.name,results:block.results.length,isError:block.error!==undefined};\n });\n return {\n bind(key: Key) { if(queue.active())current=key; },\n main(step: number, outcome: StepOutcome) {\n if(!current || !queue.active() || current.callId!==outcome.callId)return;\n // ordered(outcome) preserves the persisted step.order indices, including reasoning.\n for(let index=0;index<outcome.blocks!.length && queue.active();index++)\n if(outcome.blocks![index]!.type!==\"reasoning\")queue.push({...current,type:\"block\",step,index});\n queue.push({...current,type:\"usage\",step});\n if(!queue.active())current=undefined;\n },\n emit(event: TurnEvent) {\n if(event.type===\"tool_result\" && current && queue.active())queue.push({...current,type:\"tool_result\",step:event.step,id:event.id,isError:event.isError});\n if(!queue.active())current=undefined;\n },\n start(result: Promise<ConversationView>) {\n // Install before the caller can await result; never retain its content in the queue.\n void result.then(view=>{current=undefined;queue.finish({type:\"final\",view:view.status===\"completed\" ? {status:\"completed\",replayed:view.replayed} : view});},error=>{current=undefined;queue.fail(error);});\n return queue.stream(result);\n },\n };\n}\nexport type Observation = ReturnType<typeof observation>;\n","import type { ConversationEvent, ConversationStream, ConversationView } from \"./types\";\nexport class ConversationStreamResyncError extends Error {\n constructor(readonly reason: \"overflow\" | \"unavailable\" | \"read_failed\") {\n super(`Conversation observer requires resynchronization: ${reason}`);\n this.name = \"ConversationStreamResyncError\";\n }\n}\nconst done = (): IteratorResult<ConversationEvent> => ({ done: true, value: undefined });\n/** Content-free references only. No producer operation waits for this single reader. */\nexport function observerQueue<R>(authorize: (ref: R) => Promise<ConversationEvent>) {\n let queue: { ref: R; bytes: number }[] = [], bytes = 0, reading = false;\n let attached = false, closed = false, settled = false, generation = 0;\n let failure: unknown, failed = false;\n let waiting: { resolve(value: IteratorResult<ConversationEvent>): void; reject(error: unknown): void } | undefined;\n function detach(error?: unknown) {\n if (closed) return;\n closed = true; generation++; queue = []; bytes = 0;\n failed = error !== undefined; failure = error;\n const w = waiting; waiting = undefined;\n if (failed) w?.reject(error); else w?.resolve(done());\n }\n function pump() {\n if (!waiting || reading || closed) return;\n const item = queue.shift();\n if (!item) { if (settled) detach(); return; }\n reading = true; const version = generation;\n // The in-flight reference stays in the byte/count budget until delivered.\n void Promise.resolve().then(() => authorize(item.ref)).then(event => {\n if (closed || version !== generation) return;\n bytes -= item.bytes; reading = false;\n const w = waiting; waiting = undefined;\n w?.resolve({ done: false, value: event });\n }, error => {\n if (closed || version !== generation) return;\n reading = false;\n detach(error instanceof ConversationStreamResyncError ? error : new ConversationStreamResyncError(\"read_failed\"));\n });\n }\n function push(ref: R) {\n if (closed) return;\n // Conservative UTF-16 storage estimate plus object overhead, bounded before retention.\n const size = JSON.stringify(ref).length * 2 + 256;\n if (queue.length + Number(reading) >= 128 || bytes + size > 256 * 1024) {\n detach(new ConversationStreamResyncError(\"overflow\")); return;\n }\n queue.push({ ref, bytes: size }); bytes += size; pump();\n }\n const iterator: AsyncIterableIterator<ConversationEvent> = {\n [Symbol.asyncIterator]() { return this; },\n next() {\n if (closed) return failed ? Promise.reject(failure) : Promise.resolve(done());\n if (waiting || reading) return Promise.reject(new TypeError(\"Only one pending observer next is supported\"));\n return new Promise((resolve, reject) => { waiting = { resolve, reject }; pump(); });\n },\n return() { detach(); return Promise.resolve(done()); },\n throw() { detach(); return Promise.resolve(done()); },\n };\n return {\n push, active: () => !closed,\n finish(ref: R) {\n if (closed) return;\n if (!attached) { queue = []; bytes = 0; }\n push(ref); settled = true; pump();\n },\n fail: detach,\n stream(result: Promise<ConversationView>): ConversationStream {\n return { result, [Symbol.asyncIterator]() {\n if (attached) throw new TypeError(\"This conversation stream already has an iterator\");\n attached = true; return iterator;\n } };\n },\n };\n}\n"],"mappings":"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","names":["equalExecution","ExecutionConflictError","ExecutionResultPolicyError","settlementIdentifier","settlementScope","normalizeOperationRoot","createInternals","createGovernedStepRunner","equalExecution","equalExecution","createGovernedStepRunner","createGovernedStepRunner","fresh","equalExecution","settlementScope","settlementIdentifier","equalExecution","ExecutionResultPolicyError","normalizeOperationRoot","ExecutionConflictError","result","id","opts","createInternals","value"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alma-harness/conversation",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Governed buffered conversations for Alma.",
|
|
3
|
+
"version": "0.7.0",
|
|
4
|
+
"description": "Governed buffered and settled-step streaming conversations for Alma.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"engines": {
|
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
"directory": "packages/conversation"
|
|
20
20
|
},
|
|
21
21
|
"peerDependencies": {
|
|
22
|
-
"@alma-harness/
|
|
23
|
-
"@alma-harness/
|
|
24
|
-
"@alma-harness/loop": "^0.
|
|
25
|
-
"@alma-harness/single-call": "^0.
|
|
22
|
+
"@alma-harness/execution": "^0.7.0",
|
|
23
|
+
"@alma-harness/core": "^0.7.0",
|
|
24
|
+
"@alma-harness/loop": "^0.7.0",
|
|
25
|
+
"@alma-harness/single-call": "^0.7.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^24.1.0",
|
|
@@ -30,13 +30,13 @@
|
|
|
30
30
|
"vitest": "^3.2.4",
|
|
31
31
|
"pg": "^8.16.3",
|
|
32
32
|
"@types/pg": "^8.15.4",
|
|
33
|
-
"@alma-harness/core": "^0.
|
|
34
|
-
"@alma-harness/execution": "^0.
|
|
35
|
-
"@alma-harness/memory": "^0.
|
|
36
|
-
"@alma-harness/postgres": "^0.
|
|
37
|
-
"@alma-harness/postgres-execution": "^0.
|
|
38
|
-
"@alma-harness/loop": "^0.
|
|
39
|
-
"@alma-harness/single-call": "^0.
|
|
33
|
+
"@alma-harness/core": "^0.7.0",
|
|
34
|
+
"@alma-harness/execution": "^0.7.0",
|
|
35
|
+
"@alma-harness/memory": "^0.7.0",
|
|
36
|
+
"@alma-harness/postgres": "^0.7.0",
|
|
37
|
+
"@alma-harness/postgres-execution": "^0.7.0",
|
|
38
|
+
"@alma-harness/loop": "^0.7.0",
|
|
39
|
+
"@alma-harness/single-call": "^0.7.0"
|
|
40
40
|
},
|
|
41
41
|
"files": [
|
|
42
42
|
"dist"
|