@tagma/sdk 0.4.2 → 0.4.4
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/LICENSE +21 -0
- package/README.md +5 -5
- package/dist/adapters/stdin-approval.d.ts +6 -0
- package/dist/adapters/stdin-approval.d.ts.map +1 -0
- package/dist/adapters/stdin-approval.js +90 -0
- package/dist/adapters/stdin-approval.js.map +1 -0
- package/dist/adapters/websocket-approval.d.ts +28 -0
- package/dist/adapters/websocket-approval.d.ts.map +1 -0
- package/dist/adapters/websocket-approval.js +145 -0
- package/dist/adapters/websocket-approval.js.map +1 -0
- package/dist/approval.d.ts +13 -0
- package/dist/approval.d.ts.map +1 -0
- package/dist/approval.js +91 -0
- package/dist/approval.js.map +1 -0
- package/dist/bootstrap.d.ts +2 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +30 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/completions/exit-code.d.ts +3 -0
- package/dist/completions/exit-code.d.ts.map +1 -0
- package/dist/completions/exit-code.js +25 -0
- package/dist/completions/exit-code.js.map +1 -0
- package/dist/completions/file-exists.d.ts +3 -0
- package/dist/completions/file-exists.d.ts.map +1 -0
- package/dist/completions/file-exists.js +58 -0
- package/dist/completions/file-exists.js.map +1 -0
- package/dist/completions/output-check.d.ts +3 -0
- package/dist/completions/output-check.d.ts.map +1 -0
- package/dist/completions/output-check.js +81 -0
- package/dist/completions/output-check.js.map +1 -0
- package/dist/config-ops.d.ts +55 -0
- package/dist/config-ops.d.ts.map +1 -0
- package/dist/config-ops.js +258 -0
- package/dist/config-ops.js.map +1 -0
- package/dist/dag.d.ts +46 -0
- package/dist/dag.d.ts.map +1 -0
- package/dist/dag.js +193 -0
- package/dist/dag.js.map +1 -0
- package/dist/drivers/claude-code.d.ts +3 -0
- package/dist/drivers/claude-code.d.ts.map +1 -0
- package/dist/drivers/claude-code.js +210 -0
- package/dist/drivers/claude-code.js.map +1 -0
- package/dist/engine.d.ts +89 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +815 -0
- package/dist/engine.js.map +1 -0
- package/dist/hooks.d.ts +73 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +103 -0
- package/dist/hooks.js.map +1 -0
- package/dist/logger.d.ts +61 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +151 -0
- package/dist/logger.js.map +1 -0
- package/dist/middlewares/static-context.d.ts +3 -0
- package/dist/middlewares/static-context.d.ts.map +1 -0
- package/dist/middlewares/static-context.js +36 -0
- package/dist/middlewares/static-context.js.map +1 -0
- package/dist/pipeline-runner.d.ts +50 -0
- package/dist/pipeline-runner.d.ts.map +1 -0
- package/dist/pipeline-runner.js +139 -0
- package/dist/pipeline-runner.js.map +1 -0
- package/dist/registry.d.ts +43 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +182 -0
- package/dist/registry.js.map +1 -0
- package/dist/runner.d.ts +19 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +364 -0
- package/dist/runner.js.map +1 -0
- package/dist/schema.d.ts +27 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +373 -0
- package/dist/schema.js.map +1 -0
- package/dist/sdk.d.ts +27 -0
- package/dist/sdk.d.ts.map +1 -0
- package/dist/sdk.js +33 -0
- package/dist/sdk.js.map +1 -0
- package/dist/templates.d.ts +20 -0
- package/dist/templates.d.ts.map +1 -0
- package/dist/templates.js +93 -0
- package/dist/templates.js.map +1 -0
- package/dist/triggers/file.d.ts +3 -0
- package/dist/triggers/file.d.ts.map +1 -0
- package/dist/triggers/file.js +123 -0
- package/dist/triggers/file.js.map +1 -0
- package/dist/triggers/manual.d.ts +3 -0
- package/dist/triggers/manual.d.ts.map +1 -0
- package/dist/triggers/manual.js +73 -0
- package/dist/triggers/manual.js.map +1 -0
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +14 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +14 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +138 -0
- package/dist/utils.js.map +1 -0
- package/dist/validate-raw.d.ts +44 -0
- package/dist/validate-raw.d.ts.map +1 -0
- package/dist/validate-raw.js +327 -0
- package/dist/validate-raw.js.map +1 -0
- package/package.json +26 -17
- package/src/approval.ts +5 -3
- package/src/registry.ts +214 -214
- package/src/validate-raw.ts +92 -3
- package/scripts/preinstall.js +0 -38
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Tagma
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
# @tagma/sdk
|
|
2
2
|
|
|
3
|
-
> ## ⚠️ Bun-only
|
|
3
|
+
> ## ⚠️ Bun-only runtime
|
|
4
4
|
>
|
|
5
5
|
> ```bash
|
|
6
6
|
> bun add @tagma/sdk
|
|
7
7
|
> ```
|
|
8
8
|
>
|
|
9
|
-
> This package
|
|
10
|
-
> Bun
|
|
11
|
-
> `
|
|
9
|
+
> This package is published as pre-built JavaScript (`dist/`), but the runtime
|
|
10
|
+
> uses Bun-only APIs (`Bun.spawn`, `Bun.file`, `Bun.serve`). It will install
|
|
11
|
+
> under `npm` / `yarn` / `pnpm` without error, but **crash at runtime on Node**
|
|
12
|
+
> the first time a pipeline spawns a task. Get Bun at <https://bun.sh>.
|
|
12
13
|
>
|
|
13
14
|
> *(The `npm i @tagma/sdk` line in the npmjs.com sidebar is auto-generated by
|
|
14
15
|
> the npm registry website and cannot be removed — please ignore it and use
|
|
@@ -589,7 +590,6 @@ Truncates `text` to at most `maxBytes` UTF-8 bytes (default 16 KB), appending a
|
|
|
589
590
|
| [@tagma/types](https://www.npmjs.com/package/@tagma/types) | Shared TypeScript types |
|
|
590
591
|
| [@tagma/driver-codex](https://www.npmjs.com/package/@tagma/driver-codex) | Codex CLI driver plugin |
|
|
591
592
|
| [@tagma/driver-opencode](https://www.npmjs.com/package/@tagma/driver-opencode) | OpenCode CLI driver plugin |
|
|
592
|
-
| [@tagma/cli](https://www.npmjs.com/package/@tagma/cli) | CLI runner |
|
|
593
593
|
|
|
594
594
|
## License
|
|
595
595
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ApprovalGateway } from '../approval';
|
|
2
|
+
export interface StdinApprovalAdapter {
|
|
3
|
+
readonly detach: () => void;
|
|
4
|
+
}
|
|
5
|
+
export declare function attachStdinApprovalAdapter(gateway: ApprovalGateway): StdinApprovalAdapter;
|
|
6
|
+
//# sourceMappingURL=stdin-approval.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdin-approval.d.ts","sourceRoot":"","sources":["../../src/adapters/stdin-approval.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAmB,MAAM,aAAa,CAAC;AAQpE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,eAAe,GAAG,oBAAoB,CA4FzF"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import * as readline from 'readline';
|
|
2
|
+
export function attachStdinApprovalAdapter(gateway) {
|
|
3
|
+
const queue = [];
|
|
4
|
+
let processing = false;
|
|
5
|
+
let rl = null;
|
|
6
|
+
function ensureReadline() {
|
|
7
|
+
if (!rl) {
|
|
8
|
+
rl = readline.createInterface({ input: process.stdin, terminal: false });
|
|
9
|
+
}
|
|
10
|
+
return rl;
|
|
11
|
+
}
|
|
12
|
+
function readOneLine() {
|
|
13
|
+
return new Promise((resolvePromise) => {
|
|
14
|
+
const reader = ensureReadline();
|
|
15
|
+
const handler = (line) => {
|
|
16
|
+
reader.off('line', handler);
|
|
17
|
+
resolvePromise(line);
|
|
18
|
+
};
|
|
19
|
+
reader.on('line', handler);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
async function processNext() {
|
|
23
|
+
if (processing)
|
|
24
|
+
return;
|
|
25
|
+
processing = true;
|
|
26
|
+
try {
|
|
27
|
+
while (queue.length > 0) {
|
|
28
|
+
const req = queue.shift();
|
|
29
|
+
// If the request was already resolved by another path while queued, skip it.
|
|
30
|
+
if (!gateway.pending().some((p) => p.id === req.id))
|
|
31
|
+
continue;
|
|
32
|
+
process.stdout.write(`\n[APPROVAL REQUIRED] ${req.message}\n` +
|
|
33
|
+
` id: ${req.id}\n` +
|
|
34
|
+
` task: ${req.taskId}${req.trackId ? ` (track: ${req.trackId})` : ''}\n` +
|
|
35
|
+
` approve / reject > `);
|
|
36
|
+
const input = (await readOneLine()).trim().toLowerCase();
|
|
37
|
+
const approveAliases = new Set(['approve', 'yes', 'y', 'ok', 'true', '1']);
|
|
38
|
+
const rejectAliases = new Set(['reject', 'no', 'n', 'deny', 'false', '0']);
|
|
39
|
+
if (approveAliases.has(input)) {
|
|
40
|
+
gateway.resolve(req.id, { outcome: 'approved', actor: 'cli' });
|
|
41
|
+
}
|
|
42
|
+
else if (rejectAliases.has(input)) {
|
|
43
|
+
gateway.resolve(req.id, {
|
|
44
|
+
outcome: 'rejected',
|
|
45
|
+
actor: 'cli',
|
|
46
|
+
reason: 'user rejected via CLI',
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
process.stdout.write(` unrecognized input "${input}" — treating as rejection\n`);
|
|
51
|
+
gateway.resolve(req.id, {
|
|
52
|
+
outcome: 'rejected',
|
|
53
|
+
actor: 'cli',
|
|
54
|
+
reason: `unrecognized CLI input: ${input}`,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
processing = false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const unsubscribe = gateway.subscribe((event) => {
|
|
64
|
+
switch (event.type) {
|
|
65
|
+
case 'requested':
|
|
66
|
+
queue.push(event.request);
|
|
67
|
+
void processNext();
|
|
68
|
+
return;
|
|
69
|
+
case 'resolved':
|
|
70
|
+
case 'expired':
|
|
71
|
+
case 'aborted': {
|
|
72
|
+
// Drop from queue if it's still waiting its turn.
|
|
73
|
+
const idx = queue.findIndex((r) => r.id === event.request.id);
|
|
74
|
+
if (idx >= 0)
|
|
75
|
+
queue.splice(idx, 1);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return {
|
|
81
|
+
detach: () => {
|
|
82
|
+
unsubscribe();
|
|
83
|
+
if (rl) {
|
|
84
|
+
rl.close();
|
|
85
|
+
rl = null;
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=stdin-approval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdin-approval.js","sourceRoot":"","sources":["../../src/adapters/stdin-approval.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ApprovalGateway } from '../approval';
|
|
2
|
+
export interface WebSocketApprovalAdapterOptions {
|
|
3
|
+
port?: number;
|
|
4
|
+
hostname?: string;
|
|
5
|
+
/**
|
|
6
|
+
* M11: shared secret required from the client during the WebSocket
|
|
7
|
+
* upgrade. The token can be supplied either as the `?token=` query
|
|
8
|
+
* parameter or in the `x-tagma-token` request header. When set, any
|
|
9
|
+
* upgrade request that fails the check is rejected with HTTP 401 and
|
|
10
|
+
* never reaches the WebSocket layer (so a misconfigured client cannot
|
|
11
|
+
* exhaust rate-limit slots either). Leave undefined for backward
|
|
12
|
+
* compatibility with localhost-only deployments.
|
|
13
|
+
*/
|
|
14
|
+
token?: string;
|
|
15
|
+
/**
|
|
16
|
+
* M11: opt-out of origin checking. Defaults to false, meaning Origin
|
|
17
|
+
* headers are restricted to loopback hosts (localhost / 127.0.0.1 / ::1).
|
|
18
|
+
* Requests without an Origin header are still allowed so non-browser local
|
|
19
|
+
* clients can connect. Set true only for trusted reverse-proxy setups.
|
|
20
|
+
*/
|
|
21
|
+
allowAnyOrigin?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface WebSocketApprovalAdapter {
|
|
24
|
+
readonly port: number;
|
|
25
|
+
readonly detach: () => void;
|
|
26
|
+
}
|
|
27
|
+
export declare function attachWebSocketApprovalAdapter(gateway: ApprovalGateway, options?: WebSocketApprovalAdapterOptions): WebSocketApprovalAdapter;
|
|
28
|
+
//# sourceMappingURL=websocket-approval.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket-approval.d.ts","sourceRoot":"","sources":["../../src/adapters/websocket-approval.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,aAAa,CAAC;AAoBlE,MAAM,WAAW,+BAA+B;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC;CAC7B;AAQD,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,eAAe,EACxB,OAAO,GAAE,+BAAoC,GAC5C,wBAAwB,CA+I1B"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// Maximum allowed message payload (bytes) to prevent DoS via oversized messages.
|
|
2
|
+
const MAX_PAYLOAD_BYTES = 4_096;
|
|
3
|
+
// Per-client rate limit: at most this many messages per window.
|
|
4
|
+
const RATE_LIMIT_MAX = 10;
|
|
5
|
+
const RATE_LIMIT_WINDOW_MS = 1_000;
|
|
6
|
+
export function attachWebSocketApprovalAdapter(gateway, options = {}) {
|
|
7
|
+
const port = options.port ?? 3000;
|
|
8
|
+
const hostname = options.hostname ?? 'localhost';
|
|
9
|
+
const requiredToken = options.token ?? null;
|
|
10
|
+
const enforceOriginCheck = options.allowAnyOrigin !== true;
|
|
11
|
+
function isLoopbackOrigin(origin) {
|
|
12
|
+
try {
|
|
13
|
+
const host = new URL(origin).hostname.toLowerCase();
|
|
14
|
+
return host === 'localhost' || host === '127.0.0.1' || host === '::1' || host === '[::1]';
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const clients = new Set();
|
|
21
|
+
const clientRates = new Map();
|
|
22
|
+
function broadcast(msg) {
|
|
23
|
+
const text = JSON.stringify(msg);
|
|
24
|
+
for (const ws of clients) {
|
|
25
|
+
ws.send(text);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const unsubscribe = gateway.subscribe((event) => {
|
|
29
|
+
switch (event.type) {
|
|
30
|
+
case 'requested':
|
|
31
|
+
broadcast({ type: 'approval_requested', request: event.request });
|
|
32
|
+
break;
|
|
33
|
+
case 'resolved':
|
|
34
|
+
broadcast({ type: 'approval_resolved', request: event.request, decision: event.decision });
|
|
35
|
+
break;
|
|
36
|
+
case 'expired':
|
|
37
|
+
broadcast({ type: 'approval_expired', request: event.request });
|
|
38
|
+
break;
|
|
39
|
+
case 'aborted':
|
|
40
|
+
broadcast({ type: 'approval_aborted', request: event.request, reason: event.reason });
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
const server = Bun.serve({
|
|
45
|
+
port,
|
|
46
|
+
hostname,
|
|
47
|
+
fetch(req, server) {
|
|
48
|
+
if (enforceOriginCheck) {
|
|
49
|
+
const origin = req.headers.get('origin');
|
|
50
|
+
if (origin && !isLoopbackOrigin(origin)) {
|
|
51
|
+
return new Response('forbidden origin', { status: 403 });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// M11: enforce token before any upgrade so an unauthenticated client
|
|
55
|
+
// can't even open a socket. Tokens may arrive via header or query.
|
|
56
|
+
if (requiredToken !== null) {
|
|
57
|
+
const headerToken = req.headers.get('x-tagma-token') ?? '';
|
|
58
|
+
let queryToken = '';
|
|
59
|
+
try {
|
|
60
|
+
queryToken = new URL(req.url).searchParams.get('token') ?? '';
|
|
61
|
+
}
|
|
62
|
+
catch { /* malformed URL — leave queryToken empty */ }
|
|
63
|
+
const presented = headerToken || queryToken;
|
|
64
|
+
if (presented !== requiredToken) {
|
|
65
|
+
return new Response('unauthorized', { status: 401 });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (server.upgrade(req))
|
|
69
|
+
return undefined;
|
|
70
|
+
return new Response('tagma-sdk WebSocket approval endpoint', { status: 426 });
|
|
71
|
+
},
|
|
72
|
+
websocket: {
|
|
73
|
+
open(ws) {
|
|
74
|
+
clients.add(ws);
|
|
75
|
+
// Sync current pending approvals to newly connected client.
|
|
76
|
+
ws.send(JSON.stringify({ type: 'pending', requests: gateway.pending() }));
|
|
77
|
+
},
|
|
78
|
+
message(ws, raw) {
|
|
79
|
+
const rawStr = typeof raw === 'string' ? raw : raw.toString();
|
|
80
|
+
// Payload size guard — reject oversized messages before parsing.
|
|
81
|
+
if (rawStr.length > MAX_PAYLOAD_BYTES) {
|
|
82
|
+
ws.send(JSON.stringify({ type: 'error', message: 'message too large' }));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
// Per-client rate limit.
|
|
86
|
+
const now = Date.now();
|
|
87
|
+
const rate = clientRates.get(ws) ?? { count: 0, resetAt: now + RATE_LIMIT_WINDOW_MS };
|
|
88
|
+
if (now >= rate.resetAt) {
|
|
89
|
+
rate.count = 0;
|
|
90
|
+
rate.resetAt = now + RATE_LIMIT_WINDOW_MS;
|
|
91
|
+
}
|
|
92
|
+
rate.count++;
|
|
93
|
+
clientRates.set(ws, rate);
|
|
94
|
+
if (rate.count > RATE_LIMIT_MAX) {
|
|
95
|
+
ws.send(JSON.stringify({ type: 'error', message: 'rate limit exceeded' }));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
let msg;
|
|
99
|
+
try {
|
|
100
|
+
msg = JSON.parse(rawStr);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
ws.send(JSON.stringify({ type: 'error', message: 'invalid JSON' }));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (!isResolveMessage(msg)) {
|
|
107
|
+
ws.send(JSON.stringify({ type: 'error', message: 'unknown message type' }));
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const ok = gateway.resolve(msg.approvalId, {
|
|
111
|
+
outcome: msg.outcome,
|
|
112
|
+
actor: msg.actor ?? 'websocket',
|
|
113
|
+
reason: msg.reason,
|
|
114
|
+
});
|
|
115
|
+
if (!ok) {
|
|
116
|
+
ws.send(JSON.stringify({
|
|
117
|
+
type: 'error',
|
|
118
|
+
message: `approval ${msg.approvalId} not found or already resolved`,
|
|
119
|
+
}));
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
close(ws) {
|
|
123
|
+
clients.delete(ws);
|
|
124
|
+
clientRates.delete(ws);
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
return {
|
|
129
|
+
port: server.port,
|
|
130
|
+
detach() {
|
|
131
|
+
unsubscribe();
|
|
132
|
+
clients.clear();
|
|
133
|
+
server.stop(true);
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function isResolveMessage(v) {
|
|
138
|
+
if (typeof v !== 'object' || v === null)
|
|
139
|
+
return false;
|
|
140
|
+
const m = v;
|
|
141
|
+
return (m['type'] === 'resolve' &&
|
|
142
|
+
typeof m['approvalId'] === 'string' &&
|
|
143
|
+
(m['outcome'] === 'approved' || m['outcome'] === 'rejected'));
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=websocket-approval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket-approval.js","sourceRoot":"","sources":["../../src/adapters/websocket-approval.ts"],"names":[],"mappings":"AA+CA,iFAAiF;AACjF,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAChC,gEAAgE;AAChE,MAAM,cAAc,GAAG,EAAE,CAAC;AAC1B,MAAM,oBAAoB,GAAG,KAAK,CAAC;AAEnC,MAAM,UAAU,8BAA8B,CAC5C,OAAwB,EACxB,UAA2C,EAAE;IAE7C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC;IAClC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,WAAW,CAAC;IACjD,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC;IAC5C,MAAM,kBAAkB,GAAG,OAAO,CAAC,cAAc,KAAK,IAAI,CAAC;IAE3D,SAAS,gBAAgB,CAAC,MAAc;QACtC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;YACpD,OAAO,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,OAAO,CAAC;QAC5F,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAGD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAM,CAAC;IAC9B,MAAM,WAAW,GAAG,IAAI,GAAG,EAA0C,CAAC;IAEtE,SAAS,SAAS,CAAC,GAAY;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACjC,KAAK,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;YACzB,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,KAAoB,EAAE,EAAE;QAC7D,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,WAAW;gBACd,SAAS,CAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;gBAClE,MAAM;YACR,KAAK,UAAU;gBACb,SAAS,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAC3F,MAAM;YACR,KAAK,SAAS;gBACZ,SAAS,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;gBAChE,MAAM;YACR,KAAK,SAAS;gBACZ,SAAS,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;gBACtF,MAAM;QACV,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC;QACvB,IAAI;QACJ,QAAQ;QAER,KAAK,CAAC,GAAG,EAAE,MAAM;YACf,IAAI,kBAAkB,EAAE,CAAC;gBACvB,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACzC,IAAI,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC;oBACxC,OAAO,IAAI,QAAQ,CAAC,kBAAkB,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;gBAC3D,CAAC;YACH,CAAC;YACD,qEAAqE;YACrE,mEAAmE;YACnE,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;gBAC3B,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;gBAC3D,IAAI,UAAU,GAAG,EAAE,CAAC;gBACpB,IAAI,CAAC;oBACH,UAAU,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gBAChE,CAAC;gBAAC,MAAM,CAAC,CAAC,4CAA4C,CAAC,CAAC;gBACxD,MAAM,SAAS,GAAG,WAAW,IAAI,UAAU,CAAC;gBAC5C,IAAI,SAAS,KAAK,aAAa,EAAE,CAAC;oBAChC,OAAO,IAAI,QAAQ,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;gBACvD,CAAC;YACH,CAAC;YACD,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;gBAAE,OAAO,SAAS,CAAC;YAC1C,OAAO,IAAI,QAAQ,CAAC,uCAAuC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAChF,CAAC;QAED,SAAS,EAAE;YACT,IAAI,CAAC,EAAE;gBACL,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAChB,4DAA4D;gBAC5D,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;YAC5E,CAAC;YAED,OAAO,CAAC,EAAE,EAAE,GAAG;gBACb,MAAM,MAAM,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;gBAE9D,iEAAiE;gBACjE,IAAI,MAAM,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;oBACtC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAAC;oBACzE,OAAO;gBACT,CAAC;gBAED,yBAAyB;gBACzB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBACvB,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,GAAG,oBAAoB,EAAE,CAAC;gBACtF,IAAI,GAAG,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;oBACxB,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;oBACf,IAAI,CAAC,OAAO,GAAG,GAAG,GAAG,oBAAoB,CAAC;gBAC5C,CAAC;gBACD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACb,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;gBAC1B,IAAI,IAAI,CAAC,KAAK,GAAG,cAAc,EAAE,CAAC;oBAChC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,CAAC,CAAC,CAAC;oBAC3E,OAAO;gBACT,CAAC;gBAED,IAAI,GAAY,CAAC;gBACjB,IAAI,CAAC;oBACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBAC3B,CAAC;gBAAC,MAAM,CAAC;oBACP,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;oBACpE,OAAO;gBACT,CAAC;gBAED,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC3B,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC,CAAC,CAAC;oBAC5E,OAAO;gBACT,CAAC;gBAED,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE;oBACzC,OAAO,EAAE,GAAG,CAAC,OAAO;oBACpB,KAAK,EAAE,GAAG,CAAC,KAAK,IAAI,WAAW;oBAC/B,MAAM,EAAE,GAAG,CAAC,MAAM;iBACnB,CAAC,CAAC;gBAEH,IAAI,CAAC,EAAE,EAAE,CAAC;oBACR,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;wBACrB,IAAI,EAAE,OAAO;wBACb,OAAO,EAAE,YAAY,GAAG,CAAC,UAAU,gCAAgC;qBACpE,CAAC,CAAC,CAAC;gBACN,CAAC;YACH,CAAC;YAED,KAAK,CAAC,EAAE;gBACN,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACnB,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACzB,CAAC;SACF;KACF,CAAC,CAAC;IAEH,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,IAAK;QAClB,MAAM;YACJ,WAAW,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;KACF,CAAC;AACJ,CAAC;AAYD,SAAS,gBAAgB,CAAC,CAAU;IAClC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,OAAO,CACL,CAAC,CAAC,MAAM,CAAC,KAAK,SAAS;QACvB,OAAO,CAAC,CAAC,YAAY,CAAC,KAAK,QAAQ;QACnC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,UAAU,IAAI,CAAC,CAAC,SAAS,CAAC,KAAK,UAAU,CAAC,CAC7D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ApprovalRequest, ApprovalDecision, ApprovalListener, ApprovalGateway } from './types';
|
|
2
|
+
export type { ApprovalRequest, ApprovalDecision, ApprovalOutcome, ApprovalEvent, ApprovalListener, ApprovalGateway, } from './types';
|
|
3
|
+
export declare class InMemoryApprovalGateway implements ApprovalGateway {
|
|
4
|
+
private readonly pendingMap;
|
|
5
|
+
private readonly listeners;
|
|
6
|
+
request(req: Omit<ApprovalRequest, 'id' | 'createdAt'>): Promise<ApprovalDecision>;
|
|
7
|
+
resolve(approvalId: string, decision: Omit<ApprovalDecision, 'approvalId' | 'decidedAt'>): boolean;
|
|
8
|
+
pending(): readonly ApprovalRequest[];
|
|
9
|
+
subscribe(listener: ApprovalListener): () => void;
|
|
10
|
+
abortAll(reason: string): void;
|
|
11
|
+
private emit;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=approval.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval.d.ts","sourceRoot":"","sources":["../src/approval.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,eAAe,EAAE,gBAAgB,EAAiB,gBAAgB,EAAE,eAAe,EACpF,MAAM,SAAS,CAAC;AAGjB,YAAY,EACV,eAAe,EAAE,gBAAgB,EAAE,eAAe,EAAE,aAAa,EACjE,gBAAgB,EAAE,eAAe,GAClC,MAAM,SAAS,CAAC;AAUjB,qBAAa,uBAAwB,YAAW,eAAe;IAC7D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmC;IAC9D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+B;IAEzD,OAAO,CACL,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,WAAW,CAAC,GAC7C,OAAO,CAAC,gBAAgB,CAAC;IAkC5B,OAAO,CACL,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,IAAI,CAAC,gBAAgB,EAAE,YAAY,GAAG,WAAW,CAAC,GAC3D,OAAO;IAkBV,OAAO,IAAI,SAAS,eAAe,EAAE;IAIrC,SAAS,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,IAAI;IAOjD,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAe9B,OAAO,CAAC,IAAI;CASb"}
|
package/dist/approval.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { randomUUID } from 'crypto';
|
|
2
|
+
import { nowISO } from './utils';
|
|
3
|
+
export class InMemoryApprovalGateway {
|
|
4
|
+
pendingMap = new Map();
|
|
5
|
+
listeners = new Set();
|
|
6
|
+
request(req) {
|
|
7
|
+
const full = {
|
|
8
|
+
id: randomUUID(),
|
|
9
|
+
createdAt: nowISO(),
|
|
10
|
+
taskId: req.taskId,
|
|
11
|
+
trackId: req.trackId,
|
|
12
|
+
message: req.message,
|
|
13
|
+
timeoutMs: req.timeoutMs,
|
|
14
|
+
metadata: req.metadata,
|
|
15
|
+
};
|
|
16
|
+
return new Promise((resolvePromise) => {
|
|
17
|
+
let timer = null;
|
|
18
|
+
if (full.timeoutMs > 0) {
|
|
19
|
+
timer = setTimeout(() => {
|
|
20
|
+
const entry = this.pendingMap.get(full.id);
|
|
21
|
+
if (!entry)
|
|
22
|
+
return;
|
|
23
|
+
this.pendingMap.delete(full.id);
|
|
24
|
+
const decision = {
|
|
25
|
+
approvalId: full.id,
|
|
26
|
+
outcome: 'timeout',
|
|
27
|
+
reason: `Approval timed out after ${full.timeoutMs}ms`,
|
|
28
|
+
decidedAt: nowISO(),
|
|
29
|
+
};
|
|
30
|
+
this.emit({ type: 'expired', request: full });
|
|
31
|
+
resolvePromise(decision);
|
|
32
|
+
}, full.timeoutMs);
|
|
33
|
+
}
|
|
34
|
+
this.pendingMap.set(full.id, { request: full, settle: resolvePromise, timer });
|
|
35
|
+
this.emit({ type: 'requested', request: full });
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
resolve(approvalId, decision) {
|
|
39
|
+
const entry = this.pendingMap.get(approvalId);
|
|
40
|
+
if (!entry)
|
|
41
|
+
return false;
|
|
42
|
+
this.pendingMap.delete(approvalId);
|
|
43
|
+
if (entry.timer)
|
|
44
|
+
clearTimeout(entry.timer);
|
|
45
|
+
const full = {
|
|
46
|
+
approvalId,
|
|
47
|
+
outcome: decision.outcome,
|
|
48
|
+
actor: decision.actor,
|
|
49
|
+
reason: decision.reason,
|
|
50
|
+
decidedAt: nowISO(),
|
|
51
|
+
};
|
|
52
|
+
this.emit({ type: 'resolved', request: entry.request, decision: full });
|
|
53
|
+
entry.settle(full);
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
pending() {
|
|
57
|
+
return Array.from(this.pendingMap.values()).map((e) => e.request);
|
|
58
|
+
}
|
|
59
|
+
subscribe(listener) {
|
|
60
|
+
this.listeners.add(listener);
|
|
61
|
+
return () => {
|
|
62
|
+
this.listeners.delete(listener);
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
abortAll(reason) {
|
|
66
|
+
const entries = Array.from(this.pendingMap.entries());
|
|
67
|
+
this.pendingMap.clear();
|
|
68
|
+
for (const [id, entry] of entries) {
|
|
69
|
+
if (entry.timer)
|
|
70
|
+
clearTimeout(entry.timer);
|
|
71
|
+
this.emit({ type: 'aborted', request: entry.request, reason });
|
|
72
|
+
entry.settle({
|
|
73
|
+
approvalId: id,
|
|
74
|
+
outcome: 'aborted',
|
|
75
|
+
reason,
|
|
76
|
+
decidedAt: nowISO(),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
emit(event) {
|
|
81
|
+
for (const listener of this.listeners) {
|
|
82
|
+
try {
|
|
83
|
+
listener(event);
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
console.error('[approval gateway] listener error:', err);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=approval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval.js","sourceRoot":"","sources":["../src/approval.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAqBA,wBAAgB,iBAAiB,IAAI,IAAI,CAexC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { registerPlugin } from './registry';
|
|
2
|
+
// Built-in Drivers
|
|
3
|
+
// Only claude-code is built in. Other drivers (codex, opencode) ship as
|
|
4
|
+
// workspace plugins under plugins/ and must be declared in pipeline.yaml
|
|
5
|
+
// via the `plugins` field, e.g.:
|
|
6
|
+
// plugins: ["@tagma/driver-codex", "@tagma/driver-opencode"]
|
|
7
|
+
import { ClaudeCodeDriver } from './drivers/claude-code';
|
|
8
|
+
// Built-in Triggers
|
|
9
|
+
import { FileTrigger } from './triggers/file';
|
|
10
|
+
import { ManualTrigger } from './triggers/manual';
|
|
11
|
+
// Built-in Completions
|
|
12
|
+
import { ExitCodeCompletion } from './completions/exit-code';
|
|
13
|
+
import { FileExistsCompletion } from './completions/file-exists';
|
|
14
|
+
import { OutputCheckCompletion } from './completions/output-check';
|
|
15
|
+
// Built-in Middleware
|
|
16
|
+
import { StaticContextMiddleware } from './middlewares/static-context';
|
|
17
|
+
export function bootstrapBuiltins() {
|
|
18
|
+
// Drivers
|
|
19
|
+
registerPlugin('drivers', 'claude-code', ClaudeCodeDriver);
|
|
20
|
+
// Triggers
|
|
21
|
+
registerPlugin('triggers', 'file', FileTrigger);
|
|
22
|
+
registerPlugin('triggers', 'manual', ManualTrigger);
|
|
23
|
+
// Completions
|
|
24
|
+
registerPlugin('completions', 'exit_code', ExitCodeCompletion);
|
|
25
|
+
registerPlugin('completions', 'file_exists', FileExistsCompletion);
|
|
26
|
+
registerPlugin('completions', 'output_check', OutputCheckCompletion);
|
|
27
|
+
// Middlewares
|
|
28
|
+
registerPlugin('middlewares', 'static_context', StaticContextMiddleware);
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,mBAAmB;AACnB,wEAAwE;AACxE,yEAAyE;AACzE,iCAAiC;AACjC,+DAA+D;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,oBAAoB;AACpB,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,uBAAuB;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,sBAAsB;AACtB,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,MAAM,UAAU,iBAAiB;IAC/B,UAAU;IACV,cAAc,CAAC,SAAS,EAAE,aAAa,EAAE,gBAAgB,CAAC,CAAC;IAE3D,WAAW;IACX,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IAChD,cAAc,CAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;IAEpD,cAAc;IACd,cAAc,CAAC,aAAa,EAAE,WAAW,EAAE,kBAAkB,CAAC,CAAC;IAC/D,cAAc,CAAC,aAAa,EAAE,aAAa,EAAE,oBAAoB,CAAC,CAAC;IACnE,cAAc,CAAC,aAAa,EAAE,cAAc,EAAE,qBAAqB,CAAC,CAAC;IAErE,cAAc;IACd,cAAc,CAAC,aAAa,EAAE,gBAAgB,EAAE,uBAAuB,CAAC,CAAC;AAC3E,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exit-code.d.ts","sourceRoot":"","sources":["../../src/completions/exit-code.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAiC,MAAM,UAAU,CAAC;AAEhF,eAAO,MAAM,kBAAkB,EAAE,gBA2BhC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const ExitCodeCompletion = {
|
|
2
|
+
name: 'exit_code',
|
|
3
|
+
schema: {
|
|
4
|
+
description: 'Mark the task successful when the exit code matches.',
|
|
5
|
+
fields: {
|
|
6
|
+
expect: {
|
|
7
|
+
type: 'number-or-list',
|
|
8
|
+
default: 0,
|
|
9
|
+
description: 'Expected exit code, or list of acceptable codes (e.g. 0 or [0, 2]).',
|
|
10
|
+
placeholder: '0',
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
async check(config, result, _ctx) {
|
|
15
|
+
const expected = config.expect ?? 0;
|
|
16
|
+
if (typeof expected === 'number') {
|
|
17
|
+
return result.exitCode === expected;
|
|
18
|
+
}
|
|
19
|
+
if (Array.isArray(expected) && expected.every((v) => typeof v === 'number')) {
|
|
20
|
+
return expected.includes(result.exitCode);
|
|
21
|
+
}
|
|
22
|
+
throw new Error(`exit_code completion: "expect" must be a number or number[], got ${typeof expected}`);
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=exit-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exit-code.js","sourceRoot":"","sources":["../../src/completions/exit-code.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,kBAAkB,GAAqB;IAClD,IAAI,EAAE,WAAW;IACjB,MAAM,EAAE;QACN,WAAW,EAAE,sDAAsD;QACnE,MAAM,EAAE;YACN,MAAM,EAAE;gBACN,IAAI,EAAE,gBAAgB;gBACtB,OAAO,EAAE,CAAC;gBACV,WAAW,EAAE,qEAAqE;gBAClF,WAAW,EAAE,GAAG;aACjB;SACF;KACF;IAED,KAAK,CAAC,KAAK,CAAC,MAA+B,EAAE,MAAkB,EAAE,IAAuB;QACtF,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;QAEpC,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACjC,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC;QACtC,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;YAC5E,OAAO,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC5C,CAAC;QACD,MAAM,IAAI,KAAK,CACb,oEAAoE,OAAO,QAAQ,EAAE,CACtF,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-exists.d.ts","sourceRoot":"","sources":["../../src/completions/file-exists.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAiC,MAAM,UAAU,CAAC;AAKhF,eAAO,MAAM,oBAAoB,EAAE,gBAqDlC,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { stat } from 'node:fs/promises';
|
|
2
|
+
import { validatePath } from '../utils';
|
|
3
|
+
export const FileExistsCompletion = {
|
|
4
|
+
name: 'file_exists',
|
|
5
|
+
schema: {
|
|
6
|
+
description: 'Mark the task successful when a target file or directory exists.',
|
|
7
|
+
fields: {
|
|
8
|
+
path: {
|
|
9
|
+
type: 'path',
|
|
10
|
+
required: true,
|
|
11
|
+
description: 'Path to check (relative to workDir or absolute).',
|
|
12
|
+
},
|
|
13
|
+
kind: {
|
|
14
|
+
type: 'enum',
|
|
15
|
+
enum: ['file', 'dir', 'any'],
|
|
16
|
+
default: 'any',
|
|
17
|
+
description: 'Restrict to a file, directory, or accept either.',
|
|
18
|
+
},
|
|
19
|
+
min_size: {
|
|
20
|
+
type: 'number',
|
|
21
|
+
min: 0,
|
|
22
|
+
description: 'Optional minimum size in bytes (files only).',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
async check(config, _result, ctx) {
|
|
27
|
+
const filePath = config.path;
|
|
28
|
+
if (!filePath)
|
|
29
|
+
throw new Error('file_exists completion: "path" is required');
|
|
30
|
+
const safePath = validatePath(filePath, ctx.workDir);
|
|
31
|
+
const kind = config.kind ?? 'any';
|
|
32
|
+
if (kind !== 'file' && kind !== 'dir' && kind !== 'any') {
|
|
33
|
+
throw new Error(`file_exists completion: "kind" must be "file" | "dir" | "any", got "${kind}"`);
|
|
34
|
+
}
|
|
35
|
+
const minSize = config.min_size;
|
|
36
|
+
if (minSize != null && (typeof minSize !== 'number' || minSize < 0)) {
|
|
37
|
+
throw new Error(`file_exists completion: "min_size" must be a non-negative number`);
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const st = await stat(safePath);
|
|
41
|
+
if (kind === 'file' && !st.isFile())
|
|
42
|
+
return false;
|
|
43
|
+
if (kind === 'dir' && !st.isDirectory())
|
|
44
|
+
return false;
|
|
45
|
+
if (typeof minSize === 'number' && st.isFile() && st.size < minSize)
|
|
46
|
+
return false;
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
const code = err.code;
|
|
51
|
+
if (code === 'ENOENT' || code === 'ENOTDIR')
|
|
52
|
+
return false;
|
|
53
|
+
// Permission / IO errors should surface, not silently mean "missing"
|
|
54
|
+
throw err;
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=file-exists.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-exists.js","sourceRoot":"","sources":["../../src/completions/file-exists.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAIxC,MAAM,CAAC,MAAM,oBAAoB,GAAqB;IACpD,IAAI,EAAE,aAAa;IACnB,MAAM,EAAE;QACN,WAAW,EAAE,kEAAkE;QAC/E,MAAM,EAAE;YACN,IAAI,EAAE;gBACJ,IAAI,EAAE,MAAM;gBACZ,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,kDAAkD;aAChE;YACD,IAAI,EAAE;gBACJ,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC;gBAC5B,OAAO,EAAE,KAAK;gBACd,WAAW,EAAE,kDAAkD;aAChE;YACD,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,GAAG,EAAE,CAAC;gBACN,WAAW,EAAE,8CAA8C;aAC5D;SACF;KACF;IAED,KAAK,CAAC,KAAK,CAAC,MAA+B,EAAE,OAAmB,EAAE,GAAsB;QACtF,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAc,CAAC;QACvC,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAE7E,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAErD,MAAM,IAAI,GAAI,MAAM,CAAC,IAAyB,IAAI,KAAK,CAAC;QACxD,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;YACxD,MAAM,IAAI,KAAK,CAAC,uEAAuE,IAAI,GAAG,CAAC,CAAC;QAClG,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC;QAChC,IAAI,OAAO,IAAI,IAAI,IAAI,CAAC,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC;YACpE,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;QACtF,CAAC;QAED,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;YAChC,IAAI,IAAI,KAAK,MAAM,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE;gBAAE,OAAO,KAAK,CAAC;YAClD,IAAI,IAAI,KAAK,KAAK,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE;gBAAE,OAAO,KAAK,CAAC;YACtD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI,GAAG,OAAO;gBAAE,OAAO,KAAK,CAAC;YAClF,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;YACjD,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,SAAS;gBAAE,OAAO,KAAK,CAAC;YAC1D,qEAAqE;YACrE,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output-check.d.ts","sourceRoot":"","sources":["../../src/completions/output-check.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAiC,MAAM,UAAU,CAAC;AAKhF,eAAO,MAAM,qBAAqB,EAAE,gBAgFnC,CAAC"}
|