@byokit/herdr 0.1.0-next.dbe7142 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +94 -0
- package/README.md +192 -14
- package/dist/agents.js +48 -7
- package/dist/binary.d.ts +29 -0
- package/dist/binary.js +132 -0
- package/dist/constants.d.ts +7 -0
- package/dist/constants.js +4 -0
- package/dist/device.d.ts +34 -8
- package/dist/device.js +152 -49
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/kit.d.ts +30 -2
- package/dist/kit.js +284 -52
- package/dist/link.js +118 -2
- package/dist/supervise.js +11 -2
- package/dist/testing/contract.d.ts +13 -3
- package/dist/testing/contract.js +116 -12
- package/dist/testing/fake-herdr/bin.js +41 -12
- package/dist/testing/fake-herdr/server.d.ts +17 -1
- package/dist/testing/fake-herdr/server.js +311 -36
- package/dist/testing/fake-herdr/world.d.ts +35 -0
- package/dist/testing/fake-herdr/world.js +24 -1
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +9 -0
- package/dist/types.d.ts +64 -22
- package/package.json +7 -3
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import type { HerdrKit } from '../kit.ts';
|
|
2
2
|
import type { FakeHerdr } from './fake-herdr/server.ts';
|
|
3
|
-
import type { HerdrTransport } from '../types.ts';
|
|
3
|
+
import type { HerdrProtocolRange, HerdrTransport } from '../types.ts';
|
|
4
4
|
export type HerdrContractBench = {
|
|
5
5
|
kit: HerdrKit;
|
|
6
6
|
fake?: FakeHerdr;
|
|
7
|
-
withTransport?: (transport: HerdrTransport
|
|
7
|
+
withTransport?: (transport: HerdrTransport, o?: {
|
|
8
|
+
protocolRange?: HerdrProtocolRange;
|
|
9
|
+
}) => HerdrKit;
|
|
8
10
|
};
|
|
9
|
-
export
|
|
11
|
+
export type HerdrContractTestContext = {
|
|
12
|
+
skip: (message?: string) => void;
|
|
13
|
+
};
|
|
14
|
+
export type HerdrContractTestFn = (name: string, fn: (t: HerdrContractTestContext) => void | Promise<void>) => void | Promise<void>;
|
|
15
|
+
export type HerdrContractOptions = {
|
|
16
|
+
/** The runner's `test` (node:test's by default; pass vitest's `test` under vitest). */
|
|
17
|
+
test?: HerdrContractTestFn;
|
|
18
|
+
};
|
|
19
|
+
export declare function herdrContract(make: () => Promise<HerdrContractBench>, options?: HerdrContractOptions | HerdrContractTestFn): void;
|
package/dist/testing/contract.js
CHANGED
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
// in later work packages' tests (H3/H5 wire `make` up) and against the real pinned Herdr in the lab
|
|
3
3
|
// (H9, which passes no `fake`). Cases that need to script the transport's wire answers use
|
|
4
4
|
// `withTransport`; when a `make` omits it, those cases skip.
|
|
5
|
-
import { test } from 'node:test';
|
|
5
|
+
import { test as nodeTest } from 'node:test';
|
|
6
6
|
import assert from 'node:assert/strict';
|
|
7
7
|
import { HERDR_PROTOCOL } from "../constants.js";
|
|
8
|
-
export function herdrContract(make) {
|
|
8
|
+
export function herdrContract(make, options) {
|
|
9
|
+
const runTest = typeof options === 'function' ? options : (options?.test ?? nodeTest);
|
|
10
|
+
const test = runTest;
|
|
9
11
|
const settle = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
10
12
|
async function until(probe, ok, ms = 2000) {
|
|
11
13
|
const deadline = Date.now() + ms;
|
|
@@ -29,6 +31,14 @@ export function herdrContract(make) {
|
|
|
29
31
|
await made.fake?.stop().catch(() => { });
|
|
30
32
|
}
|
|
31
33
|
}
|
|
34
|
+
// Transport doubles that never exercise the control surface still satisfy its type.
|
|
35
|
+
function ackedStop() {
|
|
36
|
+
return Object.assign(() => { }, {
|
|
37
|
+
ready: Promise.resolve(true),
|
|
38
|
+
onReconnect() { },
|
|
39
|
+
onDisconnect() { },
|
|
40
|
+
});
|
|
41
|
+
}
|
|
32
42
|
function agentStatusOf(snapshot, paneId) {
|
|
33
43
|
let panes = 0;
|
|
34
44
|
let status;
|
|
@@ -52,24 +62,96 @@ export function herdrContract(make) {
|
|
|
52
62
|
assert.equal(typeof ping.version, 'string');
|
|
53
63
|
});
|
|
54
64
|
});
|
|
55
|
-
test('contract: a
|
|
65
|
+
test('contract: a newer server is needs-update state, not a throw — the kit stays usable', async (t) => {
|
|
56
66
|
await bench(async ({ withTransport }) => {
|
|
57
67
|
if (!withTransport)
|
|
58
68
|
return t.skip('make provides no transport double');
|
|
69
|
+
const snapshot = {
|
|
70
|
+
protocol: HERDR_PROTOCOL + 999,
|
|
71
|
+
snapshot: {
|
|
72
|
+
protocol: HERDR_PROTOCOL + 999,
|
|
73
|
+
workspaces: [{ workspace_id: 'w1', label: 'x' }],
|
|
74
|
+
tabs: [{ tab_id: 'w1:t1', workspace_id: 'w1', label: 'main' }],
|
|
75
|
+
panes: [{ pane_id: 'w1:p2', tab_id: 'w1:t1', workspace_id: 'w1' }],
|
|
76
|
+
agents: [{ pane_id: 'w1:p2', agent_status: 'idle', revision: 1 }],
|
|
77
|
+
},
|
|
78
|
+
};
|
|
59
79
|
const kit = withTransport({
|
|
60
|
-
call: async () => ({ protocol: HERDR_PROTOCOL + 999 }),
|
|
61
|
-
subscribe: () => ()
|
|
80
|
+
call: async (method) => (method === 'session.snapshot' ? snapshot : { protocol: HERDR_PROTOCOL + 999 }),
|
|
81
|
+
subscribe: () => ackedStop(),
|
|
62
82
|
close: () => { },
|
|
63
83
|
});
|
|
64
84
|
try {
|
|
65
|
-
await kit.start()
|
|
85
|
+
await kit.start();
|
|
66
86
|
assert.equal(kit.state.phase, 'needs-update');
|
|
87
|
+
assert.equal(kit.state.why, 'version');
|
|
88
|
+
assert.equal(kit.snapshot().workspaces.length, 1, 'the snapshot still installs');
|
|
89
|
+
assert.ok(kit.snapshot().connected, 'the kit stays connected');
|
|
90
|
+
await kit.call('ping', {});
|
|
67
91
|
}
|
|
68
92
|
finally {
|
|
69
93
|
await kit.stop().catch(() => { });
|
|
70
94
|
}
|
|
71
95
|
});
|
|
72
96
|
});
|
|
97
|
+
test('contract: an older server fails closed', async (t) => {
|
|
98
|
+
await bench(async ({ withTransport }) => {
|
|
99
|
+
if (!withTransport)
|
|
100
|
+
return t.skip('make provides no transport double');
|
|
101
|
+
const kit = withTransport({
|
|
102
|
+
call: async () => ({ protocol: HERDR_PROTOCOL - 1 }),
|
|
103
|
+
subscribe: () => ackedStop(),
|
|
104
|
+
close: () => { },
|
|
105
|
+
});
|
|
106
|
+
try {
|
|
107
|
+
await assert.rejects(kit.start(), /protocol mismatch/);
|
|
108
|
+
assert.equal(kit.state.phase, 'needs-update');
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
await kit.stop().catch(() => { });
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
test('contract: a declared protocol range accepts a newer server as ready', async (t) => {
|
|
116
|
+
await bench(async ({ withTransport }) => {
|
|
117
|
+
if (!withTransport)
|
|
118
|
+
return t.skip('make provides no transport double');
|
|
119
|
+
const snapshot = {
|
|
120
|
+
protocol: HERDR_PROTOCOL + 1,
|
|
121
|
+
snapshot: {
|
|
122
|
+
protocol: HERDR_PROTOCOL + 1,
|
|
123
|
+
workspaces: [{ workspace_id: 'w1', label: 'x' }],
|
|
124
|
+
tabs: [{ tab_id: 'w1:t1', workspace_id: 'w1', label: 'main' }],
|
|
125
|
+
panes: [{ pane_id: 'w1:p2', tab_id: 'w1:t1', workspace_id: 'w1' }],
|
|
126
|
+
agents: [{ pane_id: 'w1:p2', agent_status: 'idle', revision: 1 }],
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
const transport = {
|
|
130
|
+
call: async (method) => (method === 'session.snapshot' ? snapshot : { protocol: HERDR_PROTOCOL + 1 }),
|
|
131
|
+
subscribe: () => ackedStop(),
|
|
132
|
+
close: () => { },
|
|
133
|
+
};
|
|
134
|
+
const inRange = withTransport(transport);
|
|
135
|
+
try {
|
|
136
|
+
await inRange.start();
|
|
137
|
+
assert.equal(inRange.state.phase, 'needs-update', 'without the range a newer server is needs-update');
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
await inRange.stop().catch(() => { });
|
|
141
|
+
}
|
|
142
|
+
const ranged = withTransport(transport, {
|
|
143
|
+
protocolRange: { min: HERDR_PROTOCOL, max: HERDR_PROTOCOL + 1 },
|
|
144
|
+
});
|
|
145
|
+
try {
|
|
146
|
+
await ranged.start();
|
|
147
|
+
assert.equal(ranged.state.phase, 'ready', 'the declared range accepts the newer server');
|
|
148
|
+
assert.equal(ranged.snapshot().workspaces.length, 1);
|
|
149
|
+
}
|
|
150
|
+
finally {
|
|
151
|
+
await ranged.stop().catch(() => { });
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
});
|
|
73
155
|
test('contract: an event racing the bootstrap snapshot is applied after it, once', async (t) => {
|
|
74
156
|
await bench(async ({ withTransport }) => {
|
|
75
157
|
if (!withTransport)
|
|
@@ -83,12 +165,12 @@ export function herdrContract(make) {
|
|
|
83
165
|
},
|
|
84
166
|
};
|
|
85
167
|
const kit = withTransport({
|
|
86
|
-
// The ack carries the race: `
|
|
168
|
+
// The ack carries the race: `pane_updated` lands after the subscribe but before the kit
|
|
87
169
|
// installs the snapshot, so buffering must order it after — and never duplicate it.
|
|
88
170
|
call: async (method) => (method === 'session.snapshot' ? snapshot : { protocol: HERDR_PROTOCOL }),
|
|
89
171
|
subscribe: (_subs, on) => {
|
|
90
|
-
queueMicrotask(() => on({ type: '
|
|
91
|
-
return ()
|
|
172
|
+
queueMicrotask(() => on({ type: 'pane_updated', pane: { pane_id: 'w1:p2', agent_status: 'working' } }));
|
|
173
|
+
return ackedStop();
|
|
92
174
|
},
|
|
93
175
|
close: () => { },
|
|
94
176
|
});
|
|
@@ -116,7 +198,7 @@ export function herdrContract(make) {
|
|
|
116
198
|
if (subs.some((s) => s.type === 'pane.agent_status_changed')) {
|
|
117
199
|
onError('invalid_subscription', 'pane.agent_status_changed needs a pane_id');
|
|
118
200
|
}
|
|
119
|
-
return ()
|
|
201
|
+
return ackedStop();
|
|
120
202
|
},
|
|
121
203
|
close: () => { },
|
|
122
204
|
});
|
|
@@ -126,9 +208,17 @@ export function herdrContract(make) {
|
|
|
126
208
|
// Deliberately schema-invalid: the pinned schema (6.7) requires pane_id for this filtered
|
|
127
209
|
// kind, so the server rejects the batch — the exact answer the transport double gives here.
|
|
128
210
|
const rejected = { type: 'pane.agent_status_changed' };
|
|
129
|
-
|
|
211
|
+
const errors = [];
|
|
212
|
+
const stop = kit.subscribe([rejected], () => { }, (code, message) => errors.push({ code, message }));
|
|
213
|
+
assert.equal(typeof stop, 'function');
|
|
214
|
+
assert.ok(stop.ready instanceof Promise, 'the stop carries the ack promise');
|
|
215
|
+
assert.equal(typeof stop.onReconnect, 'function');
|
|
216
|
+
assert.equal(typeof stop.onDisconnect, 'function');
|
|
130
217
|
await settle(1200); // longer than the 1 s reconnect delay a retry would use
|
|
218
|
+
assert.deepEqual(errors.map((e) => e.code), ['invalid_subscription'], 'the rejection reaches onError exactly once');
|
|
219
|
+
assert.match(errors[0].message, /pane_id/);
|
|
131
220
|
assert.equal(subscribeCalls, bootstrapCalls + 1, 'the rejected subscription is never retried');
|
|
221
|
+
stop();
|
|
132
222
|
}
|
|
133
223
|
finally {
|
|
134
224
|
await kit.stop().catch(() => { });
|
|
@@ -145,6 +235,8 @@ export function herdrContract(make) {
|
|
|
145
235
|
await settle(100); // the subscribe registers on its own socket; an emit before that never arrives
|
|
146
236
|
fake.emit({ type: 'pane.created', pane_id: 'w9:p9' });
|
|
147
237
|
await until(() => seen.length, (n) => n >= 1);
|
|
238
|
+
// The fake emits the live underscore spelling; the kit matches both spellings.
|
|
239
|
+
assert.equal(seen[0].type, 'pane_created');
|
|
148
240
|
assert.equal(seen[0].pane_id, 'w9:p9');
|
|
149
241
|
stop();
|
|
150
242
|
fake.emit({ type: 'pane.created', pane_id: 'w9:p10' });
|
|
@@ -191,6 +283,18 @@ export function herdrContract(make) {
|
|
|
191
283
|
assert.ok(workspaces.workspaces?.some((workspace) => workspace.worktree?.is_linked_worktree === true), 'the worktree placement registers a linked checkout');
|
|
192
284
|
});
|
|
193
285
|
});
|
|
286
|
+
test('contract: a started agent joins snapshot() and its status stays current there', async () => {
|
|
287
|
+
await bench(async ({ kit }) => {
|
|
288
|
+
await kit.start();
|
|
289
|
+
const { paneId } = await kit.startAgent({ kind: 'pi', cwd: '/tmp/h6', place: { workspace: 'new' } });
|
|
290
|
+
await until(() => agentStatusOf(kit.snapshot(), paneId).status, (status) => status === 'idle');
|
|
291
|
+
await kit.prompt({ paneId }, 'ask permission');
|
|
292
|
+
await until(() => agentStatusOf(kit.snapshot(), paneId).status, (status) => status === 'blocked');
|
|
293
|
+
const blocked = await until(() => kit.blocked().find((b) => b.paneId === paneId), () => true);
|
|
294
|
+
await kit.answer(paneId, ['y'], { revision: blocked.revision });
|
|
295
|
+
await until(() => agentStatusOf(kit.snapshot(), paneId).status, (status) => status === 'idle');
|
|
296
|
+
});
|
|
297
|
+
});
|
|
194
298
|
test('contract: prompt validates the receipt and appends the reply text', async () => {
|
|
195
299
|
await bench(async ({ kit }) => {
|
|
196
300
|
await kit.start();
|
|
@@ -223,7 +327,7 @@ export function herdrContract(make) {
|
|
|
223
327
|
}
|
|
224
328
|
return { protocol: HERDR_PROTOCOL };
|
|
225
329
|
},
|
|
226
|
-
subscribe: () => ()
|
|
330
|
+
subscribe: () => ackedStop(),
|
|
227
331
|
close: () => { },
|
|
228
332
|
});
|
|
229
333
|
try {
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
// `api schema`, the `server` verb, JSON CLI verbs and `terminal session`. World state lives on the
|
|
3
3
|
// control socket; this process never speaks JSON-RPC except to forward a CLI verb. Ported from muxr
|
|
4
4
|
// `perf/fake-herdr/bin.mjs` with the perf byte rates and graphics probes removed.
|
|
5
|
-
import { chmodSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import { chmodSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
6
6
|
import { createConnection } from 'node:net';
|
|
7
|
-
import { dirname, resolve } from 'node:path';
|
|
7
|
+
import { dirname, join, resolve } from 'node:path';
|
|
8
8
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
9
9
|
import { HERDR_PROTOCOL, HERDR_VERSION } from "../../constants.js";
|
|
10
10
|
const SELF = fileURLToPath(import.meta.url);
|
|
@@ -82,13 +82,20 @@ async function runServer() {
|
|
|
82
82
|
process.on('SIGTERM', stop);
|
|
83
83
|
process.on('SIGINT', stop);
|
|
84
84
|
}
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
//
|
|
85
|
+
// Terminal frames carry the real Herdr shape — `{ type: 'terminal.frame', pane_id, full, bytes }`
|
|
86
|
+
// with `bytes` the UTF-8 length of `full` — plus the fake's `data` alias (same string as `full`),
|
|
87
|
+
// so older assertions reading `data` keep passing. A `{"type":"terminal.resize",cols,rows}` line
|
|
88
|
+
// resizes the session and answers one empty frame stamped with the new size; `terminal.release`
|
|
89
|
+
// exits; `{"type":"fake.stream","count":n,"size":b,"progress":file}` streams n frames with full
|
|
90
|
+
// `<i>:` plus b bytes as fast as the pipe takes them, recording the frames-written count in
|
|
91
|
+
// `progress` after each write so a test can see how far a paused reader let the stream run.
|
|
92
|
+
function frame(paneId, full, extra = {}) {
|
|
93
|
+
return `${JSON.stringify({ type: 'terminal.frame', pane_id: paneId, data: full, full, bytes: Buffer.byteLength(full), ...extra })}\n`;
|
|
94
|
+
}
|
|
88
95
|
async function stream(paneId, o) {
|
|
89
96
|
const pad = 'x'.repeat(o.size ?? 1024);
|
|
90
97
|
for (let i = 0; i < (o.count ?? 0); i += 1) {
|
|
91
|
-
const ok = process.stdout.write(
|
|
98
|
+
const ok = process.stdout.write(frame(paneId, `${i}:${pad}`));
|
|
92
99
|
if (o.progress)
|
|
93
100
|
writeFileSync(o.progress, String(i + 1));
|
|
94
101
|
if (!ok)
|
|
@@ -98,12 +105,12 @@ async function stream(paneId, o) {
|
|
|
98
105
|
function runTerminal(args) {
|
|
99
106
|
// `herdr terminal session <control|observe> <pane> [--takeover] --cols <n> --rows <n>`.
|
|
100
107
|
// The fake needs no server for this: one ready frame, then every send line echoes back as an
|
|
101
|
-
// output frame (docs/runtime-kits.md 6.8), except `fake.stream`
|
|
108
|
+
// output frame (docs/runtime-kits.md 6.8), except `fake.stream` and `terminal.resize` above.
|
|
102
109
|
const mode = args[0] === 'observe' ? 'observe' : 'control';
|
|
103
110
|
const rest = args[0] === 'control' || args[0] === 'observe' ? args.slice(1) : args;
|
|
104
111
|
const paneId = rest[0] ?? 'w1:p1';
|
|
105
|
-
|
|
106
|
-
|
|
112
|
+
let cols = Number(flag(args, '--cols')) || 80;
|
|
113
|
+
let rows = Number(flag(args, '--rows')) || 24;
|
|
107
114
|
const takeover = args.includes('--takeover');
|
|
108
115
|
process.stdout.write(`${JSON.stringify({ type: 'terminal.ready', pane_id: paneId, mode, takeover, cols, rows })}\n`);
|
|
109
116
|
let buffer = '';
|
|
@@ -116,6 +123,7 @@ function runTerminal(args) {
|
|
|
116
123
|
if (line.trim() === '')
|
|
117
124
|
continue;
|
|
118
125
|
let data = line;
|
|
126
|
+
let extra = {};
|
|
119
127
|
try {
|
|
120
128
|
const message = JSON.parse(line);
|
|
121
129
|
if (message.type === 'terminal.release')
|
|
@@ -124,11 +132,20 @@ function runTerminal(args) {
|
|
|
124
132
|
void stream(paneId, message);
|
|
125
133
|
continue;
|
|
126
134
|
}
|
|
135
|
+
if (message.type === 'terminal.resize') {
|
|
136
|
+
if (typeof message.cols === 'number' && message.cols > 0)
|
|
137
|
+
cols = Math.floor(message.cols);
|
|
138
|
+
if (typeof message.rows === 'number' && message.rows > 0)
|
|
139
|
+
rows = Math.floor(message.rows);
|
|
140
|
+
process.stdout.write(frame(paneId, '', { cols, rows }));
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
// `terminal.input` carries the keys in `data`; anything else with a string `data` echoes it.
|
|
127
144
|
if (typeof message.data === 'string')
|
|
128
145
|
data = message.data;
|
|
129
146
|
}
|
|
130
147
|
catch { /* a raw line echoes as-is */ }
|
|
131
|
-
process.stdout.write(
|
|
148
|
+
process.stdout.write(frame(paneId, data, { cols, rows }));
|
|
132
149
|
}
|
|
133
150
|
});
|
|
134
151
|
process.stdin.on('end', () => process.exit(0));
|
|
@@ -186,8 +203,20 @@ export async function main(argv) {
|
|
|
186
203
|
return;
|
|
187
204
|
}
|
|
188
205
|
if (cmd === 'api' && sub === 'schema') {
|
|
189
|
-
//
|
|
190
|
-
|
|
206
|
+
// Prints the pinned v0.9.1 snapshot itself (schema/herdr-api-0.9.1.json, docs/runtime-kits.md
|
|
207
|
+
// 6.7) — the same bytes `scripts/gen-types.ts` generates the typed surface from — exactly as
|
|
208
|
+
// the real `herdr api schema` prints its bundled schema. Only when the snapshot file is
|
|
209
|
+
// unreachable (a packed install without it) does the shim fall back to the pinned identity.
|
|
210
|
+
try {
|
|
211
|
+
const snapshot = readFileSync(join(dirname(SELF), '../../../schema/herdr-api-0.9.1.json'), 'utf8');
|
|
212
|
+
const parsed = JSON.parse(snapshot);
|
|
213
|
+
if (parsed.protocol !== HERDR_PROTOCOL)
|
|
214
|
+
throw new Error('fake-herdr bin: schema snapshot drift');
|
|
215
|
+
process.stdout.write(snapshot.endsWith('\n') ? snapshot : `${snapshot}\n`);
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
process.stdout.write(`${JSON.stringify({ protocol: HERDR_PROTOCOL, version: HERDR_VERSION })}\n`);
|
|
219
|
+
}
|
|
191
220
|
return;
|
|
192
221
|
}
|
|
193
222
|
if (cmd === 'server') {
|
|
@@ -1,21 +1,37 @@
|
|
|
1
|
-
import { type FakeWorld } from './world.ts';
|
|
1
|
+
import { type FakePluginSeed, type FakeWorld } from './world.ts';
|
|
2
2
|
export type FakeHerdrOptions = {
|
|
3
3
|
dir: string;
|
|
4
4
|
socketPath?: string;
|
|
5
5
|
world?: {
|
|
6
6
|
cwd?: string;
|
|
7
7
|
kinds?: readonly string[];
|
|
8
|
+
seed?: number;
|
|
9
|
+
plugins?: readonly FakePluginSeed[];
|
|
8
10
|
};
|
|
11
|
+
agentStartFaults?: AgentStartFault[];
|
|
9
12
|
onStop?: () => void;
|
|
10
13
|
};
|
|
14
|
+
export type AgentStartFault = {
|
|
15
|
+
code: string;
|
|
16
|
+
message?: string;
|
|
17
|
+
};
|
|
11
18
|
export type FakeHerdr = {
|
|
12
19
|
socketPath: string;
|
|
13
20
|
bin: string;
|
|
14
21
|
world: FakeWorld;
|
|
22
|
+
agentStartFaults: AgentStartFault[];
|
|
15
23
|
emit(event: {
|
|
16
24
|
type: string;
|
|
17
25
|
} & Record<string, unknown>): void;
|
|
18
26
|
setStatus(paneId: string, status: string): void;
|
|
27
|
+
watching(): string[];
|
|
28
|
+
watching(paneId: string): boolean;
|
|
29
|
+
snapshotCount(): number;
|
|
30
|
+
holdSnapshot(): () => void;
|
|
31
|
+
failNextSnapshot(code?: string, message?: string): void;
|
|
32
|
+
holdAck(): () => void;
|
|
33
|
+
failNextAck(code?: string, message?: string): void;
|
|
34
|
+
subscriptionCount(): number;
|
|
19
35
|
stop(): Promise<void>;
|
|
20
36
|
};
|
|
21
37
|
export declare function startFakeHerdr(options: FakeHerdrOptions): Promise<FakeHerdr>;
|