agentspeak-cli 0.12.0 → 0.14.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.
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Per-meeting background `run` loop manager, used by the auto-act
3
+ * branch of `agentspeak-cli watch`.
4
+ *
5
+ * When watch sees an `invite` notification, it:
6
+ * 1. Runs `agentspeak-cli join <invite-url>` (short, foreground,
7
+ * pure HTTP — no LLM required).
8
+ * 2. Spawns `agentspeak-cli run --meeting <id> --exec
9
+ * ~/.agentspeak/reply.sh` as a detached background process.
10
+ *
11
+ * Step 2 is what turns the agent from "joined but idle" into a true
12
+ * autonomous participant — the `run` loop long-polls /my_turn and
13
+ * invokes the reply shim on every assigned turn. Operators wire
14
+ * their LLM client into reply.sh (Claude Code, Cursor agent, OpenAI
15
+ * HTTP, etc.). Unedited shims self-quit after AUTO_SHIM_SELF_QUIT_AFTER
16
+ * turns so an un-configured agent still exits the meeting cleanly.
17
+ *
18
+ * Idempotency: pid-file per meeting under `~/.agentspeak/runs/<id>.run.pid`,
19
+ * probed with `process.kill(pid, 0)`. Duplicate invite events (server
20
+ * dedups via `dedup_key`, but belts-and-suspenders) are no-ops.
21
+ *
22
+ * Portability: same pattern as `watch-daemon.ts` — detached spawn
23
+ * with `.unref()` + append-mode log fd, works on macOS / Linux /
24
+ * git-bash / WSL / native Windows.
25
+ */
26
+ export interface RunSpawnerPaths {
27
+ runsDir: string;
28
+ joinLogPath: string;
29
+ runLogPath: string;
30
+ runPidPath: string;
31
+ }
32
+ export declare function runSpawnerPaths(meetingId: string): RunSpawnerPaths;
33
+ /**
34
+ * Report whether a detached `run` loop for this meeting is currently
35
+ * alive. Stale pid files (process no longer exists) are cleaned up as
36
+ * a side-effect so the next `spawnRunForMeeting` call is free to
37
+ * start a fresh loop.
38
+ */
39
+ export declare function isRunAlive(meetingId: string): {
40
+ alive: boolean;
41
+ pid: number | null;
42
+ };
43
+ export interface JoinResult {
44
+ ok: boolean;
45
+ exitCode: number | null;
46
+ signal: NodeJS.Signals | null;
47
+ logPath: string;
48
+ }
49
+ /**
50
+ * Invoke `agentspeak-cli join <inviteUrl>` and wait for it to exit.
51
+ * Join is cheap (one HTTP POST plus a skill fetch) and synchronous so
52
+ * we can decide whether to proceed to `run` only on success. Output
53
+ * is tee'd to `~/.agentspeak/runs/<meetingId>.join.log` to preserve
54
+ * the [JOINED ...] confirmation line for post-mortem debugging.
55
+ */
56
+ export declare function runJoin(opts: {
57
+ inviteUrl: string;
58
+ meetingId: string;
59
+ cliEntry?: string;
60
+ nodeBinary?: string;
61
+ timeoutMs?: number;
62
+ }): JoinResult;
63
+ export interface SpawnRunResult {
64
+ started: boolean;
65
+ reused: boolean;
66
+ pid: number | null;
67
+ pidPath: string;
68
+ logPath: string;
69
+ reason?: string;
70
+ }
71
+ /**
72
+ * Spawn `agentspeak-cli run --meeting <id> --exec <reply.sh>` as a
73
+ * detached background process, idempotently. The reply shim path is
74
+ * resolved via `autoShimPaths()` so every install shares the single
75
+ * operator-editable `~/.agentspeak/reply.sh`.
76
+ *
77
+ * Caller contract:
78
+ * - Only call this AFTER `runJoin` returned `ok: true`. The `run`
79
+ * loop itself does not re-run join, so a 404 here would burn its
80
+ * smoke-test budget and exit.
81
+ * - Duplicate calls for the same meetingId are no-ops when the
82
+ * previous loop is still alive.
83
+ */
84
+ export declare function spawnRunForMeeting(opts: {
85
+ meetingId: string;
86
+ cliEntry?: string;
87
+ nodeBinary?: string;
88
+ extraArgs?: string[];
89
+ }): SpawnRunResult;
90
+ /**
91
+ * Stop a running per-meeting loop, if any. Exposed for completeness
92
+ * (tests + future `agentspeak run stop --meeting <id>` subcommand).
93
+ */
94
+ export declare function stopRunForMeeting(meetingId: string): {
95
+ stopped: boolean;
96
+ pid: number | null;
97
+ reason?: string;
98
+ };
99
+ //# sourceMappingURL=run-spawner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-spawner.d.ts","sourceRoot":"","sources":["../src/run-spawner.ts"],"names":[],"mappings":"AAaA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,CAQlE;AAuBD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAOpF;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,UAAU,CAyCb;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB,GAAG,cAAc,CAsFjB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG;IACpD,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAmBA"}
@@ -0,0 +1,220 @@
1
+ import { spawn, spawnSync } from 'node:child_process';
2
+ import { existsSync, mkdirSync, openSync, readFileSync, unlinkSync, writeFileSync, } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { autoShimPaths } from './auto-shim.js';
5
+ import { home } from './state.js';
6
+ export function runSpawnerPaths(meetingId) {
7
+ const dir = join(home(), 'runs');
8
+ return {
9
+ runsDir: dir,
10
+ joinLogPath: join(dir, `${meetingId}.join.log`),
11
+ runLogPath: join(dir, `${meetingId}.run.log`),
12
+ runPidPath: join(dir, `${meetingId}.run.pid`),
13
+ };
14
+ }
15
+ function pidIsAlive(pid) {
16
+ try {
17
+ process.kill(pid, 0);
18
+ return true;
19
+ }
20
+ catch {
21
+ return false;
22
+ }
23
+ }
24
+ function readExistingPid(pidPath) {
25
+ if (!existsSync(pidPath))
26
+ return null;
27
+ try {
28
+ const raw = readFileSync(pidPath, 'utf8').trim();
29
+ const pid = Number.parseInt(raw, 10);
30
+ if (!Number.isFinite(pid) || pid <= 0)
31
+ return null;
32
+ return pid;
33
+ }
34
+ catch {
35
+ return null;
36
+ }
37
+ }
38
+ /**
39
+ * Report whether a detached `run` loop for this meeting is currently
40
+ * alive. Stale pid files (process no longer exists) are cleaned up as
41
+ * a side-effect so the next `spawnRunForMeeting` call is free to
42
+ * start a fresh loop.
43
+ */
44
+ export function isRunAlive(meetingId) {
45
+ const { runPidPath } = runSpawnerPaths(meetingId);
46
+ const pid = readExistingPid(runPidPath);
47
+ if (!pid)
48
+ return { alive: false, pid: null };
49
+ if (pidIsAlive(pid))
50
+ return { alive: true, pid };
51
+ try {
52
+ unlinkSync(runPidPath);
53
+ }
54
+ catch { /* best-effort */ }
55
+ return { alive: false, pid };
56
+ }
57
+ /**
58
+ * Invoke `agentspeak-cli join <inviteUrl>` and wait for it to exit.
59
+ * Join is cheap (one HTTP POST plus a skill fetch) and synchronous so
60
+ * we can decide whether to proceed to `run` only on success. Output
61
+ * is tee'd to `~/.agentspeak/runs/<meetingId>.join.log` to preserve
62
+ * the [JOINED ...] confirmation line for post-mortem debugging.
63
+ */
64
+ export function runJoin(opts) {
65
+ const { inviteUrl, meetingId } = opts;
66
+ const { runsDir, joinLogPath } = runSpawnerPaths(meetingId);
67
+ mkdirSync(runsDir, { recursive: true });
68
+ const nodeBinary = opts.nodeBinary ?? process.execPath;
69
+ const cliEntry = opts.cliEntry ?? process.argv[1];
70
+ if (!cliEntry) {
71
+ return { ok: false, exitCode: null, signal: null, logPath: joinLogPath };
72
+ }
73
+ try {
74
+ writeFileSync(joinLogPath, `\n[${new Date().toISOString()}] join starting (invite=${inviteUrl})\n`, { flag: 'a' });
75
+ }
76
+ catch { /* best-effort */ }
77
+ const result = spawnSync(nodeBinary, [cliEntry, 'join', inviteUrl], {
78
+ timeout: opts.timeoutMs ?? 60_000,
79
+ env: process.env,
80
+ stdio: 'pipe',
81
+ encoding: 'utf8',
82
+ });
83
+ const combined = [
84
+ result.stdout ?? '',
85
+ result.stderr ?? '',
86
+ `[${new Date().toISOString()}] join exited code=${result.status} signal=${result.signal ?? ''}\n`,
87
+ ].join('\n');
88
+ try {
89
+ writeFileSync(joinLogPath, combined, { flag: 'a' });
90
+ }
91
+ catch { /* best-effort */ }
92
+ return {
93
+ ok: result.status === 0,
94
+ exitCode: result.status,
95
+ signal: result.signal,
96
+ logPath: joinLogPath,
97
+ };
98
+ }
99
+ /**
100
+ * Spawn `agentspeak-cli run --meeting <id> --exec <reply.sh>` as a
101
+ * detached background process, idempotently. The reply shim path is
102
+ * resolved via `autoShimPaths()` so every install shares the single
103
+ * operator-editable `~/.agentspeak/reply.sh`.
104
+ *
105
+ * Caller contract:
106
+ * - Only call this AFTER `runJoin` returned `ok: true`. The `run`
107
+ * loop itself does not re-run join, so a 404 here would burn its
108
+ * smoke-test budget and exit.
109
+ * - Duplicate calls for the same meetingId are no-ops when the
110
+ * previous loop is still alive.
111
+ */
112
+ export function spawnRunForMeeting(opts) {
113
+ const { meetingId } = opts;
114
+ const { runsDir, runLogPath, runPidPath } = runSpawnerPaths(meetingId);
115
+ mkdirSync(runsDir, { recursive: true });
116
+ const alive = isRunAlive(meetingId);
117
+ if (alive.alive && alive.pid) {
118
+ return {
119
+ started: false,
120
+ reused: true,
121
+ pid: alive.pid,
122
+ pidPath: runPidPath,
123
+ logPath: runLogPath,
124
+ };
125
+ }
126
+ const nodeBinary = opts.nodeBinary ?? process.execPath;
127
+ const cliEntry = opts.cliEntry ?? process.argv[1];
128
+ if (!cliEntry) {
129
+ return {
130
+ started: false,
131
+ reused: false,
132
+ pid: null,
133
+ pidPath: runPidPath,
134
+ logPath: runLogPath,
135
+ reason: 'no_cli_entry',
136
+ };
137
+ }
138
+ // Resolve the operator's reply shim. The auto-shim is written on
139
+ // `init` and the EDIT-ME block is where operators plug in their
140
+ // LLM client. If the shim is missing we still proceed — `run`
141
+ // will surface a clear smoke-test failure in the per-meeting log.
142
+ const { posixPath: replyShim } = autoShimPaths();
143
+ const logFd = openSync(runLogPath, 'a');
144
+ try {
145
+ writeFileSync(runLogPath, `\n[${new Date().toISOString()}] run starting (meeting=${meetingId} exec=${replyShim})\n`, { flag: 'a' });
146
+ }
147
+ catch { /* best-effort */ }
148
+ const args = [
149
+ 'run',
150
+ '--meeting',
151
+ meetingId,
152
+ '--exec',
153
+ replyShim,
154
+ ...(opts.extraArgs ?? []),
155
+ ];
156
+ const child = spawn(nodeBinary, [cliEntry, ...args], {
157
+ detached: true,
158
+ stdio: ['ignore', logFd, logFd],
159
+ env: process.env,
160
+ });
161
+ child.unref();
162
+ if (!child.pid) {
163
+ return {
164
+ started: false,
165
+ reused: false,
166
+ pid: null,
167
+ pidPath: runPidPath,
168
+ logPath: runLogPath,
169
+ reason: 'spawn_failed',
170
+ };
171
+ }
172
+ try {
173
+ writeFileSync(runPidPath, `${child.pid}\n`, { encoding: 'utf8' });
174
+ }
175
+ catch {
176
+ // Pid file is best-effort; if we can't persist we may spawn a
177
+ // duplicate next time, which is bounded by the `run` loop's own
178
+ // exit-on-terminal-status behaviour.
179
+ }
180
+ return {
181
+ started: true,
182
+ reused: false,
183
+ pid: child.pid,
184
+ pidPath: runPidPath,
185
+ logPath: runLogPath,
186
+ };
187
+ }
188
+ /**
189
+ * Stop a running per-meeting loop, if any. Exposed for completeness
190
+ * (tests + future `agentspeak run stop --meeting <id>` subcommand).
191
+ */
192
+ export function stopRunForMeeting(meetingId) {
193
+ const { runPidPath } = runSpawnerPaths(meetingId);
194
+ const pid = readExistingPid(runPidPath);
195
+ if (!pid)
196
+ return { stopped: false, pid: null, reason: 'no_pid_file' };
197
+ if (!pidIsAlive(pid)) {
198
+ try {
199
+ unlinkSync(runPidPath);
200
+ }
201
+ catch { /* best-effort */ }
202
+ return { stopped: false, pid, reason: 'already_dead' };
203
+ }
204
+ try {
205
+ process.kill(pid, 'SIGTERM');
206
+ }
207
+ catch (err) {
208
+ return {
209
+ stopped: false,
210
+ pid,
211
+ reason: `kill_failed: ${err instanceof Error ? err.message : String(err)}`,
212
+ };
213
+ }
214
+ try {
215
+ unlinkSync(runPidPath);
216
+ }
217
+ catch { /* best-effort */ }
218
+ return { stopped: true, pid };
219
+ }
220
+ //# sourceMappingURL=run-spawner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-spawner.js","sourceRoot":"","sources":["../src/run-spawner.ts"],"names":[],"mappings":"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"}
@@ -54,7 +54,7 @@ export interface StepSkillSnippet {
54
54
  *
55
55
  * Bump this constant whenever you bump the protocol root skill.
56
56
  */
57
- export declare const CLI_SKILL_VERSION = 31;
57
+ export declare const CLI_SKILL_VERSION = 33;
58
58
  export interface RenderedSkillBlock {
59
59
  name: string;
60
60
  path: string;
@@ -249,7 +249,7 @@ const ROOT_SKILL_DESCRIPTION = 'AgentSpeak is an online meeting coordinator for
249
249
  *
250
250
  * Bump this constant whenever you bump the protocol root skill.
251
251
  */
252
- export const CLI_SKILL_VERSION = 31;
252
+ export const CLI_SKILL_VERSION = 33;
253
253
  function skillFrontmatter(name, description, version = CLI_SKILL_VERSION) {
254
254
  return [
255
255
  '---',
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Single source of truth for the CLI's semver string.
3
+ *
4
+ * Kept in its own module (rather than re-exported from index.ts) so
5
+ * sub-modules like `watch-daemon.ts` can import it without pulling the
6
+ * whole argv dispatcher into their graph.
7
+ *
8
+ * Must be kept in sync with `package.json > version` at release time.
9
+ * `npm run build` does not auto-derive this — a stale constant will
10
+ * cause the version-stamped watch-daemon restart check to misfire, so
11
+ * release hygiene: bump both files in the same commit.
12
+ */
13
+ export declare const CLI_VERSION = "0.14.1";
14
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,WAAW,WAAW,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Single source of truth for the CLI's semver string.
3
+ *
4
+ * Kept in its own module (rather than re-exported from index.ts) so
5
+ * sub-modules like `watch-daemon.ts` can import it without pulling the
6
+ * whole argv dispatcher into their graph.
7
+ *
8
+ * Must be kept in sync with `package.json > version` at release time.
9
+ * `npm run build` does not auto-derive this — a stale constant will
10
+ * cause the version-stamped watch-daemon restart check to misfire, so
11
+ * release hygiene: bump both files in the same commit.
12
+ */
13
+ export const CLI_VERSION = '0.14.1';
14
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC"}
@@ -34,7 +34,15 @@ export interface EnsureWatchResult {
34
34
  started: boolean;
35
35
  /** True iff an existing live daemon was reused. */
36
36
  reused: boolean;
37
+ /**
38
+ * True iff an existing daemon was killed and replaced because its
39
+ * stamped CLI version did not match the current one (e.g. the caller
40
+ * is `tutorial` running 0.14.1 but the daemon was spawned by 0.13.0).
41
+ */
42
+ restartedForVersionMismatch: boolean;
37
43
  pid: number | null;
44
+ /** CLI version that spawned the CURRENT daemon (null for legacy pid files). */
45
+ previousCliVersion?: string | null;
38
46
  pidPath: string;
39
47
  logPath: string;
40
48
  /** Populated only when reused=false && started=false (i.e. skipped). */
@@ -53,6 +61,11 @@ export declare function ensureWatchRunning(opts?: {
53
61
  cliEntry?: string;
54
62
  nodeBinary?: string;
55
63
  extraArgs?: string[];
64
+ /**
65
+ * CLI version to stamp into the pid file. Defaults to the compiled-in
66
+ * `CLI_VERSION`. Tests override this to simulate upgrade scenarios.
67
+ */
68
+ cliVersion?: string;
56
69
  }): EnsureWatchResult;
57
70
  export interface StopWatchResult {
58
71
  stopped: boolean;
@@ -67,10 +80,12 @@ export declare function stopWatch(): StopWatchResult;
67
80
  /**
68
81
  * Report whether a daemon is currently running, for `watch status` /
69
82
  * doctor-style introspection. Returns null when no pid file exists.
83
+ * `cliVersion` is null for legacy pid files written by CLI <= 0.14.0.
70
84
  */
71
85
  export declare function watchStatus(): {
72
86
  pid: number;
73
87
  alive: boolean;
88
+ cliVersion: string | null;
74
89
  } | null;
75
90
  /**
76
91
  * Ensure the agent's wake_config advertises pull mode (when unset)
@@ -1 +1 @@
1
- {"version":3,"file":"watch-daemon.d.ts","sourceRoot":"","sources":["../src/watch-daemon.ts"],"names":[],"mappings":"AAIA,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGtE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,gBAAgB,IAAI,gBAAgB,CAMnD;AAED,MAAM,WAAW,iBAAiB;IAChC,gDAAgD;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,mDAAmD;IACnD,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAgCD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,GAAE;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB,GAAG,iBAAiB,CAkFzB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI,eAAe,CAqB3C;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAKpE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,EACvD,WAAW,EAAE,WAAW,GAAG,SAAS,EACpC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GACzB,OAAO,CAAC,IAAI,CAAC,CA8Df"}
1
+ {"version":3,"file":"watch-daemon.d.ts","sourceRoot":"","sources":["../src/watch-daemon.ts"],"names":[],"mappings":"AAIA,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAItE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,gBAAgB,IAAI,gBAAgB,CAMnD;AAED,MAAM,WAAW,iBAAiB;IAChC,gDAAgD;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,mDAAmD;IACnD,MAAM,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,2BAA2B,EAAE,OAAO,CAAC;IACrC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,+EAA+E;IAC/E,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAoED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,GAAE;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,iBAAiB,CAoHzB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI,eAAe,CAqB3C;AAED;;;;GAIG;AACH,wBAAgB,WAAW,IAAI;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAK/F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,EACvD,WAAW,EAAE,WAAW,GAAG,SAAS,EACpC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GACzB,OAAO,CAAC,IAAI,CAAC,CAuEf"}