@defrex/autobuild 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +192 -0
- package/SPEC.md +2269 -0
- package/bin/ab-build-runner.ts +47 -0
- package/bin/ab-dev.ts +27 -0
- package/bin/ab-dispatch-kernel.ts +92 -0
- package/bin/ab-harvest-runner.ts +29 -0
- package/bin/ab-init-probe.ts +19 -0
- package/bin/ab-process-group-reaper.ts +32 -0
- package/bin/ab.ts +6 -0
- package/bin/agent/ab +3 -0
- package/docs/answering-blocked-builds.md +89 -0
- package/docs/architecture.md +726 -0
- package/docs/assets/headline-wide.png +0 -0
- package/docs/configuration.md +1623 -0
- package/docs/hosted-dispatcher-cutover-validation.md +178 -0
- package/docs/hosted-dispatcher.md +204 -0
- package/docs/mcp.md +119 -0
- package/docs/operator-api.md +186 -0
- package/docs/remote-store-protocol.md +972 -0
- package/docs/remote-ticket-protocol.md +79 -0
- package/docs/setup.md +289 -0
- package/docs/spec-standard.md +63 -0
- package/docs/ticket-dependencies.md +59 -0
- package/docs/vercel-sandbox-rollout-probe.md +7 -0
- package/package.json +135 -0
- package/packages/core/src/cli/args.ts +74 -0
- package/packages/core/src/cli/artifact.ts +182 -0
- package/packages/core/src/cli/binary.ts +198 -0
- package/packages/core/src/cli/build-control.ts +789 -0
- package/packages/core/src/cli/build-progress.ts +55 -0
- package/packages/core/src/cli/bulk-control.ts +385 -0
- package/packages/core/src/cli/context.ts +470 -0
- package/packages/core/src/cli/dashboard/actions.ts +59 -0
- package/packages/core/src/cli/dashboard/cells.ts +92 -0
- package/packages/core/src/cli/dashboard/composer.ts +230 -0
- package/packages/core/src/cli/dashboard/detail.ts +100 -0
- package/packages/core/src/cli/dashboard/frame-image.ts +373 -0
- package/packages/core/src/cli/dashboard/live.ts +152 -0
- package/packages/core/src/cli/dashboard/model.ts +1173 -0
- package/packages/core/src/cli/dashboard/poll.ts +196 -0
- package/packages/core/src/cli/dashboard/render.ts +1568 -0
- package/packages/core/src/cli/dashboard/selection.ts +66 -0
- package/packages/core/src/cli/dashboard/session-feed.ts +244 -0
- package/packages/core/src/cli/dashboard/session-view.ts +506 -0
- package/packages/core/src/cli/dashboard/transcript.ts +108 -0
- package/packages/core/src/cli/dev.ts +46 -0
- package/packages/core/src/cli/dispatch-frontend.ts +1045 -0
- package/packages/core/src/cli/dispatch-process.ts +259 -0
- package/packages/core/src/cli/dispatch.ts +3692 -0
- package/packages/core/src/cli/dotenv.ts +48 -0
- package/packages/core/src/cli/env.ts +206 -0
- package/packages/core/src/cli/harvest.ts +698 -0
- package/packages/core/src/cli/help.ts +713 -0
- package/packages/core/src/cli/init-agent.ts +106 -0
- package/packages/core/src/cli/init-validation.ts +583 -0
- package/packages/core/src/cli/init.ts +756 -0
- package/packages/core/src/cli/installation.ts +333 -0
- package/packages/core/src/cli/keyboard.ts +261 -0
- package/packages/core/src/cli/main.ts +1399 -0
- package/packages/core/src/cli/mcp.ts +279 -0
- package/packages/core/src/cli/models.ts +65 -0
- package/packages/core/src/cli/observe.ts +55 -0
- package/packages/core/src/cli/plugin.ts +227 -0
- package/packages/core/src/cli/pr-attachments.ts +138 -0
- package/packages/core/src/cli/pr-summary.ts +124 -0
- package/packages/core/src/cli/publication-settlement.ts +188 -0
- package/packages/core/src/cli/repo-state.ts +213 -0
- package/packages/core/src/cli/repository-status.ts +80 -0
- package/packages/core/src/cli/self-update.ts +443 -0
- package/packages/core/src/cli/status.ts +895 -0
- package/packages/core/src/cli/store-opening.contract.ts +289 -0
- package/packages/core/src/cli/store-opening.ts +167 -0
- package/packages/core/src/cli/store-ref.ts +33 -0
- package/packages/core/src/cli/terminal-restore.ts +174 -0
- package/packages/core/src/cli/terminal.ts +361 -0
- package/packages/core/src/cli/terminals.ts +995 -0
- package/packages/core/src/cli/testkit.ts +194 -0
- package/packages/core/src/cli/ticket.ts +484 -0
- package/packages/core/src/cli/upgrade-agent.ts +180 -0
- package/packages/core/src/cli/upgrade-commit.ts +468 -0
- package/packages/core/src/cli/upgrade-notice.ts +91 -0
- package/packages/core/src/cli/upgrade-progress.ts +110 -0
- package/packages/core/src/cli/upgrade.ts +888 -0
- package/packages/core/src/cli/wait.ts +587 -0
- package/packages/core/src/cli/watch.ts +932 -0
- package/packages/core/src/config/live.ts +255 -0
- package/packages/core/src/config/load.ts +98 -0
- package/packages/core/src/config/roles.ts +438 -0
- package/packages/core/src/config/schema.ts +774 -0
- package/packages/core/src/distribution.ts +24 -0
- package/packages/core/src/events/catalog.ts +201 -0
- package/packages/core/src/events/envelope.ts +59 -0
- package/packages/core/src/events/payloads.ts +618 -0
- package/packages/core/src/events/repository.ts +559 -0
- package/packages/core/src/events/sessions.ts +180 -0
- package/packages/core/src/harvest/schema.ts +147 -0
- package/packages/core/src/ids.ts +45 -0
- package/packages/core/src/integration/harness.ts +681 -0
- package/packages/core/src/kernel/auto-merge.ts +259 -0
- package/packages/core/src/kernel/converge.ts +117 -0
- package/packages/core/src/kernel/dispatch-settings.ts +60 -0
- package/packages/core/src/kernel/dispatch-status.ts +141 -0
- package/packages/core/src/kernel/engine.ts +1047 -0
- package/packages/core/src/kernel/harvest.ts +823 -0
- package/packages/core/src/kernel/origin.ts +69 -0
- package/packages/core/src/kernel/phases.ts +196 -0
- package/packages/core/src/kernel/plan-verify-selection.ts +105 -0
- package/packages/core/src/kernel/pr-attachments.ts +82 -0
- package/packages/core/src/kernel/reducer.ts +752 -0
- package/packages/core/src/kernel/stall.ts +155 -0
- package/packages/core/src/kernel/verify-applicability.ts +52 -0
- package/packages/core/src/markdown.ts +67 -0
- package/packages/core/src/ontology.ts +288 -0
- package/packages/core/src/open-map.ts +203 -0
- package/packages/core/src/operator/annotations.ts +187 -0
- package/packages/core/src/operator/client.ts +311 -0
- package/packages/core/src/operator/control.ts +117 -0
- package/packages/core/src/operator/index.ts +62 -0
- package/packages/core/src/operator/presentation.ts +22 -0
- package/packages/core/src/operator/protocol.ts +98 -0
- package/packages/core/src/operator/query.ts +201 -0
- package/packages/core/src/operator/registry.ts +1043 -0
- package/packages/core/src/operator/requests.ts +138 -0
- package/packages/core/src/operator/sandbox.ts +458 -0
- package/packages/core/src/operator/server.ts +616 -0
- package/packages/core/src/operator/sessions.ts +223 -0
- package/packages/core/src/operator/tickets.ts +177 -0
- package/packages/core/src/plugin-sdk/index.ts +174 -0
- package/packages/core/src/plugins/contract-entry.ts +74 -0
- package/packages/core/src/plugins/contract-env.ts +3 -0
- package/packages/core/src/plugins/load.ts +259 -0
- package/packages/core/src/plugins/manifest.ts +236 -0
- package/packages/core/src/plugins/registry.ts +274 -0
- package/packages/core/src/plugins/runtimes.ts +75 -0
- package/packages/core/src/ports/forge/contract.ts +258 -0
- package/packages/core/src/ports/forge/create.ts +74 -0
- package/packages/core/src/ports/forge/fake.ts +488 -0
- package/packages/core/src/ports/forge/github-pr-attachments.ts +351 -0
- package/packages/core/src/ports/forge/github-transport.ts +352 -0
- package/packages/core/src/ports/forge/github.ts +1162 -0
- package/packages/core/src/ports/forge/local-git.ts +568 -0
- package/packages/core/src/ports/runner/claude.ts +873 -0
- package/packages/core/src/ports/runner/cli-stream.ts +90 -0
- package/packages/core/src/ports/runner/codex.ts +873 -0
- package/packages/core/src/ports/runner/contract.ts +492 -0
- package/packages/core/src/ports/runner/fake.ts +213 -0
- package/packages/core/src/ports/runner/json-record.ts +2 -0
- package/packages/core/src/ports/runner/live-contract-fixture.ts +176 -0
- package/packages/core/src/ports/runner/one-shot.ts +29 -0
- package/packages/core/src/ports/runner/pi-bridge-core.ts +136 -0
- package/packages/core/src/ports/runner/pi-bridge.js +6 -0
- package/packages/core/src/ports/runner/pi-rpc.ts +454 -0
- package/packages/core/src/ports/runner/pi.ts +617 -0
- package/packages/core/src/ports/runner/production.ts +74 -0
- package/packages/core/src/ports/runner/provider-error.ts +121 -0
- package/packages/core/src/ports/runner/routing.ts +234 -0
- package/packages/core/src/ports/runner/runtime.ts +214 -0
- package/packages/core/src/ports/runner/session-env.ts +34 -0
- package/packages/core/src/ports/runner/stream-parts.ts +103 -0
- package/packages/core/src/ports/tickets/contract.ts +570 -0
- package/packages/core/src/ports/tickets/create.ts +135 -0
- package/packages/core/src/ports/tickets/fake.ts +215 -0
- package/packages/core/src/ports/tickets/file.ts +559 -0
- package/packages/core/src/ports/tickets/linear.ts +811 -0
- package/packages/core/src/ports/tickets/operations.ts +161 -0
- package/packages/core/src/ports/tickets/remote-index.ts +13 -0
- package/packages/core/src/ports/tickets/remote-protocol.ts +80 -0
- package/packages/core/src/ports/tickets/remote-server.ts +185 -0
- package/packages/core/src/ports/tickets/remote.ts +130 -0
- package/packages/core/src/ports/tickets/update.ts +51 -0
- package/packages/core/src/ports/types.ts +528 -0
- package/packages/core/src/ports/workspace/build-execution.ts +123 -0
- package/packages/core/src/ports/workspace/contract.ts +136 -0
- package/packages/core/src/ports/workspace/create.ts +132 -0
- package/packages/core/src/ports/workspace/distribution-archive.ts +317 -0
- package/packages/core/src/ports/workspace/fake.ts +432 -0
- package/packages/core/src/ports/workspace/git-worktree.ts +848 -0
- package/packages/core/src/ports/workspace/harvest-execution.ts +111 -0
- package/packages/core/src/ports/workspace/in-process-build-execution.ts +30 -0
- package/packages/core/src/ports/workspace/local-build-execution.ts +88 -0
- package/packages/core/src/ports/workspace/operator-sandbox.ts +142 -0
- package/packages/core/src/ports/workspace/phase-scratch.ts +156 -0
- package/packages/core/src/ports/workspace/vercel-sandbox.ts +2541 -0
- package/packages/core/src/processes/build-child-exit.ts +78 -0
- package/packages/core/src/processes/build-child.ts +119 -0
- package/packages/core/src/processes/build-execution-state.ts +95 -0
- package/packages/core/src/processes/build-parent-watch.ts +35 -0
- package/packages/core/src/processes/build-runner.ts +2614 -0
- package/packages/core/src/processes/dispatcher.ts +2825 -0
- package/packages/core/src/processes/execution-settlement.ts +171 -0
- package/packages/core/src/processes/harvest-child.ts +115 -0
- package/packages/core/src/processes/harvest-execution-state.ts +121 -0
- package/packages/core/src/processes/harvest-runner.ts +1656 -0
- package/packages/core/src/processes/harvest.ts +595 -0
- package/packages/core/src/processes/infrastructure-failure-budget.ts +146 -0
- package/packages/core/src/processes/phase-failure-budget.ts +52 -0
- package/packages/core/src/processes/process-group-reaper.ts +35 -0
- package/packages/core/src/processes/process-group.ts +65 -0
- package/packages/core/src/processes/publication-loss.ts +62 -0
- package/packages/core/src/processes/publication-state.ts +93 -0
- package/packages/core/src/processes/sandbox-state.ts +101 -0
- package/packages/core/src/registry.ts +24 -0
- package/packages/core/src/sessions/reducer.ts +185 -0
- package/packages/core/src/skills.ts +7 -0
- package/packages/core/src/spec-standard.ts +47 -0
- package/packages/core/src/store/adapter.ts +80 -0
- package/packages/core/src/store/build-scope.ts +272 -0
- package/packages/core/src/store/contract.ts +2581 -0
- package/packages/core/src/store/local/blobs.ts +38 -0
- package/packages/core/src/store/local/schema.ts +180 -0
- package/packages/core/src/store/local/store.ts +1713 -0
- package/packages/core/src/store/memory.ts +1138 -0
- package/packages/core/src/store/phase-session.ts +425 -0
- package/packages/core/src/store/remote/client.ts +780 -0
- package/packages/core/src/store/remote/index.ts +12 -0
- package/packages/core/src/store/remote/protocol.ts +348 -0
- package/packages/core/src/store/remote/server.ts +923 -0
- package/packages/core/src/store/remote/token.ts +137 -0
- package/packages/core/src/store/remote/version.ts +10 -0
- package/packages/core/src/store/retention.ts +91 -0
- package/packages/core/src/store/session-handle.ts +265 -0
- package/packages/core/src/store/streams/assemble.ts +79 -0
- package/packages/core/src/store/streams/lock.ts +42 -0
- package/packages/core/src/store/streams/session-writer.ts +306 -0
- package/packages/core/src/store/streams/types.ts +171 -0
- package/packages/core/src/store/streams/wait.ts +127 -0
- package/packages/core/src/store/subscribe.ts +105 -0
- package/packages/core/src/store/types.ts +466 -0
- package/packages/core/src/testing/fixed.ts +44 -0
- package/packages/core/src/testing/store-failures.ts +32 -0
- package/packages/core/src/zod-issues.ts +91 -0
- package/skills/code-review/SKILL.md +100 -0
- package/skills/finalize/SKILL.md +44 -0
- package/skills/guide/SKILL.md +1781 -0
- package/skills/guide/references/operator-api.md +164 -0
- package/skills/guide/references/plugin-authoring.md +354 -0
- package/skills/guide/references/remote-store-protocol.md +972 -0
- package/skills/guide/references/remote-ticket-protocol.md +79 -0
- package/skills/guide/references/setup.md +289 -0
- package/skills/guide/references/spec-standard.md +63 -0
- package/skills/guide/references/ticket-dependencies.md +59 -0
- package/skills/harvest/SKILL.md +66 -0
- package/skills/harvest-review/SKILL.md +63 -0
- package/skills/implement/SKILL.md +82 -0
- package/skills/plan/SKILL.md +123 -0
- package/skills/plan-review/SKILL.md +121 -0
- package/skills/reconcile/SKILL.md +65 -0
- package/skills/spec/SKILL.md +132 -0
- package/skills/tickets/SKILL.md +139 -0
- package/templates/autobuild.toml +36 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The operator-session reducer (SPEC §7.1.1, §15.2): a session's status, open
|
|
3
|
+
* turn, pending approval, wake settings, wake cursors, and turn list are a
|
|
4
|
+
* pure reduction of its event log — never a stored column. The catalog is
|
|
5
|
+
* closed (`events/sessions.ts`), so this function is total over session
|
|
6
|
+
* history; unknown facts cannot exist.
|
|
7
|
+
*/
|
|
8
|
+
import type { SessionEvent } from '../events/sessions'
|
|
9
|
+
|
|
10
|
+
export type SessionStatus = 'idle' | 'running' | 'suspended' | 'awaiting-approval' | 'archived'
|
|
11
|
+
export type SessionSuspensionCause = 'budget' | 'approval'
|
|
12
|
+
export type TurnOutcomeState = 'open' | 'suspended' | 'completed' | 'failed'
|
|
13
|
+
|
|
14
|
+
export type SessionTurnTrigger =
|
|
15
|
+
| { kind: 'message'; messageSeq: number }
|
|
16
|
+
| { kind: 'wake'; build: string; seq: number; type: string }
|
|
17
|
+
|
|
18
|
+
export interface SessionTurn {
|
|
19
|
+
turn: string
|
|
20
|
+
stream: string
|
|
21
|
+
startedSeq: number
|
|
22
|
+
trigger: SessionTurnTrigger
|
|
23
|
+
state: TurnOutcomeState
|
|
24
|
+
usage?: { inputTokens: number; outputTokens: number; turns?: number }
|
|
25
|
+
error?: string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface SessionState {
|
|
29
|
+
status: SessionStatus
|
|
30
|
+
/** Present only when status is `suspended`. */
|
|
31
|
+
suspendedCause?: SessionSuspensionCause
|
|
32
|
+
/** The most recent turn that has started and not completed or failed. */
|
|
33
|
+
openTurn?: { turn: string; stream: string; startedSeq: number; trigger: SessionTurnTrigger }
|
|
34
|
+
/** A requested approval with no matching `approval.answered` yet. */
|
|
35
|
+
pendingApproval?: {
|
|
36
|
+
turn: string
|
|
37
|
+
toolCallId: string
|
|
38
|
+
toolName: string
|
|
39
|
+
input: Record<string, unknown>
|
|
40
|
+
requestedSeq: number
|
|
41
|
+
}
|
|
42
|
+
/** Last `session.wake-set` wins; `[]` before the first (message-only). */
|
|
43
|
+
wakeGlobs: string[]
|
|
44
|
+
/** Per build, the highest build event seq a wake trigger has consumed. */
|
|
45
|
+
wakeCursors: Record<string, number>
|
|
46
|
+
/** Every turn in start order, with its stream id and outcome. */
|
|
47
|
+
turns: SessionTurn[]
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface TurnEntry extends SessionTurn {
|
|
51
|
+
/** The most recent suspension cause for this turn, if any. */
|
|
52
|
+
suspensionCause?: SessionSuspensionCause
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const isTerminal = (state: SessionTurn['state']): boolean =>
|
|
56
|
+
state === 'completed' || state === 'failed'
|
|
57
|
+
|
|
58
|
+
/** Reduce a session's events into its derived state. `session.archived` is
|
|
59
|
+
* terminal: every fact after it is ignored — the archived state is frozen. */
|
|
60
|
+
export function reduceSession(events: SessionEvent[]): SessionState {
|
|
61
|
+
const turns: TurnEntry[] = []
|
|
62
|
+
let archived = false
|
|
63
|
+
let pendingApproval: SessionState['pendingApproval']
|
|
64
|
+
let wakeGlobs: string[] = []
|
|
65
|
+
const wakeCursors: Record<string, number> = {}
|
|
66
|
+
|
|
67
|
+
const open = (): TurnEntry | undefined => turns.findLast((turn) => !isTerminal(turn.state))
|
|
68
|
+
|
|
69
|
+
for (const event of events) {
|
|
70
|
+
if (archived) break
|
|
71
|
+
switch (event.type) {
|
|
72
|
+
case 'session.created':
|
|
73
|
+
case 'message.posted':
|
|
74
|
+
break
|
|
75
|
+
case 'session.wake-set':
|
|
76
|
+
wakeGlobs = [...event.payload.globs]
|
|
77
|
+
break
|
|
78
|
+
case 'turn.started': {
|
|
79
|
+
const entry: TurnEntry = {
|
|
80
|
+
turn: event.payload.turn,
|
|
81
|
+
stream: event.payload.stream,
|
|
82
|
+
startedSeq: event.seq,
|
|
83
|
+
trigger: event.payload.trigger,
|
|
84
|
+
state: 'open',
|
|
85
|
+
}
|
|
86
|
+
turns.push(entry)
|
|
87
|
+
if (event.payload.trigger.kind === 'wake') {
|
|
88
|
+
const build = event.payload.trigger.build
|
|
89
|
+
wakeCursors[build] = Math.max(wakeCursors[build] ?? 0, event.payload.trigger.seq)
|
|
90
|
+
}
|
|
91
|
+
break
|
|
92
|
+
}
|
|
93
|
+
case 'turn.suspended': {
|
|
94
|
+
const entry = turns.findLast((candidate) => candidate.turn === event.payload.turn)
|
|
95
|
+
if (entry && entry.state === 'open') {
|
|
96
|
+
entry.state = 'suspended'
|
|
97
|
+
entry.suspensionCause = event.payload.cause
|
|
98
|
+
}
|
|
99
|
+
break
|
|
100
|
+
}
|
|
101
|
+
case 'turn.resumed': {
|
|
102
|
+
const entry = turns.findLast((candidate) => candidate.turn === event.payload.turn)
|
|
103
|
+
if (entry && entry.state === 'suspended') entry.state = 'open'
|
|
104
|
+
break
|
|
105
|
+
}
|
|
106
|
+
case 'approval.requested':
|
|
107
|
+
pendingApproval = {
|
|
108
|
+
turn: event.payload.turn,
|
|
109
|
+
toolCallId: event.payload.toolCallId,
|
|
110
|
+
toolName: event.payload.toolName,
|
|
111
|
+
input: event.payload.input,
|
|
112
|
+
requestedSeq: event.seq,
|
|
113
|
+
}
|
|
114
|
+
break
|
|
115
|
+
case 'approval.answered': {
|
|
116
|
+
if (
|
|
117
|
+
pendingApproval?.turn === event.payload.turn &&
|
|
118
|
+
pendingApproval.toolCallId === event.payload.toolCallId
|
|
119
|
+
) {
|
|
120
|
+
pendingApproval = undefined
|
|
121
|
+
// The answer resumes the turn; `turn.resumed` is the runner's
|
|
122
|
+
// acknowledgement of the same fact, so between answer and resume
|
|
123
|
+
// the status is already `running` when a turn is open.
|
|
124
|
+
const entry = turns.findLast((candidate) => candidate.turn === event.payload.turn)
|
|
125
|
+
if (entry && entry.state === 'suspended') entry.state = 'open'
|
|
126
|
+
}
|
|
127
|
+
break
|
|
128
|
+
}
|
|
129
|
+
case 'turn.completed': {
|
|
130
|
+
const entry = turns.findLast((candidate) => candidate.turn === event.payload.turn)
|
|
131
|
+
if (entry && !isTerminal(entry.state)) {
|
|
132
|
+
entry.state = 'completed'
|
|
133
|
+
entry.usage = event.payload.usage
|
|
134
|
+
}
|
|
135
|
+
break
|
|
136
|
+
}
|
|
137
|
+
case 'turn.failed': {
|
|
138
|
+
const entry = turns.findLast((candidate) => candidate.turn === event.payload.turn)
|
|
139
|
+
if (entry && !isTerminal(entry.state)) {
|
|
140
|
+
entry.state = 'failed'
|
|
141
|
+
entry.error = event.payload.error
|
|
142
|
+
}
|
|
143
|
+
break
|
|
144
|
+
}
|
|
145
|
+
case 'session.archived':
|
|
146
|
+
archived = true
|
|
147
|
+
break
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const openEntry = open()
|
|
152
|
+
// Status precedence: archived > awaiting-approval > suspended > running >
|
|
153
|
+
// idle. An unanswered approval outranks its turn's suspension; the answer
|
|
154
|
+
// that clears it hands status back to the turn.
|
|
155
|
+
const status: SessionStatus = archived
|
|
156
|
+
? 'archived'
|
|
157
|
+
: pendingApproval !== undefined
|
|
158
|
+
? 'awaiting-approval'
|
|
159
|
+
: openEntry === undefined
|
|
160
|
+
? 'idle'
|
|
161
|
+
: openEntry.state === 'suspended'
|
|
162
|
+
? 'suspended'
|
|
163
|
+
: 'running'
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
status,
|
|
167
|
+
...(status === 'suspended' && openEntry?.suspensionCause !== undefined
|
|
168
|
+
? { suspendedCause: openEntry.suspensionCause }
|
|
169
|
+
: {}),
|
|
170
|
+
...(openEntry !== undefined
|
|
171
|
+
? {
|
|
172
|
+
openTurn: {
|
|
173
|
+
turn: openEntry.turn,
|
|
174
|
+
stream: openEntry.stream,
|
|
175
|
+
startedSeq: openEntry.startedSeq,
|
|
176
|
+
trigger: openEntry.trigger,
|
|
177
|
+
},
|
|
178
|
+
}
|
|
179
|
+
: {}),
|
|
180
|
+
...(pendingApproval !== undefined ? { pendingApproval } : {}),
|
|
181
|
+
wakeGlobs,
|
|
182
|
+
wakeCursors,
|
|
183
|
+
turns: turns.map(({ suspensionCause: _suspensionCause, ...turn }) => turn),
|
|
184
|
+
}
|
|
185
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Repo-installed Autobuild skills share one harness-neutral namespace. */
|
|
2
|
+
export const SKILL_NAMESPACE = 'ab-'
|
|
3
|
+
|
|
4
|
+
/** Add the namespace once, accepting explicit namespaced config values too. */
|
|
5
|
+
export function installedSkillName(name: string): string {
|
|
6
|
+
return name.startsWith(SKILL_NAMESPACE) ? name : `${SKILL_NAMESPACE}${name}`
|
|
7
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** The deterministic, mechanically checkable core of docs/spec-standard.md. */
|
|
2
|
+
export interface SpecConformance {
|
|
3
|
+
conforms: boolean
|
|
4
|
+
missing: string[]
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const LIST_ITEM = /^\s*(?:[-*+]|\d+[.)])\s+\S/
|
|
8
|
+
const HEADING = /^(#{1,6})\s*(.+?)\s*$/
|
|
9
|
+
|
|
10
|
+
function sectionUnder(lines: string[], name: string): string[] | null {
|
|
11
|
+
let start = -1
|
|
12
|
+
let level = 0
|
|
13
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
14
|
+
const match = lines[i]?.match(HEADING)
|
|
15
|
+
if (match?.[2]?.toLowerCase().startsWith(name)) {
|
|
16
|
+
start = i + 1
|
|
17
|
+
level = match[1]?.length ?? 0
|
|
18
|
+
break
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (start === -1) return null
|
|
22
|
+
const section: string[] = []
|
|
23
|
+
for (let i = start; i < lines.length; i += 1) {
|
|
24
|
+
const line = lines[i]
|
|
25
|
+
if (line === undefined) break
|
|
26
|
+
const heading = line.match(HEADING)
|
|
27
|
+
if (heading !== null && (heading[1]?.length ?? 0) <= level) break
|
|
28
|
+
section.push(line)
|
|
29
|
+
}
|
|
30
|
+
return section
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function specConformance(body: string): SpecConformance {
|
|
34
|
+
const missing: string[] = []
|
|
35
|
+
if (body.trim().length === 0) missing.push('a nonempty spec body')
|
|
36
|
+
const lines = body.split('\n')
|
|
37
|
+
const criteria = sectionUnder(lines, 'acceptance criteria')
|
|
38
|
+
if (criteria === null) {
|
|
39
|
+
missing.push("an '## Acceptance criteria' heading")
|
|
40
|
+
} else if (!criteria.some((line) => LIST_ITEM.test(line))) {
|
|
41
|
+
missing.push("at least one list item under '## Acceptance criteria'")
|
|
42
|
+
}
|
|
43
|
+
if (sectionUnder(lines, 'out of scope') === null) {
|
|
44
|
+
missing.push("an '## Out of scope' heading")
|
|
45
|
+
}
|
|
46
|
+
return { conforms: missing.length === 0, missing }
|
|
47
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
export { validateEventWrite } from '../events/catalog'
|
|
2
|
+
export { humanActor } from '../events/envelope'
|
|
3
|
+
export type { AbEvent, EventEnvelope, EventWrite } from '../events/catalog'
|
|
4
|
+
export type { EventType } from '../events/payloads'
|
|
5
|
+
export { validateRepositoryEventWrite } from '../events/repository'
|
|
6
|
+
export type {
|
|
7
|
+
RepositoryEvent,
|
|
8
|
+
RepositoryEventEnvelope,
|
|
9
|
+
RepositoryEventType,
|
|
10
|
+
RepositoryEventWrite,
|
|
11
|
+
} from '../events/repository'
|
|
12
|
+
export { validateSessionEventWrite } from '../events/sessions'
|
|
13
|
+
export type {
|
|
14
|
+
SessionEvent,
|
|
15
|
+
SessionEventEnvelope,
|
|
16
|
+
SessionEventType,
|
|
17
|
+
SessionEventWrite,
|
|
18
|
+
} from '../events/sessions'
|
|
19
|
+
export { createBuildScopedStore } from './build-scope'
|
|
20
|
+
export { createSessionScopedStore } from './session-handle'
|
|
21
|
+
export {
|
|
22
|
+
DEFAULT_ARTIFACT_RETENTION_MAX_REVISIONS,
|
|
23
|
+
DISPATCHER_RETENTION_BUILD_KINDS,
|
|
24
|
+
DISPATCHER_RETENTION_REPO_KINDS,
|
|
25
|
+
isRetentionManagedKind,
|
|
26
|
+
revisionsToPrune,
|
|
27
|
+
} from './retention'
|
|
28
|
+
export { assembleUIMessageDocument } from './streams/assemble'
|
|
29
|
+
export {
|
|
30
|
+
EVENT_WAIT_POLL_MS,
|
|
31
|
+
readEventsWithWait,
|
|
32
|
+
readStreamWithWait,
|
|
33
|
+
STREAM_WAIT_POLL_MS,
|
|
34
|
+
} from './streams/wait'
|
|
35
|
+
export { createSessionStreamSink } from './streams/session-writer'
|
|
36
|
+
export {
|
|
37
|
+
clampWaitSeconds,
|
|
38
|
+
MAX_STREAM_WAIT_SECONDS,
|
|
39
|
+
serializedBatchSize,
|
|
40
|
+
STREAM_BATCH_MAX_BYTES,
|
|
41
|
+
STREAM_FORMAT,
|
|
42
|
+
StreamBatchTooLargeError,
|
|
43
|
+
StreamClosedError,
|
|
44
|
+
streamArtifactInput,
|
|
45
|
+
validateStreamParts,
|
|
46
|
+
} from './streams/types'
|
|
47
|
+
export type {
|
|
48
|
+
StreamArtifactRef,
|
|
49
|
+
StreamChunk,
|
|
50
|
+
StreamOutcome,
|
|
51
|
+
StreamPart,
|
|
52
|
+
StreamRead,
|
|
53
|
+
StreamRecord,
|
|
54
|
+
StreamScope,
|
|
55
|
+
StreamStatus,
|
|
56
|
+
} from './streams/types'
|
|
57
|
+
export { pollingSubscribe } from './subscribe'
|
|
58
|
+
export { contentHash, systemClock, toBytes, validateExpectedSeq } from './types'
|
|
59
|
+
export type {
|
|
60
|
+
Artifact,
|
|
61
|
+
ArtifactInput,
|
|
62
|
+
ArtifactMeta,
|
|
63
|
+
BlobStore,
|
|
64
|
+
BuildRecord,
|
|
65
|
+
BuildScopedStore,
|
|
66
|
+
BuildStore,
|
|
67
|
+
Clock,
|
|
68
|
+
NewBuildInput,
|
|
69
|
+
NewSessionInput,
|
|
70
|
+
RepositoryArtifact,
|
|
71
|
+
RepositoryArtifactMeta,
|
|
72
|
+
RepositoryRecord,
|
|
73
|
+
SessionArtifact,
|
|
74
|
+
SessionArtifactMeta,
|
|
75
|
+
SessionRecord,
|
|
76
|
+
SessionScopedStore,
|
|
77
|
+
SubscribeOptions,
|
|
78
|
+
Unsubscribe,
|
|
79
|
+
} from './types'
|
|
80
|
+
export { normalizeOperator } from './types'
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import type { EventType } from '../events/payloads'
|
|
2
|
+
import type { EventWrite } from '../events/catalog'
|
|
3
|
+
import type { RepositoryEventType, RepositoryEventWrite } from '../events/repository'
|
|
4
|
+
import type { AbEvent, EventEnvelope } from '../events/catalog'
|
|
5
|
+
import type { RepositoryEvent, RepositoryEventEnvelope } from '../events/repository'
|
|
6
|
+
import type {
|
|
7
|
+
SessionEvent,
|
|
8
|
+
SessionEventEnvelope,
|
|
9
|
+
SessionEventType,
|
|
10
|
+
SessionEventWrite,
|
|
11
|
+
} from '../events/sessions'
|
|
12
|
+
import type {
|
|
13
|
+
Artifact,
|
|
14
|
+
ArtifactInput,
|
|
15
|
+
ArtifactMeta,
|
|
16
|
+
BuildRecord,
|
|
17
|
+
BuildScopedStore,
|
|
18
|
+
BuildStore,
|
|
19
|
+
NewBuildInput,
|
|
20
|
+
RepositoryArtifact,
|
|
21
|
+
RepositoryArtifactMeta,
|
|
22
|
+
RepositoryRecord,
|
|
23
|
+
SessionArtifactMeta,
|
|
24
|
+
SessionRecord,
|
|
25
|
+
SubscribeOptions,
|
|
26
|
+
Unsubscribe,
|
|
27
|
+
} from './types'
|
|
28
|
+
import type {
|
|
29
|
+
StreamChunk,
|
|
30
|
+
StreamOutcome,
|
|
31
|
+
StreamPart,
|
|
32
|
+
StreamRead,
|
|
33
|
+
StreamRecord,
|
|
34
|
+
StreamScope,
|
|
35
|
+
} from './streams/types'
|
|
36
|
+
|
|
37
|
+
/** Interface-level authority failure. It is deliberately independent of the
|
|
38
|
+
* remote transport's authentication errors: tokens carry this scope over the
|
|
39
|
+
* wire, while every adapter enforces it before delegation. */
|
|
40
|
+
export class BuildScopeError extends Error {
|
|
41
|
+
constructor(
|
|
42
|
+
readonly scope: string,
|
|
43
|
+
readonly operation: string,
|
|
44
|
+
readonly target?: string,
|
|
45
|
+
) {
|
|
46
|
+
super(
|
|
47
|
+
target === undefined
|
|
48
|
+
? `build-scoped store for ${JSON.stringify(scope)} forbids ${operation}`
|
|
49
|
+
: `build-scoped store for ${JSON.stringify(scope)} forbids ${operation} targeting ${JSON.stringify(target)}`,
|
|
50
|
+
)
|
|
51
|
+
this.name = 'BuildScopeError'
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Wrap a full store with one-build authority. The wrapper intentionally keeps
|
|
56
|
+
* the complete BuildStore shape so accidental admin, collection, repository,
|
|
57
|
+
* or foreign-build calls fail loudly instead of disappearing behind a type
|
|
58
|
+
* assertion. */
|
|
59
|
+
export function createBuildScopedStore(store: BuildStore, scope: string): BuildScopedStore {
|
|
60
|
+
const own = (operation: string, slug: string): void => {
|
|
61
|
+
if (slug !== scope) throw new BuildScopeError(scope, operation, slug)
|
|
62
|
+
}
|
|
63
|
+
/** Stream scopes ride on the record, not on an argument: create and list
|
|
64
|
+
* name the scope directly; addressed operations resolve the target's scope
|
|
65
|
+
* and reject when it is not exactly this build's. An unknown id delegates
|
|
66
|
+
* so the backing store's `unknown stream` feedback survives. */
|
|
67
|
+
const ownStreamScope = (record: StreamRecord): void => {
|
|
68
|
+
if (record.scope.kind !== 'build' || record.scope.build !== scope) {
|
|
69
|
+
throw new BuildScopeError(scope, 'stream', record.id)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const ownStream = async (_operation: string, streamId: string): Promise<void> => {
|
|
73
|
+
const record = await store.getStream(streamId)
|
|
74
|
+
if (record) ownStreamScope(record)
|
|
75
|
+
}
|
|
76
|
+
const buildScope = (operation: string, candidate: StreamScope): void => {
|
|
77
|
+
if (candidate.kind !== 'build' || candidate.build !== scope) {
|
|
78
|
+
throw new BuildScopeError(scope, operation, JSON.stringify(candidate))
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
buildScope: scope,
|
|
83
|
+
scopeBuild(slug: string): BuildScopedStore {
|
|
84
|
+
own('scopeBuild', slug)
|
|
85
|
+
return this
|
|
86
|
+
},
|
|
87
|
+
createBuild(_input: NewBuildInput): Promise<BuildRecord> {
|
|
88
|
+
return Promise.reject(new BuildScopeError(scope, 'createBuild'))
|
|
89
|
+
},
|
|
90
|
+
async getBuild(slug: string): Promise<BuildRecord | null> {
|
|
91
|
+
own('getBuild', slug)
|
|
92
|
+
return store.getBuild(slug)
|
|
93
|
+
},
|
|
94
|
+
listBuilds(): Promise<BuildRecord[]> {
|
|
95
|
+
return Promise.reject(new BuildScopeError(scope, 'listBuilds'))
|
|
96
|
+
},
|
|
97
|
+
async append<T extends EventType>(
|
|
98
|
+
slug: string,
|
|
99
|
+
event: EventWrite<T>,
|
|
100
|
+
): Promise<EventEnvelope<T>> {
|
|
101
|
+
own('append', slug)
|
|
102
|
+
return store.append(slug, event)
|
|
103
|
+
},
|
|
104
|
+
async appendIfCurrent<T extends EventType>(
|
|
105
|
+
slug: string,
|
|
106
|
+
expectedSeq: number,
|
|
107
|
+
event: EventWrite<T>,
|
|
108
|
+
): Promise<EventEnvelope<T> | null> {
|
|
109
|
+
own('appendIfCurrent', slug)
|
|
110
|
+
return store.appendIfCurrent(slug, expectedSeq, event)
|
|
111
|
+
},
|
|
112
|
+
async appendWithArtifacts<T extends EventType>(
|
|
113
|
+
slug: string,
|
|
114
|
+
artifacts: ArtifactInput[],
|
|
115
|
+
makeEvent: (deposited: ArtifactMeta[]) => EventWrite<T>,
|
|
116
|
+
): Promise<{ event: EventEnvelope<T>; artifacts: ArtifactMeta[] }> {
|
|
117
|
+
own('appendWithArtifacts', slug)
|
|
118
|
+
return store.appendWithArtifacts(slug, artifacts, makeEvent)
|
|
119
|
+
},
|
|
120
|
+
async getEvents(
|
|
121
|
+
slug: string,
|
|
122
|
+
sinceSeq?: number,
|
|
123
|
+
opts?: { waitSeconds?: number; signal?: AbortSignal },
|
|
124
|
+
): Promise<AbEvent[]> {
|
|
125
|
+
own('getEvents', slug)
|
|
126
|
+
return store.getEvents(slug, sinceSeq, opts)
|
|
127
|
+
},
|
|
128
|
+
async putArtifact(slug: string, artifact: ArtifactInput): Promise<ArtifactMeta> {
|
|
129
|
+
own('putArtifact', slug)
|
|
130
|
+
return store.putArtifact(slug, artifact)
|
|
131
|
+
},
|
|
132
|
+
async getArtifact(slug: string, kind: string, rev?: number): Promise<Artifact | null> {
|
|
133
|
+
own('getArtifact', slug)
|
|
134
|
+
return store.getArtifact(slug, kind, rev)
|
|
135
|
+
},
|
|
136
|
+
async listArtifacts(slug: string, kind?: string): Promise<ArtifactMeta[]> {
|
|
137
|
+
own('listArtifacts', slug)
|
|
138
|
+
return store.listArtifacts(slug, kind)
|
|
139
|
+
},
|
|
140
|
+
async claimLease(slug: string, holder: string, ttlMs: number): Promise<boolean> {
|
|
141
|
+
own('claimLease', slug)
|
|
142
|
+
return store.claimLease(slug, holder, ttlMs)
|
|
143
|
+
},
|
|
144
|
+
async heartbeat(slug: string, holder: string): Promise<boolean> {
|
|
145
|
+
own('heartbeat', slug)
|
|
146
|
+
return store.heartbeat(slug, holder)
|
|
147
|
+
},
|
|
148
|
+
async releaseLease(slug: string, holder: string): Promise<void> {
|
|
149
|
+
own('releaseLease', slug)
|
|
150
|
+
return store.releaseLease(slug, holder)
|
|
151
|
+
},
|
|
152
|
+
subscribe(
|
|
153
|
+
slug: string,
|
|
154
|
+
opts: SubscribeOptions,
|
|
155
|
+
onEvent: (event: AbEvent) => void,
|
|
156
|
+
): Unsubscribe {
|
|
157
|
+
own('subscribe', slug)
|
|
158
|
+
return store.subscribe(slug, opts, onEvent)
|
|
159
|
+
},
|
|
160
|
+
ensureRepo(repo: string): Promise<RepositoryRecord> {
|
|
161
|
+
return Promise.reject(new BuildScopeError(scope, 'ensureRepo', repo))
|
|
162
|
+
},
|
|
163
|
+
getRepo(repo: string): Promise<RepositoryRecord | null> {
|
|
164
|
+
return Promise.reject(new BuildScopeError(scope, 'getRepo', repo))
|
|
165
|
+
},
|
|
166
|
+
appendRepo<T extends RepositoryEventType>(
|
|
167
|
+
repo: string,
|
|
168
|
+
_event: RepositoryEventWrite<T>,
|
|
169
|
+
): Promise<RepositoryEventEnvelope<T>> {
|
|
170
|
+
return Promise.reject(new BuildScopeError(scope, 'appendRepo', repo))
|
|
171
|
+
},
|
|
172
|
+
appendRepoWithArtifacts<T extends RepositoryEventType>(
|
|
173
|
+
repo: string,
|
|
174
|
+
_artifacts: ArtifactInput[],
|
|
175
|
+
_makeEvent: (deposited: RepositoryArtifactMeta[]) => RepositoryEventWrite<T>,
|
|
176
|
+
): Promise<{ event: RepositoryEventEnvelope<T>; artifacts: RepositoryArtifactMeta[] }> {
|
|
177
|
+
return Promise.reject(new BuildScopeError(scope, 'appendRepoWithArtifacts', repo))
|
|
178
|
+
},
|
|
179
|
+
getRepoEvents(repo: string, _sinceSeq?: number): Promise<RepositoryEvent[]> {
|
|
180
|
+
return Promise.reject(new BuildScopeError(scope, 'getRepoEvents', repo))
|
|
181
|
+
},
|
|
182
|
+
putRepoArtifact(repo: string, _artifact: ArtifactInput): Promise<RepositoryArtifactMeta> {
|
|
183
|
+
return Promise.reject(new BuildScopeError(scope, 'putRepoArtifact', repo))
|
|
184
|
+
},
|
|
185
|
+
getRepoArtifact(
|
|
186
|
+
repo: string,
|
|
187
|
+
_kind: string,
|
|
188
|
+
_rev?: number,
|
|
189
|
+
): Promise<RepositoryArtifact | null> {
|
|
190
|
+
return Promise.reject(new BuildScopeError(scope, 'getRepoArtifact', repo))
|
|
191
|
+
},
|
|
192
|
+
listRepoArtifacts(repo: string, _kind?: string): Promise<RepositoryArtifactMeta[]> {
|
|
193
|
+
return Promise.reject(new BuildScopeError(scope, 'listRepoArtifacts', repo))
|
|
194
|
+
},
|
|
195
|
+
claimRepoLease(repo: string, _holder: string, _ttlMs: number): Promise<boolean> {
|
|
196
|
+
return Promise.reject(new BuildScopeError(scope, 'claimRepoLease', repo))
|
|
197
|
+
},
|
|
198
|
+
heartbeatRepo(repo: string, _holder: string): Promise<boolean> {
|
|
199
|
+
return Promise.reject(new BuildScopeError(scope, 'heartbeatRepo', repo))
|
|
200
|
+
},
|
|
201
|
+
releaseRepoLease(repo: string, _holder: string): Promise<void> {
|
|
202
|
+
return Promise.reject(new BuildScopeError(scope, 'releaseRepoLease', repo))
|
|
203
|
+
},
|
|
204
|
+
createSession(input): Promise<SessionRecord> {
|
|
205
|
+
return Promise.reject(new BuildScopeError(scope, 'createSession', input.repo))
|
|
206
|
+
},
|
|
207
|
+
getSession(id: string): Promise<SessionRecord | null> {
|
|
208
|
+
return Promise.reject(new BuildScopeError(scope, 'getSession', id))
|
|
209
|
+
},
|
|
210
|
+
listSessions(repo: string): Promise<SessionRecord[]> {
|
|
211
|
+
return Promise.reject(new BuildScopeError(scope, 'listSessions', repo))
|
|
212
|
+
},
|
|
213
|
+
appendSessionEvent<T extends SessionEventType>(
|
|
214
|
+
id: string,
|
|
215
|
+
_event: SessionEventWrite<T>,
|
|
216
|
+
): Promise<SessionEventEnvelope<T>> {
|
|
217
|
+
return Promise.reject(new BuildScopeError(scope, 'appendSessionEvent', id))
|
|
218
|
+
},
|
|
219
|
+
getSessionEvents(id: string, _sinceSeq?: number): Promise<SessionEvent[]> {
|
|
220
|
+
return Promise.reject(new BuildScopeError(scope, 'getSessionEvents', id))
|
|
221
|
+
},
|
|
222
|
+
appendSessionWithArtifacts<T extends SessionEventType>(
|
|
223
|
+
id: string,
|
|
224
|
+
_artifacts: ArtifactInput[],
|
|
225
|
+
_makeEvent: (deposited: SessionArtifactMeta[]) => SessionEventWrite<T>,
|
|
226
|
+
): Promise<{ event: SessionEventEnvelope<T>; artifacts: SessionArtifactMeta[] }> {
|
|
227
|
+
return Promise.reject(new BuildScopeError(scope, 'appendSessionWithArtifacts', id))
|
|
228
|
+
},
|
|
229
|
+
putSessionArtifact(id: string, _artifact: ArtifactInput): Promise<SessionArtifactMeta> {
|
|
230
|
+
return Promise.reject(new BuildScopeError(scope, 'putSessionArtifact', id))
|
|
231
|
+
},
|
|
232
|
+
getSessionArtifact(id: string, _kind: string, _rev?: number): Promise<null> {
|
|
233
|
+
return Promise.reject(new BuildScopeError(scope, 'getSessionArtifact', id))
|
|
234
|
+
},
|
|
235
|
+
listSessionArtifacts(id: string, _kind?: string): Promise<SessionArtifactMeta[]> {
|
|
236
|
+
return Promise.reject(new BuildScopeError(scope, 'listSessionArtifacts', id))
|
|
237
|
+
},
|
|
238
|
+
scopeSession(id: string): never {
|
|
239
|
+
throw new BuildScopeError(scope, 'scopeSession', id)
|
|
240
|
+
},
|
|
241
|
+
async createStream(candidate: StreamScope, label: string): Promise<StreamRecord> {
|
|
242
|
+
buildScope('createStream', candidate)
|
|
243
|
+
return store.createStream(candidate, label)
|
|
244
|
+
},
|
|
245
|
+
async appendStreamParts(streamId: string, parts: StreamPart[]): Promise<StreamChunk> {
|
|
246
|
+
await ownStream('appendStreamParts', streamId)
|
|
247
|
+
return store.appendStreamParts(streamId, parts)
|
|
248
|
+
},
|
|
249
|
+
async readStream(
|
|
250
|
+
streamId: string,
|
|
251
|
+
opts?: { since?: number; waitSeconds?: number },
|
|
252
|
+
): Promise<StreamRead> {
|
|
253
|
+
await ownStream('readStream', streamId)
|
|
254
|
+
return store.readStream(streamId, opts)
|
|
255
|
+
},
|
|
256
|
+
async closeStream(streamId: string, outcome: StreamOutcome): Promise<StreamRecord> {
|
|
257
|
+
await ownStream('closeStream', streamId)
|
|
258
|
+
return store.closeStream(streamId, outcome)
|
|
259
|
+
},
|
|
260
|
+
async getStream(streamId: string): Promise<StreamRecord | null> {
|
|
261
|
+
await ownStream('getStream', streamId)
|
|
262
|
+
return store.getStream(streamId)
|
|
263
|
+
},
|
|
264
|
+
async listStreams(candidate: StreamScope): Promise<StreamRecord[]> {
|
|
265
|
+
buildScope('listStreams', candidate)
|
|
266
|
+
return store.listStreams(candidate)
|
|
267
|
+
},
|
|
268
|
+
close(): Promise<void> {
|
|
269
|
+
return Promise.reject(new BuildScopeError(scope, 'close'))
|
|
270
|
+
},
|
|
271
|
+
}
|
|
272
|
+
}
|