@relayflows/sdk 2.0.15 → 2.0.16
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/dist/agent-artifacts.d.ts +20 -0
- package/dist/agent-artifacts.d.ts.map +1 -0
- package/dist/agent-artifacts.js +81 -0
- package/dist/agent-artifacts.js.map +1 -0
- package/dist/authored-flow-executor.d.ts +3 -3
- package/dist/authored-flow-executor.d.ts.map +1 -1
- package/dist/authored-flow-executor.js +7 -7
- package/dist/authored-flow-executor.js.map +1 -1
- package/dist/authored-step-output.d.ts +2 -0
- package/dist/authored-step-output.d.ts.map +1 -1
- package/dist/authored-step-output.js +5 -1
- package/dist/authored-step-output.js.map +1 -1
- package/dist/authored-worker-step.d.ts.map +1 -1
- package/dist/authored-worker-step.js +19 -1
- package/dist/authored-worker-step.js.map +1 -1
- package/dist/cli/check.js +6 -1
- package/dist/cli/check.js.map +1 -1
- package/dist/cli/cloud-deploy.d.ts +30 -0
- package/dist/cli/cloud-deploy.d.ts.map +1 -0
- package/dist/cli/cloud-deploy.js +162 -0
- package/dist/cli/cloud-deploy.js.map +1 -0
- package/dist/cli/cloud-run.d.ts +3 -1
- package/dist/cli/cloud-run.d.ts.map +1 -1
- package/dist/cli/cloud-run.js +37 -5
- package/dist/cli/cloud-run.js.map +1 -1
- package/dist/cli/cloud-sync.d.ts +13 -0
- package/dist/cli/cloud-sync.d.ts.map +1 -0
- package/dist/cli/cloud-sync.js +39 -0
- package/dist/cli/cloud-sync.js.map +1 -0
- package/dist/cli/run.d.ts +1 -1
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +12 -1
- package/dist/cli/run.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +82 -12
- package/dist/cli.js.map +1 -1
- package/dist/cloud-deploy.d.ts +70 -0
- package/dist/cloud-deploy.d.ts.map +1 -0
- package/dist/cloud-deploy.js +181 -0
- package/dist/cloud-deploy.js.map +1 -0
- package/dist/cloud-http.d.ts +37 -2
- package/dist/cloud-http.d.ts.map +1 -1
- package/dist/cloud-http.js +98 -8
- package/dist/cloud-http.js.map +1 -1
- package/dist/cloud-run.d.ts +23 -0
- package/dist/cloud-run.d.ts.map +1 -1
- package/dist/cloud-run.js +30 -1
- package/dist/cloud-run.js.map +1 -1
- package/dist/cloud-sync.d.ts +66 -0
- package/dist/cloud-sync.d.ts.map +1 -0
- package/dist/cloud-sync.js +287 -0
- package/dist/cloud-sync.js.map +1 -0
- package/dist/failure-kinds.d.ts +8 -1
- package/dist/failure-kinds.d.ts.map +1 -1
- package/dist/failure-kinds.js +8 -0
- package/dist/failure-kinds.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/agent-artifacts.ts +76 -0
- package/src/authored-flow-executor.ts +8 -8
- package/src/authored-step-output.ts +6 -1
- package/src/authored-worker-step.ts +19 -1
- package/src/cli/check.ts +6 -1
- package/src/cli/cloud-deploy.ts +157 -0
- package/src/cli/cloud-run.ts +37 -6
- package/src/cli/cloud-sync.ts +37 -0
- package/src/cli/run.ts +13 -2
- package/src/cli.ts +75 -12
- package/src/cloud-deploy.ts +236 -0
- package/src/cloud-http.ts +129 -9
- package/src/cloud-run.ts +47 -1
- package/src/cloud-sync.ts +315 -0
- package/src/failure-kinds.ts +8 -0
- package/src/index.ts +8 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { createReadStream, createWriteStream, existsSync, lstatSync, mkdtempSync, readdirSync, readlinkSync, rmSync } from 'node:fs';
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
6
|
+
import { Readable } from 'node:stream';
|
|
7
|
+
import { pipeline } from 'node:stream/promises';
|
|
8
|
+
import { createGzip } from 'node:zlib';
|
|
9
|
+
import { CloudFlowError, cloudFetch, cloudRequest, cloudRunId, isCloudRecord, } from './cloud-http.js';
|
|
10
|
+
/**
|
|
11
|
+
* Code sync for hosted v2 runs, Cloud-API transport only.
|
|
12
|
+
*
|
|
13
|
+
* v1's `--sync-code` had two transports: an S3 client with STS credentials and
|
|
14
|
+
* the Cloud API's own storage route. v2 runs on Cloudflare, so this module
|
|
15
|
+
* speaks only the second: `prepare` must answer with a `cloud-api` storage
|
|
16
|
+
* backend, the tarball is `PUT` to `/workflows/runs/<id>/storage/<key>`, and
|
|
17
|
+
* the sandbox's post-run patch is read from `/workflows/runs/<id>/patch`. A
|
|
18
|
+
* `prepare` that hands back anything else is refused before any upload — the
|
|
19
|
+
* SDK never carries an AWS dependency and never sends code to a bucket it did
|
|
20
|
+
* not get through the Cloud API.
|
|
21
|
+
*/
|
|
22
|
+
/** Uncompressed bytes. Matches the sandbox's extraction budget with headroom. */
|
|
23
|
+
export const MAX_SYNC_BYTES = 256 * 1024 * 1024;
|
|
24
|
+
const ALWAYS_SKIPPED = new Set(['.git', 'node_modules']);
|
|
25
|
+
const CODE_KEY = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;
|
|
26
|
+
/** `POST /api/v1/workflows/prepare`, refusing every non-Cloud-API storage backend. */
|
|
27
|
+
export async function prepareCloudSync(options) {
|
|
28
|
+
const receipt = await cloudFetch('/api/v1/workflows/prepare', options, { method: 'POST' });
|
|
29
|
+
if (!isCloudRecord(receipt))
|
|
30
|
+
throw new CloudFlowError('invalid_response', 'Cloud prepare returned a non-object.');
|
|
31
|
+
const storage = isCloudRecord(receipt.workflowStorage) ? receipt.workflowStorage : undefined;
|
|
32
|
+
const credentials = isCloudRecord(receipt.s3Credentials) ? receipt.s3Credentials : undefined;
|
|
33
|
+
const backend = storage?.backend ?? credentials?.backend;
|
|
34
|
+
if (backend !== 'cloud-api') {
|
|
35
|
+
throw new CloudFlowError('unsupported_storage_backend', 'Cloud offered a workflow storage backend other than the Cloud API (R2). '
|
|
36
|
+
+ 'flows v2 syncs code only through the Cloud API; it never uploads to AWS directly.');
|
|
37
|
+
}
|
|
38
|
+
const codeKey = typeof receipt.s3CodeKey === 'string' ? receipt.s3CodeKey : '';
|
|
39
|
+
if (!CODE_KEY.test(codeKey))
|
|
40
|
+
throw new CloudFlowError('invalid_response', 'Cloud prepare returned an unusable code key.');
|
|
41
|
+
const uploadToken = credentials?.cloudApiAccessToken;
|
|
42
|
+
if (uploadToken !== undefined && typeof uploadToken !== 'string') {
|
|
43
|
+
throw new CloudFlowError('invalid_response', 'Cloud prepare returned an unusable storage credential.');
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
runId: cloudRunId(receipt.runId), codeKey,
|
|
47
|
+
...(uploadToken === undefined ? {} : { uploadToken }),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* gzip'd ustar of the working tree at `root`, streamed to a temporary file so
|
|
52
|
+
* the peak footprint is one file plus the compressor's window, never the
|
|
53
|
+
* whole tree. Inside a Git checkout the member list is `git ls-files --cached
|
|
54
|
+
* --others --exclude-standard`, so `.gitignore` governs and untracked-but-
|
|
55
|
+
* not-ignored files ride along, as they do in v1. Outside Git, every regular
|
|
56
|
+
* file and in-tree symlink except `.git`/`node_modules`. A Git failure other
|
|
57
|
+
* than "not a repository" is refused rather than silently widened to the walk:
|
|
58
|
+
* an ignored `.env` must never reach Cloud because `git` was missing or the
|
|
59
|
+
* index was locked. Executable bits survive; symlinks whose target leaves the
|
|
60
|
+
* tree are dropped and reported, since on the host they would point at
|
|
61
|
+
* whatever happens to live at that path. Ordering and mtimes are
|
|
62
|
+
* deterministic, so the same tree packs to the same bytes.
|
|
63
|
+
*/
|
|
64
|
+
export async function packWorkingTree(root) {
|
|
65
|
+
const absoluteRoot = resolve(root);
|
|
66
|
+
const files = listTreeFiles(absoluteRoot);
|
|
67
|
+
const spool = mkdtempSync(join(tmpdir(), 'flows-sync-'));
|
|
68
|
+
const archivePath = join(spool, 'code.tar.gz');
|
|
69
|
+
const dispose = () => rmSync(spool, { recursive: true, force: true });
|
|
70
|
+
const members = [];
|
|
71
|
+
const skippedLinks = [];
|
|
72
|
+
let bytes = 0;
|
|
73
|
+
async function* entries() {
|
|
74
|
+
for (const path of files) {
|
|
75
|
+
const absolute = join(absoluteRoot, ...path.split('/'));
|
|
76
|
+
const stat = lstatSync(absolute);
|
|
77
|
+
if (stat.isSymbolicLink()) {
|
|
78
|
+
const target = readlinkSync(absolute);
|
|
79
|
+
const relativeTarget = relative(absoluteRoot, resolve(dirname(absolute), target));
|
|
80
|
+
if (isAbsolute(target) || relativeTarget === '..' || relativeTarget.startsWith(`..${sep}`)) {
|
|
81
|
+
skippedLinks.push(path);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
members.push(path);
|
|
85
|
+
yield ustarHeader(path, 0, '2', 0o777, target);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (!stat.isFile())
|
|
89
|
+
continue;
|
|
90
|
+
bytes += stat.size;
|
|
91
|
+
if (bytes > MAX_SYNC_BYTES) {
|
|
92
|
+
throw new CloudFlowError('sync_too_large', `The working tree exceeds the ${MAX_SYNC_BYTES}-byte code sync limit; narrow it with .gitignore.`);
|
|
93
|
+
}
|
|
94
|
+
members.push(path);
|
|
95
|
+
yield ustarHeader(path, stat.size, '0', stat.mode & 0o111 ? 0o755 : 0o644);
|
|
96
|
+
yield createReadStream(absolute);
|
|
97
|
+
const padding = (512 - (stat.size % 512)) % 512;
|
|
98
|
+
if (padding)
|
|
99
|
+
yield Buffer.alloc(padding);
|
|
100
|
+
}
|
|
101
|
+
yield Buffer.alloc(1024);
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
await pipeline(Readable.from(flatten(entries())), createGzip({ level: 6 }), createWriteStream(archivePath));
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
dispose();
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
return { archivePath, files: members, bytes, skippedLinks, dispose };
|
|
111
|
+
}
|
|
112
|
+
/** Yield file streams chunk by chunk so `Readable.from` never buffers a whole file. */
|
|
113
|
+
async function* flatten(source) {
|
|
114
|
+
for await (const part of source) {
|
|
115
|
+
if (Buffer.isBuffer(part)) {
|
|
116
|
+
yield part;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
for await (const chunk of part)
|
|
120
|
+
yield chunk;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/** The nearest `.git` entry at `root` or any ancestor — the checkout a .gitignore would belong to. */
|
|
124
|
+
function nearestGitEntry(root) {
|
|
125
|
+
let directory = root;
|
|
126
|
+
while (true) {
|
|
127
|
+
if (existsSync(join(directory, '.git')))
|
|
128
|
+
return join(directory, '.git');
|
|
129
|
+
const parent = dirname(directory);
|
|
130
|
+
if (parent === directory)
|
|
131
|
+
return undefined;
|
|
132
|
+
directory = parent;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function listTreeFiles(root) {
|
|
136
|
+
const inside = spawnSync('git', ['-C', root, 'rev-parse', '--is-inside-work-tree'], { encoding: 'utf8' });
|
|
137
|
+
if (inside.error !== undefined) {
|
|
138
|
+
// Without git there is no way to honour a .gitignore, so a tree that has
|
|
139
|
+
// one anywhere above it cannot be described honestly; a tree with none is
|
|
140
|
+
// a plain directory and can be walked.
|
|
141
|
+
const entry = nearestGitEntry(root);
|
|
142
|
+
if (entry !== undefined) {
|
|
143
|
+
throw new CloudFlowError('sync_unsupported', `git is not available (${summarize(inside.error.message)}) but ${entry} exists; `
|
|
144
|
+
+ 'refusing to upload a checkout without its .gitignore.');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const notARepository = inside.error !== undefined
|
|
148
|
+
|| (inside.status !== 0 && /not a git repository/iu.test(inside.stderr));
|
|
149
|
+
let candidates;
|
|
150
|
+
if (notARepository) {
|
|
151
|
+
// A `.git` that git itself cannot read — here or in a parent — is a broken
|
|
152
|
+
// checkout, not a plain directory: its .gitignore was meant to apply, so
|
|
153
|
+
// walking would upload exactly what it excluded.
|
|
154
|
+
const entry = nearestGitEntry(root);
|
|
155
|
+
if (entry !== undefined) {
|
|
156
|
+
throw new CloudFlowError('sync_unsupported', `${entry} exists but git cannot read it (${summarize(inside.stderr ?? inside.error?.message)}); `
|
|
157
|
+
+ 'refusing to upload a checkout without its .gitignore.');
|
|
158
|
+
}
|
|
159
|
+
candidates = [];
|
|
160
|
+
walk(root, root, candidates);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
if (inside.status !== 0 || inside.stdout.trim() !== 'true') {
|
|
164
|
+
throw new CloudFlowError('sync_unsupported', `git could not describe ${root} (${summarize(inside.stderr)}); refusing to guess which files to upload.`);
|
|
165
|
+
}
|
|
166
|
+
const git = spawnSync('git', ['-C', root, 'ls-files', '-z', '--cached', '--others', '--exclude-standard'], { encoding: 'utf8', maxBuffer: 256 * 1024 * 1024 });
|
|
167
|
+
if (git.status !== 0) {
|
|
168
|
+
throw new CloudFlowError('sync_unsupported', `git ls-files failed in ${root} (${summarize(git.stderr)}); refusing to upload without .gitignore.`);
|
|
169
|
+
}
|
|
170
|
+
candidates = git.stdout.split('\0').filter(Boolean);
|
|
171
|
+
}
|
|
172
|
+
const files = new Set();
|
|
173
|
+
for (const candidate of candidates) {
|
|
174
|
+
const path = candidate.split(sep).join('/');
|
|
175
|
+
const segments = path.split('/');
|
|
176
|
+
if (segments.some(segment => ALWAYS_SKIPPED.has(segment) || segment === '..' || segment === ''))
|
|
177
|
+
continue;
|
|
178
|
+
let stat;
|
|
179
|
+
try {
|
|
180
|
+
stat = lstatSync(join(root, ...segments));
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (stat.isFile() || stat.isSymbolicLink())
|
|
186
|
+
files.add(path);
|
|
187
|
+
}
|
|
188
|
+
return [...files].sort();
|
|
189
|
+
}
|
|
190
|
+
function summarize(stderr) {
|
|
191
|
+
const line = (stderr ?? '').split('\n').map(l => l.trim()).find(Boolean) ?? 'no diagnostic';
|
|
192
|
+
return line.length > 160 ? `${line.slice(0, 157)}...` : line;
|
|
193
|
+
}
|
|
194
|
+
function walk(root, current, out) {
|
|
195
|
+
for (const entry of readdirSync(current, { withFileTypes: true })) {
|
|
196
|
+
if (ALWAYS_SKIPPED.has(entry.name))
|
|
197
|
+
continue;
|
|
198
|
+
const path = join(current, entry.name);
|
|
199
|
+
if (entry.isDirectory())
|
|
200
|
+
walk(root, path, out);
|
|
201
|
+
else if (entry.isFile() || entry.isSymbolicLink())
|
|
202
|
+
out.push(relative(root, path));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/** POSIX ustar header. Names beyond the 100+155 split are refused, not truncated. */
|
|
206
|
+
function ustarHeader(path, size, type, mode, link = '') {
|
|
207
|
+
let name = path;
|
|
208
|
+
let prefix = '';
|
|
209
|
+
if (Buffer.byteLength(name) > 100) {
|
|
210
|
+
const cut = name.lastIndexOf('/', 154);
|
|
211
|
+
if (cut <= 0 || Buffer.byteLength(name.slice(cut + 1)) > 100 || Buffer.byteLength(name.slice(0, cut)) > 155) {
|
|
212
|
+
throw new CloudFlowError('sync_unsupported', `Path "${path}" is too long for the code sync archive.`);
|
|
213
|
+
}
|
|
214
|
+
prefix = name.slice(0, cut);
|
|
215
|
+
name = name.slice(cut + 1);
|
|
216
|
+
}
|
|
217
|
+
if (Buffer.byteLength(link) > 100) {
|
|
218
|
+
throw new CloudFlowError('sync_unsupported', `Symlink target of "${path}" is too long for the code sync archive.`);
|
|
219
|
+
}
|
|
220
|
+
const header = Buffer.alloc(512);
|
|
221
|
+
header.write(name, 0, 100);
|
|
222
|
+
header.write(mode.toString(8).padStart(7, '0'), 100, 8);
|
|
223
|
+
header.write('0000000', 108, 8);
|
|
224
|
+
header.write('0000000', 116, 8);
|
|
225
|
+
header.write(size.toString(8).padStart(11, '0'), 124, 12);
|
|
226
|
+
header.write('00000000000', 136, 12);
|
|
227
|
+
header.write(' ', 148, 8);
|
|
228
|
+
header.write(type, 156, 1);
|
|
229
|
+
header.write(link, 157, 100);
|
|
230
|
+
header.write('ustar\0', 257, 6);
|
|
231
|
+
header.write('00', 263, 2);
|
|
232
|
+
header.write(prefix, 345, 155);
|
|
233
|
+
let checksum = 0;
|
|
234
|
+
for (const byte of header)
|
|
235
|
+
checksum += byte;
|
|
236
|
+
header.write(checksum.toString(8).padStart(6, '0') + '\0 ', 148, 8);
|
|
237
|
+
return header;
|
|
238
|
+
}
|
|
239
|
+
/** `PUT` the archive through the Cloud API; the run-scoped credential wins when present. */
|
|
240
|
+
export async function uploadCloudCode(prepared, packed, options) {
|
|
241
|
+
// The request needs a sized body, so the compressed archive is read back
|
|
242
|
+
// once; that is the one copy that has to exist, and it is the small one.
|
|
243
|
+
const tarball = await readFile(packed.archivePath);
|
|
244
|
+
await cloudFetch(`/api/v1/workflows/runs/${encodeURIComponent(prepared.runId)}/storage/${encodeURIComponent(prepared.codeKey)}`, { ...options, requestTimeoutMs: options.requestTimeoutMs ?? 300_000 }, { method: 'PUT', body: tarball, contentType: 'application/gzip',
|
|
245
|
+
...(prepared.uploadToken === undefined ? {} : { bearerToken: prepared.uploadToken }) });
|
|
246
|
+
}
|
|
247
|
+
/** The sandbox's post-run diff. Multi-path runs carry several patches and are refused here. */
|
|
248
|
+
export async function downloadCloudPatch(runId, options) {
|
|
249
|
+
const payload = await cloudRequest(`/api/v1/workflows/runs/${encodeURIComponent(cloudRunId(runId))}/patch`, options);
|
|
250
|
+
if (!isCloudRecord(payload))
|
|
251
|
+
throw new CloudFlowError('invalid_response', 'Cloud patch response was not an object.');
|
|
252
|
+
if (isCloudRecord(payload.patches)) {
|
|
253
|
+
const names = Object.keys(payload.patches);
|
|
254
|
+
throw new CloudFlowError('sync_unsupported', `Run ${runId} produced ${names.length} path-scoped patches (${names.join(', ')}); flows sync applies single-tree runs only.`);
|
|
255
|
+
}
|
|
256
|
+
if (typeof payload.patch !== 'string' || typeof payload.hasChanges !== 'boolean') {
|
|
257
|
+
throw new CloudFlowError('invalid_response', 'Cloud patch response is missing patch or hasChanges.');
|
|
258
|
+
}
|
|
259
|
+
return { patch: payload.patch, hasChanges: payload.hasChanges };
|
|
260
|
+
}
|
|
261
|
+
/** Every path a unified diff touches, deletions included, in order of first appearance. */
|
|
262
|
+
export function patchedPaths(patch) {
|
|
263
|
+
const paths = [];
|
|
264
|
+
for (const match of patch.matchAll(/^diff --git a\/(.+?) b\/(.+)$/gmu)) {
|
|
265
|
+
for (const path of [match[1], match[2]])
|
|
266
|
+
if (!paths.includes(path))
|
|
267
|
+
paths.push(path);
|
|
268
|
+
}
|
|
269
|
+
return paths;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* `git apply --check` then `git apply`; a conflict leaves the tree untouched.
|
|
273
|
+
* The patch lands in the working tree uncommitted, so what the run changed is
|
|
274
|
+
* reviewed with `git diff` before anything is kept — the same contract as v1.
|
|
275
|
+
*/
|
|
276
|
+
export function applyCloudPatch(root, patch) {
|
|
277
|
+
const args = ['-C', resolve(root), 'apply', '--whitespace=nowarn'];
|
|
278
|
+
const check = spawnSync('git', [...args, '--check'], { input: patch, encoding: 'utf8' });
|
|
279
|
+
if (check.status !== 0) {
|
|
280
|
+
throw new CloudFlowError('patch_conflict', `The patch does not apply cleanly to ${resolve(root)}:\n${check.stderr.trim()}`);
|
|
281
|
+
}
|
|
282
|
+
const apply = spawnSync('git', args, { input: patch, encoding: 'utf8' });
|
|
283
|
+
if (apply.status !== 0) {
|
|
284
|
+
throw new CloudFlowError('patch_conflict', `git apply failed:\n${apply.stderr.trim()}`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
//# sourceMappingURL=cloud-sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloud-sync.js","sourceRoot":"","sources":["../src/cloud-sync.ts"],"names":[],"mappings":"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"}
|
package/dist/failure-kinds.d.ts
CHANGED
|
@@ -30,8 +30,15 @@ export declare const PREFLIGHT_WARNING_KINDS: readonly ["unprovable_effects", "c
|
|
|
30
30
|
* serving and this invocation was told not to start one" (`--no-spawn`), while
|
|
31
31
|
* a spawn that was attempted and did not produce a serving daemon names which
|
|
32
32
|
* step failed. All of them are still exit 2 — refused before a journal write.
|
|
33
|
+
*
|
|
34
|
+
* Despite the name, this list is the run-outcome diagnostic vocabulary rather
|
|
35
|
+
* than failures alone. `run_parked` has always sat here and exits 3 under
|
|
36
|
+
* severity `parked`; `run_declined` joins it, exiting 0 under severity
|
|
37
|
+
* `declined`. The mismatch between the constant's name and its non-failure
|
|
38
|
+
* members is pre-existing — renaming it is a separate change, and neither this
|
|
39
|
+
* list nor `RunDiagnostic` is exported from the package index.
|
|
33
40
|
*/
|
|
34
|
-
export declare const RUN_FAILURE_KINDS: readonly ["bucket_unconfigured", "bucket_unreachable", "bundle_signature_invalid", "bundle_unsupported", "human_influenced_run", "reuse_spec_mismatch", "reuse_run_not_found", "reuse_journal_read_failed", "daemon_unreachable", "daemon_protocol_mismatch", "daemon_start_failed", "daemon_start_timeout", "relayflowd_not_found", "protocol_error", "run_parked", "run_unavailable"];
|
|
41
|
+
export declare const RUN_FAILURE_KINDS: readonly ["bucket_unconfigured", "bucket_unreachable", "bundle_signature_invalid", "bundle_unsupported", "human_influenced_run", "reuse_spec_mismatch", "reuse_run_not_found", "reuse_journal_read_failed", "daemon_unreachable", "daemon_protocol_mismatch", "daemon_start_failed", "daemon_start_timeout", "relayflowd_not_found", "protocol_error", "run_parked", "run_declined", "run_unavailable"];
|
|
35
42
|
/**
|
|
36
43
|
* Non-refusing outcomes of the attach step. `connection_file_stale` is
|
|
37
44
|
* DAEMON-LIFECYCLE.md §2 row 2: the socket answered while `connection.json`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"failure-kinds.d.ts","sourceRoot":"","sources":["../src/failure-kinds.ts"],"names":[],"mappings":"AA+BA,qEAAqE;AACrE,eAAO,MAAM,uBAAuB,+0BAG1B,CAAC;AAEX,+EAA+E;AAC/E,eAAO,MAAM,yBAAyB,4IAQ5B,CAAC;AAEX,eAAO,MAAM,mBAAmB,g8BAGtB,CAAC;AAEX;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,uBAAuB,iHAM1B,CAAC;AAEX
|
|
1
|
+
{"version":3,"file":"failure-kinds.d.ts","sourceRoot":"","sources":["../src/failure-kinds.ts"],"names":[],"mappings":"AA+BA,qEAAqE;AACrE,eAAO,MAAM,uBAAuB,+0BAG1B,CAAC;AAEX,+EAA+E;AAC/E,eAAO,MAAM,yBAAyB,4IAQ5B,CAAC;AAEX,eAAO,MAAM,mBAAmB,g8BAGtB,CAAC;AAEX;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,uBAAuB,iHAM1B,CAAC;AAEX;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,iBAAiB,yYAkBpB,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,oCAEpB,CAAC;AAEX,8EAA8E;AAC9E,eAAO,MAAM,mBAAmB,oCAAqC,CAAC;AACtE,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAC5E,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AACpE,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAC5E,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAChE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhE;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAKD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,gBAAgB,CAE3E;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,cAAc,CAEvE"}
|
package/dist/failure-kinds.js
CHANGED
|
@@ -79,6 +79,13 @@ export const PREFLIGHT_WARNING_KINDS = [
|
|
|
79
79
|
* serving and this invocation was told not to start one" (`--no-spawn`), while
|
|
80
80
|
* a spawn that was attempted and did not produce a serving daemon names which
|
|
81
81
|
* step failed. All of them are still exit 2 — refused before a journal write.
|
|
82
|
+
*
|
|
83
|
+
* Despite the name, this list is the run-outcome diagnostic vocabulary rather
|
|
84
|
+
* than failures alone. `run_parked` has always sat here and exits 3 under
|
|
85
|
+
* severity `parked`; `run_declined` joins it, exiting 0 under severity
|
|
86
|
+
* `declined`. The mismatch between the constant's name and its non-failure
|
|
87
|
+
* members is pre-existing — renaming it is a separate change, and neither this
|
|
88
|
+
* list nor `RunDiagnostic` is exported from the package index.
|
|
82
89
|
*/
|
|
83
90
|
export const RUN_FAILURE_KINDS = [
|
|
84
91
|
'bucket_unconfigured',
|
|
@@ -96,6 +103,7 @@ export const RUN_FAILURE_KINDS = [
|
|
|
96
103
|
'relayflowd_not_found',
|
|
97
104
|
'protocol_error',
|
|
98
105
|
'run_parked',
|
|
106
|
+
'run_declined',
|
|
99
107
|
'run_unavailable',
|
|
100
108
|
];
|
|
101
109
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"failure-kinds.js","sourceRoot":"","sources":["../src/failure-kinds.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,MAAM,yBAAyB,GAAG,CAAC,cAAc,CAAU,CAAC;AAE5D,yEAAyE;AACzE,MAAM,mCAAmC,GAAG;IAC1C,GAAG,wBAAwB;IAC3B,GAAG,oBAAoB;IACvB,gCAAgC;IAChC,6BAA6B;IAC7B,iCAAiC;IACjC,6BAA6B;IAC7B,uBAAuB;IACvB,uBAAuB;IACvB,iBAAiB;IACjB,uBAAuB;IACvB,aAAa;IACb,qBAAqB;IACrB,gBAAgB;IAChB,iBAAiB;IACjB,iBAAiB;IACjB,mBAAmB;IACnB,eAAe;IACf,oBAAoB;IACpB,aAAa;IACb,cAAc;IACd,sBAAsB;IACtB,eAAe;IACf,mBAAmB;CACX,CAAC;AAEX,qEAAqE;AACrE,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,GAAG,yBAAyB;IAC5B,GAAG,mCAAmC;CAC9B,CAAC;AAEX,+EAA+E;AAC/E,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,gBAAgB;IAChB,eAAe;IACf,eAAe;IACf,iBAAiB;IACjB,kBAAkB;IAClB,oBAAoB;IACpB,GAAG,yBAAyB;CACpB,CAAC;AAEX,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,GAAG,yBAAyB;IAC5B,GAAG,mCAAmC;CAC9B,CAAC;AAEX;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,oBAAoB;IACpB,oBAAoB;IACpB,oBAAoB;IACpB,cAAc;IACd,kBAAkB;CACV,CAAC;AAEX
|
|
1
|
+
{"version":3,"file":"failure-kinds.js","sourceRoot":"","sources":["../src/failure-kinds.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,MAAM,yBAAyB,GAAG,CAAC,cAAc,CAAU,CAAC;AAE5D,yEAAyE;AACzE,MAAM,mCAAmC,GAAG;IAC1C,GAAG,wBAAwB;IAC3B,GAAG,oBAAoB;IACvB,gCAAgC;IAChC,6BAA6B;IAC7B,iCAAiC;IACjC,6BAA6B;IAC7B,uBAAuB;IACvB,uBAAuB;IACvB,iBAAiB;IACjB,uBAAuB;IACvB,aAAa;IACb,qBAAqB;IACrB,gBAAgB;IAChB,iBAAiB;IACjB,iBAAiB;IACjB,mBAAmB;IACnB,eAAe;IACf,oBAAoB;IACpB,aAAa;IACb,cAAc;IACd,sBAAsB;IACtB,eAAe;IACf,mBAAmB;CACX,CAAC;AAEX,qEAAqE;AACrE,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,GAAG,yBAAyB;IAC5B,GAAG,mCAAmC;CAC9B,CAAC;AAEX,+EAA+E;AAC/E,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,gBAAgB;IAChB,eAAe;IACf,eAAe;IACf,iBAAiB;IACjB,kBAAkB;IAClB,oBAAoB;IACpB,GAAG,yBAAyB;CACpB,CAAC;AAEX,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,GAAG,yBAAyB;IAC5B,GAAG,mCAAmC;CAC9B,CAAC;AAEX;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,oBAAoB;IACpB,oBAAoB;IACpB,oBAAoB;IACpB,cAAc;IACd,kBAAkB;CACV,CAAC;AAEX;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,qBAAqB;IACrB,oBAAoB;IACpB,0BAA0B;IAC1B,oBAAoB;IACpB,sBAAsB;IACtB,qBAAqB;IACrB,qBAAqB;IACrB,2BAA2B;IAC3B,oBAAoB;IACpB,0BAA0B;IAC1B,qBAAqB;IACrB,sBAAsB;IACtB,sBAAsB;IACtB,gBAAgB;IAChB,YAAY;IACZ,cAAc;IACd,iBAAiB;CACT,CAAC;AAEX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,uBAAuB;CACf,CAAC;AAEX,8EAA8E;AAC9E,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,uBAAuB,CAAU,CAAC;AAqCtE,MAAM,sBAAsB,GAAwB,IAAI,GAAG,CAAC,mBAAmB,CAAC,CAAC;AACjF,MAAM,oBAAoB,GAAwB,IAAI,GAAG,CAAC,iBAAiB,CAAC,CAAC;AAE7E,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,OAAO,sBAAsB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,OAAO,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACzC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export type { StepSpend } from './protocol.js';
|
|
|
5
5
|
export { SPEC_SCHEMA_VERSION } from './spec.js';
|
|
6
6
|
export { CloudFlowError, type CloudConnectionOptions } from './cloud-http.js';
|
|
7
7
|
export { runInCloud, getCloudFlowRun, waitForCloudFlowRun, type CloudFlowSource, type RunInCloudOptions, type CloudRunReceipt, type CloudRunState, } from './cloud-run.js';
|
|
8
|
+
export { downloadCloudPatch, applyCloudPatch, packWorkingTree, patchedPaths, MAX_SYNC_BYTES, type CloudPatch, type PackedTree, } from './cloud-sync.js';
|
|
9
|
+
export { deployToCloud, listCloudDeployments, undeployFromCloud, parseRepository, parseTriggerSource, FLOW_TRIGGER_PROVIDERS, type DeployToCloudInput, type CloudDeployment, type CloudDeploymentSummary, type FlowTriggerSource, type FlowTriggerProvider, } from './cloud-deploy.js';
|
|
8
10
|
export { canonicalize, specHash } from './canonical.js';
|
|
9
11
|
export { compileAndHash, compileSpec, compileYaml, compileYamlToCanonicalJson, kernelToAuthoring, toKernelSpec, CompileError, } from './compile.js';
|
|
10
12
|
export { validateSpec, type ValidationResult } from './validate.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,YAAY,EACV,aAAa,EACb,aAAa,EACb,YAAY,EACZ,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,qBAAqB,EACrB,YAAY,EACZ,QAAQ,EACR,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,SAAS,EACT,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,uBAAuB,EACvB,aAAa,EACb,qBAAqB,EACrB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,sBAAsB,EACtB,WAAW,EACX,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,eAAe,EACf,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,qBAAqB,EACrB,2BAA2B,EAC3B,WAAW,EACX,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEhD,OAAO,EAAE,cAAc,EAAE,KAAK,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EACL,UAAU,EAAE,eAAe,EAAE,mBAAmB,EAChD,KAAK,eAAe,EAAE,KAAK,iBAAiB,EAAE,KAAK,eAAe,EAAE,KAAK,aAAa,GACvF,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,8 @@ export { MODEL_PRICING } from './model-pricing.js';
|
|
|
5
5
|
export { SPEC_SCHEMA_VERSION } from './spec.js';
|
|
6
6
|
export { CloudFlowError } from './cloud-http.js';
|
|
7
7
|
export { runInCloud, getCloudFlowRun, waitForCloudFlowRun, } from './cloud-run.js';
|
|
8
|
+
export { downloadCloudPatch, applyCloudPatch, packWorkingTree, patchedPaths, MAX_SYNC_BYTES, } from './cloud-sync.js';
|
|
9
|
+
export { deployToCloud, listCloudDeployments, undeployFromCloud, parseRepository, parseTriggerSource, FLOW_TRIGGER_PROVIDERS, } from './cloud-deploy.js';
|
|
8
10
|
export { canonicalize, specHash } from './canonical.js';
|
|
9
11
|
export { compileAndHash, compileSpec, compileYaml, compileYamlToCanonicalJson, kernelToAuthoring, toKernelSpec, CompileError, } from './compile.js';
|
|
10
12
|
export { validateSpec } from './validate.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,yEAAyE;AACzE,yBAAyB;AAqDzB,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEhD,OAAO,EAAE,cAAc,EAA+B,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EACL,UAAU,EAAE,eAAe,EAAE,mBAAmB,GAEjD,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,yEAAyE;AACzE,yBAAyB;AAqDzB,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEhD,OAAO,EAAE,cAAc,EAA+B,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EACL,UAAU,EAAE,eAAe,EAAE,mBAAmB,GAEjD,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,kBAAkB,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,GAEnF,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,aAAa,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,eAAe,EAAE,kBAAkB,EAAE,sBAAsB,GAEpH,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EACL,cAAc,EACd,WAAW,EACX,WAAW,EACX,0BAA0B,EAC1B,iBAAiB,EACjB,YAAY,EACZ,YAAY,GACb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAyB,MAAM,eAAe,CAAC;AAEpE,OAAO,EACL,yBAAyB,GAG1B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,SAAS,EACT,gBAAgB,GAUjB,MAAM,gBAAgB,CAAC;AAMxB,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,GAInB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,MAAM,EAA2D,MAAM,UAAU,CAAC;AA6C3F,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEvE,OAAO,EAAE,aAAa,EAA6B,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,WAAW,EAA2B,MAAM,aAAa,CAAC;AAEnE,OAAO,EACL,mBAAmB,EACnB,gBAAgB,GAIjB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,kBAAkB,GAInB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,uBAAuB,GAIxB,MAAM,6BAA6B,CAAC;AAErC,iFAAiF;AACjF,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,kBAAkB,GAInB,MAAM,gBAAgB,CAAC;AAExB,uEAAuE;AACvE,yEAAyE;AACzE,4EAA4E;AAC5E,2BAA2B;AAC3B,OAAO,EACL,iBAAiB,GAGlB,MAAM,yBAAyB,CAAC;AAEjC,2EAA2E;AAC3E,6EAA6E;AAC7E,oEAAoE;AACpE,gCAAgC;AAChC,OAAO,EACL,YAAY,EACZ,cAAc,EACd,aAAa,EACb,OAAO,EACP,aAAa,EACb,oBAAoB,EACpB,wBAAwB,EACxB,eAAe,GAMhB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,UAAU,EAA4C,MAAM,kBAAkB,CAAC;AAExF,OAAO,EAAE,cAAc,EAAsB,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@relayflows/sdk",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.16",
|
|
4
4
|
"description": "TypeScript-first authoring SDK for Relayflows. Compiles specs; speaks the journal protocol.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
46
46
|
"@relayfile/adapter-core": "0.5.24",
|
|
47
47
|
"@relayfile/relay-helpers": "0.4.11",
|
|
48
|
-
"@relayflows/surface": "2.0.
|
|
48
|
+
"@relayflows/surface": "2.0.16",
|
|
49
49
|
"@types/js-yaml": "^4.0.9",
|
|
50
50
|
"ai-hist": "0.4.1",
|
|
51
51
|
"ajv": "^8.17.1",
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { readFile, readdir, stat } from 'node:fs/promises';
|
|
3
|
+
import { join, relative, sep } from 'node:path';
|
|
4
|
+
|
|
5
|
+
function isEnoent(error: unknown): boolean {
|
|
6
|
+
return error instanceof Error && (error as NodeJS.ErrnoException).code === 'ENOENT';
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const SKIPPED_DIR_NAMES = new Set(['node_modules']);
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A recursive snapshot of every regular file under `dir`, keyed by its
|
|
13
|
+
* `dir`-relative POSIX path, valued by a content signature (size + sha256).
|
|
14
|
+
* Content, not mtime: a fast rewrite inside the filesystem's timestamp
|
|
15
|
+
* resolution must still count as a change — the same rule
|
|
16
|
+
* `examples/research/shims/agent-cli.ts`'s `snapshot()` uses for the same
|
|
17
|
+
* "did the agent actually write something" question. Dotfiles/dotdirs
|
|
18
|
+
* (`.git`, the kernel's own `.relayflowd` data dir, editor swap files, ...)
|
|
19
|
+
* are never agent-authored content and are skipped, as is `node_modules`.
|
|
20
|
+
* A missing `dir` (an agent step whose cwd does not exist yet) yields an
|
|
21
|
+
* empty snapshot rather than throwing. Only a vanished path (`ENOENT`) is
|
|
22
|
+
* ever swallowed this way; any other filesystem error (permissions,
|
|
23
|
+
* `ENOTDIR`, `EISDIR`, ...) propagates, because a step whose artifact scan
|
|
24
|
+
* silently dropped files it could not read must not report a successful,
|
|
25
|
+
* incomplete `artifacts` list as if it were the truth.
|
|
26
|
+
*/
|
|
27
|
+
export async function snapshotWorkspaceFiles(dir: string): Promise<Map<string, string>> {
|
|
28
|
+
const out = new Map<string, string>();
|
|
29
|
+
await walk(dir, dir, out);
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function walk(root: string, current: string, out: Map<string, string>): Promise<void> {
|
|
34
|
+
let entries;
|
|
35
|
+
try {
|
|
36
|
+
entries = await readdir(current, { withFileTypes: true });
|
|
37
|
+
} catch (error) {
|
|
38
|
+
if (isEnoent(error)) return;
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
for (const entry of entries) {
|
|
42
|
+
if (entry.name.startsWith('.') || SKIPPED_DIR_NAMES.has(entry.name)) continue;
|
|
43
|
+
const path = join(current, entry.name);
|
|
44
|
+
if (entry.isDirectory()) {
|
|
45
|
+
await walk(root, path, out);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (!entry.isFile()) continue;
|
|
49
|
+
let info;
|
|
50
|
+
try {
|
|
51
|
+
info = await stat(path);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
// A file can vanish between readdir and stat (a CLI's own temp file);
|
|
54
|
+
// that is not an artifact, not a scan failure.
|
|
55
|
+
if (isEnoent(error)) continue;
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
let bytes;
|
|
59
|
+
try {
|
|
60
|
+
bytes = await readFile(path);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
if (isEnoent(error)) continue;
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
out.set(relative(root, path).split(sep).join('/'), `${info.size}:${createHash('sha256').update(bytes).digest('hex')}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** `dir`-relative paths present in `after` that are new or changed since `before`, sorted. */
|
|
70
|
+
export function diffWorkspaceFiles(before: Map<string, string>, after: Map<string, string>): string[] {
|
|
71
|
+
const changed: string[] = [];
|
|
72
|
+
for (const [path, signature] of after) {
|
|
73
|
+
if (before.get(path) !== signature) changed.push(path);
|
|
74
|
+
}
|
|
75
|
+
return changed.sort();
|
|
76
|
+
}
|
|
@@ -12,7 +12,7 @@ import { buildMcpProxy, runMcpEffect } from './authored-mcp.js';
|
|
|
12
12
|
import { AuthoredBudget } from './authored-budget.js';
|
|
13
13
|
import { assertMemoryReachable, authoredMemory, scriptMemoryScope } from './authored-memory.js';
|
|
14
14
|
import { authoredDeterministicRunner, authoredWorkerRunner } from './authored-worker-step.js';
|
|
15
|
-
import { isSurfaceRunCompletionReason } from './authored-step-output.js';
|
|
15
|
+
import { isSurfaceFlowCompletionReason, isSurfaceRunCompletionReason } from './authored-step-output.js';
|
|
16
16
|
import {
|
|
17
17
|
type AgentResult,
|
|
18
18
|
type LlmOptions,
|
|
@@ -111,7 +111,7 @@ type JournalStepUsesStepCompletionReason = Assert<
|
|
|
111
111
|
* authored root, it is not a resumable public runner. The seam is narrow: an
|
|
112
112
|
* flow with an optional budget may await `f.run`, `f.llm`, and `f.agent` steps and must
|
|
113
113
|
* finish with one of the lowered completions — `f.done("success")`,
|
|
114
|
-
* `f.done("needs_human")` or `f.done("
|
|
114
|
+
* `f.done("needs_human")`, `f.done("step_failed")` or `f.done("declined")`. Each step and the terminal marker is
|
|
115
115
|
* a compiled spec submitted through
|
|
116
116
|
* `JournalClient`; values are read back from `step.completed` journal entries.
|
|
117
117
|
* Unsupported headers, verbs, gates, or completion lowering fail closed.
|
|
@@ -328,7 +328,7 @@ export async function executeAuthoredFlow<Input = undefined>(
|
|
|
328
328
|
throw unsupportedVerb('dispatch');
|
|
329
329
|
},
|
|
330
330
|
done(reason) {
|
|
331
|
-
if (
|
|
331
|
+
if (!isSurfaceFlowCompletionReason(reason)) {
|
|
332
332
|
throw new AuthoredFlowExecutionError(
|
|
333
333
|
'unsupported_completion',
|
|
334
334
|
`unknown completion reason: ${String(reason)}`,
|
|
@@ -356,7 +356,7 @@ export async function executeAuthoredFlow<Input = undefined>(
|
|
|
356
356
|
`done("${reason}") is a kernel outcome, not an authored verdict: the kernel `
|
|
357
357
|
+ 'records it when it cancels a run or exhausts its budget, so a flow body '
|
|
358
358
|
+ 'cannot declare it. Use done("step_failed") to declare that the flow\'s own '
|
|
359
|
-
+ 'checks did not pass.',
|
|
359
|
+
+ 'checks did not pass, or done("declined") to deliberately choose not to act.',
|
|
360
360
|
reason,
|
|
361
361
|
);
|
|
362
362
|
}
|
|
@@ -432,7 +432,7 @@ export async function executeAuthoredFlow<Input = undefined>(
|
|
|
432
432
|
// Record the authored verdict as a SUCCESSFUL effect carrying that verdict,
|
|
433
433
|
// not as a fabricated kernel run.completed reason. The marker step reports
|
|
434
434
|
// what the body decided; it is not itself a step that failed. The CLI turns
|
|
435
|
-
// the verdict into the exit code (success 0, needs_human 3, step_failed 1).
|
|
435
|
+
// the verdict into the exit code (success/declined 0, needs_human 3, step_failed 1).
|
|
436
436
|
await lowerDeterministic(`complete-${nextStep}`,
|
|
437
437
|
completionMarker(requestedCompletion), true);
|
|
438
438
|
return Object.freeze({
|
|
@@ -462,7 +462,7 @@ function unsupportedVerb(verb: string): AuthoredFlowExecutionError {
|
|
|
462
462
|
* The completion reasons an authored body may declare and this executor lowers.
|
|
463
463
|
*
|
|
464
464
|
* `FlowCompletionReason` is wider than this on purpose — it is the journal's
|
|
465
|
-
* run vocabulary plus
|
|
465
|
+
* run vocabulary plus authored verdicts — but the two sets drifting silently is
|
|
466
466
|
* exactly what made a type-valid `done("step_failed")` die at runtime as
|
|
467
467
|
* `unsupported_completion`. Every gate that asks "is this a completion this
|
|
468
468
|
* runtime can lower?" now asks this one function, so a reason cannot be
|
|
@@ -473,7 +473,7 @@ function unsupportedVerb(verb: string): AuthoredFlowExecutionError {
|
|
|
473
473
|
* SDK surface. `src/index.ts` deliberately re-exports nothing from this module
|
|
474
474
|
* — keep it that way, or the whole authored seam leaks with them.
|
|
475
475
|
*/
|
|
476
|
-
export const LOWERED_COMPLETIONS = ['success', 'needs_human', 'step_failed'] as const;
|
|
476
|
+
export const LOWERED_COMPLETIONS = ['success', 'needs_human', 'step_failed', 'declined'] as const;
|
|
477
477
|
export type LoweredCompletionReason = (typeof LOWERED_COMPLETIONS)[number];
|
|
478
478
|
|
|
479
479
|
export function isLoweredCompletion(value: unknown): value is LoweredCompletionReason {
|
|
@@ -504,7 +504,7 @@ function assertOperationAllowed(
|
|
|
504
504
|
throw new AuthoredFlowExecutionError(
|
|
505
505
|
'operation_after_completion',
|
|
506
506
|
`flow "${flowName}" called f.${verb} after done()`,
|
|
507
|
-
completion
|
|
507
|
+
isSurfaceRunCompletionReason(completion) ? completion : undefined,
|
|
508
508
|
);
|
|
509
509
|
}
|
|
510
510
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { COMPLETION_REASONS, RUN_COMPLETION_REASONS } from '@relayflows/surface';
|
|
1
|
+
import { COMPLETION_REASONS, RUN_COMPLETION_REASONS, FLOW_COMPLETION_REASONS, type FlowCompletionReason } from '@relayflows/surface';
|
|
2
2
|
import { AuthoredFlowExecutionError } from './authored-flow-error.js';
|
|
3
3
|
import type { JournalClient } from './journal-client.js';
|
|
4
4
|
import type { CompletionReason as ProtocolCompletionReason, RunCompletionReason as ProtocolRunCompletionReason, RunOutcome } from './protocol.js';
|
|
@@ -93,6 +93,11 @@ export function isSurfaceRunCompletionReason(value: unknown): value is ProtocolR
|
|
|
93
93
|
&& (RUN_COMPLETION_REASONS as readonly string[]).includes(value);
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
export function isSurfaceFlowCompletionReason(value: unknown): value is FlowCompletionReason {
|
|
97
|
+
return typeof value === 'string'
|
|
98
|
+
&& (FLOW_COMPLETION_REASONS as readonly string[]).includes(value);
|
|
99
|
+
}
|
|
100
|
+
|
|
96
101
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
97
102
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
98
103
|
}
|