@walkeros/cli 4.7.0 → 4.7.1-next-1791015692826

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/index.js CHANGED
@@ -4,6 +4,9 @@ var __export = (target, all) => {
4
4
  __defProp(target, name, { get: all[name], enumerable: true });
5
5
  };
6
6
 
7
+ // <define:__CLIENT_OPERATION_DIGESTS__>
8
+ var define_CLIENT_OPERATION_DIGESTS_default = [{ op: "GET /api/auth/whoami", usedBy: ["mcp auth", "walkeros auth login", "walkeros auth whoami"], digest: "f8287550f3ac65aa5b290875220f06dd3f48d607ed489b9f0a8f704d3f8f5cfd" }, { op: "POST /api/feedback", usedBy: ["mcp feedback", "walkeros feedback"], digest: "7417108c6ea8d60904b715dfedc1d8b9b597834f7d427df6b9226b36e5eef963" }, { op: "GET /api/health", usedBy: ["mcp diagnostics", "walkeros diagnostics"], digest: "2b3c0883edf4048aca77f4222247929b9045db33d06729502cb5021929d04156" }, { op: "POST /api/oauth/device_authorization", usedBy: ["mcp auth", "walkeros auth login"], digest: "a3e744775b93e7f50ea4021f8a027e656bb90e6f2358c65a35e4c45e16ac3fdd" }, { op: "POST /api/oauth/revoke", usedBy: ["mcp auth", "walkeros auth logout"], digest: "dbc453faaaa748d1129473ccda7b26a4e3267d67c25a8a9fc1da0068837fe154" }, { op: "POST /api/oauth/token", usedBy: ["@walkeros/cli resolveAccessToken", "mcp auth", "walkeros auth login"], digest: "16f5a3146c0a3fff703122a5ff25446bad07a6c37069a9e9a6db6925daa036a0" }, { op: "GET /api/openapi.json", usedBy: ["mcp diagnostics", "mcp resource walkeros://reference/openapi", "walkeros diagnostics"], digest: "dbf34e575af8f757d9a0f967c4565968d1a2d64b57a717fc65c8f81692099f0a" }, { op: "GET /api/packages", usedBy: ["mcp package_search", "mcp resource walkeros://reference/packages", "mcp resource walkeros://schema/{packageName}"], digest: "d9c713eea791e8bae3c606bcd1f0209db2c7050a39b18e96f7d913b7d0752e19" }, { op: "GET /api/projects", usedBy: ["mcp flow_manage", "mcp project_manage", "walkeros projects list"], digest: "1e65fca4cb31ccfc10b9835595ac4ee1f69bd6da14127bcc31d62616dfba7281" }, { op: "POST /api/projects", usedBy: ["mcp project_manage", "walkeros projects create"], digest: "3ab6d76c78d4433f0e0ab85a0a23753c7065bc232bfb30b7cee616a3aef8bec5" }, { op: "DELETE /api/projects/{projectId}", usedBy: ["mcp project_manage", "walkeros projects delete"], digest: "9f725b18812327c57cfbf8d8ed0139353c60ed2eb34024618e1760c2765889ca" }, { op: "GET /api/projects/{projectId}", usedBy: ["mcp project_manage", "walkeros projects get"], digest: "535d11026c7b7ff3b59512c0f68ddeb4e73104d4adab143351c7f9fa1ece6e78" }, { op: "PATCH /api/projects/{projectId}", usedBy: ["mcp project_manage", "walkeros projects update"], digest: "d15d7756dae06372328b43891a89dc839e6eb8587896d19999ff49ec8aa1d19b" }, { op: "GET /api/projects/{projectId}/deployments", usedBy: ["mcp deploy_manage", "walkeros deploy list"], digest: "2b3cc07e4cf1f739f7321b5bf157b91ac300205286a48c4f29dd11269d00f2c0" }, { op: "POST /api/projects/{projectId}/deployments", usedBy: ["walkeros deploy create"], digest: "fa0bcad018a21213f473bd058ef90975b50fd3f978340e36c61acf1d609bab95" }, { op: "DELETE /api/projects/{projectId}/deployments/{deploymentId}", usedBy: ["mcp deploy_manage", "walkeros deploy delete"], digest: "ce119e1743ecfdda590f7fae6bfc5a094c387efcbdaac6eaf9b2b7b0fffac58e" }, { op: "GET /api/projects/{projectId}/deployments/{deploymentId}", usedBy: ["mcp deploy_manage", "walkeros deploy status"], digest: "089bd54697005003c9fb256f853dad2e4431d62cbaa2805d311c6837e498ba2b" }, { op: "GET /api/projects/{projectId}/deployments/{deploymentId}/stream", usedBy: ["mcp deploy_manage", "walkeros deploy start"], digest: "cf27b0c148cfeb3b772f150a9de0359540643b3eeaff8dc373cb865557e24a82" }, { op: "GET /api/projects/{projectId}/flows", usedBy: ["mcp flow_manage", "walkeros flows list"], digest: "ecb58ddbde3808a161bee04d333d4e976e86f46505bacc6d571050a45c6c9ee8" }, { op: "POST /api/projects/{projectId}/flows", usedBy: ["mcp flow_manage", "walkeros flows create"], digest: "bcae723b986165cab63933eda1814a9da984cdfada8fe1a0c9cc01d4554d8372" }, { op: "DELETE /api/projects/{projectId}/flows/{flowId}", usedBy: ["mcp flow_manage", "walkeros flows delete"], digest: "1f164466f6b6058b79e787b0234b42d61274431dd6e29cb8acc23c2706218278" }, { op: "GET /api/projects/{projectId}/flows/{flowId}", usedBy: ["mcp deploy_manage", "mcp flow_bundle", "mcp flow_load", "mcp flow_manage", "mcp flow_simulate", "mcp observe_session", "walkeros deploy create", "walkeros deploy start", "walkeros flows get", "walkeros observe start", "walkeros previews create"], digest: "a8fc246e9b179a7becce56221be27aae649f471aebb639eda34b215c926f21dd" }, { op: "PATCH /api/projects/{projectId}/flows/{flowId}", usedBy: ["mcp flow_manage", "walkeros flows update"], digest: "f9e59060ab31184a3b5906c3346479616101f7793c7a00c35649f08d2f5d6a32" }, { op: "GET /api/projects/{projectId}/flows/{flowId}/deploy", usedBy: ["@walkeros/cli getDeployment"], digest: "8d9229fc0d884a75b1faf06877494e4dd5fa8c77affc7a7bb58d559fbd0c8646" }, { op: "POST /api/projects/{projectId}/flows/{flowId}/deploy", usedBy: ["mcp deploy_manage", "walkeros deploy start"], digest: "ea6922423f14dde427cf37f13f07e3f5f783358ff23fd7464925da068838068e" }, { op: "POST /api/projects/{projectId}/flows/{flowId}/duplicate", usedBy: ["mcp flow_manage", "walkeros flows duplicate"], digest: "b9111138d427419eea46ed590a301373a4c641b19d90ab1566891f5aaaadc231" }, { op: "GET /api/projects/{projectId}/flows/{flowId}/journeys", usedBy: ["mcp flow_manage", "mcp observe_journeys", "mcp observe_session"], digest: "78377e4a5b4b1e4dce9f94813bd3484e78b9520e57c712f963ef98c42516b01c" }, { op: "POST /api/projects/{projectId}/flows/{flowId}/observe-sessions", usedBy: ["mcp observe_session", "walkeros observe start"], digest: "5620b4826736b3aff1c80412d9861d5286304957df59d241e9adff6d101bb032" }, { op: "DELETE /api/projects/{projectId}/flows/{flowId}/observe-sessions/{sessionId}", usedBy: ["mcp observe_session"], digest: "9bdc90811f98a22030ee33bb24e2f270b64733b81e3e4dd3d16cd00620dafb44" }, { op: "GET /api/projects/{projectId}/flows/{flowId}/observe-sessions/{sessionId}", usedBy: ["mcp observe_session", "walkeros observe start"], digest: "ab5e8a2b908391c701c9e0b73813f1eb3bfa5b2a82e82b7009b2559467352491" }, { op: "POST /api/projects/{projectId}/flows/{flowId}/observe-sessions/{sessionId}/heartbeat", usedBy: ["walkeros observe start"], digest: "2b0b74a466c643aac87226c8154a530ce55deb5409a4fb65a4ef9b8aa182cbc7" }, { op: "GET /api/projects/{projectId}/flows/{flowId}/previews", usedBy: ["mcp flow_manage", "walkeros previews list"], digest: "ef72ef8b90676c59c626763f120d6a81910b29e4384f0ac8174f7e12420007c2" }, { op: "POST /api/projects/{projectId}/flows/{flowId}/previews", usedBy: ["mcp flow_manage", "walkeros previews create"], digest: "7239dc554d11983386108825087aa45eb4d0bd38eae87dbac376e68e724c6a8f" }, { op: "DELETE /api/projects/{projectId}/flows/{flowId}/previews/{previewId}", usedBy: ["mcp flow_manage", "walkeros previews delete"], digest: "de9be2358920517321c4e2c59c9ce59f174be0382596037ce36f987233689e51" }, { op: "GET /api/projects/{projectId}/flows/{flowId}/previews/{previewId}", usedBy: ["mcp flow_manage", "walkeros previews get"], digest: "4dbaa7000600aa12d45388511192dabdcd910fad9acedd802fdc68efea4e7bc7" }, { op: "POST /api/projects/{projectId}/flows/{flowId}/previews/{previewId}/grant", usedBy: ["mcp flow_manage", "walkeros previews create"], digest: "4cf5c7ea9363935bd978f858e4bb058c6dd64bb2763cefac9ce07da248605e7f" }, { op: "GET /api/projects/{projectId}/flows/{flowId}/releases", usedBy: ["mcp hub_manage"], digest: "c6ac90c93e07429b53c506292ceda03bfb8873686db76e422f5eed4638f4bee7" }, { op: "PUT /api/projects/{projectId}/flows/{flowId}/releases/annotations", usedBy: ["mcp hub_manage"], digest: "084f638f024a578ab2f401839f10f9554e6d2100ba7d67f1ab2be560616bd044" }, { op: "GET /api/projects/{projectId}/flows/{flowId}/releases/step-history", usedBy: ["mcp hub_manage"], digest: "a0d051814f7e8cc39e00592c16bc92a1afae0b58cd71b9b98ab6c85da4dd04e4" }, { op: "GET /api/projects/{projectId}/flows/{flowId}/releases/{versionId}", usedBy: ["mcp hub_manage"], digest: "d429b1564ca64148c5844e799c5dafc5d864fcf94df62f51174c3825db6a3463" }, { op: "GET /api/projects/{projectId}/flows/{flowId}/secrets", usedBy: ["mcp secret_manage"], digest: "19629983472c4e46b6c97fc8700b35549f38725fd4d7a5f59ddacd6a7bcfc8f2" }, { op: "POST /api/projects/{projectId}/flows/{flowId}/secrets", usedBy: ["mcp secret_manage"], digest: "b9407ce8584d147f84acf2562f1eb7c63c35e7ed93bd275d8c3c2ba3c4a1a8e3" }, { op: "GET /api/projects/{projectId}/flows/{flowId}/secrets/values", usedBy: ["runner"], digest: "0c02c86b0576047e8d986c2829212fef4e7eea5791250188619244bfbcdfb4aa" }, { op: "DELETE /api/projects/{projectId}/flows/{flowId}/secrets/{secretId}", usedBy: ["mcp secret_manage"], digest: "b744bcdb73b204d9aa4e4d3f846552a4154601df27c4fe18045bdb8a09624b84" }, { op: "PUT /api/projects/{projectId}/flows/{flowId}/secrets/{secretId}", usedBy: ["mcp secret_manage"], digest: "5b94004e066746ee7a83b90477db9d2a343361705c2e158df85d74e47085a46a" }, { op: "GET /api/projects/{projectId}/flows/{flowId}/settings/{settingsId}/deploy", usedBy: ["@walkeros/cli getDeployment"], digest: "0ad85a2494f22e9863362a7137d721d970b87ff60fdb41727a76cb4f590c83bc" }, { op: "POST /api/projects/{projectId}/flows/{flowId}/settings/{settingsId}/deploy", usedBy: ["mcp deploy_manage", "walkeros deploy start"], digest: "b6506c543c7e755592b5a6671016c4bae3b3e41cd76c28852297413e1a412e46" }, { op: "GET /api/projects/{projectId}/flows/{flowId}/threads", usedBy: ["mcp hub_manage"], digest: "ae0b8185fa74ba12d99eedacedb53e5801d7485cdf7b1c382334371454f8c323" }, { op: "POST /api/projects/{projectId}/flows/{flowId}/threads", usedBy: ["mcp hub_manage"], digest: "0ee52914274f52641a08b4c2d9da774c971d214929b43abee85d5e657b209144" }, { op: "POST /api/projects/{projectId}/flows/{flowId}/threads/{threadId}/messages", usedBy: ["mcp hub_manage"], digest: "28d8e964962b03c016c909111be0ce570df9bf43f89f0ab1c74b6dd65503eec1" }, { op: "GET /api/projects/{projectId}/frames", usedBy: ["mcp frame_manage"], digest: "c1cecd6354a7071418e709ecbf925a6ae14bb0099459bac786f35877108e29fd" }, { op: "GET /api/projects/{projectId}/frames/{frameId}", usedBy: ["mcp frame_manage"], digest: "98e3373cb23c9851280c505239ff960088d89bea9d922787da812bd7a59d104e" }, { op: "GET /api/projects/{projectId}/knowledge", usedBy: ["mcp hub_manage"], digest: "ca52e4593757c4fede25c41c3bb95e9a3b7476106549752b756860fc35abd1f1" }, { op: "POST /api/projects/{projectId}/runners/heartbeat", usedBy: ["runner"], digest: "96546fffffb32b66db7c5238daa2ba8f549d976f5ffcab2befa639e2eb1df0e1" }, { op: "POST /api/telemetry", usedBy: ["@walkeros/cli telemetry"], digest: "d119e16315ff9df09160d8b36ebc78dec089cb2a726f4a8fd77ff5b693999667" }];
9
+
7
10
  // src/commands/bundle/index.ts
8
11
  import path15 from "path";
9
12
  import fs16 from "fs-extra";
@@ -265,16 +268,425 @@ async function withConfigLock(fn) {
265
268
 
266
269
  // src/core/oauth-client.ts
267
270
  import { z } from "zod";
271
+
272
+ // src/core/client-context.ts
273
+ var context;
274
+ function setClientContext(input) {
275
+ const envType = process.env.WALKEROS_CLIENT_TYPE;
276
+ const type = envType ?? input.type ?? "cli";
277
+ context = { type, version: input.version };
278
+ }
279
+ function getClientContext() {
280
+ return context;
281
+ }
282
+ function resetClientContext() {
283
+ context = void 0;
284
+ }
285
+ function clientContextHeaders() {
286
+ if (!context) return {};
287
+ return {
288
+ "User-Agent": `walkeros-${context.type}/${context.version}`,
289
+ "X-WalkerOS-Client": context.type,
290
+ "X-WalkerOS-Client-Version": context.version
291
+ };
292
+ }
293
+
294
+ // src/core/openapi-subset.ts
295
+ import { createHash } from "crypto";
296
+ var HTTP_METHODS = /* @__PURE__ */ new Set([
297
+ "get",
298
+ "put",
299
+ "post",
300
+ "delete",
301
+ "options",
302
+ "head",
303
+ "patch",
304
+ "trace"
305
+ ]);
306
+ var DOC_KEYWORDS = /* @__PURE__ */ new Set([
307
+ "description",
308
+ "summary",
309
+ "title",
310
+ "example",
311
+ "examples",
312
+ "externalDocs",
313
+ "tags"
314
+ ]);
315
+ var VERBATIM_KEYWORDS = /* @__PURE__ */ new Set([
316
+ "enum",
317
+ "const",
318
+ "default",
319
+ "required",
320
+ "security",
321
+ "mapping",
322
+ "scopes"
323
+ ]);
324
+ var NAME_MAPS = /* @__PURE__ */ new Set([
325
+ "properties",
326
+ "patternProperties",
327
+ "dependentSchemas",
328
+ "$defs",
329
+ "definitions",
330
+ "paths",
331
+ "webhooks",
332
+ "schemas",
333
+ "responses",
334
+ "parameters",
335
+ "requestBodies",
336
+ "headers",
337
+ "securitySchemes",
338
+ "links",
339
+ "callbacks",
340
+ "pathItems",
341
+ "content",
342
+ "encoding",
343
+ "variables"
344
+ ]);
345
+ var DROPPED_TOP_LEVEL = /* @__PURE__ */ new Set([
346
+ "tags",
347
+ "webhooks",
348
+ "externalDocs"
349
+ ]);
350
+ var NOTHING_KEPT = /* @__PURE__ */ new Set();
351
+ function isRecord(value) {
352
+ return value !== null && typeof value === "object" && !Array.isArray(value);
353
+ }
354
+ function isVerbatim(key) {
355
+ return VERBATIM_KEYWORDS.has(key) || key.startsWith("x-");
356
+ }
357
+ function canonicalize(value) {
358
+ if (Array.isArray(value)) return value.map(canonicalize);
359
+ if (isRecord(value)) {
360
+ const result = {};
361
+ for (const key of Object.keys(value).sort()) {
362
+ result[key] = canonicalize(value[key]);
363
+ }
364
+ return result;
365
+ }
366
+ return value;
367
+ }
368
+ function parseOperation(op) {
369
+ const space = op.indexOf(" ");
370
+ const method = space > 0 ? op.slice(0, space).toLowerCase() : "";
371
+ const path23 = op.slice(space + 1);
372
+ if (!HTTP_METHODS.has(method) || !path23.startsWith("/")) {
373
+ throw new Error(`invalid operation: ${op}`);
374
+ }
375
+ return { method, path: path23 };
376
+ }
377
+ function hasOperation(doc, op) {
378
+ const { method, path: path23 } = parseOperation(op);
379
+ if (!isRecord(doc) || !isRecord(doc.paths)) return false;
380
+ const item = doc.paths[path23];
381
+ return isRecord(item) && isRecord(item[method]);
382
+ }
383
+ function stripNode(node) {
384
+ if (Array.isArray(node)) return node.map(stripNode);
385
+ if (!isRecord(node)) return node;
386
+ return stripObject(node, NOTHING_KEPT);
387
+ }
388
+ function stripObject(node, kept) {
389
+ const out = {};
390
+ for (const [key, value] of Object.entries(node)) {
391
+ if (kept.has(key) || isVerbatim(key)) out[key] = value;
392
+ else if (DOC_KEYWORDS.has(key)) continue;
393
+ else if (NAME_MAPS.has(key) && isRecord(value)) {
394
+ out[key] = stripNameMap(value, key === "responses");
395
+ } else out[key] = stripNode(value);
396
+ }
397
+ return out;
398
+ }
399
+ function stripNameMap(map, responses) {
400
+ const out = {};
401
+ for (const [name, node] of Object.entries(map)) {
402
+ out[name] = responses ? stripResponse(node) : stripNode(node);
403
+ }
404
+ return out;
405
+ }
406
+ function stripResponse(node) {
407
+ if (!isRecord(node) || typeof node.$ref === "string") return stripNode(node);
408
+ return { description: "", ...stripObject(node, NOTHING_KEPT) };
409
+ }
410
+ function stripDocument(doc) {
411
+ const out = {};
412
+ for (const [key, value] of Object.entries(doc)) {
413
+ if (DROPPED_TOP_LEVEL.has(key)) continue;
414
+ if (key === "info" && isRecord(value)) {
415
+ out.info = stripObject(value, /* @__PURE__ */ new Set(["title", "version"]));
416
+ } else if (isVerbatim(key)) out[key] = value;
417
+ else if (NAME_MAPS.has(key) && isRecord(value)) {
418
+ out[key] = stripNameMap(value, false);
419
+ } else out[key] = stripNode(value);
420
+ }
421
+ return out;
422
+ }
423
+ function collectRefs(node, refs) {
424
+ if (Array.isArray(node)) {
425
+ for (const item of node) collectRefs(item, refs);
426
+ return;
427
+ }
428
+ if (!isRecord(node)) return;
429
+ for (const [key, value] of Object.entries(node)) {
430
+ if (key === "$ref" && typeof value === "string") refs.add(value);
431
+ else if (NAME_MAPS.has(key) && isRecord(value)) {
432
+ for (const named of Object.values(value)) collectRefs(named, refs);
433
+ } else if (key === "discriminator" && isRecord(value)) {
434
+ const mapping = isRecord(value.mapping) ? value.mapping : {};
435
+ for (const target of Object.values(mapping)) {
436
+ if (typeof target === "string") refs.add(target);
437
+ }
438
+ } else if (!isVerbatim(key)) collectRefs(value, refs);
439
+ }
440
+ }
441
+ function componentOf(ref) {
442
+ const parts = ref.startsWith("#/") ? ref.slice(2).split("/").map((part) => part.replace(/~1/g, "/").replace(/~0/g, "~")) : [];
443
+ if (parts.length < 3 || parts[0] !== "components") {
444
+ throw new Error(`unsupported $ref: ${ref}`);
445
+ }
446
+ return { section: parts[1], name: parts[2] };
447
+ }
448
+ function pruneComponents(components, roots) {
449
+ const referenced = /* @__PURE__ */ new Map();
450
+ const pending = [];
451
+ const queue = (node) => {
452
+ const refs = /* @__PURE__ */ new Set();
453
+ collectRefs(node, refs);
454
+ pending.push(...refs);
455
+ };
456
+ for (const root of roots) queue(root);
457
+ if (isRecord(components.securitySchemes)) queue(components.securitySchemes);
458
+ for (let ref = pending.pop(); ref !== void 0; ref = pending.pop()) {
459
+ const { section, name } = componentOf(ref);
460
+ const names = referenced.get(section) ?? /* @__PURE__ */ new Set();
461
+ if (names.has(name)) continue;
462
+ const entries = components[section];
463
+ if (!isRecord(entries) || !(name in entries)) {
464
+ throw new Error(`$ref target not in input: ${ref}`);
465
+ }
466
+ names.add(name);
467
+ referenced.set(section, names);
468
+ queue(entries[name]);
469
+ }
470
+ const out = {};
471
+ for (const [section, entries] of Object.entries(components)) {
472
+ if (!isRecord(entries)) continue;
473
+ if (section === "securitySchemes") {
474
+ out[section] = entries;
475
+ continue;
476
+ }
477
+ const names = referenced.get(section);
478
+ if (!names) continue;
479
+ const kept = {};
480
+ for (const [name, node] of Object.entries(entries)) {
481
+ if (names.has(name)) kept[name] = node;
482
+ }
483
+ out[section] = kept;
484
+ }
485
+ return Object.keys(out).length > 0 ? out : void 0;
486
+ }
487
+ function pruneToOperations(doc, ops) {
488
+ if (!isRecord(doc) || !isRecord(doc.paths)) {
489
+ throw new Error("input is not an OpenAPI document with paths");
490
+ }
491
+ for (const op of ops) {
492
+ if (!hasOperation(doc, op)) {
493
+ throw new Error(`manifest operation not in input: ${op}`);
494
+ }
495
+ }
496
+ const listed = new Set(
497
+ ops.map((op) => {
498
+ const { method, path: path23 } = parseOperation(op);
499
+ return `${method} ${path23}`;
500
+ })
501
+ );
502
+ const stripped = stripDocument(doc);
503
+ const allPaths = isRecord(stripped.paths) ? stripped.paths : {};
504
+ const paths = {};
505
+ for (const [path23, item] of Object.entries(allPaths)) {
506
+ if (!isRecord(item)) continue;
507
+ const kept = {};
508
+ let operations = 0;
509
+ for (const [key, value] of Object.entries(item)) {
510
+ if (!HTTP_METHODS.has(key)) kept[key] = value;
511
+ else if (listed.has(`${key} ${path23}`)) {
512
+ kept[key] = value;
513
+ operations += 1;
514
+ }
515
+ }
516
+ if (operations > 0) paths[path23] = kept;
517
+ }
518
+ const out = {};
519
+ const roots = [];
520
+ for (const [key, value] of Object.entries(stripped)) {
521
+ if (key === "components") continue;
522
+ out[key] = key === "paths" ? paths : value;
523
+ roots.push(out[key]);
524
+ }
525
+ if (isRecord(stripped.components)) {
526
+ const components = pruneComponents(stripped.components, roots);
527
+ if (components) out.components = components;
528
+ }
529
+ return out;
530
+ }
531
+ function resolveRef(doc, ref) {
532
+ const { section, name } = componentOf(ref);
533
+ const components = isRecord(doc.components) ? doc.components : {};
534
+ const entries = components[section];
535
+ return isRecord(entries) ? entries[name] : void 0;
536
+ }
537
+ function inlineRefs(node, doc, stack) {
538
+ if (Array.isArray(node)) {
539
+ return node.map((item) => inlineRefs(item, doc, stack));
540
+ }
541
+ if (!isRecord(node)) return node;
542
+ const out = {};
543
+ for (const [key, value] of Object.entries(node)) {
544
+ if (key === "$ref" && typeof value === "string" && !stack.includes(value)) {
545
+ out[key] = inlineRefs(resolveRef(doc, value), doc, [...stack, value]);
546
+ } else if (key === "$ref") out[key] = value;
547
+ else if (NAME_MAPS.has(key) && isRecord(value)) {
548
+ const named = {};
549
+ for (const [name, child] of Object.entries(value)) {
550
+ named[name] = inlineRefs(child, doc, stack);
551
+ }
552
+ out[key] = named;
553
+ } else if (isVerbatim(key)) out[key] = value;
554
+ else out[key] = inlineRefs(value, doc, stack);
555
+ }
556
+ return out;
557
+ }
558
+ function operationDigests(doc, ops) {
559
+ const present = ops.filter((op) => hasOperation(doc, op));
560
+ const pruned = pruneToOperations(doc, present);
561
+ const paths = isRecord(pruned.paths) ? pruned.paths : {};
562
+ const digests = {};
563
+ for (const op of present) {
564
+ const { method, path: path23 } = parseOperation(op);
565
+ const item = paths[path23];
566
+ if (!isRecord(item)) continue;
567
+ const subtree = inlineRefs(
568
+ { pathParameters: item.parameters ?? [], operation: item[method] },
569
+ pruned,
570
+ []
571
+ );
572
+ digests[op] = createHash("sha256").update(JSON.stringify(canonicalize(subtree))).digest("hex");
573
+ }
574
+ return digests;
575
+ }
576
+
577
+ // src/core/api-request.ts
578
+ var DEPLOY_TOKEN_MISSING = "No authentication token available. Set WALKEROS_DEPLOY_TOKEN or run walkeros auth login.";
579
+ function operationTarget(op, path23, query) {
580
+ const template = parseOperation(op).path;
581
+ const filled = template.replace(/\{([^}]+)\}/g, (_match, name) => {
582
+ const value = path23?.[name];
583
+ if (value === void 0) {
584
+ throw new Error(`${op}: path parameter ${name} is missing`);
585
+ }
586
+ return encodeURIComponent(String(value));
587
+ });
588
+ const search = new URLSearchParams();
589
+ for (const [key, value] of Object.entries(query ?? {})) {
590
+ if (value === void 0 || value === null) continue;
591
+ for (const item of Array.isArray(value) ? value : [value]) {
592
+ search.append(key, String(item));
593
+ }
594
+ }
595
+ const serialized = search.toString();
596
+ return serialized ? `${filled}?${serialized}` : filled;
597
+ }
598
+ function hasHeader(headers, name) {
599
+ const lower = name.toLowerCase();
600
+ return Object.keys(headers).some((key) => key.toLowerCase() === lower);
601
+ }
602
+ function mergeHeaders(...layers) {
603
+ const merged = {};
604
+ for (const layer of layers) {
605
+ for (const [name, value] of Object.entries(layer)) {
606
+ const lower = name.toLowerCase();
607
+ for (const existing of Object.keys(merged)) {
608
+ if (existing.toLowerCase() === lower) delete merged[existing];
609
+ }
610
+ merged[name] = value;
611
+ }
612
+ }
613
+ return merged;
614
+ }
615
+ function formBody(form) {
616
+ const params = new URLSearchParams();
617
+ for (const [key, value] of Object.entries(form)) {
618
+ if (value !== void 0 && value !== null)
619
+ params.append(key, String(value));
620
+ }
621
+ return params.toString();
622
+ }
623
+ function requestParts(op, init) {
624
+ const method = parseOperation(op).method.toUpperCase();
625
+ const headers = { ...init.headers };
626
+ if (init.form !== void 0) {
627
+ if (!hasHeader(headers, "Content-Type")) {
628
+ headers["Content-Type"] = "application/x-www-form-urlencoded";
629
+ }
630
+ return { method, headers, body: formBody(init.form) };
631
+ }
632
+ if (init.body !== void 0) {
633
+ if (!hasHeader(headers, "Content-Type")) {
634
+ headers["Content-Type"] = "application/json";
635
+ }
636
+ return { method, headers, body: JSON.stringify(init.body) };
637
+ }
638
+ return { method, headers };
639
+ }
640
+ function requestInit(parts, init, headers) {
641
+ const request = {};
642
+ if (parts.method !== "GET") request.method = parts.method;
643
+ if (Object.keys(headers).length > 0) request.headers = headers;
644
+ if (parts.body !== void 0) request.body = parts.body;
645
+ if (init.signal) request.signal = init.signal;
646
+ if (init.redirect) request.redirect = init.redirect;
647
+ return request;
648
+ }
649
+ async function credential(auth) {
650
+ if (auth === "none") return null;
651
+ if (auth === "user") return resolveAccessToken();
652
+ if (auth === "deploy") {
653
+ const token = resolveDeployToken() ?? await resolveAccessToken();
654
+ if (!token) throw new Error(DEPLOY_TOKEN_MISSING);
655
+ return token;
656
+ }
657
+ return auth.token;
658
+ }
659
+ async function apiRequest(op, init = {}) {
660
+ const target = operationTarget(op, init.path, init.query);
661
+ const parts = requestParts(op, init);
662
+ const auth = init.auth ?? "user";
663
+ if (init.baseUrl === void 0 && init.fetch === void 0 && typeof auth === "string") {
664
+ const request = requestInit(parts, init, parts.headers);
665
+ const send2 = auth === "user" ? apiFetch : auth === "deploy" ? deployFetch : publicFetch;
666
+ return Object.keys(request).length > 0 ? send2(target, request) : send2(target);
667
+ }
668
+ const url = `${init.baseUrl ?? resolveAppUrl()}${target}`;
669
+ const token = await credential(auth);
670
+ if (token) requireSecureUrl(url);
671
+ const headers = mergeHeaders(
672
+ clientContextHeaders(),
673
+ parts.headers,
674
+ token ? { Authorization: `Bearer ${token}` } : {}
675
+ );
676
+ const send = init.fetch ?? fetch;
677
+ return send(url, requestInit(parts, init, headers));
678
+ }
679
+ function operationUrl(op, init) {
680
+ return `${init.baseUrl}${operationTarget(op, init.path, init.query)}`;
681
+ }
682
+
683
+ // src/core/oauth-client.ts
268
684
  var CLI_CLIENT_ID = "walkeros-cli";
269
685
  var CLI_SCOPE = "read write offline_access";
270
686
  var DEVICE_CODE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
271
687
  var REFRESH_TIMEOUT_MS = 1e4;
272
688
  var REVOKE_TIMEOUT_MS = 5e3;
273
689
  var DEVICE_AUTHORIZATION_TIMEOUT_MS = 1e4;
274
- var FORM_HEADERS = {
275
- "Content-Type": "application/x-www-form-urlencoded",
276
- Accept: "application/json"
277
- };
278
690
  var DeviceAuthorizationSchema = z.object({
279
691
  device_code: z.string().min(1),
280
692
  user_code: z.string().min(1),
@@ -310,14 +722,15 @@ function describe(response, body) {
310
722
  }
311
723
  return `HTTP ${response.status}`;
312
724
  }
313
- function post(fetchFn, url, form, signal) {
314
- return fetchFn(requireSecureUrl(url), {
315
- method: "POST",
316
- headers: { ...FORM_HEADERS },
317
- body: new URLSearchParams(form).toString(),
725
+ function credentialTransport(appUrl, fetchFn, signal) {
726
+ return {
727
+ auth: "none",
728
+ baseUrl: requireSecureUrl(appUrl),
729
+ fetch: fetchFn,
730
+ headers: { Accept: "application/json" },
318
731
  redirect: "error",
319
732
  ...signal ? { signal } : {}
320
- });
733
+ };
321
734
  }
322
735
  function toTokenSet(body) {
323
736
  const parsed = TokenSchema.safeParse(body);
@@ -331,18 +744,20 @@ function toTokenSet(body) {
331
744
  };
332
745
  }
333
746
  async function startDeviceAuthorization(appUrl, fetchFn = globalThis.fetch) {
334
- const response = await post(
335
- fetchFn,
336
- `${appUrl}/api/oauth/device_authorization`,
337
- {
747
+ const response = await apiRequest("POST /api/oauth/device_authorization", {
748
+ ...credentialTransport(
749
+ appUrl,
750
+ fetchFn,
751
+ AbortSignal.timeout(DEVICE_AUTHORIZATION_TIMEOUT_MS)
752
+ ),
753
+ form: {
338
754
  client_id: CLI_CLIENT_ID,
339
755
  scope: CLI_SCOPE,
340
756
  // RFC 8707. The token comes back bound to the API, so a leaked CLI token
341
757
  // cannot be replayed against the MCP resource.
342
758
  resource: `${appUrl}/api`
343
- },
344
- AbortSignal.timeout(DEVICE_AUTHORIZATION_TIMEOUT_MS)
345
- );
759
+ }
760
+ });
346
761
  const body = await readJson(response);
347
762
  if (!response.ok) throw new Error(describe(response, body));
348
763
  const parsed = DeviceAuthorizationSchema.safeParse(body);
@@ -360,16 +775,14 @@ async function startDeviceAuthorization(appUrl, fetchFn = globalThis.fetch) {
360
775
  async function pollDeviceToken(appUrl, deviceCode, fetchFn = globalThis.fetch, signal) {
361
776
  let response;
362
777
  try {
363
- response = await post(
364
- fetchFn,
365
- `${appUrl}/api/oauth/token`,
366
- {
778
+ response = await apiRequest("POST /api/oauth/token", {
779
+ ...credentialTransport(appUrl, fetchFn, signal),
780
+ form: {
367
781
  grant_type: DEVICE_CODE_GRANT,
368
782
  device_code: deviceCode,
369
783
  client_id: CLI_CLIENT_ID
370
- },
371
- signal
372
- );
784
+ }
785
+ });
373
786
  } catch (error) {
374
787
  if (signal?.aborted) return { status: "pending" };
375
788
  throw error;
@@ -399,16 +812,18 @@ async function pollDeviceToken(appUrl, deviceCode, fetchFn = globalThis.fetch, s
399
812
  }
400
813
  }
401
814
  async function refreshTokens(appUrl, refreshToken, fetchFn = globalThis.fetch) {
402
- const response = await post(
403
- fetchFn,
404
- `${appUrl}/api/oauth/token`,
405
- {
815
+ const response = await apiRequest("POST /api/oauth/token", {
816
+ ...credentialTransport(
817
+ appUrl,
818
+ fetchFn,
819
+ AbortSignal.timeout(REFRESH_TIMEOUT_MS)
820
+ ),
821
+ form: {
406
822
  grant_type: "refresh_token",
407
823
  refresh_token: refreshToken,
408
824
  client_id: CLI_CLIENT_ID
409
- },
410
- AbortSignal.timeout(REFRESH_TIMEOUT_MS)
411
- );
825
+ }
826
+ });
412
827
  const body = await readJson(response);
413
828
  if (!response.ok) {
414
829
  if (errorCode(body) === "invalid_grant") return null;
@@ -418,16 +833,18 @@ async function refreshTokens(appUrl, refreshToken, fetchFn = globalThis.fetch) {
418
833
  }
419
834
  async function revokeRefreshToken(appUrl, refreshToken, fetchFn = globalThis.fetch) {
420
835
  try {
421
- await post(
422
- fetchFn,
423
- `${appUrl}/api/oauth/revoke`,
424
- {
836
+ await apiRequest("POST /api/oauth/revoke", {
837
+ ...credentialTransport(
838
+ appUrl,
839
+ fetchFn,
840
+ AbortSignal.timeout(REVOKE_TIMEOUT_MS)
841
+ ),
842
+ form: {
425
843
  token: refreshToken,
426
844
  token_type_hint: "refresh_token",
427
845
  client_id: CLI_CLIENT_ID
428
- },
429
- AbortSignal.timeout(REVOKE_TIMEOUT_MS)
430
- );
846
+ }
847
+ });
431
848
  } catch {
432
849
  }
433
850
  }
@@ -513,28 +930,6 @@ function requireProjectId() {
513
930
  return projectId;
514
931
  }
515
932
 
516
- // src/core/client-context.ts
517
- var context;
518
- function setClientContext(input) {
519
- const envType = process.env.WALKEROS_CLIENT_TYPE;
520
- const type = envType ?? input.type ?? "cli";
521
- context = { type, version: input.version };
522
- }
523
- function getClientContext() {
524
- return context;
525
- }
526
- function resetClientContext() {
527
- context = void 0;
528
- }
529
- function clientContextHeaders() {
530
- if (!context) return {};
531
- return {
532
- "User-Agent": `walkeros-${context.type}/${context.version}`,
533
- "X-WalkerOS-Client": context.type,
534
- "X-WalkerOS-Client-Version": context.version
535
- };
536
- }
537
-
538
933
  // src/core/http.ts
539
934
  function normalizeHeaders(headers) {
540
935
  if (!headers) return {};
@@ -1060,16 +1455,16 @@ import fs8 from "fs-extra";
1060
1455
  import { getFlowSettings, getPlatform } from "@walkeros/core";
1061
1456
 
1062
1457
  // src/core/content-digest.ts
1063
- import { createHash } from "crypto";
1458
+ import { createHash as createHash2 } from "crypto";
1064
1459
  import path7 from "path";
1065
1460
  import fs7 from "fs-extra";
1066
1461
  var DIGEST_LENGTH = 12;
1067
- function isRecord(value) {
1462
+ function isRecord2(value) {
1068
1463
  return value !== null && typeof value === "object" && !Array.isArray(value);
1069
1464
  }
1070
1465
  function canonicalJson(value) {
1071
1466
  return JSON.stringify(value, (_key, inner) => {
1072
- if (!isRecord(inner)) return inner;
1467
+ if (!isRecord2(inner)) return inner;
1073
1468
  const sorted = {};
1074
1469
  for (const key of Object.keys(inner).sort()) sorted[key] = inner[key];
1075
1470
  return sorted;
@@ -1087,10 +1482,10 @@ function configDigest(flowSettings, flowName) {
1087
1482
  ...config,
1088
1483
  bundle: { ...config.bundle, env: Object.keys(declaredEnv).sort() }
1089
1484
  } : config;
1090
- return createHash("sha256").update(canonicalJson({ ...flowSettings, config: hashedConfig, collector })).digest("hex");
1485
+ return createHash2("sha256").update(canonicalJson({ ...flowSettings, config: hashedConfig, collector })).digest("hex");
1091
1486
  }
1092
1487
  async function hashInstalledDir(dir) {
1093
- const hash = createHash("sha256");
1488
+ const hash = createHash2("sha256");
1094
1489
  for (const rel of await listFiles(dir, "")) {
1095
1490
  const abs = path7.join(dir, rel);
1096
1491
  const stat2 = await fs7.lstat(abs);
@@ -1115,7 +1510,7 @@ async function listFiles(root, rel) {
1115
1510
  return files.sort();
1116
1511
  }
1117
1512
  function releaseDigest(input) {
1118
- return createHash("sha256").update(
1513
+ return createHash2("sha256").update(
1119
1514
  canonicalJson({
1120
1515
  config: input.configDigest,
1121
1516
  versions: input.versions,
@@ -1300,7 +1695,7 @@ import {
1300
1695
  ENV_MARKER_PREFIX,
1301
1696
  SECRET_MARKER_PREFIX as SECRET_MARKER_PREFIX2,
1302
1697
  isPathStepEntry,
1303
- isObject as isObject2
1698
+ isObject as isObject3
1304
1699
  } from "@walkeros/core";
1305
1700
 
1306
1701
  // src/commands/bundle/config-classifier.ts
@@ -2475,6 +2870,63 @@ async function resolveSiblingOrAncestor(consumerDir, depName, root) {
2475
2870
  }
2476
2871
  }
2477
2872
 
2873
+ // src/commands/bundle/build-flags.ts
2874
+ import { isObject as isObject2 } from "@walkeros/core";
2875
+ function carriesState(step) {
2876
+ if (step.state !== void 0) return true;
2877
+ if (step.config === void 0) return false;
2878
+ return !isObject2(step.config) || step.config.state !== void 0;
2879
+ }
2880
+ function flowNeeds(flow) {
2881
+ const steps = [
2882
+ ...Object.values(flow.sources ?? {}),
2883
+ ...Object.values(flow.transformers ?? {}),
2884
+ ...Object.values(flow.destinations ?? {})
2885
+ ];
2886
+ return {
2887
+ observe: flow.config?.observe !== void 0 || flow.collector?.observe !== void 0,
2888
+ stores: Object.keys(flow.stores ?? {}).length > 0,
2889
+ state: steps.some(carriesState)
2890
+ };
2891
+ }
2892
+ function buildFlagDefines(needs) {
2893
+ if (!needs) {
2894
+ return {
2895
+ __WALKEROS_OBSERVE__: "true",
2896
+ __WALKEROS_STORES__: "true",
2897
+ __WALKEROS_STATE__: "true",
2898
+ __WALKEROS_VALIDATE__: "true"
2899
+ };
2900
+ }
2901
+ return {
2902
+ __WALKEROS_OBSERVE__: String(needs.observe),
2903
+ __WALKEROS_STORES__: String(needs.stores),
2904
+ __WALKEROS_STATE__: String(needs.state),
2905
+ __WALKEROS_VALIDATE__: "false"
2906
+ };
2907
+ }
2908
+ var NEEDS_MARKER = "walkeros:needs";
2909
+ function needsMarker(needs) {
2910
+ return `/* ${NEEDS_MARKER} ${JSON.stringify(needs)} */`;
2911
+ }
2912
+ function readNeedsMarker(skeleton) {
2913
+ const match = new RegExp(`/\\* ${NEEDS_MARKER} (\\{[^}]*\\}) \\*/\\s*$`).exec(
2914
+ skeleton
2915
+ );
2916
+ if (!match) return void 0;
2917
+ let parsed;
2918
+ try {
2919
+ parsed = JSON.parse(match[1]);
2920
+ } catch {
2921
+ return void 0;
2922
+ }
2923
+ if (!isObject2(parsed)) return void 0;
2924
+ const { observe, stores, state } = parsed;
2925
+ if (typeof observe !== "boolean" || typeof stores !== "boolean" || typeof state !== "boolean")
2926
+ return void 0;
2927
+ return { observe, stores, state };
2928
+ }
2929
+
2478
2930
  // src/commands/bundle/bundler.ts
2479
2931
  import { getHashServer as getHashServer3 } from "@walkeros/server-core";
2480
2932
 
@@ -2887,9 +3339,12 @@ async function bundleCore(flowSettings, buildOptions, logger, showStats = false,
2887
3339
  const dataDeclaration = `const __configData = ${dataPayload};
2888
3340
  export { __configData };`;
2889
3341
  const banner = buildOptions.platform === "node" ? `import { createRequire } from 'module';const require = createRequire(import.meta.url);
3342
+ ` : "";
3343
+ const needs = buildOptions.platform === "browser" ? `
3344
+ ${needsMarker(flowNeeds(flowSettings))}
2890
3345
  ` : "";
2891
3346
  const esmOutput = `${banner}${compiledCode}
2892
- ${dataDeclaration}`;
3347
+ ${dataDeclaration}${needs}`;
2893
3348
  await fs14.writeFile(outputPath, esmOutput);
2894
3349
  } else {
2895
3350
  const stage2Entry = (buildOptions.platform || "node") === "browser" ? generateWebEntry(stage1Path, dataPayload, {
@@ -2921,7 +3376,8 @@ ${dataDeclaration}`;
2921
3376
  stage2Options.format = "iife";
2922
3377
  stage2Options.define = {
2923
3378
  "process.env.NODE_ENV": '"production"',
2924
- global: "globalThis"
3379
+ global: "globalThis",
3380
+ ...buildFlagDefines(flowNeeds(flowSettings))
2925
3381
  };
2926
3382
  stage2Options.target = resolveTarget(buildOptions);
2927
3383
  } else {
@@ -3259,9 +3715,9 @@ function packageSpecName(spec) {
3259
3715
  return parsePackageSpec(spec).name;
3260
3716
  }
3261
3717
  function readSourceElb(source) {
3262
- if (!isObject2(source.config)) return void 0;
3718
+ if (!isObject3(source.config)) return void 0;
3263
3719
  const settings = source.config.settings;
3264
- if (!isObject2(settings)) return void 0;
3720
+ if (!isObject3(settings)) return void 0;
3265
3721
  return typeof settings.elb === "string" ? settings.elb : void 0;
3266
3722
  }
3267
3723
  function bridgeWindowElb(flow, logger) {
@@ -3289,8 +3745,8 @@ function bridgeWindowElb(flow, logger) {
3289
3745
  }
3290
3746
  const nextSources = { ...sources };
3291
3747
  for (const [id, source] of toForward) {
3292
- const config = isObject2(source.config) ? source.config : {};
3293
- const settings = isObject2(config.settings) ? config.settings : {};
3748
+ const config = isObject3(source.config) ? source.config : {};
3749
+ const settings = isObject3(config.settings) ? config.settings : {};
3294
3750
  nextSources[id] = {
3295
3751
  ...source,
3296
3752
  config: { ...config, settings: { ...settings, elb: windowElb } }
@@ -4404,7 +4860,11 @@ function applyOverrides(config, overrides) {
4404
4860
  // src/commands/push/flow-context.ts
4405
4861
  import path16 from "path";
4406
4862
  import { pathToFileURL } from "url";
4407
- import { JSDOM, VirtualConsole } from "jsdom";
4863
+ import {
4864
+ JSDOM,
4865
+ VirtualConsole,
4866
+ requestInterceptor
4867
+ } from "jsdom";
4408
4868
 
4409
4869
  // src/commands/push/async-drain.ts
4410
4870
  function installTimerInterception(options = {}) {
@@ -4561,7 +5021,10 @@ var DOM_GLOBALS = [
4561
5021
  "Element",
4562
5022
  "HTMLElement",
4563
5023
  "Document",
4564
- "ShadowRoot"
5024
+ "ShadowRoot",
5025
+ "XMLHttpRequest",
5026
+ "location",
5027
+ "self"
4565
5028
  ];
4566
5029
  function exposeDomGlobals(domWindow) {
4567
5030
  const saved = DOM_GLOBALS.map(
@@ -4601,7 +5064,8 @@ async function withFlowContext(options, fn, onError) {
4601
5064
  networkCalls,
4602
5065
  asyncDrain,
4603
5066
  drainPump,
4604
- pageUrl
5067
+ pageUrl,
5068
+ offline
4605
5069
  } = options;
4606
5070
  const startTime = Date.now();
4607
5071
  const g = global;
@@ -4615,7 +5079,7 @@ async function withFlowContext(options, fn, onError) {
4615
5079
  dom = new JSDOM("<!DOCTYPE html><html><body></body></html>", {
4616
5080
  url: pageUrl ?? "http://localhost",
4617
5081
  runScripts: "dangerously",
4618
- resources: "usable",
5082
+ resources: offline ? offlineResources() : "usable",
4619
5083
  virtualConsole
4620
5084
  });
4621
5085
  savedWindow = g.window;
@@ -4745,6 +5209,111 @@ function applyNetworkPolyfills(dom, networkCalls) {
4745
5209
  networkCalls.push({ type: "beacon", url, body, timestamp: Date.now() });
4746
5210
  return true;
4747
5211
  };
5212
+ Object.defineProperty(dom.window, "XMLHttpRequest", {
5213
+ value: createRecordingXhr(dom, networkCalls),
5214
+ configurable: true,
5215
+ writable: true
5216
+ });
5217
+ }
5218
+ function createRecordingXhr(dom, networkCalls) {
5219
+ const PageEvent = dom.window.Event;
5220
+ return class XMLHttpRequest extends dom.window.EventTarget {
5221
+ static UNSENT = 0;
5222
+ static OPENED = 1;
5223
+ static HEADERS_RECEIVED = 2;
5224
+ static LOADING = 3;
5225
+ static DONE = 4;
5226
+ UNSENT = 0;
5227
+ OPENED = 1;
5228
+ HEADERS_RECEIVED = 2;
5229
+ LOADING = 3;
5230
+ DONE = 4;
5231
+ readyState = 0;
5232
+ status = 0;
5233
+ statusText = "";
5234
+ responseType = "";
5235
+ response = "";
5236
+ responseText = "";
5237
+ responseURL = "";
5238
+ timeout = 0;
5239
+ withCredentials = false;
5240
+ onreadystatechange = null;
5241
+ onload = null;
5242
+ onabort = null;
5243
+ onloadend = null;
5244
+ #method = "GET";
5245
+ #url = "";
5246
+ #async = true;
5247
+ #headers = {};
5248
+ #pending = false;
5249
+ open(method, url, async = true) {
5250
+ this.#method = method.toUpperCase();
5251
+ this.#url = String(url);
5252
+ this.#async = async;
5253
+ this.#headers = {};
5254
+ this.#pending = false;
5255
+ this.readyState = 1;
5256
+ }
5257
+ setRequestHeader(name, value) {
5258
+ this.#headers[name] = value;
5259
+ }
5260
+ getResponseHeader() {
5261
+ return null;
5262
+ }
5263
+ getAllResponseHeaders() {
5264
+ return "";
5265
+ }
5266
+ overrideMimeType() {
5267
+ }
5268
+ abort() {
5269
+ const pending = this.#pending;
5270
+ this.#pending = false;
5271
+ if (!pending && this.readyState !== 4) return;
5272
+ this.status = 0;
5273
+ this.statusText = "";
5274
+ if (pending) this.#finish("abort", this.onabort);
5275
+ this.readyState = 0;
5276
+ }
5277
+ send(body) {
5278
+ networkCalls.push({
5279
+ type: "xhr",
5280
+ url: this.#url,
5281
+ method: this.#method,
5282
+ body: body !== void 0 && body !== null ? String(body) : null,
5283
+ headers: { ...this.#headers },
5284
+ timestamp: Date.now()
5285
+ });
5286
+ this.#pending = true;
5287
+ if (this.#async) queueMicrotask(() => this.#complete());
5288
+ else this.#complete();
5289
+ }
5290
+ #complete() {
5291
+ if (!this.#pending) return;
5292
+ this.#pending = false;
5293
+ this.status = 200;
5294
+ this.statusText = "OK";
5295
+ this.responseURL = this.#url;
5296
+ this.#finish("load", this.onload);
5297
+ }
5298
+ #finish(outcome, onOutcome) {
5299
+ this.readyState = 4;
5300
+ const handlers = [
5301
+ ["readystatechange", this.onreadystatechange],
5302
+ [outcome, onOutcome],
5303
+ ["loadend", this.onloadend]
5304
+ ];
5305
+ for (const [type, handler] of handlers) {
5306
+ const event = new PageEvent(type);
5307
+ this.dispatchEvent(event);
5308
+ handler?.call(this, event);
5309
+ }
5310
+ }
5311
+ };
5312
+ }
5313
+ function offlineResources() {
5314
+ return {
5315
+ interceptors: [requestInterceptor(() => new Response("", { status: 200 }))]
5316
+ };
4748
5317
  }
4749
5318
  function cleanupNetworkPolyfills(savedFetch) {
4750
5319
  global.fetch = savedFetch;
@@ -4897,7 +5466,7 @@ function dispatchSimulate(flags) {
4897
5466
  }
4898
5467
 
4899
5468
  // src/commands/push/run.ts
4900
- import { isObject as isObject3 } from "@walkeros/core";
5469
+ import { isObject as isObject4 } from "@walkeros/core";
4901
5470
  function simulationToPushResult(result) {
4902
5471
  return {
4903
5472
  success: !result.error,
@@ -4911,7 +5480,7 @@ var CONSENT_SCOPE_ERROR = "--consent sets the collector's starting consent for a
4911
5480
  var CONSENT_SHAPE_ERROR = "--consent must be a JSON object of booleans";
4912
5481
  var COMMAND_SCOPE_ERROR = "--command applies to destination simulation only.";
4913
5482
  function isConsent(value) {
4914
- return isObject3(value) && Object.values(value).every((granted) => typeof granted === "boolean");
5483
+ return isObject4(value) && Object.values(value).every((granted) => typeof granted === "boolean");
4915
5484
  }
4916
5485
  async function resolveConsent(options) {
4917
5486
  if (options.consentSource === void 0) return options.consent;
@@ -4934,7 +5503,7 @@ async function resolveIngest(options) {
4934
5503
  const loaded = await loadJsonFromSource(options.ingestSource, {
4935
5504
  name: "ingest"
4936
5505
  });
4937
- if (!isObject3(loaded)) throw new Error("--ingest must be a JSON object");
5506
+ if (!isObject4(loaded)) throw new Error("--ingest must be a JSON object");
4938
5507
  return loaded;
4939
5508
  }
4940
5509
  async function runPushCommandWithSecrets(options) {
@@ -5092,22 +5661,22 @@ async function runDestinationSimulationLoop(config, event, destinationIds, optio
5092
5661
  }
5093
5662
 
5094
5663
  // src/commands/push/dev-examples.ts
5095
- function isRecord2(value) {
5664
+ function isRecord3(value) {
5096
5665
  return value !== null && typeof value === "object";
5097
5666
  }
5098
5667
  function selectDevExamples(devModule, exportName) {
5099
- if (!isRecord2(devModule)) return void 0;
5668
+ if (!isRecord3(devModule)) return void 0;
5100
5669
  const map = devModule.exportExamples;
5101
- if (isRecord2(map) && exportName !== void 0) {
5670
+ if (isRecord3(map) && exportName !== void 0) {
5102
5671
  const selected = map[exportName];
5103
- return isRecord2(selected) ? selected : void 0;
5672
+ return isRecord3(selected) ? selected : void 0;
5104
5673
  }
5105
5674
  const examples = devModule.examples;
5106
- return isRecord2(examples) ? examples : void 0;
5675
+ return isRecord3(examples) ? examples : void 0;
5107
5676
  }
5108
5677
  function legacyExportRefusal(devModule, packageExports, packageName, exportName) {
5109
5678
  if (exportName === void 0) return void 0;
5110
- if (isRecord2(devModule) && isRecord2(devModule.exportExamples))
5679
+ if (isRecord3(devModule) && isRecord3(devModule.exportExamples))
5111
5680
  return void 0;
5112
5681
  if (packageExports) {
5113
5682
  const declared = packageExports[packageName];
@@ -5155,11 +5724,11 @@ function resolveExportName(flow, kind, id) {
5155
5724
  }
5156
5725
 
5157
5726
  // src/commands/push/index.ts
5158
- function isRecord3(value) {
5727
+ function isRecord4(value) {
5159
5728
  return value !== null && typeof value === "object";
5160
5729
  }
5161
5730
  function isFlowJson(value) {
5162
- return isRecord3(value) && isRecord3(value.flows);
5731
+ return isRecord4(value) && isRecord4(value.flows);
5163
5732
  }
5164
5733
  function isString(value) {
5165
5734
  return typeof value === "string";
@@ -5177,9 +5746,9 @@ function getDevEnv(devModule, exportName) {
5177
5746
  const examples = selectDevExamples(devModule, exportName);
5178
5747
  if (!examples || !("env" in examples)) return void 0;
5179
5748
  const env = examples.env;
5180
- if (!isRecord3(env)) return void 0;
5749
+ if (!isRecord4(env)) return void 0;
5181
5750
  const result = {};
5182
- if ("push" in env && isRecord3(env.push)) result.push = env.push;
5751
+ if ("push" in env && isRecord4(env.push)) result.push = env.push;
5183
5752
  if ("simulation" in env && isStringArray(env.simulation))
5184
5753
  result.simulation = env.simulation;
5185
5754
  return result;
@@ -5187,14 +5756,14 @@ function getDevEnv(devModule, exportName) {
5187
5756
  async function applyStoreMockEnvs(flowConfig, flowSettings, devExports) {
5188
5757
  const unmocked = [];
5189
5758
  const stores = flowConfig.stores;
5190
- if (!isRecord3(stores)) return unmocked;
5759
+ if (!isRecord4(stores)) return unmocked;
5191
5760
  for (const [storeId, storeDef] of Object.entries(stores)) {
5192
5761
  const packageName = flowSettings.stores?.[storeId]?.package;
5193
5762
  const loadDev = packageName ? devExports?.[packageName] : void 0;
5194
5763
  const devModule = typeof loadDev === "function" ? await loadDev() : void 0;
5195
5764
  const { exportName } = resolveExportName(flowSettings, "store", storeId);
5196
5765
  const push2 = getDevEnv(devModule, exportName)?.push;
5197
- if (!push2 || !isRecord3(storeDef)) {
5766
+ if (!push2 || !isRecord4(storeDef)) {
5198
5767
  unmocked.push(storeId);
5199
5768
  continue;
5200
5769
  }
@@ -5345,7 +5914,7 @@ function formatPushResult(result, options = {}) {
5345
5914
  const lines = [];
5346
5915
  lines.push(`success: ${result.success}`);
5347
5916
  if (result.success) {
5348
- const elbResult = isRecord3(result.elbResult) ? result.elbResult : void 0;
5917
+ const elbResult = isRecord4(result.elbResult) ? result.elbResult : void 0;
5349
5918
  if (elbResult) {
5350
5919
  if (typeof elbResult.id === "string")
5351
5920
  lines.push(` Event ID: ${elbResult.id}`);
@@ -5538,9 +6107,9 @@ function resolvePageUrl(input, pageUrl) {
5538
6107
  return parsed.href;
5539
6108
  }
5540
6109
  function triggerUrl(input) {
5541
- if (!isRecord3(input) || !isRecord3(input.trigger)) return void 0;
6110
+ if (!isRecord4(input) || !isRecord4(input.trigger)) return void 0;
5542
6111
  const { options } = input.trigger;
5543
- return isRecord3(options) && isString(options.url) ? options.url : void 0;
6112
+ return isRecord4(options) && isString(options.url) ? options.url : void 0;
5544
6113
  }
5545
6114
  function isSourceInit(value) {
5546
6115
  return typeof value === "function";
@@ -5628,6 +6197,7 @@ async function simulateSource(configOrPath, input, options) {
5628
6197
  logger,
5629
6198
  snapshotCode,
5630
6199
  networkCalls,
6200
+ offline: true,
5631
6201
  pageUrl
5632
6202
  },
5633
6203
  async (module) => {
@@ -5666,14 +6236,15 @@ async function simulateSource(configOrPath, input, options) {
5666
6236
  `Stores without a mock env run as configured: ${unmockedStores.join(", ")}`
5667
6237
  );
5668
6238
  const wiredSources = flowConfig.sources;
5669
- const wiredSource = isRecord3(wiredSources) ? wiredSources[options.sourceId] : void 0;
5670
- const source = isRecord3(
6239
+ const wiredSource = isRecord4(wiredSources) ? wiredSources[options.sourceId] : void 0;
6240
+ const source = isRecord4(
5671
6241
  wiredSource
5672
6242
  ) ? {
5673
6243
  ...wiredSource,
5674
- ...isRecord3(wiredSource.config) ? { config: { ...wiredSource.config } } : {}
6244
+ ...isRecord4(wiredSource.config) ? { config: { ...wiredSource.config } } : {}
5675
6245
  } : void 0;
5676
6246
  flowConfig.sources = source ? { [options.sourceId]: source } : {};
6247
+ if (flowConfig.destinations) flowConfig.destinations = {};
5677
6248
  const commandCalls = [];
5678
6249
  if (source && isSourceInit(source.code))
5679
6250
  source.code = recordSourceCommands(source.code, commandCalls);
@@ -5685,7 +6256,7 @@ async function simulateSource(configOrPath, input, options) {
5685
6256
  simulation: devEnv.simulation
5686
6257
  });
5687
6258
  source.env = {
5688
- ...isRecord3(source.env) ? source.env : {},
6259
+ ...isRecord4(source.env) ? source.env : {},
5689
6260
  ...wrappedEnv
5690
6261
  };
5691
6262
  trackedCalls = calls;
@@ -5820,7 +6391,8 @@ async function simulateTransformer(configOrPath, event, options) {
5820
6391
  platform: prepared.platform,
5821
6392
  logger,
5822
6393
  snapshotCode,
5823
- networkCalls
6394
+ networkCalls,
6395
+ offline: true
5824
6396
  },
5825
6397
  async (module) => {
5826
6398
  const flowConfig = module.wireConfig(
@@ -5967,7 +6539,8 @@ async function simulateCollector(configOrPath, event, options) {
5967
6539
  platform: prepared.platform,
5968
6540
  logger,
5969
6541
  snapshotCode,
5970
- networkCalls
6542
+ networkCalls,
6543
+ offline: true
5971
6544
  },
5972
6545
  async (module) => {
5973
6546
  const flowConfig = module.wireConfig(
@@ -6036,10 +6609,10 @@ async function simulateCollector(configOrPath, event, options) {
6036
6609
  }
6037
6610
  }
6038
6611
  function isConsentRecord(value) {
6039
- return isRecord3(value) && Object.values(value).every((granted) => typeof granted === "boolean");
6612
+ return isRecord4(value) && Object.values(value).every((granted) => typeof granted === "boolean");
6040
6613
  }
6041
6614
  function pendingRequire(definition) {
6042
- if (!isRecord3(definition) || !isRecord3(definition.config)) return [];
6615
+ if (!isRecord4(definition) || !isRecord4(definition.config)) return [];
6043
6616
  const { require: require2 } = definition.config;
6044
6617
  return isStringArray(require2) ? require2 : [];
6045
6618
  }
@@ -6102,23 +6675,24 @@ async function simulateDestination(configOrPath, event, options) {
6102
6675
  platform: prepared.platform,
6103
6676
  logger,
6104
6677
  snapshotCode,
6105
- networkCalls
6678
+ networkCalls,
6679
+ offline: true
6106
6680
  },
6107
6681
  async (module) => {
6108
6682
  const flowConfig = module.wireConfig(
6109
6683
  options.data ?? module.__configData ?? void 0
6110
6684
  );
6111
6685
  const wiredDestinations = flowConfig.destinations;
6112
- const wiredTarget = isRecord3(wiredDestinations) ? wiredDestinations[options.destinationId] : void 0;
6113
- if (!isRecord3(wiredTarget)) {
6114
- const available = isRecord3(wiredDestinations) ? Object.keys(wiredDestinations).join(", ") : "";
6686
+ const wiredTarget = isRecord4(wiredDestinations) ? wiredDestinations[options.destinationId] : void 0;
6687
+ if (!isRecord4(wiredTarget)) {
6688
+ const available = isRecord4(wiredDestinations) ? Object.keys(wiredDestinations).join(", ") : "";
6115
6689
  throw new Error(
6116
6690
  `Destination "${options.destinationId}" not found in collector. Available: ${available || "none"}`
6117
6691
  );
6118
6692
  }
6119
6693
  const target = {
6120
6694
  ...wiredTarget,
6121
- config: isRecord3(wiredTarget.config) ? { ...wiredTarget.config } : {}
6695
+ config: isRecord4(wiredTarget.config) ? { ...wiredTarget.config } : {}
6122
6696
  };
6123
6697
  flowConfig.destinations = { [options.destinationId]: target };
6124
6698
  if (flowConfig.sources) flowConfig.sources = {};
@@ -6158,7 +6732,7 @@ async function simulateDestination(configOrPath, event, options) {
6158
6732
  );
6159
6733
  }
6160
6734
  const destConfig = target.config;
6161
- if (isRecord3(destConfig)) {
6735
+ if (isRecord4(destConfig)) {
6162
6736
  destConfig.env = devEnv.push;
6163
6737
  }
6164
6738
  if (devEnv.simulation?.length) {
@@ -6167,7 +6741,7 @@ async function simulateDestination(configOrPath, event, options) {
6167
6741
  simulation: devEnv.simulation
6168
6742
  };
6169
6743
  const { wrappedEnv, calls } = wrapEnv(combined);
6170
- if (isRecord3(destConfig)) destConfig.env = wrappedEnv;
6744
+ if (isRecord4(destConfig)) destConfig.env = wrappedEnv;
6171
6745
  trackedCalls = calls;
6172
6746
  }
6173
6747
  }
@@ -6257,10 +6831,10 @@ async function simulateDestination(configOrPath, event, options) {
6257
6831
  import * as fs20 from "fs";
6258
6832
  import * as path20 from "path";
6259
6833
  import chalk2 from "chalk";
6260
- import { isObject as isObject9 } from "@walkeros/core";
6834
+ import { isObject as isObject10 } from "@walkeros/core";
6261
6835
 
6262
6836
  // src/commands/validate/validators/contract.ts
6263
- import { isObject as isObject4 } from "@walkeros/core";
6837
+ import { isObject as isObject5 } from "@walkeros/core";
6264
6838
  var SECTION_KEYS = ["globals", "context", "custom", "user", "consent"];
6265
6839
  var KNOWN_KEYS = /* @__PURE__ */ new Set([
6266
6840
  "extend",
@@ -6310,7 +6884,7 @@ function validateContract(input) {
6310
6884
  const keys = Object.keys(obj);
6311
6885
  const unknownKeys = keys.filter((k) => !KNOWN_KEYS.has(k));
6312
6886
  const hasKnownKey = keys.some((k) => KNOWN_KEYS.has(k));
6313
- const objectValuedUnknown = unknownKeys.filter((k) => isObject4(obj[k]));
6887
+ const objectValuedUnknown = unknownKeys.filter((k) => isObject5(obj[k]));
6314
6888
  if (!hasKnownKey && objectValuedUnknown.length > 0) {
6315
6889
  errors.push({
6316
6890
  path: name,
@@ -6333,7 +6907,7 @@ function validateContract(input) {
6333
6907
  code: "INVALID_TAGGING"
6334
6908
  });
6335
6909
  }
6336
- if (obj.schema !== void 0 && !isObject4(obj.schema)) {
6910
+ if (obj.schema !== void 0 && !isObject5(obj.schema)) {
6337
6911
  errors.push({
6338
6912
  path: `${name}.schema`,
6339
6913
  message: "schema must be a JSON Schema object",
@@ -6405,7 +6979,7 @@ function validateContract(input) {
6405
6979
  }
6406
6980
  chain.push(current);
6407
6981
  const entry = contracts[current];
6408
- current = isObject4(entry) && typeof entry.extend === "string" ? entry.extend : "";
6982
+ current = isObject5(entry) && typeof entry.extend === "string" ? entry.extend : "";
6409
6983
  }
6410
6984
  }
6411
6985
  return {
@@ -6476,7 +7050,7 @@ import {
6476
7050
  ENV_MARKER_PREFIX as ENV_MARKER_PREFIX3,
6477
7051
  getByPath,
6478
7052
  getRouteGraph,
6479
- isObject as isObject7,
7053
+ isObject as isObject8,
6480
7054
  REF_CONTRACT,
6481
7055
  resolveContracts,
6482
7056
  validateStepEntry
@@ -6487,9 +7061,9 @@ import {
6487
7061
  } from "@walkeros/transformer-validate";
6488
7062
 
6489
7063
  // src/commands/validate/scope.ts
6490
- import { isObject as isObject5 } from "@walkeros/core";
7064
+ import { isObject as isObject6 } from "@walkeros/core";
6491
7065
  function isFlowJson2(value) {
6492
- return isObject5(value) && "version" in value && isObject5(value.flows);
7066
+ return isObject6(value) && "version" in value && isObject6(value.flows);
6493
7067
  }
6494
7068
  var ENTRY_SECTIONS = [
6495
7069
  "sources",
@@ -6501,8 +7075,8 @@ function isEntrySection(value) {
6501
7075
  return ENTRY_SECTIONS.some((section) => section === value);
6502
7076
  }
6503
7077
  function resolveScope(config, options = {}) {
6504
- const flowsValue = isObject5(config) ? config.flows : void 0;
6505
- const flowMap = isObject5(flowsValue) ? flowsValue : {};
7078
+ const flowsValue = isObject6(config) ? config.flows : void 0;
7079
+ const flowMap = isObject6(flowsValue) ? flowsValue : {};
6506
7080
  const allFlows = Object.keys(flowMap);
6507
7081
  let flows = allFlows;
6508
7082
  if (options.flow !== void 0) {
@@ -6570,12 +7144,12 @@ function resolveScope(config, options = {}) {
6570
7144
  const entries = [];
6571
7145
  for (const flow of flows) {
6572
7146
  const flowValue = flowMap[flow];
6573
- if (!isObject5(flowValue)) continue;
7147
+ if (!isObject6(flowValue)) continue;
6574
7148
  for (const candidate of sections) {
6575
7149
  const sectionValue = flowValue[candidate];
6576
- if (!isObject5(sectionValue)) continue;
7150
+ if (!isObject6(sectionValue)) continue;
6577
7151
  const entry = sectionValue[key];
6578
- if (isObject5(entry))
7152
+ if (isObject6(entry))
6579
7153
  entries.push({ flow, section: candidate, key, entry });
6580
7154
  }
6581
7155
  }
@@ -6677,12 +7251,12 @@ import {
6677
7251
  ENV_MARKER_PREFIX as ENV_MARKER_PREFIX2,
6678
7252
  fetchPackage,
6679
7253
  getErrorMessage as getErrorMessage3,
6680
- isObject as isObject6,
7254
+ isObject as isObject7,
6681
7255
  REF_CODE_PREFIX,
6682
7256
  REF_STORE,
6683
7257
  SECRET_MARKER_PREFIX as SECRET_MARKER_PREFIX3
6684
7258
  } from "@walkeros/core";
6685
- var CLIENT_HEADER = "walkeros-cli/4.7.0";
7259
+ var CLIENT_HEADER = "walkeros-cli/4.7.1-next-1791015692826";
6686
7260
  function createSettingsContext(configDir) {
6687
7261
  return { configDir, cache: /* @__PURE__ */ new Map(), compiled: /* @__PURE__ */ new Map() };
6688
7262
  }
@@ -6693,7 +7267,7 @@ function selectSettingsSchema(pkg, packageLabel, exportName) {
6693
7267
  pkg.exportSchemas,
6694
7268
  exportName
6695
7269
  ) ? pkg.exportSchemas[exportName] : void 0;
6696
- if (!isObject6(entry))
7270
+ if (!isObject7(entry))
6697
7271
  return {
6698
7272
  ok: false,
6699
7273
  reason: `${packageLabel} has no export "${exportName}"`
@@ -6721,7 +7295,7 @@ function valueAt(root, segments) {
6721
7295
  let current = root;
6722
7296
  for (const segment of segments) {
6723
7297
  if (Array.isArray(current)) current = current[Number(segment)];
6724
- else if (isObject6(current)) current = current[segment];
7298
+ else if (isObject7(current)) current = current[segment];
6725
7299
  else return void 0;
6726
7300
  }
6727
7301
  return current;
@@ -6736,7 +7310,7 @@ function prepareSettings(settings) {
6736
7310
  const walk = (value, segments) => {
6737
7311
  if (Array.isArray(value))
6738
7312
  return value.map((item, index) => walk(item, [...segments, `${index}`]));
6739
- if (isObject6(value))
7313
+ if (isObject7(value))
6740
7314
  return Object.fromEntries(
6741
7315
  Object.entries(value).map(([key, item]) => [
6742
7316
  key,
@@ -6781,11 +7355,11 @@ function isUnder(segments, prefix) {
6781
7355
  return prefix.every((segment, index) => segments[index] === segment);
6782
7356
  }
6783
7357
  function bundlePin(rawFlow, name) {
6784
- const config = isObject6(rawFlow) ? rawFlow.config : void 0;
6785
- const bundle2 = isObject6(config) ? config.bundle : void 0;
6786
- const packages = isObject6(bundle2) ? bundle2.packages : void 0;
6787
- const pin = isObject6(packages) ? packages[name] : void 0;
6788
- if (!isObject6(pin)) return {};
7358
+ const config = isObject7(rawFlow) ? rawFlow.config : void 0;
7359
+ const bundle2 = isObject7(config) ? config.bundle : void 0;
7360
+ const packages = isObject7(bundle2) ? bundle2.packages : void 0;
7361
+ const pin = isObject7(packages) ? packages[name] : void 0;
7362
+ if (!isObject7(pin)) return {};
6789
7363
  return {
6790
7364
  ...typeof pin.version === "string" ? { version: pin.version } : {},
6791
7365
  ...typeof pin.path === "string" ? { path: pin.path } : {}
@@ -6814,15 +7388,15 @@ function readLocalSchema(source, configDir) {
6814
7388
  const meta = readJson2(file);
6815
7389
  const pkgFile = path19.join(root, "package.json");
6816
7390
  const pkg = fs19.existsSync(pkgFile) ? readJson2(pkgFile) : void 0;
6817
- const schemas6 = isObject6(meta) ? meta.schemas : void 0;
6818
- const exportSchemas = isObject6(meta) ? meta.exportSchemas : void 0;
6819
- const declared = isObject6(meta) && isObject6(meta.$meta) ? meta.$meta.exports : void 0;
6820
- const version = isObject6(pkg) && typeof pkg.version === "string" ? pkg.version : void 0;
7391
+ const schemas6 = isObject7(meta) ? meta.schemas : void 0;
7392
+ const exportSchemas = isObject7(meta) ? meta.exportSchemas : void 0;
7393
+ const declared = isObject7(meta) && isObject7(meta.$meta) ? meta.$meta.exports : void 0;
7394
+ const version = isObject7(pkg) && typeof pkg.version === "string" ? pkg.version : void 0;
6821
7395
  return {
6822
7396
  ...version ? { version } : {},
6823
- settings: isObject6(schemas6) ? schemas6.settings : void 0,
6824
- ...isObject6(exportSchemas) ? { exportSchemas } : {},
6825
- ...isObject6(declared) ? { exports: Object.keys(declared) } : {}
7397
+ settings: isObject7(schemas6) ? schemas6.settings : void 0,
7398
+ ...isObject7(exportSchemas) ? { exportSchemas } : {},
7399
+ ...isObject7(declared) ? { exports: Object.keys(declared) } : {}
6826
7400
  };
6827
7401
  }
6828
7402
  async function loadSchema(source, context2) {
@@ -6846,7 +7420,7 @@ async function loadSchema(source, context2) {
6846
7420
  };
6847
7421
  }
6848
7422
  function compileSettings(settings) {
6849
- if (!isObject6(settings)) return void 0;
7423
+ if (!isObject7(settings)) return void 0;
6850
7424
  const ajv = new Ajv({ allErrors: true, validateFormats: false });
6851
7425
  try {
6852
7426
  return { ok: true, validate: ajv.compile(settings) };
@@ -6950,7 +7524,7 @@ async function checkStepSettings(target, resolvedFlow, rawFlow, check, context2)
6950
7524
  }
6951
7525
  const validate2 = compiled.validate;
6952
7526
  const step = stepOf(resolvedFlow, target.section, target.key);
6953
- const config = isObject6(step?.config) ? step.config : {};
7527
+ const config = isObject7(step?.config) ? step.config : {};
6954
7528
  const prepared = prepareSettings(config.settings ?? {});
6955
7529
  const base = `${at}.config.settings`;
6956
7530
  for (const { segments, reference } of prepared.deferred) {
@@ -7029,9 +7603,9 @@ async function validateFlowWithPackages(input, options = {}) {
7029
7603
  continue;
7030
7604
  }
7031
7605
  for (const section of ENTRY_SECTIONS) {
7032
- const steps = isObject7(rawFlow[section]) ? rawFlow[section] : {};
7606
+ const steps = isObject8(rawFlow[section]) ? rawFlow[section] : {};
7033
7607
  for (const [key, entry] of Object.entries(steps)) {
7034
- if (!isObject7(entry) || entry.package === void 0) continue;
7608
+ if (!isObject8(entry) || entry.package === void 0) continue;
7035
7609
  const target = { flow: name, section, key, entry };
7036
7610
  pending.push(
7037
7611
  checkStepSettings(
@@ -7090,9 +7664,9 @@ function runFlowChecks(input, options) {
7090
7664
  };
7091
7665
  }
7092
7666
  errors.push(...scope.errors);
7093
- const config = isObject7(input) ? input : {};
7667
+ const config = isObject8(input) ? input : {};
7094
7668
  const flowsValue = config.flows;
7095
- const flows = isObject7(flowsValue) ? flowsValue : void 0;
7669
+ const flows = isObject8(flowsValue) ? flowsValue : void 0;
7096
7670
  const allFlows = scope.allFlows;
7097
7671
  const inScope = (path23) => {
7098
7672
  const flow = flowOfPath(path23, allFlows);
@@ -7130,13 +7704,13 @@ function runFlowChecks(input, options) {
7130
7704
  checks.push("flow:steps");
7131
7705
  for (const flowName of scope.flows) {
7132
7706
  const flowValue = flows?.[flowName];
7133
- if (!isObject7(flowValue)) continue;
7707
+ if (!isObject8(flowValue)) continue;
7134
7708
  const transformersValue = flowValue.transformers;
7135
- if (isObject7(transformersValue)) {
7709
+ if (isObject8(transformersValue)) {
7136
7710
  for (const [name, transformerValue] of Object.entries(
7137
7711
  transformersValue
7138
7712
  )) {
7139
- if (!isObject7(transformerValue)) continue;
7713
+ if (!isObject8(transformerValue)) continue;
7140
7714
  const result2 = validateStepEntry(transformerValue, "Transformer");
7141
7715
  if (!result2.ok) {
7142
7716
  errors.push({
@@ -7149,9 +7723,9 @@ function runFlowChecks(input, options) {
7149
7723
  }
7150
7724
  for (const [section, kind] of OPEN_STEP_KINDS) {
7151
7725
  const steps = flowValue[section];
7152
- if (!isObject7(steps)) continue;
7726
+ if (!isObject8(steps)) continue;
7153
7727
  for (const [name, step] of Object.entries(steps)) {
7154
- if (!isObject7(step)) continue;
7728
+ if (!isObject8(step)) continue;
7155
7729
  const at = `flows.${flowName}.${section}.${name}`;
7156
7730
  for (const key of unknownStepKeys(step, kind)) {
7157
7731
  warnings.push({
@@ -7180,15 +7754,15 @@ function runFlowChecks(input, options) {
7180
7754
  let totalPackageCount = 0;
7181
7755
  for (const flowName of scope.flows) {
7182
7756
  const flowValue = flows?.[flowName];
7183
- if (!isObject7(flowValue)) continue;
7757
+ if (!isObject8(flowValue)) continue;
7184
7758
  const flowConfig = flowValue.config;
7185
- if (!isObject7(flowConfig)) continue;
7759
+ if (!isObject8(flowConfig)) continue;
7186
7760
  const bundle2 = flowConfig.bundle;
7187
- if (!isObject7(bundle2)) continue;
7761
+ if (!isObject8(bundle2)) continue;
7188
7762
  const packages = bundle2.packages;
7189
- if (!isObject7(packages)) continue;
7763
+ if (!isObject8(packages)) continue;
7190
7764
  for (const [pkgName, pkgConfigValue] of Object.entries(packages)) {
7191
- if (!isObject7(pkgConfigValue)) continue;
7765
+ if (!isObject8(pkgConfigValue)) continue;
7192
7766
  if (!pkgConfigValue.version && !pkgConfigValue.path) {
7193
7767
  warnings.push({
7194
7768
  path: `flows.${flowName}.config.bundle.packages.${pkgName}`,
@@ -7275,13 +7849,13 @@ function runFlowChecks(input, options) {
7275
7849
  warnings,
7276
7850
  options.strict === true,
7277
7851
  skipped,
7278
- isObject7(resolvedConfig) && isObject7(resolvedConfig.settings) ? resolvedConfig.settings : void 0
7852
+ isObject8(resolvedConfig) && isObject8(resolvedConfig.settings) ? resolvedConfig.settings : void 0
7279
7853
  );
7280
7854
  }
7281
7855
  for (const [destName, dest] of Object.entries(flow.destinations || {})) {
7282
- if (!isObject7(dest.config)) continue;
7856
+ if (!isObject8(dest.config)) continue;
7283
7857
  const mapping = dest.config.mapping;
7284
- if (!isObject7(mapping)) continue;
7858
+ if (!isObject8(mapping)) continue;
7285
7859
  for (const key of Object.keys(mapping)) {
7286
7860
  if (key.includes(".") && !key.includes(" ")) {
7287
7861
  const parts = key.split(".");
@@ -7449,21 +8023,21 @@ function isStepOut(value) {
7449
8023
  return Array.isArray(value) && value.every((entry) => Array.isArray(entry) && typeof entry[0] === "string");
7450
8024
  }
7451
8025
  function returnedEvents(value) {
7452
- if (isObject7(value)) return [isObject7(value.event) ? value.event : value];
8026
+ if (isObject8(value)) return [isObject8(value.event) ? value.event : value];
7453
8027
  if (Array.isArray(value)) return value.flatMap(returnedEvents);
7454
8028
  return [];
7455
8029
  }
7456
8030
  function outEvents(out) {
7457
8031
  if (isStepOut(out)) {
7458
8032
  return out.flatMap(([head, first]) => {
7459
- if (head === "elb") return isObject7(first) ? [first] : [];
8033
+ if (head === "elb") return isObject8(first) ? [first] : [];
7460
8034
  if (head === "return") return returnedEvents(first);
7461
8035
  return [];
7462
8036
  });
7463
8037
  }
7464
8038
  if (Array.isArray(out) || typeof out === "string")
7465
8039
  return out.length > 0 ? [out] : [];
7466
- return isObject7(out) && Object.keys(out).length > 0 ? [out] : [];
8040
+ return isObject8(out) && Object.keys(out).length > 0 ? [out] : [];
7467
8041
  }
7468
8042
  function hasComparableOut(out) {
7469
8043
  return outEvents(out).length > 0;
@@ -7505,7 +8079,7 @@ function routeAt(spec, path23) {
7505
8079
  for (const key of path23) {
7506
8080
  if (typeof key === "number")
7507
8081
  current = Array.isArray(current) ? current[key] : void 0;
7508
- else current = isObject7(current) ? current[key] : void 0;
8082
+ else current = isObject8(current) ? current[key] : void 0;
7509
8083
  }
7510
8084
  return current;
7511
8085
  }
@@ -7530,7 +8104,7 @@ function lintRoute(spec, position, known, errors, warnings) {
7530
8104
  if (node.stop && !node.match && node.kind !== "many") {
7531
8105
  const self = routeAt(spec, node.path);
7532
8106
  const list = routeAt(spec, node.path.slice(0, -1));
7533
- if (isObject7(self) && self.stop === true && typeof last === "number" && Array.isArray(list) && last < list.length - 1 && once(`stop:${where(node.path)}`)) {
8107
+ if (isObject8(self) && self.stop === true && typeof last === "number" && Array.isArray(list) && last < list.length - 1 && once(`stop:${where(node.path)}`)) {
7534
8108
  const at = where(node.path);
7535
8109
  warnings.push({
7536
8110
  path: at,
@@ -7596,7 +8170,7 @@ function resolveStepContracts(entries, contract) {
7596
8170
  }
7597
8171
  const sources = [];
7598
8172
  for (const [index, entry] of entries.entries()) {
7599
- if (isObject7(entry)) {
8173
+ if (isObject8(entry)) {
7600
8174
  sources.push(entry);
7601
8175
  continue;
7602
8176
  }
@@ -7614,7 +8188,7 @@ function resolveStepContracts(entries, contract) {
7614
8188
  message: `contract "${match[1]}" is not defined in the root contract (defined: ${Object.keys(resolved).join(", ") || "none"})`
7615
8189
  };
7616
8190
  const rule = match[2] ? getByPath(resolved[match[1]], match[2]) : resolved[match[1]];
7617
- if (!isObject7(rule))
8191
+ if (!isObject8(rule))
7618
8192
  return {
7619
8193
  ok: false,
7620
8194
  index,
@@ -7625,7 +8199,7 @@ function resolveStepContracts(entries, contract) {
7625
8199
  return { ok: true, sources };
7626
8200
  }
7627
8201
  function checkValidateStepExamples(stepPath, step, contract, errors, warnings, strict, skipped, resolvedSettings) {
7628
- const settings = resolvedSettings ?? (isObject7(step.config) && isObject7(step.config.settings) ? step.config.settings : {});
8202
+ const settings = resolvedSettings ?? (isObject8(step.config) && isObject8(step.config.settings) ? step.config.settings : {});
7629
8203
  const contractPath = `${stepPath}.config.settings.contract`;
7630
8204
  if (settings.contract !== void 0 && !Array.isArray(settings.contract)) {
7631
8205
  if (step.examples)
@@ -7650,10 +8224,10 @@ function checkValidateStepExamples(stepPath, step, contract, errors, warnings, s
7650
8224
  const contracts = resolution.sources;
7651
8225
  const mode = settings.mode === "strict" ? "strict" : "pass";
7652
8226
  const format = settings.format === true;
7653
- const output = isObject7(settings.output) ? settings.output : {};
8227
+ const output = isObject8(settings.output) ? settings.output : {};
7654
8228
  const isValidPath = typeof output.isValid === "string" ? output.isValid : "source.valid";
7655
8229
  for (const [exName, example] of Object.entries(step.examples)) {
7656
- if (example.command || !isObject7(example.in)) continue;
8230
+ if (example.command || !isObject8(example.in)) continue;
7657
8231
  if (example.out === void 0) continue;
7658
8232
  const event = example.in;
7659
8233
  const verdict = validateEventAgainstContract(event, void 0, {
@@ -7691,14 +8265,14 @@ function checkValidateStepExamples(stepPath, step, contract, errors, warnings, s
7691
8265
  }
7692
8266
 
7693
8267
  // src/commands/validate/validators/mapping.ts
7694
- import { isObject as isObject8 } from "@walkeros/core";
8268
+ import { isObject as isObject9 } from "@walkeros/core";
7695
8269
  import { schemas as schemas5 } from "@walkeros/core/dev";
7696
8270
  var { RuleSchema } = schemas5.MappingSchemas;
7697
8271
  function isRule(value) {
7698
- return isObject8(value) && RuleSchema.safeParse(value).success;
8272
+ return isObject9(value) && RuleSchema.safeParse(value).success;
7699
8273
  }
7700
8274
  function isNestedActions(key, value) {
7701
- if (key.includes(" ") || !isObject8(value)) return false;
8275
+ if (key.includes(" ") || !isObject9(value)) return false;
7702
8276
  const rules = Object.values(value);
7703
8277
  return rules.length > 0 && rules.every(
7704
8278
  (rule) => Array.isArray(rule) ? rule.length > 0 && rule.every(isRule) : isRule(rule)
@@ -7708,7 +8282,7 @@ function validateMapping(input) {
7708
8282
  const errors = [];
7709
8283
  const warnings = [];
7710
8284
  const details = {};
7711
- if (!isObject8(input)) {
8285
+ if (!isObject9(input)) {
7712
8286
  errors.push({
7713
8287
  path: "root",
7714
8288
  message: "Mapping must be an object with event patterns as keys",
@@ -7931,7 +8505,7 @@ function inapplicableOptions(type, options) {
7931
8505
  }
7932
8506
  function validateContractInput(input) {
7933
8507
  if (!isFlowJson2(input)) return validateContract(input);
7934
- const contract = isObject9(input) ? input.contract : void 0;
8508
+ const contract = isObject10(input) ? input.contract : void 0;
7935
8509
  if (contract === void 0) {
7936
8510
  return {
7937
8511
  valid: false,
@@ -8194,8 +8768,10 @@ async function loginCommand(options) {
8194
8768
  }
8195
8769
  async function fetchEmail(appUrl, accessToken, fetchFn) {
8196
8770
  try {
8197
- const response = await fetchFn(`${appUrl}/api/auth/whoami`, {
8198
- headers: { Authorization: `Bearer ${accessToken}` },
8771
+ const response = await apiRequest("GET /api/auth/whoami", {
8772
+ auth: { token: accessToken },
8773
+ baseUrl: appUrl,
8774
+ fetch: fetchFn,
8199
8775
  signal: AbortSignal.timeout(WHOAMI_TIMEOUT_MS)
8200
8776
  });
8201
8777
  if (!response.ok) return void 0;
@@ -8334,121 +8910,6 @@ async function logout() {
8334
8910
 
8335
8911
  // src/core/api-client.ts
8336
8912
  import createClient from "openapi-fetch";
8337
-
8338
- // src/core/contract.ts
8339
- import { createHash as createHash2 } from "crypto";
8340
- import semver4 from "semver";
8341
- var bakedContractVersion = true ? "4.7.0" : PLACEHOLDER;
8342
- var bakedContractHash = true ? "1758bf6b37ad72eb37dd8176f240ae64b16c5b1f9da376cab6357027c835a833" : "";
8343
- function isRecord4(value) {
8344
- return value !== null && typeof value === "object" && !Array.isArray(value);
8345
- }
8346
- function canonicalize(value) {
8347
- if (Array.isArray(value)) {
8348
- return value.map(canonicalize);
8349
- }
8350
- if (isRecord4(value)) {
8351
- const result = {};
8352
- for (const key of Object.keys(value).sort()) {
8353
- result[key] = canonicalize(value[key]);
8354
- }
8355
- return result;
8356
- }
8357
- return value;
8358
- }
8359
- function stripInfoVersion(doc) {
8360
- if (!isRecord4(doc) || !isRecord4(doc.info)) {
8361
- return doc;
8362
- }
8363
- const restInfo = {};
8364
- for (const [key, value] of Object.entries(doc.info)) {
8365
- if (key !== "version") restInfo[key] = value;
8366
- }
8367
- return { ...doc, info: restInfo };
8368
- }
8369
- function canonicalContractHash(doc) {
8370
- const canonical = canonicalize(stripInfoVersion(doc));
8371
- return createHash2("sha256").update(JSON.stringify(canonical)).digest("hex");
8372
- }
8373
- var HEALTH_TIMEOUT_MS = 5e3;
8374
- async function fetchHealth(baseUrl) {
8375
- try {
8376
- const res = await fetch(`${baseUrl ?? resolveAppUrl()}/api/health`, {
8377
- signal: AbortSignal.timeout(HEALTH_TIMEOUT_MS)
8378
- });
8379
- const body = await res.json().catch(() => void 0);
8380
- const result = { reachable: true };
8381
- if (isRecord4(body)) {
8382
- const record = body;
8383
- if (typeof record.status === "string") result.status = record.status;
8384
- if (typeof record.appVersion === "string")
8385
- result.appVersion = record.appVersion;
8386
- if (typeof record.contractVersion === "string")
8387
- result.contractVersion = record.contractVersion;
8388
- if (typeof record.contractHash === "string")
8389
- result.contractHash = record.contractHash;
8390
- }
8391
- return result;
8392
- } catch {
8393
- return { reachable: false };
8394
- }
8395
- }
8396
- async function compareContract(input = {}) {
8397
- const bakedVersion = input.bakedVersion ?? bakedContractVersion;
8398
- const bakedHash = input.bakedHash ?? bakedContractHash;
8399
- const health = await fetchHealth(input.baseUrl);
8400
- if (!health.reachable || health.contractVersion === void 0 || health.contractHash === void 0) {
8401
- return { verdict: "unknown", bakedVersion };
8402
- }
8403
- const liveVersion = health.contractVersion;
8404
- if (health.contractHash === bakedHash) {
8405
- return { verdict: "in-sync", bakedVersion, liveVersion };
8406
- }
8407
- const liveNewer = semver4.valid(liveVersion) && semver4.valid(bakedVersion) ? semver4.gt(liveVersion, bakedVersion) : liveVersion > bakedVersion;
8408
- if (liveNewer) {
8409
- return {
8410
- verdict: "client-older",
8411
- bakedVersion,
8412
- liveVersion,
8413
- action: `upgrade @walkeros/cli to >= ${liveVersion}`
8414
- };
8415
- }
8416
- return { verdict: "client-newer", bakedVersion, liveVersion };
8417
- }
8418
- async function annotateErrorWithDrift(error, input = {}) {
8419
- const comparison = await compareContract(input).catch(
8420
- () => ({
8421
- verdict: "unknown",
8422
- bakedVersion: input.bakedVersion ?? bakedContractVersion
8423
- })
8424
- );
8425
- if (comparison.verdict !== "client-older" || !comparison.action) {
8426
- return error;
8427
- }
8428
- const annotated = new Error(
8429
- `${error.message}
8430
-
8431
- The server runs contract ${comparison.liveVersion}, this client was built against ${comparison.bakedVersion}. This may be the cause: ${comparison.action}.`
8432
- );
8433
- annotated.stack = error.stack;
8434
- return annotated;
8435
- }
8436
-
8437
- // src/core/api-client.ts
8438
- var driftWarned = false;
8439
- function emitDriftWarning(responseHeaders) {
8440
- if (driftWarned) return;
8441
- const serverVersion = responseHeaders.get("X-WalkerOS-Server-Version");
8442
- if (!serverVersion) return;
8443
- if (serverVersion === bakedContractVersion) return;
8444
- driftWarned = true;
8445
- const minClient = responseHeaders.get("X-WalkerOS-Min-Client");
8446
- const minNote = minClient ? ` (min client ${minClient})` : "";
8447
- process.stderr.write(
8448
- `walkerOS: server contract version is ${serverVersion}${minNote}, this client was built against ${bakedContractVersion}. Run \`walkeros diagnostics\` or upgrade @walkeros/cli if commands misbehave.
8449
- `
8450
- );
8451
- }
8452
8913
  function createApiClient() {
8453
8914
  const client = createClient({
8454
8915
  baseUrl: resolveAppUrl(),
@@ -8468,12 +8929,6 @@ function createApiClient() {
8468
8929
  requireSecureUrl(request.url);
8469
8930
  request.headers.set("Authorization", `Bearer ${token}`);
8470
8931
  return request;
8471
- },
8472
- // Surface contract drift once per process from any response's version
8473
- // headers. openapi-fetch ^0.17 supports `use({ onResponse })`.
8474
- onResponse({ response }) {
8475
- emitDriftWarning(response.headers);
8476
- return void 0;
8477
8932
  }
8478
8933
  });
8479
8934
  return client;
@@ -8896,9 +9351,10 @@ async function getAvailableFlowNames(options) {
8896
9351
  var DEFAULT_DEPLOY_WAIT_MS = 12 * 60 * 1e3;
8897
9352
  async function streamDeploymentStatus(projectId, deploymentId, options) {
8898
9353
  const timeoutMs = options.timeout ?? DEFAULT_DEPLOY_WAIT_MS;
8899
- const response = await apiFetch(
8900
- `/api/projects/${projectId}/deployments/${deploymentId}/stream`,
9354
+ const response = await apiRequest(
9355
+ "GET /api/projects/{projectId}/deployments/{deploymentId}/stream",
8901
9356
  {
9357
+ path: { projectId, deploymentId },
8902
9358
  headers: { Accept: "text/event-stream" },
8903
9359
  signal: options.signal ?? AbortSignal.timeout(timeoutMs)
8904
9360
  }
@@ -8987,9 +9443,12 @@ Available: ${names.join(", ")}`,
8987
9443
  }
8988
9444
  async function deploySettings(options) {
8989
9445
  const { flowId, projectId, settingsId } = options;
8990
- const triggerDeploy = () => apiFetch(
8991
- `/api/projects/${projectId}/flows/${flowId}/settings/${settingsId}/deploy`,
8992
- { method: "POST", headers: { "Idempotency-Key": randomUUID() } }
9446
+ const triggerDeploy = () => apiRequest(
9447
+ "POST /api/projects/{projectId}/flows/{flowId}/settings/{settingsId}/deploy",
9448
+ {
9449
+ path: { projectId, flowId, settingsId },
9450
+ headers: { "Idempotency-Key": randomUUID() }
9451
+ }
8993
9452
  );
8994
9453
  let response = await triggerDeploy();
8995
9454
  if (!response.ok && options.wait) {
@@ -9037,8 +9496,9 @@ async function getDeployment(options) {
9037
9496
  projectId,
9038
9497
  flowName: options.flowName
9039
9498
  });
9040
- const response = await apiFetch(
9041
- `/api/projects/${projectId}/flows/${options.flowId}/settings/${settingsId}/deploy`
9499
+ const response = await apiRequest(
9500
+ "GET /api/projects/{projectId}/flows/{flowId}/settings/{settingsId}/deploy",
9501
+ { path: { projectId, flowId: options.flowId, settingsId } }
9042
9502
  );
9043
9503
  if (!response.ok) {
9044
9504
  const body = await response.json().catch(() => ({}));
@@ -9133,18 +9593,39 @@ async function getDeploymentCommand(flowId, options) {
9133
9593
  }
9134
9594
 
9135
9595
  // src/commands/deployments/index.ts
9136
- import { getPlatform as getPlatform4, isObject as isObject10 } from "@walkeros/core";
9596
+ import { getPlatform as getPlatform4, isObject as isObject11 } from "@walkeros/core";
9597
+ var DEPLOYMENT_STATUSES = {
9598
+ idle: true,
9599
+ deploying: true,
9600
+ published: true,
9601
+ active: true,
9602
+ stopped: true,
9603
+ failed: true
9604
+ };
9605
+ var DEPLOYMENT_TYPES = {
9606
+ web: true,
9607
+ server: true
9608
+ };
9609
+ function isMember(members, value) {
9610
+ return Object.hasOwn(members, value);
9611
+ }
9612
+ function isDeploymentStatus(value) {
9613
+ return isMember(DEPLOYMENT_STATUSES, value);
9614
+ }
9137
9615
  async function listDeployments(options = {}) {
9138
9616
  const id = options.projectId ?? requireProjectId();
9139
- const params = new URLSearchParams();
9140
- if (options.type) params.set("type", options.type);
9141
- if (options.status) params.set("status", options.status);
9142
- if (options.flowId) params.set("flowId", options.flowId);
9143
- if (options.cursor) params.set("cursor", options.cursor);
9144
- if (options.limit !== void 0) params.set("limit", String(options.limit));
9145
- const qs = params.toString();
9146
- const response = await apiFetch(
9147
- `/api/projects/${id}/deployments${qs ? `?${qs}` : ""}`
9617
+ const response = await apiRequest(
9618
+ "GET /api/projects/{projectId}/deployments",
9619
+ {
9620
+ path: { projectId: id },
9621
+ query: {
9622
+ type: options.type,
9623
+ status: options.status,
9624
+ flowId: options.flowId || void 0,
9625
+ cursor: options.cursor || void 0,
9626
+ limit: options.limit
9627
+ }
9628
+ }
9148
9629
  );
9149
9630
  if (!response.ok) {
9150
9631
  const body = await response.json().catch(() => ({}));
@@ -9191,8 +9672,9 @@ async function deleteDeploymentByFlowId(options) {
9191
9672
  }
9192
9673
  async function getDeploymentBySlug(options) {
9193
9674
  const id = options.projectId ?? requireProjectId();
9194
- const response = await apiFetch(
9195
- `/api/projects/${id}/deployments/${options.slug}`
9675
+ const response = await apiRequest(
9676
+ "GET /api/projects/{projectId}/deployments/{deploymentId}",
9677
+ { path: { projectId: id, deploymentId: options.slug } }
9196
9678
  );
9197
9679
  if (!response.ok) {
9198
9680
  const body = await response.json().catch(() => ({}));
@@ -9202,11 +9684,13 @@ async function getDeploymentBySlug(options) {
9202
9684
  }
9203
9685
  async function createDeployment(options) {
9204
9686
  const id = options.projectId ?? requireProjectId();
9205
- const response = await apiFetch(`/api/projects/${id}/deployments`, {
9206
- method: "POST",
9207
- headers: { "Content-Type": "application/json" },
9208
- body: JSON.stringify({ type: options.type, label: options.label })
9209
- });
9687
+ const response = await apiRequest(
9688
+ "POST /api/projects/{projectId}/deployments",
9689
+ {
9690
+ path: { projectId: id },
9691
+ body: { type: options.type, label: options.label }
9692
+ }
9693
+ );
9210
9694
  if (!response.ok) {
9211
9695
  const body = await response.json().catch(() => ({}));
9212
9696
  throwApiError(body, "Failed to create deployment");
@@ -9215,9 +9699,9 @@ async function createDeployment(options) {
9215
9699
  }
9216
9700
  async function deleteDeployment(options) {
9217
9701
  const id = options.projectId ?? requireProjectId();
9218
- const response = await apiFetch(
9219
- `/api/projects/${id}/deployments/${options.slug}`,
9220
- { method: "DELETE" }
9702
+ const response = await apiRequest(
9703
+ "DELETE /api/projects/{projectId}/deployments/{deploymentId}",
9704
+ { path: { projectId: id, deploymentId: options.slug } }
9221
9705
  );
9222
9706
  if (!response.ok) {
9223
9707
  const body = await response.json().catch(() => ({}));
@@ -9226,6 +9710,11 @@ async function deleteDeployment(options) {
9226
9710
  const data = await response.json().catch(() => null);
9227
9711
  return data ?? { success: true };
9228
9712
  }
9713
+ function flagValue(flag, value, members) {
9714
+ if (value === void 0) return void 0;
9715
+ if (isMember(members, value)) return value;
9716
+ throw new Error(`${flag} must be one of: ${Object.keys(members).join(", ")}`);
9717
+ }
9229
9718
  async function handleResult3(fn, options) {
9230
9719
  try {
9231
9720
  const result = await fn();
@@ -9238,8 +9727,8 @@ async function listDeploymentsCommand(options) {
9238
9727
  await handleResult3(
9239
9728
  () => listDeployments({
9240
9729
  projectId: options.project,
9241
- type: options.type,
9242
- status: options.status,
9730
+ type: flagValue("--type", options.type, DEPLOYMENT_TYPES),
9731
+ status: flagValue("--status", options.status, DEPLOYMENT_STATUSES),
9243
9732
  cursor: options.cursor,
9244
9733
  limit: options.limit
9245
9734
  }),
@@ -9281,21 +9770,23 @@ async function createDeployCommand(config, options) {
9281
9770
  const isRemoteFlow = config.startsWith("cfg_");
9282
9771
  if (isRemoteFlow) {
9283
9772
  const id = options.project ?? requireProjectId();
9284
- const resp = await apiFetch(`/api/projects/${id}/flows/${config}`);
9773
+ const resp = await apiRequest(
9774
+ "GET /api/projects/{projectId}/flows/{flowId}",
9775
+ { path: { projectId: id, flowId: config } }
9776
+ );
9285
9777
  if (!resp.ok) {
9286
9778
  const body = await resp.json().catch(() => ({}));
9287
9779
  throwApiError(body, `Failed to fetch flow ${config}`);
9288
9780
  }
9289
9781
  const flow = await resp.json();
9290
9782
  if (!flow.config) throw new Error("Flow has no config");
9291
- const flowConfig = flow.config;
9292
- const flows = flowConfig.flows;
9783
+ const flows = flow.config.flows;
9293
9784
  if (!flows) throw new Error("Invalid flow config: missing flows");
9294
9785
  const flowName = options.flow ?? Object.keys(flows)[0];
9295
9786
  if (!flowName) throw new Error("No flows found in config");
9296
9787
  const flowSettings = flows[flowName];
9297
- if (!isObject10(flowSettings)) throw new Error("Invalid flow config");
9298
- const platform = isObject10(flowSettings.config) ? flowSettings.config.platform : void 0;
9788
+ if (!isObject11(flowSettings)) throw new Error("Invalid flow config");
9789
+ const platform = isObject11(flowSettings.config) ? flowSettings.config.platform : void 0;
9299
9790
  if (platform !== "web" && platform !== "server")
9300
9791
  throw new Error(
9301
9792
  `Flow "${flowName}" must have config.platform set to "web" or "server"`
@@ -9375,10 +9866,9 @@ async function feedback(text, options) {
9375
9866
  payload.projectId = projectId;
9376
9867
  }
9377
9868
  }
9378
- const response = await publicFetch("/api/feedback", {
9379
- method: "POST",
9380
- headers: { "Content-Type": "application/json" },
9381
- body: JSON.stringify(payload)
9869
+ const response = await apiRequest("POST /api/feedback", {
9870
+ auth: "none",
9871
+ body: payload
9382
9872
  });
9383
9873
  if (!response.ok) {
9384
9874
  throw new Error(
@@ -9591,9 +10081,16 @@ async function wrapSkeleton(options) {
9591
10081
  };
9592
10082
  if (platform === "browser") {
9593
10083
  esbuildOptions.format = "iife";
10084
+ const needs = readNeedsMarker(skeletonText);
9594
10085
  esbuildOptions.define = {
9595
10086
  "process.env.NODE_ENV": '"production"',
9596
- global: "globalThis"
10087
+ global: "globalThis",
10088
+ ...buildFlagDefines(
10089
+ needs && {
10090
+ ...needs,
10091
+ observe: needs.observe || options.observe !== void 0
10092
+ }
10093
+ )
9597
10094
  };
9598
10095
  esbuildOptions.external = devExternals;
9599
10096
  esbuildOptions.target = target ?? "es2018";
@@ -10094,11 +10591,219 @@ function resolveManifestSource(manifest, env = process.env) {
10094
10591
  return fromEnv;
10095
10592
  }
10096
10593
 
10594
+ // src/core/contract.ts
10595
+ import { createHash as createHash3 } from "crypto";
10596
+ import semver4 from "semver";
10597
+ var bakedContractVersion = true ? "4.7.0+80fb4d79" : PLACEHOLDER;
10598
+ var bakedContractHash = true ? "7096fd745fbe3993fe5f1f90d87aec45b20ff8d15adce2c3b0f871f99b0183de" : "";
10599
+ var bakedClientOperations = typeof define_CLIENT_OPERATION_DIGESTS_default === "object" ? define_CLIENT_OPERATION_DIGESTS_default : [];
10600
+ function isRecord5(value) {
10601
+ return value !== null && typeof value === "object" && !Array.isArray(value);
10602
+ }
10603
+ function stripInfoVersion(doc) {
10604
+ if (!isRecord5(doc) || !isRecord5(doc.info)) {
10605
+ return doc;
10606
+ }
10607
+ const restInfo = {};
10608
+ for (const [key, value] of Object.entries(doc.info)) {
10609
+ if (key !== "version") restInfo[key] = value;
10610
+ }
10611
+ return { ...doc, info: restInfo };
10612
+ }
10613
+ function canonicalContractHash(doc) {
10614
+ const canonical = canonicalize(stripInfoVersion(doc));
10615
+ return createHash3("sha256").update(JSON.stringify(canonical)).digest("hex");
10616
+ }
10617
+ var HEALTH_TIMEOUT_MS = 5e3;
10618
+ var OPENAPI_TIMEOUT_MS = 1e4;
10619
+ function trimTrailingSlashes(url) {
10620
+ return url.replace(/\/+$/, "");
10621
+ }
10622
+ function failureReason(error, timeoutMs) {
10623
+ if (!isRecord5(error)) return String(error);
10624
+ if (error.name === "TimeoutError") return `timeout after ${timeoutMs} ms`;
10625
+ const message = typeof error.message === "string" ? error.message : String(error);
10626
+ const cause = error.cause;
10627
+ const code = isRecord5(cause) && typeof cause.code === "string" ? cause.code : void 0;
10628
+ return code ? `${message} (${code})` : message;
10629
+ }
10630
+ async function fetchHealth(baseUrl) {
10631
+ try {
10632
+ const res = await apiRequest("GET /api/health", {
10633
+ auth: "none",
10634
+ signal: AbortSignal.timeout(HEALTH_TIMEOUT_MS),
10635
+ ...baseUrl === void 0 ? {} : { baseUrl }
10636
+ });
10637
+ const body = await res.json().catch(() => void 0);
10638
+ const result = { reachable: true };
10639
+ if (!res.ok) result.httpStatus = res.status;
10640
+ if (isRecord5(body)) {
10641
+ if (typeof body.status === "string") result.status = body.status;
10642
+ if (typeof body.appVersion === "string")
10643
+ result.appVersion = body.appVersion;
10644
+ if (typeof body.contractVersion === "string")
10645
+ result.contractVersion = body.contractVersion;
10646
+ if (typeof body.contractHash === "string")
10647
+ result.contractHash = body.contractHash;
10648
+ if (typeof body.minSupportedClient === "string")
10649
+ result.minSupportedClient = body.minSupportedClient;
10650
+ }
10651
+ return result;
10652
+ } catch (error) {
10653
+ return {
10654
+ reachable: false,
10655
+ error: failureReason(error, HEALTH_TIMEOUT_MS)
10656
+ };
10657
+ }
10658
+ }
10659
+ async function fetchOpenApi(baseUrl) {
10660
+ const base = baseUrl ?? trimTrailingSlashes(resolveAppUrl());
10661
+ const url = operationUrl("GET /api/openapi.json", { baseUrl: base });
10662
+ let res;
10663
+ try {
10664
+ res = await apiRequest("GET /api/openapi.json", {
10665
+ auth: "none",
10666
+ baseUrl: base,
10667
+ signal: AbortSignal.timeout(OPENAPI_TIMEOUT_MS)
10668
+ });
10669
+ } catch (error) {
10670
+ return { ok: false, url, error: failureReason(error, OPENAPI_TIMEOUT_MS) };
10671
+ }
10672
+ if (!res.ok) return { ok: false, url, error: `HTTP ${res.status}` };
10673
+ const document = await res.json().catch(() => void 0);
10674
+ if (!isRecord5(document)) {
10675
+ return { ok: false, url, error: "response is not JSON" };
10676
+ }
10677
+ if (!isRecord5(document.paths)) return { ok: false, url, error: "no paths" };
10678
+ return { ok: true, url, document };
10679
+ }
10680
+ function isBelow(version, floor) {
10681
+ return semver4.valid(version) !== null && semver4.valid(floor) !== null && semver4.lt(version, floor);
10682
+ }
10683
+ function serverFloorBelow(server, client) {
10684
+ if (server === void 0 || !server.includes("+")) return true;
10685
+ if (semver4.valid(server) === null) return true;
10686
+ return isBelow(server, client);
10687
+ }
10688
+ function documentLabel(document) {
10689
+ const info = document.info;
10690
+ return isRecord5(info) && typeof info.version === "string" ? info.version : void 0;
10691
+ }
10692
+ async function compareContract(input = {}) {
10693
+ const appUrl = trimTrailingSlashes(input.baseUrl ?? resolveAppUrl());
10694
+ const context2 = input.client ?? getClientContext() ?? { type: "cli", version: VERSION };
10695
+ const client = {
10696
+ package: `@walkeros/${context2.type}`,
10697
+ version: context2.version,
10698
+ contract: input.bakedVersion ?? bakedContractVersion
10699
+ };
10700
+ const operations = input.operations ?? bakedClientOperations;
10701
+ const health = await fetchHealth(appUrl);
10702
+ if (!health.reachable) {
10703
+ const url = operationUrl("GET /api/health", { baseUrl: appUrl });
10704
+ return {
10705
+ verdict: "unknown",
10706
+ appUrl,
10707
+ client,
10708
+ reason: `GET ${url}: ${health.error ?? "no response"}`
10709
+ };
10710
+ }
10711
+ const known = {
10712
+ verdict: "unknown",
10713
+ appUrl,
10714
+ client,
10715
+ ...health.contractVersion !== void 0 && {
10716
+ server: health.contractVersion
10717
+ },
10718
+ ...health.minSupportedClient !== void 0 && {
10719
+ minSupportedClient: health.minSupportedClient
10720
+ }
10721
+ };
10722
+ if (health.minSupportedClient !== void 0 && isBelow(client.version, health.minSupportedClient)) {
10723
+ return {
10724
+ ...known,
10725
+ verdict: "client-outdated",
10726
+ requires: { package: client.package, version: health.minSupportedClient }
10727
+ };
10728
+ }
10729
+ if (operations.length === 0) {
10730
+ return { ...known, reason: "no baked client operations" };
10731
+ }
10732
+ const live = await fetchOpenApi(appUrl);
10733
+ if (!live.ok) {
10734
+ return { ...known, reason: `GET ${live.url}: ${live.error}` };
10735
+ }
10736
+ let liveDigests;
10737
+ try {
10738
+ liveDigests = operationDigests(
10739
+ live.document,
10740
+ operations.map(({ op }) => op)
10741
+ );
10742
+ } catch (error) {
10743
+ const message = error instanceof Error ? error.message : String(error);
10744
+ return { ...known, reason: `GET ${live.url}: ${message}` };
10745
+ }
10746
+ const missing = operations.filter(({ op }) => !Object.hasOwn(liveDigests, op)).map(({ op, usedBy }) => ({ op, usedBy }));
10747
+ const changed = operations.filter(({ op, digest }) => {
10748
+ return Object.hasOwn(liveDigests, op) && liveDigests[op] !== digest;
10749
+ }).map(({ op }) => op);
10750
+ const server = known.server ?? documentLabel(live.document);
10751
+ const compared = {
10752
+ ...known,
10753
+ ...server !== void 0 && { server },
10754
+ operations: operations.length,
10755
+ missing,
10756
+ changed
10757
+ };
10758
+ if (missing.length > 0) return { ...compared, verdict: "server-older" };
10759
+ if (changed.length > 0) {
10760
+ const older = serverFloorBelow(server, client.contract);
10761
+ return { ...compared, verdict: older ? "server-older" : "changed" };
10762
+ }
10763
+ return { ...compared, verdict: "in-sync" };
10764
+ }
10765
+ function missingList(missing) {
10766
+ return missing.map(
10767
+ ({ op, usedBy }) => usedBy.length > 0 ? `${op} (${usedBy.join(", ")})` : op
10768
+ ).join(", ");
10769
+ }
10770
+ function formatContract(c) {
10771
+ const server = c.server ?? "without a label";
10772
+ const labels = `server ${server}, client ${c.client.contract}`;
10773
+ const missing = c.missing ?? [];
10774
+ const changed = c.changed ?? [];
10775
+ switch (c.verdict) {
10776
+ case "in-sync":
10777
+ return `contract: in-sync (${labels}, ${c.operations ?? 0} operations)`;
10778
+ case "changed":
10779
+ return `contract: changed (${labels}); changed: ${changed.join(", ")}`;
10780
+ case "server-older": {
10781
+ const parts = [`contract: server-older (${labels})`];
10782
+ if (missing.length > 0) {
10783
+ parts.push(`not offered (${missing.length}): ${missingList(missing)}`);
10784
+ }
10785
+ if (changed.length > 0) parts.push(`changed: ${changed.length}`);
10786
+ return parts.join("; ");
10787
+ }
10788
+ case "client-outdated": {
10789
+ const pkg = c.requires?.package ?? c.client.package;
10790
+ const floor = c.requires?.version ?? c.minSupportedClient;
10791
+ const requires = floor === void 0 ? "" : ` requires ${pkg} >= ${floor}`;
10792
+ return `contract: client-outdated (${c.appUrl}${requires}; this is ${c.client.version})`;
10793
+ }
10794
+ case "unknown":
10795
+ return `contract: unknown (${c.reason ?? "no reason given"})`;
10796
+ case "in-process":
10797
+ return `contract: in-process (server ${server})`;
10798
+ }
10799
+ }
10800
+
10097
10801
  // src/commands/previews/index.ts
10098
10802
  async function listPreviews(options) {
10099
10803
  const pid = options.projectId ?? requireProjectId();
10100
- const response = await apiFetch(
10101
- `/api/projects/${pid}/flows/${options.flowId}/previews`
10804
+ const response = await apiRequest(
10805
+ "GET /api/projects/{projectId}/flows/{flowId}/previews",
10806
+ { path: { projectId: pid, flowId: options.flowId } }
10102
10807
  );
10103
10808
  if (!response.ok) {
10104
10809
  const body = await response.json().catch(() => ({}));
@@ -10108,8 +10813,15 @@ async function listPreviews(options) {
10108
10813
  }
10109
10814
  async function getPreview(options) {
10110
10815
  const pid = options.projectId ?? requireProjectId();
10111
- const response = await apiFetch(
10112
- `/api/projects/${pid}/flows/${options.flowId}/previews/${options.previewId}`
10816
+ const response = await apiRequest(
10817
+ "GET /api/projects/{projectId}/flows/{flowId}/previews/{previewId}",
10818
+ {
10819
+ path: {
10820
+ projectId: pid,
10821
+ flowId: options.flowId,
10822
+ previewId: options.previewId
10823
+ }
10824
+ }
10113
10825
  );
10114
10826
  if (!response.ok) {
10115
10827
  const body = await response.json().catch(() => ({}));
@@ -10142,15 +10854,14 @@ async function createPreview(options) {
10142
10854
  }
10143
10855
  settingsId = match.id;
10144
10856
  }
10145
- const response = await apiFetch(
10146
- `/api/projects/${pid}/flows/${options.flowId}/previews`,
10857
+ const response = await apiRequest(
10858
+ "POST /api/projects/{projectId}/flows/{flowId}/previews",
10147
10859
  {
10148
- method: "POST",
10149
- headers: { "Content-Type": "application/json" },
10150
- body: JSON.stringify({
10860
+ path: { projectId: pid, flowId: options.flowId },
10861
+ body: {
10151
10862
  flowSettingsId: settingsId,
10152
10863
  ...options.source ? { source: options.source } : {}
10153
- })
10864
+ }
10154
10865
  }
10155
10866
  );
10156
10867
  if (!response.ok) {
@@ -10159,12 +10870,11 @@ async function createPreview(options) {
10159
10870
  }
10160
10871
  const created = await response.json();
10161
10872
  if (origin === void 0) return created;
10162
- const grantResponse = await apiFetch(
10163
- `/api/projects/${pid}/flows/${options.flowId}/previews/${created.id}/grant`,
10873
+ const grantResponse = await apiRequest(
10874
+ "POST /api/projects/{projectId}/flows/{flowId}/previews/{previewId}/grant",
10164
10875
  {
10165
- method: "POST",
10166
- headers: { "Content-Type": "application/json" },
10167
- body: JSON.stringify({ origins: [origin] })
10876
+ path: { projectId: pid, flowId: options.flowId, previewId: created.id },
10877
+ body: { origins: [origin] }
10168
10878
  }
10169
10879
  );
10170
10880
  if (!grantResponse.ok) {
@@ -10183,15 +10893,18 @@ async function createPreview(options) {
10183
10893
  }
10184
10894
  async function regrantPreview(options) {
10185
10895
  const pid = options.projectId ?? requireProjectId();
10186
- const response = await apiFetch(
10187
- `/api/projects/${pid}/flows/${options.flowId}/previews/${options.previewId}/grant`,
10896
+ const response = await apiRequest(
10897
+ "POST /api/projects/{projectId}/flows/{flowId}/previews/{previewId}/grant",
10188
10898
  {
10189
- method: "POST",
10190
- headers: { "Content-Type": "application/json" },
10191
- body: JSON.stringify({
10899
+ path: {
10900
+ projectId: pid,
10901
+ flowId: options.flowId,
10902
+ previewId: options.previewId
10903
+ },
10904
+ body: {
10192
10905
  origins: options.origins,
10193
10906
  ...options.sessionId ? { sessionId: options.sessionId } : {}
10194
- })
10907
+ }
10195
10908
  }
10196
10909
  );
10197
10910
  if (!response.ok) {
@@ -10202,9 +10915,15 @@ async function regrantPreview(options) {
10202
10915
  }
10203
10916
  async function deletePreview(options) {
10204
10917
  const pid = options.projectId ?? requireProjectId();
10205
- const response = await apiFetch(
10206
- `/api/projects/${pid}/flows/${options.flowId}/previews/${options.previewId}`,
10207
- { method: "DELETE" }
10918
+ const response = await apiRequest(
10919
+ "DELETE /api/projects/{projectId}/flows/{flowId}/previews/{previewId}",
10920
+ {
10921
+ path: {
10922
+ projectId: pid,
10923
+ flowId: options.flowId,
10924
+ previewId: options.previewId
10925
+ }
10926
+ }
10208
10927
  );
10209
10928
  if (!response.ok) {
10210
10929
  const body = await response.json().catch(() => ({}));
@@ -10218,12 +10937,12 @@ async function deletePreview(options) {
10218
10937
  // src/commands/journeys/index.ts
10219
10938
  async function listJourneys(options) {
10220
10939
  const id = options.projectId ?? requireProjectId();
10221
- const params = new URLSearchParams();
10222
- if (options.traceId) params.set("traceId", options.traceId);
10223
- if (options.limit !== void 0) params.set("limit", String(options.limit));
10224
- const qs = params.toString();
10225
- const response = await apiFetch(
10226
- `/api/projects/${id}/flows/${options.flowId}/journeys${qs ? `?${qs}` : ""}`
10940
+ const response = await apiRequest(
10941
+ "GET /api/projects/{projectId}/flows/{flowId}/journeys",
10942
+ {
10943
+ path: { projectId: id, flowId: options.flowId },
10944
+ query: { traceId: options.traceId || void 0, limit: options.limit }
10945
+ }
10227
10946
  );
10228
10947
  if (!response.ok) {
10229
10948
  const body = await response.json().catch(() => ({}));
@@ -10243,13 +10962,9 @@ async function startObserveSession(options) {
10243
10962
  // omitted rather than sent as a bare [] the app would have to interpret.
10244
10963
  ...options.origins?.length ? { origins: options.origins } : {}
10245
10964
  };
10246
- const response = await apiFetch(
10247
- `/api/projects/${pid}/flows/${options.flowId}/observe-sessions`,
10248
- {
10249
- method: "POST",
10250
- headers: { "Content-Type": "application/json" },
10251
- body: JSON.stringify(body)
10252
- }
10965
+ const response = await apiRequest(
10966
+ "POST /api/projects/{projectId}/flows/{flowId}/observe-sessions",
10967
+ { path: { projectId: pid, flowId: options.flowId }, body }
10253
10968
  );
10254
10969
  if (!response.ok) {
10255
10970
  const errorBody = await response.json().catch(() => ({}));
@@ -10263,8 +10978,15 @@ async function startObserveSession(options) {
10263
10978
  }
10264
10979
  async function getObserveSession(options) {
10265
10980
  const pid = options.projectId ?? requireProjectId();
10266
- const response = await apiFetch(
10267
- `/api/projects/${pid}/flows/${options.flowId}/observe-sessions/${options.sessionId}`
10981
+ const response = await apiRequest(
10982
+ "GET /api/projects/{projectId}/flows/{flowId}/observe-sessions/{sessionId}",
10983
+ {
10984
+ path: {
10985
+ projectId: pid,
10986
+ flowId: options.flowId,
10987
+ sessionId: options.sessionId
10988
+ }
10989
+ }
10268
10990
  );
10269
10991
  if (!response.ok) {
10270
10992
  const errorBody = await response.json().catch(() => ({}));
@@ -10274,9 +10996,15 @@ async function getObserveSession(options) {
10274
10996
  }
10275
10997
  async function endObserveSession(options) {
10276
10998
  const pid = options.projectId ?? requireProjectId();
10277
- const response = await apiFetch(
10278
- `/api/projects/${pid}/flows/${options.flowId}/observe-sessions/${options.sessionId}`,
10279
- { method: "DELETE" }
10999
+ const response = await apiRequest(
11000
+ "DELETE /api/projects/{projectId}/flows/{flowId}/observe-sessions/{sessionId}",
11001
+ {
11002
+ path: {
11003
+ projectId: pid,
11004
+ flowId: options.flowId,
11005
+ sessionId: options.sessionId
11006
+ }
11007
+ }
10280
11008
  );
10281
11009
  if (!response.ok) {
10282
11010
  const errorBody = await response.json().catch(() => ({}));
@@ -10294,103 +11022,110 @@ async function readJson3(response, fallback) {
10294
11022
  }
10295
11023
  async function listReleases(options) {
10296
11024
  const pid = options.projectId ?? requireProjectId();
10297
- const params = new URLSearchParams({ rationale: "true" });
10298
- if (options.limit !== void 0) params.set("limit", String(options.limit));
10299
- if (options.offset !== void 0)
10300
- params.set("offset", String(options.offset));
10301
- const response = await apiFetch(
10302
- `/api/projects/${pid}/flows/${options.flowId}/releases?${params.toString()}`
11025
+ const response = await apiRequest(
11026
+ "GET /api/projects/{projectId}/flows/{flowId}/releases",
11027
+ {
11028
+ path: { projectId: pid, flowId: options.flowId },
11029
+ query: {
11030
+ rationale: "true",
11031
+ limit: options.limit,
11032
+ offset: options.offset
11033
+ }
11034
+ }
10303
11035
  );
10304
11036
  return readJson3(response, "Failed to list releases");
10305
11037
  }
10306
11038
  async function getRelease(options) {
10307
11039
  const pid = options.projectId ?? requireProjectId();
10308
11040
  const segment = "versionId" in options.ref ? options.ref.versionId : String(options.ref.versionNumber);
10309
- const response = await apiFetch(
10310
- `/api/projects/${pid}/flows/${options.flowId}/releases/${encodeURIComponent(segment)}`
11041
+ const response = await apiRequest(
11042
+ "GET /api/projects/{projectId}/flows/{flowId}/releases/{versionId}",
11043
+ { path: { projectId: pid, flowId: options.flowId, versionId: segment } }
10311
11044
  );
10312
11045
  return readJson3(response, "Failed to read release");
10313
11046
  }
10314
11047
  async function listStepHistory(options) {
10315
11048
  const pid = options.projectId ?? requireProjectId();
10316
- const params = new URLSearchParams({ step: options.step });
10317
- if (options.flow !== void 0) params.set("flow", options.flow);
10318
- if (options.limit !== void 0) params.set("limit", String(options.limit));
10319
- const response = await apiFetch(
10320
- `/api/projects/${pid}/flows/${options.flowId}/releases/step-history?${params.toString()}`
11049
+ const response = await apiRequest(
11050
+ "GET /api/projects/{projectId}/flows/{flowId}/releases/step-history",
11051
+ {
11052
+ path: { projectId: pid, flowId: options.flowId },
11053
+ query: { step: options.step, flow: options.flow, limit: options.limit }
11054
+ }
10321
11055
  );
10322
11056
  return readJson3(response, "Failed to read step history");
10323
11057
  }
10324
11058
  async function setReleaseRationale(options) {
10325
11059
  const pid = options.projectId ?? requireProjectId();
10326
- const response = await apiFetch(
10327
- `/api/projects/${pid}/flows/${options.flowId}/releases/annotations`,
11060
+ const response = await apiRequest(
11061
+ "PUT /api/projects/{projectId}/flows/{flowId}/releases/annotations",
10328
11062
  {
10329
- method: "PUT",
10330
- headers: { "Content-Type": "application/json" },
10331
- body: JSON.stringify({
10332
- versionId: options.versionId,
10333
- humanText: options.text
10334
- })
11063
+ path: { projectId: pid, flowId: options.flowId },
11064
+ body: { versionId: options.versionId, humanText: options.text }
10335
11065
  }
10336
11066
  );
10337
11067
  return readJson3(response, "Failed to write release rationale");
10338
11068
  }
10339
11069
  async function listThreads(options) {
10340
11070
  const pid = options.projectId ?? requireProjectId();
10341
- const params = new URLSearchParams();
10342
- if (options.anchorType !== void 0)
10343
- params.set("anchorType", options.anchorType);
10344
- if (options.anchorKey !== void 0)
10345
- params.set("anchorKey", options.anchorKey);
10346
- if (options.status !== void 0) params.set("status", options.status);
10347
- params.set("includeMessages", options.includeMessages ? "true" : "false");
10348
- if (options.limit !== void 0) params.set("limit", String(options.limit));
10349
- const response = await apiFetch(
10350
- `/api/projects/${pid}/flows/${options.flowId}/threads?${params.toString()}`
11071
+ const response = await apiRequest(
11072
+ "GET /api/projects/{projectId}/flows/{flowId}/threads",
11073
+ {
11074
+ path: { projectId: pid, flowId: options.flowId },
11075
+ query: {
11076
+ anchorType: options.anchorType,
11077
+ anchorKey: options.anchorKey,
11078
+ status: options.status,
11079
+ includeMessages: options.includeMessages ? "true" : "false",
11080
+ limit: options.limit
11081
+ }
11082
+ }
10351
11083
  );
10352
11084
  return readJson3(response, "Failed to list threads");
10353
11085
  }
10354
11086
  async function createThread(options) {
10355
11087
  const pid = options.projectId ?? requireProjectId();
10356
- const response = await apiFetch(
10357
- `/api/projects/${pid}/flows/${options.flowId}/threads`,
11088
+ const response = await apiRequest(
11089
+ "POST /api/projects/{projectId}/flows/{flowId}/threads",
10358
11090
  {
10359
- method: "POST",
10360
- headers: { "Content-Type": "application/json" },
10361
- body: JSON.stringify({
11091
+ path: { projectId: pid, flowId: options.flowId },
11092
+ body: {
10362
11093
  anchorType: options.anchorType,
10363
11094
  anchorKey: options.anchorKey,
10364
11095
  ...options.anchorLabel !== void 0 ? { anchorLabel: options.anchorLabel } : {},
10365
11096
  text: options.text
10366
- })
11097
+ }
10367
11098
  }
10368
11099
  );
10369
11100
  return readJson3(response, "Failed to open thread");
10370
11101
  }
10371
11102
  async function addThreadMessage(options) {
10372
11103
  const pid = options.projectId ?? requireProjectId();
10373
- const response = await apiFetch(
10374
- `/api/projects/${pid}/flows/${options.flowId}/threads/${encodeURIComponent(options.threadId)}/messages`,
11104
+ const response = await apiRequest(
11105
+ "POST /api/projects/{projectId}/flows/{flowId}/threads/{threadId}/messages",
10375
11106
  {
10376
- method: "POST",
10377
- headers: { "Content-Type": "application/json" },
10378
- body: JSON.stringify({ text: options.text })
11107
+ path: {
11108
+ projectId: pid,
11109
+ flowId: options.flowId,
11110
+ threadId: options.threadId
11111
+ },
11112
+ body: { text: options.text }
10379
11113
  }
10380
11114
  );
10381
11115
  return readJson3(response, "Failed to add message");
10382
11116
  }
10383
11117
  async function listKnowledge(options) {
10384
11118
  const pid = options.projectId ?? requireProjectId();
10385
- const params = new URLSearchParams();
10386
- if (options.pageKey !== void 0) params.set("pageKey", options.pageKey);
10387
- if (options.frameId !== void 0) params.set("frameId", options.frameId);
10388
- if (options.markId !== void 0) params.set("markId", options.markId);
10389
- params.set("includeMessages", options.includeMessages ? "true" : "false");
10390
- if (options.limit !== void 0) params.set("limit", String(options.limit));
10391
- const response = await apiFetch(
10392
- `/api/projects/${pid}/knowledge?${params.toString()}`
10393
- );
11119
+ const response = await apiRequest("GET /api/projects/{projectId}/knowledge", {
11120
+ path: { projectId: pid },
11121
+ query: {
11122
+ pageKey: options.pageKey,
11123
+ frameId: options.frameId,
11124
+ markId: options.markId,
11125
+ includeMessages: options.includeMessages ? "true" : "false",
11126
+ limit: options.limit
11127
+ }
11128
+ });
10394
11129
  return readJson3(response, "Failed to read knowledge");
10395
11130
  }
10396
11131
 
@@ -10404,21 +11139,24 @@ async function readJson4(response, fallback) {
10404
11139
  }
10405
11140
  async function listFrames(options = {}) {
10406
11141
  const pid = options.projectId ?? requireProjectId();
10407
- const response = await apiFetch(`/api/projects/${pid}/frames`);
11142
+ const response = await apiRequest("GET /api/projects/{projectId}/frames", {
11143
+ path: { projectId: pid }
11144
+ });
10408
11145
  return readJson4(response, "Failed to list frames");
10409
11146
  }
10410
11147
  async function listPageFrames(options) {
10411
11148
  const pid = options.projectId ?? requireProjectId();
10412
- const params = new URLSearchParams({ pageKey: options.pageKey });
10413
- const response = await apiFetch(
10414
- `/api/projects/${pid}/frames?${params.toString()}`
10415
- );
11149
+ const response = await apiRequest("GET /api/projects/{projectId}/frames", {
11150
+ path: { projectId: pid },
11151
+ query: { pageKey: options.pageKey }
11152
+ });
10416
11153
  return readJson4(response, "Failed to list page frames");
10417
11154
  }
10418
11155
  async function getFrame(options) {
10419
11156
  const pid = options.projectId ?? requireProjectId();
10420
- const response = await apiFetch(
10421
- `/api/projects/${pid}/frames/${encodeURIComponent(options.frameId)}`
11157
+ const response = await apiRequest(
11158
+ "GET /api/projects/{projectId}/frames/{frameId}",
11159
+ { path: { projectId: pid, frameId: options.frameId } }
10422
11160
  );
10423
11161
  return readJson4(response, "Failed to read frame");
10424
11162
  }
@@ -10426,8 +11164,9 @@ async function getFrame(options) {
10426
11164
  // src/commands/secrets/index.ts
10427
11165
  async function listSecrets(options) {
10428
11166
  const pid = options.projectId ?? requireProjectId();
10429
- const response = await apiFetch(
10430
- `/api/projects/${pid}/flows/${options.flowId}/secrets`
11167
+ const response = await apiRequest(
11168
+ "GET /api/projects/{projectId}/flows/{flowId}/secrets",
11169
+ { path: { projectId: pid, flowId: options.flowId } }
10431
11170
  );
10432
11171
  if (!response.ok) {
10433
11172
  const body = await response.json().catch(() => ({}));
@@ -10437,12 +11176,11 @@ async function listSecrets(options) {
10437
11176
  }
10438
11177
  async function createSecret(options) {
10439
11178
  const pid = options.projectId ?? requireProjectId();
10440
- const response = await apiFetch(
10441
- `/api/projects/${pid}/flows/${options.flowId}/secrets`,
11179
+ const response = await apiRequest(
11180
+ "POST /api/projects/{projectId}/flows/{flowId}/secrets",
10442
11181
  {
10443
- method: "POST",
10444
- headers: { "Content-Type": "application/json" },
10445
- body: JSON.stringify({ name: options.name, value: options.value })
11182
+ path: { projectId: pid, flowId: options.flowId },
11183
+ body: { name: options.name, value: options.value }
10446
11184
  }
10447
11185
  );
10448
11186
  if (!response.ok) {
@@ -10453,12 +11191,15 @@ async function createSecret(options) {
10453
11191
  }
10454
11192
  async function updateSecret(options) {
10455
11193
  const pid = options.projectId ?? requireProjectId();
10456
- const response = await apiFetch(
10457
- `/api/projects/${pid}/flows/${options.flowId}/secrets/${options.secretId}`,
11194
+ const response = await apiRequest(
11195
+ "PUT /api/projects/{projectId}/flows/{flowId}/secrets/{secretId}",
10458
11196
  {
10459
- method: "PUT",
10460
- headers: { "Content-Type": "application/json" },
10461
- body: JSON.stringify({ value: options.value })
11197
+ path: {
11198
+ projectId: pid,
11199
+ flowId: options.flowId,
11200
+ secretId: options.secretId
11201
+ },
11202
+ body: { value: options.value }
10462
11203
  }
10463
11204
  );
10464
11205
  if (!response.ok) {
@@ -10469,9 +11210,15 @@ async function updateSecret(options) {
10469
11210
  }
10470
11211
  async function deleteSecret(options) {
10471
11212
  const pid = options.projectId ?? requireProjectId();
10472
- const response = await apiFetch(
10473
- `/api/projects/${pid}/flows/${options.flowId}/secrets/${options.secretId}`,
10474
- { method: "DELETE" }
11213
+ const response = await apiRequest(
11214
+ "DELETE /api/projects/{projectId}/flows/{flowId}/secrets/{secretId}",
11215
+ {
11216
+ path: {
11217
+ projectId: pid,
11218
+ flowId: options.flowId,
11219
+ secretId: options.secretId
11220
+ }
11221
+ }
10475
11222
  );
10476
11223
  if (!response.ok) {
10477
11224
  const body = await response.json().catch(() => ({}));
@@ -10658,7 +11405,9 @@ async function createEmitter(opts) {
10658
11405
  function resolveTelemetryEndpoint() {
10659
11406
  const appUrl = resolveAppUrl();
10660
11407
  if (!appUrl) return void 0;
10661
- return `${appUrl.replace(/\/$/, "")}/api/telemetry`;
11408
+ return operationUrl("POST /api/telemetry", {
11409
+ baseUrl: appUrl.replace(/\/$/, "")
11410
+ });
10662
11411
  }
10663
11412
  async function withTimeout(p, ms) {
10664
11413
  return Promise.race([
@@ -10689,12 +11438,15 @@ export {
10689
11438
  BuildResultSchema,
10690
11439
  BuildWrapArtifactSchema,
10691
11440
  BuildWrapOptionsSchema,
11441
+ DEPLOYMENT_STATUSES,
11442
+ DEPLOYMENT_TYPES,
10692
11443
  DeploymentAmbiguityError,
10693
11444
  VALIDATE_CODES,
10694
11445
  VERSION,
10695
11446
  addThreadMessage,
10696
- annotateErrorWithDrift,
10697
11447
  apiFetch,
11448
+ apiRequest,
11449
+ bakedClientOperations,
10698
11450
  bakedContractHash,
10699
11451
  bakedContractVersion,
10700
11452
  buildDataPayload,
@@ -10739,6 +11491,8 @@ export {
10739
11491
  feedback,
10740
11492
  feedbackCommand,
10741
11493
  fetchHealth,
11494
+ fetchOpenApi,
11495
+ formatContract,
10742
11496
  formatPushResult,
10743
11497
  getAuthHeaders,
10744
11498
  getClientContext,
@@ -10756,6 +11510,7 @@ export {
10756
11510
  getProject,
10757
11511
  getProjectCommand,
10758
11512
  getRelease,
11513
+ isDeploymentStatus,
10759
11514
  listAllFlows,
10760
11515
  listDeployments,
10761
11516
  listDeploymentsCommand,
@@ -10779,6 +11534,7 @@ export {
10779
11534
  logout,
10780
11535
  logoutCommand,
10781
11536
  mergeAuthHeaders,
11537
+ operationUrl,
10782
11538
  parseSSEEvents,
10783
11539
  publicFetch,
10784
11540
  push,