@astrosheep/keiyaku 4.6.8 → 4.6.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -14
- package/build/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/build/plugins/claude/skills/keiyaku/SKILL.md +5 -6
- package/build/plugins/claude/skills/keiyaku-akuma/SKILL.md +1 -1
- package/build/plugins/claude/skills/keiyaku-akuma/references/automation.md +8 -8
- package/build/plugins/claude/skills/keiyaku-babysit/SKILL.md +1 -1
- package/build/plugins/claude/skills/keiyaku-bind/SKILL.md +9 -9
- package/build/plugins/claude/skills/keiyaku-debt/SKILL.md +91 -0
- package/build/plugins/claude/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/plugins/codex/.codex-plugin/plugin.json +1 -1
- package/build/plugins/codex/skills/keiyaku/SKILL.md +5 -6
- package/build/plugins/codex/skills/keiyaku-akuma/SKILL.md +1 -1
- package/build/plugins/codex/skills/keiyaku-akuma/references/automation.md +8 -8
- package/build/plugins/codex/skills/keiyaku-babysit/SKILL.md +1 -1
- package/build/plugins/codex/skills/keiyaku-bind/SKILL.md +9 -9
- package/build/plugins/codex/skills/keiyaku-debt/SKILL.md +91 -0
- package/build/plugins/codex/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/plugins/opencode/index.js +1 -1
- package/build/plugins/opencode/skills/keiyaku/SKILL.md +5 -6
- package/build/plugins/opencode/skills/keiyaku-akuma/SKILL.md +1 -1
- package/build/plugins/opencode/skills/keiyaku-akuma/references/automation.md +8 -8
- package/build/plugins/opencode/skills/keiyaku-babysit/SKILL.md +1 -1
- package/build/plugins/opencode/skills/keiyaku-bind/SKILL.md +9 -9
- package/build/plugins/opencode/skills/keiyaku-debt/SKILL.md +91 -0
- package/build/plugins/opencode/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/skills/keiyaku/SKILL.md +5 -6
- package/build/skills/keiyaku-akuma/SKILL.md +1 -1
- package/build/skills/keiyaku-akuma/references/automation.md +8 -8
- package/build/skills/keiyaku-babysit/SKILL.md +1 -1
- package/build/skills/keiyaku-bind/SKILL.md +9 -9
- package/build/skills/keiyaku-debt/SKILL.md +91 -0
- package/build/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/src/akuma/akuma-instance.d.ts +2 -0
- package/build/src/akuma/akuma-instance.js +10 -0
- package/build/src/akuma/akuma-observe.d.ts +33 -8
- package/build/src/akuma/akuma-observe.js +88 -64
- package/build/src/akuma/akuma-owner.d.ts +11 -2
- package/build/src/akuma/akuma-owner.js +45 -35
- package/build/src/akuma/akuma-selection-execution.js +9 -1
- package/build/src/akuma/akuma-stream.d.ts +22 -0
- package/build/src/akuma/akuma-stream.js +116 -0
- package/build/src/akuma/akuma-wait.d.ts +1 -40
- package/build/src/akuma/akuma-wait.js +23 -84
- package/build/src/akuma/akuma.d.ts +17 -11
- package/build/src/akuma/akuma.js +2 -0
- package/build/src/akuma/allowed.d.ts +7 -12
- package/build/src/akuma/allowed.js +13 -4
- package/build/src/akuma/body-supervisor.d.ts +5 -5
- package/build/src/akuma/body-supervisor.js +22 -20
- package/build/src/akuma/body.js +28 -1
- package/build/src/akuma/call-request.d.ts +12 -22
- package/build/src/akuma/heart/activity-schema.d.ts +12 -0
- package/build/src/akuma/heart/activity-schema.js +6 -0
- package/build/src/akuma/heart/index.d.ts +59 -2
- package/build/src/akuma/heart/index.js +87 -8
- package/build/src/akuma/heart/rows.js +5 -3
- package/build/src/akuma/heart/soul.d.ts +9 -0
- package/build/src/akuma/heart/soul.js +29 -0
- package/build/src/akuma/heart/storage.d.ts +15 -0
- package/build/src/akuma/heart/storage.js +55 -0
- package/build/src/akuma/heart/timeline.d.ts +7 -0
- package/build/src/akuma/heart/timeline.js +10 -0
- package/build/src/akuma/index.d.ts +1 -0
- package/build/src/akuma/projection.d.ts +25 -0
- package/build/src/akuma/projection.js +24 -7
- package/build/src/akuma/provider-recipe.d.ts +11 -0
- package/build/src/akuma/provider-recipe.js +23 -0
- package/build/src/akuma/provider.d.ts +25 -0
- package/build/src/akuma/provider.js +99 -7
- package/build/src/akuma/providers/acp/events.js +25 -2
- package/build/src/akuma/providers/claude/events.js +76 -10
- package/build/src/akuma/providers/claude/index.js +2 -5
- package/build/src/akuma/providers/codex-app-server/events.js +17 -2
- package/build/src/akuma/providers/codex-app-server/index.js +15 -9
- package/build/src/akuma/providers/decode.d.ts +8 -0
- package/build/src/akuma/providers/decode.js +21 -0
- package/build/src/akuma/providers/grok-build/index.js +10 -26
- package/build/src/akuma/providers/opencode-sdk/event-stream.d.ts +3 -3
- package/build/src/akuma/providers/opencode-sdk/event-stream.js +2 -25
- package/build/src/akuma/providers/opencode-sdk/events.d.ts +7 -43
- package/build/src/akuma/providers/opencode-sdk/events.js +147 -284
- package/build/src/akuma/providers/opencode-sdk/index.js +267 -421
- package/build/src/akuma/providers/opencode-sdk/native-http.d.ts +9 -0
- package/build/src/akuma/providers/opencode-sdk/native-http.js +69 -0
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +42 -36
- package/build/src/akuma/providers/opencode-sdk/session.js +75 -82
- package/build/src/akuma/providers/paseo/events.d.ts +8 -0
- package/build/src/akuma/providers/paseo/events.js +58 -11
- package/build/src/akuma/providers/paseo/index.js +11 -7
- package/build/src/akuma/providers/pi/events.d.ts +2 -0
- package/build/src/akuma/providers/pi/events.js +32 -24
- package/build/src/akuma/providers/pi/index.js +21 -35
- package/build/src/akuma/request-lifecycle.d.ts +1 -2
- package/build/src/akuma/request-lifecycle.js +2 -8
- package/build/src/akuma/request-rendezvous.js +38 -55
- package/build/src/akuma/request-serve.d.ts +1 -1
- package/build/src/akuma/request-serve.js +77 -113
- package/build/src/akuma/selection-observation.d.ts +57 -51
- package/build/src/akuma/selection-observation.js +3 -3
- package/build/src/akuma/turn-drive.d.ts +3 -0
- package/build/src/akuma/turn-drive.js +26 -5
- package/build/src/akuma-body.js +12 -22
- package/build/src/cli/akuma-caller.js +10 -0
- package/build/src/cli/commands/akuma-grammar.js +3 -4
- package/build/src/cli/commands/akuma.js +13 -51
- package/build/src/cli/commands/contract-grammar.d.ts +7 -6
- package/build/src/cli/commands/contract-grammar.js +27 -32
- package/build/src/cli/commands/contract-help.d.ts +16 -7
- package/build/src/cli/commands/contract-help.js +20 -11
- package/build/src/cli/commands/contract.js +11 -11
- package/build/src/cli/commands/debt-grammar.d.ts +19 -0
- package/build/src/cli/commands/debt-grammar.js +323 -0
- package/build/src/cli/commands/debt-query.d.ts +5 -0
- package/build/src/cli/commands/{task-query.js → debt-query.js} +9 -9
- package/build/src/cli/commands/{task.d.ts → debt.d.ts} +2 -2
- package/build/src/cli/commands/{task.js → debt.js} +83 -143
- package/build/src/cli/coordinates.d.ts +1 -1
- package/build/src/cli/coordinates.js +1 -1
- package/build/src/cli/parse.d.ts +4 -4
- package/build/src/cli/parse.js +17 -16
- package/build/src/cli/render/akuma-activity.d.ts +11 -83
- package/build/src/cli/render/akuma-activity.js +20 -382
- package/build/src/cli/render/catalog.d.ts +2 -2
- package/build/src/cli/render/catalog.js +5 -5
- package/build/src/cli/render/contract.js +2 -2
- package/build/src/cli/render/debt.d.ts +28 -0
- package/build/src/cli/render/{task.js → debt.js} +51 -112
- package/build/src/cli/render/kanshi.js +28 -28
- package/build/src/cli/render/marks.d.ts +5 -5
- package/build/src/cli/render/marks.js +4 -10
- package/build/src/cli/render/nuke.js +1 -1
- package/build/src/cli/runtime.js +3 -3
- package/build/src/cli/scan.d.ts +1 -1
- package/build/src/cli/usage.d.ts +1 -1
- package/build/src/cli/usage.js +4 -4
- package/build/src/contract-worktree.js +3 -3
- package/build/src/debt/board.d.ts +160 -0
- package/build/src/{task → debt}/board.js +89 -89
- package/build/src/debt/catalog.d.ts +11 -0
- package/build/src/debt/catalog.js +59 -0
- package/build/src/{task → debt}/context.d.ts +1 -1
- package/build/src/{task → debt}/context.js +1 -1
- package/build/src/{task → debt}/created-observation.d.ts +6 -10
- package/build/src/{task → debt}/created-observation.js +7 -7
- package/build/src/debt/document.d.ts +37 -0
- package/build/src/{task → debt}/document.js +37 -37
- package/build/src/debt/identity.d.ts +21 -0
- package/build/src/{task → debt}/identity.js +35 -35
- package/build/src/debt/index.d.ts +111 -0
- package/build/src/debt/index.js +203 -0
- package/build/src/{task → debt}/input.d.ts +8 -8
- package/build/src/{task → debt}/input.js +21 -21
- package/build/src/debt/lifecycle-operations.d.ts +6 -0
- package/build/src/{task → debt}/lifecycle-operations.js +27 -31
- package/build/src/debt/mutation-result.d.ts +981 -0
- package/build/src/debt/mutation-result.js +109 -0
- package/build/src/debt/mutation.d.ts +424 -0
- package/build/src/debt/mutation.js +223 -0
- package/build/src/debt/operation-types.d.ts +71 -0
- package/build/src/debt/operations.d.ts +28 -0
- package/build/src/{task → debt}/operations.js +59 -60
- package/build/src/debt/query.d.ts +76 -0
- package/build/src/{task → debt}/query.js +55 -55
- package/build/src/{task → debt}/store.d.ts +13 -13
- package/build/src/{task → debt}/store.js +58 -49
- package/build/src/debt/view.d.ts +4 -0
- package/build/src/debt/view.js +7 -0
- package/build/src/identity/coordinates.d.ts +1 -1
- package/build/src/index.d.ts +13 -13
- package/build/src/index.js +9 -9
- package/build/src/kanshi/index.d.ts +1 -1
- package/build/src/kanshi/read.js +33 -33
- package/build/src/kanshi/report.d.ts +7 -7
- package/build/src/kanshi/select.js +4 -4
- package/build/src/library/akumas.d.ts +2 -3
- package/build/src/library/bind.d.ts +3 -3
- package/build/src/library/bind.js +5 -5
- package/build/src/library/contract-creation.js +5 -5
- package/build/src/library/contract-execution.js +4 -4
- package/build/src/library/contract-types.d.ts +2 -2
- package/build/src/library/input.d.ts +2 -2
- package/build/src/library/input.js +5 -5
- package/build/src/library/invocation.js +2 -2
- package/build/src/library/nuke.js +3 -3
- package/build/src/library/outcome.d.ts +126 -126
- package/build/src/library/outcome.js +3 -3
- package/build/src/library/selection.d.ts +1 -4
- package/build/src/library/selection.js +11 -62
- package/build/src/plugin/public.d.ts +5 -0
- package/build/src/plugin/runtime.js +3 -1
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/build/src/settlement/fence.d.ts +3 -3
- package/build/src/settlement/fence.js +4 -4
- package/build/src/settlement/holder.d.ts +16 -16
- package/build/src/settlement/holder.js +69 -63
- package/build/src/settlement/settle.d.ts +5 -5
- package/build/src/settlement/settle.js +53 -53
- package/package.json +12 -6
- package/plugins/paseo/plugin/index.server.ts +17 -0
- package/plugins/paseo/plugin/paseo-plugin.json +4 -0
- package/plugins/paseo/plugin/server/attach.ts +52 -0
- package/plugins/paseo/plugin/server/keiyaku.ts +44 -0
- package/plugins/paseo/plugin/server/message.ts +60 -0
- package/plugins/paseo/plugin/server/mirror.ts +193 -0
- package/plugins/paseo/plugin/server/model.ts +14 -0
- package/plugins/paseo/plugin/server/provider.ts +276 -0
- package/plugins/paseo/plugin/server/sdk-worker.ts +237 -0
- package/plugins/paseo/plugin/server/sdk.ts +289 -0
- package/plugins/paseo/plugin/server/stop.ts +26 -0
- package/plugins/paseo/plugin/server/transport.ts +35 -0
- package/plugins/paseo/plugin/shared/attach-rpc.ts +10 -0
- package/plugins/paseo/plugin/shared/refresh-rpc.ts +6 -0
- package/plugins/paseo/plugin/tsconfig.json +6 -0
- package/skills/keiyaku/SKILL.md +5 -6
- package/skills/keiyaku-akuma/SKILL.md +1 -1
- package/skills/keiyaku-akuma/references/automation.md +8 -8
- package/skills/keiyaku-babysit/SKILL.md +1 -1
- package/skills/keiyaku-bind/SKILL.md +9 -9
- package/skills/keiyaku-debt/SKILL.md +91 -0
- package/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/plugins/claude/skills/keiyaku-task/SKILL.md +0 -104
- package/build/plugins/codex/skills/keiyaku-task/SKILL.md +0 -104
- package/build/plugins/opencode/skills/keiyaku-task/SKILL.md +0 -104
- package/build/skills/keiyaku-task/SKILL.md +0 -104
- package/build/src/cli/commands/task-grammar.d.ts +0 -19
- package/build/src/cli/commands/task-grammar.js +0 -384
- package/build/src/cli/commands/task-query.d.ts +0 -5
- package/build/src/cli/render/task.d.ts +0 -39
- package/build/src/task/board.d.ts +0 -168
- package/build/src/task/catalog.d.ts +0 -11
- package/build/src/task/catalog.js +0 -59
- package/build/src/task/compose-language.d.ts +0 -57
- package/build/src/task/compose-language.js +0 -364
- package/build/src/task/compose-parser.d.ts +0 -32
- package/build/src/task/compose-parser.js +0 -180
- package/build/src/task/compose.d.ts +0 -16
- package/build/src/task/compose.js +0 -189
- package/build/src/task/document.d.ts +0 -39
- package/build/src/task/identity.d.ts +0 -21
- package/build/src/task/index.d.ts +0 -138
- package/build/src/task/index.js +0 -269
- package/build/src/task/lifecycle-operations.d.ts +0 -6
- package/build/src/task/mutation-result.d.ts +0 -1726
- package/build/src/task/mutation-result.js +0 -198
- package/build/src/task/mutation.d.ts +0 -590
- package/build/src/task/mutation.js +0 -262
- package/build/src/task/operation-types.d.ts +0 -71
- package/build/src/task/operations.d.ts +0 -28
- package/build/src/task/query.d.ts +0 -76
- package/build/src/task/view.d.ts +0 -4
- package/build/src/task/view.js +0 -7
- package/skills/keiyaku-task/SKILL.md +0 -104
- /package/build/src/{task → debt}/operation-types.js +0 -0
|
@@ -33,7 +33,7 @@ to create parallel work.
|
|
|
33
33
|
|
|
34
34
|
- Separate `kei`s have independently acceptable outcomes.
|
|
35
35
|
- An Arc is a chapter of one `kei`; it is not separately accepted.
|
|
36
|
-
- A
|
|
36
|
+
- A Debt records confirmed unresolved work and its dependencies.
|
|
37
37
|
|
|
38
38
|
Use `after` only when one `kei` requires another to be accepted first. Ordinary
|
|
39
39
|
overlap is not a dependency.
|
|
@@ -101,7 +101,7 @@ authority.
|
|
|
101
101
|
| Role | Grant at birth | Return |
|
|
102
102
|
| --- | --- | --- |
|
|
103
103
|
| Holder | The actions the delegated loop will perform; include `contract.review` when this holder will review. Commission with the `kei`, current Arc when one exists, appointed worktree, and holder duties. | Acceptance or abandonment, with receipts. |
|
|
104
|
-
| Deliverer | The ordinary baseline: every
|
|
104
|
+
| Deliverer | The ordinary baseline: every Debt mutation, Contract audit and delivery, and Akuma management. `keiyaku -C <repo> call worker --alias @deliverer --contract <kei/...> --workdir <appointed-path> -` | The delivery receipt. |
|
|
105
105
|
| Reviewer | `--allowed contract.review`: `keiyaku -C <repo> call review-akuma --alias @reviewer --contract <kei/...> --workdir <appointed-path> --allowed contract.review -` | The verdict receipt. Without the grant, `not-allowed` refuses and no verdict is recorded. |
|
|
106
106
|
|
|
107
107
|
An Archetype's explicit allowed set replaces the ordinary baseline; check
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AkumaCaller } from "./caller.js";
|
|
2
2
|
import type { Settings } from "../settings.js";
|
|
3
3
|
import type { WorldRoot } from "../world.js";
|
|
4
|
+
import type { AkumaStreamSnapshot } from "./akuma-stream.js";
|
|
4
5
|
import { type InterruptReceipt } from "./akuma-owner.js";
|
|
5
6
|
import { type AkumaStatus } from "./akuma.js";
|
|
6
7
|
import type { AllowedAction } from "./allowed.js";
|
|
@@ -66,5 +67,6 @@ export declare class Akuma {
|
|
|
66
67
|
status(): Promise<AkumaStatus>;
|
|
67
68
|
idle(options?: AkumaIdleOptions): Promise<AkumaIdleResult>;
|
|
68
69
|
history(options?: AkumaHistoryOptions): Promise<ActivityHistory>;
|
|
70
|
+
stream(options?: AkumaSignalOptions): AsyncIterable<AkumaStreamSnapshot>;
|
|
69
71
|
kill(options?: AkumaSignalOptions): Promise<KillEvidence>;
|
|
70
72
|
}
|
|
@@ -151,6 +151,16 @@ export class Akuma {
|
|
|
151
151
|
...(options.limit === undefined ? {} : { limit: options.limit }),
|
|
152
152
|
}));
|
|
153
153
|
}
|
|
154
|
+
stream(options = {}) {
|
|
155
|
+
if (typeof options !== "object" || options === null || Array.isArray(options)) {
|
|
156
|
+
throw new TypeError("Akuma stream options must be an object");
|
|
157
|
+
}
|
|
158
|
+
const unknown = Object.keys(options).find((key) => key !== "signal");
|
|
159
|
+
if (unknown !== undefined)
|
|
160
|
+
throw new TypeError(`Akuma stream options has unknown field: ${unknown}`);
|
|
161
|
+
const signal = signalOption(options.signal);
|
|
162
|
+
return this.owner(true).stream(signal === undefined ? {} : { signal });
|
|
163
|
+
}
|
|
154
164
|
async kill(options = {}) {
|
|
155
165
|
if (typeof options !== "object" || options === null || Array.isArray(options)) {
|
|
156
166
|
throw new TypeError("Akuma kill options must be an object");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type AkuId, type AkumaPaths } from "./identity.js";
|
|
2
|
-
import { selectHistory,
|
|
2
|
+
import { selectHistory, type ActivityHistory, type ActivityRow, type ActivitySnapshot } from "./projection.js";
|
|
3
3
|
import type { WorldRoot } from "../world.js";
|
|
4
4
|
import type { AkumaAlias } from "../identity/selector.js";
|
|
5
5
|
import type { AkumaListRow, AkumaStatus, UnbornAkumaListRow } from "./akuma.js";
|
|
@@ -25,23 +25,47 @@ type StatusObservationInput = Readonly<{
|
|
|
25
25
|
ordinaryBudget?: number;
|
|
26
26
|
admittedTellId?: string;
|
|
27
27
|
}>;
|
|
28
|
-
type StatusProjection = Readonly<{
|
|
29
|
-
ledger: TurnLedger;
|
|
30
|
-
selected: ReturnType<typeof selectSnapshot>;
|
|
31
|
-
}>;
|
|
32
28
|
/** Private to a live wait: retain only this member's current frontier and last selection. */
|
|
33
29
|
export declare function createLiveStatusReader(paths: AkumaPaths, expected: AkuId): {
|
|
34
30
|
clear: () => void;
|
|
31
|
+
execution(signal?: AbortSignal): Promise<import("./heart/facts.js").AkumaLife>;
|
|
32
|
+
tellOutcome: (id: string, signal?: AbortSignal) => Promise<{
|
|
33
|
+
tell: Readonly<{
|
|
34
|
+
kind: "tell";
|
|
35
|
+
sequence: number;
|
|
36
|
+
id: string;
|
|
37
|
+
body: string;
|
|
38
|
+
initiator?: string;
|
|
39
|
+
schemaJson?: string;
|
|
40
|
+
recordedAt: string;
|
|
41
|
+
state: "pending" | "told";
|
|
42
|
+
deliveries: readonly import("./heart/facts.js").TellDelivery[];
|
|
43
|
+
binding?: import("./heart/facts.js").TellBinding;
|
|
44
|
+
}> | null;
|
|
45
|
+
end: Readonly<{
|
|
46
|
+
kind: "turn-end";
|
|
47
|
+
sequence: number;
|
|
48
|
+
turnSequence: number;
|
|
49
|
+
outcome: import("./heart/facts.js").TurnOutcome;
|
|
50
|
+
completedAt: string;
|
|
51
|
+
}> | undefined;
|
|
52
|
+
}>;
|
|
53
|
+
complete(signal?: AbortSignal): Promise<boolean>;
|
|
35
54
|
read(input: StatusObservationInput, signal?: AbortSignal): Promise<LiveStatusObservation>;
|
|
36
55
|
};
|
|
37
|
-
/**
|
|
38
|
-
export declare function bornLiveStatus(paths: AkumaPaths, expected: AkuId, input: StatusObservationInput, signal?: AbortSignal
|
|
56
|
+
/** One-shot observations use the same reader and always release it. */
|
|
57
|
+
export declare function bornLiveStatus(paths: AkumaPaths, expected: AkuId, input: StatusObservationInput, signal?: AbortSignal): Promise<LiveStatusObservation>;
|
|
39
58
|
export declare function bornStatus(paths: AkumaPaths, expected: AkuId, input: StatusObservationInput): Promise<BudgetedStatusObservation>;
|
|
40
59
|
export declare function readLiveStatus(worldPath: WorldRoot, id: AkuId, input: StatusObservationInput, signal?: AbortSignal): Promise<LiveStatusObservation>;
|
|
60
|
+
export type ExecutionProgress = "settled" | "advancing" | "stopped";
|
|
61
|
+
/** Pending input is not execution. An owned launch can bridge the admission gap. */
|
|
62
|
+
export declare function executionProgress(life: AkumaStatus["life"], pending: boolean, wake?: "launching" | "settled" | "failed"): ExecutionProgress;
|
|
41
63
|
export declare function defaultWaitComplete(status: AkumaStatus): boolean;
|
|
42
64
|
/** Probe completion only; returned statuses still come from a full observation. */
|
|
43
|
-
export declare function readWaitComplete(worldPath: WorldRoot, ids: readonly AkuId[], completion: "any" | "all", signal?: AbortSignal): Promise<boolean>;
|
|
65
|
+
export declare function readWaitComplete(worldPath: WorldRoot, ids: readonly AkuId[], completion: "any" | "all", signal?: AbortSignal, probe?: (id: AkuId) => Promise<boolean>): Promise<boolean>;
|
|
44
66
|
export type WaitReason = "completed" | "deadline";
|
|
67
|
+
/** The one observation cadence public waiting and timeline streaming share. */
|
|
68
|
+
export declare const OBSERVATION_POLL_MS = 100;
|
|
45
69
|
/**
|
|
46
70
|
* The one deadline-aware observation loop for public Akuma waiting. It always
|
|
47
71
|
* reads once before judging a passed deadline, so a zero-duration wait remains
|
|
@@ -49,6 +73,7 @@ export type WaitReason = "completed" | "deadline";
|
|
|
49
73
|
*/
|
|
50
74
|
export declare function waitForObservation<T>(input: Readonly<{
|
|
51
75
|
timeoutMs?: number;
|
|
76
|
+
pollMs?: number;
|
|
52
77
|
signal?: AbortSignal;
|
|
53
78
|
probe?(): Promise<boolean>;
|
|
54
79
|
observe(): Promise<T>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { projectAkumaBirth } from "./caller.js";
|
|
2
|
-
import {
|
|
2
|
+
import { createStatusFactReader, readLifeSnapshot, HeldAkumaLeash, isHeartAbsent, life, lifeAt, probeLeash, readHeart, readSeal, readSoul, } from "./heart/index.js";
|
|
3
3
|
import { pathsForAkuId } from "./identity.js";
|
|
4
4
|
import { ordinarySnapshotBudget, projectTurns, selectHistory, selectSnapshot, } from "./projection.js";
|
|
5
5
|
import { resolveProviderExecution } from "./providers/index.js";
|
|
@@ -89,60 +89,75 @@ export function createLiveStatusReader(paths, expected) {
|
|
|
89
89
|
};
|
|
90
90
|
return {
|
|
91
91
|
clear,
|
|
92
|
-
async
|
|
92
|
+
async execution(signal) {
|
|
93
|
+
return (await bornObservation(paths, expected, () => reader.life(signal))).currentLife;
|
|
94
|
+
},
|
|
95
|
+
tellOutcome: reader.tellOutcome,
|
|
96
|
+
async complete(signal) {
|
|
93
97
|
try {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const ledger = memo?.facts === facts ? memo.ledger : projectTurns(facts);
|
|
97
|
-
const options = snapshotSelection(input);
|
|
98
|
-
const selected = memo?.ledger === ledger &&
|
|
99
|
-
memo.options.aperture === options.aperture &&
|
|
100
|
-
memo.options.admittedTellId === options.admittedTellId &&
|
|
101
|
-
memo.options.budget.tail === options.budget.tail &&
|
|
102
|
-
memo.options.budget.voice === options.budget.voice
|
|
103
|
-
? memo.selected
|
|
104
|
-
: selectSnapshot(ledger, options);
|
|
105
|
-
memo = { facts, ledger, options, selected };
|
|
106
|
-
return { ledger, selected };
|
|
107
|
-
});
|
|
98
|
+
const observed = await bornObservation(paths, expected, () => reader.life(signal));
|
|
99
|
+
return complete(observed.currentLife, observed.snapshot.hasPendingTell);
|
|
108
100
|
}
|
|
109
101
|
catch (error) {
|
|
110
102
|
clear();
|
|
111
103
|
throw error;
|
|
112
104
|
}
|
|
113
105
|
},
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
106
|
+
async read(input, signal) {
|
|
107
|
+
try {
|
|
108
|
+
if (input.ordinaryBudget !== undefined &&
|
|
109
|
+
(!Number.isSafeInteger(input.ordinaryBudget) || input.ordinaryBudget < 0))
|
|
110
|
+
throw new TypeError("ordinary budget must be a nonnegative safe integer");
|
|
111
|
+
const { snapshot, soul, currentLife } = await bornObservation(paths, expected, () => reader.life(signal));
|
|
112
|
+
const resumeUnsupported = currentLife === "stranded" &&
|
|
113
|
+
snapshot.latestSession?.provider === soul.provider.name &&
|
|
114
|
+
(await resolveProviderExecution(soul.provider)).adapter.resume === undefined;
|
|
115
|
+
const facts = await reader.read(input, signal);
|
|
116
|
+
const ledger = memo?.facts === facts ? memo.ledger : projectTurns(facts);
|
|
117
|
+
const options = snapshotSelection(input);
|
|
118
|
+
const selected = memo?.ledger === ledger &&
|
|
119
|
+
memo.options.aperture === options.aperture &&
|
|
120
|
+
memo.options.admittedTellId === options.admittedTellId &&
|
|
121
|
+
memo.options.budget.tail === options.budget.tail &&
|
|
122
|
+
memo.options.budget.voice === options.budget.voice
|
|
123
|
+
? memo.selected
|
|
124
|
+
: selectSnapshot(ledger, options);
|
|
125
|
+
memo = { facts, ledger, options, selected };
|
|
126
|
+
return {
|
|
127
|
+
status: {
|
|
128
|
+
id: soul.id,
|
|
129
|
+
birth: projectAkumaBirth(soul),
|
|
130
|
+
life: currentLife,
|
|
131
|
+
cwd: soul.cwd,
|
|
132
|
+
// The execution adapter and its one current model are what this Akuma
|
|
133
|
+
// actually runs; a birth request the Soul still only seeded is not a
|
|
134
|
+
// claim that a native runtime ever used it.
|
|
135
|
+
provider: soul.provider.name,
|
|
136
|
+
...(soul.options.model === undefined ? {} : { model: soul.options.model }),
|
|
137
|
+
allowed: soul.allowed,
|
|
138
|
+
...(resumeUnsupported ? { strandedReason: "resume-unsupported" } : {}),
|
|
139
|
+
timeline: selected.snapshot,
|
|
140
|
+
},
|
|
141
|
+
ordinarySelected: selected.ordinaryCount,
|
|
142
|
+
rows: ledger.rows,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
clear();
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
134
149
|
},
|
|
135
|
-
ordinarySelected: selected.ordinaryCount,
|
|
136
|
-
rows: ledger.rows,
|
|
137
150
|
};
|
|
138
151
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
152
|
+
/** One-shot observations use the same reader and always release it. */
|
|
153
|
+
export async function bornLiveStatus(paths, expected, input, signal) {
|
|
154
|
+
const reader = createLiveStatusReader(paths, expected);
|
|
155
|
+
try {
|
|
156
|
+
return await reader.read(input, signal);
|
|
157
|
+
}
|
|
158
|
+
finally {
|
|
159
|
+
reader.clear();
|
|
160
|
+
}
|
|
146
161
|
}
|
|
147
162
|
export async function bornStatus(paths, expected, input) {
|
|
148
163
|
const { rows: _rows, ...status } = await bornLiveStatus(paths, expected, input);
|
|
@@ -151,21 +166,33 @@ export async function bornStatus(paths, expected, input) {
|
|
|
151
166
|
export async function readLiveStatus(worldPath, id, input, signal) {
|
|
152
167
|
return await bornLiveStatus(pathsForAkuId(worldPath, id), id, input, signal);
|
|
153
168
|
}
|
|
169
|
+
/** Pending input is not execution. An owned launch can bridge the admission gap. */
|
|
170
|
+
export function executionProgress(life, pending, wake = "settled") {
|
|
171
|
+
if (wake === "launching" || life === "running")
|
|
172
|
+
return "advancing";
|
|
173
|
+
if (wake === "failed")
|
|
174
|
+
return "stopped";
|
|
175
|
+
if (life === "asleep")
|
|
176
|
+
return pending ? "advancing" : "settled";
|
|
177
|
+
return "stopped";
|
|
178
|
+
}
|
|
154
179
|
function complete(life, pending) {
|
|
155
|
-
return life !== "
|
|
180
|
+
return executionProgress(life, pending) !== "advancing";
|
|
156
181
|
}
|
|
157
182
|
export function defaultWaitComplete(status) {
|
|
158
183
|
return complete(status.life, status.timeline.entries.some((entry) => entry.kind === "row" && entry.row.kind === "tell" && entry.row.state === "pending"));
|
|
159
184
|
}
|
|
160
185
|
/** Probe completion only; returned statuses still come from a full observation. */
|
|
161
|
-
export async function readWaitComplete(worldPath, ids, completion, signal) {
|
|
186
|
+
export async function readWaitComplete(worldPath, ids, completion, signal, probe) {
|
|
162
187
|
let completed = 0;
|
|
163
188
|
for (const id of ids) {
|
|
164
189
|
signal?.throwIfAborted();
|
|
165
190
|
try {
|
|
166
191
|
const paths = pathsForAkuId(worldPath, id);
|
|
167
|
-
const
|
|
168
|
-
|
|
192
|
+
const ready = probe === undefined
|
|
193
|
+
? await bornObservation(paths, id, () => readLifeSnapshot(paths, signal)).then((observed) => complete(observed.currentLife, observed.snapshot.hasPendingTell))
|
|
194
|
+
: await probe(id);
|
|
195
|
+
if (ready) {
|
|
169
196
|
if (completion === "any")
|
|
170
197
|
return true;
|
|
171
198
|
completed += 1;
|
|
@@ -178,7 +205,8 @@ export async function readWaitComplete(worldPath, ids, completion, signal) {
|
|
|
178
205
|
}
|
|
179
206
|
return ids.length > 0 && completed === ids.length;
|
|
180
207
|
}
|
|
181
|
-
|
|
208
|
+
/** The one observation cadence public waiting and timeline streaming share. */
|
|
209
|
+
export const OBSERVATION_POLL_MS = 100;
|
|
182
210
|
/**
|
|
183
211
|
* The one deadline-aware observation loop for public Akuma waiting. It always
|
|
184
212
|
* reads once before judging a passed deadline, so a zero-duration wait remains
|
|
@@ -190,22 +218,18 @@ export async function waitForObservation(input) {
|
|
|
190
218
|
input.signal?.throwIfAborted();
|
|
191
219
|
const ready = input.probe === undefined || (await input.probe());
|
|
192
220
|
input.signal?.throwIfAborted();
|
|
193
|
-
if (
|
|
194
|
-
await
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
221
|
+
if (ready || (deadline !== undefined && performance.now() >= deadline)) {
|
|
222
|
+
const value = await input.observe();
|
|
223
|
+
input.signal?.throwIfAborted();
|
|
224
|
+
await input.onObserve?.(value);
|
|
225
|
+
if (input.complete(value))
|
|
226
|
+
return { reason: "completed", value };
|
|
227
|
+
if (deadline !== undefined && performance.now() >= deadline)
|
|
228
|
+
return { reason: "deadline", value };
|
|
198
229
|
}
|
|
199
|
-
const value = await input.observe();
|
|
200
|
-
input.signal?.throwIfAborted();
|
|
201
|
-
await input.onObserve?.(value);
|
|
202
|
-
if (input.complete(value))
|
|
203
|
-
return { reason: "completed", value };
|
|
204
|
-
if (deadline !== undefined && performance.now() >= deadline)
|
|
205
|
-
return { reason: "deadline", value };
|
|
206
230
|
await abortableDelay(deadline === undefined
|
|
207
|
-
? OBSERVATION_POLL_MS
|
|
208
|
-
: Math.min(OBSERVATION_POLL_MS, Math.max(0, deadline - performance.now())), input.signal);
|
|
231
|
+
? (input.pollMs ?? OBSERVATION_POLL_MS)
|
|
232
|
+
: Math.min(input.pollMs ?? OBSERVATION_POLL_MS, Math.max(0, deadline - performance.now())), input.signal);
|
|
209
233
|
}
|
|
210
234
|
}
|
|
211
235
|
export async function readAkumaBirthCwd(worldPath, id) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type AkumaCaller } from "./caller.js";
|
|
2
2
|
import type { WorldRoot } from "../world.js";
|
|
3
3
|
import { type OutcomeObserver, type LiveStatusObservation, type WaitReason } from "./akuma-observe.js";
|
|
4
|
+
import { type AkumaStreamSnapshot } from "./akuma-stream.js";
|
|
4
5
|
import type { AkumaStatus } from "./akuma.js";
|
|
5
6
|
import { type TellResult, type TellWakeRuntime } from "./body.js";
|
|
6
7
|
import { type CallInitialTell, type CallInitialTellAdmission } from "./call-initial-tell.js";
|
|
@@ -64,7 +65,7 @@ export declare function killAkumaWithRecovery(paths: AkumaPaths, recover?: (path
|
|
|
64
65
|
* The one lower native Akuma owner: standalone identity, plural selection and
|
|
65
66
|
* the request service all consume these same single-target algorithms. It reads
|
|
66
67
|
* only Heart, leash, provider and filesystem state; optional Alias, Dispatch,
|
|
67
|
-
*
|
|
68
|
+
* Debt and Contract associations are composed above this boundary.
|
|
68
69
|
*/
|
|
69
70
|
export declare class AkumaOwner {
|
|
70
71
|
readonly id: AkuId;
|
|
@@ -81,6 +82,14 @@ export declare class AkumaOwner {
|
|
|
81
82
|
since?: number;
|
|
82
83
|
limit?: number;
|
|
83
84
|
}>): Promise<ActivityHistory | ExactHistory>;
|
|
85
|
+
/**
|
|
86
|
+
* Continuously observe that same retained timeline. Each emission is the whole
|
|
87
|
+
* latest bounded window through the existing history projection, and the
|
|
88
|
+
* operation observes until its caller stops pulling or aborts.
|
|
89
|
+
*/
|
|
90
|
+
stream(options?: Readonly<{
|
|
91
|
+
signal?: AbortSignal;
|
|
92
|
+
}>): AsyncIterable<AkumaStreamSnapshot>;
|
|
84
93
|
waitReceipt(predicate?: (status: AkumaStatus) => boolean, options?: Readonly<{
|
|
85
94
|
timeoutMs?: number;
|
|
86
95
|
signal?: AbortSignal;
|
|
@@ -122,12 +131,12 @@ export declare class AkumaOwner {
|
|
|
122
131
|
timeoutMs?: number;
|
|
123
132
|
signal?: AbortSignal;
|
|
124
133
|
observe?: (observation: LiveStatusObservation) => void | Promise<void>;
|
|
134
|
+
wake?: () => "launching" | "settled" | "failed";
|
|
125
135
|
}>): Promise<Readonly<{
|
|
126
136
|
reason: WaitReason;
|
|
127
137
|
outcome: TurnOutcome | null;
|
|
128
138
|
completedAt: string | null;
|
|
129
139
|
}>>;
|
|
130
|
-
private boundTellOutcome;
|
|
131
140
|
interrupt(body: string, options?: Readonly<{
|
|
132
141
|
tellId?: string;
|
|
133
142
|
schemaJson?: string;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { decodeAkumaCaller } from "./caller.js";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { AkumaNotBornError, AkumaProviderError } from "./akuma-errors.js";
|
|
4
|
-
import {
|
|
4
|
+
import { createLiveStatusReader, bornStatus, defaultWaitComplete, executionProgress, observeOutcomeRows, observeStatusOutcome, waitForObservation, } from "./akuma-observe.js";
|
|
5
5
|
import { executeWaitAkuma } from "./akuma-wait.js";
|
|
6
|
+
import { createAkumaStream } from "./akuma-stream.js";
|
|
6
7
|
import { handoffPendingTells, spawnAkumaBody, wakeRecordedTell, } from "./body.js";
|
|
7
8
|
import { admitCallInitialTell } from "./call-initial-tell.js";
|
|
8
9
|
import { acquireLeash } from "./control.js";
|
|
9
|
-
import { HeldAkumaLeash, activitySlice, projectTell, readForkPoint, readHeart, readKill, readLastAnsweredTurn, readSoul, readTell,
|
|
10
|
+
import { HeldAkumaLeash, activitySlice, projectTell, readForkPoint, readHeart, readKill, readLastAnsweredTurn, readSoul, readTell, recordTell, requestPause, requestStop, } from "./heart/index.js";
|
|
10
11
|
import { parsePublicHistoryId, pathsForAkuId } from "./identity.js";
|
|
11
12
|
import { projectTurns, selectExactHistory, selectHistory } from "./projection.js";
|
|
12
13
|
import { resolveProviderExecution } from "./providers/index.js";
|
|
@@ -84,7 +85,7 @@ export async function killAkumaWithRecovery(paths, recover, signal) {
|
|
|
84
85
|
* The one lower native Akuma owner: standalone identity, plural selection and
|
|
85
86
|
* the request service all consume these same single-target algorithms. It reads
|
|
86
87
|
* only Heart, leash, provider and filesystem state; optional Alias, Dispatch,
|
|
87
|
-
*
|
|
88
|
+
* Debt and Contract associations are composed above this boundary.
|
|
88
89
|
*/
|
|
89
90
|
export class AkumaOwner {
|
|
90
91
|
id;
|
|
@@ -146,6 +147,14 @@ export class AkumaOwner {
|
|
|
146
147
|
await observeOutcomeRows(this.id, history.rows, this.outcomeObserved);
|
|
147
148
|
return history;
|
|
148
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* Continuously observe that same retained timeline. Each emission is the whole
|
|
152
|
+
* latest bounded window through the existing history projection, and the
|
|
153
|
+
* operation observes until its caller stops pulling or aborts.
|
|
154
|
+
*/
|
|
155
|
+
stream(options = {}) {
|
|
156
|
+
return createAkumaStream(this.paths, this.id, options, this.outcomeObserved);
|
|
157
|
+
}
|
|
149
158
|
async waitReceipt(predicate = defaultWaitComplete, options = {}) {
|
|
150
159
|
if (options.timeoutMs !== undefined && (!Number.isFinite(options.timeoutMs) || options.timeoutMs < 0)) {
|
|
151
160
|
throw new TypeError("Akuma wait timeoutMs must be a nonnegative finite millisecond duration");
|
|
@@ -224,38 +233,39 @@ export class AkumaOwner {
|
|
|
224
233
|
}
|
|
225
234
|
/** Observe the exact admitted Tell's bound Turn without substituting Akuma-wide idleness. */
|
|
226
235
|
async tellOutcome(tellId, options = {}) {
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
236
|
+
const reader = createLiveStatusReader(this.paths, this.id);
|
|
237
|
+
try {
|
|
238
|
+
const waited = await waitForObservation({
|
|
239
|
+
...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),
|
|
240
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
241
|
+
observe: async () => {
|
|
242
|
+
const currentLife = await reader.execution(options.signal);
|
|
243
|
+
const progress = executionProgress(currentLife, true, options.wake?.());
|
|
244
|
+
const { tell, end } = await reader.tellOutcome(tellId, options.signal);
|
|
245
|
+
if (tell === null)
|
|
246
|
+
throw new AkumaProviderError(`recorded Tell ${tellId} is missing from Heart`);
|
|
247
|
+
if (end !== undefined)
|
|
248
|
+
await this.outcomeObserved?.(this.id, [`turn/${end.turnSequence}`]);
|
|
249
|
+
if (options.observe !== undefined) {
|
|
250
|
+
await options.observe(await reader.read({ aperture: "monitoring", admittedTellId: tellId }, options.signal));
|
|
251
|
+
}
|
|
252
|
+
return {
|
|
253
|
+
outcome: end?.outcome ?? null,
|
|
254
|
+
completedAt: end?.completedAt ?? null,
|
|
255
|
+
terminalWithoutTurn: (tell.state === "told" && tell.binding === undefined) || progress === "stopped",
|
|
256
|
+
};
|
|
257
|
+
},
|
|
258
|
+
complete: (observed) => observed.outcome !== null || observed.terminalWithoutTurn,
|
|
259
|
+
});
|
|
260
|
+
return {
|
|
261
|
+
reason: waited.reason,
|
|
262
|
+
outcome: waited.value.outcome,
|
|
263
|
+
completedAt: waited.value.completedAt,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
finally {
|
|
267
|
+
reader.clear();
|
|
268
|
+
}
|
|
259
269
|
}
|
|
260
270
|
async interrupt(body, options = {}) {
|
|
261
271
|
const admitted = await this.admitInterrupt(body, options);
|
|
@@ -68,9 +68,12 @@ export async function observeAdmittedAskAkuma(input) {
|
|
|
68
68
|
const tell = input.receipt ?? (await owner.admittedReceipt(input.tellId));
|
|
69
69
|
await input.onObserve?.admitted?.(tell, input.id);
|
|
70
70
|
let settled;
|
|
71
|
+
let wakeError;
|
|
72
|
+
let wakeState = input.wake === undefined ? "settled" : "launching";
|
|
71
73
|
void input.wake?.then((receipt) => {
|
|
72
74
|
settled = receipt;
|
|
73
|
-
|
|
75
|
+
wakeState = receipt.wake.kind === "failed" ? "failed" : "settled";
|
|
76
|
+
}, (error) => { wakeError = { error }; wakeState = "failed"; });
|
|
74
77
|
const admittedAt = Date.parse(tell.row.at);
|
|
75
78
|
const observedAt = performance.timeOrigin + performance.now();
|
|
76
79
|
const elapsed = input.startedAt === undefined
|
|
@@ -79,6 +82,11 @@ export async function observeAdmittedAskAkuma(input) {
|
|
|
79
82
|
: 0
|
|
80
83
|
: Math.max(0, performance.now() - input.startedAt);
|
|
81
84
|
const observed = await owner.tellOutcome(input.tellId, {
|
|
85
|
+
wake: () => {
|
|
86
|
+
if (wakeError !== undefined)
|
|
87
|
+
throw wakeError.error;
|
|
88
|
+
return wakeState;
|
|
89
|
+
},
|
|
82
90
|
...(input.timeoutMs === undefined ? {} : { timeoutMs: Math.max(0, input.timeoutMs - elapsed) }),
|
|
83
91
|
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
84
92
|
...(input.onObserve?.observe === undefined ? {} : { observe: input.onObserve.observe }),
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type OutcomeObserver } from "./akuma-observe.js";
|
|
2
|
+
import type { AkuId, AkumaPaths } from "./identity.js";
|
|
3
|
+
import { type ActivityHistory } from "./projection.js";
|
|
4
|
+
/** The complete bounded latest timeline window one stream emission carries; never a delta. */
|
|
5
|
+
export type AkumaStreamSnapshot = ActivityHistory;
|
|
6
|
+
/**
|
|
7
|
+
* The one continuous timeline observation as its caller sees it: pull-driven,
|
|
8
|
+
* so a slow consumer accumulates no queue.
|
|
9
|
+
*
|
|
10
|
+
* The observation runs behind this wrapper because a bare async generator
|
|
11
|
+
* cannot honour an end request while a pull is pending: `return()` would queue
|
|
12
|
+
* behind a pull that an idle timeline never settles, and the observation would
|
|
13
|
+
* hold its reader and its polling timer forever. The wrapper owns an internal
|
|
14
|
+
* controller instead, and the observation watches the caller's cancellation
|
|
15
|
+
* composed with it. `return` aborts that controller, which settles the pending
|
|
16
|
+
* poll and lets the loop release its reader in the same turn; because a
|
|
17
|
+
* composed signal keeps the reason of whichever source aborted first, an end
|
|
18
|
+
* request reads as completion while a caller's own abort keeps its own failure.
|
|
19
|
+
*/
|
|
20
|
+
export declare function createAkumaStream(paths: AkumaPaths, id: AkuId, options?: Readonly<{
|
|
21
|
+
signal?: AbortSignal;
|
|
22
|
+
}>, observe?: OutcomeObserver): AsyncIterableIterator<AkumaStreamSnapshot>;
|