taskflow-core 0.2.2 → 0.2.3

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 CHANGED
@@ -131,7 +131,7 @@ Save it as `.pi/taskflows/audit-api.json`, then run:
131
131
  /tf:audit-api dir=src/api
132
132
  ```
133
133
 
134
- On Codex, Claude Code, OpenCode, and Grok Build, run the same saved definition by name through `taskflow_run`.
134
+ On Codex, Claude Code, OpenCode, and Grok Build, run the same saved definition by name through `taskflow_run`. For long DAGs, use `mode: "background"`, then manage the durable run with `taskflow_runs` (`list` / `status` / `wait` / `cancel`); list output reports active concurrency and can filter `running` or `terminal` runs.
135
135
 
136
136
  [Follow the full quickstart →](https://heggria.github.io/taskflow/en/docs/getting-started)
137
137
 
@@ -315,7 +315,7 @@ claude plugin install claude-taskflow@taskflow
315
315
 
316
316
  ```bash
317
317
  opencode mcp add taskflow -- \
318
- npx -y -p opencode-taskflow@0.2.2 opencode-taskflow-mcp
318
+ npx -y -p opencode-taskflow@0.2.3 opencode-taskflow-mcp
319
319
  ```
320
320
 
321
321
  [OpenCode guide →](https://heggria.github.io/taskflow/en/docs/guides/opencode)
@@ -324,7 +324,7 @@ opencode mcp add taskflow -- \
324
324
 
325
325
  ```bash
326
326
  grok mcp add taskflow -- \
327
- npx -y -p grok-taskflow@0.2.2 grok-taskflow-mcp
327
+ npx -y -p grok-taskflow@0.2.3 grok-taskflow-mcp
328
328
  ```
329
329
 
330
330
  Grok Build support is new in 0.2. Its CLI stream does not report token/cost usage, so budget-declaring flows are rejected rather than silently running without enforcement.
@@ -365,6 +365,7 @@ The test suite covers orchestration semantics, persistence and file-lock races,
365
365
  | [Host Guides](https://heggria.github.io/taskflow/en/docs/guides/) | Pi, Codex, Claude Code, OpenCode, and Grok setup |
366
366
  | [Reference](https://heggria.github.io/taskflow/en/docs/reference/) | Commands, shorthand, and exact tool surfaces |
367
367
  | [Showcase](https://heggria.github.io/taskflow/en/docs/showcase/) | Real flows and case studies |
368
+ | [0.2.0 Frontier Assessment](https://github.com/heggria/taskflow/blob/main/docs/taskflow-0.2.0-frontier-assessment.zh-CN.md) | Independent, evidence-based technical assessment (Chinese) |
368
369
 
369
370
  Also see [`examples/`](https://github.com/heggria/taskflow/blob/main/examples), the [changelog](https://github.com/heggria/taskflow/blob/main/CHANGELOG.md), and the [release guide](https://github.com/heggria/taskflow/blob/main/RELEASE.md).
370
371
 
package/dist/agents.d.ts CHANGED
@@ -18,9 +18,9 @@ export interface TaskflowSettings {
18
18
  builtInAgents: boolean;
19
19
  /** Whether package-local built-ins are copied into the current project's .pi/agents/. */
20
20
  syncBuiltinAgentsToProject: boolean;
21
- /** Maximum completed/failed runs to keep. 0 disables cleanup. */
21
+ /** Maximum inactive runs to keep. Running runs are never pruned. 0 disables cleanup. */
22
22
  maxKeptRuns: number;
23
- /** Maximum age (days) for completed/failed runs. 0 disables age cleanup. */
23
+ /** Maximum age (days) for inactive runs. Running runs are never pruned. 0 disables age cleanup. */
24
24
  maxRunAgeDays: number;
25
25
  /** Library (reusable-flow asset layer) settings. RFC: docs/rfc-library-reuse.md */
26
26
  library: LibrarySettings;
@@ -1 +1 @@
1
- {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  {
2
- "gitCommit": "300da53ea85ef820a49e72827f9f3261f377a9c9",
3
- "buildTime": 1784017618000
2
+ "gitCommit": "b0a3c22058941f05d7ae3a4072e3721de9e24d5c",
3
+ "buildTime": 1784369228000
4
4
  }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * File-backed control plane for detached Taskflow runs.
3
+ *
4
+ * A detached runner cannot rely on an IPC channel surviving its parent MCP
5
+ * process. Cancellation is therefore requested through a small durable marker
6
+ * in a user-private control directory keyed by the canonical invocation root.
7
+ * The child polls that marker and aborts the normal RuntimeDeps signal,
8
+ * preserving the runtime's existing paused semantics and process-tree cleanup.
9
+ */
10
+ export interface DetachedCancelRequest {
11
+ requestedAt: number;
12
+ reason?: string;
13
+ }
14
+ export declare const DETACHED_CONTROL_VERSION = 1;
15
+ export declare const DETACHED_CONTROL_CWD_ENV = "TASKFLOW_DETACHED_CONTROL_CWD";
16
+ export declare const DETACHED_CONTROL_RUN_ID_ENV = "TASKFLOW_DETACHED_CONTROL_RUN_ID";
17
+ export declare const DETACHED_CONTROL_INSTANCE_ENV = "TASKFLOW_DETACHED_CONTROL_INSTANCE";
18
+ export declare const DETACHED_CONTROL_OWNER_PID_ENV = "TASKFLOW_DETACHED_CONTROL_OWNER_PID";
19
+ export declare const DETACHED_CONTROL_SIGNAL_READY_ENV = "TASKFLOW_DETACHED_CONTROL_SIGNAL_READY";
20
+ export interface DetachedProcessRegistry {
21
+ version: number;
22
+ instanceId: string;
23
+ ownerPid: number;
24
+ heartbeatAt: number;
25
+ pids: number[];
26
+ }
27
+ /** Resolve the cancel marker for a run without accepting caller-selected paths. */
28
+ export declare function detachedCancelRequestPath(cwd: string, runId: string): string;
29
+ /** Persist an idempotent cancellation request for a detached runner. */
30
+ export declare function requestDetachedCancel(cwd: string, runId: string, reason?: string): DetachedCancelRequest;
31
+ /** Read a cancellation request. Corrupt markers still mean "cancel" fail-safe. */
32
+ export declare function readDetachedCancelRequest(cwd: string, runId: string): DetachedCancelRequest | null;
33
+ export declare function clearDetachedCancelRequest(cwd: string, runId: string): void;
34
+ export declare function detachedProcessRegistryPath(cwd: string, runId: string): string;
35
+ export declare function readDetachedProcessRegistry(cwd: string, runId: string): DetachedProcessRegistry | null;
36
+ export declare function heartbeatDetachedProcessRegistry(cwd: string, runId: string, instanceId: string, ownerPid?: number): void;
37
+ /** True only after this exact detached owner installed its persistence-aware signal bridge. */
38
+ export declare function isDetachedSignalOwnerReady(): boolean;
39
+ /** Best-effort hook used by runner-core whenever a Host CLI process group starts. */
40
+ export declare function registerDetachedProcessTreeFromEnv(pid: number): void;
41
+ /** Best-effort hook used by runner-core after a Host CLI process group is reaped. */
42
+ export declare function unregisterDetachedProcessTreeFromEnv(pid: number): void;
43
+ /** Reap every Host CLI process group owned by exactly this worker instance. */
44
+ export declare function terminateDetachedProcessTrees(cwd: string, runId: string, instanceId: string): number[];
45
+ export declare function clearDetachedProcessRegistry(cwd: string, runId: string, instanceId?: string): void;
46
+ /**
47
+ * Poll a detached cancellation marker and bridge it into an AbortController.
48
+ * Returns a cleanup callback. The timer is unref'd so it never keeps a
49
+ * completed detached runner alive by itself.
50
+ */
51
+ export declare function watchDetachedCancel(cwd: string, runId: string, controller: AbortController, pollMs?: number, onRequest?: (request: DetachedCancelRequest) => void): () => void;
52
+ //# sourceMappingURL=detached-control.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detached-control.d.ts","sourceRoot":"","sources":["../src/detached-control.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,MAAM,WAAW,qBAAqB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAKD,eAAO,MAAM,wBAAwB,IAAkB,CAAC;AACxD,eAAO,MAAM,wBAAwB,kCAAkC,CAAC;AACxE,eAAO,MAAM,2BAA2B,qCAAqC,CAAC;AAC9E,eAAO,MAAM,6BAA6B,uCAAuC,CAAC;AAClF,eAAO,MAAM,8BAA8B,wCAAwC,CAAC;AACpF,eAAO,MAAM,iCAAiC,2CAA2C,CAAC;AAE1F,MAAM,WAAW,uBAAuB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;CACf;AAkBD,mFAAmF;AACnF,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE5E;AAED,wEAAwE;AACxE,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,qBAAqB,CAUxG;AAED,kFAAkF;AAClF,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,qBAAqB,GAAG,IAAI,CAiBlG;AAED,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAO3E;AAED,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,uBAAuB,GAAG,IAAI,CAuBtG;AAOD,wBAAgB,gCAAgC,CAC/C,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,QAAQ,SAAc,GACpB,IAAI,CAUN;AAcD,+FAA+F;AAC/F,wBAAgB,0BAA0B,IAAI,OAAO,CAGpD;AAED,qFAAqF;AACrF,wBAAgB,kCAAkC,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAcpE;AAED,qFAAqF;AACrF,wBAAgB,oCAAoC,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAYtE;AAmBD,+EAA+E;AAC/E,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAKtG;AAED,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAOlG;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAClC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,eAAe,EAC3B,MAAM,SAAkB,EACxB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,GAClD,MAAM,IAAI,CAaZ"}
@@ -0,0 +1,251 @@
1
+ /**
2
+ * File-backed control plane for detached Taskflow runs.
3
+ *
4
+ * A detached runner cannot rely on an IPC channel surviving its parent MCP
5
+ * process. Cancellation is therefore requested through a small durable marker
6
+ * in a user-private control directory keyed by the canonical invocation root.
7
+ * The child polls that marker and aborts the normal RuntimeDeps signal,
8
+ * preserving the runtime's existing paused semantics and process-tree cleanup.
9
+ */
10
+ import * as fs from "node:fs";
11
+ import * as path from "node:path";
12
+ import { spawnSync } from "node:child_process";
13
+ import { detachedControlDir, validateRunId, writeFileAtomic } from "./store.js";
14
+ const DEFAULT_POLL_MS = 250;
15
+ const CONTROL_VERSION = 1;
16
+ export const DETACHED_CONTROL_VERSION = CONTROL_VERSION;
17
+ export const DETACHED_CONTROL_CWD_ENV = "TASKFLOW_DETACHED_CONTROL_CWD";
18
+ export const DETACHED_CONTROL_RUN_ID_ENV = "TASKFLOW_DETACHED_CONTROL_RUN_ID";
19
+ export const DETACHED_CONTROL_INSTANCE_ENV = "TASKFLOW_DETACHED_CONTROL_INSTANCE";
20
+ export const DETACHED_CONTROL_OWNER_PID_ENV = "TASKFLOW_DETACHED_CONTROL_OWNER_PID";
21
+ export const DETACHED_CONTROL_SIGNAL_READY_ENV = "TASKFLOW_DETACHED_CONTROL_SIGNAL_READY";
22
+ function ensureControlDir(cwd) {
23
+ const dir = detachedControlDir(cwd);
24
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
25
+ const stat = fs.lstatSync(dir);
26
+ if (!stat.isDirectory() || stat.isSymbolicLink()) {
27
+ throw new Error("Detached control root must be a private physical directory");
28
+ }
29
+ try {
30
+ fs.chmodSync(dir, 0o700);
31
+ }
32
+ catch { /* Windows / restrictive filesystem */ }
33
+ return dir;
34
+ }
35
+ function controlPath(cwd, runId, suffix) {
36
+ if (!validateRunId(runId))
37
+ throw new Error("Invalid runId for detached control");
38
+ return path.join(detachedControlDir(cwd), `${runId}.${suffix}.json`);
39
+ }
40
+ /** Resolve the cancel marker for a run without accepting caller-selected paths. */
41
+ export function detachedCancelRequestPath(cwd, runId) {
42
+ return controlPath(cwd, runId, "cancel");
43
+ }
44
+ /** Persist an idempotent cancellation request for a detached runner. */
45
+ export function requestDetachedCancel(cwd, runId, reason) {
46
+ ensureControlDir(cwd);
47
+ const request = {
48
+ requestedAt: Date.now(),
49
+ ...(typeof reason === "string" && reason.trim()
50
+ ? { reason: reason.trim().slice(0, 500) }
51
+ : {}),
52
+ };
53
+ writeFileAtomic(detachedCancelRequestPath(cwd, runId), `${JSON.stringify(request)}\n`);
54
+ return request;
55
+ }
56
+ /** Read a cancellation request. Corrupt markers still mean "cancel" fail-safe. */
57
+ export function readDetachedCancelRequest(cwd, runId) {
58
+ const filePath = detachedCancelRequestPath(cwd, runId);
59
+ if (!fs.existsSync(filePath))
60
+ return null;
61
+ try {
62
+ const parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
63
+ if (typeof parsed === "object" && parsed !== null) {
64
+ const record = parsed;
65
+ return {
66
+ requestedAt: typeof record.requestedAt === "number" ? record.requestedAt : Date.now(),
67
+ ...(typeof record.reason === "string" ? { reason: record.reason } : {}),
68
+ };
69
+ }
70
+ }
71
+ catch {
72
+ // The marker exists, so fail safe and cancel even if its optional metadata
73
+ // was truncated or externally corrupted.
74
+ }
75
+ return { requestedAt: Date.now(), reason: "Cancellation marker was unreadable" };
76
+ }
77
+ export function clearDetachedCancelRequest(cwd, runId) {
78
+ try {
79
+ fs.unlinkSync(detachedCancelRequestPath(cwd, runId));
80
+ }
81
+ catch {
82
+ /* missing/already consumed */
83
+ }
84
+ try {
85
+ fs.rmdirSync(detachedControlDir(cwd));
86
+ }
87
+ catch { /* other markers / missing */ }
88
+ }
89
+ export function detachedProcessRegistryPath(cwd, runId) {
90
+ return controlPath(cwd, runId, "processes");
91
+ }
92
+ export function readDetachedProcessRegistry(cwd, runId) {
93
+ const filePath = detachedProcessRegistryPath(cwd, runId);
94
+ try {
95
+ const parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
96
+ if (typeof parsed !== "object" || parsed === null)
97
+ return null;
98
+ const value = parsed;
99
+ if (value.version !== CONTROL_VERSION ||
100
+ typeof value.instanceId !== "string" ||
101
+ !Number.isSafeInteger(value.ownerPid) ||
102
+ typeof value.heartbeatAt !== "number" ||
103
+ !Array.isArray(value.pids))
104
+ return null;
105
+ return {
106
+ version: CONTROL_VERSION,
107
+ instanceId: value.instanceId,
108
+ ownerPid: value.ownerPid,
109
+ heartbeatAt: value.heartbeatAt,
110
+ pids: value.pids.filter((pid) => Number.isSafeInteger(pid) && Number(pid) > 0),
111
+ };
112
+ }
113
+ catch {
114
+ return null;
115
+ }
116
+ }
117
+ function writeDetachedProcessRegistry(cwd, runId, registry) {
118
+ ensureControlDir(cwd);
119
+ writeFileAtomic(detachedProcessRegistryPath(cwd, runId), `${JSON.stringify(registry)}\n`);
120
+ }
121
+ export function heartbeatDetachedProcessRegistry(cwd, runId, instanceId, ownerPid = process.pid) {
122
+ const existing = readDetachedProcessRegistry(cwd, runId);
123
+ const pids = existing?.instanceId === instanceId ? existing.pids : [];
124
+ writeDetachedProcessRegistry(cwd, runId, {
125
+ version: CONTROL_VERSION,
126
+ instanceId,
127
+ ownerPid,
128
+ heartbeatAt: Date.now(),
129
+ pids,
130
+ });
131
+ }
132
+ function processRegistryContextFromEnv() {
133
+ const cwd = process.env[DETACHED_CONTROL_CWD_ENV];
134
+ const runId = process.env[DETACHED_CONTROL_RUN_ID_ENV];
135
+ const instanceId = process.env[DETACHED_CONTROL_INSTANCE_ENV];
136
+ // Host CLIs inherit the detached worker's environment. Only the process that
137
+ // owns this exact PID token may mutate the outer worker's registry; nested
138
+ // Taskflow instances must not overwrite its heartbeat/owner identity.
139
+ if (process.env[DETACHED_CONTROL_OWNER_PID_ENV] !== String(process.pid))
140
+ return null;
141
+ if (!cwd || !runId || !instanceId || !validateRunId(runId))
142
+ return null;
143
+ return { cwd, runId, instanceId };
144
+ }
145
+ /** True only after this exact detached owner installed its persistence-aware signal bridge. */
146
+ export function isDetachedSignalOwnerReady() {
147
+ return process.env[DETACHED_CONTROL_OWNER_PID_ENV] === String(process.pid) &&
148
+ process.env[DETACHED_CONTROL_SIGNAL_READY_ENV] === "1";
149
+ }
150
+ /** Best-effort hook used by runner-core whenever a Host CLI process group starts. */
151
+ export function registerDetachedProcessTreeFromEnv(pid) {
152
+ const context = processRegistryContextFromEnv();
153
+ if (!context || !Number.isSafeInteger(pid) || pid <= 0)
154
+ return;
155
+ try {
156
+ const existing = readDetachedProcessRegistry(context.cwd, context.runId);
157
+ const pids = existing?.instanceId === context.instanceId ? existing.pids : [];
158
+ writeDetachedProcessRegistry(context.cwd, context.runId, {
159
+ version: CONTROL_VERSION,
160
+ instanceId: context.instanceId,
161
+ ownerPid: process.pid,
162
+ heartbeatAt: Date.now(),
163
+ pids: [...new Set([...pids, pid])],
164
+ });
165
+ }
166
+ catch { /* lifecycle diagnostics must never replace phase execution */ }
167
+ }
168
+ /** Best-effort hook used by runner-core after a Host CLI process group is reaped. */
169
+ export function unregisterDetachedProcessTreeFromEnv(pid) {
170
+ const context = processRegistryContextFromEnv();
171
+ if (!context)
172
+ return;
173
+ try {
174
+ const existing = readDetachedProcessRegistry(context.cwd, context.runId);
175
+ if (!existing || existing.instanceId !== context.instanceId)
176
+ return;
177
+ writeDetachedProcessRegistry(context.cwd, context.runId, {
178
+ ...existing,
179
+ heartbeatAt: Date.now(),
180
+ pids: existing.pids.filter((candidate) => candidate !== pid),
181
+ });
182
+ }
183
+ catch { /* lifecycle diagnostics must never replace phase execution */ }
184
+ }
185
+ function killRegisteredProcessTree(pid) {
186
+ if (!Number.isSafeInteger(pid) || pid <= 0 || pid === process.pid)
187
+ return;
188
+ if (process.platform === "win32") {
189
+ try {
190
+ spawnSync("taskkill", ["/PID", String(pid), "/T", "/F"], {
191
+ shell: false,
192
+ stdio: "ignore",
193
+ windowsHide: true,
194
+ });
195
+ }
196
+ catch { /* already gone / taskkill unavailable */ }
197
+ return;
198
+ }
199
+ try {
200
+ process.kill(-pid, "SIGKILL");
201
+ }
202
+ catch {
203
+ try {
204
+ process.kill(pid, "SIGKILL");
205
+ }
206
+ catch { /* already gone */ }
207
+ }
208
+ }
209
+ /** Reap every Host CLI process group owned by exactly this worker instance. */
210
+ export function terminateDetachedProcessTrees(cwd, runId, instanceId) {
211
+ const registry = readDetachedProcessRegistry(cwd, runId);
212
+ if (!registry || registry.instanceId !== instanceId)
213
+ return [];
214
+ for (const pid of registry.pids)
215
+ killRegisteredProcessTree(pid);
216
+ return registry.pids;
217
+ }
218
+ export function clearDetachedProcessRegistry(cwd, runId, instanceId) {
219
+ try {
220
+ const existing = readDetachedProcessRegistry(cwd, runId);
221
+ if (instanceId && existing && existing.instanceId !== instanceId)
222
+ return;
223
+ fs.unlinkSync(detachedProcessRegistryPath(cwd, runId));
224
+ }
225
+ catch { /* missing/already cleared */ }
226
+ try {
227
+ fs.rmdirSync(detachedControlDir(cwd));
228
+ }
229
+ catch { /* other markers / missing */ }
230
+ }
231
+ /**
232
+ * Poll a detached cancellation marker and bridge it into an AbortController.
233
+ * Returns a cleanup callback. The timer is unref'd so it never keeps a
234
+ * completed detached runner alive by itself.
235
+ */
236
+ export function watchDetachedCancel(cwd, runId, controller, pollMs = DEFAULT_POLL_MS, onRequest) {
237
+ const check = () => {
238
+ if (controller.signal.aborted)
239
+ return;
240
+ const request = readDetachedCancelRequest(cwd, runId);
241
+ if (request) {
242
+ onRequest?.(request);
243
+ controller.abort(request);
244
+ }
245
+ };
246
+ check();
247
+ const timer = setInterval(check, Math.max(50, pollMs));
248
+ timer.unref();
249
+ return () => clearInterval(timer);
250
+ }
251
+ //# sourceMappingURL=detached-control.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detached-control.js","sourceRoot":"","sources":["../src/detached-control.ts"],"names":[],"mappings":"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"}