@wrongstack/tools 0.284.1 → 0.286.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 +19 -0
- package/dist/_concurrency.d.ts +16 -0
- package/dist/_concurrency.d.ts.map +1 -0
- package/dist/_danger-detect.d.ts +54 -0
- package/dist/_danger-detect.d.ts.map +1 -0
- package/dist/_edit-match.d.ts +86 -0
- package/dist/_edit-match.d.ts.map +1 -0
- package/dist/_env.d.ts +6 -0
- package/dist/_env.d.ts.map +1 -0
- package/dist/_fetch-guard.d.ts +31 -0
- package/dist/_fetch-guard.d.ts.map +1 -0
- package/dist/_output-spool.d.ts +38 -0
- package/dist/_output-spool.d.ts.map +1 -0
- package/dist/_redact-command.d.ts +6 -0
- package/dist/_redact-command.d.ts.map +1 -0
- package/dist/_regex.d.ts +39 -0
- package/dist/_regex.d.ts.map +1 -0
- package/dist/_session-shell.d.ts +73 -0
- package/dist/_session-shell.d.ts.map +1 -0
- package/dist/_shell-pick.d.ts +158 -0
- package/dist/_shell-pick.d.ts.map +1 -0
- package/dist/_spawn-stream.d.ts +32 -0
- package/dist/_spawn-stream.d.ts.map +1 -0
- package/dist/_syntax-check.d.ts +16 -0
- package/dist/_syntax-check.d.ts.map +1 -0
- package/dist/_util.d.ts +68 -0
- package/dist/_util.d.ts.map +1 -0
- package/dist/_win32-resolve.d.ts +42 -0
- package/dist/_win32-resolve.d.ts.map +1 -0
- package/dist/audit.d.ts +4 -5
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +2743 -28
- package/dist/audit.js.map +7 -1
- package/dist/bash-kill-guard.d.ts +62 -0
- package/dist/bash-kill-guard.d.ts.map +1 -0
- package/dist/bash.d.ts +4 -5
- package/dist/bash.d.ts.map +1 -0
- package/dist/bash.js +59 -30
- package/dist/bash.js.map +7 -1
- package/dist/batch-tool-use.d.ts +4 -5
- package/dist/batch-tool-use.d.ts.map +1 -0
- package/dist/batch-tool-use.js +3 -3
- package/dist/batch-tool-use.js.map +7 -1
- package/dist/browser/artifacts.d.ts +13 -0
- package/dist/browser/artifacts.d.ts.map +1 -0
- package/dist/browser/index.d.ts +7 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +1264 -0
- package/dist/browser/index.js.map +7 -0
- package/dist/browser/manager.d.ts +57 -0
- package/dist/browser/manager.d.ts.map +1 -0
- package/dist/browser/network-guard-proxy.d.ts +23 -0
- package/dist/browser/network-guard-proxy.d.ts.map +1 -0
- package/dist/browser/security.d.ts +29 -0
- package/dist/browser/security.d.ts.map +1 -0
- package/dist/browser/tools.d.ts +62 -0
- package/dist/browser/tools.d.ts.map +1 -0
- package/dist/browser/types.d.ts +60 -0
- package/dist/browser/types.d.ts.map +1 -0
- package/dist/builtin.d.ts +11 -12
- package/dist/builtin.d.ts.map +1 -0
- package/dist/builtin.js +8099 -2178
- package/dist/builtin.js.map +7 -1
- package/dist/circuit-breaker.d.ts +4 -5
- package/dist/circuit-breaker.d.ts.map +1 -0
- package/dist/circuit-breaker.js +3 -3
- package/dist/circuit-breaker.js.map +7 -1
- package/dist/codebase-index/background-indexer.d.ts +116 -0
- package/dist/codebase-index/background-indexer.d.ts.map +1 -0
- package/dist/codebase-index/bm25.d.ts +40 -0
- package/dist/codebase-index/bm25.d.ts.map +1 -0
- package/dist/codebase-index/circuit-breaker.d.ts +94 -0
- package/dist/codebase-index/circuit-breaker.d.ts.map +1 -0
- package/dist/codebase-index/codebase-index-tool.d.ts +17 -0
- package/dist/codebase-index/codebase-index-tool.d.ts.map +1 -0
- package/dist/codebase-index/codebase-search-tool.d.ts +43 -0
- package/dist/codebase-index/codebase-search-tool.d.ts.map +1 -0
- package/dist/codebase-index/codebase-stats-tool.d.ts +23 -0
- package/dist/codebase-index/codebase-stats-tool.d.ts.map +1 -0
- package/dist/codebase-index/gitignore.d.ts +22 -0
- package/dist/codebase-index/gitignore.d.ts.map +1 -0
- package/dist/codebase-index/go-parser.d.ts +16 -0
- package/dist/codebase-index/go-parser.d.ts.map +1 -0
- package/dist/codebase-index/index-service.d.ts +25 -0
- package/dist/codebase-index/index-service.d.ts.map +1 -0
- package/dist/codebase-index/index.d.ts +23 -271
- package/dist/codebase-index/index.d.ts.map +1 -0
- package/dist/codebase-index/index.js +136 -68
- package/dist/codebase-index/index.js.map +7 -1
- package/dist/codebase-index/indexer.d.ts +28 -0
- package/dist/codebase-index/indexer.d.ts.map +1 -0
- package/dist/codebase-index/json-parser.d.ts +8 -0
- package/dist/codebase-index/json-parser.d.ts.map +1 -0
- package/dist/codebase-index/lsp-kind.d.ts +53 -0
- package/dist/codebase-index/lsp-kind.d.ts.map +1 -0
- package/dist/codebase-index/py-parser.d.ts +16 -0
- package/dist/codebase-index/py-parser.d.ts.map +1 -0
- package/dist/codebase-index/refs-extractor.d.ts +25 -0
- package/dist/codebase-index/refs-extractor.d.ts.map +1 -0
- package/dist/codebase-index/rs-parser.d.ts +8 -0
- package/dist/codebase-index/rs-parser.d.ts.map +1 -0
- package/dist/codebase-index/schema.d.ts +82 -0
- package/dist/codebase-index/schema.d.ts.map +1 -0
- package/dist/codebase-index/ts-parser.d.ts +30 -0
- package/dist/codebase-index/ts-parser.d.ts.map +1 -0
- package/dist/codebase-index/worker-protocol.d.ts +77 -0
- package/dist/codebase-index/worker-protocol.d.ts.map +1 -0
- package/dist/codebase-index/worker.d.ts +16 -2
- package/dist/codebase-index/worker.d.ts.map +1 -0
- package/dist/codebase-index/worker.js +103 -65
- package/dist/codebase-index/worker.js.map +7 -1
- package/dist/codebase-index/writer.d.ts +189 -0
- package/dist/codebase-index/writer.d.ts.map +1 -0
- package/dist/codebase-index/yaml-parser.d.ts +8 -0
- package/dist/codebase-index/yaml-parser.d.ts.map +1 -0
- package/dist/design.d.ts +38 -0
- package/dist/design.d.ts.map +1 -0
- package/dist/design.js +270 -0
- package/dist/design.js.map +7 -0
- package/dist/diff.d.ts +4 -5
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +14 -12
- package/dist/diff.js.map +7 -1
- package/dist/document.d.ts +4 -5
- package/dist/document.d.ts.map +1 -0
- package/dist/document.js +8 -7
- package/dist/document.js.map +7 -1
- package/dist/e2e.d.ts +56 -0
- package/dist/e2e.d.ts.map +1 -0
- package/dist/edit.d.ts +5 -36
- package/dist/edit.d.ts.map +1 -0
- package/dist/edit.js +28 -16
- package/dist/edit.js.map +7 -1
- package/dist/exec.d.ts +67 -2
- package/dist/exec.d.ts.map +1 -0
- package/dist/exec.js +51 -26
- package/dist/exec.js.map +7 -1
- package/dist/fetch.d.ts +4 -32
- package/dist/fetch.d.ts.map +1 -0
- package/dist/fetch.js +89 -77
- package/dist/fetch.js.map +7 -1
- package/dist/format.d.ts +4 -5
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +2415 -28
- package/dist/format.js.map +7 -1
- package/dist/git.d.ts +4 -5
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +10 -9
- package/dist/git.js.map +7 -1
- package/dist/glob.d.ts +4 -5
- package/dist/glob.d.ts.map +1 -0
- package/dist/glob.js +15 -12
- package/dist/glob.js.map +7 -1
- package/dist/grep.d.ts +4 -5
- package/dist/grep.d.ts.map +1 -0
- package/dist/grep.js +13 -10
- package/dist/grep.js.map +7 -1
- package/dist/index.d.ts +21 -724
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8955 -2866
- package/dist/index.js.map +7 -1
- package/dist/install.d.ts +4 -5
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +2680 -31
- package/dist/install.js.map +7 -1
- package/dist/json.d.ts +4 -5
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +13 -11
- package/dist/json.js.map +7 -1
- package/dist/kanban.d.ts +107 -0
- package/dist/kanban.d.ts.map +1 -0
- package/dist/kanban.js +845 -0
- package/dist/kanban.js.map +7 -0
- package/dist/languages/detect.d.ts +3 -0
- package/dist/languages/detect.d.ts.map +1 -0
- package/dist/languages/diagnostics.d.ts +15 -0
- package/dist/languages/diagnostics.d.ts.map +1 -0
- package/dist/languages/execute-tool.d.ts +34 -0
- package/dist/languages/execute-tool.d.ts.map +1 -0
- package/dist/languages/execute.d.ts +18 -0
- package/dist/languages/execute.d.ts.map +1 -0
- package/dist/languages/index.d.ts +12 -0
- package/dist/languages/index.d.ts.map +1 -0
- package/dist/languages/index.js +4457 -0
- package/dist/languages/index.js.map +7 -0
- package/dist/languages/legacy-bridge.d.ts +29 -0
- package/dist/languages/legacy-bridge.d.ts.map +1 -0
- package/dist/languages/package-tool.d.ts +29 -0
- package/dist/languages/package-tool.d.ts.map +1 -0
- package/dist/languages/plan.d.ts +4 -0
- package/dist/languages/plan.d.ts.map +1 -0
- package/dist/languages/profile-helpers.d.ts +14 -0
- package/dist/languages/profile-helpers.d.ts.map +1 -0
- package/dist/languages/profiles/additional.d.ts +3 -0
- package/dist/languages/profiles/additional.d.ts.map +1 -0
- package/dist/languages/profiles/primary.d.ts +3 -0
- package/dist/languages/profiles/primary.d.ts.map +1 -0
- package/dist/languages/registry.d.ts +11 -0
- package/dist/languages/registry.d.ts.map +1 -0
- package/dist/languages/tool.d.ts +32 -0
- package/dist/languages/tool.d.ts.map +1 -0
- package/dist/languages/types.d.ts +207 -0
- package/dist/languages/types.d.ts.map +1 -0
- package/dist/lint.d.ts +4 -5
- package/dist/lint.d.ts.map +1 -0
- package/dist/lint.js +2415 -27
- package/dist/lint.js.map +7 -1
- package/dist/logs.d.ts +4 -5
- package/dist/logs.d.ts.map +1 -0
- package/dist/logs.js +16 -10
- package/dist/logs.js.map +7 -1
- package/dist/memory.d.ts +7 -8
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +7 -5
- package/dist/memory.js.map +7 -1
- package/dist/mode.d.ts +4 -5
- package/dist/mode.d.ts.map +1 -0
- package/dist/mode.js +3 -3
- package/dist/mode.js.map +7 -1
- package/dist/next-steps.d.ts +5 -6
- package/dist/next-steps.d.ts.map +1 -0
- package/dist/next-steps.js +5 -4
- package/dist/next-steps.js.map +7 -1
- package/dist/outdated.d.ts +4 -5
- package/dist/outdated.d.ts.map +1 -0
- package/dist/outdated.js +4777 -68
- package/dist/outdated.js.map +7 -1
- package/dist/pack.d.ts +3 -6
- package/dist/pack.d.ts.map +1 -0
- package/dist/pack.js +8134 -2204
- package/dist/pack.js.map +7 -1
- package/dist/patch.d.ts +4 -5
- package/dist/patch.d.ts.map +1 -0
- package/dist/patch.js +18 -16
- package/dist/patch.js.map +7 -1
- package/dist/plan.d.ts +55 -0
- package/dist/plan.d.ts.map +1 -0
- package/dist/plan.js +280 -0
- package/dist/plan.js.map +7 -0
- package/dist/process-guardian.d.ts +100 -0
- package/dist/process-guardian.d.ts.map +1 -0
- package/dist/process-registry-persistent.d.ts +121 -0
- package/dist/process-registry-persistent.d.ts.map +1 -0
- package/dist/process-registry.d.ts +13 -17
- package/dist/process-registry.d.ts.map +1 -0
- package/dist/process-registry.js +15 -9
- package/dist/process-registry.js.map +7 -1
- package/dist/ps-slash.d.ts +106 -0
- package/dist/ps-slash.d.ts.map +1 -0
- package/dist/ps-slash.js +1291 -0
- package/dist/ps-slash.js.map +7 -0
- package/dist/read.d.ts +4 -5
- package/dist/read.d.ts.map +1 -0
- package/dist/read.js +13 -11
- package/dist/read.js.map +7 -1
- package/dist/replace.d.ts +4 -5
- package/dist/replace.d.ts.map +1 -0
- package/dist/replace.js +26 -13
- package/dist/replace.js.map +7 -1
- package/dist/scaffold.d.ts +4 -5
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +16 -14
- package/dist/scaffold.js.map +7 -1
- package/dist/search.d.ts +5 -6
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +32 -27
- package/dist/search.js.map +7 -1
- package/dist/set-working-dir.d.ts +18 -0
- package/dist/set-working-dir.d.ts.map +1 -0
- package/dist/shim/node-sqlite.d.ts +3 -0
- package/dist/shim/node-sqlite.d.ts.map +1 -0
- package/dist/skill.d.ts +45 -0
- package/dist/skill.d.ts.map +1 -0
- package/dist/skill.js +175 -0
- package/dist/skill.js.map +7 -0
- package/dist/spawn-background.d.ts +80 -0
- package/dist/spawn-background.d.ts.map +1 -0
- package/dist/task.d.ts +35 -0
- package/dist/task.d.ts.map +1 -0
- package/dist/task.js +380 -0
- package/dist/task.js.map +7 -0
- package/dist/test.d.ts +4 -5
- package/dist/test.d.ts.map +1 -0
- package/dist/test.js +2419 -27
- package/dist/test.js.map +7 -1
- package/dist/todo.d.ts +4 -5
- package/dist/todo.d.ts.map +1 -0
- package/dist/todo.js +5 -5
- package/dist/todo.js.map +7 -1
- package/dist/tool-diff.d.ts +16 -17
- package/dist/tool-diff.d.ts.map +1 -0
- package/dist/tool-diff.js +11 -3
- package/dist/tool-diff.js.map +7 -1
- package/dist/tool-help.d.ts +4 -5
- package/dist/tool-help.d.ts.map +1 -0
- package/dist/tool-help.js +3 -3
- package/dist/tool-help.js.map +7 -1
- package/dist/tool-icon-map.d.ts +46 -0
- package/dist/tool-icon-map.d.ts.map +1 -0
- package/dist/tool-icons.d.ts +5 -6
- package/dist/tool-icons.d.ts.map +1 -0
- package/dist/tool-icons.js +16 -4
- package/dist/tool-icons.js.map +7 -1
- package/dist/tool-search.d.ts +4 -5
- package/dist/tool-search.d.ts.map +1 -0
- package/dist/tool-search.js +3 -3
- package/dist/tool-search.js.map +7 -1
- package/dist/tool-summary.d.ts +4 -5
- package/dist/tool-summary.d.ts.map +1 -0
- package/dist/tool-summary.js +5 -3
- package/dist/tool-summary.js.map +7 -1
- package/dist/tool-use.d.ts +4 -5
- package/dist/tool-use.d.ts.map +1 -0
- package/dist/tool-use.js +3 -3
- package/dist/tool-use.js.map +7 -1
- package/dist/tree.d.ts +4 -5
- package/dist/tree.d.ts.map +1 -0
- package/dist/tree.js +11 -9
- package/dist/tree.js.map +7 -1
- package/dist/typecheck.d.ts +4 -5
- package/dist/typecheck.d.ts.map +1 -0
- package/dist/typecheck.js +2416 -28
- package/dist/typecheck.js.map +7 -1
- package/dist/write.d.ts +4 -5
- package/dist/write.d.ts.map +1 -0
- package/dist/write.js +21 -16
- package/dist/write.js.map +7 -1
- package/package.json +39 -6
- package/dist/background-indexer-BeDBxfSh.d.ts +0 -371
- package/dist/exec-2OKoT6tk.d.ts +0 -121
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* spawn-background — platform-independent background process spawning.
|
|
3
|
+
*
|
|
4
|
+
* Provides truly fire-and-forget background process execution that:
|
|
5
|
+
* - Works consistently on Windows and POSIX
|
|
6
|
+
* - Does not block the parent Node.js event loop
|
|
7
|
+
* - Creates a fully independent child process (new process group/session)
|
|
8
|
+
* - Does NOT register with the ProcessRegistry (fire-and-forget)
|
|
9
|
+
* - Does NOT affect the circuit breaker
|
|
10
|
+
*
|
|
11
|
+
* POSIX: Uses setsid() (detached: true) to create a new session, fully
|
|
12
|
+
* detaching from the parent's process group. The child becomes a
|
|
13
|
+
* daemon-like process.
|
|
14
|
+
*
|
|
15
|
+
* Windows: detached: false + windowsHide: true (CREATE_NO_WINDOW). This is
|
|
16
|
+
* deliberate: CreateProcess IGNORES CREATE_NO_WINDOW when combined
|
|
17
|
+
* with DETACHED_PROCESS (which detached: true sets), so a detached
|
|
18
|
+
* cmd.exe runs console-less and its console-app *grandchildren*
|
|
19
|
+
* (node, etc.) each allocate a fresh VISIBLE console window.
|
|
20
|
+
* CREATE_NO_WINDOW instead gives the child a hidden console that
|
|
21
|
+
* grandchildren inherit — no window ever appears. Windows children
|
|
22
|
+
* survive parent exit regardless of detached, and the hidden
|
|
23
|
+
* console also isolates them from the terminal's Ctrl+C, so
|
|
24
|
+
* nothing is lost by dropping DETACHED_PROCESS.
|
|
25
|
+
*/
|
|
26
|
+
import { spawn } from 'node:child_process';
|
|
27
|
+
export interface SpawnBackgroundOptions {
|
|
28
|
+
/**
|
|
29
|
+
* Shell command string to execute (e.g. `"node --version"`, `"npm run dev"`).
|
|
30
|
+
*
|
|
31
|
+
* ⚠️ SECURITY: This value is passed verbatim to the system shell
|
|
32
|
+
* (`/bin/bash -c` on POSIX, `cmd.exe /c` on Windows). Shell metacharacters
|
|
33
|
+
* (`;`, `&&`, `|`, `$()`, backticks, etc.) ARE interpreted. Never pass
|
|
34
|
+
* untrusted or user-controlled input here — use {@link spawnBackgroundExec}
|
|
35
|
+
* instead, which spawns a command + args array with no shell interpretation.
|
|
36
|
+
*/
|
|
37
|
+
command: string;
|
|
38
|
+
/** Arguments (for exec-style commands) */
|
|
39
|
+
args?: string[];
|
|
40
|
+
/** Working directory */
|
|
41
|
+
cwd?: string;
|
|
42
|
+
/** Environment variables */
|
|
43
|
+
env?: Record<string, string>;
|
|
44
|
+
/** Shell to use (default: system default) */
|
|
45
|
+
shell?: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Spawn a fully detached background process **via the system shell**.
|
|
49
|
+
*
|
|
50
|
+
* ⚠️ SECURITY: `opts.command` is interpreted by `/bin/bash -c` (POSIX) or
|
|
51
|
+
* `cmd.exe /c` (Windows). This is an explicit shell-exec sink. If
|
|
52
|
+
* `opts.command` contains untrusted or user-influenced input, it is a direct
|
|
53
|
+
* command-injection vector. For untrusted input use {@link spawnBackgroundExec},
|
|
54
|
+
* which takes a command + args array and never invokes a shell.
|
|
55
|
+
*
|
|
56
|
+
* @returns The spawned ChildProcess (already unref'd so it doesn't block exit)
|
|
57
|
+
*/
|
|
58
|
+
export declare function spawnBackground(opts: SpawnBackgroundOptions): {
|
|
59
|
+
pid: number | null;
|
|
60
|
+
child: ReturnType<typeof spawn>;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Spawn a command (exec-style, no shell) as a detached background process.
|
|
64
|
+
* This is more secure than {@link spawnBackground} since there are no shell
|
|
65
|
+
* injection risks — args are passed as an argv array, never through a shell.
|
|
66
|
+
*
|
|
67
|
+
* On Windows, `.cmd`/`.bat` wrappers are launched through `cmd.exe` directly
|
|
68
|
+
* because CreateProcess cannot run them natively. The shim helper rejects any
|
|
69
|
+
* argument containing a cmd.exe injection metacharacter
|
|
70
|
+
* (`& | < >` or newline) — the same guard used by exec.ts, _spawn-stream.ts,
|
|
71
|
+
* and outdated.ts. Safe args pass through unchanged.
|
|
72
|
+
*
|
|
73
|
+
* @returns The spawned ChildProcess (already unref'd so it doesn't block exit)
|
|
74
|
+
*/
|
|
75
|
+
export declare function spawnBackgroundExec(command: string, args?: string[], cwd?: string, env?: Record<string, string>): {
|
|
76
|
+
pid: number | null;
|
|
77
|
+
child: ReturnType<typeof spawn>;
|
|
78
|
+
};
|
|
79
|
+
export type { ChildProcess } from 'node:child_process';
|
|
80
|
+
//# sourceMappingURL=spawn-background.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spawn-background.d.ts","sourceRoot":"","sources":["../src/spawn-background.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,KAAK,EAAqB,MAAM,oBAAoB,CAAC;AAU9D,MAAM,WAAW,sBAAsB;IACrC;;;;;;;;OAQG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,wBAAwB;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,sBAAsB,GAAG;IAC7D,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,KAAK,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;CACjC,CAuCA;AAoBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,MAAM,EAAO,EACnB,GAAG,CAAC,EAAE,MAAM,EACZ,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B;IACD,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,KAAK,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;CACjC,CAwCA;AAGD,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/task.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type TaskItem, type TaskStatus } from '@wrongstack/core';
|
|
2
|
+
import type { Tool } from '@wrongstack/core';
|
|
3
|
+
interface TaskInput {
|
|
4
|
+
/** Replace: set new task list. Add: append a task. Status: update task status. Promote: convert a task to todo items. */
|
|
5
|
+
action: 'replace' | 'add' | 'status' | 'show' | 'promote' | 'planify';
|
|
6
|
+
/** Full task list for action=replace. */
|
|
7
|
+
tasks?: TaskItem[] | undefined;
|
|
8
|
+
/** Single task for action=add. id, createdAt, updatedAt are auto-generated. */
|
|
9
|
+
task?: Omit<TaskItem, 'id' | 'createdAt' | 'updatedAt'> | undefined;
|
|
10
|
+
/** Task id for action=status or target for action=promote. */
|
|
11
|
+
id?: string | undefined;
|
|
12
|
+
/** New status for action=status. */
|
|
13
|
+
status?: TaskStatus | undefined;
|
|
14
|
+
/** Target task (id, 1-based index, or title substring) for action=promote. */
|
|
15
|
+
target?: string | undefined;
|
|
16
|
+
/** Optional subtask titles for action=promote. */
|
|
17
|
+
subtasks?: string[] | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Storage scope. Default (unset): uses the session-scoped path — isolated to this
|
|
20
|
+
* session, survives resume within the same session.
|
|
21
|
+
* `scope: 'project'`: uses a shared project-level path, visible to all sessions
|
|
22
|
+
* for this project. Useful for a shared backlog that outlasts any single session.
|
|
23
|
+
*/
|
|
24
|
+
scope?: 'session' | 'project';
|
|
25
|
+
}
|
|
26
|
+
interface TaskOutput {
|
|
27
|
+
ok: boolean;
|
|
28
|
+
message: string;
|
|
29
|
+
count: number;
|
|
30
|
+
completed: number;
|
|
31
|
+
inProgress: number;
|
|
32
|
+
}
|
|
33
|
+
export declare const taskTool: Tool<TaskInput, TaskOutput>;
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=task.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../src/task.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,UAAU,EAIhB,MAAM,kBAAkB,CAAC;AAU1B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAqC7C,UAAU,SAAS;IACjB,yHAAyH;IACzH,MAAM,EAAE,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;IACtE,yCAAyC;IACzC,KAAK,CAAC,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC;IAC/B,+EAA+E;IAC/E,IAAI,CAAC,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,CAAC,GAAG,SAAS,CAAC;IACpE,8DAA8D;IAC9D,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,oCAAoC;IACpC,MAAM,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IAChC,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAChC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CAC/B;AAED,UAAU,UAAU;IAClB,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE,UAAU,CA4ahD,CAAC"}
|
package/dist/task.js
ADDED
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
// src/task.ts
|
|
2
|
+
import {
|
|
3
|
+
computeTaskItemProgress,
|
|
4
|
+
formatTaskList
|
|
5
|
+
} from "@wrongstack/core";
|
|
6
|
+
import {
|
|
7
|
+
mutateTasks
|
|
8
|
+
} from "@wrongstack/core";
|
|
9
|
+
import {
|
|
10
|
+
addPlanItem,
|
|
11
|
+
mutatePlan,
|
|
12
|
+
formatPlan
|
|
13
|
+
} from "@wrongstack/core";
|
|
14
|
+
import { randomUUID } from "node:crypto";
|
|
15
|
+
function findTaskIndex(tasks, query) {
|
|
16
|
+
const asNum = Number.parseInt(query, 10);
|
|
17
|
+
if (!Number.isNaN(asNum)) {
|
|
18
|
+
const idx = asNum - 1;
|
|
19
|
+
if (tasks[idx]) return idx;
|
|
20
|
+
}
|
|
21
|
+
const byId = tasks.findIndex((t) => t.id === query);
|
|
22
|
+
if (byId >= 0) return byId;
|
|
23
|
+
const lower = query.toLowerCase();
|
|
24
|
+
return tasks.findIndex((t) => t.title.toLowerCase().includes(lower));
|
|
25
|
+
}
|
|
26
|
+
var taskTool = {
|
|
27
|
+
name: "task",
|
|
28
|
+
category: "Session",
|
|
29
|
+
description: 'Manage session-persistent structured work items with dependencies, types, and priorities. Unlike `todo` (flat, tactical), `task` supports typed work (feature/bugfix/refactor/etc.), dependencies between items, priority ranking, and agent assignment. Tasks are written to disk and survive session resumes. By default they are isolated to this session; use `scope: "project"` to store tasks in a shared project-level file visible to all sessions.',
|
|
30
|
+
usageHint: 'USE FOR STRUCTURED WORK:\n- `action: "replace"` \u2014 set the complete task list (tasks ordered by priority)\n- `action: "add"` \u2014 append a single task\n- `action: "status"` \u2014 update a task\'s status (e.g. pending\u2192in_progress, in_progress\u2192completed)\n- `action: "show"` \u2014 view current tasks without changing them\n- `action: "promote"` \u2014 convert a task into actionable todo items via `target` (id|index|substring)\n- `action: "planify"` \u2014 promote a task to a plan item (strategic level) via `target` (id|index|substring)\n\nTask fields:\n- `dependsOn`: list of task IDs this one waits for\n- `type`: "feature" | "bugfix" | "refactor" | "docs" | "test" | "chore"\n- `priority`: "critical" | "high" | "medium" | "low"\n- `assignee`: agent/subagent name (e.g. "bug-hunter", "refactor-planner")\n- `estimateHours`: rough time estimate\n- `scope`: "session" (default, isolated) or "project" (shared across sessions)',
|
|
31
|
+
permission: "confirm",
|
|
32
|
+
mutating: true,
|
|
33
|
+
capabilities: ["fs.write"],
|
|
34
|
+
icon: "task",
|
|
35
|
+
timeoutMs: 2e3,
|
|
36
|
+
inputSchema: {
|
|
37
|
+
type: "object",
|
|
38
|
+
properties: {
|
|
39
|
+
action: {
|
|
40
|
+
type: "string",
|
|
41
|
+
enum: ["replace", "add", "status", "show", "promote", "planify"],
|
|
42
|
+
description: "replace = set full list, add = append, status = update task status, show = view only, promote = convert task to todos, planify = convert task to plan item."
|
|
43
|
+
},
|
|
44
|
+
tasks: {
|
|
45
|
+
type: "array",
|
|
46
|
+
items: {
|
|
47
|
+
type: "object",
|
|
48
|
+
properties: {
|
|
49
|
+
id: { type: "string", description: 'Unique id (e.g. "t1", "auth-flow").' },
|
|
50
|
+
title: { type: "string", description: "Short title." },
|
|
51
|
+
description: { type: "string", description: "Optional details." },
|
|
52
|
+
type: { type: "string", enum: ["feature", "bugfix", "refactor", "docs", "test", "chore"] },
|
|
53
|
+
priority: { type: "string", enum: ["critical", "high", "medium", "low"] },
|
|
54
|
+
status: { type: "string", enum: ["pending", "in_progress", "blocked", "failed", "review", "completed"] },
|
|
55
|
+
dependsOn: {
|
|
56
|
+
type: "array",
|
|
57
|
+
items: { type: "string" },
|
|
58
|
+
description: "IDs of tasks this one depends on."
|
|
59
|
+
},
|
|
60
|
+
assignee: { type: "string", description: "Agent/subagent assigned." },
|
|
61
|
+
estimateHours: { type: "number", description: "Estimated hours." },
|
|
62
|
+
tags: { type: "array", items: { type: "string" }, description: "Optional tags." },
|
|
63
|
+
createdAt: { type: "string" },
|
|
64
|
+
updatedAt: { type: "string" }
|
|
65
|
+
},
|
|
66
|
+
required: ["id", "title", "type", "priority", "status"]
|
|
67
|
+
},
|
|
68
|
+
description: "Complete task list. Replaces previous list entirely."
|
|
69
|
+
},
|
|
70
|
+
task: {
|
|
71
|
+
type: "object",
|
|
72
|
+
properties: {
|
|
73
|
+
title: { type: "string" },
|
|
74
|
+
description: { type: "string" },
|
|
75
|
+
type: { type: "string", enum: ["feature", "bugfix", "refactor", "docs", "test", "chore"] },
|
|
76
|
+
priority: { type: "string", enum: ["critical", "high", "medium", "low"] },
|
|
77
|
+
status: { type: "string", enum: ["pending", "in_progress", "blocked", "failed", "review", "completed"] },
|
|
78
|
+
dependsOn: { type: "array", items: { type: "string" } },
|
|
79
|
+
assignee: { type: "string" },
|
|
80
|
+
estimateHours: { type: "number" },
|
|
81
|
+
tags: { type: "array", items: { type: "string" } }
|
|
82
|
+
},
|
|
83
|
+
required: ["title", "type", "priority"],
|
|
84
|
+
description: "Single task to append (id/createdAt/updatedAt auto-generated)."
|
|
85
|
+
},
|
|
86
|
+
id: { type: "string", description: "Task id for action=status or target for action=promote." },
|
|
87
|
+
status: {
|
|
88
|
+
type: "string",
|
|
89
|
+
enum: ["pending", "in_progress", "blocked", "failed", "review", "completed"],
|
|
90
|
+
description: "New status for action=status."
|
|
91
|
+
},
|
|
92
|
+
target: {
|
|
93
|
+
type: "string",
|
|
94
|
+
description: "Target task identifier (id, 1-based index, or title substring) for action=promote."
|
|
95
|
+
},
|
|
96
|
+
subtasks: {
|
|
97
|
+
type: "array",
|
|
98
|
+
items: { type: "string" },
|
|
99
|
+
description: "Optional subtask titles for action=promote. Each becomes a pending todo."
|
|
100
|
+
},
|
|
101
|
+
scope: {
|
|
102
|
+
type: "string",
|
|
103
|
+
enum: ["session", "project"],
|
|
104
|
+
description: 'Storage scope: "session" (default, isolated to this session) or "project" (shared across all sessions for this project).'
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
required: ["action"]
|
|
108
|
+
},
|
|
109
|
+
async execute(input, ctx) {
|
|
110
|
+
const sessionTaskPath = ctx.meta["task.path"];
|
|
111
|
+
let taskPath;
|
|
112
|
+
if (input.scope === "project") {
|
|
113
|
+
if (typeof sessionTaskPath === "string") {
|
|
114
|
+
const lastSep = Math.max(sessionTaskPath.lastIndexOf("/"), sessionTaskPath.lastIndexOf("\\"));
|
|
115
|
+
taskPath = lastSep >= 0 ? sessionTaskPath.slice(0, lastSep + 1) + "backlog.tasks.json" : "backlog.tasks.json";
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
taskPath = sessionTaskPath;
|
|
119
|
+
}
|
|
120
|
+
if (typeof taskPath !== "string" || !taskPath) {
|
|
121
|
+
return { ok: false, message: "Task storage path not configured.", count: 0, completed: 0, inProgress: 0 };
|
|
122
|
+
}
|
|
123
|
+
const sessionId = ctx.session?.id ?? "unknown";
|
|
124
|
+
let early = null;
|
|
125
|
+
const promoteMeta = { count: 0, title: "" };
|
|
126
|
+
const planifyMeta = { title: "", details: "" };
|
|
127
|
+
let didPlanify = false;
|
|
128
|
+
let todosToReplace = null;
|
|
129
|
+
let file;
|
|
130
|
+
try {
|
|
131
|
+
file = await mutateTasks(taskPath, sessionId, async (f) => {
|
|
132
|
+
switch (input.action) {
|
|
133
|
+
case "show":
|
|
134
|
+
break;
|
|
135
|
+
case "replace": {
|
|
136
|
+
if (!Array.isArray(input.tasks)) {
|
|
137
|
+
early = { ok: false, message: "action=replace requires `tasks` array.", count: 0, completed: 0, inProgress: 0 };
|
|
138
|
+
return f;
|
|
139
|
+
}
|
|
140
|
+
const newIds = new Set(input.tasks.map((t) => t.id));
|
|
141
|
+
if (newIds.size !== input.tasks.length) {
|
|
142
|
+
const seen = /* @__PURE__ */ new Set();
|
|
143
|
+
const dupes = [...new Set(input.tasks.map((t) => t.id).filter((id) => {
|
|
144
|
+
if (seen.has(id)) return true;
|
|
145
|
+
seen.add(id);
|
|
146
|
+
return false;
|
|
147
|
+
}))];
|
|
148
|
+
early = {
|
|
149
|
+
ok: false,
|
|
150
|
+
message: `action=replace has duplicate task IDs: ${dupes.join(", ")}. Each task id must be unique.`,
|
|
151
|
+
count: 0,
|
|
152
|
+
completed: 0,
|
|
153
|
+
inProgress: 0
|
|
154
|
+
};
|
|
155
|
+
return f;
|
|
156
|
+
}
|
|
157
|
+
for (const t of input.tasks) {
|
|
158
|
+
if (t.dependsOn && t.dependsOn.length > 0) {
|
|
159
|
+
const missing = t.dependsOn.filter((d) => !newIds.has(d));
|
|
160
|
+
if (missing.length > 0) {
|
|
161
|
+
early = {
|
|
162
|
+
ok: false,
|
|
163
|
+
message: `dependsOn validation failed: task "${t.id}" references unknown IDs: ${missing.join(", ")}`,
|
|
164
|
+
count: 0,
|
|
165
|
+
completed: 0,
|
|
166
|
+
inProgress: 0
|
|
167
|
+
};
|
|
168
|
+
return f;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
173
|
+
f.tasks = input.tasks.map((t) => ({
|
|
174
|
+
...t,
|
|
175
|
+
createdAt: t.createdAt || now,
|
|
176
|
+
updatedAt: now
|
|
177
|
+
}));
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
case "add": {
|
|
181
|
+
const t = input.task;
|
|
182
|
+
if (!t?.title) {
|
|
183
|
+
early = { ok: false, message: "action=add requires `task` with at least `title`.", count: 0, completed: 0, inProgress: 0 };
|
|
184
|
+
return f;
|
|
185
|
+
}
|
|
186
|
+
if (t.dependsOn && t.dependsOn.length > 0) {
|
|
187
|
+
const existingIds = new Set(f.tasks.map((e) => e.id));
|
|
188
|
+
const missing = t.dependsOn.filter((d) => !existingIds.has(d));
|
|
189
|
+
if (missing.length > 0) {
|
|
190
|
+
early = {
|
|
191
|
+
ok: false,
|
|
192
|
+
message: `dependsOn validation failed: unknown task IDs: ${missing.join(", ")}`,
|
|
193
|
+
count: 0,
|
|
194
|
+
completed: 0,
|
|
195
|
+
inProgress: 0
|
|
196
|
+
};
|
|
197
|
+
return f;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
201
|
+
const newTask = {
|
|
202
|
+
id: `task_${Date.now()}_${randomUUID().slice(0, 8)}`,
|
|
203
|
+
title: t.title,
|
|
204
|
+
description: t.description,
|
|
205
|
+
type: t.type || "feature",
|
|
206
|
+
priority: t.priority || "medium",
|
|
207
|
+
status: t.status || "pending",
|
|
208
|
+
dependsOn: t.dependsOn,
|
|
209
|
+
assignee: t.assignee,
|
|
210
|
+
estimateHours: t.estimateHours,
|
|
211
|
+
tags: t.tags,
|
|
212
|
+
createdAt: now,
|
|
213
|
+
updatedAt: now
|
|
214
|
+
};
|
|
215
|
+
f.tasks.push(newTask);
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
case "status": {
|
|
219
|
+
if (!input.id || !input.status) {
|
|
220
|
+
early = { ok: false, message: "action=status requires `id` and `status`.", count: 0, completed: 0, inProgress: 0 };
|
|
221
|
+
return f;
|
|
222
|
+
}
|
|
223
|
+
const task = f.tasks.find((t) => t.id === input.id);
|
|
224
|
+
if (!task) {
|
|
225
|
+
early = { ok: false, message: `Task "${input.id}" not found.`, count: 0, completed: 0, inProgress: 0 };
|
|
226
|
+
return f;
|
|
227
|
+
}
|
|
228
|
+
task.status = input.status;
|
|
229
|
+
task.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
case "promote": {
|
|
233
|
+
const target = input.target?.trim();
|
|
234
|
+
if (!target) {
|
|
235
|
+
early = { ok: false, message: "action=promote requires `target` (task id, index, or title substring).", count: 0, completed: 0, inProgress: 0 };
|
|
236
|
+
return f;
|
|
237
|
+
}
|
|
238
|
+
const idx = findTaskIndex(f.tasks, target);
|
|
239
|
+
if (idx === -1) {
|
|
240
|
+
early = { ok: false, message: `No task matched "${target}".`, count: 0, completed: 0, inProgress: 0 };
|
|
241
|
+
return f;
|
|
242
|
+
}
|
|
243
|
+
const match = f.tasks[idx];
|
|
244
|
+
if (!match) {
|
|
245
|
+
early = { ok: false, message: `No task matched "${target}".`, count: 0, completed: 0, inProgress: 0 };
|
|
246
|
+
return f;
|
|
247
|
+
}
|
|
248
|
+
if (match.status !== "completed" && match.status !== "failed") {
|
|
249
|
+
match.status = "in_progress";
|
|
250
|
+
match.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
251
|
+
}
|
|
252
|
+
const todos = [];
|
|
253
|
+
const ts = Date.now();
|
|
254
|
+
todos.push({
|
|
255
|
+
id: `todo_${ts}_task`,
|
|
256
|
+
content: match.title,
|
|
257
|
+
status: "in_progress",
|
|
258
|
+
activeForm: match.title,
|
|
259
|
+
promotedFromTask: match.id
|
|
260
|
+
});
|
|
261
|
+
if (match.description) {
|
|
262
|
+
todos.push({
|
|
263
|
+
id: `todo_${ts}_${randomUUID().slice(0, 6)}`,
|
|
264
|
+
content: match.description.slice(0, 200),
|
|
265
|
+
status: "pending",
|
|
266
|
+
promotedFromTask: match.id
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
if (input.subtasks && input.subtasks.length > 0) {
|
|
270
|
+
for (const st of input.subtasks) {
|
|
271
|
+
todos.push({
|
|
272
|
+
id: `todo_${ts}_${randomUUID().slice(0, 6)}`,
|
|
273
|
+
content: st,
|
|
274
|
+
status: "pending",
|
|
275
|
+
promotedFromTask: match.id
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
todosToReplace = todos;
|
|
280
|
+
promoteMeta.count = todos.length;
|
|
281
|
+
promoteMeta.title = match.title;
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
case "planify": {
|
|
285
|
+
const target = input.target?.trim();
|
|
286
|
+
if (!target) {
|
|
287
|
+
early = { ok: false, message: "action=planify requires `target` (task id, index, or title substring).", count: 0, completed: 0, inProgress: 0 };
|
|
288
|
+
return f;
|
|
289
|
+
}
|
|
290
|
+
const idx = findTaskIndex(f.tasks, target);
|
|
291
|
+
if (idx === -1) {
|
|
292
|
+
early = { ok: false, message: `No task matched "${target}".`, count: 0, completed: 0, inProgress: 0 };
|
|
293
|
+
return f;
|
|
294
|
+
}
|
|
295
|
+
const match = f.tasks[idx];
|
|
296
|
+
if (!match) {
|
|
297
|
+
early = { ok: false, message: `No task matched "${target}".`, count: 0, completed: 0, inProgress: 0 };
|
|
298
|
+
return f;
|
|
299
|
+
}
|
|
300
|
+
planifyMeta.title = match.title;
|
|
301
|
+
planifyMeta.details = match.description ?? "";
|
|
302
|
+
didPlanify = true;
|
|
303
|
+
break;
|
|
304
|
+
}
|
|
305
|
+
default:
|
|
306
|
+
early = { ok: false, message: `Unknown action "${input.action}". Use replace | add | status | show | promote | planify.`, count: 0, completed: 0, inProgress: 0 };
|
|
307
|
+
return f;
|
|
308
|
+
}
|
|
309
|
+
return f;
|
|
310
|
+
});
|
|
311
|
+
} catch (err) {
|
|
312
|
+
return {
|
|
313
|
+
ok: false,
|
|
314
|
+
message: `Task change not saved \u2014 ${err instanceof Error ? err.message : String(err)}`,
|
|
315
|
+
count: 0,
|
|
316
|
+
completed: 0,
|
|
317
|
+
inProgress: 0
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
if (todosToReplace) ctx.state.replaceTodos(todosToReplace);
|
|
321
|
+
if (early) return early;
|
|
322
|
+
if (didPlanify) {
|
|
323
|
+
const { title, details } = planifyMeta;
|
|
324
|
+
const planPathRaw = ctx.meta["plan.path"];
|
|
325
|
+
const prog = computeTaskItemProgress(file.tasks);
|
|
326
|
+
if (typeof planPathRaw === "string" && planPathRaw) {
|
|
327
|
+
let planPath = planPathRaw;
|
|
328
|
+
if (input.scope === "project") {
|
|
329
|
+
const lastSep = Math.max(planPath.lastIndexOf("/"), planPath.lastIndexOf("\\"));
|
|
330
|
+
planPath = lastSep >= 0 ? planPath.slice(0, lastSep + 1) + "backlog.plan.json" : "backlog.plan.json";
|
|
331
|
+
}
|
|
332
|
+
let formatted = "";
|
|
333
|
+
try {
|
|
334
|
+
await mutatePlan(planPath, sessionId, (pf) => {
|
|
335
|
+
const { plan: updated } = addPlanItem(pf, title, details || void 0);
|
|
336
|
+
formatted = formatPlan(updated);
|
|
337
|
+
return updated;
|
|
338
|
+
});
|
|
339
|
+
} catch (err) {
|
|
340
|
+
return {
|
|
341
|
+
ok: false,
|
|
342
|
+
message: `planify: plan not saved \u2014 ${err instanceof Error ? err.message : String(err)}`,
|
|
343
|
+
count: file.tasks.length,
|
|
344
|
+
completed: prog.completed,
|
|
345
|
+
inProgress: prog.inProgress
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
return {
|
|
349
|
+
ok: true,
|
|
350
|
+
message: `planify ok \u2014 added "${title}" to plan.
|
|
351
|
+
${formatted}`,
|
|
352
|
+
count: file.tasks.length,
|
|
353
|
+
completed: prog.completed,
|
|
354
|
+
inProgress: prog.inProgress
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
return {
|
|
358
|
+
ok: false,
|
|
359
|
+
message: "Plan storage path not configured \u2014 cannot planify.",
|
|
360
|
+
count: file.tasks.length,
|
|
361
|
+
completed: prog.completed,
|
|
362
|
+
inProgress: prog.inProgress
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
const p = computeTaskItemProgress(file.tasks);
|
|
366
|
+
const summary = promoteMeta.count > 0 ? `promote ok \u2014 ${promoteMeta.count} todo(s) created from "${promoteMeta.title}".
|
|
367
|
+
${formatTaskList(file.tasks)}` : file.tasks.length > 0 ? formatTaskList(file.tasks) : "No tasks.";
|
|
368
|
+
return {
|
|
369
|
+
ok: true,
|
|
370
|
+
message: summary,
|
|
371
|
+
count: file.tasks.length,
|
|
372
|
+
completed: p.completed,
|
|
373
|
+
inProgress: p.inProgress
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
export {
|
|
378
|
+
taskTool
|
|
379
|
+
};
|
|
380
|
+
//# sourceMappingURL=task.js.map
|
package/dist/task.js.map
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/task.ts"],
|
|
4
|
+
"sourcesContent": ["import {\n type TaskItem,\n type TaskStatus,\n type TaskFile,\n computeTaskItemProgress,\n formatTaskList,\n} from '@wrongstack/core';\nimport {\n mutateTasks,\n} from '@wrongstack/core';\nimport {\n addPlanItem,\n mutatePlan,\n formatPlan,\n} from '@wrongstack/core';\nimport { randomUUID } from 'node:crypto';\nimport type { Tool } from '@wrongstack/core';\n\n// ---------------------------------------------------------------------------\n// Task tool \u2014 structured work items with dependencies, types, and priorities.\n// Unlike `todo` (flat, session-scoped), tasks support:\n// - Dependencies (task can depend on other tasks)\n// - Type classification (feature, bugfix, refactor, docs, test, chore)\n// - Priority ranking (critical, high, medium, low)\n// - Assignment (which agent/subagent)\n// - Estimates (hours)\n//\n// Like `todo`, the list is fully replaced on every call. Session-persistent:\n// stored at `ctx.meta['task.path']` and isolated to this session \u2014 other sessions\n// have their own separate task lists.\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Find a task by 1-based index, exact id, or case-insensitive title substring. */\nfunction findTaskIndex(tasks: TaskItem[], query: string): number {\n const asNum = Number.parseInt(query, 10);\n if (!Number.isNaN(asNum)) {\n const idx = asNum - 1;\n if (tasks[idx]) return idx;\n }\n const byId = tasks.findIndex((t) => t.id === query);\n if (byId >= 0) return byId;\n const lower = query.toLowerCase();\n return tasks.findIndex((t) => t.title.toLowerCase().includes(lower));\n}\n\n// ---------------------------------------------------------------------------\n// Tool\n// ---------------------------------------------------------------------------\n\ninterface TaskInput {\n /** Replace: set new task list. Add: append a task. Status: update task status. Promote: convert a task to todo items. */\n action: 'replace' | 'add' | 'status' | 'show' | 'promote' | 'planify';\n /** Full task list for action=replace. */\n tasks?: TaskItem[] | undefined;\n /** Single task for action=add. id, createdAt, updatedAt are auto-generated. */\n task?: Omit<TaskItem, 'id' | 'createdAt' | 'updatedAt'> | undefined;\n /** Task id for action=status or target for action=promote. */\n id?: string | undefined;\n /** New status for action=status. */\n status?: TaskStatus | undefined;\n /** Target task (id, 1-based index, or title substring) for action=promote. */\n target?: string | undefined;\n /** Optional subtask titles for action=promote. */\n subtasks?: string[] | undefined;\n /**\n * Storage scope. Default (unset): uses the session-scoped path \u2014 isolated to this\n * session, survives resume within the same session.\n * `scope: 'project'`: uses a shared project-level path, visible to all sessions\n * for this project. Useful for a shared backlog that outlasts any single session.\n */\n scope?: 'session' | 'project';\n}\n\ninterface TaskOutput {\n ok: boolean;\n message: string;\n count: number;\n completed: number;\n inProgress: number;\n}\n\nexport const taskTool: Tool<TaskInput, TaskOutput> = {\n name: 'task',\n category: 'Session',\n description:\n 'Manage session-persistent structured work items with dependencies, types, and priorities. ' +\n 'Unlike `todo` (flat, tactical), `task` supports typed work (feature/bugfix/refactor/etc.), ' +\n 'dependencies between items, priority ranking, and agent assignment. ' +\n 'Tasks are written to disk and survive session resumes. By default they are isolated to this session; ' +\n 'use `scope: \"project\"` to store tasks in a shared project-level file visible to all sessions.',\n usageHint:\n 'USE FOR STRUCTURED WORK:\\n' +\n '- `action: \"replace\"` \u2014 set the complete task list (tasks ordered by priority)\\n' +\n '- `action: \"add\"` \u2014 append a single task\\n' +\n '- `action: \"status\"` \u2014 update a task\\'s status (e.g. pending\u2192in_progress, in_progress\u2192completed)\\n' +\n '- `action: \"show\"` \u2014 view current tasks without changing them\\n' +\n '- `action: \"promote\"` \u2014 convert a task into actionable todo items via `target` (id|index|substring)\\n' +\n '- `action: \"planify\"` \u2014 promote a task to a plan item (strategic level) via `target` (id|index|substring)\\n\\n' +\n 'Task fields:\\n' +\n '- `dependsOn`: list of task IDs this one waits for\\n' +\n '- `type`: \"feature\" | \"bugfix\" | \"refactor\" | \"docs\" | \"test\" | \"chore\"\\n' +\n '- `priority`: \"critical\" | \"high\" | \"medium\" | \"low\"\\n' +\n '- `assignee`: agent/subagent name (e.g. \"bug-hunter\", \"refactor-planner\")\\n' +\n '- `estimateHours`: rough time estimate\\n' +\n '- `scope`: \"session\" (default, isolated) or \"project\" (shared across sessions)',\n permission: 'confirm',\n mutating: true,\n capabilities: ['fs.write'],\n icon: 'task',\n timeoutMs: 2_000,\n inputSchema: {\n type: 'object',\n properties: {\n action: {\n type: 'string',\n enum: ['replace', 'add', 'status', 'show', 'promote', 'planify'],\n description: 'replace = set full list, add = append, status = update task status, show = view only, promote = convert task to todos, planify = convert task to plan item.',\n },\n tasks: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n id: { type: 'string', description: 'Unique id (e.g. \"t1\", \"auth-flow\").' },\n title: { type: 'string', description: 'Short title.' },\n description: { type: 'string', description: 'Optional details.' },\n type: { type: 'string', enum: ['feature', 'bugfix', 'refactor', 'docs', 'test', 'chore'] },\n priority: { type: 'string', enum: ['critical', 'high', 'medium', 'low'] },\n status: { type: 'string', enum: ['pending', 'in_progress', 'blocked', 'failed', 'review', 'completed'] },\n dependsOn: {\n type: 'array',\n items: { type: 'string' },\n description: 'IDs of tasks this one depends on.',\n },\n assignee: { type: 'string', description: 'Agent/subagent assigned.' },\n estimateHours: { type: 'number', description: 'Estimated hours.' },\n tags: { type: 'array', items: { type: 'string' }, description: 'Optional tags.' },\n createdAt: { type: 'string' },\n updatedAt: { type: 'string' },\n },\n required: ['id', 'title', 'type', 'priority', 'status'],\n },\n description: 'Complete task list. Replaces previous list entirely.',\n },\n task: {\n type: 'object',\n properties: {\n title: { type: 'string' },\n description: { type: 'string' },\n type: { type: 'string', enum: ['feature', 'bugfix', 'refactor', 'docs', 'test', 'chore'] },\n priority: { type: 'string', enum: ['critical', 'high', 'medium', 'low'] },\n status: { type: 'string', enum: ['pending', 'in_progress', 'blocked', 'failed', 'review', 'completed'] },\n dependsOn: { type: 'array', items: { type: 'string' } },\n assignee: { type: 'string' },\n estimateHours: { type: 'number' },\n tags: { type: 'array', items: { type: 'string' } },\n },\n required: ['title', 'type', 'priority'],\n description: 'Single task to append (id/createdAt/updatedAt auto-generated).',\n },\n id: { type: 'string', description: 'Task id for action=status or target for action=promote.' },\n status: {\n type: 'string',\n enum: ['pending', 'in_progress', 'blocked', 'failed', 'review', 'completed'],\n description: 'New status for action=status.',\n },\n target: {\n type: 'string',\n description: 'Target task identifier (id, 1-based index, or title substring) for action=promote.',\n },\n subtasks: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional subtask titles for action=promote. Each becomes a pending todo.',\n },\n scope: {\n type: 'string',\n enum: ['session', 'project'],\n description: 'Storage scope: \"session\" (default, isolated to this session) or \"project\" (shared across all sessions for this project).',\n },\n },\n required: ['action'],\n },\n async execute(input, ctx) {\n const sessionTaskPath = (ctx.meta as Record<string, unknown>)['task.path'] as string | undefined;\n let taskPath: string | undefined;\n\n if (input.scope === 'project') {\n // Project-level: derive from the session path by replacing the filename with\n // 'backlog.tasks.json' so all sessions share the same file.\n if (typeof sessionTaskPath === 'string') {\n // Handle BOTH separators \u2014 a Windows-native path uses '\\\\'; a '/'-only\n // search would miss it and fall back to a bare relative path written\n // into the process CWD instead of the sessions dir.\n const lastSep = Math.max(sessionTaskPath.lastIndexOf('/'), sessionTaskPath.lastIndexOf('\\\\'));\n taskPath = lastSep >= 0\n ? sessionTaskPath.slice(0, lastSep + 1) + 'backlog.tasks.json'\n : 'backlog.tasks.json';\n }\n } else {\n taskPath = sessionTaskPath;\n }\n\n if (typeof taskPath !== 'string' || !taskPath) {\n return { ok: false, message: 'Task storage path not configured.', count: 0, completed: 0, inProgress: 0 };\n }\n const sessionId = ctx.session?.id ?? 'unknown';\n\n // Early-return result for validation errors that happen before or\n // during the critical section. The lock callback sets this instead of\n // mutating the file, and we return it after the lock releases.\n let early: TaskOutput | null = null;\n // Track promote output for the custom message\n const promoteMeta = { count: 0, title: '' };\n // Track planify data \u2014 written to plan file after the task lock releases\n const planifyMeta = { title: '', details: '' };\n let didPlanify = false;\n // collect todos to replace \u2014 called AFTER mutateTasks so rollback is possible\n type TodosReplacement = Array<{ id: string; content: string; status: 'pending' | 'in_progress' | 'completed'; activeForm?: string; promotedFromTask?: string }>;\n let todosToReplace: TodosReplacement | null = null;\n\n let file: TaskFile;\n try {\n file = await mutateTasks(taskPath, sessionId, async (f: TaskFile) => {\n switch (input.action) {\n case 'show':\n // read-only \u2014 no mutation, just return current state\n break;\n\n case 'replace': {\n if (!Array.isArray(input.tasks)) {\n early = { ok: false, message: 'action=replace requires `tasks` array.', count: 0, completed: 0, inProgress: 0 };\n return f;\n }\n // Validate id uniqueness: findTaskIndex / status resolve a task by\n // the FIRST id match, so a duplicate id silently becomes unaddressable.\n const newIds = new Set(input.tasks.map((t) => t.id));\n if (newIds.size !== input.tasks.length) {\n const seen = new Set<string>();\n const dupes = [...new Set(input.tasks.map((t) => t.id).filter((id) => {\n if (seen.has(id)) return true;\n seen.add(id);\n return false;\n }))];\n early = {\n ok: false,\n message: `action=replace has duplicate task IDs: ${dupes.join(', ')}. Each task id must be unique.`,\n count: 0,\n completed: 0,\n inProgress: 0,\n };\n return f;\n }\n // Validate dependsOn references: must point to IDs within the new batch\n for (const t of input.tasks) {\n if (t.dependsOn && t.dependsOn.length > 0) {\n const missing = t.dependsOn.filter((d) => !newIds.has(d));\n if (missing.length > 0) {\n early = {\n ok: false,\n message: `dependsOn validation failed: task \"${t.id}\" references unknown IDs: ${missing.join(', ')}`,\n count: 0,\n completed: 0,\n inProgress: 0,\n };\n return f;\n }\n }\n }\n const now = new Date().toISOString();\n f.tasks = input.tasks.map((t) => ({\n ...t,\n createdAt: t.createdAt || now,\n updatedAt: now,\n }));\n break;\n }\n\n case 'add': {\n const t = input.task;\n if (!t?.title) {\n early = { ok: false, message: 'action=add requires `task` with at least `title`.', count: 0, completed: 0, inProgress: 0 };\n return f;\n }\n // Validate dependsOn: all referenced IDs must exist in the current task list\n if (t.dependsOn && t.dependsOn.length > 0) {\n const existingIds = new Set(f.tasks.map((e: TaskItem) => e.id));\n const missing = t.dependsOn.filter((d) => !existingIds.has(d));\n if (missing.length > 0) {\n early = {\n ok: false,\n message: `dependsOn validation failed: unknown task IDs: ${missing.join(', ')}`,\n count: 0,\n completed: 0,\n inProgress: 0,\n };\n return f;\n }\n }\n const now = new Date().toISOString();\n const newTask: TaskItem = {\n id: `task_${Date.now()}_${randomUUID().slice(0, 8)}`,\n title: t.title,\n description: t.description,\n type: t.type || 'feature',\n priority: t.priority || 'medium',\n status: t.status || 'pending',\n dependsOn: t.dependsOn,\n assignee: t.assignee,\n estimateHours: t.estimateHours,\n tags: t.tags,\n createdAt: now,\n updatedAt: now,\n };\n f.tasks.push(newTask);\n break;\n }\n\n case 'status': {\n if (!input.id || !input.status) {\n early = { ok: false, message: 'action=status requires `id` and `status`.', count: 0, completed: 0, inProgress: 0 };\n return f;\n }\n const task = f.tasks.find((t: TaskItem) => t.id === input.id);\n if (!task) {\n early = { ok: false, message: `Task \"${input.id}\" not found.`, count: 0, completed: 0, inProgress: 0 };\n return f;\n }\n task.status = input.status;\n task.updatedAt = new Date().toISOString();\n break;\n }\n\n case 'promote': {\n const target = input.target?.trim();\n if (!target) {\n early = { ok: false, message: 'action=promote requires `target` (task id, index, or title substring).', count: 0, completed: 0, inProgress: 0 };\n return f;\n }\n const idx = findTaskIndex(f.tasks, target);\n if (idx === -1) {\n early = { ok: false, message: `No task matched \"${target}\".`, count: 0, completed: 0, inProgress: 0 };\n return f;\n }\n const match = f.tasks[idx];\n /* v8 ignore next 4 -- findTaskIndex returned a valid in-range idx, so match is always defined; defensive. */\n if (!match) {\n early = { ok: false, message: `No task matched \"${target}\".`, count: 0, completed: 0, inProgress: 0 };\n return f;\n }\n\n // Mark task in_progress\n if (match.status !== 'completed' && match.status !== 'failed') {\n match.status = 'in_progress';\n match.updatedAt = new Date().toISOString();\n }\n\n // Build todo items\n const todos: Array<{ id: string; content: string; status: 'pending' | 'in_progress' | 'completed'; activeForm?: string; promotedFromTask?: string }> = [];\n const ts = Date.now();\n todos.push({\n id: `todo_${ts}_task`,\n content: match.title,\n status: 'in_progress',\n activeForm: match.title,\n promotedFromTask: match.id,\n });\n\n if (match.description) {\n todos.push({\n id: `todo_${ts}_${randomUUID().slice(0, 6)}`,\n content: match.description.slice(0, 200),\n status: 'pending',\n promotedFromTask: match.id,\n });\n }\n\n if (input.subtasks && input.subtasks.length > 0) {\n for (const st of input.subtasks) {\n todos.push({\n id: `todo_${ts}_${randomUUID().slice(0, 6)}`,\n content: st,\n status: 'pending',\n promotedFromTask: match.id,\n });\n }\n }\n\n todosToReplace = todos;\n promoteMeta.count = todos.length;\n promoteMeta.title = match.title;\n break;\n }\n\n case 'planify': {\n const target = input.target?.trim();\n if (!target) {\n early = { ok: false, message: 'action=planify requires `target` (task id, index, or title substring).', count: 0, completed: 0, inProgress: 0 };\n return f;\n }\n const idx = findTaskIndex(f.tasks, target);\n if (idx === -1) {\n early = { ok: false, message: `No task matched \"${target}\".`, count: 0, completed: 0, inProgress: 0 };\n return f;\n }\n const match = f.tasks[idx];\n /* v8 ignore next 4 -- findTaskIndex returned a valid in-range idx, so match is always defined; defensive. */\n if (!match) {\n early = { ok: false, message: `No task matched \"${target}\".`, count: 0, completed: 0, inProgress: 0 };\n return f;\n }\n // Extract data \u2014 plan write happens after the task lock releases\n planifyMeta.title = match.title;\n planifyMeta.details = match.description ?? '';\n didPlanify = true;\n // Do NOT mutate the task \u2014 just copy to plan\n break;\n }\n\n default:\n early = { ok: false, message: `Unknown action \"${(input as { action: string }).action}\". Use replace | add | status | show | promote | planify.`, count: 0, completed: 0, inProgress: 0 };\n return f;\n }\n\n return f;\n });\n } catch (err) {\n // Persist failed (mutateTasks throws on a failed save) \u2014 report ok:false\n // instead of falsely claiming the tasks were saved.\n return {\n ok: false,\n message: `Task change not saved \u2014 ${err instanceof Error ? err.message : String(err)}`,\n count: 0,\n completed: 0,\n inProgress: 0,\n };\n }\n\n // Apply todo replacements after the task file mutation succeeds so that\n // on error the state is rolled back cleanly.\n if (todosToReplace) ctx.state.replaceTodos(todosToReplace);\n\n // If the callback set an early-return result, use it\n if (early) return early;\n\n // If planify copied task data, write it to the plan file now\n if (didPlanify) {\n const { title, details } = planifyMeta;\n const planPathRaw = (ctx.meta as Record<string, unknown>)['plan.path'];\n const prog = computeTaskItemProgress(file.tasks);\n if (typeof planPathRaw === 'string' && planPathRaw) {\n let planPath: string = planPathRaw;\n // Honor project scope for the PLAN file too (mirror of plan.ts taskify);\n // handle both separators.\n if (input.scope === 'project') {\n const lastSep = Math.max(planPath.lastIndexOf('/'), planPath.lastIndexOf('\\\\'));\n planPath = lastSep >= 0 ? planPath.slice(0, lastSep + 1) + 'backlog.plan.json' : 'backlog.plan.json';\n }\n // Mutate the cross-file under ITS OWN lock so a concurrent plan tool\n // call in the same batch can't clobber the write.\n let formatted = '';\n try {\n await mutatePlan(planPath, sessionId, (pf) => {\n const { plan: updated } = addPlanItem(pf, title, details || undefined);\n formatted = formatPlan(updated);\n return updated;\n });\n } catch (err) {\n return {\n ok: false,\n message: `planify: plan not saved \u2014 ${err instanceof Error ? err.message : String(err)}`,\n count: file.tasks.length,\n completed: prog.completed,\n inProgress: prog.inProgress,\n };\n }\n return {\n ok: true,\n message: `planify ok \u2014 added \"${title}\" to plan.\\n${formatted}`,\n count: file.tasks.length,\n completed: prog.completed,\n inProgress: prog.inProgress,\n };\n }\n // Plan path missing \u2014 still report the REAL task counts (the task file was\n // loaded and may be non-empty), not zeros.\n return {\n ok: false,\n message: 'Plan storage path not configured \u2014 cannot planify.',\n count: file.tasks.length,\n completed: prog.completed,\n inProgress: prog.inProgress,\n };\n }\n\n const p = computeTaskItemProgress(file.tasks);\n const summary = promoteMeta.count > 0\n ? `promote ok \u2014 ${promoteMeta.count} todo(s) created from \"${promoteMeta.title}\".\\n${formatTaskList(file.tasks)}`\n : file.tasks.length > 0\n ? formatTaskList(file.tasks)\n : 'No tasks.';\n return {\n ok: true,\n message: summary,\n count: file.tasks.length,\n completed: p.completed,\n inProgress: p.inProgress,\n };\n },\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/test.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { Tool } from '@wrongstack/core';
|
|
2
|
-
|
|
1
|
+
import type { Tool } from '@wrongstack/core';
|
|
3
2
|
interface TestInput {
|
|
4
3
|
files?: string | string[] | undefined;
|
|
5
4
|
runner?: 'vitest' | 'jest' | 'mocha' | 'auto' | undefined;
|
|
@@ -20,6 +19,6 @@ interface TestOutput {
|
|
|
20
19
|
output: string;
|
|
21
20
|
truncated: boolean;
|
|
22
21
|
}
|
|
23
|
-
declare const testTool: Tool<TestInput, TestOutput>;
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
export declare const testTool: Tool<TestInput, TestOutput>;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAmB,MAAM,kBAAkB,CAAC;AAK9D,UAAU,SAAS;IACjB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;IACtC,MAAM,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IAC1D,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC/B;AAED,UAAU,UAAU;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE,UAAU,CAkHhD,CAAC"}
|