@earendil-works/pi-durable 0.99.2 → 1.0.1
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/CHANGELOG.md +9 -0
- package/README.md +196 -74
- package/dist/env/index.d.ts +5 -0
- package/dist/env/index.d.ts.map +1 -1
- package/dist/env/index.js.map +1 -1
- package/dist/env/node.d.ts +2 -0
- package/dist/env/node.d.ts.map +1 -1
- package/dist/env/node.js +2 -0
- package/dist/env/node.js.map +1 -1
- package/dist/harness/agent.d.ts +31 -0
- package/dist/harness/agent.d.ts.map +1 -0
- package/dist/harness/agent.js +209 -0
- package/dist/harness/agent.js.map +1 -0
- package/dist/harness/compaction.d.ts.map +1 -1
- package/dist/harness/compaction.js +8 -11
- package/dist/harness/compaction.js.map +1 -1
- package/dist/harness/define.d.ts +18 -0
- package/dist/harness/define.d.ts.map +1 -0
- package/dist/harness/define.js +25 -0
- package/dist/harness/define.js.map +1 -0
- package/dist/harness/events.d.ts +5 -5
- package/dist/harness/events.d.ts.map +1 -1
- package/dist/harness/events.js +6 -6
- package/dist/harness/events.js.map +1 -1
- package/dist/harness/generation.d.ts +2 -4
- package/dist/harness/generation.d.ts.map +1 -1
- package/dist/harness/generation.js +39 -43
- package/dist/harness/generation.js.map +1 -1
- package/dist/harness/harness.d.ts.map +1 -1
- package/dist/harness/harness.js +68 -154
- package/dist/harness/harness.js.map +1 -1
- package/dist/harness/inbox.d.ts +4 -2
- package/dist/harness/inbox.d.ts.map +1 -1
- package/dist/harness/inbox.js +3 -5
- package/dist/harness/inbox.js.map +1 -1
- package/dist/harness/prompt.d.ts +1 -3
- package/dist/harness/prompt.d.ts.map +1 -1
- package/dist/harness/prompt.js +1 -11
- package/dist/harness/prompt.js.map +1 -1
- package/dist/harness/registry.d.ts +2 -3
- package/dist/harness/registry.d.ts.map +1 -1
- package/dist/harness/registry.js +66 -283
- package/dist/harness/registry.js.map +1 -1
- package/dist/harness/scheduler.d.ts +7 -2
- package/dist/harness/scheduler.d.ts.map +1 -1
- package/dist/harness/scheduler.js +41 -27
- package/dist/harness/scheduler.js.map +1 -1
- package/dist/harness/submissions.d.ts +4 -4
- package/dist/harness/submissions.d.ts.map +1 -1
- package/dist/harness/submissions.js +7 -4
- package/dist/harness/submissions.js.map +1 -1
- package/dist/harness/task-graph.d.ts +49 -0
- package/dist/harness/task-graph.d.ts.map +1 -0
- package/dist/harness/task-graph.js +163 -0
- package/dist/harness/task-graph.js.map +1 -0
- package/dist/harness/tool.d.ts +1 -1
- package/dist/harness/tool.d.ts.map +1 -1
- package/dist/harness/tool.js +9 -6
- package/dist/harness/tool.js.map +1 -1
- package/dist/harness/types.d.ts +171 -140
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/view.d.ts +1 -1
- package/dist/harness/view.d.ts.map +1 -1
- package/dist/harness/view.js +2 -7
- package/dist/harness/view.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/session/session.d.ts.map +1 -1
- package/dist/session/session.js +5 -1
- package/dist/session/session.js.map +1 -1
- package/dist/session/transaction.d.ts +2 -2
- package/dist/session/transaction.d.ts.map +1 -1
- package/dist/session/transaction.js +7 -4
- package/dist/session/transaction.js.map +1 -1
- package/dist/storage/sqlite/database.d.ts +26 -19
- package/dist/storage/sqlite/database.d.ts.map +1 -1
- package/dist/storage/sqlite/database.js.map +1 -1
- package/dist/storage/sqlite/index.d.ts +1 -1
- package/dist/storage/sqlite/index.d.ts.map +1 -1
- package/dist/storage/sqlite/index.js.map +1 -1
- package/dist/storage/sqlite/migrations.js +6 -6
- package/dist/storage/sqlite/migrations.js.map +1 -1
- package/dist/storage/sqlite/node.d.ts +23 -7
- package/dist/storage/sqlite/node.d.ts.map +1 -1
- package/dist/storage/sqlite/node.js +129 -47
- package/dist/storage/sqlite/node.js.map +1 -1
- package/dist/storage/sqlite/storage.d.ts +12 -0
- package/dist/storage/sqlite/storage.d.ts.map +1 -1
- package/dist/storage/sqlite/storage.js +121 -129
- package/dist/storage/sqlite/storage.js.map +1 -1
- package/dist/tools/bash.d.ts +1 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +3 -2
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/edit.d.ts +3 -3
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +5 -4
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/file-mutation-queue.d.ts +5 -1
- package/dist/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/tools/file-mutation-queue.js +39 -33
- package/dist/tools/file-mutation-queue.js.map +1 -1
- package/dist/tools/index.d.ts +18 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +10 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/read.d.ts +3 -3
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +4 -3
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/write.d.ts +1 -1
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js +3 -2
- package/dist/tools/write.js.map +1 -1
- package/dist/types.d.ts +15 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +25 -15
- package/dist/harness/config.d.ts +0 -29
- package/dist/harness/config.d.ts.map +0 -1
- package/dist/harness/config.js +0 -24
- package/dist/harness/config.js.map +0 -1
- package/docs/chord-delta-findings.md +0 -358
- package/docs/pico-v5-chord-usage.md +0 -373
- package/docs/pico-v5-handoff.md +0 -861
- package/docs/pico-v5.md +0 -4174
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/harness/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AttachedReplicatedState, Context, JsonValue } from \"@earendil-works/chord\";\nimport type {\n\tAssistantMessage,\n\tCacheRetention,\n\tMessage,\n\tModels,\n\tModelThinkingLevel,\n\tTool,\n\tToolCall,\n\tToolResultMessage,\n\tTransport,\n\tUsage,\n\tUserMessage,\n} from \"@earendil-works/pi-ai\";\nimport type { ExecutionEnv } from \"../env/index.ts\";\nimport type {\n\tConversationId,\n\tConversationOwnership,\n\tConversationRecord,\n\tCursor,\n\tDocumentObserver,\n\tDocumentReader,\n\tEntryDraft,\n\tEntryId,\n\tEntryQuery,\n\tEntryRecord,\n\tJsonObject,\n\tPage,\n\tSession,\n\tSubmissionId,\n\tSubmissionRecord,\n\tTask,\n\tTaskId,\n\tTaskOptions,\n\tTaskRecord,\n\tTaskState,\n\tTx,\n\tWatchHandle,\n} from \"../types.ts\";\nimport type { UsageState } from \"./usage.ts\";\nimport type { ConversationView } from \"./view.ts\";\n\n/** Provider and model ID resolved through pi-ai `Models`. */\nexport type ModelRef = {\n\treadonly provider: string;\n\treadonly modelId: string;\n};\n\nexport type UserInput = UserMessage[\"content\"];\n\n/** Host submission: user input that may start a run, or a passive entry write. */\nexport type SubmissionDraft = {\n\treadonly requestId?: string;\n} & (\n\t| {\n\t\t\treadonly type: \"input\";\n\t\t\treadonly content: UserInput;\n\t\t\treadonly whenBusy?: \"steer\" | \"followUp\" | \"reject\";\n\t\t\treadonly entry?: never;\n\t }\n\t| {\n\t\t\treadonly type: \"write\";\n\t\t\treadonly entry: EntryDraft;\n\t\t\treadonly content?: never;\n\t\t\treadonly whenBusy?: never;\n\t }\n);\n\nexport type InputSubmissionDraft = Extract<SubmissionDraft, { readonly type: \"input\" }>;\n\nexport type SettledSubmissionRecord = SubmissionRecord & {\n\treadonly status: \"done\" | \"unanswered\";\n};\n\n/** Awaitable host object for one durably admitted submission. */\nexport interface Submission {\n\treadonly id: SubmissionId;\n\tstatus(context: Context): Promise<SubmissionRecord>;\n\twait(context: Context): Promise<SettledSubmissionRecord>;\n\tabort(context: Context): Promise<\"aborted\" | \"already_placed\" | \"settled\">;\n}\n\nexport type SettledTask<R> = TaskRecord<JsonValue, JsonValue, R> & {\n\treadonly state: Extract<TaskState<JsonValue, R>, { readonly status: \"terminal\" }>;\n};\n\n/** Erased executable task definition stored in the registry. */\nexport type AnyTask = {\n\treadonly definition: {\n\t\treadonly name: string;\n\t\treadonly version: number;\n\t\treadonly initial: unknown;\n\t\treadonly phases: Readonly<Record<string, unknown>>;\n\t\treadonly abort: unknown;\n\t\treadonly migrate?: unknown;\n\t\treadonly hooks?: object;\n\t};\n};\n\n/** Options of `Conversation.abort()`. */\nexport type ConversationAbortOptions = {\n\t/**\n\t * Cross background boundaries: mark every live task reached ignoring the background flag when the abort is admitted,\n\t * withdraw the queued inputs of every conversation reached, and wait until those tasks are terminal and the\n\t * conversation is ordinarily idle. Background work created afterwards is neither marked nor awaited.\n\t */\n\treadonly background?: boolean;\n};\n\n/** Hook handler map declared by a task definition. */\nexport type HooksOf<K> = K extends Task<infer _I, infer _S, infer _R, infer H> ? H : never;\n\n/**\n * Invocation-bound conversation operations for tasks and tools. Rejects after the invocation ends; passive entries are\n * written with ordinary transaction writes instead.\n */\nexport interface ConversationHandle {\n\treadonly id: ConversationId;\n\tsubmit(submission: InputSubmissionDraft, context: Context): Promise<Submission>;\n\t/** `Conversation.abort()`: withdraw queued inputs, abort the ordinary ownership scope, and wait until it is idle. */\n\tabort(context: Context, options?: ConversationAbortOptions): Promise<void>;\n\t/** Resolve when the conversation's ordinary ownership scope has no live non-background task. */\n\twaitForIdle(context: Context): Promise<void>;\n}\n\n/** Post-tools controls requested by a tool result. */\nexport type ToolControl = {\n\treadonly addTools?: readonly string[];\n\treadonly terminate?: true;\n\treadonly handoff?: string;\n};\n\n/** Remark about a call for the model and the UI, such as truncation or a spill path; never part of the tool's data. */\nexport type ToolDiagnostic = {\n\treadonly severity: \"info\" | \"warn\" | \"error\";\n\treadonly message: string;\n\treadonly code?: string;\n};\n\nexport type ToolExecutionResult = {\n\t/** Omitted: the retained `output()` text becomes the content. */\n\treadonly content?: ToolResultMessage[\"content\"];\n\treadonly isError?: boolean;\n\t/** Omitted: the last `details()` value becomes the details. */\n\treadonly details?: JsonValue;\n\t/** Added after those recorded through `api.diagnostic()`. */\n\treadonly diagnostics?: readonly ToolDiagnostic[];\n\t/** Spend of the execution itself, such as a model call; stored on the result and in `pi.usage.tools`. */\n\treadonly usage?: Usage;\n\treadonly control?: ToolControl;\n};\n\n/** Whether the tools of one round run at once or one after another in call order. */\nexport type ToolExecutionMode = \"parallel\" | \"sequential\";\n\n/** How many queued items of one mode a boundary places: the first, or all of them. */\nexport type QueueMode = \"all\" | \"one-at-a-time\";\n\n/**\n * Operations available to one tool invocation. A plain object, so a wrapper can pass `{ ...api, env }` to the tool it\n * wraps. Every operation rejects after the invocation ends.\n */\nexport interface ToolExecutionApi extends DocumentObserver, DocumentReader {\n\treadonly taskId: TaskId;\n\treadonly conversationId: ConversationId;\n\treadonly callId: string;\n\t/** `HarnessOptions.env` unless a wrapper supplies another environment. */\n\treadonly env: ExecutionEnv | undefined;\n\t/** Append running output; it becomes the result content when the result omits `content`. */\n\toutput(chunk: string | Uint8Array): void;\n\t/** Record a model-visible remark about this call. */\n\tdiagnostic(diagnostic: ToolDiagnostic): void;\n\t/** Replace running details; the last value becomes the result details when the result omits `details`. */\n\tdetails(value: JsonValue, context: Context): Promise<void>;\n\tcommit<T>(change: (tx: Tx) => T | Promise<T>, context: Context): Promise<T>;\n\tmemo<T extends JsonValue>(name: string, context: Context): Promise<T | undefined>;\n\tmemo<T extends JsonValue>(name: string, candidate: T, context: Context): Promise<T>;\n\tcreateTask<I, S extends { phase: string }, R, H extends object>(\n\t\ttask: Task<I, S, R, H>,\n\t\tinput: I,\n\t\toptions: Omit<TaskOptions, \"conversationId\">,\n\t\tcontext: Context,\n\t): Promise<TaskId<R>>;\n\tgetTask<R>(id: TaskId<R>, context: Context): Promise<TaskRecord<JsonValue, JsonValue, R> | undefined>;\n\twaitForTask<R>(id: TaskId<R>, context: Context): Promise<SettledTask<R>>;\n\t/** Invocation-bound handle of an existing conversation, such as one this tool created in `commit()`. */\n\tconversation(id: ConversationId, context: Context): Promise<ConversationHandle | undefined>;\n}\n\n/** Executable tool registered in a registry. Only pi-ai `Tool` fields enter the transcript. */\nexport type ToolRegistration = Tool & {\n\t/** Whether an interrupted execution may rerun on recovery. Default `unsafe`. */\n\treadonly replay?: \"safe\" | \"unsafe\";\n\t/** Default: the conversation's `toolExecution`. One sequential call makes its whole round sequential. */\n\treadonly executionMode?: ToolExecutionMode;\n\t/**\n\t * Repair arguments models commonly get wrong before validation, such as a JSON string where an array belongs. Must be\n\t * pure and must not mutate `args`: it runs again when a call is retried before its intent is recorded.\n\t */\n\tprepareArguments?(args: JsonValue): JsonValue;\n\treadonly outputLimits?: {\n\t\treadonly maxBytes?: number;\n\t\treadonly maxLines?: number;\n\t\treadonly retain?: \"head\" | \"tail\";\n\t};\n\texecute(args: JsonValue, api: ToolExecutionApi, context: Context): Promise<ToolExecutionResult>;\n};\n\n/** Token for removing registrations. Work already running keeps using what it started with. */\nexport interface Registration {\n\t/** Idempotent; removes exactly the registrations this token covers. */\n\tdispose(): void;\n}\n\n/** Pure decorator; returns a new tool with the same name and never mutates its input. */\nexport type ToolWrapper<Tool extends ToolRegistration> = (tool: Tool) => Tool;\n\n/** Conversation selection for a scoped hook registration. */\nexport type HookScope = {\n\treadonly conversationId: ConversationId;\n\t/** Also match conversations owned, transitively, by tasks of this conversation. */\n\treadonly subtree?: boolean;\n};\n\n/** Input to system prompt section rendering for one request preparation. */\nexport type PromptInput<Tool extends ToolRegistration> = {\n\treadonly conversationId: ConversationId;\n\t/** Active and registered tools in configured order, as offered in this request. */\n\treadonly tools: readonly Tool[];\n\t/** Sections already in effect after replaying the active transcript. */\n\treadonly shown: Readonly<Record<string, string>>;\n\treadonly model?: ModelRef;\n\treadonly thinkingLevel: ModelThinkingLevel;\n\t/** Committed document reads. */\n\treadonly read: DocumentReader;\n};\n\n/** One registered system prompt section; sections render in registry order before each request. */\nexport type PromptSection<Tool extends ToolRegistration> = {\n\treadonly key: string;\n\trender(input: PromptInput<Tool>, context: Context): string | undefined | Promise<string | undefined>;\n\t/** Default true: wrap the text as `<key>\\n...\\n</key>`. */\n\treadonly tag?: boolean;\n};\n\n/** Pure decorator; returns a new section with the same key and never mutates its input. */\nexport type PromptSectionWrapper<Tool extends ToolRegistration> = (section: PromptSection<Tool>) => PromptSection<Tool>;\n\n/** One registered hook handler map for task `K`. */\nexport type HookRegistration<K extends AnyTask> = {\n\treadonly handlers: Partial<HooksOf<K>>;\n\treadonly scope?: HookScope;\n};\n\n/** Wrapper composition failure found while building a snapshot. */\nexport type RegistryFailure = {\n\treadonly kind: \"tool\" | \"section\";\n\t/** Tool name or section key. */\n\treadonly name: string;\n\treadonly error: unknown;\n};\n\n/** Immutable view of one published registry state. */\nexport interface RegistrySnapshot<Tool extends ToolRegistration = ToolRegistration> {\n\t/** Composed tools in registry order; a tool whose wrapper failed is absent. */\n\ttools(): readonly Tool[];\n\ttool(name: string): Tool | undefined;\n\t/** Base tool names in registry order, including tools whose wrappers fail. */\n\ttoolNames(): readonly string[];\n\ttask(name: string): AnyTask | undefined;\n\t/** Hooks registered for tasks with `task`'s name, in registry order. */\n\thooks<K extends AnyTask>(task: K): readonly HookRegistration<K>[];\n\t/** Composed sections in registry order; a section whose wrapper failed is absent. */\n\tsections(): readonly PromptSection<Tool>[];\n\t/** Wrapper failures of this state. */\n\tfailures(): readonly RegistryFailure[];\n\t/** Conversation setups in registry order, the built-in `pi` setup first. */\n\tconversationSetups(): readonly { readonly key: string; readonly setup: ConversationSetup }[];\n}\n\n/** Read side of a registry consumed by a Harness. */\nexport interface RegistryReader<Tool extends ToolRegistration = ToolRegistration> {\n\t/** Immutable view of the whole current registry. */\n\tsnapshot(): RegistrySnapshot<Tool>;\n\t/** Called synchronously after every publication; wakes the scheduler to reconsider blocked tasks. */\n\tsubscribe(listener: () => void): () => void;\n}\n\n/** Application-owned registry of tools, hooks, tasks, and the system prompt. */\nexport interface Registry<Tool extends ToolRegistration = ToolRegistration> extends RegistryReader<Tool> {\n\treadonly tools: {\n\t\tadd(tool: Tool): Registration;\n\t\t/** `key` identifies the wrapper: it orders wrappers of one tool and keeps its position on re-registration. */\n\t\twrap(name: string, key: string, wrapper: ToolWrapper<Tool>): Registration;\n\t\t/** Composed tools of the current state. */\n\t\tlist(): readonly Tool[];\n\t};\n\treadonly hooks: {\n\t\tadd<K extends AnyTask>(\n\t\t\ttask: K,\n\t\t\thandlers: Partial<HooksOf<K>>,\n\t\t\toptions?: { readonly scope?: HookScope; readonly key?: string },\n\t\t): Registration;\n\t};\n\treadonly tasks: {\n\t\tadd(task: AnyTask): Registration;\n\t\tlist(): readonly AnyTask[];\n\t};\n\treadonly conversations: {\n\t\t/** `key` orders setups and keeps its position on re-registration. */\n\t\tsetup(key: string, setup: ConversationSetup): Registration;\n\t};\n\treadonly systemPrompt: {\n\t\tsection(key: string, render: PromptSection<Tool>[\"render\"], options?: { readonly tag?: boolean }): Registration;\n\t\twrap(key: string, wrapperKey: string, wrapper: PromptSectionWrapper<Tool>): Registration;\n\t\t/** Composed sections of the current state. */\n\t\tsections(): readonly PromptSection<Tool>[];\n\t};\n\t/** Stage registrations and disposals made synchronously by `register`, then publish them at once. Cannot nest. */\n\tbatch(register: () => void): Registration;\n}\n\n/**\n * Stages the documents every new conversation gets. Runs inside every Harness commit that creates or forks a\n * conversation, including raw `Tx` creation, after fork copies and before host `init`. Table reads throw, since the\n * conversation write came first; a fork (`conversation.parent`) already holds its copied documents. A throw fails the\n * creating commit.\n */\nexport type ConversationSetup = (\n\ttx: Tx,\n\tconversation: ConversationRecord,\n\tregistry: RegistrySnapshot,\n) => void | Promise<void>;\n\n/**\n * Runs inside the creating commit, after the conversation and its configuration exist. The conversation creation is\n * already a table write, so table reads here throw `ReadAfterWrite`; document access remains available.\n */\nexport type ConversationInit = (tx: Tx, conversationId: ConversationId) => void | Promise<void>;\n\nexport type ConversationCreateOptions = {\n\treadonly ownership: ConversationOwnership;\n\treadonly init?: ConversationInit;\n};\n\n/** Curated pi-ai request options; absent fields use pi-ai defaults. */\nexport type ConversationStreamOptions = {\n\ttransport?: Transport;\n\ttimeoutMs?: number;\n\t/** Provider/SDK retries inside one request attempt. */\n\tmaxRetries?: number;\n\tmaxRetryDelayMs?: number;\n\theaders?: Record<string, string>;\n\tmetadata?: JsonObject;\n\tcacheRetention?: CacheRetention;\n\tdeferred?: boolean | { window?: \"15m\" | \"1h\" | \"24h\" };\n};\n\n/** Durable generation attempt retries; the JSON shape of pi-ai `RetryPolicy`. */\nexport type ConversationRetryPolicy = {\n\tenabled: boolean;\n\tmaxRetries: number;\n\tbaseDelayMs: number;\n\tmaxAgentDelayMs?: number;\n};\n\n/** Automatic compaction thresholds (spec §8.7); manual compaction ignores `enabled`. */\nexport type CompactionPolicy = {\n\t/** Threshold and overflow compaction. */\n\tenabled: boolean;\n\t/** Room kept free for the answer: generation blocks to compact above `contextWindow - reserveTokens`. */\n\treserveTokens: number;\n\t/** Approximate size of the recent context a summary keeps verbatim. */\n\tkeepRecentTokens: number;\n\t/** Background compaction starts `backgroundTokens` below the blocking threshold; `0` disables it. */\n\tbackgroundTokens: number;\n};\n\n/** Why a compaction runs: `compact()`, a threshold in generation preparation, or a context overflow. */\nexport type CompactionReason = \"manual\" | \"threshold\" | \"overflow\";\n\n/**\n * `entryId` of a blocking compaction's summary, or the `submissionId` of a conversation-owned compaction's summary\n * write; both absent when nothing was compacted.\n */\nexport type CompactionResult = { entryId?: EntryId; submissionId?: SubmissionId };\n\nexport type HarnessOptions<Tool extends ToolRegistration = ToolRegistration> = {\n\t/** pi-ai model access used by generation. */\n\treadonly models: Models;\n\treadonly registry: RegistryReader<Tool>;\n\t/** Default execution environment offered to tools as `api.env`. */\n\treadonly env?: ExecutionEnv;\n\treadonly now?: () => number;\n\t/** Receives extension failures that do not fail the calling operation. Must not throw. */\n\treadonly onReport?: (error: unknown) => void;\n};\n\n/** Live task and what the scheduler would do with it under the current registry. */\nexport type TaskInspection = {\n\treadonly record: TaskRecord<JsonValue, JsonValue, JsonValue>;\n\treadonly state: /** An invocation is active. */\n\t\t| { readonly kind: \"running\" }\n\t\t/** The next scheduling pass reserves it; `migrates` when its definition is newer and has `migrate`. */\n\t\t| { readonly kind: \"ready\"; readonly migrates: boolean }\n\t\t/**\n\t\t * Waits for these live tasks: the live part of its `on`, or, when abort-marked, its live ordinary owned work, which\n\t\t * must end before its abort handler starts.\n\t\t */\n\t\t| { readonly kind: \"waiting\"; readonly on: readonly TaskId[] }\n\t\t/** Outcome held until its ordinary owned work drains. */\n\t\t| { readonly kind: \"completing\" }\n\t\t/** No registered definition can take it; aborting it settles it as `orphaned`. */\n\t\t| {\n\t\t\t\treadonly kind: \"blocked\";\n\t\t\t\treadonly reason: \"missing_task\" | \"task_too_old\" | \"migration_failed\";\n\t\t\t\treadonly error?: unknown;\n\t\t };\n};\n\n/** Point-in-time view of live work: unfinished tasks and submissions, read on the Session line. */\nexport type HarnessInspection = {\n\treadonly scheduling: \"paused\" | \"running\" | \"closing\";\n\treadonly tasks: readonly TaskInspection[];\n\t/** Queued and placed submissions, in ID order. */\n\treadonly submissions: readonly SubmissionRecord[];\n\t/** Wrapper failures of the current registry snapshot. */\n\treadonly registry: readonly RegistryFailure[];\n};\n\n/** Raw active transcript and derived model context. */\nexport type ContextView = {\n\t/** Newest applicable head marker, if any. */\n\treadonly head: EntryRecord | undefined;\n\t/** Raw active entries: the head marker followed by non-head entries from its head through the tail. */\n\treadonly entries: readonly EntryRecord[];\n\t/** Per entry of `entries`, its model messages after edits and excluded stop reasons, before tool result ordering. */\n\treadonly contributions: readonly (readonly Message[])[];\n\t/** Model context for the next provider request. */\n\treadonly messages: readonly Message[];\n};\n\n/** Stateless handle for one conversation, bound to the Harness that returned it. Compare handles by `id`. */\nexport interface Conversation {\n\treadonly id: ConversationId;\n\n\tgetModel(context: Context): Promise<ModelRef | undefined>;\n\tsetModel(model: ModelRef | undefined, context: Context): Promise<void>;\n\tgetThinkingLevel(context: Context): Promise<ModelThinkingLevel>;\n\tsetThinkingLevel(level: ModelThinkingLevel, context: Context): Promise<void>;\n\tgetActiveTools(context: Context): Promise<readonly string[]>;\n\tsetActiveTools(names: readonly string[], context: Context): Promise<void>;\n\t/** `{}` when unset. */\n\tgetStreamOptions(context: Context): Promise<ConversationStreamOptions>;\n\tsetStreamOptions(options: ConversationStreamOptions, context: Context): Promise<void>;\n\t/** The default policy when unset. */\n\tgetRetryPolicy(context: Context): Promise<ConversationRetryPolicy>;\n\t/** `undefined` removes the configured policy. */\n\tsetRetryPolicy(policy: ConversationRetryPolicy | undefined, context: Context): Promise<void>;\n\t/** `parallel` when unset. */\n\tgetToolExecution(context: Context): Promise<ToolExecutionMode>;\n\t/** `undefined` removes the configured mode. */\n\tsetToolExecution(mode: ToolExecutionMode | undefined, context: Context): Promise<void>;\n\t/** `one-at-a-time` when unset. */\n\tgetSteeringMode(context: Context): Promise<QueueMode>;\n\t/** `undefined` removes the configured mode. */\n\tsetSteeringMode(mode: QueueMode | undefined, context: Context): Promise<void>;\n\t/** `one-at-a-time` when unset. */\n\tgetFollowUpMode(context: Context): Promise<QueueMode>;\n\t/** `undefined` removes the configured mode. */\n\tsetFollowUpMode(mode: QueueMode | undefined, context: Context): Promise<void>;\n\t/** `DEFAULT_COMPACTION_POLICY` when unset. */\n\tgetCompaction(context: Context): Promise<CompactionPolicy>;\n\t/** `undefined` removes the configured policy. */\n\tsetCompaction(policy: CompactionPolicy | undefined, context: Context): Promise<void>;\n\n\t/**\n\t * Durably admit user input or a passive entry write. A busy conversation, or one with queued items, queues it in\n\t * `pi.inbox`; `whenBusy: \"reject\"` rejects with `ConversationBusy` instead and writes nothing.\n\t */\n\tsubmit(submission: SubmissionDraft, context: Context): Promise<Submission>;\n\t/**\n\t * Admit a write of a `pi.reset` entry that starts a new context, carrying `handoff` as a user message when given.\n\t * Resolves after admission; while busy, it is placed at the next boundary.\n\t */\n\treset(handoff: string | undefined, context: Context): Promise<void>;\n\t/**\n\t * Admit a manual compaction task and return its ID. It summarizes while the conversation keeps working and places its\n\t * summary through a write submission: at once when idle, otherwise at the next boundary (spec §8.7).\n\t */\n\tcompact(instructions: string | undefined, context: Context): Promise<TaskId<CompactionResult>>;\n\n\t/** Session commit whose `tx.createTask()` defaults to this conversation. */\n\tcommit<T>(change: (tx: Tx) => T | Promise<T>, context: Context): Promise<T>;\n\tcontext(context: Context): Promise<ContextView>;\n\t/** Newest-first fork-aware history of this conversation. */\n\tentries(\n\t\tquery: Omit<EntryQuery, \"conversationId\">,\n\t\tlimit: number,\n\t\tcursor: Cursor | undefined,\n\t\tcontext: Context,\n\t): Promise<Page<EntryRecord, Cursor>>;\n\tfork(at: EntryId, options: ConversationCreateOptions, context: Context): Promise<Conversation>;\n\t/**\n\t * Withdraw queued inputs (queued writes stay), mark every live non-background task of the ordinary ownership scope,\n\t * signal them, and resolve once the scope is idle. Background subtrees survive unless `background` is set.\n\t */\n\tabort(context: Context, options?: ConversationAbortOptions): Promise<void>;\n\t/**\n\t * Resolve when the ordinary ownership scope has no live non-background task: this conversation and the conversations\n\t * owned, transitively, by its non-background tasks.\n\t */\n\twaitForIdle(context: Context): Promise<void>;\n\t/** The structural view (spec §9.3) as a disposable read-only Chord state. */\n\tviewState(context: Context): Promise<AttachedReplicatedState<ConversationView>>;\n\t/** The structural view as a serialized exact-frame watch with bounded pending frames. */\n\twatch(context: Context): Promise<WatchHandle<ConversationView>>;\n}\n\n// TODO: decide how Harness exposes subscribeCommits() and subscribeClose(). Their listeners run on the Session line\n// and must not throw or call Session APIs, and Harness close will also join task invocations.\n/** Durable agent harness over one Session. */\nexport interface Harness extends Session {\n\t/**\n\t * Enable task scheduling. Idempotent; throws after close. Calls that wait for progress (`Conversation.submit()`,\n\t * `Submission.wait()`, `waitForTask()`, `waitForIdle()`) enable it too.\n\t */\n\tresume(): void;\n\n\t/** Return the reserved root conversation, creating it with `init` in one commit when absent. */\n\troot(context: Context, options?: { readonly init?: ConversationInit }): Promise<Conversation>;\n\tconversation(id: ConversationId, context: Context): Promise<Conversation | undefined>;\n\tcreateConversation(options: ConversationCreateOptions, context: Context): Promise<Conversation>;\n\n\tgetTask<R>(id: TaskId<R>, context: Context): Promise<TaskRecord<JsonValue, JsonValue, R> | undefined>;\n\t/** Live tasks, unsettled submissions, and registry failures. Writes nothing and runs no task code. */\n\tinspect(context: Context): Promise<HarnessInspection>;\n\t/** Reacquire a submission, for example after reopen. */\n\tsubmission(id: SubmissionId, context: Context): Promise<Submission | undefined>;\n\t/** `not_found` for an unknown submission or one of another conversation than `conversationId`. */\n\tabortSubmission(\n\t\tid: SubmissionId,\n\t\tcontext: Context,\n\t\tconversationId?: ConversationId,\n\t): Promise<\"aborted\" | \"already_placed\" | \"settled\" | \"not_found\">;\n\t/**\n\t * Commit the abort mark, signal and join an active run invocation, and schedule the abort invocation. A task whose\n\t * definition cannot take it settles as `orphaned` instead.\n\t */\n\tabortTask(id: TaskId, context: Context): Promise<\"marked\" | \"terminal\">;\n\t/** Resolve with the terminal receipt; cancelling `context` cancels only this wait. */\n\twaitForTask<R>(id: TaskId<R>, context: Context): Promise<SettledTask<R>>;\n\t/** Resolve when the ordinary ownership scope of every ownerless conversation has no live non-background task. */\n\twaitForIdle(context: Context): Promise<void>;\n\t/** Session total: every conversation's `pi.usage` summed. */\n\tusage(context: Context): Promise<UsageState>;\n}\n\n/** What a hook may use: committed reads and the asking task's memos, which hooks and the task share. */\nexport interface HookApi extends DocumentReader {\n\treadonly taskId: TaskId;\n\treadonly conversationId: ConversationId;\n\tmemo<T extends JsonValue>(name: string, context: Context): Promise<T | undefined>;\n\tmemo<T extends JsonValue>(name: string, candidate: T, context: Context): Promise<T>;\n}\n\nexport type HookResult<T> = T | undefined | Promise<T | undefined>;\n\n/** Hooks of the built-in generation task. */\nexport interface GenerationHooks {\n\t/** Before every request attempt, including recovery; the result is used for that request only. */\n\tbeforeRequest(\n\t\trequest: { readonly messages: readonly Message[] },\n\t\tapi: HookApi,\n\t\tcontext: Context,\n\t): HookResult<{ readonly messages: readonly Message[] }>;\n\t/** Every terminal provider message, before classification. */\n\tafterResponse(message: AssistantMessage, api: HookApi, context: Context): void | Promise<void>;\n\t/** A final answer; the first `continue` appends a user message and continues the run. */\n\tonYield(answer: AssistantMessage, api: HookApi, context: Context): HookResult<{ readonly continue: UserInput }>;\n\t/** After every tool of the round is terminal; `results` are the round's result entries in call order. */\n\tafterTools(assistant: EntryId, results: readonly EntryId[], api: HookApi, context: Context): void | Promise<void>;\n}\n\n/** Hooks of the built-in tool task. */\nexport interface ToolHooks {\n\t/** Before intent; the first `block` wins, otherwise `arguments` replace the call's arguments. A throw blocks. */\n\tbeforeTool(\n\t\tcall: ToolCall,\n\t\tapi: HookApi,\n\t\tcontext: Context,\n\t): HookResult<{ readonly arguments?: JsonObject; readonly block?: string }>;\n\t/** After execution, before the result entry; replaces the result. */\n\tafterTool(\n\t\tcall: ToolCall,\n\t\tresult: ToolExecutionResult,\n\t\tapi: HookApi,\n\t\tcontext: Context,\n\t): HookResult<ToolExecutionResult>;\n}\n\n/** Hooks of the built-in compaction task. */\nexport interface CompactionHooks {\n\t/**\n\t * After range selection, before summarizing; the first decision wins. `entries` are the active entries the summary\n\t * replaces, the head marker first, and `messages` their model context, the summarizer's source; `firstKept` is the\n\t * first entry kept verbatim.\n\t */\n\tbeforeCompact(\n\t\tcompaction: {\n\t\t\treadonly reason: CompactionReason;\n\t\t\treadonly entries: readonly EntryRecord[];\n\t\t\treadonly messages: readonly Message[];\n\t\t\treadonly firstKept: EntryId;\n\t\t\treadonly instructions?: string;\n\t\t},\n\t\tapi: HookApi,\n\t\tcontext: Context,\n\t): HookResult<{ readonly decline: true } | { readonly summary: string }>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/harness/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AttachedReplicatedState, Context, JsonValue } from \"@earendil-works/chord\";\nimport type {\n\tAssistantMessage,\n\tCacheRetention,\n\tMessage,\n\tModels,\n\tModelThinkingLevel,\n\tStatic,\n\tTool,\n\tToolCall,\n\tToolResultMessage,\n\tTransport,\n\tTSchema,\n\tUsage,\n\tUserMessage,\n} from \"@earendil-works/pi-ai\";\nimport type { ExecutionEnv } from \"../env/index.ts\";\nimport type {\n\tConversationId,\n\tConversationOwnership,\n\tConversationRecord,\n\tCursor,\n\tDocumentObserver,\n\tDocumentReader,\n\tEntryDraft,\n\tEntryId,\n\tEntryQuery,\n\tEntryRecord,\n\tJsonObject,\n\tPage,\n\tSession,\n\tSubmissionId,\n\tSubmissionRecord,\n\tTask,\n\tTaskId,\n\tTaskOptions,\n\tTaskRecord,\n\tTaskState,\n\tTx,\n\tWatchHandle,\n} from \"../types.ts\";\nimport type { TaskGraph, TaskGraphWatch } from \"./task-graph.ts\";\nimport type { UsageState } from \"./usage.ts\";\nimport type { ConversationView } from \"./view.ts\";\n\n/** Provider and model ID resolved through pi-ai `Models`. */\nexport type ModelRef = {\n\treadonly provider: string;\n\treadonly modelId: string;\n};\n\nexport type UserInput = UserMessage[\"content\"];\n\n/** Host submission: user input that may start a run, or a passive entry write. */\nexport type SubmissionDraft = {\n\treadonly requestId?: string;\n} & (\n\t| {\n\t\t\treadonly type: \"input\";\n\t\t\treadonly content: UserInput;\n\t\t\treadonly whenBusy?: \"steer\" | \"followUp\" | \"reject\";\n\t\t\treadonly entry?: never;\n\t }\n\t| {\n\t\t\treadonly type: \"write\";\n\t\t\treadonly entry: EntryDraft;\n\t\t\treadonly content?: never;\n\t\t\treadonly whenBusy?: never;\n\t }\n);\n\nexport type InputSubmissionDraft = Extract<SubmissionDraft, { readonly type: \"input\" }>;\n\nexport type SettledSubmissionRecord = SubmissionRecord & {\n\treadonly status: \"done\" | \"unanswered\";\n};\n\n/** Awaitable host object for one durably admitted submission. */\nexport interface Submission {\n\treadonly id: SubmissionId;\n\tstatus(context: Context): Promise<SubmissionRecord>;\n\twait(context: Context): Promise<SettledSubmissionRecord>;\n\tabort(context: Context): Promise<\"aborted\" | \"already_placed\" | \"settled\">;\n}\n\nexport type SettledTask<R> = TaskRecord<JsonValue, JsonValue, R> & {\n\treadonly state: Extract<TaskState<JsonValue, R>, { readonly status: \"terminal\" }>;\n};\n\n/** Erased executable task definition stored in the registry. */\nexport type AnyTask = {\n\treadonly definition: {\n\t\treadonly name: string;\n\t\treadonly version: number;\n\t\treadonly initial: unknown;\n\t\treadonly phases: Readonly<Record<string, unknown>>;\n\t\treadonly abort: unknown;\n\t\treadonly migrate?: unknown;\n\t\treadonly hooks?: object;\n\t};\n};\n\n/** Options of `Conversation.abort()`. */\nexport type ConversationAbortOptions = {\n\t/**\n\t * Cross background boundaries: mark every live task reached ignoring the background flag when the abort is admitted,\n\t * withdraw the queued inputs of every conversation reached, and wait until those tasks are terminal and the\n\t * conversation is ordinarily idle. Background work created afterwards is neither marked nor awaited.\n\t */\n\treadonly background?: boolean;\n};\n\n/** Hook handler map declared by a task definition. */\nexport type HooksOf<K> = K extends Task<infer _I, infer _S, infer _R, infer H> ? H : never;\n\n/**\n * Invocation-bound conversation operations for tasks and tools. Rejects after the invocation ends; passive entries are\n * written with ordinary transaction writes instead.\n */\nexport interface ConversationHandle {\n\treadonly id: ConversationId;\n\tsubmit(submission: InputSubmissionDraft, context: Context): Promise<Submission>;\n\t/** `Conversation.abort()`: withdraw queued inputs, abort the ordinary ownership scope, and wait until it is idle. */\n\tabort(context: Context, options?: ConversationAbortOptions): Promise<void>;\n\t/** Resolve when the conversation's ordinary ownership scope has no live non-background task. */\n\twaitForIdle(context: Context): Promise<void>;\n}\n\n/** Post-tools controls requested by a tool result. */\nexport type ToolControl = {\n\treadonly addTools?: readonly string[];\n\treadonly terminate?: true;\n\treadonly handoff?: string;\n};\n\n/** Remark about a call for the model and the UI, such as truncation or a spill path; never part of the tool's data. */\nexport type ToolDiagnostic = {\n\treadonly severity: \"info\" | \"warn\" | \"error\";\n\treadonly message: string;\n\treadonly code?: string;\n};\n\nexport type ToolExecutionResult<TDetails extends JsonValue = JsonValue> = {\n\t/** Omitted: the retained `output()` text becomes the content. */\n\treadonly content?: ToolResultMessage[\"content\"];\n\treadonly isError?: boolean;\n\t/** Omitted: the last `details()` value becomes the details. */\n\treadonly details?: TDetails;\n\t/** Added after those recorded through `api.diagnostic()`. */\n\treadonly diagnostics?: readonly ToolDiagnostic[];\n\t/** Spend of the execution itself, such as a model call; stored on the result and in `pi.usage.tools`. */\n\treadonly usage?: Usage;\n\treadonly control?: ToolControl;\n};\n\n/** Whether the tools of one round run at once or one after another in call order. */\nexport type ToolExecutionMode = \"parallel\" | \"sequential\";\n\n/** How many queued items of one mode a boundary places: the first, or all of them. */\nexport type QueueMode = \"all\" | \"one-at-a-time\";\n\n/**\n * Operations available to one tool invocation. A plain object, so a wrapper can spread it. Every operation rejects after\n * the invocation ends.\n */\nexport interface ToolExecutionApi<TDetails extends JsonValue = JsonValue> extends DocumentObserver, DocumentReader {\n\treadonly taskId: TaskId;\n\treadonly conversationId: ConversationId;\n\treadonly callId: string;\n\t/** The tool task's phase snapshot. */\n\treadonly registry: RegistrySnapshot;\n\t/** The calling conversation's agent, as the tool task's phase resolved it. */\n\tagent(context: Context): Promise<Agent>;\n\t/** Built by `HarnessOptions.env` for this call; `undefined` without an environment. */\n\treadonly env: ExecutionEnv | undefined;\n\t/** Append running output; it becomes the result content when the result omits `content`. */\n\toutput(chunk: string | Uint8Array): void;\n\t/** Record a model-visible remark about this call. */\n\tdiagnostic(diagnostic: ToolDiagnostic): void;\n\t/** Replace running details; the last value becomes the result details when the result omits `details`. */\n\tdetails(value: TDetails, context: Context): Promise<void>;\n\tcommit<T>(change: (tx: Tx) => T | Promise<T>, context: Context): Promise<T>;\n\tmemo<T extends JsonValue>(name: string, context: Context): Promise<T | undefined>;\n\tmemo<T extends JsonValue>(name: string, candidate: T, context: Context): Promise<T>;\n\tcreateTask<I, S extends { phase: string }, R, H extends object>(\n\t\ttask: Task<I, S, R, H>,\n\t\tinput: I,\n\t\toptions: Omit<TaskOptions, \"conversationId\">,\n\t\tcontext: Context,\n\t): Promise<TaskId<R>>;\n\tgetTask<R>(id: TaskId<R>, context: Context): Promise<TaskRecord<JsonValue, JsonValue, R> | undefined>;\n\twaitForTask<R>(id: TaskId<R>, context: Context): Promise<SettledTask<R>>;\n\t/** Invocation-bound handle of an existing conversation, such as one this tool created in `commit()`. */\n\tconversation(id: ConversationId, context: Context): Promise<ConversationHandle | undefined>;\n}\n\n/**\n * Executable tool registered in a registry. Only pi-ai `Tool` fields enter the transcript. `args` are typed by\n * `parameters`, which the Harness validates them against before `execute()`; `defineTool()` infers both generics.\n */\nexport type ToolRegistration<\n\tTParameters extends TSchema = TSchema,\n\tTDetails extends JsonValue = JsonValue,\n> = Tool<TParameters> & {\n\t/** Whether an interrupted execution may rerun on recovery. Default `unsafe`. */\n\treadonly replay?: \"safe\" | \"unsafe\";\n\t/** Default: the settings' `toolExecution`. One sequential call makes its whole round sequential. */\n\treadonly executionMode?: ToolExecutionMode;\n\t/**\n\t * Repair arguments models commonly get wrong before validation, such as a JSON string where an array belongs. Must be\n\t * pure and must not mutate `args`: it runs again when a call is retried before its intent is recorded. Its result is\n\t * still validated against `parameters`.\n\t */\n\tprepareArguments?(args: unknown): Static<TParameters>;\n\treadonly outputLimits?: {\n\t\treadonly maxBytes?: number;\n\t\treadonly maxLines?: number;\n\t\treadonly retain?: \"head\" | \"tail\";\n\t};\n\texecute(\n\t\targs: Static<TParameters>,\n\t\tapi: ToolExecutionApi<TDetails>,\n\t\tcontext: Context,\n\t): Promise<ToolExecutionResult<TDetails>>;\n};\n\n/** Input to system prompt section rendering for one request preparation. */\nexport type PromptInput<Tool extends ToolRegistration = ToolRegistration> = {\n\treadonly conversationId: ConversationId;\n\t/** The request's resolution; `agent.tools` are the tools offered in this request. */\n\treadonly agent: Agent<Tool>;\n\t/** Built by `HarnessOptions.env` for this preparation; `undefined` without an environment. */\n\treadonly env: ExecutionEnv | undefined;\n\t/** Sections already in effect after replaying the active transcript. */\n\treadonly shown: Readonly<Record<string, string>>;\n\t/** Committed document reads. */\n\treadonly read: DocumentReader;\n};\n\n/** One system prompt section; the agent's sections render in order before each request. */\nexport type PromptSection<Tool extends ToolRegistration = ToolRegistration> = {\n\treadonly key: string;\n\trender(input: PromptInput<Tool>, context: Context): string | undefined | Promise<string | undefined>;\n\t/** Default true: wrap the text as `<key>\\n...\\n</key>`. */\n\treadonly tag?: boolean;\n};\n\n/** Built by `hook()`; matches tasks by name. */\nexport type HookRegistration = { readonly task: string; readonly handlers: object };\n\n/** Built by `wrapTool()` and `wrapSection()`; targets a tool name or a section key. Wrappers are pure. */\nexport type Wrap<Tool extends ToolRegistration = ToolRegistration> =\n\t| { readonly tool: string; wrap(tool: Tool): Tool }\n\t| { readonly section: string; wrap(section: PromptSection<Tool>): PromptSection<Tool> };\n\n/** Named bundle of code; installed in a registry and selected by conversations by name. */\nexport interface Extension<Tool extends ToolRegistration = ToolRegistration> {\n\treadonly name: string;\n\treadonly tools?: readonly Tool[];\n\treadonly sections?: readonly PromptSection<Tool>[];\n\treadonly hooks?: readonly HookRegistration[];\n\t/** Apply where this extension is selected, in order. */\n\treadonly wraps?: readonly Wrap<Tool>[];\n\t/** Resolved by name for every task, whichever conversations select this extension. */\n\treadonly tasks?: readonly AnyTask[];\n}\n\n/** Immutable view of one published registry state. */\nexport interface RegistrySnapshot<Tool extends ToolRegistration = ToolRegistration> {\n\tinstalled(): readonly Extension<Tool>[];\n\textension(name: string): Extension<Tool> | undefined;\n\t/** Every installed tool with its extension, in install order. Names may repeat across extensions. */\n\ttools(): readonly { readonly extension: Extension<Tool>; readonly tool: Tool }[];\n\tsections(): readonly { readonly extension: Extension<Tool>; readonly section: PromptSection<Tool> }[];\n\t/** Built-in and installed task definitions. */\n\ttasks(): readonly AnyTask[];\n\ttask(name: string): AnyTask | undefined;\n}\n\n/** Read side of a registry consumed by a Harness. */\nexport interface RegistryReader<Tool extends ToolRegistration = ToolRegistration> {\n\t/** Immutable view of the whole current registry. */\n\tsnapshot(): RegistrySnapshot<Tool>;\n\t/** Called synchronously after every publication; wakes the scheduler to reconsider blocked tasks. */\n\tsubscribe(listener: () => void): () => void;\n}\n\n/** Application-owned registry of extensions. */\nexport interface Registry<Tool extends ToolRegistration = ToolRegistration> extends RegistryReader<Tool> {\n\t/** Install `extension`, or replace the installed extension with its name in place. Publishes at once. */\n\tinstall(extension: Extension<Tool>): void;\n\t/** Remove the installed extension with `extension.name`, whichever object it is. A later install appends. */\n\tuninstall(extension: Extension): void;\n}\n\n/** Stored choices of one conversation; names, not objects. Unset fields follow the host. */\nexport type AgentState = {\n\tmodel?: ModelRef;\n\tthinkingLevel?: ModelThinkingLevel;\n\t/** An array selects exactly these extensions, in order. An object edits the host default selection. */\n\textensions?: string[] | { add?: string[]; remove?: string[] };\n\t/** Filters the selected extensions' tools. An array offers exactly these, in order. */\n\ttools?: string[] | { remove: string[] };\n\t/** Rendered after every extension section, as the section `instructions`. */\n\tinstructions?: string;\n\t/** Directory within the environment's file system, passed to `HarnessOptions.env`. */\n\tcwd?: string;\n};\n\n/** A change to `pi.agent`: a given field replaces the stored one, `null` clears it, `undefined` changes nothing. */\nexport type AgentChange = {\n\treadonly model?: ModelRef | null;\n\treadonly thinkingLevel?: ModelThinkingLevel | null;\n\treadonly extensions?:\n\t\t| readonly Extension[]\n\t\t| { readonly add?: readonly Extension[]; readonly remove?: readonly Extension[] }\n\t\t| null;\n\treadonly tools?: readonly ToolRegistration[] | { readonly remove: readonly ToolRegistration[] } | null;\n\treadonly instructions?: string | null;\n\treadonly cwd?: string | null;\n};\n\n/** A conversation's agent resolved against a registry snapshot and the settings. */\nexport type Agent<Tool extends ToolRegistration = ToolRegistration> = {\n\treadonly model?: ModelRef;\n\treadonly thinkingLevel: ModelThinkingLevel;\n\treadonly extensions: readonly Extension<Tool>[];\n\t/** The tools a request offers, in order. */\n\treadonly tools: readonly Tool[];\n\t/** Extension sections, then `instructions` when set. */\n\treadonly sections: readonly PromptSection<Tool>[];\n\treadonly instructions?: string;\n\treadonly cwd?: string;\n};\n\n/**\n * Runs inside the creating commit, after the creation hook and the `agent` change. The conversation creation is already\n * a table write, so table reads here throw `ReadAfterWrite`; document access remains available.\n */\nexport type ConversationInit = (tx: Tx, conversationId: ConversationId) => void | Promise<void>;\n\nexport type ConversationCreateOptions = {\n\treadonly ownership: ConversationOwnership;\n\t/** Applied in the creating commit after the creation hook's copy, before `init`. */\n\treadonly agent?: AgentChange;\n\treadonly init?: ConversationInit;\n};\n\n/** Curated pi-ai request options; absent fields use pi-ai defaults. */\nexport type ConversationStreamOptions = {\n\ttransport?: Transport;\n\ttimeoutMs?: number;\n\t/** Provider/SDK retries inside one request attempt. */\n\tmaxRetries?: number;\n\tmaxRetryDelayMs?: number;\n\theaders?: Record<string, string>;\n\tmetadata?: JsonObject;\n\tcacheRetention?: CacheRetention;\n\tdeferred?: boolean | { window?: \"15m\" | \"1h\" | \"24h\" };\n};\n\n/** Durable generation attempt retries; the JSON shape of pi-ai `RetryPolicy`. */\nexport type ConversationRetryPolicy = {\n\tenabled: boolean;\n\tmaxRetries: number;\n\tbaseDelayMs: number;\n\tmaxAgentDelayMs?: number;\n};\n\n/** Automatic compaction thresholds (spec §8.7); manual compaction ignores `enabled`. */\nexport type CompactionPolicy = {\n\t/** Threshold and overflow compaction. */\n\tenabled: boolean;\n\t/** Room kept free for the answer: generation blocks to compact above `contextWindow - reserveTokens`. */\n\treserveTokens: number;\n\t/** Approximate size of the recent context a summary keeps verbatim. */\n\tkeepRecentTokens: number;\n\t/** Background compaction starts `backgroundTokens` below the blocking threshold; `0` disables it. */\n\tbackgroundTokens: number;\n};\n\n/** Why a compaction runs: `compact()`, a threshold in generation preparation, or a context overflow. */\nexport type CompactionReason = \"manual\" | \"threshold\" | \"overflow\";\n\n/**\n * `entryId` of a blocking compaction's summary, or the `submissionId` of a conversation-owned compaction's summary\n * write; both absent when nothing was compacted.\n */\nexport type CompactionResult = { entryId?: EntryId; submissionId?: SubmissionId };\n\n/** Harness-wide run policy. Read at every resolution and never copied; getters are fine. Synchronous: some readers run on the Session line. */\nexport type HarnessSettings = {\n\t/** Default extension selection; absent: every installed extension, in install order. */\n\treadonly extensions?: readonly Extension[];\n\treadonly stream?: ConversationStreamOptions;\n\treadonly retry?: Partial<ConversationRetryPolicy>;\n\treadonly compaction?: Partial<CompactionPolicy>;\n\treadonly toolExecution?: ToolExecutionMode;\n\treadonly steeringMode?: QueueMode;\n\treadonly followUpMode?: QueueMode;\n};\n\n/** Resolved settings: every field over its built-in default, object fields merged. */\nexport type Settings = {\n\t/** Absent: every installed extension, in install order. */\n\treadonly extensions?: readonly Extension[];\n\treadonly stream: ConversationStreamOptions;\n\treadonly retry: ConversationRetryPolicy;\n\treadonly compaction: CompactionPolicy;\n\treadonly toolExecution: ToolExecutionMode;\n\treadonly steeringMode: QueueMode;\n\treadonly followUpMode: QueueMode;\n};\n\n/** What `HarnessOptions.env` builds an environment for. */\nexport type EnvTarget = {\n\treadonly conversationId: ConversationId;\n\t/** The conversation's agent `cwd`. */\n\treadonly cwd?: string;\n\treadonly read: DocumentReader;\n};\n\nexport type HarnessOptions<Tool extends ToolRegistration = ToolRegistration> = {\n\t/** pi-ai model access used by generation. */\n\treadonly models: Models;\n\treadonly registry: RegistryReader<Tool>;\n\treadonly settings?: HarnessSettings;\n\t/** Builds a conversation's environment at each use. Never called on the Session line; may be async. */\n\treadonly env?: (target: EnvTarget, context: Context) => ExecutionEnv | undefined | Promise<ExecutionEnv | undefined>;\n\t/**\n\t * Runs in every commit that creates or forks a conversation, raw `tx.createConversation()` included, after the\n\t * built-in `pi.*` documents and before the conveniences apply `agent` and run `init`. A fork already has its copies.\n\t * Table reads throw `ReadAfterWrite`, as in `init`; a throw fails the creating commit.\n\t */\n\treadonly conversationCreated?: (tx: Tx, conversation: ConversationRecord) => void | Promise<void>;\n\treadonly now?: () => number;\n\t/** Receives extension failures that do not fail the calling operation. Must not throw. */\n\treadonly onReport?: (error: unknown) => void;\n};\n\n/** Live task and what the scheduler would do with it under the current registry. */\nexport type TaskInspection = {\n\treadonly record: TaskRecord<JsonValue, JsonValue, JsonValue>;\n\treadonly state: /** An invocation is active. */\n\t\t| { readonly kind: \"running\" }\n\t\t/** The next scheduling pass reserves it; `migrates` when its definition is newer and has `migrate`. */\n\t\t| { readonly kind: \"ready\"; readonly migrates: boolean }\n\t\t/**\n\t\t * Waits for these live tasks: the live part of its `on`, or, when abort-marked, its live ordinary owned work, which\n\t\t * must end before its abort handler starts.\n\t\t */\n\t\t| { readonly kind: \"waiting\"; readonly on: readonly TaskId[] }\n\t\t/** Outcome held until its ordinary owned work drains. */\n\t\t| { readonly kind: \"completing\" }\n\t\t/** No registered definition can take it; aborting it settles it as `orphaned`. */\n\t\t| {\n\t\t\t\treadonly kind: \"blocked\";\n\t\t\t\treadonly reason: \"missing_task\" | \"task_too_old\" | \"migration_failed\";\n\t\t\t\treadonly error?: unknown;\n\t\t };\n};\n\n/** Point-in-time view of live work: unfinished tasks and submissions, read on the Session line. */\nexport type HarnessInspection = {\n\treadonly scheduling: \"paused\" | \"running\" | \"closing\";\n\treadonly tasks: readonly TaskInspection[];\n\t/** Queued and placed submissions, in ID order. */\n\treadonly submissions: readonly SubmissionRecord[];\n};\n\n/** Raw active transcript and derived model context. */\nexport type ContextView = {\n\t/** Newest applicable head marker, if any. */\n\treadonly head: EntryRecord | undefined;\n\t/** Raw active entries: the head marker followed by non-head entries from its head through the tail. */\n\treadonly entries: readonly EntryRecord[];\n\t/** Per entry of `entries`, its model messages after edits and excluded stop reasons, before tool result ordering. */\n\treadonly contributions: readonly (readonly Message[])[];\n\t/** Model context for the next provider request. */\n\treadonly messages: readonly Message[];\n};\n\n/** Stateless handle for one conversation, bound to the Harness that returned it. Compare handles by `id`. */\nexport interface Conversation {\n\treadonly id: ConversationId;\n\n\t/** Resolved with the current registry snapshot and settings. */\n\tagent(context: Context): Promise<Agent>;\n\t/** `configure()` in its own commit. */\n\tconfigure(change: AgentChange, context: Context): Promise<void>;\n\n\t/**\n\t * Durably admit user input or a passive entry write. A busy conversation, or one with queued items, queues it in\n\t * `pi.inbox`; `whenBusy: \"reject\"` rejects with `ConversationBusy` instead and writes nothing.\n\t */\n\tsubmit(submission: SubmissionDraft, context: Context): Promise<Submission>;\n\t/**\n\t * Admit a write of a `pi.reset` entry that starts a new context, carrying `handoff` as a user message when given.\n\t * Resolves after admission; while busy, it is placed at the next boundary.\n\t */\n\treset(handoff: string | undefined, context: Context): Promise<void>;\n\t/**\n\t * Admit a manual compaction task and return its ID. It summarizes while the conversation keeps working and places its\n\t * summary through a write submission: at once when idle, otherwise at the next boundary (spec §8.7).\n\t */\n\tcompact(instructions: string | undefined, context: Context): Promise<TaskId<CompactionResult>>;\n\n\t/** Session commit whose `tx.createTask()` defaults to this conversation. */\n\tcommit<T>(change: (tx: Tx) => T | Promise<T>, context: Context): Promise<T>;\n\tcontext(context: Context): Promise<ContextView>;\n\t/** Newest-first fork-aware history of this conversation. */\n\tentries(\n\t\tquery: Omit<EntryQuery, \"conversationId\">,\n\t\tlimit: number,\n\t\tcursor: Cursor | undefined,\n\t\tcontext: Context,\n\t): Promise<Page<EntryRecord, Cursor>>;\n\tfork(at: EntryId, options: ConversationCreateOptions, context: Context): Promise<Conversation>;\n\t/**\n\t * Withdraw queued inputs (queued writes stay), mark every live non-background task of the ordinary ownership scope,\n\t * signal them, and resolve once the scope is idle. Background subtrees survive unless `background` is set.\n\t */\n\tabort(context: Context, options?: ConversationAbortOptions): Promise<void>;\n\t/**\n\t * Resolve when the ordinary ownership scope has no live non-background task: this conversation and the conversations\n\t * owned, transitively, by its non-background tasks.\n\t */\n\twaitForIdle(context: Context): Promise<void>;\n\t/** The structural view (spec §9.3) as a disposable read-only Chord state. */\n\tviewState(context: Context): Promise<AttachedReplicatedState<ConversationView>>;\n\t/** The structural view as a serialized exact-frame watch with bounded pending frames. */\n\twatch(context: Context): Promise<ConversationWatch>;\n}\n\nexport type ConversationWatch = WatchHandle<ConversationView>;\n\n/** Durable agent harness over one Session. */\nexport interface Harness extends Session {\n\t/**\n\t * Enable task scheduling. Idempotent; throws after close. Calls that ask for progress enable it too:\n\t * `Conversation.submit()`, `Conversation.compact()`, `Conversation.abort()`, `Submission.wait()`, `waitForTask()`,\n\t * `Harness.waitForIdle()`, and `Conversation.waitForIdle()`. Read-only viewers never do.\n\t */\n\tresume(): void;\n\n\t/** Return the reserved root conversation, creating it with `agent` and `init` in one commit when absent. */\n\troot(\n\t\tcontext: Context,\n\t\toptions?: { readonly agent?: AgentChange; readonly init?: ConversationInit },\n\t): Promise<Conversation>;\n\tconversation(id: ConversationId, context: Context): Promise<Conversation | undefined>;\n\tcreateConversation(options: ConversationCreateOptions, context: Context): Promise<Conversation>;\n\n\tgetTask<R>(id: TaskId<R>, context: Context): Promise<TaskRecord<JsonValue, JsonValue, R> | undefined>;\n\t/** Live tasks and unsettled submissions. Writes nothing and runs no task code. */\n\tinspect(context: Context): Promise<HarnessInspection>;\n\t/** Reacquire a submission, for example after reopen. */\n\tsubmission(id: SubmissionId, context: Context): Promise<Submission | undefined>;\n\t/** `not_found` for an unknown submission or one of another conversation than `conversationId`. */\n\tabortSubmission(\n\t\tid: SubmissionId,\n\t\tcontext: Context,\n\t\tconversationId?: ConversationId,\n\t): Promise<\"aborted\" | \"already_placed\" | \"settled\" | \"not_found\">;\n\t/**\n\t * Commit the abort mark, signal and join an active run invocation, and schedule the abort invocation. A task whose\n\t * definition cannot take it settles as `orphaned` instead.\n\t */\n\tabortTask(id: TaskId, context: Context): Promise<\"marked\" | \"terminal\">;\n\t/** Resolve with the terminal receipt; cancelling `context` cancels only this wait. */\n\twaitForTask<R>(id: TaskId<R>, context: Context): Promise<SettledTask<R>>;\n\t/** Resolve when the ordinary ownership scope of every ownerless conversation has no live non-background task. */\n\twaitForIdle(context: Context): Promise<void>;\n\t/** Session total: every conversation's `pi.usage` summed. */\n\tusage(context: Context): Promise<UsageState>;\n\t/** Every live task with its owner edge, status, and owned conversations (spec §9.5), as a disposable Chord state. */\n\ttaskGraph(context: Context): Promise<AttachedReplicatedState<TaskGraph>>;\n\t/** The task graph as a serialized exact-frame watch with bounded pending frames. */\n\twatchTaskGraph(context: Context): Promise<TaskGraphWatch>;\n}\n\n/** What a hook may use: committed reads and the asking task's memos, which hooks and the task share. */\nexport interface HookApi extends DocumentReader {\n\treadonly taskId: TaskId;\n\treadonly conversationId: ConversationId;\n\tmemo<T extends JsonValue>(name: string, context: Context): Promise<T | undefined>;\n\tmemo<T extends JsonValue>(name: string, candidate: T, context: Context): Promise<T>;\n}\n\nexport type HookResult<T> = T | undefined | Promise<T | undefined>;\n\n/** Hooks of the built-in generation task. */\nexport interface GenerationHooks {\n\t/** Before every request attempt, including recovery; the result is used for that request only. */\n\tbeforeRequest(\n\t\trequest: { readonly messages: readonly Message[] },\n\t\tapi: HookApi,\n\t\tcontext: Context,\n\t): HookResult<{ readonly messages: readonly Message[] }>;\n\t/** Every terminal provider message, before classification. */\n\tafterResponse(message: AssistantMessage, api: HookApi, context: Context): void | Promise<void>;\n\t/** A final answer; the first `continue` appends a user message and continues the run. */\n\tonYield(answer: AssistantMessage, api: HookApi, context: Context): HookResult<{ readonly continue: UserInput }>;\n\t/** After every tool of the round is terminal; `results` are the round's result entries in call order. */\n\tafterTools(assistant: EntryId, results: readonly EntryId[], api: HookApi, context: Context): void | Promise<void>;\n}\n\n/** Hooks of the built-in tool task. */\nexport interface ToolHooks {\n\t/** Before intent; the first `block` wins, otherwise `arguments` replace the call's arguments. A throw blocks. */\n\tbeforeTool(\n\t\tcall: ToolCall,\n\t\tapi: HookApi,\n\t\tcontext: Context,\n\t): HookResult<{ readonly arguments?: JsonObject; readonly block?: string }>;\n\t/** After execution, before the result entry; replaces the result. */\n\tafterTool(\n\t\tcall: ToolCall,\n\t\tresult: ToolExecutionResult,\n\t\tapi: HookApi,\n\t\tcontext: Context,\n\t): HookResult<ToolExecutionResult>;\n}\n\n/** Hooks of the built-in compaction task. */\nexport interface CompactionHooks {\n\t/**\n\t * After range selection, before summarizing; the first decision wins. `entries` are the active entries the summary\n\t * replaces, the head marker first, and `messages` their model context, the summarizer's source; `firstKept` is the\n\t * first entry kept verbatim.\n\t */\n\tbeforeCompact(\n\t\tcompaction: {\n\t\t\treadonly reason: CompactionReason;\n\t\t\treadonly entries: readonly EntryRecord[];\n\t\t\treadonly messages: readonly Message[];\n\t\t\treadonly firstKept: EntryId;\n\t\t\treadonly instructions?: string;\n\t\t},\n\t\tapi: HookApi,\n\t\tcontext: Context,\n\t): HookResult<{ readonly decline: true } | { readonly summary: string }>;\n}\n"]}
|
package/dist/harness/view.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export type ConversationView = {
|
|
|
7
7
|
readonly conversation: ConversationRecord;
|
|
8
8
|
/** Raw active entries, as `ContextView.entries`: the head marker, then the non-head entries from its head. */
|
|
9
9
|
readonly entries: readonly EntryRecord[];
|
|
10
|
-
/** `pi.
|
|
10
|
+
/** `pi.agent`, `pi.live`, `pi.inbox`, and `pi.usage`, keyed by kind; absent documents are absent. */
|
|
11
11
|
readonly docs: Readonly<Record<string, JsonObject>>;
|
|
12
12
|
};
|
|
13
13
|
/** Receives each next revision of a mount, and the Session's close. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../src/harness/view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,uBAAuB,EAAE,KAAK,OAAO,EAAmC,MAAM,uBAAuB,CAAC;AAEpH,OAAO,EAAqC,KAAK,EAAE,EAAa,MAAM,6BAA6B,CAAC;AAEpG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EACX,iBAAiB,EAEjB,cAAc,EACd,kBAAkB,EAElB,WAAW,EACX,UAAU,EACV,OAAO,EACP,WAAW,EACX,MAAM,aAAa,CAAC;AAQrB,mGAAmG;AACnG,MAAM,MAAM,gBAAgB,GAAG;IAC9B,QAAQ,CAAC,YAAY,EAAE,kBAAkB,CAAC;IAC1C,8GAA8G;IAC9G,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC,
|
|
1
|
+
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../src/harness/view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,uBAAuB,EAAE,KAAK,OAAO,EAAmC,MAAM,uBAAuB,CAAC;AAEpH,OAAO,EAAqC,KAAK,EAAE,EAAa,MAAM,6BAA6B,CAAC;AAEpG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EACX,iBAAiB,EAEjB,cAAc,EACd,kBAAkB,EAElB,WAAW,EACX,UAAU,EACV,OAAO,EACP,WAAW,EACX,MAAM,aAAa,CAAC;AAQrB,mGAAmG;AACnG,MAAM,MAAM,gBAAgB,GAAG;IAC9B,QAAQ,CAAC,YAAY,EAAE,kBAAkB,CAAC;IAC1C,8GAA8G;IAC9G,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC,qGAAqG;IACrG,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;CACpD,CAAC;AAEF,uEAAuE;AACvE,MAAM,MAAM,YAAY,GAAG;IAC1B,OAAO,CAAC,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9E,wFAAwF;IACxF,WAAW,CAAC,CACX,MAAM,EAAE,gBAAgB,EACxB,KAAK,EAAE,gBAAgB,EACvB,GAAG,EAAE,SAAS,EAAE,EAAE,EAClB,WAAW,EAAE,iBAAiB,EAC9B,OAAO,EAAE,OAAO,GACd,IAAI,CAAC;IACR,YAAY,IAAI,IAAI,CAAC;CACrB,CAAC;AAeF,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAIpE;AAED;;;GAGG;AACH,qBAAa,iBAAiB;;IAM7B,YAAY,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAajD;IAED,sDAAsD;IAChD,KAAK,CAAC,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,uBAAuB,CAAC,gBAAgB,CAAC,CAAC,CAYpG;IAED,iFAAiF;IAC3E,KAAK,CAAC,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAaxF;IAED;;;;OAIG;IACH,MAAM,CAAC,CAAC,SAAS,YAAY,EAC5B,EAAE,EAAE,cAAc,EAClB,MAAM,EAAE,CAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,IAAI,EAAE,OAAO,EAAE,OAAO,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAC1F,OAAO,EAAE,OAAO,GACd,OAAO,CAAC;QAAE,QAAQ,EAAE,CAAC,CAAC;QAAC,MAAM,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC,CAe9C;CAiBD"}
|
package/dist/harness/view.js
CHANGED
|
@@ -2,18 +2,13 @@ import { replicatedState } from "@earendil-works/chord";
|
|
|
2
2
|
import { withoutAbortSignal } from "@earendil-works/chord/context";
|
|
3
3
|
import { applyImmutable } from "@earendil-works/chord/delta";
|
|
4
4
|
import { CommittedStateSource, CommittedWatch } from "../session/observation.js";
|
|
5
|
-
import {
|
|
5
|
+
import { AgentDoc } from "./agent.js";
|
|
6
6
|
import { activeEntries, captureContextBounds } from "./context.js";
|
|
7
7
|
import { InboxDoc } from "./inbox.js";
|
|
8
8
|
import { LiveDoc } from "./live.js";
|
|
9
9
|
import { UsageDoc } from "./usage.js";
|
|
10
10
|
import { closedError } from "./util.js";
|
|
11
|
-
const MOUNTED = [
|
|
12
|
-
ConversationConfig,
|
|
13
|
-
LiveDoc,
|
|
14
|
-
InboxDoc,
|
|
15
|
-
UsageDoc,
|
|
16
|
-
];
|
|
11
|
+
const MOUNTED = [AgentDoc, LiveDoc, InboxDoc, UsageDoc];
|
|
17
12
|
const MOUNTED_KINDS = new Set(MOUNTED.map((token) => token.definition.kind));
|
|
18
13
|
const VIEWS = new WeakMap();
|
|
19
14
|
/** The view mounts of a Harness, for adapters built on them. */
|
package/dist/harness/view.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view.js","sourceRoot":"","sources":["../../src/harness/view.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8D,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACpH,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,cAAc,EAAyC,MAAM,6BAA6B,CAAC;AACpG,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAajF,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAyBxC,MAAM,OAAO,GAAG;IACf,kBAAkB;IAClB,OAAO;IACP,QAAQ;IACR,QAAQ;CACkD,CAAC;AAC5D,MAAM,aAAa,GAAwB,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;AAUlG,MAAM,KAAK,GAAG,IAAI,OAAO,EAA6B,CAAC;AAEvD,gEAAgE;AAChE,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAChD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,KAAK,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IAC1D,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,iBAAiB;IACpB,QAAQ,CAAc;IACtB,QAAQ,CAAU;IAClB,OAAO,GAAG,IAAI,GAAG,EAAyB,CAAC;IACpD,OAAO,GAAG,KAAK,CAAC;IAEhB,YAAY,OAAoB,EAAE,OAAgB;QACjD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACzB,OAAO,CAAC,gBAAgB,CAAC,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE;YACjD,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO;gBAAE,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;QAClF,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,cAAc,CAAC,GAAG,EAAE;YAC3B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;gBACxC,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC;oBAAE,QAAQ,CAAC,YAAY,EAAE,CAAC;YACtE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,sDAAsD;IACtD,KAAK,CAAC,KAAK,CAAC,EAAkB,EAAE,OAAgB;QAC/C,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAC7C,EAAE,EACF,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,oBAAoB,CAAmB,KAAK,EAAE,OAAO,CAAC,EAC9E,OAAO,CACP,CAAC;QACF,IAAI,CAAC;YACJ,OAAO,eAAe,CAAC,QAAQ,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,EAAE,CAAC;YACT,MAAM,KAAK,CAAC;QACb,CAAC;IACF,CAAC;IAED,iFAAiF;IACjF,KAAK,CAAC,KAAK,CAAC,EAAkB,EAAE,OAAgB;QAC/C,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CACrC,EAAE,EACF,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,cAAc,CAAmB,KAAK,EAAE,OAAO,CAAC,EACxE,OAAO,CACP,CAAC;QACF,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;QACnC,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACrB,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,MAAM,CAAC,MAAM,CAAC;QACrB,CAAC;QACD,IAAI,MAAM,KAAK,SAAS;YAAE,QAAQ,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;QAC/D,OAAO,QAAQ,CAAC;IACjB,CAAC;IAED;;;;OAIG;IACH,MAAM,CACL,EAAkB,EAClB,MAA0F,EAC1F,OAAgB;QAEhB,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,IAAI,EAAE;YAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;YACvE,MAAM,MAAM,GAAG,GAAS,EAAE;gBACzB,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACjC,IAAI,KAAK,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,KAAK;oBAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC3F,CAAC,CAAC;YACF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YAClE,mFAAmF;YACnF,IAAI,IAAI,CAAC,OAAO;gBAAE,MAAM,WAAW,EAAE,CAAC;YACtC,OAAO,CAAC,WAAW,EAAE,cAAc,EAAE,CAAC;YACtC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YAC5B,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC9B,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAkB,EAAE,OAAgB;QAChD,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACnE,IAAI,YAAY,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,EAAE,iBAAiB,CAAC,CAAC;QACrF,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;QACtE,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QACxE,MAAM,IAAI,GAA+B,EAAE,CAAC;QAC5C,MAAM,YAAY,GAAG,IAAI,GAAG,EAA+C,CAAC;QAC5E,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,0BAA0B,CAAC,KAAK,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;YAClF,IAAI,MAAM,KAAK,SAAS;gBAAE,SAAS;YACnC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;YAC3C,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5F,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;IAC7F,CAAC;CACD;AAED,+GAA+G;AAC/G,SAAS,OAAO,CAAC,EAAkB,EAAE,KAAY,EAAE,WAA8B,EAAE,OAAgB;IAClG,MAAM,MAAM,GAAS,EAAE,CAAC;IACxB,MAAM,QAAQ,GAAS,EAAE,CAAC;IAC1B,IAAI,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC;IAClC,0CAA0C;IAC1C,KAAK,MAAM,MAAM,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;QAC1C,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,cAAc,KAAK,EAAE,EAAE,CAAC;YACnE,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;YAC3B,MAAM,KAAK,GAAG,KAA6B,CAAC;YAC5C,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC9B,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAC9D,OAAO,GAAG,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,CAAC;gBAC9B,SAAS;YACV,CAAC;YACD,wGAAwG;YACxG,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC;YAC1B,IAAI,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,SAAS,IAAI,SAAS,CAAC,EAAE,IAAI,MAAM,CAAC,CAAC;YACpG,IAAI,IAAI,GAAG,CAAC;gBAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;YACpC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACpD,OAAO,GAAG,CAAC,KAAK,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YAC1C,SAAS;QACV,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,IAAI,MAAM,CAAC,cAAc,KAAK,EAAE;YAAE,SAAS;QACzE,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;QAChC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,KAAK,SAAS;YAAE,SAAS;QAC1E,MAAM,IAAI,GAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YAC3B,IAAI,OAAO,EAAE,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,EAAE;gBAAE,SAAS;YAC/C,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;QAC1B,CAAC;aAAM,IAAI,OAAO,EAAE,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,OAAO,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC;YACnF,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,GAAG;gBAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;QAC9D,CAAC;aAAM,CAAC;YACP,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,OAAQ,EAAE,CAAC,CAAC;YACzE,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACxC,CAAC;IACF,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC;IAC3B,MAAM,GAAG,GAAG,CAAC,GAAG,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC;IACrC,MAAM,YAAY,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACjD,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACtF,KAAK,CAAC,KAAK,GAAG,OAAO,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,CAAC;QACxE,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC;YAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,YAAY,CAAC,CAAC;IACjG,CAAC;IACD,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7C,QAAQ,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;IAC7E,CAAC;AACF,CAAC;AAED,iFAAiF;AACjF,SAAS,QAAQ,CAAC,EAAM,EAAE,MAAoB;IAC7C,MAAM,EAAE,GAAG,CAAC,IAAU,EAAgB,EAAE,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,IAAI,CAA4B,CAAC;IACzF,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACf,KAAK,GAAG;YACP,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7B,KAAK,GAAG;YACP,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,KAAK,GAAG;YACP,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAChC,KAAK,GAAG;YACP,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAChC,KAAK,GAAG;YACP,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,KAAK,GAAG;YACP,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAChC,KAAK,GAAG;YACP,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC;AACF,CAAC","sourcesContent":["import { type AttachedReplicatedState, type Context, type JsonValue, replicatedState } from \"@earendil-works/chord\";\nimport { withoutAbortSignal } from \"@earendil-works/chord/context\";\nimport { applyImmutable, type NonEmptyPath, type Op, type Path } from \"@earendil-works/chord/delta\";\nimport { CommittedStateSource, CommittedWatch } from \"../session/observation.ts\";\nimport type { SessionImpl } from \"../session/session.ts\";\nimport type {\n\tCommitPublication,\n\tConversationDocToken,\n\tConversationId,\n\tConversationRecord,\n\tDocumentId,\n\tEntryRecord,\n\tJsonObject,\n\tStorage,\n\tWatchHandle,\n} from \"../types.ts\";\nimport { ConversationConfig } from \"./config.ts\";\nimport { activeEntries, captureContextBounds } from \"./context.ts\";\nimport { InboxDoc } from \"./inbox.ts\";\nimport { LiveDoc } from \"./live.ts\";\nimport { UsageDoc } from \"./usage.ts\";\nimport { closedError } from \"./util.ts\";\n\n/** Structural mount of one conversation's active transcript and built-in documents (spec §9.3). */\nexport type ConversationView = {\n\treadonly conversation: ConversationRecord;\n\t/** Raw active entries, as `ContextView.entries`: the head marker, then the non-head entries from its head. */\n\treadonly entries: readonly EntryRecord[];\n\t/** `pi.conversation.config`, `pi.live`, `pi.inbox`, and `pi.usage`, keyed by kind; absent documents are absent. */\n\treadonly docs: Readonly<Record<string, JsonObject>>;\n};\n\n/** Receives each next revision of a mount, and the Session's close. */\nexport type ViewObserver = {\n\tadvance?(value: ConversationView, ops: readonly Op[], context: Context): void;\n\t/** Every publication, after the mount took it; `ops` are the mount's, possibly none. */\n\tpublication?(\n\t\tbefore: ConversationView,\n\t\tafter: ConversationView,\n\t\tops: readonly Op[],\n\t\tpublication: CommitPublication,\n\t\tcontext: Context,\n\t): void;\n\tcloseSession(): void;\n};\n\nconst MOUNTED = [\n\tConversationConfig,\n\tLiveDoc,\n\tInboxDoc,\n\tUsageDoc,\n] as unknown as readonly ConversationDocToken<JsonObject>[];\nconst MOUNTED_KINDS: ReadonlySet<string> = new Set(MOUNTED.map((token) => token.definition.kind));\n\n/** One conversation's mount: its current revision, the document incarnations it shows, and its observers. */\ntype Mount = {\n\tvalue: ConversationView;\n\t/** Mounted incarnation and definition version per kind; another incarnation or version is set whole. */\n\treadonly docs: Map<string, { id: DocumentId; version: number }>;\n\treadonly observers: Set<ViewObserver>;\n};\n\nconst VIEWS = new WeakMap<object, ConversationViews>();\n\n/** The view mounts of a Harness, for adapters built on them. */\nexport function conversationViews(harness: object): ConversationViews {\n\tconst views = VIEWS.get(harness);\n\tif (views === undefined) throw new Error(\"Not a Harness\");\n\treturn views;\n}\n\n/**\n * The Harness's conversation view mounts: at most one per conversation, built on the Session line by its first\n * observer and dropped with its last. Each mount advances from the Session's commit publications, which are durable.\n */\nexport class ConversationViews {\n\treadonly #session: SessionImpl;\n\treadonly #storage: Storage;\n\treadonly #mounts = new Map<ConversationId, Mount>();\n\t#closed = false;\n\n\tconstructor(session: SessionImpl, storage: Storage) {\n\t\tthis.#session = session;\n\t\tthis.#storage = storage;\n\t\tVIEWS.set(session, this);\n\t\tsession.subscribeCommits((publication, context) => {\n\t\t\tfor (const [id, mount] of this.#mounts) advance(id, mount, publication, context);\n\t\t});\n\t\tsession.subscribeClose(() => {\n\t\t\tthis.#closed = true;\n\t\t\tfor (const mount of this.#mounts.values())\n\t\t\t\tfor (const observer of [...mount.observers]) observer.closeSession();\n\t\t\tthis.#mounts.clear();\n\t\t});\n\t}\n\n\t/** A disposable read-only Chord state of the view. */\n\tasync state(id: ConversationId, context: Context): Promise<AttachedReplicatedState<ConversationView>> {\n\t\tconst { observer, detach } = await this.attach(\n\t\t\tid,\n\t\t\t(value, release) => new CommittedStateSource<ConversationView>(value, release),\n\t\t\tcontext,\n\t\t);\n\t\ttry {\n\t\t\treturn replicatedState(observer);\n\t\t} catch (error) {\n\t\t\tdetach();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/** A serialized exact-frame watch of the view; cancelling `context` stops it. */\n\tasync watch(id: ConversationId, context: Context): Promise<WatchHandle<ConversationView>> {\n\t\tconst { observer } = await this.attach(\n\t\t\tid,\n\t\t\t(value, release) => new CommittedWatch<ConversationView>(value, release),\n\t\t\tcontext,\n\t\t);\n\t\tconst signal = context.abortSignal;\n\t\tif (signal?.aborted) {\n\t\t\tobserver.cancel();\n\t\t\tthrow signal.reason;\n\t\t}\n\t\tif (signal !== undefined) observer.observeCancellation(signal);\n\t\treturn observer;\n\t}\n\n\t/**\n\t * Register an observer created from the current revision, atomically on the Session line: it sees every later\n\t * publication and nothing earlier. `create` may read committed Storage, still on the line. `release` drops it, and\n\t * the mount with its last observer.\n\t */\n\tattach<O extends ViewObserver>(\n\t\tid: ConversationId,\n\t\tcreate: (value: ConversationView, release: () => void, storage: Storage) => O | Promise<O>,\n\t\tcontext: Context,\n\t): Promise<{ observer: O; detach: () => void }> {\n\t\treturn this.#session.readOnLine(async () => {\n\t\t\tconst mount = this.#mounts.get(id) ?? (await this.#build(id, context));\n\t\t\tconst detach = (): void => {\n\t\t\t\tmount.observers.delete(observer);\n\t\t\t\tif (mount.observers.size === 0 && this.#mounts.get(id) === mount) this.#mounts.delete(id);\n\t\t\t};\n\t\t\tconst observer = await create(mount.value, detach, this.#storage);\n\t\t\t// Close or cancellation may begin while the mount hydrates; register nothing then.\n\t\t\tif (this.#closed) throw closedError();\n\t\t\tcontext.abortSignal?.throwIfAborted();\n\t\t\tthis.#mounts.set(id, mount);\n\t\t\tmount.observers.add(observer);\n\t\t\treturn { observer, detach };\n\t\t});\n\t}\n\n\tasync #build(id: ConversationId, context: Context): Promise<Mount> {\n\t\tconst conversation = await this.#storage.conversation(id, context);\n\t\tif (conversation === undefined) throw new Error(`Conversation ${id} does not exist`);\n\t\tconst bounds = await captureContextBounds(this.#storage, id, context);\n\t\tconst entries = await activeEntries(this.#storage, id, bounds, context);\n\t\tconst docs: Record<string, JsonObject> = {};\n\t\tconst incarnations = new Map<string, { id: DocumentId; version: number }>();\n\t\tfor (const token of MOUNTED) {\n\t\t\tconst loaded = await this.#session.conversationDocumentOnLine(token, id, context);\n\t\t\tif (loaded === undefined) continue;\n\t\t\tdocs[token.definition.kind] = loaded.value;\n\t\t\tincarnations.set(token.definition.kind, { id: loaded.record.id, version: loaded.version });\n\t\t}\n\t\treturn { value: { conversation, entries, docs }, docs: incarnations, observers: new Set() };\n\t}\n}\n\n/** Derive the mount's operations from one publication, apply them, and hand the revision to every observer. */\nfunction advance(id: ConversationId, mount: Mount, publication: CommitPublication, context: Context): void {\n\tconst docOps: Op[] = [];\n\tconst entryOps: Op[] = [];\n\tlet entries = mount.value.entries;\n\t// Entry writes are published in ID order.\n\tfor (const change of publication.changes) {\n\t\tif (change.type === \"entry\" && change.value.conversationId === id) {\n\t\t\tconst entry = change.value;\n\t\t\tconst value = entry as unknown as JsonValue;\n\t\t\tif (entry.head === undefined) {\n\t\t\t\tentryOps.push([\"p\", [\"entries\"], entries.length, 0, [value]]);\n\t\t\t\tentries = [...entries, entry];\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// A head marker keeps the non-head entries from its head, which are always a suffix, and goes in front.\n\t\t\tconst target = entry.head;\n\t\t\tlet kept = entries.findIndex((candidate) => candidate.head === undefined && candidate.id >= target);\n\t\t\tif (kept < 0) kept = entries.length;\n\t\t\tentryOps.push([\"p\", [\"entries\"], 0, kept, [value]]);\n\t\t\tentries = [entry, ...entries.slice(kept)];\n\t\t\tcontinue;\n\t\t}\n\t\tif (change.type !== \"document\" || change.conversationId !== id) continue;\n\t\tconst kind = change.record.kind;\n\t\tif (!MOUNTED_KINDS.has(kind) || change.record.key !== undefined) continue;\n\t\tconst path: NonEmptyPath = [\"docs\", kind];\n\t\tconst mounted = mount.docs.get(kind);\n\t\tif (change.value === null) {\n\t\t\tif (mounted?.id !== change.record.id) continue;\n\t\t\tmount.docs.delete(kind);\n\t\t\tdocOps.push([\"d\", path]);\n\t\t} else if (mounted?.id === change.record.id && mounted.version === change.version) {\n\t\t\tfor (const op of change.ops) docOps.push(prefixed(op, path));\n\t\t} else {\n\t\t\tmount.docs.set(kind, { id: change.record.id, version: change.version! });\n\t\t\tdocOps.push([\"s\", path, change.value]);\n\t\t}\n\t}\n\tconst before = mount.value;\n\tconst ops = [...docOps, ...entryOps];\n\tconst frameContext = withoutAbortSignal(context);\n\tif (ops.length > 0) {\n\t\tconst value = docOps.length === 0 ? mount.value : applyImmutable(mount.value, docOps);\n\t\tmount.value = entries === value.entries ? value : { ...value, entries };\n\t\tfor (const observer of [...mount.observers]) observer.advance?.(mount.value, ops, frameContext);\n\t}\n\tfor (const observer of [...mount.observers]) {\n\t\tobserver.publication?.(before, mount.value, ops, publication, frameContext);\n\t}\n}\n\n/** `op` moved under `prefix`; a root replacement becomes a set of the prefix. */\nfunction prefixed(op: Op, prefix: NonEmptyPath): Op {\n\tconst at = (path: Path): NonEmptyPath => [...prefix, ...path] as unknown as NonEmptyPath;\n\tswitch (op[0]) {\n\t\tcase \"r\":\n\t\t\treturn [\"s\", prefix, op[1]];\n\t\tcase \"p\":\n\t\t\treturn [\"p\", at(op[1]), op[2], op[3], op[4]];\n\t\tcase \"m\":\n\t\t\treturn [\"m\", at(op[1]), op[2]];\n\t\tcase \"s\":\n\t\t\treturn [\"s\", at(op[1]), op[2]];\n\t\tcase \"d\":\n\t\t\treturn [\"d\", at(op[1])];\n\t\tcase \"a\":\n\t\t\treturn [\"a\", at(op[1]), op[2]];\n\t\tcase \"t\":\n\t\t\treturn [\"t\", at(op[1]), op[2]];\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"view.js","sourceRoot":"","sources":["../../src/harness/view.ts"],"names":[],"mappings":"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","sourcesContent":["import { type AttachedReplicatedState, type Context, type JsonValue, replicatedState } from \"@earendil-works/chord\";\nimport { withoutAbortSignal } from \"@earendil-works/chord/context\";\nimport { applyImmutable, type NonEmptyPath, type Op, type Path } from \"@earendil-works/chord/delta\";\nimport { CommittedStateSource, CommittedWatch } from \"../session/observation.ts\";\nimport type { SessionImpl } from \"../session/session.ts\";\nimport type {\n\tCommitPublication,\n\tConversationDocToken,\n\tConversationId,\n\tConversationRecord,\n\tDocumentId,\n\tEntryRecord,\n\tJsonObject,\n\tStorage,\n\tWatchHandle,\n} from \"../types.ts\";\nimport { AgentDoc } from \"./agent.ts\";\nimport { activeEntries, captureContextBounds } from \"./context.ts\";\nimport { InboxDoc } from \"./inbox.ts\";\nimport { LiveDoc } from \"./live.ts\";\nimport { UsageDoc } from \"./usage.ts\";\nimport { closedError } from \"./util.ts\";\n\n/** Structural mount of one conversation's active transcript and built-in documents (spec §9.3). */\nexport type ConversationView = {\n\treadonly conversation: ConversationRecord;\n\t/** Raw active entries, as `ContextView.entries`: the head marker, then the non-head entries from its head. */\n\treadonly entries: readonly EntryRecord[];\n\t/** `pi.agent`, `pi.live`, `pi.inbox`, and `pi.usage`, keyed by kind; absent documents are absent. */\n\treadonly docs: Readonly<Record<string, JsonObject>>;\n};\n\n/** Receives each next revision of a mount, and the Session's close. */\nexport type ViewObserver = {\n\tadvance?(value: ConversationView, ops: readonly Op[], context: Context): void;\n\t/** Every publication, after the mount took it; `ops` are the mount's, possibly none. */\n\tpublication?(\n\t\tbefore: ConversationView,\n\t\tafter: ConversationView,\n\t\tops: readonly Op[],\n\t\tpublication: CommitPublication,\n\t\tcontext: Context,\n\t): void;\n\tcloseSession(): void;\n};\n\nconst MOUNTED = [AgentDoc, LiveDoc, InboxDoc, UsageDoc] as unknown as readonly ConversationDocToken<JsonObject>[];\nconst MOUNTED_KINDS: ReadonlySet<string> = new Set(MOUNTED.map((token) => token.definition.kind));\n\n/** One conversation's mount: its current revision, the document incarnations it shows, and its observers. */\ntype Mount = {\n\tvalue: ConversationView;\n\t/** Mounted incarnation and definition version per kind; another incarnation or version is set whole. */\n\treadonly docs: Map<string, { id: DocumentId; version: number }>;\n\treadonly observers: Set<ViewObserver>;\n};\n\nconst VIEWS = new WeakMap<object, ConversationViews>();\n\n/** The view mounts of a Harness, for adapters built on them. */\nexport function conversationViews(harness: object): ConversationViews {\n\tconst views = VIEWS.get(harness);\n\tif (views === undefined) throw new Error(\"Not a Harness\");\n\treturn views;\n}\n\n/**\n * The Harness's conversation view mounts: at most one per conversation, built on the Session line by its first\n * observer and dropped with its last. Each mount advances from the Session's commit publications, which are durable.\n */\nexport class ConversationViews {\n\treadonly #session: SessionImpl;\n\treadonly #storage: Storage;\n\treadonly #mounts = new Map<ConversationId, Mount>();\n\t#closed = false;\n\n\tconstructor(session: SessionImpl, storage: Storage) {\n\t\tthis.#session = session;\n\t\tthis.#storage = storage;\n\t\tVIEWS.set(session, this);\n\t\tsession.subscribeCommits((publication, context) => {\n\t\t\tfor (const [id, mount] of this.#mounts) advance(id, mount, publication, context);\n\t\t});\n\t\tsession.subscribeClose(() => {\n\t\t\tthis.#closed = true;\n\t\t\tfor (const mount of this.#mounts.values())\n\t\t\t\tfor (const observer of [...mount.observers]) observer.closeSession();\n\t\t\tthis.#mounts.clear();\n\t\t});\n\t}\n\n\t/** A disposable read-only Chord state of the view. */\n\tasync state(id: ConversationId, context: Context): Promise<AttachedReplicatedState<ConversationView>> {\n\t\tconst { observer, detach } = await this.attach(\n\t\t\tid,\n\t\t\t(value, release) => new CommittedStateSource<ConversationView>(value, release),\n\t\t\tcontext,\n\t\t);\n\t\ttry {\n\t\t\treturn replicatedState(observer);\n\t\t} catch (error) {\n\t\t\tdetach();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/** A serialized exact-frame watch of the view; cancelling `context` stops it. */\n\tasync watch(id: ConversationId, context: Context): Promise<WatchHandle<ConversationView>> {\n\t\tconst { observer } = await this.attach(\n\t\t\tid,\n\t\t\t(value, release) => new CommittedWatch<ConversationView>(value, release),\n\t\t\tcontext,\n\t\t);\n\t\tconst signal = context.abortSignal;\n\t\tif (signal?.aborted) {\n\t\t\tobserver.cancel();\n\t\t\tthrow signal.reason;\n\t\t}\n\t\tif (signal !== undefined) observer.observeCancellation(signal);\n\t\treturn observer;\n\t}\n\n\t/**\n\t * Register an observer created from the current revision, atomically on the Session line: it sees every later\n\t * publication and nothing earlier. `create` may read committed Storage, still on the line. `release` drops it, and\n\t * the mount with its last observer.\n\t */\n\tattach<O extends ViewObserver>(\n\t\tid: ConversationId,\n\t\tcreate: (value: ConversationView, release: () => void, storage: Storage) => O | Promise<O>,\n\t\tcontext: Context,\n\t): Promise<{ observer: O; detach: () => void }> {\n\t\treturn this.#session.readOnLine(async () => {\n\t\t\tconst mount = this.#mounts.get(id) ?? (await this.#build(id, context));\n\t\t\tconst detach = (): void => {\n\t\t\t\tmount.observers.delete(observer);\n\t\t\t\tif (mount.observers.size === 0 && this.#mounts.get(id) === mount) this.#mounts.delete(id);\n\t\t\t};\n\t\t\tconst observer = await create(mount.value, detach, this.#storage);\n\t\t\t// Close or cancellation may begin while the mount hydrates; register nothing then.\n\t\t\tif (this.#closed) throw closedError();\n\t\t\tcontext.abortSignal?.throwIfAborted();\n\t\t\tthis.#mounts.set(id, mount);\n\t\t\tmount.observers.add(observer);\n\t\t\treturn { observer, detach };\n\t\t});\n\t}\n\n\tasync #build(id: ConversationId, context: Context): Promise<Mount> {\n\t\tconst conversation = await this.#storage.conversation(id, context);\n\t\tif (conversation === undefined) throw new Error(`Conversation ${id} does not exist`);\n\t\tconst bounds = await captureContextBounds(this.#storage, id, context);\n\t\tconst entries = await activeEntries(this.#storage, id, bounds, context);\n\t\tconst docs: Record<string, JsonObject> = {};\n\t\tconst incarnations = new Map<string, { id: DocumentId; version: number }>();\n\t\tfor (const token of MOUNTED) {\n\t\t\tconst loaded = await this.#session.conversationDocumentOnLine(token, id, context);\n\t\t\tif (loaded === undefined) continue;\n\t\t\tdocs[token.definition.kind] = loaded.value;\n\t\t\tincarnations.set(token.definition.kind, { id: loaded.record.id, version: loaded.version });\n\t\t}\n\t\treturn { value: { conversation, entries, docs }, docs: incarnations, observers: new Set() };\n\t}\n}\n\n/** Derive the mount's operations from one publication, apply them, and hand the revision to every observer. */\nfunction advance(id: ConversationId, mount: Mount, publication: CommitPublication, context: Context): void {\n\tconst docOps: Op[] = [];\n\tconst entryOps: Op[] = [];\n\tlet entries = mount.value.entries;\n\t// Entry writes are published in ID order.\n\tfor (const change of publication.changes) {\n\t\tif (change.type === \"entry\" && change.value.conversationId === id) {\n\t\t\tconst entry = change.value;\n\t\t\tconst value = entry as unknown as JsonValue;\n\t\t\tif (entry.head === undefined) {\n\t\t\t\tentryOps.push([\"p\", [\"entries\"], entries.length, 0, [value]]);\n\t\t\t\tentries = [...entries, entry];\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// A head marker keeps the non-head entries from its head, which are always a suffix, and goes in front.\n\t\t\tconst target = entry.head;\n\t\t\tlet kept = entries.findIndex((candidate) => candidate.head === undefined && candidate.id >= target);\n\t\t\tif (kept < 0) kept = entries.length;\n\t\t\tentryOps.push([\"p\", [\"entries\"], 0, kept, [value]]);\n\t\t\tentries = [entry, ...entries.slice(kept)];\n\t\t\tcontinue;\n\t\t}\n\t\tif (change.type !== \"document\" || change.conversationId !== id) continue;\n\t\tconst kind = change.record.kind;\n\t\tif (!MOUNTED_KINDS.has(kind) || change.record.key !== undefined) continue;\n\t\tconst path: NonEmptyPath = [\"docs\", kind];\n\t\tconst mounted = mount.docs.get(kind);\n\t\tif (change.value === null) {\n\t\t\tif (mounted?.id !== change.record.id) continue;\n\t\t\tmount.docs.delete(kind);\n\t\t\tdocOps.push([\"d\", path]);\n\t\t} else if (mounted?.id === change.record.id && mounted.version === change.version) {\n\t\t\tfor (const op of change.ops) docOps.push(prefixed(op, path));\n\t\t} else {\n\t\t\tmount.docs.set(kind, { id: change.record.id, version: change.version! });\n\t\t\tdocOps.push([\"s\", path, change.value]);\n\t\t}\n\t}\n\tconst before = mount.value;\n\tconst ops = [...docOps, ...entryOps];\n\tconst frameContext = withoutAbortSignal(context);\n\tif (ops.length > 0) {\n\t\tconst value = docOps.length === 0 ? mount.value : applyImmutable(mount.value, docOps);\n\t\tmount.value = entries === value.entries ? value : { ...value, entries };\n\t\tfor (const observer of [...mount.observers]) observer.advance?.(mount.value, ops, frameContext);\n\t}\n\tfor (const observer of [...mount.observers]) {\n\t\tobserver.publication?.(before, mount.value, ops, publication, frameContext);\n\t}\n}\n\n/** `op` moved under `prefix`; a root replacement becomes a set of the prefix. */\nfunction prefixed(op: Op, prefix: NonEmptyPath): Op {\n\tconst at = (path: Path): NonEmptyPath => [...prefix, ...path] as unknown as NonEmptyPath;\n\tswitch (op[0]) {\n\t\tcase \"r\":\n\t\t\treturn [\"s\", prefix, op[1]];\n\t\tcase \"p\":\n\t\t\treturn [\"p\", at(op[1]), op[2], op[3], op[4]];\n\t\tcase \"m\":\n\t\t\treturn [\"m\", at(op[1]), op[2]];\n\t\tcase \"s\":\n\t\t\treturn [\"s\", at(op[1]), op[2]];\n\t\tcase \"d\":\n\t\t\treturn [\"d\", at(op[1])];\n\t\tcase \"a\":\n\t\t\treturn [\"a\", at(op[1]), op[2]];\n\t\tcase \"t\":\n\t\t\treturn [\"t\", at(op[1]), op[2]];\n\t}\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
export { defineDoc, defineDocFamily } from "./documents.ts";
|
|
2
2
|
export { AssistantEntry, CompactionEntry, defineEntry, ResetEntry, SystemEntry, ToolResultEntry, UserEntry, } from "./entries.ts";
|
|
3
3
|
export { ConversationBusy, ReadAfterWrite, StorageRejected } from "./errors.ts";
|
|
4
|
+
export { AgentDoc, configure, DEFAULT_COMPACTION_POLICY, DEFAULT_RETRY_POLICY, } from "./harness/agent.ts";
|
|
4
5
|
export { type CompactionCheckpoint, type CompactionInput, CompactionTask, type SummaryRequest, } from "./harness/compaction.ts";
|
|
5
|
-
export {
|
|
6
|
+
export { defineExtension, defineTool, hook, section, wrapSection, wrapTool } from "./harness/define.ts";
|
|
6
7
|
export { type AgentEvent, type AgentEventStream, type MessageChange, type SnapshotEvent, watchEvents, } from "./harness/events.ts";
|
|
7
8
|
export { type GenerationCheckpoint, type GenerationInput, type GenerationResult, GenerationTask, } from "./harness/generation.ts";
|
|
8
9
|
export { Harness } from "./harness/harness.ts";
|
|
9
10
|
export { InboxDoc, type InboxItem, type InboxState } from "./harness/inbox.ts";
|
|
10
11
|
export { type CompactionStatus, LiveDoc, type LiveState, type ToolSlot } from "./harness/live.ts";
|
|
11
12
|
export { createRegistry } from "./harness/registry.ts";
|
|
13
|
+
export type { TaskGraph, TaskGraphNode, TaskGraphState, TaskGraphWatch } from "./harness/task-graph.ts";
|
|
12
14
|
export { ToolTask, type ToolTaskCheckpoint, type ToolTaskInput, type ToolTaskResult } from "./harness/tool.ts";
|
|
13
|
-
export type { AnyTask, CompactionHooks, CompactionPolicy, CompactionReason, CompactionResult, ContextView, Conversation, ConversationAbortOptions, ConversationCreateOptions, ConversationHandle, ConversationInit, ConversationRetryPolicy,
|
|
15
|
+
export type { Agent, AgentChange, AgentState, AnyTask, CompactionHooks, CompactionPolicy, CompactionReason, CompactionResult, ContextView, Conversation, ConversationAbortOptions, ConversationCreateOptions, ConversationHandle, ConversationInit, ConversationRetryPolicy, ConversationStreamOptions, ConversationWatch, EnvTarget, Extension, GenerationHooks, HarnessInspection, HarnessOptions, HarnessSettings, HookApi, HookRegistration, HookResult, HooksOf, InputSubmissionDraft, ModelRef, PromptInput, PromptSection, QueueMode, Registry, RegistryReader, RegistrySnapshot, Settings, SettledSubmissionRecord, SettledTask, Submission, SubmissionDraft, TaskInspection, ToolControl, ToolDiagnostic, ToolExecutionApi, ToolExecutionMode, ToolExecutionResult, ToolHooks, ToolRegistration, UserInput, Wrap, } from "./harness/types.ts";
|
|
14
16
|
export { UsageDoc, type UsageState } from "./harness/usage.ts";
|
|
15
17
|
export type { ConversationView } from "./harness/view.ts";
|
|
16
18
|
export { createSession } from "./session/session.ts";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EACN,cAAc,EACd,eAAe,EACf,WAAW,EACX,UAAU,EACV,WAAW,EACX,eAAe,EACf,SAAS,GACT,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,EACN,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,cAAc,EACd,KAAK,cAAc,GACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export { defineDoc, defineDocFamily } from "./documents.js";
|
|
2
2
|
export { AssistantEntry, CompactionEntry, defineEntry, ResetEntry, SystemEntry, ToolResultEntry, UserEntry, } from "./entries.js";
|
|
3
3
|
export { ConversationBusy, ReadAfterWrite, StorageRejected } from "./errors.js";
|
|
4
|
+
export { AgentDoc, configure, DEFAULT_COMPACTION_POLICY, DEFAULT_RETRY_POLICY, } from "./harness/agent.js";
|
|
4
5
|
export { CompactionTask, } from "./harness/compaction.js";
|
|
5
|
-
export {
|
|
6
|
+
export { defineExtension, defineTool, hook, section, wrapSection, wrapTool } from "./harness/define.js";
|
|
6
7
|
export { watchEvents, } from "./harness/events.js";
|
|
7
8
|
export { GenerationTask, } from "./harness/generation.js";
|
|
8
9
|
export { Harness } from "./harness/harness.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EACN,cAAc,EACd,eAAe,EACf,WAAW,EACX,UAAU,EACV,WAAW,EACX,eAAe,EACf,SAAS,GACT,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,EAGN,cAAc,GAEd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EACN,cAAc,EACd,eAAe,EACf,WAAW,EACX,UAAU,EACV,WAAW,EACX,eAAe,EACf,SAAS,GACT,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,EACN,QAAQ,EACR,SAAS,EACT,yBAAyB,EACzB,oBAAoB,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAGN,cAAc,GAEd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACxG,OAAO,EAKN,WAAW,GACX,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAIN,cAAc,GACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAmC,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAyB,OAAO,EAAiC,MAAM,mBAAmB,CAAC;AAClG,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAoE,MAAM,mBAAmB,CAAC;AAqD/G,OAAO,EAAE,QAAQ,EAAmB,MAAM,oBAAoB,CAAC;AAE/D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAiFxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC","sourcesContent":["export { defineDoc, defineDocFamily } from \"./documents.ts\";\nexport {\n\tAssistantEntry,\n\tCompactionEntry,\n\tdefineEntry,\n\tResetEntry,\n\tSystemEntry,\n\tToolResultEntry,\n\tUserEntry,\n} from \"./entries.ts\";\nexport { ConversationBusy, ReadAfterWrite, StorageRejected } from \"./errors.ts\";\nexport {\n\tAgentDoc,\n\tconfigure,\n\tDEFAULT_COMPACTION_POLICY,\n\tDEFAULT_RETRY_POLICY,\n} from \"./harness/agent.ts\";\nexport {\n\ttype CompactionCheckpoint,\n\ttype CompactionInput,\n\tCompactionTask,\n\ttype SummaryRequest,\n} from \"./harness/compaction.ts\";\nexport { defineExtension, defineTool, hook, section, wrapSection, wrapTool } from \"./harness/define.ts\";\nexport {\n\ttype AgentEvent,\n\ttype AgentEventStream,\n\ttype MessageChange,\n\ttype SnapshotEvent,\n\twatchEvents,\n} from \"./harness/events.ts\";\nexport {\n\ttype GenerationCheckpoint,\n\ttype GenerationInput,\n\ttype GenerationResult,\n\tGenerationTask,\n} from \"./harness/generation.ts\";\nexport { Harness } from \"./harness/harness.ts\";\nexport { InboxDoc, type InboxItem, type InboxState } from \"./harness/inbox.ts\";\nexport { type CompactionStatus, LiveDoc, type LiveState, type ToolSlot } from \"./harness/live.ts\";\nexport { createRegistry } from \"./harness/registry.ts\";\nexport type { TaskGraph, TaskGraphNode, TaskGraphState, TaskGraphWatch } from \"./harness/task-graph.ts\";\nexport { ToolTask, type ToolTaskCheckpoint, type ToolTaskInput, type ToolTaskResult } from \"./harness/tool.ts\";\nexport type {\n\tAgent,\n\tAgentChange,\n\tAgentState,\n\tAnyTask,\n\tCompactionHooks,\n\tCompactionPolicy,\n\tCompactionReason,\n\tCompactionResult,\n\tContextView,\n\tConversation,\n\tConversationAbortOptions,\n\tConversationCreateOptions,\n\tConversationHandle,\n\tConversationInit,\n\tConversationRetryPolicy,\n\tConversationStreamOptions,\n\tConversationWatch,\n\tEnvTarget,\n\tExtension,\n\tGenerationHooks,\n\tHarnessInspection,\n\tHarnessOptions,\n\tHarnessSettings,\n\tHookApi,\n\tHookRegistration,\n\tHookResult,\n\tHooksOf,\n\tInputSubmissionDraft,\n\tModelRef,\n\tPromptInput,\n\tPromptSection,\n\tQueueMode,\n\tRegistry,\n\tRegistryReader,\n\tRegistrySnapshot,\n\tSettings,\n\tSettledSubmissionRecord,\n\tSettledTask,\n\tSubmission,\n\tSubmissionDraft,\n\tTaskInspection,\n\tToolControl,\n\tToolDiagnostic,\n\tToolExecutionApi,\n\tToolExecutionMode,\n\tToolExecutionResult,\n\tToolHooks,\n\tToolRegistration,\n\tUserInput,\n\tWrap,\n} from \"./harness/types.ts\";\nexport { UsageDoc, type UsageState } from \"./harness/usage.ts\";\nexport type { ConversationView } from \"./harness/view.ts\";\nexport { createSession } from \"./session/session.ts\";\nexport { MemoryStorage } from \"./storage/memory.ts\";\nexport { defineTask } from \"./tasks.ts\";\nexport type {\n\tCheckpointInfo,\n\tCommitChange,\n\tCommitPublication,\n\tCommonDocDefinition,\n\tContextEdit,\n\tConversationDocFamilyToken,\n\tConversationDocToken,\n\tConversationId,\n\tConversationOwnership,\n\tConversationQuery,\n\tConversationRecord,\n\tCursor,\n\tDocDefinition,\n\tDocFamilyDefinition,\n\tDocFamilyToken,\n\tDocToken,\n\tDocumentAddress,\n\tDocumentCommitChange,\n\tDocumentContent,\n\tDocumentCopySource,\n\tDocumentCreate,\n\tDocumentId,\n\tDocumentObserver,\n\tDocumentPoint,\n\tDocumentQuery,\n\tDocumentReader,\n\tDocumentRecord,\n\tDocumentSemantics,\n\tDocumentState,\n\tDocumentWatch,\n\tEntry,\n\tEntryDraft,\n\tEntryId,\n\tEntryQuery,\n\tEntryRecord,\n\tHookRunner,\n\tId,\n\tJoinPolicy,\n\tJsonObject,\n\tLatestConversationSemantics,\n\tNextTaskState,\n\tPage,\n\tPhaseHandler,\n\tRewindableConversationDocFamilyToken,\n\tRewindableConversationDocToken,\n\tRewindableConversationSemantics,\n\tRunningTask,\n\tSeq,\n\tSession,\n\tSessionDocFamilyToken,\n\tSessionDocToken,\n\tStorage,\n\tStorageWrite,\n\tStoredDocument,\n\tSubmissionCreate,\n\tSubmissionId,\n\tSubmissionQuery,\n\tSubmissionRecord,\n\tSubmissionSettlement,\n\tTableCommitChange,\n\tTask,\n\tTaskDefinition,\n\tTaskDocFamilyToken,\n\tTaskDocToken,\n\tTaskId,\n\tTaskOptions,\n\tTaskOutcome,\n\tTaskOutcomeError,\n\tTaskOwnership,\n\tTaskQuery,\n\tTaskRecord,\n\tTaskRuntime,\n\tTaskState,\n\tTx,\n\tTypedEntry,\n\tTypedEntryDraft,\n\tWatchEnd,\n\tWatchHandle,\n} from \"./types.ts\";\nexport { ROOT_CONVERSATION_ID } from \"./types.ts\";\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/session/session.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/session/session.ts"],"names":[],"mappings":"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"}
|
package/dist/session/session.js
CHANGED
|
@@ -327,7 +327,11 @@ export class SessionImpl {
|
|
|
327
327
|
continue;
|
|
328
328
|
// A document state's frames carry no caller cancellation; a watch observes its own cancellation.
|
|
329
329
|
const frameContext = observer instanceof CommittedStateSource ? withoutAbortSignal(context) : context;
|
|
330
|
-
|
|
330
|
+
const ops = observedOperations(observed, change);
|
|
331
|
+
// A migration-only base changes nothing for an observer of the new version.
|
|
332
|
+
if (ops.length === 0)
|
|
333
|
+
continue;
|
|
334
|
+
observer.advance(change.value, ops, frameContext);
|
|
331
335
|
}
|
|
332
336
|
});
|
|
333
337
|
unsubscribeClose = this.subscribeClose(() => observer.closeSession());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session/session.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Context, type JsonValue, replicatedState } from \"@earendil-works/chord\";\nimport { awaitWithContext, withoutAbortSignal } from \"@earendil-works/chord/context\";\nimport { type Op, track } from \"@earendil-works/chord/delta\";\nimport {\n\ttype AnyDocToken,\n\tcheckRecordScope,\n\tcheckRecordVersion,\n\tmaterializeDocument,\n\tresolveAddress,\n} from \"../documents.ts\";\nimport { StorageRejected } from \"../errors.ts\";\nimport { idFromNumber } from \"../ids.ts\";\nimport type {\n\tCommitChange,\n\tCommitPublication,\n\tConversationDocFamilyToken,\n\tConversationDocToken,\n\tConversationId,\n\tConversationRecord,\n\tDocumentAddress,\n\tDocumentCommitChange,\n\tDocumentRecord,\n\tDocumentState,\n\tDocumentWatch,\n\tEntryId,\n\tJsonObject,\n\tRewindableConversationDocFamilyToken,\n\tRewindableConversationDocToken,\n\tSeq,\n\tSession,\n\tSessionDocFamilyToken,\n\tSessionDocToken,\n\tStorage,\n\tStorageWrite,\n\tTaskDocFamilyToken,\n\tTaskDocToken,\n\tTaskId,\n\tTx,\n} from \"../types.ts\";\nimport {\n\tCommittedStateSource,\n\tCommittedWatch,\n\ttype ObservedDocumentValue,\n\tRETIREMENT_OPERATIONS,\n} from \"./observation.ts\";\nimport { type LoadedDocument, Transaction, type TransactionHost, type TransactionScope } from \"./transaction.ts\";\n\n/** Open a Session kernel over one storage backend. */\nexport function createSession(storage: Storage): Session {\n\treturn new SessionImpl(storage);\n}\n\n/**\n * Session kernel: one mutation line, the loaded document tracker cache, and committed publication.\n *\n * Only committed state is observable. Every commit callback, preparation, Storage settlement, adoption, and\n * publication enqueue runs while the line is held; listeners run later.\n */\nexport class SessionImpl implements Session {\n\treadonly #storage: Storage;\n\treadonly #documents = new Map<string, LoadedDocument>();\n\treadonly #commitListeners = new Set<(publication: CommitPublication, context: Context) => void>();\n\treadonly #closeListeners = new Set<() => void>();\n\treadonly #host: TransactionHost;\n\t#tail: Promise<void> = Promise.resolve();\n\t#closing: Promise<void> | undefined;\n\t#poison: { readonly error: unknown } | undefined;\n\n\tconstructor(storage: Storage) {\n\t\tthis.#storage = storage;\n\t\tthis.#host = {\n\t\t\tstorage,\n\t\t\tcached: (id) => this.#documents.get(id),\n\t\t\tload: (definition, addressId, address, context) => this.#loadDocument(definition, addressId, address, context),\n\t\t\tinstall: (document) => {\n\t\t\t\tthis.#documents.set(document.addressId, document);\n\t\t\t},\n\t\t\tevict: (id, recordId) => {\n\t\t\t\tif (this.#documents.get(id)?.record.id === recordId) this.#documents.delete(id);\n\t\t\t},\n\t\t\tconversationCreated: (tx, record) => this.conversationCreated(tx, record),\n\t\t};\n\t}\n\n\tcommit<T>(change: (tx: Tx) => T | Promise<T>, context: Context): Promise<T> {\n\t\treturn this.commitWith(change, context);\n\t}\n\n\t/**\n\t * Internal commit exposing the concrete transaction and its internal operations, such as the reserved-ID root\n\t * bootstrap and task replacement. `scope` sets the default `tx.createTask()` conversation and the task attributed to\n\t * appended entries.\n\t */\n\tcommitWith<T>(change: (tx: Transaction) => T | Promise<T>, context: Context, scope?: TransactionScope): Promise<T> {\n\t\ttry {\n\t\t\tthis.#assertUsable();\n\t\t} catch (error) {\n\t\t\treturn Promise.reject(error);\n\t\t}\n\t\treturn this.#enqueue(() => this.#runCommit(change, context, scope));\n\t}\n\n\t/** Internal: run a read-only job on the mutation line so multi-read derivations observe one committed state. */\n\treadOnLine<T>(job: () => Promise<T>): Promise<T> {\n\t\ttry {\n\t\t\tthis.#assertUsable();\n\t\t} catch (error) {\n\t\t\treturn Promise.reject(error);\n\t\t}\n\t\treturn this.#enqueue(async () => {\n\t\t\tthis.#assertHealthy();\n\t\t\treturn job();\n\t\t});\n\t}\n\n\t/**\n\t * Internal: a conversation document's current incarnation and value, for a job already running on the line (see\n\t * `readOnLine()`). Absent documents are `undefined`.\n\t */\n\tasync conversationDocumentOnLine(\n\t\ttoken: ConversationDocToken<JsonObject>,\n\t\tconversationId: ConversationId,\n\t\tcontext: Context,\n\t): Promise<{ readonly record: DocumentRecord; readonly version: number; readonly value: JsonObject } | undefined> {\n\t\tconst definition = token.definition;\n\t\tconst resolved = resolveAddress(definition, [conversationId, context]);\n\t\tconst loaded = await this.#loadDocument(definition, resolved.id, resolved.address, context);\n\t\tif (loaded === undefined) return undefined;\n\t\tcheckRecordScope(definition, loaded.record);\n\t\tcheckRecordVersion(definition, loaded.record, loaded.storedVersion);\n\t\treturn { record: loaded.record, version: loaded.valueVersion, value: loaded.tracker.value };\n\t}\n\n\tsnapshot<T extends JsonObject>(token: SessionDocToken<T>, context: Context): Promise<Readonly<T> | undefined>;\n\tsnapshot<T extends JsonObject>(\n\t\ttoken: ConversationDocToken<T>,\n\t\tconversationId: ConversationId,\n\t\tcontext: Context,\n\t): Promise<Readonly<T> | undefined>;\n\tsnapshot<T extends JsonObject>(\n\t\ttoken: TaskDocToken<T>,\n\t\ttaskId: TaskId,\n\t\tcontext: Context,\n\t): Promise<Readonly<T> | undefined>;\n\tsnapshot<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: SessionDocFamilyToken<T, I>,\n\t\tkey: string,\n\t\tcontext: Context,\n\t): Promise<Readonly<T> | undefined>;\n\tsnapshot<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: ConversationDocFamilyToken<T, I>,\n\t\tconversationId: ConversationId,\n\t\tkey: string,\n\t\tcontext: Context,\n\t): Promise<Readonly<T> | undefined>;\n\tsnapshot<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: TaskDocFamilyToken<T, I>,\n\t\ttaskId: TaskId,\n\t\tkey: string,\n\t\tcontext: Context,\n\t): Promise<Readonly<T> | undefined>;\n\tasync snapshot(token: AnyDocToken, ...args: readonly unknown[]): Promise<JsonObject | undefined> {\n\t\tthis.#assertUsable();\n\t\tconst definition = token.definition;\n\t\tconst resolved = resolveAddress(definition, args);\n\t\tconst context = args[resolved.nextArgument] as Context;\n\t\tconst cached = this.#documents.get(resolved.id);\n\t\tconst loaded =\n\t\t\tcached?.valueVersion === definition.version\n\t\t\t\t? cached\n\t\t\t\t: await this.#enqueue(async () => {\n\t\t\t\t\t\tthis.#assertHealthy();\n\t\t\t\t\t\treturn this.#loadDocument(definition, resolved.id, resolved.address, context);\n\t\t\t\t\t});\n\t\tif (loaded === undefined) return undefined;\n\t\tcheckRecordScope(definition, loaded.record);\n\t\tcheckRecordVersion(definition, loaded.record, loaded.storedVersion);\n\t\treturn loaded.tracker.value;\n\t}\n\n\tdocumentState<T extends JsonObject>(\n\t\ttoken: SessionDocToken<T>,\n\t\tcontext: Context,\n\t): Promise<DocumentState<T> | undefined>;\n\tdocumentState<T extends JsonObject>(\n\t\ttoken: ConversationDocToken<T>,\n\t\tconversationId: ConversationId,\n\t\tcontext: Context,\n\t): Promise<DocumentState<T> | undefined>;\n\tdocumentState<T extends JsonObject>(\n\t\ttoken: TaskDocToken<T>,\n\t\ttaskId: TaskId,\n\t\tcontext: Context,\n\t): Promise<DocumentState<T> | undefined>;\n\tdocumentState<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: SessionDocFamilyToken<T, I>,\n\t\tkey: string,\n\t\tcontext: Context,\n\t): Promise<DocumentState<T> | undefined>;\n\tdocumentState<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: ConversationDocFamilyToken<T, I>,\n\t\tconversationId: ConversationId,\n\t\tkey: string,\n\t\tcontext: Context,\n\t): Promise<DocumentState<T> | undefined>;\n\tdocumentState<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: TaskDocFamilyToken<T, I>,\n\t\ttaskId: TaskId,\n\t\tkey: string,\n\t\tcontext: Context,\n\t): Promise<DocumentState<T> | undefined>;\n\tdocumentState(token: AnyDocToken, ...args: readonly unknown[]): Promise<DocumentState<JsonObject> | undefined> {\n\t\ttry {\n\t\t\tthis.#assertUsable();\n\t\t\tconst definition = token.definition;\n\t\t\tconst resolved = resolveAddress(definition, args);\n\t\t\tconst context = args[resolved.nextArgument] as Context;\n\t\t\treturn this.#enqueue(async () => {\n\t\t\t\tthis.#assertHealthy();\n\t\t\t\tconst loaded = await this.#loadDocument(definition, resolved.id, resolved.address, context);\n\t\t\t\tif (loaded === undefined) return undefined;\n\t\t\t\tconst { observer: source, detach } = this.#attachDocument(\n\t\t\t\t\tdefinition,\n\t\t\t\t\tloaded,\n\t\t\t\t\t(value, release) => new CommittedStateSource<ObservedDocumentValue>(value, release),\n\t\t\t\t);\n\t\t\t\ttry {\n\t\t\t\t\treturn replicatedState(source) as DocumentState<JsonObject>;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tdetach();\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error) {\n\t\t\treturn Promise.reject(error);\n\t\t}\n\t}\n\n\twatchDoc<T extends JsonObject>(token: SessionDocToken<T>, context: Context): Promise<DocumentWatch<T> | undefined>;\n\twatchDoc<T extends JsonObject>(\n\t\ttoken: ConversationDocToken<T>,\n\t\tconversationId: ConversationId,\n\t\tcontext: Context,\n\t): Promise<DocumentWatch<T> | undefined>;\n\twatchDoc<T extends JsonObject>(\n\t\ttoken: TaskDocToken<T>,\n\t\ttaskId: TaskId,\n\t\tcontext: Context,\n\t): Promise<DocumentWatch<T> | undefined>;\n\twatchDoc<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: SessionDocFamilyToken<T, I>,\n\t\tkey: string,\n\t\tcontext: Context,\n\t): Promise<DocumentWatch<T> | undefined>;\n\twatchDoc<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: ConversationDocFamilyToken<T, I>,\n\t\tconversationId: ConversationId,\n\t\tkey: string,\n\t\tcontext: Context,\n\t): Promise<DocumentWatch<T> | undefined>;\n\twatchDoc<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: TaskDocFamilyToken<T, I>,\n\t\ttaskId: TaskId,\n\t\tkey: string,\n\t\tcontext: Context,\n\t): Promise<DocumentWatch<T> | undefined>;\n\tasync watchDoc(token: AnyDocToken, ...args: readonly unknown[]): Promise<DocumentWatch<JsonObject> | undefined> {\n\t\tthis.#assertUsable();\n\t\tconst definition = token.definition;\n\t\tconst resolved = resolveAddress(definition, args);\n\t\tconst context = args[resolved.nextArgument] as Context;\n\t\tconst signal = context.abortSignal;\n\t\tlet cancelled = signal?.aborted ?? false;\n\t\tconst markCancelled = (): void => {\n\t\t\tcancelled = true;\n\t\t};\n\t\tsignal?.addEventListener(\"abort\", markCancelled, { once: true });\n\t\ttry {\n\t\t\tconst watch = await this.#enqueue(async () => {\n\t\t\t\tthis.#assertHealthy();\n\t\t\t\tif (cancelled) throw cancellationError(signal!);\n\t\t\t\tconst loaded = await this.#loadDocument(definition, resolved.id, resolved.address, context);\n\t\t\t\tif (cancelled) throw cancellationError(signal!);\n\t\t\t\tif (loaded === undefined) return undefined;\n\t\t\t\treturn this.#attachDocument(\n\t\t\t\t\tdefinition,\n\t\t\t\t\tloaded,\n\t\t\t\t\t(value, release) => new CommittedWatch<ObservedDocumentValue>(value, release),\n\t\t\t\t).observer;\n\t\t\t});\n\t\t\tif (watch === undefined) return undefined;\n\t\t\tif (cancelled) {\n\t\t\t\twatch.cancel();\n\t\t\t\tthrow cancellationError(signal!);\n\t\t\t}\n\t\t\tif (signal !== undefined) watch.observeCancellation(signal);\n\t\t\treturn watch as DocumentWatch<JsonObject>;\n\t\t} finally {\n\t\t\tsignal?.removeEventListener(\"abort\", markCancelled);\n\t\t}\n\t}\n\n\tsnapshotAsOf<T extends JsonObject>(\n\t\ttoken: RewindableConversationDocToken<T>,\n\t\tconversationId: ConversationId,\n\t\tat: EntryId,\n\t\tcontext: Context,\n\t): Promise<Readonly<T> | undefined>;\n\tsnapshotAsOf<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: RewindableConversationDocFamilyToken<T, I>,\n\t\tconversationId: ConversationId,\n\t\tkey: string,\n\t\tat: EntryId,\n\t\tcontext: Context,\n\t): Promise<Readonly<T> | undefined>;\n\tasync snapshotAsOf(token: AnyDocToken, ...args: readonly unknown[]): Promise<JsonObject | undefined> {\n\t\tthis.#assertUsable();\n\t\tconst definition = token.definition;\n\t\tconst resolved = resolveAddress(definition, args);\n\t\tif (resolved.address.scope.kind !== \"conversation\") {\n\t\t\tthrow new TypeError(\"Session.snapshotAsOf() requires a conversation document\");\n\t\t}\n\t\tconst conversationId = resolved.address.scope.conversationId;\n\t\tconst atValue = args[resolved.nextArgument];\n\t\tif (typeof atValue !== \"number\" || !Number.isSafeInteger(atValue)) {\n\t\t\tthrow new TypeError(\"Session.snapshotAsOf() requires an entry ID\");\n\t\t}\n\t\tconst at = idFromNumber<EntryId>(atValue);\n\t\tconst context = args[resolved.nextArgument + 1] as Context;\n\t\treturn this.#enqueue(async () => {\n\t\t\tthis.#assertHealthy();\n\t\t\tconst storedEntry = await this.#storage.entry(conversationId, at, context);\n\t\t\tif (storedEntry === undefined) {\n\t\t\t\tthrow new Error(`Entry ${at} is not visible from conversation ${conversationId}`);\n\t\t\t}\n\t\t\tconst address: DocumentAddress = {\n\t\t\t\t...resolved.address,\n\t\t\t\tscope: { kind: \"conversation\", conversationId: storedEntry.entry.conversationId },\n\t\t\t};\n\t\t\tconst record = await this.#storage.findDocument(address, storedEntry.commitSeq, context);\n\t\t\tif (record === undefined) return undefined;\n\t\t\tconst stored = await this.#storage.document(record.id, storedEntry.commitSeq, context);\n\t\t\tif (stored === undefined) {\n\t\t\t\tthrow new Error(`Historical document ${record.id} (${record.kind}) cannot be read`);\n\t\t\t}\n\t\t\treturn materializeDocument(definition, stored);\n\t\t});\n\t}\n\n\tclose(context: Context): Promise<void> {\n\t\tif (this.#closing === undefined) {\n\t\t\tconst cleanup = withoutAbortSignal(context);\n\t\t\t// Seal admission before anything else runs, then stop observers; admitted work settles before Storage closes.\n\t\t\tthis.#closing = Promise.resolve()\n\t\t\t\t.then(() => this.beforeClose())\n\t\t\t\t.then(() =>\n\t\t\t\t\tthis.#enqueue(async () => {\n\t\t\t\t\t\tthis.#commitListeners.clear();\n\t\t\t\t\t\tthis.#documents.clear();\n\t\t\t\t\t\tawait this.#storage.close(cleanup);\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\tconst listeners = [...this.#closeListeners];\n\t\t\tthis.#closeListeners.clear();\n\t\t\tfor (const listener of listeners) listener();\n\t\t}\n\t\treturn awaitWithContext(this.#closing, context);\n\t}\n\n\t/**\n\t * Runs inside every transaction that creates or forks a conversation, after the conversation record is staged. A\n\t * plain Session stages nothing; a Harness stages its built-in documents.\n\t */\n\tprotected conversationCreated(_tx: Transaction, _record: ConversationRecord): Promise<void> {\n\t\treturn Promise.resolve();\n\t}\n\n\t/** Runs after close seals admission and before the line closes Storage; must not reject. */\n\tprotected beforeClose(): Promise<void> {\n\t\treturn Promise.resolve();\n\t}\n\n\t/** Register a synchronous post-adoption listener. It must not throw, block, or call Session operations. */\n\tsubscribeCommits(listener: (publication: CommitPublication, context: Context) => void): () => void {\n\t\tthis.#assertUsable();\n\t\tthis.#commitListeners.add(listener);\n\t\treturn () => this.#commitListeners.delete(listener);\n\t}\n\n\t/** Register a listener called synchronously when close begins. It must not throw, block, or call Session operations. */\n\tsubscribeClose(listener: () => void): () => void {\n\t\tthis.#assertUsable();\n\t\tthis.#closeListeners.add(listener);\n\t\treturn () => this.#closeListeners.delete(listener);\n\t}\n\n\t/** Drop every loaded tracker on the mutation line; later access cold-loads from Storage. */\n\tunloadDocuments(): Promise<void> {\n\t\treturn this.#enqueue(async () => {\n\t\t\tthis.#documents.clear();\n\t\t});\n\t}\n\n\tasync #runCommit<T>(\n\t\tchange: (tx: Transaction) => T | Promise<T>,\n\t\tcontext: Context,\n\t\tscope?: TransactionScope,\n\t): Promise<T> {\n\t\tthis.#assertHealthy();\n\t\tcontext.abortSignal?.throwIfAborted();\n\t\tconst tx = new Transaction(this.#host, context, scope);\n\t\tlet result: T;\n\t\ttry {\n\t\t\tresult = await change(tx);\n\t\t} catch (error) {\n\t\t\tawait tx.settleFailure();\n\t\t\tthrow error;\n\t\t}\n\t\tconst writes = await tx.settleSuccess();\n\t\tif (writes.length === 0) {\n\t\t\ttx.discard();\n\t\t\treturn result;\n\t\t}\n\t\tlet seq: Seq;\n\t\ttry {\n\t\t\t// Once admitted, caller cancellation does not interrupt Storage settlement.\n\t\t\tseq = await this.#storage.commit(writes, withoutAbortSignal(context));\n\t\t} catch (error) {\n\t\t\ttx.discard();\n\t\t\t// Callback errors never reach this branch; StorageRejected alone guarantees that no batch effect committed.\n\t\t\tif (!(error instanceof StorageRejected)) this.#poison = { error };\n\t\t\tthrow error;\n\t\t}\n\t\tlet documents: DocumentCommitChange[];\n\t\ttry {\n\t\t\tdocuments = tx.adopt(seq);\n\t\t} catch (error) {\n\t\t\t// Storage already committed; a failed adoption leaves memory behind durable state.\n\t\t\tthis.#poison = { error };\n\t\t\tthrow error;\n\t\t}\n\t\tthis.#publish(seq, writes, documents, context);\n\t\treturn result;\n\t}\n\n\t#publish(\n\t\tseq: Seq,\n\t\twrites: readonly StorageWrite[],\n\t\tdocuments: readonly DocumentCommitChange[],\n\t\tcontext: Context,\n\t): void {\n\t\tif (this.#commitListeners.size === 0) return;\n\t\tconst changes: CommitChange[] = [];\n\t\tfor (const write of writes) {\n\t\t\tswitch (write.type) {\n\t\t\t\tcase \"conversation\":\n\t\t\t\tcase \"entry\":\n\t\t\t\tcase \"task\":\n\t\t\t\tcase \"submission\":\n\t\t\t\t\tchanges.push(write);\n\t\t\t}\n\t\t}\n\t\tfor (const document of documents) changes.push(document);\n\t\tconst publication: CommitPublication = { seq, changes };\n\t\tfor (const listener of [...this.#commitListeners]) listener(publication, context);\n\t}\n\n\t/**\n\t * Attach an observer to one committed incarnation: check the definition, then forward this incarnation's committed\n\t * changes and close. `detach` removes both subscriptions.\n\t */\n\t#attachDocument<O extends CommittedStateSource | CommittedWatch>(\n\t\tdefinition: AnyDocToken[\"definition\"],\n\t\tloaded: LoadedDocument,\n\t\tcreate: (value: JsonObject, detach: () => void) => O,\n\t): { observer: O; detach: () => void } {\n\t\tcheckRecordScope(definition, loaded.record);\n\t\tcheckRecordVersion(definition, loaded.record, loaded.storedVersion);\n\t\tlet unsubscribeCommit = (): void => {};\n\t\tlet unsubscribeClose = (): void => {};\n\t\tconst detach = (): void => {\n\t\t\tunsubscribeCommit();\n\t\t\tunsubscribeClose();\n\t\t};\n\t\tconst observer = create(loaded.tracker.value, detach);\n\t\tconst observed = { version: loaded.valueVersion };\n\t\tunsubscribeCommit = this.subscribeCommits((publication, context) => {\n\t\t\tfor (const change of publication.changes) {\n\t\t\t\tif (change.type !== \"document\" || change.record.id !== loaded.record.id) continue;\n\t\t\t\t// A document state's frames carry no caller cancellation; a watch observes its own cancellation.\n\t\t\t\tconst frameContext = observer instanceof CommittedStateSource ? withoutAbortSignal(context) : context;\n\t\t\t\tobserver.advance(change.value, observedOperations(observed, change), frameContext);\n\t\t\t}\n\t\t});\n\t\tunsubscribeClose = this.subscribeClose(() => observer.closeSession());\n\t\treturn { observer, detach };\n\t}\n\n\tasync #loadDocument(\n\t\tdefinition: AnyDocToken[\"definition\"],\n\t\taddressId: string,\n\t\taddress: DocumentAddress,\n\t\tcontext: Context,\n\t): Promise<LoadedDocument | undefined> {\n\t\tconst cached = this.#documents.get(addressId);\n\t\t// A tracker serves only tokens of the version its value was materialized for; others reload from Storage.\n\t\tif (cached?.valueVersion === definition.version) return cached;\n\t\tif (cached !== undefined) this.#documents.delete(addressId);\n\t\tconst record = await this.#storage.findDocument(address, \"current\", context);\n\t\tif (record === undefined) return undefined;\n\t\tconst stored = await this.#storage.document(record.id, \"current\", context);\n\t\tif (stored === undefined) throw new Error(`Current document ${record.id} (${record.kind}) cannot be read`);\n\t\tconst value = materializeDocument(definition, stored);\n\t\tconst loaded: LoadedDocument = {\n\t\t\taddressId,\n\t\t\trecord: stored.record,\n\t\t\tstoredVersion: stored.version,\n\t\t\tvalueVersion: definition.version,\n\t\t\tdeltasSinceBase: stored.deltasSinceBase,\n\t\t\ttracker: track(value),\n\t\t};\n\t\tthis.#documents.set(addressId, loaded);\n\t\treturn loaded;\n\t}\n\n\t#enqueue<T>(job: () => Promise<T>): Promise<T> {\n\t\tconst run = this.#tail.then(job);\n\t\tthis.#tail = run.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t);\n\t\treturn run;\n\t}\n\n\t#assertUsable(): void {\n\t\tif (this.#closing !== undefined) throw new Error(\"Session is closed\");\n\t\tthis.#assertHealthy();\n\t}\n\n\t#assertHealthy(): void {\n\t\tif (this.#poison !== undefined) {\n\t\t\tthrow new Error(\"Session is poisoned by a failed commit after storage admission; reopen it\", {\n\t\t\t\tcause: this.#poison.error,\n\t\t\t});\n\t\t}\n\t}\n}\n\n/**\n * Operations an observer applies for one committed change. An observer hydrated under another definition version holds\n * a differently shaped value, so it receives the new value as a root replacement instead of operations for that shape.\n */\nfunction observedOperations(\n\tobserved: { version: number },\n\tchange: Extract<DocumentCommitChange, { readonly type: \"document\" }>,\n): readonly Op[] {\n\tif (change.value === null) return RETIREMENT_OPERATIONS;\n\tif (change.version === observed.version) return change.ops;\n\tobserved.version = change.version!;\n\treturn [[\"r\", change.value]];\n}\n\nfunction cancellationError(signal: AbortSignal): Error {\n\treturn signal.reason instanceof Error ? signal.reason : new DOMException(\"The operation was aborted\", \"AbortError\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACrF,OAAO,EAAW,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAEN,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,GACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AA4BzC,OAAO,EACN,oBAAoB,EACpB,cAAc,EAEd,qBAAqB,GACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAuB,WAAW,EAA+C,MAAM,kBAAkB,CAAC;AAEjH,sDAAsD;AACtD,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC7C,OAAO,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,WAAW;IACd,QAAQ,CAAU;IAClB,UAAU,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC/C,gBAAgB,GAAG,IAAI,GAAG,EAA8D,CAAC;IACzF,eAAe,GAAG,IAAI,GAAG,EAAc,CAAC;IACxC,KAAK,CAAkB;IAChC,KAAK,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IACzC,QAAQ,CAA4B;IACpC,OAAO,CAA0C;IAEjD,YAAY,OAAgB;QAC3B,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,KAAK,GAAG;YACZ,OAAO;YACP,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACvC,IAAI,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC;YAC9G,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE;gBACrB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YACnD,CAAC;YACD,KAAK,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE;gBACvB,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE,KAAK,QAAQ;oBAAE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACjF,CAAC;YACD,mBAAmB,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,EAAE,EAAE,MAAM,CAAC;SACzE,CAAC;IACH,CAAC;IAED,MAAM,CAAI,MAAkC,EAAE,OAAgB;QAC7D,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;IAED;;;;OAIG;IACH,UAAU,CAAI,MAA2C,EAAE,OAAgB,EAAE,KAAwB;QACpG,IAAI,CAAC;YACJ,IAAI,CAAC,aAAa,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,gHAAgH;IAChH,UAAU,CAAI,GAAqB;QAClC,IAAI,CAAC;YACJ,IAAI,CAAC,aAAa,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;YAC/B,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,OAAO,GAAG,EAAE,CAAC;QACd,CAAC,CAAC,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,0BAA0B,CAC/B,KAAuC,EACvC,cAA8B,EAC9B,OAAgB;QAEhB,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;QACpC,MAAM,QAAQ,GAAG,cAAc,CAAC,UAAU,EAAE,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;QACvE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5F,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAC3C,gBAAgB,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5C,kBAAkB,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;QACpE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,YAAY,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IAC7F,CAAC;IA8BD,KAAK,CAAC,QAAQ,CAAC,KAAkB,EAAE,GAAG,IAAwB;QAC7D,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;QACpC,MAAM,QAAQ,GAAG,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAY,CAAC;QACvD,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAChD,MAAM,MAAM,GACX,MAAM,EAAE,YAAY,KAAK,UAAU,CAAC,OAAO;YAC1C,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;gBAC/B,IAAI,CAAC,cAAc,EAAE,CAAC;gBACtB,OAAO,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC/E,CAAC,CAAC,CAAC;QACN,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAC3C,gBAAgB,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5C,kBAAkB,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;QACpE,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;IAC7B,CAAC;IAiCD,aAAa,CAAC,KAAkB,EAAE,GAAG,IAAwB;QAC5D,IAAI,CAAC;YACJ,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;YACpC,MAAM,QAAQ,GAAG,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;YAClD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAY,CAAC;YACvD,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;gBAC/B,IAAI,CAAC,cAAc,EAAE,CAAC;gBACtB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAC5F,IAAI,MAAM,KAAK,SAAS;oBAAE,OAAO,SAAS,CAAC;gBAC3C,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,eAAe,CACxD,UAAU,EACV,MAAM,EACN,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,oBAAoB,CAAwB,KAAK,EAAE,OAAO,CAAC,CACnF,CAAC;gBACF,IAAI,CAAC;oBACJ,OAAO,eAAe,CAAC,MAAM,CAA8B,CAAC;gBAC7D,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBAChB,MAAM,EAAE,CAAC;oBACT,MAAM,KAAK,CAAC;gBACb,CAAC;YACF,CAAC,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;IACF,CAAC;IA8BD,KAAK,CAAC,QAAQ,CAAC,KAAkB,EAAE,GAAG,IAAwB;QAC7D,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;QACpC,MAAM,QAAQ,GAAG,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAY,CAAC;QACvD,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;QACnC,IAAI,SAAS,GAAG,MAAM,EAAE,OAAO,IAAI,KAAK,CAAC;QACzC,MAAM,aAAa,GAAG,GAAS,EAAE;YAChC,SAAS,GAAG,IAAI,CAAC;QAClB,CAAC,CAAC;QACF,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,IAAI,CAAC;YACJ,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;gBAC5C,IAAI,CAAC,cAAc,EAAE,CAAC;gBACtB,IAAI,SAAS;oBAAE,MAAM,iBAAiB,CAAC,MAAO,CAAC,CAAC;gBAChD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAC5F,IAAI,SAAS;oBAAE,MAAM,iBAAiB,CAAC,MAAO,CAAC,CAAC;gBAChD,IAAI,MAAM,KAAK,SAAS;oBAAE,OAAO,SAAS,CAAC;gBAC3C,OAAO,IAAI,CAAC,eAAe,CAC1B,UAAU,EACV,MAAM,EACN,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,cAAc,CAAwB,KAAK,EAAE,OAAO,CAAC,CAC7E,CAAC,QAAQ,CAAC;YACZ,CAAC,CAAC,CAAC;YACH,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO,SAAS,CAAC;YAC1C,IAAI,SAAS,EAAE,CAAC;gBACf,KAAK,CAAC,MAAM,EAAE,CAAC;gBACf,MAAM,iBAAiB,CAAC,MAAO,CAAC,CAAC;YAClC,CAAC;YACD,IAAI,MAAM,KAAK,SAAS;gBAAE,KAAK,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;YAC5D,OAAO,KAAkC,CAAC;QAC3C,CAAC;gBAAS,CAAC;YACV,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QACrD,CAAC;IACF,CAAC;IAeD,KAAK,CAAC,YAAY,CAAC,KAAkB,EAAE,GAAG,IAAwB;QACjE,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;QACpC,MAAM,QAAQ,GAAG,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAClD,IAAI,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YACpD,MAAM,IAAI,SAAS,CAAC,yDAAyD,CAAC,CAAC;QAChF,CAAC;QACD,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC;QAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAC5C,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;YACnE,MAAM,IAAI,SAAS,CAAC,6CAA6C,CAAC,CAAC;QACpE,CAAC;QACD,MAAM,EAAE,GAAG,YAAY,CAAU,OAAO,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,GAAG,CAAC,CAAY,CAAC;QAC3D,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;YAC/B,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;YAC3E,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CAAC,SAAS,EAAE,qCAAqC,cAAc,EAAE,CAAC,CAAC;YACnF,CAAC;YACD,MAAM,OAAO,GAAoB;gBAChC,GAAG,QAAQ,CAAC,OAAO;gBACnB,KAAK,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,CAAC,KAAK,CAAC,cAAc,EAAE;aACjF,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACzF,IAAI,MAAM,KAAK,SAAS;gBAAE,OAAO,SAAS,CAAC;YAC3C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACvF,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,uBAAuB,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,IAAI,kBAAkB,CAAC,CAAC;YACrF,CAAC;YACD,OAAO,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAgB;QACrB,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACjC,MAAM,OAAO,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;YAC5C,8GAA8G;YAC9G,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,EAAE;iBAC/B,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;iBAC9B,IAAI,CAAC,GAAG,EAAE,CACV,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;gBACxB,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;gBAC9B,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;gBACxB,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACpC,CAAC,CAAC,CACF,CAAC;YACH,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,CAAC;YAC5C,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;YAC7B,KAAK,MAAM,QAAQ,IAAI,SAAS;gBAAE,QAAQ,EAAE,CAAC;QAC9C,CAAC;QACD,OAAO,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACjD,CAAC;IAED;;;OAGG;IACO,mBAAmB,CAAC,GAAgB,EAAE,OAA2B;QAC1E,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC1B,CAAC;IAED,4FAA4F;IAClF,WAAW;QACpB,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC1B,CAAC;IAED,2GAA2G;IAC3G,gBAAgB,CAAC,QAAoE;QACpF,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACpC,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACrD,CAAC;IAED,wHAAwH;IACxH,cAAc,CAAC,QAAoB;QAClC,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACnC,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACpD,CAAC;IAED,4FAA4F;IAC5F,eAAe;QACd,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;YAC/B,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACzB,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,UAAU,CACf,MAA2C,EAC3C,OAAgB,EAChB,KAAwB;QAExB,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,OAAO,CAAC,WAAW,EAAE,cAAc,EAAE,CAAC;QACtC,MAAM,EAAE,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;QACvD,IAAI,MAAS,CAAC;QACd,IAAI,CAAC;YACJ,MAAM,GAAG,MAAM,MAAM,CAAC,EAAE,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,EAAE,CAAC,aAAa,EAAE,CAAC;YACzB,MAAM,KAAK,CAAC;QACb,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,aAAa,EAAE,CAAC;QACxC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,EAAE,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,MAAM,CAAC;QACf,CAAC;QACD,IAAI,GAAQ,CAAC;QACb,IAAI,CAAC;YACJ,4EAA4E;YAC5E,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;QACvE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,EAAE,CAAC,OAAO,EAAE,CAAC;YACb,4GAA4G;YAC5G,IAAI,CAAC,CAAC,KAAK,YAAY,eAAe,CAAC;gBAAE,IAAI,CAAC,OAAO,GAAG,EAAE,KAAK,EAAE,CAAC;YAClE,MAAM,KAAK,CAAC;QACb,CAAC;QACD,IAAI,SAAiC,CAAC;QACtC,IAAI,CAAC;YACJ,SAAS,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,mFAAmF;YACnF,IAAI,CAAC,OAAO,GAAG,EAAE,KAAK,EAAE,CAAC;YACzB,MAAM,KAAK,CAAC;QACb,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QAC/C,OAAO,MAAM,CAAC;IACf,CAAC;IAED,QAAQ,CACP,GAAQ,EACR,MAA+B,EAC/B,SAA0C,EAC1C,OAAgB;QAEhB,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO;QAC7C,MAAM,OAAO,GAAmB,EAAE,CAAC;QACnC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC5B,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;gBACpB,KAAK,cAAc,CAAC;gBACpB,KAAK,OAAO,CAAC;gBACb,KAAK,MAAM,CAAC;gBACZ,KAAK,YAAY;oBAChB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;QACF,CAAC;QACD,KAAK,MAAM,QAAQ,IAAI,SAAS;YAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzD,MAAM,WAAW,GAAsB,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;QACxD,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC;YAAE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACnF,CAAC;IAED;;;OAGG;IACH,eAAe,CACd,UAAqC,EACrC,MAAsB,EACtB,MAAoD;QAEpD,gBAAgB,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5C,kBAAkB,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;QACpE,IAAI,iBAAiB,GAAG,GAAS,EAAE,GAAE,CAAC,CAAC;QACvC,IAAI,gBAAgB,GAAG,GAAS,EAAE,GAAE,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,GAAS,EAAE;YACzB,iBAAiB,EAAE,CAAC;YACpB,gBAAgB,EAAE,CAAC;QACpB,CAAC,CAAC;QACF,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACtD,MAAM,QAAQ,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC;QAClD,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE;YAClE,KAAK,MAAM,MAAM,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;gBAC1C,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,IAAI,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,EAAE;oBAAE,SAAS;gBAClF,iGAAiG;gBACjG,MAAM,YAAY,GAAG,QAAQ,YAAY,oBAAoB,CAAC,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;gBACtG,MAAM,GAAG,GAAG,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;gBACjD,4EAA4E;gBAC5E,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;oBAAE,SAAS;gBAC/B,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,YAAY,CAAC,CAAC;YACnD,CAAC;QACF,CAAC,CAAC,CAAC;QACH,gBAAgB,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC;QACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,aAAa,CAClB,UAAqC,EACrC,SAAiB,EACjB,OAAwB,EACxB,OAAgB;QAEhB,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC9C,0GAA0G;QAC1G,IAAI,MAAM,EAAE,YAAY,KAAK,UAAU,CAAC,OAAO;YAAE,OAAO,MAAM,CAAC;QAC/D,IAAI,MAAM,KAAK,SAAS;YAAE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QAC7E,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAC3C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QAC3E,IAAI,MAAM,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,IAAI,kBAAkB,CAAC,CAAC;QAC3G,MAAM,KAAK,GAAG,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACtD,MAAM,MAAM,GAAmB;YAC9B,SAAS;YACT,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,aAAa,EAAE,MAAM,CAAC,OAAO;YAC7B,YAAY,EAAE,UAAU,CAAC,OAAO;YAChC,eAAe,EAAE,MAAM,CAAC,eAAe;YACvC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC;SACrB,CAAC;QACF,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACvC,OAAO,MAAM,CAAC;IACf,CAAC;IAED,QAAQ,CAAI,GAAqB;QAChC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,IAAI,CACpB,GAAG,EAAE,CAAC,SAAS,EACf,GAAG,EAAE,CAAC,SAAS,CACf,CAAC;QACF,OAAO,GAAG,CAAC;IACZ,CAAC;IAED,aAAa;QACZ,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACtE,IAAI,CAAC,cAAc,EAAE,CAAC;IACvB,CAAC;IAED,cAAc;QACb,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,2EAA2E,EAAE;gBAC5F,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;aACzB,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;CACD;AAED;;;GAGG;AACH,SAAS,kBAAkB,CAC1B,QAA6B,EAC7B,MAAoE;IAEpE,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI;QAAE,OAAO,qBAAqB,CAAC;IACxD,IAAI,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,OAAO;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC;IAC3D,QAAQ,CAAC,OAAO,GAAG,MAAM,CAAC,OAAQ,CAAC;IACnC,OAAO,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAmB;IAC7C,OAAO,MAAM,CAAC,MAAM,YAAY,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,2BAA2B,EAAE,YAAY,CAAC,CAAC;AACrH,CAAC","sourcesContent":["import { type Context, type JsonValue, replicatedState } from \"@earendil-works/chord\";\nimport { awaitWithContext, withoutAbortSignal } from \"@earendil-works/chord/context\";\nimport { type Op, track } from \"@earendil-works/chord/delta\";\nimport {\n\ttype AnyDocToken,\n\tcheckRecordScope,\n\tcheckRecordVersion,\n\tmaterializeDocument,\n\tresolveAddress,\n} from \"../documents.ts\";\nimport { StorageRejected } from \"../errors.ts\";\nimport { idFromNumber } from \"../ids.ts\";\nimport type {\n\tCommitChange,\n\tCommitPublication,\n\tConversationDocFamilyToken,\n\tConversationDocToken,\n\tConversationId,\n\tConversationRecord,\n\tDocumentAddress,\n\tDocumentCommitChange,\n\tDocumentRecord,\n\tDocumentState,\n\tDocumentWatch,\n\tEntryId,\n\tJsonObject,\n\tRewindableConversationDocFamilyToken,\n\tRewindableConversationDocToken,\n\tSeq,\n\tSession,\n\tSessionDocFamilyToken,\n\tSessionDocToken,\n\tStorage,\n\tStorageWrite,\n\tTaskDocFamilyToken,\n\tTaskDocToken,\n\tTaskId,\n\tTx,\n} from \"../types.ts\";\nimport {\n\tCommittedStateSource,\n\tCommittedWatch,\n\ttype ObservedDocumentValue,\n\tRETIREMENT_OPERATIONS,\n} from \"./observation.ts\";\nimport { type LoadedDocument, Transaction, type TransactionHost, type TransactionScope } from \"./transaction.ts\";\n\n/** Open a Session kernel over one storage backend. */\nexport function createSession(storage: Storage): Session {\n\treturn new SessionImpl(storage);\n}\n\n/**\n * Session kernel: one mutation line, the loaded document tracker cache, and committed publication.\n *\n * Only committed state is observable. Every commit callback, preparation, Storage settlement, adoption, and\n * publication enqueue runs while the line is held; listeners run later.\n */\nexport class SessionImpl implements Session {\n\treadonly #storage: Storage;\n\treadonly #documents = new Map<string, LoadedDocument>();\n\treadonly #commitListeners = new Set<(publication: CommitPublication, context: Context) => void>();\n\treadonly #closeListeners = new Set<() => void>();\n\treadonly #host: TransactionHost;\n\t#tail: Promise<void> = Promise.resolve();\n\t#closing: Promise<void> | undefined;\n\t#poison: { readonly error: unknown } | undefined;\n\n\tconstructor(storage: Storage) {\n\t\tthis.#storage = storage;\n\t\tthis.#host = {\n\t\t\tstorage,\n\t\t\tcached: (id) => this.#documents.get(id),\n\t\t\tload: (definition, addressId, address, context) => this.#loadDocument(definition, addressId, address, context),\n\t\t\tinstall: (document) => {\n\t\t\t\tthis.#documents.set(document.addressId, document);\n\t\t\t},\n\t\t\tevict: (id, recordId) => {\n\t\t\t\tif (this.#documents.get(id)?.record.id === recordId) this.#documents.delete(id);\n\t\t\t},\n\t\t\tconversationCreated: (tx, record) => this.conversationCreated(tx, record),\n\t\t};\n\t}\n\n\tcommit<T>(change: (tx: Tx) => T | Promise<T>, context: Context): Promise<T> {\n\t\treturn this.commitWith(change, context);\n\t}\n\n\t/**\n\t * Internal commit exposing the concrete transaction and its internal operations, such as the reserved-ID root\n\t * bootstrap and task replacement. `scope` sets the default `tx.createTask()` conversation and the task attributed to\n\t * appended entries.\n\t */\n\tcommitWith<T>(change: (tx: Transaction) => T | Promise<T>, context: Context, scope?: TransactionScope): Promise<T> {\n\t\ttry {\n\t\t\tthis.#assertUsable();\n\t\t} catch (error) {\n\t\t\treturn Promise.reject(error);\n\t\t}\n\t\treturn this.#enqueue(() => this.#runCommit(change, context, scope));\n\t}\n\n\t/** Internal: run a read-only job on the mutation line so multi-read derivations observe one committed state. */\n\treadOnLine<T>(job: () => Promise<T>): Promise<T> {\n\t\ttry {\n\t\t\tthis.#assertUsable();\n\t\t} catch (error) {\n\t\t\treturn Promise.reject(error);\n\t\t}\n\t\treturn this.#enqueue(async () => {\n\t\t\tthis.#assertHealthy();\n\t\t\treturn job();\n\t\t});\n\t}\n\n\t/**\n\t * Internal: a conversation document's current incarnation and value, for a job already running on the line (see\n\t * `readOnLine()`). Absent documents are `undefined`.\n\t */\n\tasync conversationDocumentOnLine(\n\t\ttoken: ConversationDocToken<JsonObject>,\n\t\tconversationId: ConversationId,\n\t\tcontext: Context,\n\t): Promise<{ readonly record: DocumentRecord; readonly version: number; readonly value: JsonObject } | undefined> {\n\t\tconst definition = token.definition;\n\t\tconst resolved = resolveAddress(definition, [conversationId, context]);\n\t\tconst loaded = await this.#loadDocument(definition, resolved.id, resolved.address, context);\n\t\tif (loaded === undefined) return undefined;\n\t\tcheckRecordScope(definition, loaded.record);\n\t\tcheckRecordVersion(definition, loaded.record, loaded.storedVersion);\n\t\treturn { record: loaded.record, version: loaded.valueVersion, value: loaded.tracker.value };\n\t}\n\n\tsnapshot<T extends JsonObject>(token: SessionDocToken<T>, context: Context): Promise<Readonly<T> | undefined>;\n\tsnapshot<T extends JsonObject>(\n\t\ttoken: ConversationDocToken<T>,\n\t\tconversationId: ConversationId,\n\t\tcontext: Context,\n\t): Promise<Readonly<T> | undefined>;\n\tsnapshot<T extends JsonObject>(\n\t\ttoken: TaskDocToken<T>,\n\t\ttaskId: TaskId,\n\t\tcontext: Context,\n\t): Promise<Readonly<T> | undefined>;\n\tsnapshot<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: SessionDocFamilyToken<T, I>,\n\t\tkey: string,\n\t\tcontext: Context,\n\t): Promise<Readonly<T> | undefined>;\n\tsnapshot<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: ConversationDocFamilyToken<T, I>,\n\t\tconversationId: ConversationId,\n\t\tkey: string,\n\t\tcontext: Context,\n\t): Promise<Readonly<T> | undefined>;\n\tsnapshot<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: TaskDocFamilyToken<T, I>,\n\t\ttaskId: TaskId,\n\t\tkey: string,\n\t\tcontext: Context,\n\t): Promise<Readonly<T> | undefined>;\n\tasync snapshot(token: AnyDocToken, ...args: readonly unknown[]): Promise<JsonObject | undefined> {\n\t\tthis.#assertUsable();\n\t\tconst definition = token.definition;\n\t\tconst resolved = resolveAddress(definition, args);\n\t\tconst context = args[resolved.nextArgument] as Context;\n\t\tconst cached = this.#documents.get(resolved.id);\n\t\tconst loaded =\n\t\t\tcached?.valueVersion === definition.version\n\t\t\t\t? cached\n\t\t\t\t: await this.#enqueue(async () => {\n\t\t\t\t\t\tthis.#assertHealthy();\n\t\t\t\t\t\treturn this.#loadDocument(definition, resolved.id, resolved.address, context);\n\t\t\t\t\t});\n\t\tif (loaded === undefined) return undefined;\n\t\tcheckRecordScope(definition, loaded.record);\n\t\tcheckRecordVersion(definition, loaded.record, loaded.storedVersion);\n\t\treturn loaded.tracker.value;\n\t}\n\n\tdocumentState<T extends JsonObject>(\n\t\ttoken: SessionDocToken<T>,\n\t\tcontext: Context,\n\t): Promise<DocumentState<T> | undefined>;\n\tdocumentState<T extends JsonObject>(\n\t\ttoken: ConversationDocToken<T>,\n\t\tconversationId: ConversationId,\n\t\tcontext: Context,\n\t): Promise<DocumentState<T> | undefined>;\n\tdocumentState<T extends JsonObject>(\n\t\ttoken: TaskDocToken<T>,\n\t\ttaskId: TaskId,\n\t\tcontext: Context,\n\t): Promise<DocumentState<T> | undefined>;\n\tdocumentState<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: SessionDocFamilyToken<T, I>,\n\t\tkey: string,\n\t\tcontext: Context,\n\t): Promise<DocumentState<T> | undefined>;\n\tdocumentState<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: ConversationDocFamilyToken<T, I>,\n\t\tconversationId: ConversationId,\n\t\tkey: string,\n\t\tcontext: Context,\n\t): Promise<DocumentState<T> | undefined>;\n\tdocumentState<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: TaskDocFamilyToken<T, I>,\n\t\ttaskId: TaskId,\n\t\tkey: string,\n\t\tcontext: Context,\n\t): Promise<DocumentState<T> | undefined>;\n\tdocumentState(token: AnyDocToken, ...args: readonly unknown[]): Promise<DocumentState<JsonObject> | undefined> {\n\t\ttry {\n\t\t\tthis.#assertUsable();\n\t\t\tconst definition = token.definition;\n\t\t\tconst resolved = resolveAddress(definition, args);\n\t\t\tconst context = args[resolved.nextArgument] as Context;\n\t\t\treturn this.#enqueue(async () => {\n\t\t\t\tthis.#assertHealthy();\n\t\t\t\tconst loaded = await this.#loadDocument(definition, resolved.id, resolved.address, context);\n\t\t\t\tif (loaded === undefined) return undefined;\n\t\t\t\tconst { observer: source, detach } = this.#attachDocument(\n\t\t\t\t\tdefinition,\n\t\t\t\t\tloaded,\n\t\t\t\t\t(value, release) => new CommittedStateSource<ObservedDocumentValue>(value, release),\n\t\t\t\t);\n\t\t\t\ttry {\n\t\t\t\t\treturn replicatedState(source) as DocumentState<JsonObject>;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tdetach();\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error) {\n\t\t\treturn Promise.reject(error);\n\t\t}\n\t}\n\n\twatchDoc<T extends JsonObject>(token: SessionDocToken<T>, context: Context): Promise<DocumentWatch<T> | undefined>;\n\twatchDoc<T extends JsonObject>(\n\t\ttoken: ConversationDocToken<T>,\n\t\tconversationId: ConversationId,\n\t\tcontext: Context,\n\t): Promise<DocumentWatch<T> | undefined>;\n\twatchDoc<T extends JsonObject>(\n\t\ttoken: TaskDocToken<T>,\n\t\ttaskId: TaskId,\n\t\tcontext: Context,\n\t): Promise<DocumentWatch<T> | undefined>;\n\twatchDoc<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: SessionDocFamilyToken<T, I>,\n\t\tkey: string,\n\t\tcontext: Context,\n\t): Promise<DocumentWatch<T> | undefined>;\n\twatchDoc<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: ConversationDocFamilyToken<T, I>,\n\t\tconversationId: ConversationId,\n\t\tkey: string,\n\t\tcontext: Context,\n\t): Promise<DocumentWatch<T> | undefined>;\n\twatchDoc<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: TaskDocFamilyToken<T, I>,\n\t\ttaskId: TaskId,\n\t\tkey: string,\n\t\tcontext: Context,\n\t): Promise<DocumentWatch<T> | undefined>;\n\tasync watchDoc(token: AnyDocToken, ...args: readonly unknown[]): Promise<DocumentWatch<JsonObject> | undefined> {\n\t\tthis.#assertUsable();\n\t\tconst definition = token.definition;\n\t\tconst resolved = resolveAddress(definition, args);\n\t\tconst context = args[resolved.nextArgument] as Context;\n\t\tconst signal = context.abortSignal;\n\t\tlet cancelled = signal?.aborted ?? false;\n\t\tconst markCancelled = (): void => {\n\t\t\tcancelled = true;\n\t\t};\n\t\tsignal?.addEventListener(\"abort\", markCancelled, { once: true });\n\t\ttry {\n\t\t\tconst watch = await this.#enqueue(async () => {\n\t\t\t\tthis.#assertHealthy();\n\t\t\t\tif (cancelled) throw cancellationError(signal!);\n\t\t\t\tconst loaded = await this.#loadDocument(definition, resolved.id, resolved.address, context);\n\t\t\t\tif (cancelled) throw cancellationError(signal!);\n\t\t\t\tif (loaded === undefined) return undefined;\n\t\t\t\treturn this.#attachDocument(\n\t\t\t\t\tdefinition,\n\t\t\t\t\tloaded,\n\t\t\t\t\t(value, release) => new CommittedWatch<ObservedDocumentValue>(value, release),\n\t\t\t\t).observer;\n\t\t\t});\n\t\t\tif (watch === undefined) return undefined;\n\t\t\tif (cancelled) {\n\t\t\t\twatch.cancel();\n\t\t\t\tthrow cancellationError(signal!);\n\t\t\t}\n\t\t\tif (signal !== undefined) watch.observeCancellation(signal);\n\t\t\treturn watch as DocumentWatch<JsonObject>;\n\t\t} finally {\n\t\t\tsignal?.removeEventListener(\"abort\", markCancelled);\n\t\t}\n\t}\n\n\tsnapshotAsOf<T extends JsonObject>(\n\t\ttoken: RewindableConversationDocToken<T>,\n\t\tconversationId: ConversationId,\n\t\tat: EntryId,\n\t\tcontext: Context,\n\t): Promise<Readonly<T> | undefined>;\n\tsnapshotAsOf<T extends JsonObject, I extends JsonValue>(\n\t\ttoken: RewindableConversationDocFamilyToken<T, I>,\n\t\tconversationId: ConversationId,\n\t\tkey: string,\n\t\tat: EntryId,\n\t\tcontext: Context,\n\t): Promise<Readonly<T> | undefined>;\n\tasync snapshotAsOf(token: AnyDocToken, ...args: readonly unknown[]): Promise<JsonObject | undefined> {\n\t\tthis.#assertUsable();\n\t\tconst definition = token.definition;\n\t\tconst resolved = resolveAddress(definition, args);\n\t\tif (resolved.address.scope.kind !== \"conversation\") {\n\t\t\tthrow new TypeError(\"Session.snapshotAsOf() requires a conversation document\");\n\t\t}\n\t\tconst conversationId = resolved.address.scope.conversationId;\n\t\tconst atValue = args[resolved.nextArgument];\n\t\tif (typeof atValue !== \"number\" || !Number.isSafeInteger(atValue)) {\n\t\t\tthrow new TypeError(\"Session.snapshotAsOf() requires an entry ID\");\n\t\t}\n\t\tconst at = idFromNumber<EntryId>(atValue);\n\t\tconst context = args[resolved.nextArgument + 1] as Context;\n\t\treturn this.#enqueue(async () => {\n\t\t\tthis.#assertHealthy();\n\t\t\tconst storedEntry = await this.#storage.entry(conversationId, at, context);\n\t\t\tif (storedEntry === undefined) {\n\t\t\t\tthrow new Error(`Entry ${at} is not visible from conversation ${conversationId}`);\n\t\t\t}\n\t\t\tconst address: DocumentAddress = {\n\t\t\t\t...resolved.address,\n\t\t\t\tscope: { kind: \"conversation\", conversationId: storedEntry.entry.conversationId },\n\t\t\t};\n\t\t\tconst record = await this.#storage.findDocument(address, storedEntry.commitSeq, context);\n\t\t\tif (record === undefined) return undefined;\n\t\t\tconst stored = await this.#storage.document(record.id, storedEntry.commitSeq, context);\n\t\t\tif (stored === undefined) {\n\t\t\t\tthrow new Error(`Historical document ${record.id} (${record.kind}) cannot be read`);\n\t\t\t}\n\t\t\treturn materializeDocument(definition, stored);\n\t\t});\n\t}\n\n\tclose(context: Context): Promise<void> {\n\t\tif (this.#closing === undefined) {\n\t\t\tconst cleanup = withoutAbortSignal(context);\n\t\t\t// Seal admission before anything else runs, then stop observers; admitted work settles before Storage closes.\n\t\t\tthis.#closing = Promise.resolve()\n\t\t\t\t.then(() => this.beforeClose())\n\t\t\t\t.then(() =>\n\t\t\t\t\tthis.#enqueue(async () => {\n\t\t\t\t\t\tthis.#commitListeners.clear();\n\t\t\t\t\t\tthis.#documents.clear();\n\t\t\t\t\t\tawait this.#storage.close(cleanup);\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\tconst listeners = [...this.#closeListeners];\n\t\t\tthis.#closeListeners.clear();\n\t\t\tfor (const listener of listeners) listener();\n\t\t}\n\t\treturn awaitWithContext(this.#closing, context);\n\t}\n\n\t/**\n\t * Runs inside every transaction that creates or forks a conversation, after the conversation record is staged. A\n\t * plain Session stages nothing; a Harness stages its built-in documents.\n\t */\n\tprotected conversationCreated(_tx: Transaction, _record: ConversationRecord): Promise<void> {\n\t\treturn Promise.resolve();\n\t}\n\n\t/** Runs after close seals admission and before the line closes Storage; must not reject. */\n\tprotected beforeClose(): Promise<void> {\n\t\treturn Promise.resolve();\n\t}\n\n\t/** Register a synchronous post-adoption listener. It must not throw, block, or call Session operations. */\n\tsubscribeCommits(listener: (publication: CommitPublication, context: Context) => void): () => void {\n\t\tthis.#assertUsable();\n\t\tthis.#commitListeners.add(listener);\n\t\treturn () => this.#commitListeners.delete(listener);\n\t}\n\n\t/** Register a listener called synchronously when close begins. It must not throw, block, or call Session operations. */\n\tsubscribeClose(listener: () => void): () => void {\n\t\tthis.#assertUsable();\n\t\tthis.#closeListeners.add(listener);\n\t\treturn () => this.#closeListeners.delete(listener);\n\t}\n\n\t/** Drop every loaded tracker on the mutation line; later access cold-loads from Storage. */\n\tunloadDocuments(): Promise<void> {\n\t\treturn this.#enqueue(async () => {\n\t\t\tthis.#documents.clear();\n\t\t});\n\t}\n\n\tasync #runCommit<T>(\n\t\tchange: (tx: Transaction) => T | Promise<T>,\n\t\tcontext: Context,\n\t\tscope?: TransactionScope,\n\t): Promise<T> {\n\t\tthis.#assertHealthy();\n\t\tcontext.abortSignal?.throwIfAborted();\n\t\tconst tx = new Transaction(this.#host, context, scope);\n\t\tlet result: T;\n\t\ttry {\n\t\t\tresult = await change(tx);\n\t\t} catch (error) {\n\t\t\tawait tx.settleFailure();\n\t\t\tthrow error;\n\t\t}\n\t\tconst writes = await tx.settleSuccess();\n\t\tif (writes.length === 0) {\n\t\t\ttx.discard();\n\t\t\treturn result;\n\t\t}\n\t\tlet seq: Seq;\n\t\ttry {\n\t\t\t// Once admitted, caller cancellation does not interrupt Storage settlement.\n\t\t\tseq = await this.#storage.commit(writes, withoutAbortSignal(context));\n\t\t} catch (error) {\n\t\t\ttx.discard();\n\t\t\t// Callback errors never reach this branch; StorageRejected alone guarantees that no batch effect committed.\n\t\t\tif (!(error instanceof StorageRejected)) this.#poison = { error };\n\t\t\tthrow error;\n\t\t}\n\t\tlet documents: DocumentCommitChange[];\n\t\ttry {\n\t\t\tdocuments = tx.adopt(seq);\n\t\t} catch (error) {\n\t\t\t// Storage already committed; a failed adoption leaves memory behind durable state.\n\t\t\tthis.#poison = { error };\n\t\t\tthrow error;\n\t\t}\n\t\tthis.#publish(seq, writes, documents, context);\n\t\treturn result;\n\t}\n\n\t#publish(\n\t\tseq: Seq,\n\t\twrites: readonly StorageWrite[],\n\t\tdocuments: readonly DocumentCommitChange[],\n\t\tcontext: Context,\n\t): void {\n\t\tif (this.#commitListeners.size === 0) return;\n\t\tconst changes: CommitChange[] = [];\n\t\tfor (const write of writes) {\n\t\t\tswitch (write.type) {\n\t\t\t\tcase \"conversation\":\n\t\t\t\tcase \"entry\":\n\t\t\t\tcase \"task\":\n\t\t\t\tcase \"submission\":\n\t\t\t\t\tchanges.push(write);\n\t\t\t}\n\t\t}\n\t\tfor (const document of documents) changes.push(document);\n\t\tconst publication: CommitPublication = { seq, changes };\n\t\tfor (const listener of [...this.#commitListeners]) listener(publication, context);\n\t}\n\n\t/**\n\t * Attach an observer to one committed incarnation: check the definition, then forward this incarnation's committed\n\t * changes and close. `detach` removes both subscriptions.\n\t */\n\t#attachDocument<O extends CommittedStateSource | CommittedWatch>(\n\t\tdefinition: AnyDocToken[\"definition\"],\n\t\tloaded: LoadedDocument,\n\t\tcreate: (value: JsonObject, detach: () => void) => O,\n\t): { observer: O; detach: () => void } {\n\t\tcheckRecordScope(definition, loaded.record);\n\t\tcheckRecordVersion(definition, loaded.record, loaded.storedVersion);\n\t\tlet unsubscribeCommit = (): void => {};\n\t\tlet unsubscribeClose = (): void => {};\n\t\tconst detach = (): void => {\n\t\t\tunsubscribeCommit();\n\t\t\tunsubscribeClose();\n\t\t};\n\t\tconst observer = create(loaded.tracker.value, detach);\n\t\tconst observed = { version: loaded.valueVersion };\n\t\tunsubscribeCommit = this.subscribeCommits((publication, context) => {\n\t\t\tfor (const change of publication.changes) {\n\t\t\t\tif (change.type !== \"document\" || change.record.id !== loaded.record.id) continue;\n\t\t\t\t// A document state's frames carry no caller cancellation; a watch observes its own cancellation.\n\t\t\t\tconst frameContext = observer instanceof CommittedStateSource ? withoutAbortSignal(context) : context;\n\t\t\t\tconst ops = observedOperations(observed, change);\n\t\t\t\t// A migration-only base changes nothing for an observer of the new version.\n\t\t\t\tif (ops.length === 0) continue;\n\t\t\t\tobserver.advance(change.value, ops, frameContext);\n\t\t\t}\n\t\t});\n\t\tunsubscribeClose = this.subscribeClose(() => observer.closeSession());\n\t\treturn { observer, detach };\n\t}\n\n\tasync #loadDocument(\n\t\tdefinition: AnyDocToken[\"definition\"],\n\t\taddressId: string,\n\t\taddress: DocumentAddress,\n\t\tcontext: Context,\n\t): Promise<LoadedDocument | undefined> {\n\t\tconst cached = this.#documents.get(addressId);\n\t\t// A tracker serves only tokens of the version its value was materialized for; others reload from Storage.\n\t\tif (cached?.valueVersion === definition.version) return cached;\n\t\tif (cached !== undefined) this.#documents.delete(addressId);\n\t\tconst record = await this.#storage.findDocument(address, \"current\", context);\n\t\tif (record === undefined) return undefined;\n\t\tconst stored = await this.#storage.document(record.id, \"current\", context);\n\t\tif (stored === undefined) throw new Error(`Current document ${record.id} (${record.kind}) cannot be read`);\n\t\tconst value = materializeDocument(definition, stored);\n\t\tconst loaded: LoadedDocument = {\n\t\t\taddressId,\n\t\t\trecord: stored.record,\n\t\t\tstoredVersion: stored.version,\n\t\t\tvalueVersion: definition.version,\n\t\t\tdeltasSinceBase: stored.deltasSinceBase,\n\t\t\ttracker: track(value),\n\t\t};\n\t\tthis.#documents.set(addressId, loaded);\n\t\treturn loaded;\n\t}\n\n\t#enqueue<T>(job: () => Promise<T>): Promise<T> {\n\t\tconst run = this.#tail.then(job);\n\t\tthis.#tail = run.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t);\n\t\treturn run;\n\t}\n\n\t#assertUsable(): void {\n\t\tif (this.#closing !== undefined) throw new Error(\"Session is closed\");\n\t\tthis.#assertHealthy();\n\t}\n\n\t#assertHealthy(): void {\n\t\tif (this.#poison !== undefined) {\n\t\t\tthrow new Error(\"Session is poisoned by a failed commit after storage admission; reopen it\", {\n\t\t\t\tcause: this.#poison.error,\n\t\t\t});\n\t\t}\n\t}\n}\n\n/**\n * Operations an observer applies for one committed change. An observer hydrated under another definition version holds\n * a differently shaped value, so it receives the new value as a root replacement instead of operations for that shape.\n */\nfunction observedOperations(\n\tobserved: { version: number },\n\tchange: Extract<DocumentCommitChange, { readonly type: \"document\" }>,\n): readonly Op[] {\n\tif (change.value === null) return RETIREMENT_OPERATIONS;\n\tif (change.version === observed.version) return change.ops;\n\tobserved.version = change.version!;\n\treturn [[\"r\", change.value]];\n}\n\nfunction cancellationError(signal: AbortSignal): Error {\n\treturn signal.reason instanceof Error ? signal.reason : new DOMException(\"The operation was aborted\", \"AbortError\");\n}\n"]}
|