@adhdev/daemon-core 0.9.82-rc.209 → 0.9.82-rc.210
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/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +2 -0
- package/dist/commands/router.d.ts +6 -0
- package/dist/git/git-commands.d.ts +2 -0
- package/dist/git/git-diff.d.ts +6 -0
- package/dist/index.d.ts +11 -5
- package/dist/index.js +5699 -3486
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5679 -3483
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/coordinator-prompt.d.ts +6 -0
- package/dist/mesh/mesh-delivery-policy.d.ts +5 -0
- package/dist/mesh/mesh-events-coordinator.d.ts +151 -0
- package/dist/mesh/mesh-events-pending.d.ts +33 -0
- package/dist/mesh/mesh-events-stale.d.ts +40 -0
- package/dist/mesh/mesh-events-utils.d.ts +14 -0
- package/dist/mesh/mesh-events.d.ts +5 -198
- package/dist/mesh/mesh-ledger-reconciliation.d.ts +23 -3
- package/dist/mesh/mesh-ledger.d.ts +19 -0
- package/dist/mesh/mesh-missions.d.ts +58 -0
- package/dist/mesh/mesh-review-inbox.d.ts +90 -0
- package/dist/mesh/mesh-runtime-store.d.ts +175 -0
- package/dist/mesh/mesh-task-stats.d.ts +49 -0
- package/dist/mesh/mesh-work-queue.d.ts +82 -0
- package/dist/mesh/refine-config.d.ts +24 -2
- package/dist/mesh/worktree-bootstrap-config.d.ts +22 -0
- package/dist/providers/acp-provider-instance.d.ts +2 -0
- package/dist/providers/spec/driver.d.ts +8 -0
- package/dist/providers/spec/evaluator.d.ts +4 -5
- package/dist/providers/spec/loader.d.ts +1 -0
- package/dist/providers/spec/schema.gen.d.ts +1409 -6
- package/dist/providers/spec/types.d.ts +188 -175
- package/dist/repo-mesh-types.d.ts +1 -0
- package/package.json +1 -1
- package/src/boot/daemon-lifecycle.ts +3 -0
- package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +20 -7
- package/src/commands/router.ts +594 -66
- package/src/git/git-commands.ts +5 -5
- package/src/git/git-diff.ts +53 -0
- package/src/index.ts +11 -5
- package/src/mesh/coordinator-prompt.ts +14 -1
- package/src/mesh/mesh-delivery-policy.ts +17 -0
- package/src/mesh/mesh-events-coordinator.ts +1404 -0
- package/src/mesh/mesh-events-pending.ts +371 -0
- package/src/mesh/mesh-events-stale.ts +283 -0
- package/src/mesh/mesh-events-utils.ts +161 -0
- package/src/mesh/mesh-events.ts +27 -2143
- package/src/mesh/mesh-ledger-reconciliation.ts +12 -5
- package/src/mesh/mesh-ledger.ts +134 -2
- package/src/mesh/mesh-missions.ts +151 -0
- package/src/mesh/mesh-review-inbox.ts +307 -0
- package/src/mesh/mesh-runtime-store.ts +539 -3
- package/src/mesh/mesh-task-stats.ts +154 -0
- package/src/mesh/mesh-work-queue.ts +233 -17
- package/src/mesh/refine-config.ts +42 -5
- package/src/mesh/worktree-bootstrap-config.ts +79 -0
- package/src/providers/acp-provider-instance.ts +15 -1
- package/src/providers/cli-provider-instance.ts +34 -13
- package/src/providers/spec/driver.ts +57 -29
- package/src/providers/spec/evaluator.ts +302 -112
- package/src/providers/spec/loader.ts +226 -37
- package/src/providers/spec/schema.gen.ts +450 -334
- package/src/providers/spec/schema.json +162 -75
- package/src/providers/spec/types.ts +234 -183
- package/src/repo-mesh-types.ts +1 -0
|
@@ -1,86 +1,9 @@
|
|
|
1
1
|
export type Size = number | string;
|
|
2
|
-
export interface Section {
|
|
3
|
-
id: string;
|
|
4
|
-
from_top?: Size;
|
|
5
|
-
from_bottom?: Size;
|
|
6
|
-
until?: {
|
|
7
|
-
section: string;
|
|
8
|
-
};
|
|
9
|
-
/** Scan the screen for the first (or last, if anchor_last=true) line
|
|
10
|
-
* matching this regex and use that line as the section start.
|
|
11
|
-
* Combine with `lines`, `until_regex`, or leave alone (defaults to
|
|
12
|
-
* end-of-screen) to control how far it extends. */
|
|
13
|
-
anchor_regex?: string;
|
|
14
|
-
anchor_flags?: string;
|
|
15
|
-
/** If true, use the LAST matching line instead of the first. Useful
|
|
16
|
-
* when the anchor pattern appears multiple times (e.g. separator
|
|
17
|
-
* lines) and you want the one closest to the bottom. */
|
|
18
|
-
anchor_last?: boolean;
|
|
19
|
-
/** Optional neighbouring-line guards that must also match for the
|
|
20
|
-
* anchor to be accepted. Reduces false positives when the anchor
|
|
21
|
-
* pattern could appear elsewhere on screen (e.g. `>` in body text).
|
|
22
|
-
* `prev` checks the line immediately above; `next` the line below. */
|
|
23
|
-
anchor_context?: {
|
|
24
|
-
prev?: string;
|
|
25
|
-
prev_flags?: string;
|
|
26
|
-
next?: string;
|
|
27
|
-
next_flags?: string;
|
|
28
|
-
};
|
|
29
|
-
/** When used with anchor_regex: take at most this many lines from the
|
|
30
|
-
* anchor point. */
|
|
31
|
-
lines?: number;
|
|
32
|
-
/** When used with anchor_regex: extend until the first line matching
|
|
33
|
-
* this regex (exclusive). Takes precedence over `lines`. */
|
|
34
|
-
until_regex?: string;
|
|
35
|
-
until_regex_flags?: string;
|
|
36
|
-
}
|
|
37
|
-
export interface SectionRegex {
|
|
38
|
-
section?: string;
|
|
39
|
-
regex: string;
|
|
40
|
-
flags?: string;
|
|
41
|
-
/**
|
|
42
|
-
* Optional cursor-position guards. When present, the state is only
|
|
43
|
-
* considered matched if the terminal cursor row/column satisfies the
|
|
44
|
-
* bounds (0-based, inclusive). Missing or undefined means "no constraint".
|
|
45
|
-
*
|
|
46
|
-
* Use case: distinguish modal zone from body zone for TUIs that use
|
|
47
|
-
* cursor position rather than distinct text to locate the active prompt
|
|
48
|
-
* (e.g. Antigravity cursor lands in modal_zone rows 8-31 when approval
|
|
49
|
-
* is visible, never in body rows 0-7). Without this guard, body text
|
|
50
|
-
* containing "Do you want to proceed?" could false-positive a modal match.
|
|
51
|
-
*/
|
|
52
|
-
cursor_row_min?: number;
|
|
53
|
-
cursor_row_max?: number;
|
|
54
|
-
cursor_col_min?: number;
|
|
55
|
-
cursor_col_max?: number;
|
|
56
|
-
}
|
|
57
2
|
export interface SectionPattern {
|
|
58
3
|
section?: string;
|
|
59
4
|
pattern: string;
|
|
60
5
|
flags?: string;
|
|
61
6
|
}
|
|
62
|
-
export interface ModalButtonsRule {
|
|
63
|
-
section?: string;
|
|
64
|
-
/** Single pattern (original). Use `patterns` for multi-format fallback. */
|
|
65
|
-
pattern?: string;
|
|
66
|
-
flags?: string;
|
|
67
|
-
/** Ordered list of pattern alternatives. Evaluated in order; first that
|
|
68
|
-
* yields >= min_count buttons wins. Mutually exclusive with `pattern`. */
|
|
69
|
-
patterns?: Array<{
|
|
70
|
-
pattern: string;
|
|
71
|
-
flags?: string;
|
|
72
|
-
}>;
|
|
73
|
-
key_for_index: string;
|
|
74
|
-
min_count?: number;
|
|
75
|
-
continuation_lines?: boolean;
|
|
76
|
-
}
|
|
77
|
-
export interface SpecState {
|
|
78
|
-
id: string;
|
|
79
|
-
label: string;
|
|
80
|
-
when: SectionRegex;
|
|
81
|
-
extract_title?: SectionRegex;
|
|
82
|
-
modal_buttons?: ModalButtonsRule;
|
|
83
|
-
}
|
|
84
7
|
export type ControlAction = {
|
|
85
8
|
type: 'send_keys';
|
|
86
9
|
keys: string;
|
|
@@ -117,23 +40,10 @@ export interface DelegateTrigger {
|
|
|
117
40
|
* Native history config — three modes, picked by which fields are present:
|
|
118
41
|
*
|
|
119
42
|
* 1. `reader`: built-in reader id (claude-cli / codex-cli / antigravity-cli / hermes-cli).
|
|
120
|
-
* Backwards-compatible path used by the four shipped providers.
|
|
121
43
|
*
|
|
122
|
-
* 2. `source`: declarative source descriptor.
|
|
123
|
-
* executor reads the on-disk store (jsonl file / sqlite db) directly using
|
|
124
|
-
* paths + jsonpath maps from this block. New providers should prefer this
|
|
125
|
-
* mode — no daemon changes required.
|
|
44
|
+
* 2. `source`: declarative source descriptor.
|
|
126
45
|
*
|
|
127
|
-
* 3. `override_path`: relative path to a provider-supplied reader module
|
|
128
|
-
* (e.g. "./native_history/index.js"). Escape hatch for formats too
|
|
129
|
-
* exotic for the declarative executor. The module must default-export
|
|
130
|
-
* a function with the signature
|
|
131
|
-
* (input: NativeHistoryInput) => NativeHistoryResult | null
|
|
132
|
-
* and runs under provider-script-root sandboxing (same gate as
|
|
133
|
-
* scripts.js).
|
|
134
|
-
*
|
|
135
|
-
* The three modes are mutually exclusive — set exactly one. Loader rejects
|
|
136
|
-
* specs that set zero or more than one.
|
|
46
|
+
* 3. `override_path`: relative path to a provider-supplied reader module.
|
|
137
47
|
*/
|
|
138
48
|
export interface NativeHistoryConfig {
|
|
139
49
|
reader?: 'claude-cli' | 'codex-cli' | 'antigravity-cli' | 'hermes-cli';
|
|
@@ -141,20 +51,6 @@ export interface NativeHistoryConfig {
|
|
|
141
51
|
override_path?: string;
|
|
142
52
|
}
|
|
143
53
|
export type NativeHistorySource = NativeHistoryJsonlSource | NativeHistorySqliteSource;
|
|
144
|
-
/**
|
|
145
|
-
* JSONL source — each line in the resolved file is one record.
|
|
146
|
-
*
|
|
147
|
-
* `path` accepts ~/, environment variables (${HOME}), and a small set of
|
|
148
|
-
* runtime variables:
|
|
149
|
-
* {cwd} — the session's working directory, raw
|
|
150
|
-
* {cwd_dashed} — cwd with `/` replaced by `-` (claude's per-project key)
|
|
151
|
-
* {session_id} — providerSessionId, when known
|
|
152
|
-
* {yyyy} {mm} {dd} — UTC date components
|
|
153
|
-
*
|
|
154
|
-
* When `path` resolves to a directory, the daemon picks the newest file
|
|
155
|
-
* matching `file_pattern` whose mtime is inside `recent_window_ms` (default
|
|
156
|
-
* 5min) — prevents the wrong session's transcript from leaking through.
|
|
157
|
-
*/
|
|
158
54
|
export interface NativeHistoryJsonlSource {
|
|
159
55
|
kind: 'jsonl';
|
|
160
56
|
path: string;
|
|
@@ -167,12 +63,6 @@ export interface NativeHistoryJsonlSource {
|
|
|
167
63
|
};
|
|
168
64
|
message_map: NativeHistoryMessageMap;
|
|
169
65
|
}
|
|
170
|
-
/**
|
|
171
|
-
* SQLite source — provider runs two queries on a read-only handle: one to
|
|
172
|
-
* pick the session row (`session_query` — first row's first column is the
|
|
173
|
-
* sessionId), then one to fetch messages (`message_query` — `?` is bound
|
|
174
|
-
* to the sessionId). Output rows are projected through `message_map`.
|
|
175
|
-
*/
|
|
176
66
|
export interface NativeHistorySqliteSource {
|
|
177
67
|
kind: 'sqlite';
|
|
178
68
|
path: string;
|
|
@@ -180,50 +70,200 @@ export interface NativeHistorySqliteSource {
|
|
|
180
70
|
message_query: string;
|
|
181
71
|
message_map: NativeHistoryMessageMap;
|
|
182
72
|
}
|
|
183
|
-
/**
|
|
184
|
-
* Maps a source record (jsonl line object / sqlite row) to a daemon
|
|
185
|
-
* native-history message. Values are jsonpath-lite strings: `$.foo.bar`
|
|
186
|
-
* or `$.items[0].text`. Literal strings (no leading `$`) pass through.
|
|
187
|
-
*
|
|
188
|
-
* `content_strip` lets a spec drop wrapper tags that the agent injects
|
|
189
|
-
* into its own transcript (claude's `<local-command-caveat>`, agy's
|
|
190
|
-
* `<USER_REQUEST>` / `<ADDITIONAL_METADATA>` / `<USER_SETTINGS_CHANGE>`).
|
|
191
|
-
* Each entry is a tag name; the executor removes `<tag>…</tag>` segments
|
|
192
|
-
* non-greedily before the value is handed to the dashboard. After all
|
|
193
|
-
* strips, leading/trailing whitespace is trimmed. If the result is empty
|
|
194
|
-
* the message is dropped.
|
|
195
|
-
*/
|
|
196
73
|
export interface NativeHistoryMessageMap {
|
|
197
74
|
role: string;
|
|
198
75
|
content: string;
|
|
199
|
-
/**
|
|
200
|
-
* Tags whose entire `<tag>…</tag>` segment is removed from content.
|
|
201
|
-
* Use for noise wrappers the agent ships alongside the real message
|
|
202
|
-
* (claude's `<local-command-caveat>`, agy's `<ADDITIONAL_METADATA>`).
|
|
203
|
-
*/
|
|
204
76
|
content_strip?: string[];
|
|
205
|
-
/**
|
|
206
|
-
* Tags whose open/close markers are removed but inner content is kept.
|
|
207
|
-
* Use when the *real* user/assistant message is wrapped in a tag
|
|
208
|
-
* the agent uses for routing (agy wraps user input in `<USER_REQUEST>`).
|
|
209
|
-
*/
|
|
210
77
|
content_unwrap?: string[];
|
|
211
78
|
timestamp_ms?: string;
|
|
212
79
|
kind?: string;
|
|
213
80
|
}
|
|
81
|
+
export interface Section {
|
|
82
|
+
id: string;
|
|
83
|
+
from_top?: Size;
|
|
84
|
+
from_bottom?: Size;
|
|
85
|
+
until?: {
|
|
86
|
+
section: string;
|
|
87
|
+
};
|
|
88
|
+
anchor_regex?: string;
|
|
89
|
+
anchor_flags?: string;
|
|
90
|
+
anchor_last?: boolean;
|
|
91
|
+
anchor_context?: {
|
|
92
|
+
prev?: string;
|
|
93
|
+
prev_flags?: string;
|
|
94
|
+
next?: string;
|
|
95
|
+
next_flags?: string;
|
|
96
|
+
};
|
|
97
|
+
lines?: number;
|
|
98
|
+
until_regex?: string;
|
|
99
|
+
until_regex_flags?: string;
|
|
100
|
+
}
|
|
101
|
+
/** v1 condition — flat SectionRegex object. Also used in control_bar.wait_for. */
|
|
102
|
+
export interface SectionRegex {
|
|
103
|
+
section?: string;
|
|
104
|
+
regex?: string;
|
|
105
|
+
flags?: string;
|
|
106
|
+
cursor_row_min?: number;
|
|
107
|
+
cursor_row_max?: number;
|
|
108
|
+
cursor_col_min?: number;
|
|
109
|
+
cursor_col_max?: number;
|
|
110
|
+
/** v1 delta detection (cursor_above_lines + changed). */
|
|
111
|
+
cursor_above_lines?: number;
|
|
112
|
+
/** Required when cursor_above_lines is set. */
|
|
113
|
+
changed?: true;
|
|
114
|
+
}
|
|
115
|
+
export interface ModalButtonsRule {
|
|
116
|
+
section?: string;
|
|
117
|
+
pattern?: string;
|
|
118
|
+
flags?: string;
|
|
119
|
+
patterns?: Array<{
|
|
120
|
+
pattern: string;
|
|
121
|
+
flags?: string;
|
|
122
|
+
}>;
|
|
123
|
+
key_for_index: string;
|
|
124
|
+
min_count?: number;
|
|
125
|
+
continuation_lines?: boolean;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* v3 section definition — keyed by id in `sections{}` object.
|
|
129
|
+
* `until` is EITHER a section-id string (no `^` prefix) OR a regex string (starts with `^`).
|
|
130
|
+
*/
|
|
131
|
+
export interface SectionDef {
|
|
132
|
+
from_top?: Size;
|
|
133
|
+
from_bottom?: Size;
|
|
134
|
+
until?: string;
|
|
135
|
+
anchor?: string;
|
|
136
|
+
anchor_flags?: string;
|
|
137
|
+
anchor_last?: boolean;
|
|
138
|
+
anchor_context?: {
|
|
139
|
+
prev?: string;
|
|
140
|
+
next?: string;
|
|
141
|
+
prev_flags?: string;
|
|
142
|
+
next_flags?: string;
|
|
143
|
+
};
|
|
144
|
+
lines?: number;
|
|
145
|
+
until_regex?: string;
|
|
146
|
+
until_regex_flags?: string;
|
|
147
|
+
}
|
|
148
|
+
/** v3 regex condition against a section (or full screen). */
|
|
149
|
+
export interface RegexCondition {
|
|
150
|
+
section?: string;
|
|
151
|
+
matches: string;
|
|
152
|
+
flags?: string;
|
|
153
|
+
cursor_row_min?: number;
|
|
154
|
+
cursor_row_max?: number;
|
|
155
|
+
cursor_col_min?: number;
|
|
156
|
+
cursor_col_max?: number;
|
|
157
|
+
}
|
|
158
|
+
/** v3 delta condition: N lines above cursor changed vs prevLines. */
|
|
159
|
+
export interface ChangedCondition {
|
|
160
|
+
cursor_above: number;
|
|
161
|
+
changed: true;
|
|
162
|
+
}
|
|
163
|
+
/** v3 AND composite. */
|
|
164
|
+
export interface AllCondition {
|
|
165
|
+
all: Condition[];
|
|
166
|
+
}
|
|
167
|
+
/** v3 OR composite. */
|
|
168
|
+
export interface AnyCondition {
|
|
169
|
+
any: Condition[];
|
|
170
|
+
}
|
|
171
|
+
export type Condition = RegexCondition | ChangedCondition | AllCondition | AnyCondition;
|
|
172
|
+
/** v3 extract_title config. */
|
|
173
|
+
export interface ExtractTitle {
|
|
174
|
+
section?: string;
|
|
175
|
+
regex?: string;
|
|
176
|
+
flags?: string;
|
|
177
|
+
first_line?: true;
|
|
178
|
+
}
|
|
179
|
+
/** v3 extract_buttons config. */
|
|
180
|
+
export interface ExtractButtons {
|
|
181
|
+
section?: string;
|
|
182
|
+
pattern: string;
|
|
183
|
+
flags?: string;
|
|
184
|
+
key_for_index: string;
|
|
185
|
+
min_count?: number;
|
|
186
|
+
continuation_lines?: boolean;
|
|
187
|
+
}
|
|
188
|
+
/** v3 state. */
|
|
189
|
+
export interface SpecStateV3 {
|
|
190
|
+
id: string;
|
|
191
|
+
label: string;
|
|
192
|
+
when: AllCondition | AnyCondition;
|
|
193
|
+
extract?: {
|
|
194
|
+
title?: ExtractTitle;
|
|
195
|
+
buttons?: ExtractButtons;
|
|
196
|
+
};
|
|
197
|
+
}
|
|
214
198
|
export interface CliSpec {
|
|
215
|
-
$schema: 'adhdev:cli/spec@
|
|
199
|
+
$schema: 'adhdev:cli/spec@3';
|
|
216
200
|
id: string;
|
|
217
201
|
name: string;
|
|
218
202
|
binary: string;
|
|
219
203
|
spawn_args?: string[];
|
|
220
204
|
env?: Record<string, string>;
|
|
205
|
+
cli_version_range?: string;
|
|
206
|
+
send_message: {
|
|
207
|
+
submit_key: string;
|
|
208
|
+
delay_ms_before_submit?: number;
|
|
209
|
+
delay_ms_per_char?: number;
|
|
210
|
+
};
|
|
211
|
+
sections: Record<string, SectionDef>;
|
|
212
|
+
states: SpecStateV3[];
|
|
213
|
+
default_state: string;
|
|
214
|
+
control_bar?: Control[];
|
|
215
|
+
notifications?: NotificationRule[];
|
|
216
|
+
delegate?: DelegateTrigger[];
|
|
217
|
+
native_history?: NativeHistoryConfig;
|
|
218
|
+
requiresFinalAssistantBeforeIdle?: boolean;
|
|
221
219
|
/**
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
* Spec authors include this so a misrouted spec is easy to spot.
|
|
220
|
+
* Per-spec timing knobs. Replaces v1 `debounce`.
|
|
221
|
+
* Also accessible via the legacy `debounce` alias in the driver for
|
|
222
|
+
* backward compat with older callers.
|
|
226
223
|
*/
|
|
224
|
+
timing?: {
|
|
225
|
+
busy_hold_ms?: number;
|
|
226
|
+
idle_hold_ms?: number;
|
|
227
|
+
startup_grace_ms?: number;
|
|
228
|
+
completion_marker?: {
|
|
229
|
+
section?: string;
|
|
230
|
+
matches: string;
|
|
231
|
+
flags?: string;
|
|
232
|
+
hold_ms: number;
|
|
233
|
+
force_after_ms?: number;
|
|
234
|
+
};
|
|
235
|
+
};
|
|
236
|
+
/**
|
|
237
|
+
* Legacy alias: v1 callers (tests, tooling) may read `debounce`.
|
|
238
|
+
* The loader populates both `timing` and `debounce` pointing at the
|
|
239
|
+
* same object so callers that use either field see consistent values.
|
|
240
|
+
* @deprecated Use `timing` instead.
|
|
241
|
+
*/
|
|
242
|
+
debounce?: {
|
|
243
|
+
busy_hold_ms?: number;
|
|
244
|
+
idle_hold_ms?: number;
|
|
245
|
+
startup_grace_ms?: number;
|
|
246
|
+
/**
|
|
247
|
+
* Legacy field name for completion_marker. Populated by the loader
|
|
248
|
+
* from `timing.completion_marker` for backward compat.
|
|
249
|
+
*/
|
|
250
|
+
completion_idle_after?: {
|
|
251
|
+
section?: string;
|
|
252
|
+
regex: string;
|
|
253
|
+
flags?: string;
|
|
254
|
+
hold_ms: number;
|
|
255
|
+
force_after_ms?: number;
|
|
256
|
+
};
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
/** Raw v1 spec shape as loaded from JSON. Used only in migrateV1toV3. */
|
|
260
|
+
export interface RawCliSpecV1 {
|
|
261
|
+
$schema: 'adhdev:cli/spec@1';
|
|
262
|
+
id: string;
|
|
263
|
+
name: string;
|
|
264
|
+
binary: string;
|
|
265
|
+
spawn_args?: string[];
|
|
266
|
+
env?: Record<string, string>;
|
|
227
267
|
cli_version_range?: string;
|
|
228
268
|
send_message: {
|
|
229
269
|
submit_key: string;
|
|
@@ -233,57 +273,30 @@ export interface CliSpec {
|
|
|
233
273
|
layout: {
|
|
234
274
|
sections: Section[];
|
|
235
275
|
};
|
|
236
|
-
states:
|
|
276
|
+
states: Array<{
|
|
277
|
+
id: string;
|
|
278
|
+
label: string;
|
|
279
|
+
when: SectionRegex;
|
|
280
|
+
extract_title?: SectionRegex;
|
|
281
|
+
modal_buttons?: ModalButtonsRule;
|
|
282
|
+
}>;
|
|
237
283
|
default_state: string;
|
|
238
284
|
control_bar?: Control[];
|
|
239
285
|
notifications?: NotificationRule[];
|
|
240
286
|
delegate?: DelegateTrigger[];
|
|
241
287
|
native_history?: NativeHistoryConfig;
|
|
242
|
-
/**
|
|
243
|
-
* When true, the daemon's completed-finalization gate will not emit
|
|
244
|
-
* `generating_completed` until native history confirms the last message
|
|
245
|
-
* role is `assistant`. Prevents PTY quiet-period from triggering idle
|
|
246
|
-
* before the CLI has finished writing its response to disk.
|
|
247
|
-
*/
|
|
248
288
|
requiresFinalAssistantBeforeIdle?: boolean;
|
|
249
|
-
/**
|
|
250
|
-
* Per-spec debounce knobs. Defaults are conservative (busy_hold_ms
|
|
251
|
-
* 6000) and live in SpecDriver. Spec authors override here when a
|
|
252
|
-
* particular CLI flickers slower/faster than the default.
|
|
253
|
-
*/
|
|
254
289
|
debounce?: {
|
|
255
|
-
/** Min time to stay in busy after the evaluator last reported it.
|
|
256
|
-
* Absorbs per-frame flicker in TUIs that stream output through
|
|
257
|
-
* the same region as the spinner. */
|
|
258
290
|
busy_hold_ms?: number;
|
|
259
|
-
/** Min time the idle state must remain matched before it is
|
|
260
|
-
* committed. Filters transient idle flickers that appear during
|
|
261
|
-
* approval dismissals, layout reflows, or brief spinner gaps.
|
|
262
|
-
* Any non-idle reading within the window cancels the transition.
|
|
263
|
-
* When omitted the idle transition is immediate (legacy behaviour). */
|
|
264
291
|
idle_hold_ms?: number;
|
|
265
|
-
/** Min time after start() before a send_message is allowed to
|
|
266
|
-
* reach the PTY. Banner paints + auth flows + skill listings
|
|
267
|
-
* can keep the agent unable to accept input for several seconds
|
|
268
|
-
* even though the idle regex matches a transient empty prompt.
|
|
269
|
-
* Send_messages issued before this window are queued and drained
|
|
270
|
-
* once the window passes and an idle state has actually been
|
|
271
|
-
* observed. */
|
|
272
292
|
startup_grace_ms?: number;
|
|
273
|
-
/** Treat a provider-specific completion marker as idle after it has
|
|
274
|
-
* remained visible for hold_ms. This handles TUIs that leave their
|
|
275
|
-
* last spinner glyph next to a completed timer, causing the normal
|
|
276
|
-
* busy regex to keep matching after the turn is done. */
|
|
277
293
|
completion_idle_after?: {
|
|
278
294
|
section?: string;
|
|
279
295
|
regex: string;
|
|
280
296
|
flags?: string;
|
|
281
297
|
hold_ms: number;
|
|
282
|
-
/** If the target-state check still fails this many ms after hold_ms
|
|
283
|
-
* expired, force an idle transition anyway. Guards against TUIs that
|
|
284
|
-
* show transient UI (pickers, option lists) after the completion
|
|
285
|
-
* marker appears, keeping the target-state regex from matching. */
|
|
286
298
|
force_after_ms?: number;
|
|
287
299
|
};
|
|
288
300
|
};
|
|
289
301
|
}
|
|
302
|
+
export type SpecState = SpecStateV3;
|
|
@@ -361,6 +361,7 @@ export interface RepoMeshNodeStatus {
|
|
|
361
361
|
worktreeBootstrap?: LocalMeshNodeEntry['worktreeBootstrap'];
|
|
362
362
|
launchBlockedReason?: string;
|
|
363
363
|
launchBlockedMessage?: string;
|
|
364
|
+
recoveryHint?: string;
|
|
364
365
|
lastSeenAt?: string;
|
|
365
366
|
updatedAt?: string;
|
|
366
367
|
connection?: RepoMeshPeerConnectionStatus;
|
package/package.json
CHANGED
|
@@ -353,6 +353,9 @@ export async function initDaemonComponents(config: DaemonInitConfig): Promise<Da
|
|
|
353
353
|
// 11. Setup Mesh Event Forwarding
|
|
354
354
|
setupMeshEventForwarding(components);
|
|
355
355
|
|
|
356
|
+
// 12. Resume any refine jobs that were interrupted by a previous daemon restart.
|
|
357
|
+
setImmediate(() => void router.resumePendingRefineJobsOnStartup());
|
|
358
|
+
|
|
356
359
|
return components;
|
|
357
360
|
}
|
|
358
361
|
|
|
@@ -83,45 +83,58 @@ function loadGhosttyVtBinding(): GhosttyVtBinding {
|
|
|
83
83
|
export class GhosttyVtTerminalBackend implements TerminalViewportBackend {
|
|
84
84
|
readonly kind = 'ghostty-vt' as const;
|
|
85
85
|
private terminal: GhosttyVtTerminal;
|
|
86
|
+
private rows: number;
|
|
87
|
+
private disposed = false;
|
|
86
88
|
|
|
87
89
|
constructor(options: TerminalViewportBackendOptions) {
|
|
88
90
|
const binding = loadGhosttyVtBinding();
|
|
91
|
+
this.rows = Math.max(1, options.rows | 0);
|
|
89
92
|
this.terminal = binding.createTerminal({
|
|
90
93
|
cols: Math.max(1, options.cols | 0),
|
|
91
|
-
rows:
|
|
94
|
+
rows: this.rows,
|
|
92
95
|
scrollback: Math.max(0, options.scrollback | 0),
|
|
93
96
|
});
|
|
94
97
|
}
|
|
95
98
|
|
|
96
99
|
resize(rows: number, cols: number): void {
|
|
97
|
-
this.
|
|
100
|
+
this.rows = Math.max(1, rows | 0);
|
|
101
|
+
this.terminal.resize(Math.max(1, cols | 0), this.rows);
|
|
98
102
|
}
|
|
99
103
|
|
|
100
104
|
write(data: string): void {
|
|
101
|
-
if (!data) return;
|
|
105
|
+
if (!data || this.disposed) return;
|
|
102
106
|
this.terminal.write(data);
|
|
103
107
|
}
|
|
104
108
|
|
|
105
109
|
getText(): string {
|
|
110
|
+
if (this.disposed) return '';
|
|
106
111
|
// ghostty's `trim:true` collapses CUF-advanced cells — many TUIs including
|
|
107
112
|
// Claude Code render spaces via cursor-forward rather than literal spaces,
|
|
108
113
|
// which would break downstream regex matching. Keep per-row padding and
|
|
109
114
|
// trim trailing whitespace ourselves.
|
|
115
|
+
//
|
|
116
|
+
// formatPlainText uses a .screen pin which includes scrollback history.
|
|
117
|
+
// Slice to the last `rows` lines to get only the visible viewport.
|
|
110
118
|
const raw = this.terminal.formatPlainText({ trim: false }) || '';
|
|
111
119
|
if (!raw) return '';
|
|
112
120
|
const lines = raw.split('\n').map((row) => row.replace(/\s+$/, ''));
|
|
121
|
+
// Take only the viewport (last `rows` lines) to exclude scrollback history.
|
|
122
|
+
const viewport = lines.length > this.rows ? lines.slice(-this.rows) : lines;
|
|
113
123
|
let first = 0;
|
|
114
|
-
let last =
|
|
115
|
-
while (first < last && !
|
|
116
|
-
while (last > first && !
|
|
117
|
-
return
|
|
124
|
+
let last = viewport.length;
|
|
125
|
+
while (first < last && !viewport[first]) first += 1;
|
|
126
|
+
while (last > first && !viewport[last - 1]) last -= 1;
|
|
127
|
+
return viewport.slice(first, last).join('\n');
|
|
118
128
|
}
|
|
119
129
|
|
|
120
130
|
getCursorPosition(): { col: number; row: number } {
|
|
131
|
+
if (this.disposed) return { col: 0, row: 0 };
|
|
121
132
|
return this.terminal.getCursorPosition();
|
|
122
133
|
}
|
|
123
134
|
|
|
124
135
|
dispose(): void {
|
|
136
|
+
if (this.disposed) return;
|
|
137
|
+
this.disposed = true;
|
|
125
138
|
this.terminal.dispose();
|
|
126
139
|
}
|
|
127
140
|
}
|