@tagma/sdk 0.7.4 → 0.7.5

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.
Files changed (190) hide show
  1. package/README.md +60 -53
  2. package/dist/completions/file-exists.js +1 -1
  3. package/dist/completions/file-exists.js.map +1 -1
  4. package/dist/completions/output-check.d.ts.map +1 -1
  5. package/dist/completions/output-check.js +17 -4
  6. package/dist/completions/output-check.js.map +1 -1
  7. package/dist/config.d.ts +4 -4
  8. package/dist/config.d.ts.map +1 -1
  9. package/dist/config.js +2 -2
  10. package/dist/config.js.map +1 -1
  11. package/dist/dataflow.d.ts +3 -0
  12. package/dist/dataflow.d.ts.map +1 -0
  13. package/dist/dataflow.js +2 -0
  14. package/dist/dataflow.js.map +1 -0
  15. package/dist/drivers/opencode.d.ts.map +1 -1
  16. package/dist/drivers/opencode.js +23 -71
  17. package/dist/drivers/opencode.js.map +1 -1
  18. package/dist/middlewares/static-context.d.ts.map +1 -1
  19. package/dist/middlewares/static-context.js +1 -2
  20. package/dist/middlewares/static-context.js.map +1 -1
  21. package/dist/pipeline-runner.d.ts.map +1 -1
  22. package/dist/pipeline-runner.js +2 -2
  23. package/dist/pipeline-runner.js.map +1 -1
  24. package/dist/schema.d.ts.map +1 -1
  25. package/dist/schema.js +3 -4
  26. package/dist/schema.js.map +1 -1
  27. package/dist/triggers/file.d.ts.map +1 -1
  28. package/dist/triggers/file.js +1 -2
  29. package/dist/triggers/file.js.map +1 -1
  30. package/dist/triggers/manual.d.ts.map +1 -1
  31. package/dist/triggers/manual.js +1 -2
  32. package/dist/triggers/manual.js.map +1 -1
  33. package/dist/types.d.ts +1 -2
  34. package/dist/types.d.ts.map +1 -1
  35. package/dist/types.js +1 -12
  36. package/dist/types.js.map +1 -1
  37. package/dist/utils-api.d.ts +1 -1
  38. package/dist/utils-api.d.ts.map +1 -1
  39. package/dist/utils-api.js +1 -1
  40. package/dist/utils-api.js.map +1 -1
  41. package/dist/validate-raw.d.ts.map +1 -1
  42. package/dist/validate-raw.js +5 -12
  43. package/dist/validate-raw.js.map +1 -1
  44. package/package.json +11 -24
  45. package/dist/adapters/stdin-approval.d.ts +0 -2
  46. package/dist/adapters/stdin-approval.d.ts.map +0 -1
  47. package/dist/adapters/stdin-approval.js +0 -2
  48. package/dist/adapters/stdin-approval.js.map +0 -1
  49. package/dist/adapters/websocket-approval.d.ts +0 -2
  50. package/dist/adapters/websocket-approval.d.ts.map +0 -1
  51. package/dist/adapters/websocket-approval.js +0 -2
  52. package/dist/adapters/websocket-approval.js.map +0 -1
  53. package/dist/core/dataflow.d.ts +0 -23
  54. package/dist/core/dataflow.d.ts.map +0 -1
  55. package/dist/core/dataflow.js +0 -99
  56. package/dist/core/dataflow.js.map +0 -1
  57. package/dist/core/log-prune.d.ts +0 -16
  58. package/dist/core/log-prune.d.ts.map +0 -1
  59. package/dist/core/log-prune.js +0 -34
  60. package/dist/core/log-prune.js.map +0 -1
  61. package/dist/core/preflight.d.ts +0 -13
  62. package/dist/core/preflight.d.ts.map +0 -1
  63. package/dist/core/preflight.js +0 -61
  64. package/dist/core/preflight.js.map +0 -1
  65. package/dist/core/run-context.d.ts +0 -55
  66. package/dist/core/run-context.d.ts.map +0 -1
  67. package/dist/core/run-context.js +0 -158
  68. package/dist/core/run-context.js.map +0 -1
  69. package/dist/core/run-state.d.ts +0 -25
  70. package/dist/core/run-state.d.ts.map +0 -1
  71. package/dist/core/run-state.js +0 -93
  72. package/dist/core/run-state.js.map +0 -1
  73. package/dist/core/scheduler.d.ts +0 -13
  74. package/dist/core/scheduler.d.ts.map +0 -1
  75. package/dist/core/scheduler.js +0 -35
  76. package/dist/core/scheduler.js.map +0 -1
  77. package/dist/core/task-executor.d.ts +0 -13
  78. package/dist/core/task-executor.d.ts.map +0 -1
  79. package/dist/core/task-executor.js +0 -610
  80. package/dist/core/task-executor.js.map +0 -1
  81. package/dist/core/trigger-errors.d.ts +0 -9
  82. package/dist/core/trigger-errors.d.ts.map +0 -1
  83. package/dist/core/trigger-errors.js +0 -15
  84. package/dist/core/trigger-errors.js.map +0 -1
  85. package/dist/dag.d.ts +0 -45
  86. package/dist/dag.d.ts.map +0 -1
  87. package/dist/dag.js +0 -177
  88. package/dist/dag.js.map +0 -1
  89. package/dist/hooks.d.ts +0 -73
  90. package/dist/hooks.d.ts.map +0 -1
  91. package/dist/hooks.js +0 -106
  92. package/dist/hooks.js.map +0 -1
  93. package/dist/pipeline-definition.d.ts +0 -3
  94. package/dist/pipeline-definition.d.ts.map +0 -1
  95. package/dist/pipeline-definition.js +0 -4
  96. package/dist/pipeline-definition.js.map +0 -1
  97. package/dist/ports.d.ts +0 -196
  98. package/dist/ports.d.ts.map +0 -1
  99. package/dist/ports.js +0 -688
  100. package/dist/ports.js.map +0 -1
  101. package/dist/prompt-doc.d.ts +0 -70
  102. package/dist/prompt-doc.d.ts.map +0 -1
  103. package/dist/prompt-doc.js +0 -154
  104. package/dist/prompt-doc.js.map +0 -1
  105. package/dist/registry.d.ts +0 -3
  106. package/dist/registry.d.ts.map +0 -1
  107. package/dist/registry.js +0 -2
  108. package/dist/registry.js.map +0 -1
  109. package/dist/task-ref.d.ts +0 -55
  110. package/dist/task-ref.d.ts.map +0 -1
  111. package/dist/task-ref.js +0 -103
  112. package/dist/task-ref.js.map +0 -1
  113. package/dist/utils.d.ts +0 -13
  114. package/dist/utils.d.ts.map +0 -1
  115. package/dist/utils.js +0 -177
  116. package/dist/utils.js.map +0 -1
  117. package/src/adapters/stdin-approval.ts +0 -1
  118. package/src/adapters/websocket-approval.ts +0 -1
  119. package/src/approval.ts +0 -9
  120. package/src/bootstrap.ts +0 -55
  121. package/src/completions/exit-code.ts +0 -34
  122. package/src/completions/file-exists.ts +0 -66
  123. package/src/completions/output-check.test.ts +0 -50
  124. package/src/completions/output-check.ts +0 -92
  125. package/src/config-ops.test.ts +0 -70
  126. package/src/config-ops.ts +0 -328
  127. package/src/config.ts +0 -26
  128. package/src/core/dataflow.test.ts +0 -166
  129. package/src/core/dataflow.ts +0 -161
  130. package/src/core/log-prune.test.ts +0 -58
  131. package/src/core/log-prune.ts +0 -43
  132. package/src/core/preflight.test.ts +0 -49
  133. package/src/core/preflight.ts +0 -89
  134. package/src/core/run-context.test.ts +0 -291
  135. package/src/core/run-context.ts +0 -211
  136. package/src/core/run-state.test.ts +0 -98
  137. package/src/core/run-state.ts +0 -122
  138. package/src/core/scheduler.test.ts +0 -83
  139. package/src/core/scheduler.ts +0 -42
  140. package/src/core/task-executor.ts +0 -752
  141. package/src/core/trigger-errors.ts +0 -15
  142. package/src/dag.test.ts +0 -56
  143. package/src/dag.ts +0 -245
  144. package/src/drivers/opencode.ts +0 -410
  145. package/src/engine-ports-mixed.test.ts +0 -182
  146. package/src/engine-ports.test.ts +0 -210
  147. package/src/engine-task-type.test.ts +0 -56
  148. package/src/engine.ts +0 -32
  149. package/src/hooks.ts +0 -193
  150. package/src/index.ts +0 -31
  151. package/src/logger.ts +0 -2
  152. package/src/middlewares/static-context.ts +0 -49
  153. package/src/package-split.test.ts +0 -15
  154. package/src/pipeline-definition.ts +0 -5
  155. package/src/pipeline-runner.test.ts +0 -144
  156. package/src/pipeline-runner.ts +0 -194
  157. package/src/plugin-registry.test.ts +0 -448
  158. package/src/plugins.ts +0 -21
  159. package/src/ports.test.ts +0 -678
  160. package/src/ports.ts +0 -925
  161. package/src/prompt-doc.test.ts +0 -174
  162. package/src/prompt-doc.ts +0 -169
  163. package/src/registry.ts +0 -7
  164. package/src/runner.test.ts +0 -142
  165. package/src/runner.ts +0 -1
  166. package/src/runtime/adapters/stdin-approval.ts +0 -1
  167. package/src/runtime/adapters/websocket-approval.ts +0 -1
  168. package/src/runtime/bun-process-runner.ts +0 -1
  169. package/src/runtime-adapters.test.ts +0 -10
  170. package/src/runtime.ts +0 -12
  171. package/src/schema-ports.test.ts +0 -172
  172. package/src/schema.test.ts +0 -213
  173. package/src/schema.ts +0 -379
  174. package/src/tagma.test.ts +0 -317
  175. package/src/tagma.ts +0 -67
  176. package/src/task-ref.test.ts +0 -401
  177. package/src/task-ref.ts +0 -121
  178. package/src/triggers/file.test.ts +0 -79
  179. package/src/triggers/file.ts +0 -131
  180. package/src/triggers/manual.ts +0 -86
  181. package/src/types.ts +0 -18
  182. package/src/utils-api.ts +0 -8
  183. package/src/utils.test.ts +0 -28
  184. package/src/utils.ts +0 -203
  185. package/src/validate-raw-plugin-types.test.ts +0 -60
  186. package/src/validate-raw-ports.test.ts +0 -136
  187. package/src/validate-raw.ts +0 -852
  188. package/src/yaml-compiler.test.ts +0 -108
  189. package/src/yaml-compiler.ts +0 -110
  190. package/src/yaml.ts +0 -11
package/dist/utils.js DELETED
@@ -1,177 +0,0 @@
1
- import { isAbsolute, resolve, relative, parse as parsePath, sep } from 'path';
2
- import { realpathSync, lstatSync, existsSync } from 'fs';
3
- import { randomBytes } from 'crypto';
4
- const DURATION_RE = /^(\d*\.?\d+)\s*(s|m|h|d)$/;
5
- export function parseDuration(input) {
6
- const match = DURATION_RE.exec(input.trim());
7
- if (!match) {
8
- throw new Error(`Invalid duration format: "${input}". Expected format: <number>(s|m|h|d)`);
9
- }
10
- const value = parseFloat(match[1]);
11
- const unit = match[2];
12
- switch (unit) {
13
- case 's':
14
- return value * 1000;
15
- case 'm':
16
- return value * 60_000;
17
- case 'h':
18
- return value * 3_600_000;
19
- case 'd':
20
- return value * 86_400_000;
21
- default:
22
- throw new Error(`Unknown duration unit: "${unit}"`);
23
- }
24
- }
25
- export function validatePath(filePath, projectRoot) {
26
- const resolved = resolve(projectRoot, filePath);
27
- // D2: Cross-drive check (Windows) — path.relative('C:\\root', 'D:\\x') returns
28
- // 'D:\\x' which does NOT start with '..', so a pure relative check would wrongly
29
- // allow cross-drive paths. Reject them explicitly before any further comparison.
30
- if (parsePath(projectRoot).root !== parsePath(resolved).root) {
31
- throw new Error(`Security: path "${filePath}" is on a different drive than the project root "${projectRoot}".`);
32
- }
33
- const rel = relative(projectRoot, resolved);
34
- if (rel === '..' || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {
35
- throw new Error(`Security: path "${filePath}" escapes project root. ` +
36
- `All file references must be within "${projectRoot}".`);
37
- }
38
- // D1: Resolve symlinks and re-validate so a symlink whose string path is
39
- // inside the project root but whose target lies outside is rejected.
40
- // Only resolve if the path exists on disk; at parse time the file may not
41
- // yet exist (e.g. a future output path), so we skip realpath for absent paths.
42
- if (existsSync(resolved)) {
43
- // Reject the entry outright if it is itself a symlink — callers that want
44
- // to allow symlinks within the tree can pass pre-resolved paths.
45
- try {
46
- const stat = lstatSync(resolved);
47
- if (stat.isSymbolicLink()) {
48
- throw new Error(`Security: path "${filePath}" is a symbolic link. Symbolic links are not allowed within the project root.`);
49
- }
50
- }
51
- catch (err) {
52
- if (err.code !== 'ENOENT')
53
- throw err;
54
- }
55
- // Also verify the real (fully resolved) path stays within the project root.
56
- let real;
57
- try {
58
- real = realpathSync.native(resolved);
59
- }
60
- catch {
61
- real = resolved; // path vanished between existsSync and realpathSync — skip
62
- }
63
- const realRoot = (() => {
64
- try {
65
- return realpathSync.native(projectRoot);
66
- }
67
- catch {
68
- return projectRoot;
69
- }
70
- })();
71
- if (parsePath(realRoot).root !== parsePath(real).root) {
72
- throw new Error(`Security: resolved path "${real}" is on a different drive than the project root "${realRoot}".`);
73
- }
74
- const realRel = relative(realRoot, real);
75
- if (realRel === '..' || realRel.startsWith(`..${sep}`) || isAbsolute(realRel)) {
76
- throw new Error(`Security: path "${filePath}" resolves via symlink to "${real}" which escapes project root "${realRoot}".`);
77
- }
78
- }
79
- return resolved;
80
- }
81
- export function generateRunId() {
82
- const ts = Date.now().toString(36);
83
- const rand = randomBytes(6).toString('hex');
84
- return `run_${ts}_${rand}`;
85
- }
86
- export function truncateForName(text, maxLen = 40) {
87
- const first = text.split('\n')[0].trim();
88
- // Guard: if the first line is empty (e.g. prompt is all whitespace/newlines),
89
- // fall back to the raw text trimmed rather than silently producing an empty name.
90
- if (!first)
91
- return text.trim().slice(0, maxLen) || '...';
92
- return first.length > maxLen ? first.slice(0, maxLen) + '...' : first;
93
- }
94
- export function nowISO() {
95
- return new Date().toISOString();
96
- }
97
- // ═══ Platform-aware shell ═══
98
- //
99
- // Resolution order:
100
- // 1. Env override: PIPELINE_SHELL="bash" or PIPELINE_SHELL="cmd" etc.
101
- // 2. Windows: prefer sh (Git Bash / MSYS2) if on PATH, fall back to cmd.exe
102
- // 3. Unix: sh
103
- //
104
- // Resolution is cached once on first call to avoid repeated PATH lookups.
105
- const IS_WINDOWS = process.platform === 'win32';
106
- let resolvedShell = null;
107
- function detectShell() {
108
- // Env override takes precedence
109
- const override = process.env.PIPELINE_SHELL;
110
- if (override) {
111
- const kind = override;
112
- return { kind, path: override };
113
- }
114
- if (!IS_WINDOWS) {
115
- return { kind: 'sh', path: 'sh' };
116
- }
117
- // Windows: probe PATH for sh (bundled with Git for Windows / MSYS2)
118
- const pathEnv = process.env.PATH ?? '';
119
- const pathExt = (process.env.PATHEXT ?? '.EXE;.CMD;.BAT').split(';');
120
- const dirs = pathEnv.split(';').filter(Boolean);
121
- for (const dir of dirs) {
122
- for (const ext of ['', ...pathExt]) {
123
- const candidate = `${dir}\\sh${ext}`;
124
- try {
125
- if (Bun.file(candidate).size > 0) {
126
- return { kind: 'sh', path: candidate };
127
- }
128
- }
129
- catch {
130
- /* ignore */
131
- }
132
- }
133
- }
134
- // Fallback: cmd.exe (always present on Windows)
135
- const systemRoot = process.env.SystemRoot ?? 'C:\\Windows';
136
- return { kind: 'cmd', path: `${systemRoot}\\System32\\cmd.exe` };
137
- }
138
- function getShell() {
139
- if (!resolvedShell)
140
- resolvedShell = detectShell();
141
- return resolvedShell;
142
- }
143
- export function shellArgs(command) {
144
- const sh = getShell();
145
- if (sh.kind === 'cmd') {
146
- return [sh.path, '/c', command];
147
- }
148
- if (sh.kind === 'powershell') {
149
- return [sh.path, '-Command', command];
150
- }
151
- // sh or bash
152
- return [sh.path, '-c', command];
153
- }
154
- /** Quote a single argument for inclusion in a shell command string. */
155
- function quoteArg(arg) {
156
- if (!/[\s"'\\<>|&;`$!^%]/.test(arg))
157
- return arg;
158
- if (IS_WINDOWS) {
159
- // On Windows (cmd.exe), double-quote and escape embedded quotes + backslashes
160
- return '"' + arg.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
161
- }
162
- // On Unix, use single quotes to prevent $variable expansion.
163
- // Escape embedded single quotes via the '\'' idiom.
164
- return "'" + arg.replace(/'/g, "'\\''") + "'";
165
- }
166
- /**
167
- * Convert an args array to shell-wrapped args suitable for Bun.spawn.
168
- * Each arg is quoted as needed, then joined and passed through shellArgs.
169
- */
170
- export function shellArgsFromArray(args) {
171
- return shellArgs(args.map(quoteArg).join(' '));
172
- }
173
- // For tests: allow resetting the cached shell detection
174
- export function _resetShellCache() {
175
- resolvedShell = null;
176
- }
177
- //# sourceMappingURL=utils.js.map
package/dist/utils.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,IAAI,SAAS,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAC9E,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErC,MAAM,WAAW,GAAG,2BAA2B,CAAC;AAEhD,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,6BAA6B,KAAK,uCAAuC,CAAC,CAAC;IAC7F,CAAC;IACD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACtB,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,GAAG;YACN,OAAO,KAAK,GAAG,IAAI,CAAC;QACtB,KAAK,GAAG;YACN,OAAO,KAAK,GAAG,MAAM,CAAC;QACxB,KAAK,GAAG;YACN,OAAO,KAAK,GAAG,SAAS,CAAC;QAC3B,KAAK,GAAG;YACN,OAAO,KAAK,GAAG,UAAU,CAAC;QAC5B;YACE,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,GAAG,CAAC,CAAC;IACxD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,WAAmB;IAChE,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAEhD,+EAA+E;IAC/E,iFAAiF;IACjF,iFAAiF;IACjF,IAAI,SAAS,CAAC,WAAW,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CACb,mBAAmB,QAAQ,oDAAoD,WAAW,IAAI,CAC/F,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC5C,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CACb,mBAAmB,QAAQ,0BAA0B;YACnD,uCAAuC,WAAW,IAAI,CACzD,CAAC;IACJ,CAAC;IAED,yEAAyE;IACzE,qEAAqE;IACrE,0EAA0E;IAC1E,+EAA+E;IAC/E,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,0EAA0E;QAC1E,iEAAiE;QACjE,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;YACjC,IAAI,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CACb,mBAAmB,QAAQ,+EAA+E,CAC3G,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;gBAAE,MAAM,GAAG,CAAC;QAClE,CAAC;QAED,4EAA4E;QAC5E,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACvC,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,GAAG,QAAQ,CAAC,CAAC,2DAA2D;QAC9E,CAAC;QACD,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE;YACrB,IAAI,CAAC;gBACH,OAAO,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAC1C,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,WAAW,CAAC;YACrB,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QACL,IAAI,SAAS,CAAC,QAAQ,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;YACtD,MAAM,IAAI,KAAK,CACb,4BAA4B,IAAI,oDAAoD,QAAQ,IAAI,CACjG,CAAC;QACJ,CAAC;QACD,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACzC,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9E,MAAM,IAAI,KAAK,CACb,mBAAmB,QAAQ,8BAA8B,IAAI,iCAAiC,QAAQ,IAAI,CAC3G,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,OAAO,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,MAAM,GAAG,EAAE;IACvD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;IAC1C,8EAA8E;IAC9E,kFAAkF;IAClF,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,KAAK,CAAC;IACzD,OAAO,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,MAAM;IACpB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED,+BAA+B;AAC/B,EAAE;AACF,oBAAoB;AACpB,wEAAwE;AACxE,8EAA8E;AAC9E,gBAAgB;AAChB,EAAE;AACF,0EAA0E;AAE1E,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;AAGhD,IAAI,aAAa,GAA6C,IAAI,CAAC;AAEnE,SAAS,WAAW;IAClB,gCAAgC;IAChC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAC5C,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,QAAqB,CAAC;QACnC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAClC,CAAC;IAED,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACpC,CAAC;IAED,oEAAoE;IACpE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;IACvC,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,gBAAgB,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACrE,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEhD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,KAAK,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC;YACnC,MAAM,SAAS,GAAG,GAAG,GAAG,OAAO,GAAG,EAAE,CAAC;YACrC,IAAI,CAAC;gBACH,IAAI,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;oBACjC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;gBACzC,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAED,gDAAgD;IAChD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,aAAa,CAAC;IAC3D,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,UAAU,qBAAqB,EAAE,CAAC;AACnE,CAAC;AAED,SAAS,QAAQ;IACf,IAAI,CAAC,aAAa;QAAE,aAAa,GAAG,WAAW,EAAE,CAAC;IAClD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;IACtB,IAAI,EAAE,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QACtB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAClC,CAAC;IACD,IAAI,EAAE,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QAC7B,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IACD,aAAa;IACb,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAClC,CAAC;AAED,uEAAuE;AACvE,SAAS,QAAQ,CAAC,GAAW;IAC3B,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC;IAChD,IAAI,UAAU,EAAE,CAAC;QACf,8EAA8E;QAC9E,OAAO,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,GAAG,CAAC;IACrE,CAAC;IACD,6DAA6D;IAC7D,oDAAoD;IACpD,OAAO,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,GAAG,CAAC;AAChD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAuB;IACxD,OAAO,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,gBAAgB;IAC9B,aAAa,GAAG,IAAI,CAAC;AACvB,CAAC"}
@@ -1 +0,0 @@
1
- export * from '../runtime/adapters/stdin-approval';
@@ -1 +0,0 @@
1
- export * from '../runtime/adapters/websocket-approval';
package/src/approval.ts DELETED
@@ -1,9 +0,0 @@
1
- export { InMemoryApprovalGateway } from '@tagma/core';
2
- export type {
3
- ApprovalDecision,
4
- ApprovalEvent,
5
- ApprovalGateway,
6
- ApprovalListener,
7
- ApprovalOutcome,
8
- ApprovalRequest,
9
- } from '@tagma/core';
package/src/bootstrap.ts DELETED
@@ -1,55 +0,0 @@
1
- import type { PluginRegistry } from '@tagma/core';
2
- import type { TagmaPlugin } from './types';
3
-
4
- // Built-in Drivers
5
- // Only opencode is built in. Other drivers (codex, claude-code) ship as
6
- // workspace plugins under packages/ and must be declared in pipeline.yaml
7
- // via the `plugins` field, e.g.:
8
- // plugins: ["@tagma/driver-codex", "@tagma/driver-claude-code"]
9
- import { OpenCodeDriver } from './drivers/opencode';
10
-
11
- // Built-in Triggers
12
- import { FileTrigger } from './triggers/file';
13
- import { ManualTrigger } from './triggers/manual';
14
-
15
- // Built-in Completions
16
- import { ExitCodeCompletion } from './completions/exit-code';
17
- import { FileExistsCompletion } from './completions/file-exists';
18
- import { OutputCheckCompletion } from './completions/output-check';
19
-
20
- // Built-in Middleware
21
- import { StaticContextMiddleware } from './middlewares/static-context';
22
-
23
- export const BuiltinTagmaPlugin = {
24
- name: '@tagma/sdk/builtins',
25
- capabilities: {
26
- drivers: {
27
- opencode: OpenCodeDriver,
28
- },
29
- triggers: {
30
- file: FileTrigger,
31
- manual: ManualTrigger,
32
- },
33
- completions: {
34
- exit_code: ExitCodeCompletion,
35
- file_exists: FileExistsCompletion,
36
- output_check: OutputCheckCompletion,
37
- },
38
- middlewares: {
39
- static_context: StaticContextMiddleware,
40
- },
41
- },
42
- } satisfies TagmaPlugin;
43
-
44
- /**
45
- * Register every built-in plugin into `target`. Hosts instantiate one
46
- * PluginRegistry per workspace or SDK instance and call this once per
47
- * instance so each workspace sees the same built-ins without sharing
48
- * registration state.
49
- *
50
- * Built-in handlers are stateless module singletons — registering the same
51
- * handler object into N registries is cheap and safe; no cloning is needed.
52
- */
53
- export function bootstrapBuiltins(target: PluginRegistry): void {
54
- target.registerTagmaPlugin(BuiltinTagmaPlugin);
55
- }
@@ -1,34 +0,0 @@
1
- import type { CompletionPlugin, CompletionContext, TaskResult } from '../types';
2
-
3
- export const ExitCodeCompletion: CompletionPlugin = {
4
- name: 'exit_code',
5
- schema: {
6
- description: 'Mark the task successful when the exit code matches.',
7
- fields: {
8
- expect: {
9
- type: 'number-or-list',
10
- default: 0,
11
- description: 'Expected exit code, or list of acceptable codes (e.g. 0 or [0, 2]).',
12
- placeholder: '0',
13
- },
14
- },
15
- },
16
-
17
- async check(
18
- config: Record<string, unknown>,
19
- result: TaskResult,
20
- _ctx: CompletionContext,
21
- ): Promise<boolean> {
22
- const expected = config.expect ?? 0;
23
-
24
- if (typeof expected === 'number') {
25
- return result.exitCode === expected;
26
- }
27
- if (Array.isArray(expected) && expected.every((v) => typeof v === 'number')) {
28
- return expected.includes(result.exitCode);
29
- }
30
- throw new Error(
31
- `exit_code completion: "expect" must be a number or number[], got ${typeof expected}`,
32
- );
33
- },
34
- };
@@ -1,66 +0,0 @@
1
- import { stat } from 'node:fs/promises';
2
- import type { CompletionPlugin, CompletionContext, TaskResult } from '../types';
3
- import { validatePath } from '../utils';
4
-
5
- type Kind = 'file' | 'dir' | 'any';
6
-
7
- export const FileExistsCompletion: CompletionPlugin = {
8
- name: 'file_exists',
9
- schema: {
10
- description: 'Mark the task successful when a target file or directory exists.',
11
- fields: {
12
- path: {
13
- type: 'path',
14
- required: true,
15
- description: 'Path to check (relative to workDir or absolute).',
16
- },
17
- kind: {
18
- type: 'enum',
19
- enum: ['file', 'dir', 'any'],
20
- default: 'any',
21
- description: 'Restrict to a file, directory, or accept either.',
22
- },
23
- min_size: {
24
- type: 'number',
25
- min: 0,
26
- description: 'Optional minimum size in bytes (files only).',
27
- },
28
- },
29
- },
30
-
31
- async check(
32
- config: Record<string, unknown>,
33
- _result: TaskResult,
34
- ctx: CompletionContext,
35
- ): Promise<boolean> {
36
- const filePath = config.path as string;
37
- if (!filePath) throw new Error('file_exists completion: "path" is required');
38
-
39
- const safePath = validatePath(filePath, ctx.workDir);
40
-
41
- const kind = (config.kind as Kind | undefined) ?? 'any';
42
- if (kind !== 'file' && kind !== 'dir' && kind !== 'any') {
43
- throw new Error(
44
- `file_exists completion: "kind" must be "file" | "dir" | "any", got "${kind}"`,
45
- );
46
- }
47
-
48
- const minSize = config.min_size;
49
- if (minSize != null && (typeof minSize !== 'number' || minSize < 0)) {
50
- throw new Error(`file_exists completion: "min_size" must be a non-negative number`);
51
- }
52
-
53
- try {
54
- const st = await stat(safePath);
55
- if (kind === 'file' && !st.isFile()) return false;
56
- if (kind === 'dir' && !st.isDirectory()) return false;
57
- if (typeof minSize === 'number' && st.isFile() && st.size < minSize) return false;
58
- return true;
59
- } catch (err: unknown) {
60
- const code = (err as NodeJS.ErrnoException).code;
61
- if (code === 'ENOENT' || code === 'ENOTDIR') return false;
62
- // Permission / IO errors should surface, not silently mean "missing"
63
- throw err;
64
- }
65
- },
66
- };
@@ -1,50 +0,0 @@
1
- import { expect, test } from 'bun:test';
2
- import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
3
- import { tmpdir } from 'node:os';
4
- import { join } from 'node:path';
5
- import { OutputCheckCompletion } from './output-check';
6
- import type { TaskResult } from '../types';
7
-
8
- function taskResult(stdout = 'payload'): TaskResult {
9
- return {
10
- exitCode: 0,
11
- stdout,
12
- stderr: '',
13
- stdoutPath: null,
14
- stderrPath: null,
15
- stdoutBytes: stdout.length,
16
- stderrBytes: 0,
17
- durationMs: 0,
18
- sessionId: null,
19
- normalizedOutput: null,
20
- failureKind: null,
21
- };
22
- }
23
-
24
- test(
25
- 'output_check drains verbose check stdout so the check process can exit',
26
- async () => {
27
- const dir = mkdtempSync(join(tmpdir(), 'tagma-output-check-'));
28
- try {
29
- const script = join(dir, 'verbose-check.js');
30
- writeFileSync(
31
- script,
32
- 'process.stdout.write("x".repeat(16 * 1024 * 1024));\n',
33
- );
34
-
35
- const passed = await OutputCheckCompletion.check(
36
- {
37
- check: `node "${script}"`,
38
- timeout: '1s',
39
- },
40
- taskResult(),
41
- { workDir: dir, signal: new AbortController().signal },
42
- );
43
-
44
- expect(passed).toBe(true);
45
- } finally {
46
- rmSync(dir, { recursive: true, force: true });
47
- }
48
- },
49
- 5_000,
50
- );
@@ -1,92 +0,0 @@
1
- import type { CompletionPlugin, CompletionContext, TaskResult } from '../types';
2
- import { shellArgs, parseDuration } from '../utils';
3
-
4
- const DEFAULT_TIMEOUT_MS = 30_000;
5
-
6
- export const OutputCheckCompletion: CompletionPlugin = {
7
- name: 'output_check',
8
- schema: {
9
- description:
10
- 'Pipe the task output into a shell command; mark success when that command exits 0. For AI driver tasks the driver-normalized text is piped (not the raw NDJSON); command tasks see their raw stdout.',
11
- fields: {
12
- check: {
13
- type: 'string',
14
- required: true,
15
- description:
16
- 'Shell command to run. The task output is piped to its stdin — normalizedOutput when the driver provides one, otherwise raw stdout.',
17
- placeholder: "grep -q 'PASS'",
18
- },
19
- timeout: {
20
- type: 'duration',
21
- default: '30s',
22
- description: 'Maximum time to wait for the check command.',
23
- placeholder: '30s',
24
- },
25
- },
26
- },
27
-
28
- async check(
29
- config: Record<string, unknown>,
30
- result: TaskResult,
31
- ctx: CompletionContext,
32
- ): Promise<boolean> {
33
- const checkCmd = config.check as string;
34
- if (!checkCmd) throw new Error('output_check completion: "check" is required');
35
-
36
- const timeoutMs =
37
- config.timeout != null ? parseDuration(String(config.timeout)) : DEFAULT_TIMEOUT_MS;
38
-
39
- const controller = new AbortController();
40
- const timer = setTimeout(() => controller.abort(), timeoutMs);
41
-
42
- // Wire pipeline abort signal into the check process so external abort
43
- // terminates the child instead of leaving it running undetected.
44
- const onAbort = () => controller.abort();
45
- if (ctx.signal) {
46
- if (ctx.signal.aborted) {
47
- controller.abort();
48
- } else {
49
- ctx.signal.addEventListener('abort', onAbort, { once: true });
50
- }
51
- }
52
-
53
- const proc = Bun.spawn(shellArgs(checkCmd) as string[], {
54
- cwd: ctx.workDir,
55
- stdin: 'pipe',
56
- stdout: 'pipe',
57
- stderr: 'pipe',
58
- signal: controller.signal,
59
- });
60
-
61
- try {
62
- if (proc.stdin) {
63
- try {
64
- // Prefer driver-normalized text (e.g. concatenated message text for
65
- // AI drivers that emit NDJSON). Falling back to raw stdout keeps
66
- // command tasks and drivers without parseResult working.
67
- const payload = result.normalizedOutput ?? result.stdout;
68
- proc.stdin.write(payload);
69
- proc.stdin.end(); // no await — consistent with runner.ts; proc.exited handles sync
70
- } catch (err: unknown) {
71
- // EPIPE is expected when the check process exits before reading all of stdin
72
- // (e.g. `grep -q` exits on first match). Anything else is a real failure.
73
- const code = (err as NodeJS.ErrnoException)?.code;
74
- if (code !== 'EPIPE') throw err;
75
- }
76
- }
77
-
78
- // Consume stderr concurrently with waiting for exit to prevent pipe-buffer
79
- // deadlock when check script emits more than ~64 KB of stderr output.
80
- const [exitCode, stderr] = await Promise.all([proc.exited, new Response(proc.stderr).text()]);
81
-
82
- if (exitCode !== 0 && stderr.trim()) {
83
- console.warn(`[output_check] "${checkCmd}" exit=${exitCode}: ${stderr.trim()}`);
84
- }
85
-
86
- return exitCode === 0;
87
- } finally {
88
- clearTimeout(timer);
89
- if (ctx.signal) ctx.signal.removeEventListener('abort', onAbort);
90
- }
91
- },
92
- };
@@ -1,70 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
- import { transferTask } from './config-ops';
3
- import type { RawPipelineConfig } from './types';
4
-
5
- describe('transferTask', () => {
6
- test('does not remove the source task when the target track is missing', () => {
7
- const config: RawPipelineConfig = {
8
- name: 'Transfer',
9
- tracks: [
10
- {
11
- id: 'a',
12
- name: 'A',
13
- tasks: [{ id: 'move_me', command: 'echo a' }],
14
- },
15
- ],
16
- };
17
-
18
- const next = transferTask(config, 'a', 'move_me', 'missing');
19
-
20
- expect(next).toEqual(config);
21
- });
22
-
23
- test('qualifies moved task same-track dependencies so they keep pointing at the old track', () => {
24
- const config: RawPipelineConfig = {
25
- name: 'Transfer',
26
- tracks: [
27
- {
28
- id: 'a',
29
- name: 'A',
30
- tasks: [
31
- { id: 'build', command: 'echo old' },
32
- { id: 'move_me', command: 'echo move', depends_on: ['build'] },
33
- ],
34
- },
35
- {
36
- id: 'b',
37
- name: 'B',
38
- tasks: [{ id: 'build', command: 'echo new' }],
39
- },
40
- ],
41
- };
42
-
43
- const next = transferTask(config, 'a', 'move_me', 'b');
44
- const moved = next.tracks[1].tasks.find((task) => task.id === 'move_me');
45
-
46
- expect(moved?.depends_on).toEqual(['a.build']);
47
- });
48
-
49
- test('does not overwrite an existing task in the target track with the same id', () => {
50
- const config: RawPipelineConfig = {
51
- name: 'Transfer',
52
- tracks: [
53
- {
54
- id: 'a',
55
- name: 'A',
56
- tasks: [{ id: 'same', command: 'echo source' }],
57
- },
58
- {
59
- id: 'b',
60
- name: 'B',
61
- tasks: [{ id: 'same', command: 'echo target' }],
62
- },
63
- ],
64
- };
65
-
66
- const next = transferTask(config, 'a', 'same', 'b');
67
-
68
- expect(next).toEqual(config);
69
- });
70
- });