@ny4n/durable 0.0.0-stage → 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/LICENSE +21 -0
- package/README.md +711 -2
- package/dist/documents.d.ts +66 -0
- package/dist/documents.d.ts.map +1 -0
- package/dist/documents.js +98 -0
- package/dist/documents.js.map +1 -0
- package/dist/entries.d.ts +31 -0
- package/dist/entries.d.ts.map +1 -0
- package/dist/entries.js +31 -0
- package/dist/entries.js.map +1 -0
- package/dist/env/decode.d.ts +16 -0
- package/dist/env/decode.d.ts.map +1 -0
- package/dist/env/decode.js +28 -0
- package/dist/env/decode.js.map +1 -0
- package/dist/env/index.d.ts +263 -0
- package/dist/env/index.d.ts.map +1 -0
- package/dist/env/index.js +49 -0
- package/dist/env/index.js.map +1 -0
- package/dist/env/line-scan.d.ts +13 -0
- package/dist/env/line-scan.d.ts.map +1 -0
- package/dist/env/line-scan.js +147 -0
- package/dist/env/line-scan.js.map +1 -0
- package/dist/env/node-watch.d.ts +29 -0
- package/dist/env/node-watch.d.ts.map +1 -0
- package/dist/env/node-watch.js +485 -0
- package/dist/env/node-watch.js.map +1 -0
- package/dist/env/node.d.ts +56 -0
- package/dist/env/node.d.ts.map +1 -0
- package/dist/env/node.js +1166 -0
- package/dist/env/node.js.map +1 -0
- package/dist/errors.d.ts +32 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +53 -0
- package/dist/errors.js.map +1 -0
- package/dist/harness/agent.d.ts +33 -0
- package/dist/harness/agent.d.ts.map +1 -0
- package/dist/harness/agent.js +235 -0
- package/dist/harness/agent.js.map +1 -0
- package/dist/harness/assistant.d.ts +15 -0
- package/dist/harness/assistant.d.ts.map +1 -0
- package/dist/harness/assistant.js +23 -0
- package/dist/harness/assistant.js.map +1 -0
- package/dist/harness/compaction.d.ts +56 -0
- package/dist/harness/compaction.d.ts.map +1 -0
- package/dist/harness/compaction.js +384 -0
- package/dist/harness/compaction.js.map +1 -0
- package/dist/harness/context.d.ts +63 -0
- package/dist/harness/context.d.ts.map +1 -0
- package/dist/harness/context.js +221 -0
- package/dist/harness/context.js.map +1 -0
- 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 +180 -0
- package/dist/harness/events.d.ts.map +1 -0
- package/dist/harness/events.js +370 -0
- package/dist/harness/events.js.map +1 -0
- package/dist/harness/generation.d.ts +54 -0
- package/dist/harness/generation.d.ts.map +1 -0
- package/dist/harness/generation.js +514 -0
- package/dist/harness/generation.js.map +1 -0
- package/dist/harness/harness.d.ts +17 -0
- package/dist/harness/harness.d.ts.map +1 -0
- package/dist/harness/harness.js +332 -0
- package/dist/harness/harness.js.map +1 -0
- package/dist/harness/inbox.d.ts +59 -0
- package/dist/harness/inbox.d.ts.map +1 -0
- package/dist/harness/inbox.js +97 -0
- package/dist/harness/inbox.js.map +1 -0
- package/dist/harness/json.d.ts +10 -0
- package/dist/harness/json.d.ts.map +1 -0
- package/dist/harness/json.js +33 -0
- package/dist/harness/json.js.map +1 -0
- package/dist/harness/live.d.ts +142 -0
- package/dist/harness/live.d.ts.map +1 -0
- package/dist/harness/live.js +149 -0
- package/dist/harness/live.js.map +1 -0
- package/dist/harness/output.d.ts +69 -0
- package/dist/harness/output.d.ts.map +1 -0
- package/dist/harness/output.js +318 -0
- package/dist/harness/output.js.map +1 -0
- package/dist/harness/prompt.d.ts +27 -0
- package/dist/harness/prompt.d.ts.map +1 -0
- package/dist/harness/prompt.js +131 -0
- package/dist/harness/prompt.js.map +1 -0
- package/dist/harness/provider.d.ts +14 -0
- package/dist/harness/provider.d.ts.map +1 -0
- package/dist/harness/provider.js +30 -0
- package/dist/harness/provider.js.map +1 -0
- package/dist/harness/registry.d.ts +6 -0
- package/dist/harness/registry.d.ts.map +1 -0
- package/dist/harness/registry.js +101 -0
- package/dist/harness/registry.js.map +1 -0
- package/dist/harness/run.d.ts +17 -0
- package/dist/harness/run.d.ts.map +1 -0
- package/dist/harness/run.js +26 -0
- package/dist/harness/run.js.map +1 -0
- package/dist/harness/scheduler.d.ts +106 -0
- package/dist/harness/scheduler.d.ts.map +1 -0
- package/dist/harness/scheduler.js +1743 -0
- package/dist/harness/scheduler.js.map +1 -0
- package/dist/harness/submissions.d.ts +29 -0
- package/dist/harness/submissions.d.ts.map +1 -0
- package/dist/harness/submissions.js +175 -0
- package/dist/harness/submissions.js.map +1 -0
- 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 +168 -0
- package/dist/harness/task-graph.js.map +1 -0
- package/dist/harness/tool.d.ts +76 -0
- package/dist/harness/tool.d.ts.map +1 -0
- package/dist/harness/tool.js +736 -0
- package/dist/harness/tool.js.map +1 -0
- package/dist/harness/types.d.ts +713 -0
- package/dist/harness/types.d.ts.map +1 -0
- package/dist/harness/types.js +2 -0
- package/dist/harness/types.js.map +1 -0
- package/dist/harness/usage.d.ts +18 -0
- package/dist/harness/usage.d.ts.map +1 -0
- package/dist/harness/usage.js +57 -0
- package/dist/harness/usage.js.map +1 -0
- package/dist/harness/util.d.ts +19 -0
- package/dist/harness/util.d.ts.map +1 -0
- package/dist/harness/util.js +58 -0
- package/dist/harness/util.js.map +1 -0
- package/dist/harness/view.d.ts +47 -0
- package/dist/harness/view.d.ts.map +1 -0
- package/dist/harness/view.js +206 -0
- package/dist/harness/view.js.map +1 -0
- package/dist/ids.d.ts +6 -0
- package/dist/ids.d.ts.map +1 -0
- package/dist/ids.js +9 -0
- package/dist/ids.js.map +1 -0
- package/dist/images/cloudflare.d.ts +4 -0
- package/dist/images/cloudflare.d.ts.map +1 -0
- package/dist/images/cloudflare.js +9 -0
- package/dist/images/cloudflare.js.map +1 -0
- package/dist/images/exif.d.ts +3 -0
- package/dist/images/exif.d.ts.map +1 -0
- package/dist/images/exif.js +71 -0
- package/dist/images/exif.js.map +1 -0
- package/dist/images/index.d.ts +18 -0
- package/dist/images/index.d.ts.map +1 -0
- package/dist/images/index.js +125 -0
- package/dist/images/index.js.map +1 -0
- package/dist/images/node-worker.d.ts +17 -0
- package/dist/images/node-worker.d.ts.map +1 -0
- package/dist/images/node-worker.js +16 -0
- package/dist/images/node-worker.js.map +1 -0
- package/dist/images/node.d.ts +21 -0
- package/dist/images/node.d.ts.map +1 -0
- package/dist/images/node.js +121 -0
- package/dist/images/node.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/session/forks.d.ts +10 -0
- package/dist/session/forks.d.ts.map +1 -0
- package/dist/session/forks.js +42 -0
- package/dist/session/forks.js.map +1 -0
- package/dist/session/observation.d.ts +42 -0
- package/dist/session/observation.d.ts.map +1 -0
- package/dist/session/observation.js +281 -0
- package/dist/session/observation.js.map +1 -0
- package/dist/session/session.d.ts +133 -0
- package/dist/session/session.d.ts.map +1 -0
- package/dist/session/session.js +811 -0
- package/dist/session/session.js.map +1 -0
- package/dist/session/transaction.d.ts +119 -0
- package/dist/session/transaction.d.ts.map +1 -0
- package/dist/session/transaction.js +795 -0
- package/dist/session/transaction.js.map +1 -0
- package/dist/storage/jsonl/index.d.ts +2 -0
- package/dist/storage/jsonl/index.d.ts.map +1 -0
- package/dist/storage/jsonl/index.js +2 -0
- package/dist/storage/jsonl/index.js.map +1 -0
- package/dist/storage/jsonl/node.d.ts +6 -0
- package/dist/storage/jsonl/node.d.ts.map +1 -0
- package/dist/storage/jsonl/node.js +8 -0
- package/dist/storage/jsonl/node.js.map +1 -0
- package/dist/storage/jsonl/storage.d.ts +143 -0
- package/dist/storage/jsonl/storage.d.ts.map +1 -0
- package/dist/storage/jsonl/storage.js +682 -0
- package/dist/storage/jsonl/storage.js.map +1 -0
- package/dist/storage/memory.d.ts +62 -0
- package/dist/storage/memory.d.ts.map +1 -0
- package/dist/storage/memory.js +733 -0
- package/dist/storage/memory.js.map +1 -0
- package/dist/storage/scan.d.ts +18 -0
- package/dist/storage/scan.d.ts.map +1 -0
- package/dist/storage/scan.js +29 -0
- package/dist/storage/scan.js.map +1 -0
- package/dist/storage/sqlite/cloudflare.d.ts +46 -0
- package/dist/storage/sqlite/cloudflare.d.ts.map +1 -0
- package/dist/storage/sqlite/cloudflare.js +106 -0
- package/dist/storage/sqlite/cloudflare.js.map +1 -0
- package/dist/storage/sqlite/database.d.ts +37 -0
- package/dist/storage/sqlite/database.d.ts.map +1 -0
- package/dist/storage/sqlite/database.js +2 -0
- package/dist/storage/sqlite/database.js.map +1 -0
- package/dist/storage/sqlite/index.d.ts +4 -0
- package/dist/storage/sqlite/index.d.ts.map +1 -0
- package/dist/storage/sqlite/index.js +3 -0
- package/dist/storage/sqlite/index.js.map +1 -0
- package/dist/storage/sqlite/migrations.d.ts +11 -0
- package/dist/storage/sqlite/migrations.d.ts.map +1 -0
- package/dist/storage/sqlite/migrations.js +111 -0
- package/dist/storage/sqlite/migrations.js.map +1 -0
- package/dist/storage/sqlite/node.d.ts +41 -0
- package/dist/storage/sqlite/node.d.ts.map +1 -0
- package/dist/storage/sqlite/node.js +179 -0
- package/dist/storage/sqlite/node.js.map +1 -0
- package/dist/storage/sqlite/storage.d.ts +65 -0
- package/dist/storage/sqlite/storage.d.ts.map +1 -0
- package/dist/storage/sqlite/storage.js +670 -0
- package/dist/storage/sqlite/storage.js.map +1 -0
- package/dist/tasks.d.ts +6 -0
- package/dist/tasks.d.ts.map +1 -0
- package/dist/tasks.js +5 -0
- package/dist/tasks.js.map +1 -0
- package/dist/testing/assertions.d.ts +5 -0
- package/dist/testing/assertions.d.ts.map +1 -0
- package/dist/testing/assertions.js +25 -0
- package/dist/testing/assertions.js.map +1 -0
- package/dist/testing/env-conformance.d.ts +7 -0
- package/dist/testing/env-conformance.d.ts.map +1 -0
- package/dist/testing/env-conformance.js +431 -0
- package/dist/testing/env-conformance.js.map +1 -0
- package/dist/testing/index.d.ts +7 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +6 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/runner.d.ts +12 -0
- package/dist/testing/runner.d.ts.map +1 -0
- package/dist/testing/runner.js +23 -0
- package/dist/testing/runner.js.map +1 -0
- package/dist/testing/storage-benchmark.d.ts +41 -0
- package/dist/testing/storage-benchmark.d.ts.map +1 -0
- package/dist/testing/storage-benchmark.js +350 -0
- package/dist/testing/storage-benchmark.js.map +1 -0
- package/dist/testing/storage-conformance.d.ts +4 -0
- package/dist/testing/storage-conformance.d.ts.map +1 -0
- package/dist/testing/storage-conformance.js +1213 -0
- package/dist/testing/storage-conformance.js.map +1 -0
- package/dist/testing/types.d.ts +37 -0
- package/dist/testing/types.d.ts.map +1 -0
- package/dist/testing/types.js +2 -0
- package/dist/testing/types.js.map +1 -0
- package/dist/tools/bash.d.ts +55 -0
- package/dist/tools/bash.d.ts.map +1 -0
- package/dist/tools/bash.js +138 -0
- package/dist/tools/bash.js.map +1 -0
- package/dist/tools/edit-diff.d.ts +89 -0
- package/dist/tools/edit-diff.d.ts.map +1 -0
- package/dist/tools/edit-diff.js +386 -0
- package/dist/tools/edit-diff.js.map +1 -0
- package/dist/tools/edit.d.ts +18 -0
- package/dist/tools/edit.d.ts.map +1 -0
- package/dist/tools/edit.js +117 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/env.d.ts +5 -0
- package/dist/tools/env.d.ts.map +1 -0
- package/dist/tools/env.js +7 -0
- package/dist/tools/env.js.map +1 -0
- package/dist/tools/file-mutation-queue.d.ts +9 -0
- package/dist/tools/file-mutation-queue.d.ts.map +1 -0
- package/dist/tools/file-mutation-queue.js +52 -0
- package/dist/tools/file-mutation-queue.js.map +1 -0
- package/dist/tools/image-processor.d.ts +47 -0
- package/dist/tools/image-processor.d.ts.map +1 -0
- package/dist/tools/image-processor.js +30 -0
- package/dist/tools/image-processor.js.map +1 -0
- package/dist/tools/image.d.ts +20 -0
- package/dist/tools/image.d.ts.map +1 -0
- package/dist/tools/image.js +178 -0
- package/dist/tools/image.js.map +1 -0
- package/dist/tools/index.d.ts +46 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +23 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/path-utils.d.ts +5 -0
- package/dist/tools/path-utils.d.ts.map +1 -0
- package/dist/tools/path-utils.js +26 -0
- package/dist/tools/path-utils.js.map +1 -0
- package/dist/tools/read.d.ts +25 -0
- package/dist/tools/read.d.ts.map +1 -0
- package/dist/tools/read.js +235 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/write.d.ts +10 -0
- package/dist/tools/write.d.ts.map +1 -0
- package/dist/tools/write.js +31 -0
- package/dist/tools/write.js.map +1 -0
- package/dist/truncate.d.ts +64 -0
- package/dist/truncate.d.ts.map +1 -0
- package/dist/truncate.js +154 -0
- package/dist/truncate.js.map +1 -0
- package/dist/types.d.ts +932 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +140 -5
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export { defineDoc, defineDocFamily } from "./documents.ts";
|
|
2
|
+
export { AssistantEntry, CompactionEntry, defineEntry, ResetEntry, SystemEntry, ToolResultEntry, UserEntry, } from "./entries.ts";
|
|
3
|
+
export { ConversationBusy, ReadAfterWrite, SessionFailed, StorageRequestError } from "./errors.ts";
|
|
4
|
+
export { AgentDoc, configure, DEFAULT_COMPACTION_POLICY, DEFAULT_PROGRESS_POLICY, DEFAULT_RETRY_POLICY, } from "./harness/agent.ts";
|
|
5
|
+
export { type CompactionCheckpoint, type CompactionInput, CompactionTask, type SummaryRequest, } from "./harness/compaction.ts";
|
|
6
|
+
export { defineExtension, defineTool, hook, section, wrapSection, wrapTool } from "./harness/define.ts";
|
|
7
|
+
export { type AgentEvent, type AgentEventStream, type MessageChange, type SnapshotEvent, type ToolEventCall, watchEvents, } from "./harness/events.ts";
|
|
8
|
+
export { type GenerationCheckpoint, type GenerationInput, type GenerationResult, GenerationTask, } from "./harness/generation.ts";
|
|
9
|
+
export { Harness } from "./harness/harness.ts";
|
|
10
|
+
export { InboxDoc, type InboxItem, type InboxState } from "./harness/inbox.ts";
|
|
11
|
+
export { type CompactionStatus, LiveDoc, type LiveState, type NestedToolSlot, type NestedToolSummary, type ToolSlot, } from "./harness/live.ts";
|
|
12
|
+
export { ProviderDoc, type ProviderState } from "./harness/provider.ts";
|
|
13
|
+
export { createRegistry } from "./harness/registry.ts";
|
|
14
|
+
export type { TaskGraph, TaskGraphNode, TaskGraphState, TaskGraphWatch } from "./harness/task-graph.ts";
|
|
15
|
+
export { NestedCallDoc, type NestedCallState, ToolTask, type ToolTaskCheckpoint, type ToolTaskInput, type ToolTaskResult, } from "./harness/tool.ts";
|
|
16
|
+
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, NestedToolExecutionResult, ProgressPolicy, PromptInput, PromptSection, QueueMode, Registry, RegistryReader, RegistrySnapshot, Settings, SettledSubmissionRecord, SettledTask, Submission, SubmissionDraft, TaskInspection, ToolControl, ToolDiagnostic, ToolExecutionApi, ToolExecutionMode, ToolExecutionResult, ToolHookCall, ToolHooks, ToolRegistration, UserInput, Wrap, } from "./harness/types.ts";
|
|
17
|
+
export { UsageDoc, type UsageState } from "./harness/usage.ts";
|
|
18
|
+
export type { ConversationView } from "./harness/view.ts";
|
|
19
|
+
export { createSession } from "./session/session.ts";
|
|
20
|
+
export { MemoryStorage } from "./storage/memory.ts";
|
|
21
|
+
export { defineTask } from "./tasks.ts";
|
|
22
|
+
export type { CheckpointInfo, CommitChange, CommitPublication, CommonDocDefinition, ContextEdit, ConversationDocFamilyToken, ConversationDocToken, ConversationId, ConversationOwnership, ConversationQuery, ConversationRecord, Cursor, DocDefinition, DocFamilyDefinition, DocFamilyToken, DocToken, DocumentAddress, DocumentCommitChange, DocumentContent, DocumentCopySource, DocumentCreate, DocumentId, DocumentObserver, DocumentPoint, DocumentQuery, DocumentReader, DocumentRecord, DocumentSemantics, DocumentState, DocumentWatch, Entry, EntryDraft, EntryId, EntryQuery, EntryRecord, HookRunner, Id, JoinPolicy, JsonObject, LatestConversationSemantics, NextTaskState, Page, PhaseHandler, RewindableConversationDocFamilyToken, RewindableConversationDocToken, RewindableConversationSemantics, RunningTask, ScanOrder, Seq, Session, SessionDocFamilyToken, SessionDocToken, SessionEnd, Storage, StorageWrite, StoredDocument, SubmissionCreate, SubmissionId, SubmissionQuery, SubmissionRecord, SubmissionSettlement, TableCommitChange, Task, TaskDefinition, TaskDocFamilyToken, TaskDocToken, TaskId, TaskOptions, TaskOutcome, TaskOutcomeError, TaskOwnership, TaskQuery, TaskRecord, TaskRuntime, TaskState, Tx, TypedEntry, TypedEntryDraft, WatchEnd, WatchHandle, } from "./types.ts";
|
|
23
|
+
export { ROOT_CONVERSATION_ID } from "./types.ts";
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export { defineDoc, defineDocFamily } from "./documents.js";
|
|
2
|
+
export { AssistantEntry, CompactionEntry, defineEntry, ResetEntry, SystemEntry, ToolResultEntry, UserEntry, } from "./entries.js";
|
|
3
|
+
export { ConversationBusy, ReadAfterWrite, SessionFailed, StorageRequestError } from "./errors.js";
|
|
4
|
+
export { AgentDoc, configure, DEFAULT_COMPACTION_POLICY, DEFAULT_PROGRESS_POLICY, DEFAULT_RETRY_POLICY, } from "./harness/agent.js";
|
|
5
|
+
export { CompactionTask, } from "./harness/compaction.js";
|
|
6
|
+
export { defineExtension, defineTool, hook, section, wrapSection, wrapTool } from "./harness/define.js";
|
|
7
|
+
export { watchEvents, } from "./harness/events.js";
|
|
8
|
+
export { GenerationTask, } from "./harness/generation.js";
|
|
9
|
+
export { Harness } from "./harness/harness.js";
|
|
10
|
+
export { InboxDoc } from "./harness/inbox.js";
|
|
11
|
+
export { LiveDoc, } from "./harness/live.js";
|
|
12
|
+
export { ProviderDoc } from "./harness/provider.js";
|
|
13
|
+
export { createRegistry } from "./harness/registry.js";
|
|
14
|
+
export { NestedCallDoc, ToolTask, } from "./harness/tool.js";
|
|
15
|
+
export { UsageDoc } from "./harness/usage.js";
|
|
16
|
+
export { createSession } from "./session/session.js";
|
|
17
|
+
export { MemoryStorage } from "./storage/memory.js";
|
|
18
|
+
export { defineTask } from "./tasks.js";
|
|
19
|
+
export { ROOT_CONVERSATION_ID } from "./types.js";
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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,aAAa,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACnG,OAAO,EACN,QAAQ,EACR,SAAS,EACT,yBAAyB,EACzB,uBAAuB,EACvB,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,EAMN,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,EAEN,OAAO,GAKP,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAsB,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EACN,aAAa,EAEb,QAAQ,GAIR,MAAM,mBAAmB,CAAC;AAwD3B,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;AAmFxC,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, SessionFailed, StorageRequestError } from \"./errors.ts\";\nexport {\n\tAgentDoc,\n\tconfigure,\n\tDEFAULT_COMPACTION_POLICY,\n\tDEFAULT_PROGRESS_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\ttype ToolEventCall,\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 {\n\ttype CompactionStatus,\n\tLiveDoc,\n\ttype LiveState,\n\ttype NestedToolSlot,\n\ttype NestedToolSummary,\n\ttype ToolSlot,\n} from \"./harness/live.ts\";\nexport { ProviderDoc, type ProviderState } from \"./harness/provider.ts\";\nexport { createRegistry } from \"./harness/registry.ts\";\nexport type { TaskGraph, TaskGraphNode, TaskGraphState, TaskGraphWatch } from \"./harness/task-graph.ts\";\nexport {\n\tNestedCallDoc,\n\ttype NestedCallState,\n\tToolTask,\n\ttype ToolTaskCheckpoint,\n\ttype ToolTaskInput,\n\ttype ToolTaskResult,\n} 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\tNestedToolExecutionResult,\n\tProgressPolicy,\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\tToolHookCall,\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\tScanOrder,\n\tSeq,\n\tSession,\n\tSessionDocFamilyToken,\n\tSessionDocToken,\n\tSessionEnd,\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"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Context } from "@ny4n/chord";
|
|
2
|
+
import type { ConversationId, DocumentCopySource, DocumentCreate, EntryId, Storage } from "../types.ts";
|
|
3
|
+
/** One definition-free document copy to create with a forked conversation. */
|
|
4
|
+
export type ForkDocumentCopy = {
|
|
5
|
+
readonly record: DocumentCreate;
|
|
6
|
+
readonly source: DocumentCopySource;
|
|
7
|
+
};
|
|
8
|
+
/** Select every persisted conversation document copied by one fork. */
|
|
9
|
+
export declare function prepareForkDocumentCopies(storage: Storage, parentConversationId: ConversationId, at: EntryId, childConversationId: ConversationId, context: Context): Promise<readonly ForkDocumentCopy[]>;
|
|
10
|
+
//# sourceMappingURL=forks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forks.d.ts","sourceRoot":"","sources":["../../src/session/forks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EACX,cAAc,EAEd,kBAAkB,EAClB,cAAc,EAId,OAAO,EACP,OAAO,EACP,MAAM,aAAa,CAAC;AAMrB,8EAA8E;AAC9E,MAAM,MAAM,gBAAgB,GAAG;IAC9B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;CACpC,CAAC;AAEF,uEAAuE;AACvE,wBAAsB,yBAAyB,CAC9C,OAAO,EAAE,OAAO,EAChB,oBAAoB,EAAE,cAAc,EACpC,EAAE,EAAE,OAAO,EACX,mBAAmB,EAAE,cAAc,EACnC,OAAO,EAAE,OAAO,GACd,OAAO,CAAC,SAAS,gBAAgB,EAAE,CAAC,CA2BtC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { addressId } from "../documents.js";
|
|
2
|
+
const SCAN_PAGE_SIZE = 256;
|
|
3
|
+
/** Select every persisted conversation document copied by one fork. */
|
|
4
|
+
export async function prepareForkDocumentCopies(storage, parentConversationId, at, childConversationId, context) {
|
|
5
|
+
const entry = await storage.entry(parentConversationId, at, context);
|
|
6
|
+
if (entry === undefined)
|
|
7
|
+
throw new Error(`Entry ${at} is not visible from conversation ${parentConversationId}`);
|
|
8
|
+
const copies = [];
|
|
9
|
+
const copiedAddresses = new Set();
|
|
10
|
+
await collectCopies(storage, { kind: "conversation", conversationId: entry.entry.conversationId }, entry.commitSeq, "asOf", childConversationId, copies, copiedAddresses, context);
|
|
11
|
+
await collectCopies(storage, { kind: "conversation", conversationId: parentConversationId }, "current", "current", childConversationId, copies, copiedAddresses, context);
|
|
12
|
+
return copies;
|
|
13
|
+
}
|
|
14
|
+
async function collectCopies(storage, scope, at, policy, childConversationId, copies, copiedAddresses, context) {
|
|
15
|
+
let cursor;
|
|
16
|
+
do {
|
|
17
|
+
const page = await storage.scanDocuments({ scope, at }, SCAN_PAGE_SIZE, cursor, context);
|
|
18
|
+
for (const source of page.items) {
|
|
19
|
+
if (source.scope.kind !== "conversation" || source.fork !== policy)
|
|
20
|
+
continue;
|
|
21
|
+
const id = await storage.mintId();
|
|
22
|
+
const identity = {
|
|
23
|
+
id,
|
|
24
|
+
kind: source.kind,
|
|
25
|
+
...(source.key === undefined ? {} : { key: source.key }),
|
|
26
|
+
scope: { kind: "conversation", conversationId: childConversationId },
|
|
27
|
+
};
|
|
28
|
+
const record = source.history === "latest"
|
|
29
|
+
? { ...identity, history: "latest", fork: source.fork }
|
|
30
|
+
: { ...identity, history: "rewindable", fork: source.fork };
|
|
31
|
+
const copyAddress = addressId(record);
|
|
32
|
+
if (copiedAddresses.has(copyAddress)) {
|
|
33
|
+
const member = record.key === undefined ? record.kind : `${record.kind}/${record.key}`;
|
|
34
|
+
throw new Error(`Fork selects multiple source documents for ${member}`);
|
|
35
|
+
}
|
|
36
|
+
copiedAddresses.add(copyAddress);
|
|
37
|
+
copies.push({ record, source: { id: source.id, at } });
|
|
38
|
+
}
|
|
39
|
+
cursor = page.next;
|
|
40
|
+
} while (cursor !== undefined);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=forks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forks.js","sourceRoot":"","sources":["../../src/session/forks.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Context } from \"@ny4n/chord\";\nimport { addressId } from \"../documents.ts\";\nimport type {\n\tConversationId,\n\tCursor,\n\tDocumentCopySource,\n\tDocumentCreate,\n\tDocumentId,\n\tDocumentPoint,\n\tDocumentRecord,\n\tEntryId,\n\tStorage,\n} from \"../types.ts\";\n\nconst SCAN_PAGE_SIZE = 256;\n\ntype ForkPolicy = \"asOf\" | \"current\";\n\n/** One definition-free document copy to create with a forked conversation. */\nexport type ForkDocumentCopy = {\n\treadonly record: DocumentCreate;\n\treadonly source: DocumentCopySource;\n};\n\n/** Select every persisted conversation document copied by one fork. */\nexport async function prepareForkDocumentCopies(\n\tstorage: Storage,\n\tparentConversationId: ConversationId,\n\tat: EntryId,\n\tchildConversationId: ConversationId,\n\tcontext: Context,\n): Promise<readonly ForkDocumentCopy[]> {\n\tconst entry = await storage.entry(parentConversationId, at, context);\n\tif (entry === undefined) throw new Error(`Entry ${at} is not visible from conversation ${parentConversationId}`);\n\n\tconst copies: ForkDocumentCopy[] = [];\n\tconst copiedAddresses = new Set<string>();\n\tawait collectCopies(\n\t\tstorage,\n\t\t{ kind: \"conversation\", conversationId: entry.entry.conversationId },\n\t\tentry.commitSeq,\n\t\t\"asOf\",\n\t\tchildConversationId,\n\t\tcopies,\n\t\tcopiedAddresses,\n\t\tcontext,\n\t);\n\tawait collectCopies(\n\t\tstorage,\n\t\t{ kind: \"conversation\", conversationId: parentConversationId },\n\t\t\"current\",\n\t\t\"current\",\n\t\tchildConversationId,\n\t\tcopies,\n\t\tcopiedAddresses,\n\t\tcontext,\n\t);\n\treturn copies;\n}\n\nasync function collectCopies(\n\tstorage: Storage,\n\tscope: Extract<DocumentRecord[\"scope\"], { readonly kind: \"conversation\" }>,\n\tat: DocumentPoint,\n\tpolicy: ForkPolicy,\n\tchildConversationId: ConversationId,\n\tcopies: ForkDocumentCopy[],\n\tcopiedAddresses: Set<string>,\n\tcontext: Context,\n): Promise<void> {\n\tlet cursor: Cursor | undefined;\n\tdo {\n\t\tconst page = await storage.scanDocuments({ scope, at }, SCAN_PAGE_SIZE, cursor, context);\n\t\tfor (const source of page.items) {\n\t\t\tif (source.scope.kind !== \"conversation\" || source.fork !== policy) continue;\n\t\t\tconst id = await storage.mintId<DocumentId>();\n\t\t\tconst identity = {\n\t\t\t\tid,\n\t\t\t\tkind: source.kind,\n\t\t\t\t...(source.key === undefined ? {} : { key: source.key }),\n\t\t\t\tscope: { kind: \"conversation\" as const, conversationId: childConversationId },\n\t\t\t};\n\t\t\tconst record: DocumentCreate =\n\t\t\t\tsource.history === \"latest\"\n\t\t\t\t\t? { ...identity, history: \"latest\", fork: source.fork }\n\t\t\t\t\t: { ...identity, history: \"rewindable\", fork: source.fork };\n\t\t\tconst copyAddress = addressId(record);\n\t\t\tif (copiedAddresses.has(copyAddress)) {\n\t\t\t\tconst member = record.key === undefined ? record.kind : `${record.kind}/${record.key}`;\n\t\t\t\tthrow new Error(`Fork selects multiple source documents for ${member}`);\n\t\t\t}\n\t\t\tcopiedAddresses.add(copyAddress);\n\t\t\tcopies.push({ record, source: { id: source.id, at } });\n\t\t}\n\t\tcursor = page.next;\n\t} while (cursor !== undefined);\n}\n"]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Context, ReplicatedStateSource, ReplicatedStateSourceAttachment } from "@ny4n/chord";
|
|
2
|
+
import type { Op } from "@ny4n/chord/delta";
|
|
3
|
+
import type { JsonObject, WatchEnd, WatchHandle } from "../types.ts";
|
|
4
|
+
export type ObservedDocumentValue = Readonly<JsonObject> | null;
|
|
5
|
+
/** Canonical terminal update for a retired document incarnation. */
|
|
6
|
+
export declare const RETIREMENT_OPERATIONS: readonly Op[];
|
|
7
|
+
/**
|
|
8
|
+
* Session-to-Chord bridge owned one-to-one by one attached state: a document, or a conversation view. A `null` value
|
|
9
|
+
* retires it. @internal
|
|
10
|
+
*/
|
|
11
|
+
export declare class CommittedStateSource<T = ObservedDocumentValue> implements ReplicatedStateSource<T> {
|
|
12
|
+
#private;
|
|
13
|
+
constructor(value: T, release: () => void);
|
|
14
|
+
attach(): ReplicatedStateSourceAttachment<T>;
|
|
15
|
+
advance(value: T, ops: readonly Op[], context: Context): void;
|
|
16
|
+
/** Stop publishing; the attached states keep their last value. A failure ends them the same way. */
|
|
17
|
+
closeSession(): void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Serialized exact-frame watch bound to one document incarnation or conversation view. A `null` value retires it.
|
|
21
|
+
* @internal
|
|
22
|
+
*/
|
|
23
|
+
export declare class CommittedWatch<T = ObservedDocumentValue> implements WatchHandle<T> {
|
|
24
|
+
#private;
|
|
25
|
+
/**
|
|
26
|
+
* `report` gets a listener's throw, which also ends the watch. `replace` gives the value an overflow delivers; by
|
|
27
|
+
* default the newest value.
|
|
28
|
+
*/
|
|
29
|
+
constructor(value: T, detach: () => void, report: (error: unknown) => void, replace?: () => T);
|
|
30
|
+
get value(): T;
|
|
31
|
+
get closed(): Promise<WatchEnd>;
|
|
32
|
+
start(listener: (value: T, ops: readonly Op[], context: Context) => Promise<void>): void;
|
|
33
|
+
stop(): Promise<WatchEnd>;
|
|
34
|
+
observeCancellation(signal: AbortSignal): void;
|
|
35
|
+
cancel(): void;
|
|
36
|
+
/** End with `session_closed`, or with `session_failed` and the error when the Session failed. */
|
|
37
|
+
closeSession(failure?: {
|
|
38
|
+
readonly error: unknown;
|
|
39
|
+
}): void;
|
|
40
|
+
advance(value: T, ops: readonly Op[], context: Context): void;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=observation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../../src/session/observation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,OAAO,EAEP,qBAAqB,EACrB,+BAA+B,EAE/B,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AAE5C,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAErE,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;AAKhE,oEAAoE;AACpE,eAAO,MAAM,qBAAqB,EAAE,SAAS,EAAE,EAAkB,CAAC;AAElE;;;GAGG;AACH,qBAAa,oBAAoB,CAAC,CAAC,GAAG,qBAAqB,CAAE,YAAW,qBAAqB,CAAC,CAAC,CAAC;;IAS/F,YAAY,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,IAAI,EAGxC;IAED,MAAM,IAAI,+BAA+B,CAAC,CAAC,CAAC,CAQ3C;IAED,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAY5D;IAED,oGAAoG;IACpG,YAAY,IAAI,IAAI,CAInB;CAUD;AA2ED;;;GAGG;AACH,qBAAa,cAAc,CAAC,CAAC,GAAG,qBAAqB,CAAE,YAAW,WAAW,CAAC,CAAC,CAAC;;IAiB/E;;;OAGG;IACH,YAAY,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAK5F;IAED,IAAI,KAAK,IAAI,CAAC,CAEb;IAED,IAAI,MAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,CAE9B;IAED,KAAK,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAMvF;IAED,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,CAGxB;IAED,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAO7C;IAED,MAAM,IAAI,IAAI,CAEb;IAED,iGAAiG;IACjG,YAAY,CAAC,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAIxD;IAED,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAW5D;CAmDD"}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { withoutAbortSignal } from "@ny4n/chord/context";
|
|
2
|
+
import { errorMessage } from "../errors.js";
|
|
3
|
+
/** Maximum exact committed frames retained behind one unavailable watch listener. */
|
|
4
|
+
const MAX_PENDING_WATCH_FRAMES = 100;
|
|
5
|
+
/** Canonical terminal update for a retired document incarnation. */
|
|
6
|
+
export const RETIREMENT_OPERATIONS = [["r", null]];
|
|
7
|
+
/**
|
|
8
|
+
* Session-to-Chord bridge owned one-to-one by one attached state: a document, or a conversation view. A `null` value
|
|
9
|
+
* retires it. @internal
|
|
10
|
+
*/
|
|
11
|
+
export class CommittedStateSource {
|
|
12
|
+
#attachments = new Set();
|
|
13
|
+
#release;
|
|
14
|
+
/** Released on disposal. */
|
|
15
|
+
#value;
|
|
16
|
+
#cursor = 0;
|
|
17
|
+
#retired = false;
|
|
18
|
+
#closed = false;
|
|
19
|
+
constructor(value, release) {
|
|
20
|
+
this.#value = value;
|
|
21
|
+
this.#release = release;
|
|
22
|
+
}
|
|
23
|
+
attach() {
|
|
24
|
+
if (this.#closed)
|
|
25
|
+
throw new Error("State source is closed");
|
|
26
|
+
const attachment = new SessionSourceAttachment({ value: this.#value, cursor: this.#cursor }, () => {
|
|
27
|
+
this.#attachments.delete(attachment);
|
|
28
|
+
if (this.#attachments.size === 0)
|
|
29
|
+
this.#finishDisposal();
|
|
30
|
+
});
|
|
31
|
+
this.#attachments.add(attachment);
|
|
32
|
+
return attachment;
|
|
33
|
+
}
|
|
34
|
+
advance(value, ops, context) {
|
|
35
|
+
if (this.#closed || this.#retired)
|
|
36
|
+
return;
|
|
37
|
+
this.#value = value;
|
|
38
|
+
this.#cursor += 1;
|
|
39
|
+
if (value === null)
|
|
40
|
+
this.#retired = true;
|
|
41
|
+
const frame = {
|
|
42
|
+
cursor: this.#cursor,
|
|
43
|
+
value,
|
|
44
|
+
ops,
|
|
45
|
+
context,
|
|
46
|
+
};
|
|
47
|
+
for (const attachment of [...this.#attachments])
|
|
48
|
+
attachment.publish(frame);
|
|
49
|
+
}
|
|
50
|
+
/** Stop publishing; the attached states keep their last value. A failure ends them the same way. */
|
|
51
|
+
closeSession() {
|
|
52
|
+
if (this.#closed)
|
|
53
|
+
return;
|
|
54
|
+
for (const attachment of [...this.#attachments])
|
|
55
|
+
attachment.dispose();
|
|
56
|
+
this.#finishDisposal();
|
|
57
|
+
}
|
|
58
|
+
#finishDisposal() {
|
|
59
|
+
if (this.#closed)
|
|
60
|
+
return;
|
|
61
|
+
this.#closed = true;
|
|
62
|
+
this.#value = undefined;
|
|
63
|
+
const release = this.#release;
|
|
64
|
+
this.#release = undefined;
|
|
65
|
+
release?.();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
class SessionSourceAttachment {
|
|
69
|
+
snapshot;
|
|
70
|
+
#release;
|
|
71
|
+
#frames = [];
|
|
72
|
+
#listener;
|
|
73
|
+
#activated = false;
|
|
74
|
+
#disposed = false;
|
|
75
|
+
#scheduled = false;
|
|
76
|
+
#delivering = false;
|
|
77
|
+
constructor(snapshot, release) {
|
|
78
|
+
this.snapshot = snapshot;
|
|
79
|
+
this.#release = release;
|
|
80
|
+
}
|
|
81
|
+
activate(listener) {
|
|
82
|
+
if (this.#activated)
|
|
83
|
+
throw new Error("State attachment is already active");
|
|
84
|
+
if (this.#disposed)
|
|
85
|
+
throw new Error("State attachment is disposed");
|
|
86
|
+
this.#activated = true;
|
|
87
|
+
this.#listener = listener;
|
|
88
|
+
this.#drain();
|
|
89
|
+
}
|
|
90
|
+
publish(frame) {
|
|
91
|
+
if (this.#disposed)
|
|
92
|
+
return;
|
|
93
|
+
this.#frames.push(frame);
|
|
94
|
+
if (!this.#activated || this.#delivering || this.#scheduled)
|
|
95
|
+
return;
|
|
96
|
+
this.#scheduled = true;
|
|
97
|
+
queueMicrotask(() => {
|
|
98
|
+
this.#scheduled = false;
|
|
99
|
+
if (this.#disposed)
|
|
100
|
+
return;
|
|
101
|
+
try {
|
|
102
|
+
this.#drain();
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// Chord's frame listener contains source-contract failures. Isolate an
|
|
106
|
+
// unexpected direct listener failure to this attachment as well.
|
|
107
|
+
this.dispose();
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
dispose() {
|
|
112
|
+
if (this.#disposed)
|
|
113
|
+
return;
|
|
114
|
+
this.#disposed = true;
|
|
115
|
+
this.#frames.length = 0;
|
|
116
|
+
this.#listener = undefined;
|
|
117
|
+
const release = this.#release;
|
|
118
|
+
this.#release = undefined;
|
|
119
|
+
release?.();
|
|
120
|
+
}
|
|
121
|
+
#drain() {
|
|
122
|
+
const listener = this.#listener;
|
|
123
|
+
if (listener === undefined || this.#delivering || this.#disposed)
|
|
124
|
+
return;
|
|
125
|
+
this.#delivering = true;
|
|
126
|
+
try {
|
|
127
|
+
while (!this.#disposed) {
|
|
128
|
+
const frame = this.#frames.shift();
|
|
129
|
+
if (frame === undefined)
|
|
130
|
+
break;
|
|
131
|
+
listener(frame);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
this.#delivering = false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Serialized exact-frame watch bound to one document incarnation or conversation view. A `null` value retires it.
|
|
141
|
+
* @internal
|
|
142
|
+
*/
|
|
143
|
+
export class CommittedWatch {
|
|
144
|
+
#detach;
|
|
145
|
+
#report;
|
|
146
|
+
#replace;
|
|
147
|
+
#closed = Promise.withResolvers();
|
|
148
|
+
#pending = [];
|
|
149
|
+
#value;
|
|
150
|
+
#listener;
|
|
151
|
+
#started = false;
|
|
152
|
+
#scheduled = false;
|
|
153
|
+
#running = false;
|
|
154
|
+
#retired = false;
|
|
155
|
+
/** Set once, by `#terminate()`. */
|
|
156
|
+
#end;
|
|
157
|
+
#cancellationSignal;
|
|
158
|
+
#cancellationListener;
|
|
159
|
+
/**
|
|
160
|
+
* `report` gets a listener's throw, which also ends the watch. `replace` gives the value an overflow delivers; by
|
|
161
|
+
* default the newest value.
|
|
162
|
+
*/
|
|
163
|
+
constructor(value, detach, report, replace) {
|
|
164
|
+
this.#value = value;
|
|
165
|
+
this.#detach = detach;
|
|
166
|
+
this.#report = report;
|
|
167
|
+
this.#replace = replace;
|
|
168
|
+
}
|
|
169
|
+
get value() {
|
|
170
|
+
return this.#value;
|
|
171
|
+
}
|
|
172
|
+
get closed() {
|
|
173
|
+
return this.#closed.promise;
|
|
174
|
+
}
|
|
175
|
+
start(listener) {
|
|
176
|
+
if (this.#started)
|
|
177
|
+
throw new Error("Watch is already started");
|
|
178
|
+
if (this.#end !== undefined)
|
|
179
|
+
throw new Error("Watch is stopped");
|
|
180
|
+
this.#started = true;
|
|
181
|
+
this.#listener = listener;
|
|
182
|
+
if (this.#pending.length > 0)
|
|
183
|
+
this.#schedule();
|
|
184
|
+
}
|
|
185
|
+
stop() {
|
|
186
|
+
this.#terminate({ reason: "stopped" });
|
|
187
|
+
return this.#closed.promise;
|
|
188
|
+
}
|
|
189
|
+
observeCancellation(signal) {
|
|
190
|
+
if (this.#cancellationSignal !== undefined)
|
|
191
|
+
throw new Error("Watch cancellation is already installed");
|
|
192
|
+
if (this.#end !== undefined)
|
|
193
|
+
return;
|
|
194
|
+
this.#cancellationSignal = signal;
|
|
195
|
+
this.#cancellationListener = () => this.cancel();
|
|
196
|
+
signal.addEventListener("abort", this.#cancellationListener, { once: true });
|
|
197
|
+
if (signal.aborted)
|
|
198
|
+
this.cancel();
|
|
199
|
+
}
|
|
200
|
+
cancel() {
|
|
201
|
+
this.#terminate({ reason: "cancelled" });
|
|
202
|
+
}
|
|
203
|
+
/** End with `session_closed`, or with `session_failed` and the error when the Session failed. */
|
|
204
|
+
closeSession(failure) {
|
|
205
|
+
this.#terminate(failure === undefined ? { reason: "session_closed" } : { reason: "session_failed", error: failure.error });
|
|
206
|
+
}
|
|
207
|
+
advance(value, ops, context) {
|
|
208
|
+
if (this.#end !== undefined || this.#retired)
|
|
209
|
+
return;
|
|
210
|
+
if (value === null)
|
|
211
|
+
this.#retired = true;
|
|
212
|
+
if (this.#pending.length >= MAX_PENDING_WATCH_FRAMES) {
|
|
213
|
+
this.#pending.length = 0;
|
|
214
|
+
const replacement = this.#replace?.() ?? value;
|
|
215
|
+
this.#pending.push({ value: replacement, ops: [["r", replacement]], context });
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
this.#pending.push({ value, ops, context });
|
|
219
|
+
}
|
|
220
|
+
if (this.#started)
|
|
221
|
+
this.#schedule();
|
|
222
|
+
}
|
|
223
|
+
#schedule() {
|
|
224
|
+
if (this.#scheduled || this.#running || this.#end !== undefined)
|
|
225
|
+
return;
|
|
226
|
+
this.#scheduled = true;
|
|
227
|
+
queueMicrotask(() => {
|
|
228
|
+
this.#scheduled = false;
|
|
229
|
+
void this.#drain();
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
async #drain() {
|
|
233
|
+
if (this.#running || this.#end !== undefined || !this.#started)
|
|
234
|
+
return;
|
|
235
|
+
this.#running = true;
|
|
236
|
+
try {
|
|
237
|
+
while (this.#end === undefined) {
|
|
238
|
+
const frame = this.#pending.shift();
|
|
239
|
+
if (frame === undefined)
|
|
240
|
+
break;
|
|
241
|
+
this.#value = frame.value;
|
|
242
|
+
const deliveryContext = withoutAbortSignal(frame.context);
|
|
243
|
+
try {
|
|
244
|
+
await this.#listener(frame.value, frame.ops, deliveryContext);
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
if (this.#end === undefined) {
|
|
248
|
+
this.#report(error);
|
|
249
|
+
this.#terminate({ reason: "listener_error", error: toError(error) });
|
|
250
|
+
}
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
if (frame.value === null) {
|
|
254
|
+
this.#terminate({ reason: "retired" });
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
finally {
|
|
260
|
+
this.#running = false;
|
|
261
|
+
if (this.#end === undefined && this.#pending.length > 0)
|
|
262
|
+
this.#schedule();
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/** End the watch, once: detach, drop pending frames, and settle `closed`. A callback already running keeps running. */
|
|
266
|
+
#terminate(end) {
|
|
267
|
+
if (this.#end !== undefined)
|
|
268
|
+
return;
|
|
269
|
+
this.#end = end;
|
|
270
|
+
this.#detach();
|
|
271
|
+
this.#pending.length = 0;
|
|
272
|
+
if (this.#cancellationListener !== undefined) {
|
|
273
|
+
this.#cancellationSignal?.removeEventListener("abort", this.#cancellationListener);
|
|
274
|
+
}
|
|
275
|
+
this.#closed.resolve(end);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
function toError(error) {
|
|
279
|
+
return error instanceof Error ? error : new Error(errorMessage(error));
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=observation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observation.js","sourceRoot":"","sources":["../../src/session/observation.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tContext,\n\tJsonValue,\n\tReplicatedStateSource,\n\tReplicatedStateSourceAttachment,\n\tReplicatedStateSourceFrame,\n} from \"@ny4n/chord\";\nimport { withoutAbortSignal } from \"@ny4n/chord/context\";\nimport type { Op } from \"@ny4n/chord/delta\";\nimport { errorMessage } from \"../errors.ts\";\nimport type { JsonObject, WatchEnd, WatchHandle } from \"../types.ts\";\n\nexport type ObservedDocumentValue = Readonly<JsonObject> | null;\n\n/** Maximum exact committed frames retained behind one unavailable watch listener. */\nconst MAX_PENDING_WATCH_FRAMES = 100;\n\n/** Canonical terminal update for a retired document incarnation. */\nexport const RETIREMENT_OPERATIONS: readonly Op[] = [[\"r\", null]];\n\n/**\n * Session-to-Chord bridge owned one-to-one by one attached state: a document, or a conversation view. A `null` value\n * retires it. @internal\n */\nexport class CommittedStateSource<T = ObservedDocumentValue> implements ReplicatedStateSource<T> {\n\treadonly #attachments = new Set<SessionSourceAttachment<T>>();\n\t#release: (() => void) | undefined;\n\t/** Released on disposal. */\n\t#value: T | undefined;\n\t#cursor = 0;\n\t#retired = false;\n\t#closed = false;\n\n\tconstructor(value: T, release: () => void) {\n\t\tthis.#value = value;\n\t\tthis.#release = release;\n\t}\n\n\tattach(): ReplicatedStateSourceAttachment<T> {\n\t\tif (this.#closed) throw new Error(\"State source is closed\");\n\t\tconst attachment = new SessionSourceAttachment({ value: this.#value as T, cursor: this.#cursor }, () => {\n\t\t\tthis.#attachments.delete(attachment);\n\t\t\tif (this.#attachments.size === 0) this.#finishDisposal();\n\t\t});\n\t\tthis.#attachments.add(attachment);\n\t\treturn attachment;\n\t}\n\n\tadvance(value: T, ops: readonly Op[], context: Context): void {\n\t\tif (this.#closed || this.#retired) return;\n\t\tthis.#value = value;\n\t\tthis.#cursor += 1;\n\t\tif (value === null) this.#retired = true;\n\t\tconst frame: ReplicatedStateSourceFrame<T> = {\n\t\t\tcursor: this.#cursor,\n\t\t\tvalue,\n\t\t\tops,\n\t\t\tcontext,\n\t\t};\n\t\tfor (const attachment of [...this.#attachments]) attachment.publish(frame);\n\t}\n\n\t/** Stop publishing; the attached states keep their last value. A failure ends them the same way. */\n\tcloseSession(): void {\n\t\tif (this.#closed) return;\n\t\tfor (const attachment of [...this.#attachments]) attachment.dispose();\n\t\tthis.#finishDisposal();\n\t}\n\n\t#finishDisposal(): void {\n\t\tif (this.#closed) return;\n\t\tthis.#closed = true;\n\t\tthis.#value = undefined;\n\t\tconst release = this.#release;\n\t\tthis.#release = undefined;\n\t\trelease?.();\n\t}\n}\n\nclass SessionSourceAttachment<T> implements ReplicatedStateSourceAttachment<T> {\n\treadonly snapshot: { readonly value: T; readonly cursor: number };\n\t#release: (() => void) | undefined;\n\treadonly #frames: ReplicatedStateSourceFrame<T>[] = [];\n\t#listener: ((frame: ReplicatedStateSourceFrame<T>) => void) | undefined;\n\t#activated = false;\n\t#disposed = false;\n\t#scheduled = false;\n\t#delivering = false;\n\n\tconstructor(snapshot: { readonly value: T; readonly cursor: number }, release: () => void) {\n\t\tthis.snapshot = snapshot;\n\t\tthis.#release = release;\n\t}\n\n\tactivate(listener: (frame: ReplicatedStateSourceFrame<T>) => void): void {\n\t\tif (this.#activated) throw new Error(\"State attachment is already active\");\n\t\tif (this.#disposed) throw new Error(\"State attachment is disposed\");\n\t\tthis.#activated = true;\n\t\tthis.#listener = listener;\n\t\tthis.#drain();\n\t}\n\n\tpublish(frame: ReplicatedStateSourceFrame<T>): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#frames.push(frame);\n\t\tif (!this.#activated || this.#delivering || this.#scheduled) return;\n\t\tthis.#scheduled = true;\n\t\tqueueMicrotask(() => {\n\t\t\tthis.#scheduled = false;\n\t\t\tif (this.#disposed) return;\n\t\t\ttry {\n\t\t\t\tthis.#drain();\n\t\t\t} catch {\n\t\t\t\t// Chord's frame listener contains source-contract failures. Isolate an\n\t\t\t\t// unexpected direct listener failure to this attachment as well.\n\t\t\t\tthis.dispose();\n\t\t\t}\n\t\t});\n\t}\n\n\tdispose(): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#disposed = true;\n\t\tthis.#frames.length = 0;\n\t\tthis.#listener = undefined;\n\t\tconst release = this.#release;\n\t\tthis.#release = undefined;\n\t\trelease?.();\n\t}\n\n\t#drain(): void {\n\t\tconst listener = this.#listener;\n\t\tif (listener === undefined || this.#delivering || this.#disposed) return;\n\t\tthis.#delivering = true;\n\t\ttry {\n\t\t\twhile (!this.#disposed) {\n\t\t\t\tconst frame = this.#frames.shift();\n\t\t\t\tif (frame === undefined) break;\n\t\t\t\tlistener(frame);\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.#delivering = false;\n\t\t}\n\t}\n}\n\ntype WatchFrame<T> = {\n\treadonly value: T;\n\treadonly ops: readonly Op[];\n\treadonly context: Context;\n};\n\n/**\n * Serialized exact-frame watch bound to one document incarnation or conversation view. A `null` value retires it.\n * @internal\n */\nexport class CommittedWatch<T = ObservedDocumentValue> implements WatchHandle<T> {\n\treadonly #detach: () => void;\n\treadonly #report: (error: unknown) => void;\n\treadonly #replace: (() => T) | undefined;\n\treadonly #closed = Promise.withResolvers<WatchEnd>();\n\treadonly #pending: WatchFrame<T>[] = [];\n\t#value: T;\n\t#listener: ((value: T, ops: readonly Op[], context: Context) => Promise<void>) | undefined;\n\t#started = false;\n\t#scheduled = false;\n\t#running = false;\n\t#retired = false;\n\t/** Set once, by `#terminate()`. */\n\t#end: WatchEnd | undefined;\n\t#cancellationSignal: AbortSignal | undefined;\n\t#cancellationListener: (() => void) | undefined;\n\n\t/**\n\t * `report` gets a listener's throw, which also ends the watch. `replace` gives the value an overflow delivers; by\n\t * default the newest value.\n\t */\n\tconstructor(value: T, detach: () => void, report: (error: unknown) => void, replace?: () => T) {\n\t\tthis.#value = value;\n\t\tthis.#detach = detach;\n\t\tthis.#report = report;\n\t\tthis.#replace = replace;\n\t}\n\n\tget value(): T {\n\t\treturn this.#value;\n\t}\n\n\tget closed(): Promise<WatchEnd> {\n\t\treturn this.#closed.promise;\n\t}\n\n\tstart(listener: (value: T, ops: readonly Op[], context: Context) => Promise<void>): void {\n\t\tif (this.#started) throw new Error(\"Watch is already started\");\n\t\tif (this.#end !== undefined) throw new Error(\"Watch is stopped\");\n\t\tthis.#started = true;\n\t\tthis.#listener = listener;\n\t\tif (this.#pending.length > 0) this.#schedule();\n\t}\n\n\tstop(): Promise<WatchEnd> {\n\t\tthis.#terminate({ reason: \"stopped\" });\n\t\treturn this.#closed.promise;\n\t}\n\n\tobserveCancellation(signal: AbortSignal): void {\n\t\tif (this.#cancellationSignal !== undefined) throw new Error(\"Watch cancellation is already installed\");\n\t\tif (this.#end !== undefined) return;\n\t\tthis.#cancellationSignal = signal;\n\t\tthis.#cancellationListener = () => this.cancel();\n\t\tsignal.addEventListener(\"abort\", this.#cancellationListener, { once: true });\n\t\tif (signal.aborted) this.cancel();\n\t}\n\n\tcancel(): void {\n\t\tthis.#terminate({ reason: \"cancelled\" });\n\t}\n\n\t/** End with `session_closed`, or with `session_failed` and the error when the Session failed. */\n\tcloseSession(failure?: { readonly error: unknown }): void {\n\t\tthis.#terminate(\n\t\t\tfailure === undefined ? { reason: \"session_closed\" } : { reason: \"session_failed\", error: failure.error },\n\t\t);\n\t}\n\n\tadvance(value: T, ops: readonly Op[], context: Context): void {\n\t\tif (this.#end !== undefined || this.#retired) return;\n\t\tif (value === null) this.#retired = true;\n\t\tif (this.#pending.length >= MAX_PENDING_WATCH_FRAMES) {\n\t\t\tthis.#pending.length = 0;\n\t\t\tconst replacement = this.#replace?.() ?? value;\n\t\t\tthis.#pending.push({ value: replacement, ops: [[\"r\", replacement as JsonValue]], context });\n\t\t} else {\n\t\t\tthis.#pending.push({ value, ops, context });\n\t\t}\n\t\tif (this.#started) this.#schedule();\n\t}\n\n\t#schedule(): void {\n\t\tif (this.#scheduled || this.#running || this.#end !== undefined) return;\n\t\tthis.#scheduled = true;\n\t\tqueueMicrotask(() => {\n\t\t\tthis.#scheduled = false;\n\t\t\tvoid this.#drain();\n\t\t});\n\t}\n\n\tasync #drain(): Promise<void> {\n\t\tif (this.#running || this.#end !== undefined || !this.#started) return;\n\t\tthis.#running = true;\n\t\ttry {\n\t\t\twhile (this.#end === undefined) {\n\t\t\t\tconst frame = this.#pending.shift();\n\t\t\t\tif (frame === undefined) break;\n\t\t\t\tthis.#value = frame.value;\n\t\t\t\tconst deliveryContext = withoutAbortSignal(frame.context);\n\t\t\t\ttry {\n\t\t\t\t\tawait this.#listener!(frame.value, frame.ops, deliveryContext);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (this.#end === undefined) {\n\t\t\t\t\t\tthis.#report(error);\n\t\t\t\t\t\tthis.#terminate({ reason: \"listener_error\", error: toError(error) });\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (frame.value === null) {\n\t\t\t\t\tthis.#terminate({ reason: \"retired\" });\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.#running = false;\n\t\t\tif (this.#end === undefined && this.#pending.length > 0) this.#schedule();\n\t\t}\n\t}\n\n\t/** End the watch, once: detach, drop pending frames, and settle `closed`. A callback already running keeps running. */\n\t#terminate(end: WatchEnd): void {\n\t\tif (this.#end !== undefined) return;\n\t\tthis.#end = end;\n\t\tthis.#detach();\n\t\tthis.#pending.length = 0;\n\t\tif (this.#cancellationListener !== undefined) {\n\t\t\tthis.#cancellationSignal?.removeEventListener(\"abort\", this.#cancellationListener);\n\t\t}\n\t\tthis.#closed.resolve(end);\n\t}\n}\n\nfunction toError(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(errorMessage(error));\n}\n"]}
|