ferrycat 0.3.2 → 0.4.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/README.md +132 -21
- package/README_zh.md +131 -23
- package/bin/ferrycat.js +19 -1
- package/dist/cli.js +112 -146
- package/dist/cli.js.map +1 -1
- package/dist/daemon.d.ts +54 -0
- package/dist/daemon.js +372 -0
- package/dist/daemon.js.map +1 -0
- package/dist/demo.d.ts +36 -0
- package/dist/demo.js +340 -0
- package/dist/demo.js.map +1 -0
- package/dist/engine.d.ts +29 -1
- package/dist/engine.js +188 -27
- package/dist/engine.js.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/schemas.d.ts +228 -0
- package/dist/schemas.js +41 -0
- package/dist/schemas.js.map +1 -1
- package/dist/supervisor.d.ts +98 -0
- package/dist/supervisor.js +562 -0
- package/dist/supervisor.js.map +1 -0
- package/dist/types.d.ts +41 -0
- package/package.json +2 -1
- package/server.json +2 -2
package/dist/daemon.js
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FerryCat Controlled Daemon (Phase 3 Step 1, ADR-0005 Hardened).
|
|
3
|
+
*
|
|
4
|
+
* Provides a production-grade, background-ready execution orchestrator:
|
|
5
|
+
* - Short-transaction CAS leases on `daemon_locks` table.
|
|
6
|
+
* - Cryptographically random per-process owner token (prevents split-brain on identical configs).
|
|
7
|
+
* - Automatic process tree termination on lease loss (CK-04/05).
|
|
8
|
+
* - Safe heartbeat intervals clamped to <= lease_ttl_sec / 2.
|
|
9
|
+
* - Robust heartbeat exception recovery.
|
|
10
|
+
* - Declarative handler execution with args and environment forwarding.
|
|
11
|
+
* - Graceful shutdown on SIGINT/SIGTERM.
|
|
12
|
+
*/
|
|
13
|
+
import crypto from 'node:crypto';
|
|
14
|
+
import fs from 'node:fs';
|
|
15
|
+
import os from 'node:os';
|
|
16
|
+
import path from 'node:path';
|
|
17
|
+
import { FerryCatEngine, expandTilde } from './engine.js';
|
|
18
|
+
import { FerryCatConfigFileSchema, } from './schemas.js';
|
|
19
|
+
import { executeTaskAndFulfill, terminateActiveChildrenSync } from './supervisor.js';
|
|
20
|
+
export function loadFerryCatConfig(customConfigPath) {
|
|
21
|
+
const candidatePaths = [];
|
|
22
|
+
if (customConfigPath) {
|
|
23
|
+
candidatePaths.push(path.resolve(expandTilde(customConfigPath)));
|
|
24
|
+
}
|
|
25
|
+
if (process.env.FERRYCAT_CONFIG) {
|
|
26
|
+
candidatePaths.push(path.resolve(expandTilde(process.env.FERRYCAT_CONFIG)));
|
|
27
|
+
}
|
|
28
|
+
candidatePaths.push(path.resolve(process.cwd(), 'ferrycat.config.json'));
|
|
29
|
+
candidatePaths.push(path.join(os.homedir(), '.ferrycat', 'config.json'));
|
|
30
|
+
for (const candidate of candidatePaths) {
|
|
31
|
+
if (fs.existsSync(candidate)) {
|
|
32
|
+
try {
|
|
33
|
+
const raw = fs.readFileSync(candidate, 'utf8');
|
|
34
|
+
const parsed = JSON.parse(raw);
|
|
35
|
+
const validated = FerryCatConfigFileSchema.parse(parsed);
|
|
36
|
+
return { config: validated, resolvedPath: candidate };
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
throw new Error(`Failed to parse FerryCat configuration file at '${candidate}': ${err instanceof Error ? err.message : String(err)}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Return empty valid default configuration if no file exists
|
|
44
|
+
return {
|
|
45
|
+
config: FerryCatConfigFileSchema.parse({}),
|
|
46
|
+
resolvedPath: null,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export function notifyOperator(title, message) {
|
|
50
|
+
try {
|
|
51
|
+
const timestamp = new Date().toISOString();
|
|
52
|
+
// Always emit structured line to stderr/stdout
|
|
53
|
+
process.stderr.write(`[FerryCat Daemon Notice] ${timestamp} | ${title}: ${message}\n`);
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
if (err && typeof err === 'object' && 'code' in err && err.code === 'EPIPE') {
|
|
57
|
+
// EPIPE indicates downstream logger closed its pipe early; safe to swallow silently
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export class FerryCatDaemon {
|
|
63
|
+
engine;
|
|
64
|
+
config;
|
|
65
|
+
configPath;
|
|
66
|
+
lockId;
|
|
67
|
+
leaseTtlSec;
|
|
68
|
+
heartbeatIntervalMs;
|
|
69
|
+
pollIntervalMs;
|
|
70
|
+
ownerToken;
|
|
71
|
+
targetAgentFilter;
|
|
72
|
+
notifyEnabled;
|
|
73
|
+
isRunning = false;
|
|
74
|
+
isLeader = false;
|
|
75
|
+
heartbeatTimer = null;
|
|
76
|
+
pollTimer = null;
|
|
77
|
+
signalCleanupRegistered = false;
|
|
78
|
+
activeInFlightContract = null;
|
|
79
|
+
constructor(options = {}) {
|
|
80
|
+
const { config, resolvedPath } = loadFerryCatConfig(options.configPath);
|
|
81
|
+
this.config = config;
|
|
82
|
+
this.configPath = resolvedPath;
|
|
83
|
+
this.engine = new FerryCatEngine({ dbPath: options.dbPath });
|
|
84
|
+
this.lockId = options.lockId ?? config.daemon.lock_id ?? 'global';
|
|
85
|
+
// Ensure lease TTL is at least 5 seconds
|
|
86
|
+
const reqTtl = options.leaseTtlSec ?? config.daemon.lease_ttl_sec ?? 30;
|
|
87
|
+
this.leaseTtlSec = Math.max(5, reqTtl);
|
|
88
|
+
// Enforce heartbeat interval <= leaseTtl / 2 to prevent false expirations
|
|
89
|
+
const reqHeartbeat = options.heartbeatIntervalMs ?? config.daemon.heartbeat_interval_ms ?? 5000;
|
|
90
|
+
const maxHeartbeat = Math.floor((this.leaseTtlSec * 1000) / 2);
|
|
91
|
+
this.heartbeatIntervalMs = Math.min(reqHeartbeat, maxHeartbeat);
|
|
92
|
+
this.pollIntervalMs = options.pollIntervalMs ?? config.daemon.poll_interval_ms ?? 1000;
|
|
93
|
+
// Critical Finding 1: Never accept a static shared owner_token across daemon processes.
|
|
94
|
+
// Always generate a unique cryptographic token per runtime instance.
|
|
95
|
+
this.ownerToken = `daemon-${process.pid}-${crypto.randomBytes(8).toString('hex')}`;
|
|
96
|
+
this.targetAgentFilter = options.targetAgent;
|
|
97
|
+
this.notifyEnabled = options.notify ?? config.daemon.notify ?? true;
|
|
98
|
+
}
|
|
99
|
+
registerSignalHandlers() {
|
|
100
|
+
if (this.signalCleanupRegistered)
|
|
101
|
+
return;
|
|
102
|
+
this.signalCleanupRegistered = true;
|
|
103
|
+
const cleanup = (sig) => {
|
|
104
|
+
if (this.notifyEnabled) {
|
|
105
|
+
notifyOperator('Shutdown', `Received ${sig}, terminating children and releasing lease...`);
|
|
106
|
+
}
|
|
107
|
+
this.stop();
|
|
108
|
+
terminateActiveChildrenSync();
|
|
109
|
+
this.engine.releaseDaemonLease({ lock_id: this.lockId, owner_token: this.ownerToken });
|
|
110
|
+
this.engine.close();
|
|
111
|
+
process.exit(0);
|
|
112
|
+
};
|
|
113
|
+
process.once('SIGINT', () => cleanup('SIGINT'));
|
|
114
|
+
process.once('SIGTERM', () => cleanup('SIGTERM'));
|
|
115
|
+
}
|
|
116
|
+
acquireLease() {
|
|
117
|
+
try {
|
|
118
|
+
const res = this.engine.acquireDaemonLease({
|
|
119
|
+
lock_id: this.lockId,
|
|
120
|
+
owner_token: this.ownerToken,
|
|
121
|
+
ttl_sec: this.leaseTtlSec,
|
|
122
|
+
metadata: {
|
|
123
|
+
pid: process.pid,
|
|
124
|
+
hostname: os.hostname(),
|
|
125
|
+
platform: process.platform,
|
|
126
|
+
config_path: this.configPath,
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
if (res.ok) {
|
|
130
|
+
this.isLeader = true;
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
this.isLeader = false;
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
this.isLeader = false;
|
|
138
|
+
if (this.notifyEnabled) {
|
|
139
|
+
notifyOperator('Lease Error', `Acquire lease error: ${err instanceof Error ? err.message : String(err)}`);
|
|
140
|
+
}
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
renewLease() {
|
|
145
|
+
if (!this.isLeader)
|
|
146
|
+
return false;
|
|
147
|
+
try {
|
|
148
|
+
const res = this.engine.renewDaemonLease({
|
|
149
|
+
lock_id: this.lockId,
|
|
150
|
+
owner_token: this.ownerToken,
|
|
151
|
+
ttl_sec: this.leaseTtlSec,
|
|
152
|
+
});
|
|
153
|
+
if (!res.ok) {
|
|
154
|
+
// Critical WorkBuddy P1 Fix: When lease is lost, don't kill active contract to FAILED.
|
|
155
|
+
// First voluntarily release in-flight contract back to queue tail so new leader can claim it!
|
|
156
|
+
this.isLeader = false;
|
|
157
|
+
if (this.activeInFlightContract) {
|
|
158
|
+
try {
|
|
159
|
+
this.engine.releaseContract({
|
|
160
|
+
contract_id: this.activeInFlightContract.contract_id,
|
|
161
|
+
agent_id: this.activeInFlightContract.target_agent,
|
|
162
|
+
claim_token: this.activeInFlightContract.claim_token,
|
|
163
|
+
reason: 'DAEMON_LEASE_LOST',
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// best-effort release
|
|
168
|
+
}
|
|
169
|
+
this.activeInFlightContract = null;
|
|
170
|
+
}
|
|
171
|
+
terminateActiveChildrenSync();
|
|
172
|
+
if (this.notifyEnabled) {
|
|
173
|
+
notifyOperator('Lease Lost', `Failed to renew lease '${this.lockId}': ${res.message}. In-flight contract released and children terminated.`);
|
|
174
|
+
}
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
catch (err) {
|
|
180
|
+
// WorkBuddy Finding: On SQLite/IO exception, demote to non-leader, backoff, and release in-flight contract
|
|
181
|
+
this.isLeader = false;
|
|
182
|
+
if (this.activeInFlightContract) {
|
|
183
|
+
try {
|
|
184
|
+
this.engine.releaseContract({
|
|
185
|
+
contract_id: this.activeInFlightContract.contract_id,
|
|
186
|
+
agent_id: this.activeInFlightContract.target_agent,
|
|
187
|
+
claim_token: this.activeInFlightContract.claim_token,
|
|
188
|
+
reason: 'DAEMON_HEARTBEAT_EXCEPTION',
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// best-effort release
|
|
193
|
+
}
|
|
194
|
+
this.activeInFlightContract = null;
|
|
195
|
+
}
|
|
196
|
+
terminateActiveChildrenSync();
|
|
197
|
+
if (this.notifyEnabled) {
|
|
198
|
+
notifyOperator('Lease Error', `Heartbeat exception: ${err instanceof Error ? err.message : String(err)}. Contract released and children terminated.`);
|
|
199
|
+
}
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
releaseLease() {
|
|
204
|
+
if (this.isLeader) {
|
|
205
|
+
try {
|
|
206
|
+
this.engine.releaseDaemonLease({
|
|
207
|
+
lock_id: this.lockId,
|
|
208
|
+
owner_token: this.ownerToken,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
// best-effort cleanup on shutdown
|
|
213
|
+
}
|
|
214
|
+
this.isLeader = false;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
resolveHandler(targetAgent, taskType) {
|
|
218
|
+
const agentConfig = this.config.agents[targetAgent];
|
|
219
|
+
if (!agentConfig)
|
|
220
|
+
return null;
|
|
221
|
+
const typedTask = taskType;
|
|
222
|
+
if (agentConfig.handlers && agentConfig.handlers[typedTask]) {
|
|
223
|
+
return agentConfig.handlers[typedTask];
|
|
224
|
+
}
|
|
225
|
+
if (agentConfig.default_handler) {
|
|
226
|
+
return agentConfig.default_handler;
|
|
227
|
+
}
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Process a single cycle: check lease, poll task, execute configured handler if matched.
|
|
232
|
+
*/
|
|
233
|
+
async pollAndDispatchOnce() {
|
|
234
|
+
if (!this.isLeader) {
|
|
235
|
+
const acquired = this.acquireLease();
|
|
236
|
+
if (!acquired) {
|
|
237
|
+
return { processed: false, reason: 'LEASE_NOT_HELD' };
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
// Determine target agent(s) to poll
|
|
241
|
+
const targetAgentsToPoll = this.targetAgentFilter
|
|
242
|
+
? [this.targetAgentFilter]
|
|
243
|
+
: Object.keys(this.config.agents);
|
|
244
|
+
if (targetAgentsToPoll.length === 0) {
|
|
245
|
+
// If no configured agents, poll without target agent filter
|
|
246
|
+
return this.pollAgentQueue(undefined);
|
|
247
|
+
}
|
|
248
|
+
for (const agent of targetAgentsToPoll) {
|
|
249
|
+
const res = await this.pollAgentQueue(agent);
|
|
250
|
+
if (res.processed) {
|
|
251
|
+
return res;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return { processed: false, reason: 'NO_TASK_AVAILABLE' };
|
|
255
|
+
}
|
|
256
|
+
async pollAgentQueue(agentId) {
|
|
257
|
+
// Determine configured task types for this agent to avoid claiming unhandled tasks (WorkBuddy P1)
|
|
258
|
+
let eligibleTaskTypes;
|
|
259
|
+
if (agentId && this.config.agents[agentId]) {
|
|
260
|
+
const agentCfg = this.config.agents[agentId];
|
|
261
|
+
if (!agentCfg.default_handler && agentCfg.handlers) {
|
|
262
|
+
eligibleTaskTypes = Object.keys(agentCfg.handlers);
|
|
263
|
+
if (eligibleTaskTypes.length === 0) {
|
|
264
|
+
// If agent has no handlers and no default_handler, skip polling this agent completely
|
|
265
|
+
return { processed: false, reason: 'NO_HANDLERS_CONFIGURED' };
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
const pollResult = this.engine.pollNextTask({
|
|
270
|
+
agent_id: agentId,
|
|
271
|
+
task_types: eligibleTaskTypes,
|
|
272
|
+
});
|
|
273
|
+
if (!pollResult.has_task || !pollResult.contract || pollResult.status !== 'CLAIMED') {
|
|
274
|
+
return { processed: false, reason: 'NO_TASK_AVAILABLE' };
|
|
275
|
+
}
|
|
276
|
+
const contract = pollResult.contract;
|
|
277
|
+
const handler = this.resolveHandler(contract.target_agent, contract.task_type);
|
|
278
|
+
if (!handler) {
|
|
279
|
+
// Fallback: If somehow claimed without handler (e.g. default_handler was missing), release back to queue cleanly
|
|
280
|
+
const warningMsg = `No handler configured in ferrycat.config.json for agent '${contract.target_agent}' task '${contract.task_type}'. Releasing contract back to queue.`;
|
|
281
|
+
if (this.notifyEnabled) {
|
|
282
|
+
notifyOperator('Unhandled Task', warningMsg);
|
|
283
|
+
}
|
|
284
|
+
this.engine.releaseContract({
|
|
285
|
+
contract_id: contract.contract_id,
|
|
286
|
+
agent_id: contract.target_agent,
|
|
287
|
+
claim_token: contract.claim_token,
|
|
288
|
+
reason: `NO_HANDLER_CONFIGURED: Task type '${contract.task_type}' not handled by this node.`,
|
|
289
|
+
});
|
|
290
|
+
return {
|
|
291
|
+
processed: false,
|
|
292
|
+
contract_id: contract.contract_id,
|
|
293
|
+
reason: 'NO_HANDLER_CONFIGURED',
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
if (this.notifyEnabled) {
|
|
297
|
+
notifyOperator('Task Claimed', `Agent '${contract.target_agent}' executing contract ${contract.contract_id} (${contract.task_type}: "${contract.title}") via ${handler.exec_file}`);
|
|
298
|
+
}
|
|
299
|
+
// Track active in-flight contract for graceful lease loss failover
|
|
300
|
+
this.activeInFlightContract = {
|
|
301
|
+
contract_id: contract.contract_id,
|
|
302
|
+
target_agent: contract.target_agent,
|
|
303
|
+
claim_token: contract.claim_token,
|
|
304
|
+
};
|
|
305
|
+
try {
|
|
306
|
+
// Forward configured args and pass_env (contract's own exec_ttl_sec is authoritative)
|
|
307
|
+
const execResult = await executeTaskAndFulfill(this.engine, contract, {
|
|
308
|
+
execFile: handler.exec_file,
|
|
309
|
+
passEnv: handler.pass_env,
|
|
310
|
+
args: handler.args,
|
|
311
|
+
});
|
|
312
|
+
if (this.notifyEnabled) {
|
|
313
|
+
notifyOperator('Task Finished', `Contract ${contract.contract_id} concluded with status '${execResult.status}' (ok=${execResult.ok})`);
|
|
314
|
+
}
|
|
315
|
+
return {
|
|
316
|
+
processed: true,
|
|
317
|
+
contract_id: contract.contract_id,
|
|
318
|
+
status: execResult.status,
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
finally {
|
|
322
|
+
this.activeInFlightContract = null;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
async start() {
|
|
326
|
+
this.registerSignalHandlers();
|
|
327
|
+
this.isRunning = true;
|
|
328
|
+
// Heartbeat ticker loop for lease renewal
|
|
329
|
+
this.heartbeatTimer = setInterval(() => {
|
|
330
|
+
try {
|
|
331
|
+
if (this.isRunning && this.isLeader) {
|
|
332
|
+
this.renewLease();
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
catch (err) {
|
|
336
|
+
if (this.notifyEnabled) {
|
|
337
|
+
notifyOperator('Heartbeat Ticker Error', err instanceof Error ? err.message : String(err));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}, this.heartbeatIntervalMs);
|
|
341
|
+
// Main polling loop
|
|
342
|
+
const tick = async () => {
|
|
343
|
+
if (!this.isRunning)
|
|
344
|
+
return;
|
|
345
|
+
try {
|
|
346
|
+
await this.pollAndDispatchOnce();
|
|
347
|
+
}
|
|
348
|
+
catch (err) {
|
|
349
|
+
if (this.notifyEnabled) {
|
|
350
|
+
notifyOperator('Daemon Loop Error', err instanceof Error ? err.message : String(err));
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
if (this.isRunning) {
|
|
354
|
+
this.pollTimer = setTimeout(tick, this.pollIntervalMs);
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
tick();
|
|
358
|
+
}
|
|
359
|
+
stop() {
|
|
360
|
+
this.isRunning = false;
|
|
361
|
+
if (this.heartbeatTimer) {
|
|
362
|
+
clearInterval(this.heartbeatTimer);
|
|
363
|
+
this.heartbeatTimer = null;
|
|
364
|
+
}
|
|
365
|
+
if (this.pollTimer) {
|
|
366
|
+
clearTimeout(this.pollTimer);
|
|
367
|
+
this.pollTimer = null;
|
|
368
|
+
}
|
|
369
|
+
this.releaseLease();
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
//# sourceMappingURL=daemon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
|
package/dist/demo.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export interface DemoOptions {
|
|
2
|
+
/** Keep the sandbox directory on disk and report its path instead of deleting it. */
|
|
3
|
+
keep?: boolean;
|
|
4
|
+
/** Suppress all human-readable output; the caller receives only the structured result. */
|
|
5
|
+
json?: boolean;
|
|
6
|
+
/** Sink for human-readable lines. Defaults to process.stdout. Ignored when `json` is true. */
|
|
7
|
+
write?: (line: string) => void;
|
|
8
|
+
/** Force ANSI colors on/off. Defaults to auto-detection (TTY and no NO_COLOR). */
|
|
9
|
+
color?: boolean;
|
|
10
|
+
/** Lifetime of the demo child process in ms (0 = finish immediately). */
|
|
11
|
+
execDelayMs?: number;
|
|
12
|
+
/** Execution TTL granted to the demo contract, in seconds. */
|
|
13
|
+
execTtlSec?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface DemoStepRecord {
|
|
16
|
+
index: number;
|
|
17
|
+
total: number;
|
|
18
|
+
title: string;
|
|
19
|
+
fields: Record<string, string>;
|
|
20
|
+
}
|
|
21
|
+
export interface DemoResult {
|
|
22
|
+
ok: boolean;
|
|
23
|
+
sandbox: string;
|
|
24
|
+
sandbox_kept: boolean;
|
|
25
|
+
contract_id: string;
|
|
26
|
+
claim_token: string;
|
|
27
|
+
status: string;
|
|
28
|
+
verdict: 'PASSED' | 'CHANGES_REQUESTED';
|
|
29
|
+
issues: string[];
|
|
30
|
+
dirty_files: number;
|
|
31
|
+
heartbeat_renewals: number;
|
|
32
|
+
elapsed_ms: number;
|
|
33
|
+
steps: DemoStepRecord[];
|
|
34
|
+
warnings: string[];
|
|
35
|
+
}
|
|
36
|
+
export declare function runDemo(options?: DemoOptions): Promise<DemoResult>;
|