@adhdev/daemon-core 0.9.82-rc.34 → 0.9.82-rc.340
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/dist/boot/daemon-lifecycle.d.ts +8 -0
- package/dist/boot/process-hardening.d.ts +50 -0
- package/dist/build-info.d.ts +37 -0
- package/dist/chat/source-machine.d.ts +166 -0
- package/dist/chat/source-resolver.d.ts +104 -0
- package/dist/chat/subscription-updates.d.ts +1 -0
- package/dist/cli-adapter-types.d.ts +46 -2
- package/dist/cli-adapters/cli-script-runner.d.ts +117 -0
- package/dist/cli-adapters/cli-state-engine.d.ts +198 -0
- package/dist/cli-adapters/provider-cli-adapter.d.ts +116 -64
- package/dist/cli-adapters/provider-cli-parse.d.ts +4 -0
- package/dist/cli-adapters/provider-cli-runtime.d.ts +34 -0
- package/dist/cli-adapters/provider-cli-shared.d.ts +53 -0
- package/dist/cli-adapters/raw-terminal-io.d.ts +37 -0
- package/dist/cli-adapters/resolve-executable.d.ts +14 -0
- package/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +6 -3
- package/dist/cli-adapters/terminal-backends/types.d.ts +10 -2
- package/dist/cli-adapters/terminal-screen.d.ts +4 -11
- package/dist/commands/cli-manager.d.ts +2 -1
- package/dist/commands/handler.d.ts +110 -0
- package/dist/commands/mesh-coordinator.d.ts +85 -1
- package/dist/commands/router.d.ts +308 -1
- package/dist/commands/upgrade-helper.d.ts +12 -0
- package/dist/config/chat-history.d.ts +9 -0
- package/dist/config/config.d.ts +5 -0
- package/dist/config/mesh-config.d.ts +77 -1
- package/dist/detection/ide-detector.d.ts +13 -0
- package/dist/detection/win32-ide-version.d.ts +37 -0
- package/dist/git/change-impact-config.d.ts +159 -0
- package/dist/git/git-commands.d.ts +11 -1
- package/dist/git/git-diff.d.ts +6 -0
- package/dist/git/git-executor.d.ts +11 -0
- package/dist/git/git-status.d.ts +23 -0
- package/dist/git/git-types.d.ts +2 -50
- package/dist/git/index.d.ts +2 -0
- package/dist/index.d.ts +52 -13
- package/dist/index.js +39439 -14533
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +39000 -14215
- package/dist/index.mjs.map +1 -1
- package/dist/installer.d.ts +1 -4
- package/dist/ipc/local-ipc-server.d.ts +91 -0
- package/dist/launch.d.ts +1 -1
- package/dist/logging/async-batch-writer.d.ts +10 -0
- package/dist/logging/log-redactor.d.ts +24 -0
- package/dist/logging/log-tail-reader.d.ts +46 -0
- package/dist/mesh/contracts.d.ts +164 -0
- package/dist/mesh/coordinator-prompt.d.ts +36 -0
- package/dist/mesh/coordinator-registry.d.ts +59 -0
- package/dist/mesh/mesh-active-work.d.ts +174 -0
- package/dist/mesh/mesh-delivery-policy.d.ts +131 -0
- package/dist/mesh/mesh-events-coordinator.d.ts +169 -0
- package/dist/mesh/mesh-events-pending.d.ts +45 -0
- package/dist/mesh/mesh-events-stale.d.ts +40 -0
- package/dist/mesh/mesh-events-utils.d.ts +66 -0
- package/dist/mesh/mesh-events.d.ts +6 -49
- package/dist/mesh/mesh-fast-forward.d.ts +81 -0
- package/dist/mesh/mesh-host-ownership.d.ts +9 -0
- package/dist/mesh/mesh-init.d.ts +86 -0
- package/dist/mesh/mesh-ledger-reconciliation.d.ts +23 -3
- package/dist/mesh/mesh-ledger.d.ts +77 -1
- package/dist/mesh/mesh-missions.d.ts +116 -0
- package/dist/mesh/mesh-reconcile-loop.d.ts +7 -0
- package/dist/mesh/mesh-refine-batch.d.ts +68 -0
- package/dist/mesh/mesh-refine-status.d.ts +62 -0
- package/dist/mesh/mesh-review-inbox.d.ts +90 -0
- package/dist/mesh/mesh-routing.d.ts +70 -0
- package/dist/mesh/mesh-runtime-store.d.ts +418 -0
- package/dist/mesh/mesh-task-stats.d.ts +49 -0
- package/dist/mesh/mesh-unresolved-forward-outbox.d.ts +30 -0
- package/dist/mesh/mesh-work-queue.d.ts +208 -5
- package/dist/mesh/preview-freshness.d.ts +18 -0
- package/dist/mesh/refine-config.d.ts +216 -0
- package/dist/mesh/worktree-bootstrap-config.d.ts +135 -0
- package/dist/providers/acp-provider-instance.d.ts +2 -0
- package/dist/providers/approval-utils.d.ts +13 -0
- package/dist/providers/chat-message-normalization.d.ts +12 -0
- package/dist/providers/cli-provider-instance.d.ts +76 -3
- package/dist/providers/contracts.d.ts +139 -6
- package/dist/providers/external-sources.d.ts +71 -0
- package/dist/providers/native-history/antigravity-cli-transcript.d.ts +100 -0
- package/dist/providers/native-history/claude-cli-transcript.d.ts +70 -0
- package/dist/providers/native-history/codex-cli-transcript.d.ts +73 -0
- package/dist/providers/native-history/dispatcher.d.ts +27 -0
- package/dist/providers/native-history/hermes-cli-transcript.d.ts +30 -0
- package/dist/providers/native-history/index.d.ts +13 -0
- package/dist/providers/provider-instance-manager.d.ts +13 -0
- package/dist/providers/provider-instance.d.ts +13 -1
- package/dist/providers/provider-loader.d.ts +26 -4
- package/dist/providers/provider-trust.d.ts +31 -0
- package/dist/providers/read-chat-contract.d.ts +29 -0
- package/dist/providers/sdk/v1/builders/acp/detect-status.d.ts +68 -0
- package/dist/providers/sdk/v1/builders/cli/detect-status.d.ts +85 -0
- package/dist/providers/sdk/v1/builders/cli/parse-approval-squash.d.ts +59 -0
- package/dist/providers/sdk/v1/builders/cli/parse-approval.d.ts +65 -0
- package/dist/providers/sdk/v1/builders/cli/parse-session.d.ts +91 -0
- package/dist/providers/sdk/v1/builders/cli/visible-region.d.ts +42 -0
- package/dist/providers/sdk/v1/fixture-tooling/format.d.ts +126 -0
- package/dist/providers/sdk/v1/fixture-tooling/index.d.ts +8 -0
- package/dist/providers/sdk/v1/fixture-tooling/replay.d.ts +38 -0
- package/dist/providers/sdk/v1/index.d.ts +30 -0
- package/dist/providers/sdk/v1/sandbox/README-design.d.ts +193 -0
- package/dist/providers/sdk/v1/sandbox/require-whitelist.d.ts +74 -0
- package/dist/providers/sdk/v1/sandbox/script-runner.d.ts +98 -0
- package/dist/providers/sdk/v1/types/cli/index.d.ts +277 -0
- package/dist/providers/sdk/v1/types/common/index.d.ts +203 -0
- package/dist/providers/sdk/v1/validators/index.d.ts +5 -0
- package/dist/providers/sdk/v1/validators/manifest.d.ts +40 -0
- package/dist/providers/sdk/v1/validators/taint.d.ts +52 -0
- package/dist/providers/spec/adapter.d.ts +69 -0
- package/dist/providers/spec/cli-adapter.d.ts +217 -0
- package/dist/providers/spec/evaluator.d.ts +23 -0
- package/dist/providers/spec/fsm-driver.d.ts +306 -0
- package/dist/providers/spec/fsm-evaluator.d.ts +72 -0
- package/dist/providers/spec/fsm-loader.d.ts +14 -0
- package/dist/providers/spec/fsm-types.d.ts +144 -0
- package/dist/providers/spec/native-history-executor.d.ts +41 -0
- package/dist/providers/spec/pre-launch-trust.d.ts +16 -0
- package/dist/providers/spec/route.d.ts +4 -0
- package/dist/providers/spec/types.d.ts +180 -0
- package/dist/providers/status-monitor.d.ts +7 -7
- package/dist/providers/transcript-v2.d.ts +176 -0
- package/dist/providers/types/interactive-prompt.d.ts +84 -0
- package/dist/providers/working-dir.d.ts +17 -0
- package/dist/repo-mesh-types.d.ts +295 -13
- package/dist/sessions/registry.d.ts +6 -0
- package/dist/shared-types-extra.d.ts +2 -4
- package/dist/shared-types.d.ts +59 -2
- package/dist/status/normalize.d.ts +1 -1
- package/dist/status/normalize.js +1 -0
- package/dist/status/normalize.js.map +1 -1
- package/dist/status/normalize.mjs +1 -0
- package/dist/status/normalize.mjs.map +1 -1
- package/dist/status/reporter.d.ts +2 -0
- package/dist/status/snapshot.d.ts +26 -0
- package/dist/system/load-better-sqlite3.d.ts +21 -0
- package/dist/types.d.ts +5 -0
- package/package.json +7 -3
- package/src/agent-stream/poller.ts +2 -3
- package/src/agent-stream/provider-adapter.ts +1 -1
- package/src/boot/daemon-lifecycle.ts +55 -12
- package/src/boot/process-hardening.ts +89 -0
- package/src/build-info.ts +73 -0
- package/src/chat/source-machine.ts +534 -0
- package/src/chat/source-resolver.ts +0 -0
- package/src/chat/subscription-updates.ts +20 -1
- package/src/cli-adapter-types.d.ts +1 -0
- package/src/cli-adapter-types.ts +47 -2
- package/src/cli-adapters/cli-script-runner.ts +421 -0
- package/src/cli-adapters/cli-state-engine.ts +1215 -0
- package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
- package/src/cli-adapters/provider-cli-adapter.ts +774 -1141
- package/src/cli-adapters/provider-cli-parse.d.ts +1 -0
- package/src/cli-adapters/provider-cli-parse.ts +13 -0
- package/src/cli-adapters/provider-cli-runtime.ts +56 -7
- package/src/cli-adapters/provider-cli-shared.d.ts +4 -0
- package/src/cli-adapters/provider-cli-shared.ts +100 -11
- package/src/cli-adapters/pty-transport.ts +2 -1
- package/src/cli-adapters/raw-terminal-io.ts +252 -0
- package/src/cli-adapters/resolve-executable.ts +90 -0
- package/src/cli-adapters/session-host-transport.ts +2 -1
- package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +53 -29
- package/src/cli-adapters/terminal-backends/types.ts +10 -3
- package/src/cli-adapters/terminal-screen.ts +16 -81
- package/src/commands/chat-commands.ts +1823 -62
- package/src/commands/cli-manager.ts +286 -14
- package/src/commands/handler.ts +809 -2
- package/src/commands/mesh-coordinator.ts +332 -122
- package/src/commands/router.ts +7433 -1317
- package/src/commands/stream-commands.ts +8 -0
- package/src/commands/upgrade-helper.ts +81 -30
- package/src/config/chat-history.ts +483 -24
- package/src/config/config.ts +12 -0
- package/src/config/mesh-config.ts +388 -6
- package/src/config/recent-activity.ts +8 -2
- package/src/daemon/dev-auto-implement.ts +3 -2
- package/src/daemon/dev-cli-debug.ts +10 -1
- package/src/detection/cli-detector.ts +28 -9
- package/src/detection/ide-detector.ts +55 -16
- package/src/detection/win32-ide-version.ts +106 -0
- package/src/git/change-impact-config.ts +354 -0
- package/src/git/git-commands.ts +55 -14
- package/src/git/git-diff.ts +53 -0
- package/src/git/git-executor.ts +12 -0
- package/src/git/git-status.ts +574 -43
- package/src/git/git-types.ts +14 -62
- package/src/git/git-worktree.ts +8 -1
- package/src/git/index.ts +16 -0
- package/src/index.ts +146 -12
- package/src/installer.d.ts +1 -1
- package/src/installer.ts +8 -6
- package/src/ipc/local-ipc-server.ts +278 -0
- package/src/launch.d.ts +1 -1
- package/src/launch.ts +37 -28
- package/src/logging/async-batch-writer.ts +55 -0
- package/src/logging/log-redactor.ts +100 -0
- package/src/logging/log-tail-reader.ts +220 -0
- package/src/logging/logger.ts +2 -1
- package/src/mesh/contracts.ts +329 -0
- package/src/mesh/coordinator-prompt.ts +234 -31
- package/src/mesh/coordinator-registry.ts +121 -0
- package/src/mesh/mesh-active-work.ts +623 -0
- package/src/mesh/mesh-delivery-policy.ts +315 -0
- package/src/mesh/mesh-events-coordinator.ts +2144 -0
- package/src/mesh/mesh-events-pending.ts +508 -0
- package/src/mesh/mesh-events-stale.ts +290 -0
- package/src/mesh/mesh-events-utils.ts +300 -0
- package/src/mesh/mesh-events.ts +30 -1035
- package/src/mesh/mesh-fast-forward.ts +839 -0
- package/src/mesh/mesh-host-ownership.ts +73 -0
- package/src/mesh/mesh-init.ts +260 -0
- package/src/mesh/mesh-ledger-reconciliation.ts +12 -5
- package/src/mesh/mesh-ledger.ts +589 -102
- package/src/mesh/mesh-missions.ts +248 -0
- package/src/mesh/mesh-reconcile-loop.ts +822 -0
- package/src/mesh/mesh-refine-batch.ts +197 -0
- package/src/mesh/mesh-refine-status.ts +231 -0
- package/src/mesh/mesh-review-inbox.ts +307 -0
- package/src/mesh/mesh-routing.ts +291 -0
- package/src/mesh/mesh-runtime-store.ts +1626 -0
- package/src/mesh/mesh-task-stats.ts +154 -0
- package/src/mesh/mesh-unresolved-forward-outbox.ts +185 -0
- package/src/mesh/mesh-work-queue.ts +888 -141
- package/src/mesh/preview-freshness.ts +118 -0
- package/src/mesh/refine-config.ts +423 -0
- package/src/mesh/worktree-bootstrap-config.ts +331 -0
- package/src/providers/acp-provider-instance.ts +25 -9
- package/src/providers/approval-utils.d.ts +4 -0
- package/src/providers/approval-utils.ts +47 -5
- package/src/providers/chat-message-normalization.ts +45 -5
- package/src/providers/cli-provider-instance.ts +1038 -99
- package/src/providers/contracts.d.ts +55 -0
- package/src/providers/contracts.ts +150 -6
- package/src/providers/extension-provider-instance.ts +12 -7
- package/src/providers/external-sources.ts +218 -0
- package/src/providers/ide-provider-instance.ts +35 -12
- package/src/providers/native-history/antigravity-cli-transcript.ts +643 -0
- package/src/providers/native-history/claude-cli-transcript.ts +396 -0
- package/src/providers/native-history/codex-cli-transcript.ts +479 -0
- package/src/providers/native-history/dispatcher.ts +340 -0
- package/src/providers/native-history/hermes-cli-transcript.ts +230 -0
- package/src/providers/native-history/index.ts +30 -0
- package/src/providers/provider-instance-manager.ts +30 -0
- package/src/providers/provider-instance.ts +10 -1
- package/src/providers/provider-loader.ts +670 -50
- package/src/providers/provider-schema.ts +87 -14
- package/src/providers/provider-trust.ts +114 -0
- package/src/providers/read-chat-contract.ts +76 -16
- package/src/providers/sdk/README.md +49 -0
- package/src/providers/sdk/v1/builders/acp/detect-status.ts +144 -0
- package/src/providers/sdk/v1/builders/cli/detect-status.ts +262 -0
- package/src/providers/sdk/v1/builders/cli/parse-approval-squash.ts +158 -0
- package/src/providers/sdk/v1/builders/cli/parse-approval.ts +250 -0
- package/src/providers/sdk/v1/builders/cli/parse-session.ts +276 -0
- package/src/providers/sdk/v1/builders/cli/visible-region.ts +143 -0
- package/src/providers/sdk/v1/fixture-tooling/format.ts +130 -0
- package/src/providers/sdk/v1/fixture-tooling/index.ts +22 -0
- package/src/providers/sdk/v1/fixture-tooling/replay.ts +352 -0
- package/src/providers/sdk/v1/index.ts +152 -0
- package/src/providers/sdk/v1/sandbox/README-design.ts +195 -0
- package/src/providers/sdk/v1/sandbox/require-whitelist.ts +472 -0
- package/src/providers/sdk/v1/sandbox/script-runner.ts +150 -0
- package/src/providers/sdk/v1/schemas/cli/provider.schema.json +504 -0
- package/src/providers/sdk/v1/schemas/primitives/acp-session-protocol-v1.json +131 -0
- package/src/providers/sdk/v1/schemas/primitives/native-history-codex-rollout-v1.json +66 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-approval-squash-v1.json +91 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-assistant-block-v1.json +91 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-cue-ordering-v1.json +47 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-dispatch-order-v1.json +32 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-footer-chrome-v1.json +42 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-index-finder-v1.json +27 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-modal-v1.json +125 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-prompt-marker-v1.json +45 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-session-id-extraction-v1.json +46 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-settled-prompt-v1.json +71 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-spinner-v1.json +83 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-transcript-pty-v1.json +83 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-visible-region-v1.json +57 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-welcome-screen-v1.json +35 -0
- package/src/providers/sdk/v1/types/cli/index.ts +365 -0
- package/src/providers/sdk/v1/types/common/index.ts +229 -0
- package/src/providers/sdk/v1/validators/index.ts +19 -0
- package/src/providers/sdk/v1/validators/manifest.ts +110 -0
- package/src/providers/sdk/v1/validators/taint.ts +309 -0
- package/src/providers/spec/adapter.ts +168 -0
- package/src/providers/spec/cli-adapter.ts +986 -0
- package/src/providers/spec/evaluator.ts +345 -0
- package/src/providers/spec/fsm-driver.ts +993 -0
- package/src/providers/spec/fsm-evaluator.ts +255 -0
- package/src/providers/spec/fsm-loader.ts +120 -0
- package/src/providers/spec/fsm-types.ts +238 -0
- package/src/providers/spec/native-history-executor.ts +1136 -0
- package/src/providers/spec/pre-launch-trust.ts +104 -0
- package/src/providers/spec/route.ts +51 -0
- package/src/providers/spec/types.ts +226 -0
- package/src/providers/status-monitor.d.ts +7 -7
- package/src/providers/status-monitor.ts +37 -22
- package/src/providers/transcript-v2.ts +567 -0
- package/src/providers/types/interactive-prompt.ts +536 -0
- package/src/providers/version-archive.ts +64 -24
- package/src/providers/working-dir.ts +23 -0
- package/src/repo-mesh-types.ts +378 -14
- package/src/sessions/registry.ts +6 -0
- package/src/shared-types-extra.ts +2 -4
- package/src/shared-types.d.ts +8 -0
- package/src/shared-types.ts +64 -1
- package/src/status/builders.ts +26 -6
- package/src/status/normalize.ts +2 -0
- package/src/status/reporter.ts +19 -1
- package/src/status/snapshot.ts +95 -26
- package/src/system/host-memory.ts +29 -12
- package/src/system/load-better-sqlite3.ts +68 -0
- package/src/types.ts +5 -0
- package/dist/cli-adapters/terminal-backends/xterm-backend.d.ts +0 -17
- package/dist/mesh/mesh-sync.d.ts +0 -53
- package/src/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +0 -16
- package/src/cli-adapters/terminal-backends/xterm-backend.ts +0 -97
- package/src/mesh/mesh-sync.ts +0 -111
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* buildParseSessionFromTui — synthesize a parseSession function from the
|
|
3
|
+
* manifest tui block alone.
|
|
4
|
+
*
|
|
5
|
+
* Composition:
|
|
6
|
+
* 1. detectStatus from tui.spinner/modal/settledPrompt/dispatchOrder
|
|
7
|
+
* (delegated to buildDetectStatusFromTui)
|
|
8
|
+
* 2. parseApproval from tui.modal (delegated to buildParseApprovalFromTui)
|
|
9
|
+
* 3. message extraction from tui.transcriptPty (this file)
|
|
10
|
+
*
|
|
11
|
+
* The result has the same shape as the legacy parse_output:
|
|
12
|
+
* { status, messages, activeModal, transcriptAuthority?, coverage?, providerSessionId? }
|
|
13
|
+
*
|
|
14
|
+
* Identity stamping (providerUnitKey, bubbleId, sequence, bubbleState) is
|
|
15
|
+
* applied by the caller, mirroring _shared/parse_session.js. We export the
|
|
16
|
+
* stamper as `normalizeMessageIdentity` for reuse.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { buildDetectStatusFromTui, type DetectStatusTuiSpec } from './detect-status.js'
|
|
20
|
+
import { buildParseApprovalFromTui, type ModalTuiSpec } from './parse-approval.js'
|
|
21
|
+
import * as crypto from 'node:crypto'
|
|
22
|
+
|
|
23
|
+
// ─── Schema types ────────────────────────────────
|
|
24
|
+
|
|
25
|
+
export interface PrefixSpec {
|
|
26
|
+
regex: string
|
|
27
|
+
flags?: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface ToolPrefixSpec extends PrefixSpec {
|
|
31
|
+
skip?: boolean
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface ChromePatternSpec {
|
|
35
|
+
regex: string
|
|
36
|
+
flags?: string
|
|
37
|
+
label?: string
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface TranscriptPtySpec {
|
|
41
|
+
$schema?: 'adhdev:tui/transcript-pty@1'
|
|
42
|
+
assistantPrefix: PrefixSpec
|
|
43
|
+
userPrefix?: PrefixSpec
|
|
44
|
+
toolPrefix?: ToolPrefixSpec
|
|
45
|
+
continuationLine?: { indented?: boolean }
|
|
46
|
+
chromePatterns?: ChromePatternSpec[]
|
|
47
|
+
stripLeadingChrome?: boolean
|
|
48
|
+
scope?: 'screen' | 'buffer' | 'tail'
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface SessionIdExtractionSpec {
|
|
52
|
+
$schema?: 'adhdev:tui/session-id-extraction@1'
|
|
53
|
+
regex: string
|
|
54
|
+
flags?: string
|
|
55
|
+
scope?: 'screen' | 'tail' | 'buffer'
|
|
56
|
+
label?: string
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface ParseSessionTuiSpec {
|
|
60
|
+
spinner?: any
|
|
61
|
+
settledPrompt?: any
|
|
62
|
+
modal?: ModalTuiSpec
|
|
63
|
+
dispatchOrder?: any
|
|
64
|
+
transcriptPty: TranscriptPtySpec
|
|
65
|
+
sessionIdExtraction?: SessionIdExtractionSpec
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ─── Output shape ────────────────────────────────
|
|
69
|
+
|
|
70
|
+
export interface SynthesizedMessage {
|
|
71
|
+
role: 'user' | 'assistant'
|
|
72
|
+
kind?: 'standard' | 'tool'
|
|
73
|
+
content: string
|
|
74
|
+
receivedAt?: number
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface SynthesizedSession {
|
|
78
|
+
status: string | null
|
|
79
|
+
messages: SynthesizedMessage[]
|
|
80
|
+
activeModal: { message: string; buttons: string[] } | null
|
|
81
|
+
modal: { message: string; buttons: string[] } | null
|
|
82
|
+
parsedStatus: string | null
|
|
83
|
+
transcriptAuthority?: 'provider' | 'daemon'
|
|
84
|
+
coverage?: 'full' | 'tail' | 'current-turn'
|
|
85
|
+
providerSessionId?: string
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ─── ANSI / line helpers ─────────────────────────
|
|
89
|
+
|
|
90
|
+
const ANSI_RE = /\x1b\[[0-?]*[ -/]*[@-~]/g
|
|
91
|
+
const OSC_RE = /\x1b\][^\x07\x1b\n]*(?:\x07|\x1b\\|(?=\n|$))/g
|
|
92
|
+
|
|
93
|
+
function stripAnsi(text: string): string {
|
|
94
|
+
return String(text || '')
|
|
95
|
+
.replace(/\x1b\[(\d*)C/g, (_m, n) => ' '.repeat(Math.max(1, Number(n) || 1)))
|
|
96
|
+
.replace(/\x1b\[\d*D/g, '')
|
|
97
|
+
.replace(ANSI_RE, '')
|
|
98
|
+
.replace(OSC_RE, '')
|
|
99
|
+
.replace(/\x1b[P^_X][\s\S]*?(?:\x07|\x1b\\)/g, '')
|
|
100
|
+
.replace(/\x1b(?:[@-Z\\-_])/g, '')
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function splitLines(text: string): string[] {
|
|
104
|
+
return stripAnsi(text)
|
|
105
|
+
.replace(//g, '')
|
|
106
|
+
.split(/\r?\n/)
|
|
107
|
+
.map(l => l.replace(/\s+$/, ''))
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function pickInputText(input: any, scope: TranscriptPtySpec['scope']): string {
|
|
111
|
+
if (!input) return ''
|
|
112
|
+
if (scope === 'screen') return String(input.screenText || input.screen?.text || '')
|
|
113
|
+
if (scope === 'tail') return String(input.tail || input.recentBuffer || input.buffer || '')
|
|
114
|
+
return String(input.buffer || input.rawBuffer || input.screenText || '')
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// ─── Identity stamping (mirrors _shared/parse_session.js) ─────
|
|
118
|
+
|
|
119
|
+
function stableHash(value: string): string {
|
|
120
|
+
return crypto.createHash('sha1').update(String(value || '')).digest('hex').slice(0, 12)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function normalizeMessageIdentity<T extends { role?: string; kind?: string; content?: string }>(
|
|
124
|
+
messages: T[],
|
|
125
|
+
status: string,
|
|
126
|
+
): Array<T & {
|
|
127
|
+
providerUnitKey: string
|
|
128
|
+
bubbleId: string
|
|
129
|
+
sequence: number
|
|
130
|
+
_turnKey: string
|
|
131
|
+
bubbleState: 'streaming' | 'final'
|
|
132
|
+
}> {
|
|
133
|
+
const list = Array.isArray(messages) ? messages : []
|
|
134
|
+
let turnIndex = -1
|
|
135
|
+
return list.map((message, index) => {
|
|
136
|
+
const role = message?.role || 'assistant'
|
|
137
|
+
const kind = message?.kind || 'standard'
|
|
138
|
+
const content = typeof message?.content === 'string' ? message.content : ''
|
|
139
|
+
if (role === 'user' || turnIndex < 0) turnIndex += 1
|
|
140
|
+
const seed = [role, kind, '', index, content].join('\n')
|
|
141
|
+
const providerUnitKey = `v2-pty:${role}:${kind}:${index}:${stableHash(seed)}`
|
|
142
|
+
const bubbleId = `bubble:${providerUnitKey}`
|
|
143
|
+
const turnKey = `turn:${turnIndex}`
|
|
144
|
+
const isStreamingTail = status === 'generating' && role === 'assistant' && index === list.length - 1
|
|
145
|
+
return {
|
|
146
|
+
...message,
|
|
147
|
+
providerUnitKey,
|
|
148
|
+
bubbleId,
|
|
149
|
+
sequence: index,
|
|
150
|
+
_turnKey: turnKey,
|
|
151
|
+
bubbleState: isStreamingTail ? 'streaming' as const : 'final' as const,
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ─── Main builder ────────────────────────────────
|
|
157
|
+
|
|
158
|
+
export function buildParseSessionFromTui(spec: ParseSessionTuiSpec): (input: any) => SynthesizedSession {
|
|
159
|
+
if (!spec.transcriptPty) {
|
|
160
|
+
throw new Error('buildParseSessionFromTui: spec.transcriptPty is required')
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Compile regexes once
|
|
164
|
+
const assistantRe = new RegExp(spec.transcriptPty.assistantPrefix.regex, spec.transcriptPty.assistantPrefix.flags || '')
|
|
165
|
+
const userRe = spec.transcriptPty.userPrefix
|
|
166
|
+
? new RegExp(spec.transcriptPty.userPrefix.regex, spec.transcriptPty.userPrefix.flags || '')
|
|
167
|
+
: null
|
|
168
|
+
const toolRe = spec.transcriptPty.toolPrefix
|
|
169
|
+
? new RegExp(spec.transcriptPty.toolPrefix.regex, spec.transcriptPty.toolPrefix.flags || '')
|
|
170
|
+
: null
|
|
171
|
+
const toolSkip = spec.transcriptPty.toolPrefix?.skip ?? false
|
|
172
|
+
const chromeRes = (spec.transcriptPty.chromePatterns || []).map(p =>
|
|
173
|
+
new RegExp(p.regex, p.flags || ''))
|
|
174
|
+
const requireIndentForContinuation = spec.transcriptPty.continuationLine?.indented ?? false
|
|
175
|
+
const stripLeadingChrome = spec.transcriptPty.stripLeadingChrome ?? true
|
|
176
|
+
const scope = spec.transcriptPty.scope ?? 'buffer'
|
|
177
|
+
|
|
178
|
+
// Compose detect + approval helpers if their inputs are present.
|
|
179
|
+
const detectStatus = (spec.spinner || spec.settledPrompt || spec.modal || spec.dispatchOrder)
|
|
180
|
+
? buildDetectStatusFromTui({
|
|
181
|
+
spinner: spec.spinner,
|
|
182
|
+
settledPrompt: spec.settledPrompt,
|
|
183
|
+
modal: spec.modal,
|
|
184
|
+
dispatchOrder: spec.dispatchOrder,
|
|
185
|
+
})
|
|
186
|
+
: () => null
|
|
187
|
+
const parseApproval = spec.modal ? buildParseApprovalFromTui(spec.modal) : () => null
|
|
188
|
+
|
|
189
|
+
// Optional session-id extraction (tui/session-id-extraction@1). Compile once
|
|
190
|
+
// so each parseSession call is a single regex.exec on the chosen scope.
|
|
191
|
+
const sessionIdRe = spec.sessionIdExtraction
|
|
192
|
+
? new RegExp(
|
|
193
|
+
spec.sessionIdExtraction.regex,
|
|
194
|
+
spec.sessionIdExtraction.flags ?? 'i',
|
|
195
|
+
)
|
|
196
|
+
: null
|
|
197
|
+
const sessionIdScope: TranscriptPtySpec['scope'] = spec.sessionIdExtraction?.scope ?? 'tail'
|
|
198
|
+
|
|
199
|
+
return function parseSession(input: any): SynthesizedSession {
|
|
200
|
+
// status + modal first
|
|
201
|
+
const status = detectStatus(input as any) ?? 'idle'
|
|
202
|
+
const modal = parseApproval(input as any)
|
|
203
|
+
|
|
204
|
+
const text = pickInputText(input, scope)
|
|
205
|
+
const lines = splitLines(text)
|
|
206
|
+
|
|
207
|
+
const messages: SynthesizedMessage[] = []
|
|
208
|
+
let seenFirstRoleLine = !stripLeadingChrome
|
|
209
|
+
|
|
210
|
+
for (const raw of lines) {
|
|
211
|
+
const line = raw
|
|
212
|
+
if (line.trim() === '') {
|
|
213
|
+
// Blank line: ends streaming continuation but doesn't add a message.
|
|
214
|
+
continue
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Chrome filter
|
|
218
|
+
let isChrome = false
|
|
219
|
+
for (const cre of chromeRes) {
|
|
220
|
+
if (cre.test(line)) { isChrome = true; break }
|
|
221
|
+
}
|
|
222
|
+
if (isChrome) continue
|
|
223
|
+
|
|
224
|
+
// Role detection
|
|
225
|
+
const userMatch = userRe ? line.match(userRe) : null
|
|
226
|
+
const toolMatch = toolRe ? line.match(toolRe) : null
|
|
227
|
+
const assistMatch = line.match(assistantRe)
|
|
228
|
+
|
|
229
|
+
if (userMatch) {
|
|
230
|
+
seenFirstRoleLine = true
|
|
231
|
+
const content = (userMatch[1] ?? userMatch[0]).trim()
|
|
232
|
+
if (content) messages.push({ role: 'user', kind: 'standard', content })
|
|
233
|
+
continue
|
|
234
|
+
}
|
|
235
|
+
if (toolMatch) {
|
|
236
|
+
seenFirstRoleLine = true
|
|
237
|
+
if (toolSkip) continue
|
|
238
|
+
const content = (toolMatch[1] ?? toolMatch[0]).trim()
|
|
239
|
+
if (content) messages.push({ role: 'assistant', kind: 'tool', content })
|
|
240
|
+
continue
|
|
241
|
+
}
|
|
242
|
+
if (assistMatch) {
|
|
243
|
+
seenFirstRoleLine = true
|
|
244
|
+
const content = (assistMatch[1] ?? assistMatch[0]).trim()
|
|
245
|
+
if (content) messages.push({ role: 'assistant', kind: 'standard', content })
|
|
246
|
+
continue
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (!seenFirstRoleLine) continue
|
|
250
|
+
|
|
251
|
+
// Continuation rule
|
|
252
|
+
if (requireIndentForContinuation && !/^\s/.test(line)) continue
|
|
253
|
+
const last = messages[messages.length - 1]
|
|
254
|
+
if (!last) continue
|
|
255
|
+
const cont = line.replace(/^\s+/, '')
|
|
256
|
+
if (cont) last.content = last.content ? `${last.content}\n${cont}` : cont
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const result: SynthesizedSession = {
|
|
260
|
+
status,
|
|
261
|
+
messages,
|
|
262
|
+
activeModal: modal,
|
|
263
|
+
modal,
|
|
264
|
+
parsedStatus: status,
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (sessionIdRe) {
|
|
268
|
+
const haystack = stripAnsi(pickInputText(input, sessionIdScope))
|
|
269
|
+
const match = haystack.match(sessionIdRe)
|
|
270
|
+
const captured = match?.[1]?.trim()
|
|
271
|
+
if (captured) result.providerSessionId = captured
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return result
|
|
275
|
+
}
|
|
276
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* applyVisibleRegion
|
|
3
|
+
*
|
|
4
|
+
* Scopes the raw terminal text to the "visible region" declared by a
|
|
5
|
+
* `tui/visible-region@1` spec before handing it to detect-status and
|
|
6
|
+
* parse-approval matchers.
|
|
7
|
+
*
|
|
8
|
+
* Scope semantics:
|
|
9
|
+
* screen → full text unchanged (daemon already passes rendered screen)
|
|
10
|
+
* buffer → full text unchanged
|
|
11
|
+
* tail → last `tailChars` characters (default 4000)
|
|
12
|
+
* between-anchors → text between most recent (or first) top/bottom anchor
|
|
13
|
+
* regex matches; falls back to full text if anchors not found
|
|
14
|
+
*
|
|
15
|
+
* selectAnchor:
|
|
16
|
+
* "last" → use the LAST occurrence of the top anchor — useful for providers
|
|
17
|
+
* like Antigravity that redraw a separator + prompt on every turn;
|
|
18
|
+
* this excludes all scrollback above the current session frame.
|
|
19
|
+
* "first" → use the FIRST occurrence (default per schema).
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
// ─── Spec shape (mirrors tui-visible-region-v1.json) ───────────────────
|
|
23
|
+
|
|
24
|
+
interface AnchorPatternSpec {
|
|
25
|
+
pattern: string;
|
|
26
|
+
flags?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface AnchorsSpec {
|
|
30
|
+
top?: AnchorPatternSpec;
|
|
31
|
+
bottom?: AnchorPatternSpec;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface VisibleRegionSpec {
|
|
35
|
+
$schema?: 'adhdev:tui/visible-region@1';
|
|
36
|
+
scope: 'screen' | 'tail' | 'buffer' | 'between-anchors';
|
|
37
|
+
tailChars?: number;
|
|
38
|
+
anchors?: AnchorsSpec;
|
|
39
|
+
selectAnchor?: 'first' | 'last';
|
|
40
|
+
stripCues?: string[];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ─── Helpers ───────────────────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
function compile(re: string, flags?: string): RegExp {
|
|
46
|
+
try {
|
|
47
|
+
return new RegExp(re, flags ?? '');
|
|
48
|
+
} catch (e) {
|
|
49
|
+
throw new Error(`Invalid visible-region anchor regex /${re}/${flags ?? ''}: ${(e as Error).message}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Find all non-overlapping matches of `re` in `text`.
|
|
55
|
+
* Returns them in order of occurrence (earliest first).
|
|
56
|
+
*/
|
|
57
|
+
function findAllMatches(re: RegExp, text: string): RegExpExecArray[] {
|
|
58
|
+
const results: RegExpExecArray[] = [];
|
|
59
|
+
// Operate on a non-global copy with sticky-safe iteration to avoid
|
|
60
|
+
// mutating the caller's RegExp state.
|
|
61
|
+
const iter = new RegExp(re.source, re.flags.replace('g', '') + 'g');
|
|
62
|
+
let m: RegExpExecArray | null;
|
|
63
|
+
while ((m = iter.exec(text)) !== null) {
|
|
64
|
+
results.push(m);
|
|
65
|
+
// Advance past zero-width matches to prevent infinite loop.
|
|
66
|
+
if (m[0].length === 0) iter.lastIndex += 1;
|
|
67
|
+
}
|
|
68
|
+
return results;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ─── Public API ────────────────────────────────────────────────────────
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Apply the visible-region spec to `text` and return the scoped substring.
|
|
75
|
+
* Never throws on missing anchors — falls back to the full text instead.
|
|
76
|
+
*/
|
|
77
|
+
export function applyVisibleRegion(spec: VisibleRegionSpec, text: string): string {
|
|
78
|
+
if (!text) return text;
|
|
79
|
+
|
|
80
|
+
switch (spec.scope) {
|
|
81
|
+
case 'screen':
|
|
82
|
+
case 'buffer':
|
|
83
|
+
return text;
|
|
84
|
+
|
|
85
|
+
case 'tail': {
|
|
86
|
+
const limit = spec.tailChars ?? 4000;
|
|
87
|
+
if (text.length <= limit) return text;
|
|
88
|
+
return text.slice(-limit);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
case 'between-anchors': {
|
|
92
|
+
const anchors = spec.anchors;
|
|
93
|
+
if (!anchors?.top && !anchors?.bottom) return text;
|
|
94
|
+
|
|
95
|
+
const selectLast = (spec.selectAnchor ?? 'first') === 'last';
|
|
96
|
+
|
|
97
|
+
// ── Top anchor ──
|
|
98
|
+
let topEnd = 0; // default: start of text
|
|
99
|
+
if (anchors.top) {
|
|
100
|
+
const topRe = compile(anchors.top.pattern, anchors.top.flags);
|
|
101
|
+
const topMatches = findAllMatches(topRe, text);
|
|
102
|
+
if (topMatches.length === 0) {
|
|
103
|
+
// Top anchor not found — fall back to full text.
|
|
104
|
+
return text;
|
|
105
|
+
}
|
|
106
|
+
const chosen = selectLast
|
|
107
|
+
? topMatches[topMatches.length - 1]
|
|
108
|
+
: topMatches[0];
|
|
109
|
+
// Region starts just after the end of the top anchor match.
|
|
110
|
+
topEnd = chosen.index + chosen[0].length;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// ── Bottom anchor ──
|
|
114
|
+
let bottomStart = text.length; // default: end of text
|
|
115
|
+
if (anchors.bottom) {
|
|
116
|
+
const bottomRe = compile(anchors.bottom.pattern, anchors.bottom.flags);
|
|
117
|
+
// Only search the portion that comes AFTER the top anchor end so we
|
|
118
|
+
// always pick the immediately-following bottom anchor.
|
|
119
|
+
const searchFrom = topEnd;
|
|
120
|
+
const suffix = text.slice(searchFrom);
|
|
121
|
+
const bottomMatches = findAllMatches(bottomRe, suffix);
|
|
122
|
+
if (bottomMatches.length === 0) {
|
|
123
|
+
// Bottom anchor not found — fall back to full text.
|
|
124
|
+
return text;
|
|
125
|
+
}
|
|
126
|
+
const chosen = selectLast
|
|
127
|
+
? bottomMatches[bottomMatches.length - 1]
|
|
128
|
+
: bottomMatches[0];
|
|
129
|
+
bottomStart = searchFrom + chosen.index;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (topEnd >= bottomStart) {
|
|
133
|
+
// Degenerate / overlapping anchors — fall back to full text.
|
|
134
|
+
return text;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return text.slice(topEnd, bottomStart);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
default:
|
|
141
|
+
return text;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider fixture format — v1.
|
|
3
|
+
*
|
|
4
|
+
* A fixture is two files committed alongside a provider:
|
|
5
|
+
*
|
|
6
|
+
* fixtures/<scenario>.pty — raw PTY byte capture (binary or text)
|
|
7
|
+
* fixtures/<scenario>.expected.json — expected handler outputs at one
|
|
8
|
+
* or more anchor frames
|
|
9
|
+
*
|
|
10
|
+
* Scenarios cover one concrete agent behaviour: cold start, prompt sent,
|
|
11
|
+
* generating with tool call, approval modal, idle after assistant complete,
|
|
12
|
+
* etc.
|
|
13
|
+
*
|
|
14
|
+
* The replay runner feeds the .pty bytes through the daemon's terminal
|
|
15
|
+
* emulator (TerminalTranscriptAccumulator) building up snapshots at each
|
|
16
|
+
* declared anchor, invokes the provider handlers, and compares results
|
|
17
|
+
* to the .expected.json shape.
|
|
18
|
+
*
|
|
19
|
+
* This file is the source of truth for the format. Schema mirror at
|
|
20
|
+
* sdk/v1/schemas/fixture-expected.schema.json.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import type {
|
|
24
|
+
CliApprovalModal,
|
|
25
|
+
CliChatMessage,
|
|
26
|
+
CliStatus,
|
|
27
|
+
} from '../types/cli/index.js';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The top-level shape of <scenario>.expected.json.
|
|
31
|
+
*
|
|
32
|
+
* `anchors` is an ordered list; each anchor declares a point in the
|
|
33
|
+
* PTY stream (by byte offset or by sentinel string) and the expected
|
|
34
|
+
* handler outputs at that point.
|
|
35
|
+
*/
|
|
36
|
+
export interface FixtureExpected {
|
|
37
|
+
/** Schema version. Currently always 1. */
|
|
38
|
+
version: 1;
|
|
39
|
+
/** Free-form human description of the scenario. */
|
|
40
|
+
description?: string;
|
|
41
|
+
/** Provider type this fixture is for. */
|
|
42
|
+
providerType: string;
|
|
43
|
+
/** Path (relative to the .expected.json file) of the corresponding .pty file. */
|
|
44
|
+
ptyFile: string;
|
|
45
|
+
/** Optional cols/rows the recording was captured under. Defaults to 80x24. */
|
|
46
|
+
terminal?: { cols: number; rows: number };
|
|
47
|
+
/** Anchor points. Order matters; bytes are replayed up to each anchor. */
|
|
48
|
+
anchors: FixtureAnchor[];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface FixtureAnchor {
|
|
52
|
+
/** Human-readable identifier. Used in test reporter output. */
|
|
53
|
+
name: string;
|
|
54
|
+
/** Optional description. */
|
|
55
|
+
description?: string;
|
|
56
|
+
/**
|
|
57
|
+
* Where to stop replaying bytes. Exactly one of:
|
|
58
|
+
* - `untilByte` — stop after the Nth raw byte
|
|
59
|
+
* - `untilSentinel` — stop the first time `sentinel` appears in the
|
|
60
|
+
* accumulated rendered screen text
|
|
61
|
+
*/
|
|
62
|
+
untilByte?: number;
|
|
63
|
+
untilSentinel?: string;
|
|
64
|
+
/**
|
|
65
|
+
* Expected handler outputs. All keys optional; the replay runner only
|
|
66
|
+
* checks the keys you provide.
|
|
67
|
+
*/
|
|
68
|
+
expect: {
|
|
69
|
+
detectStatus?: CliStatus | null;
|
|
70
|
+
parseApproval?: CliApprovalModal | null;
|
|
71
|
+
parseSession?: {
|
|
72
|
+
status?: CliStatus;
|
|
73
|
+
modal?: CliApprovalModal | null;
|
|
74
|
+
providerSessionId?: string;
|
|
75
|
+
/**
|
|
76
|
+
* Either an exact array (deep-equal) or a shape declaration that lets
|
|
77
|
+
* you match only the role/kind/content shape without pinning specific
|
|
78
|
+
* fields. Pin specific message-by-message when you care about content.
|
|
79
|
+
*/
|
|
80
|
+
messages?: CliChatMessage[] | MessageShape[];
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Optional notes about why this anchor exists. Encouraged for
|
|
85
|
+
* regression-style fixtures so future maintainers know what bug the
|
|
86
|
+
* fixture catches.
|
|
87
|
+
*/
|
|
88
|
+
notes?: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* A shape declaration that matches a message by role/kind plus optional
|
|
93
|
+
* content substring or regex. Use this instead of an exact CliChatMessage
|
|
94
|
+
* when you do not want to pin exact text.
|
|
95
|
+
*/
|
|
96
|
+
export interface MessageShape {
|
|
97
|
+
role: CliChatMessage['role'];
|
|
98
|
+
kind?: CliChatMessage['kind'];
|
|
99
|
+
/** Substring the content must contain. Plain string only. */
|
|
100
|
+
contentIncludes?: string;
|
|
101
|
+
/** Regex the content must match. */
|
|
102
|
+
contentMatches?: { source: string; flags?: string };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Result of replaying one anchor — what the handlers actually emitted.
|
|
107
|
+
* Used by the test runner to produce diff output.
|
|
108
|
+
*/
|
|
109
|
+
export interface AnchorReplayResult {
|
|
110
|
+
anchor: FixtureAnchor;
|
|
111
|
+
passes: boolean;
|
|
112
|
+
diffs: string[];
|
|
113
|
+
actual: {
|
|
114
|
+
detectStatus?: CliStatus | null;
|
|
115
|
+
parseApproval?: CliApprovalModal | null;
|
|
116
|
+
parseSession?: {
|
|
117
|
+
status: CliStatus;
|
|
118
|
+
modal: CliApprovalModal | null;
|
|
119
|
+
providerSessionId?: string;
|
|
120
|
+
messages: CliChatMessage[];
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface FixtureReplayResult {
|
|
126
|
+
fixturePath: string;
|
|
127
|
+
expected: FixtureExpected;
|
|
128
|
+
perAnchor: AnchorReplayResult[];
|
|
129
|
+
overallPasses: boolean;
|
|
130
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixture tooling — public surface.
|
|
3
|
+
*
|
|
4
|
+
* Imported by `adhdev provider test` and by daemon-core's CI regression
|
|
5
|
+
* suite. Format types and the replay runner are stable v1.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type {
|
|
9
|
+
FixtureExpected,
|
|
10
|
+
FixtureAnchor,
|
|
11
|
+
MessageShape,
|
|
12
|
+
AnchorReplayResult,
|
|
13
|
+
FixtureReplayResult,
|
|
14
|
+
} from './format.js';
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
loadFixtureExpected,
|
|
18
|
+
replayFixture,
|
|
19
|
+
formatReplayReport,
|
|
20
|
+
type CliProviderHandlers,
|
|
21
|
+
type ReplayOptions,
|
|
22
|
+
} from './replay.js';
|