create-dynamicagents 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,6 +1,3271 @@
1
1
  #!/usr/bin/env node
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ try {
10
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
11
+ } catch (e) {
12
+ throw mod = 0, e;
13
+ }
14
+ };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") {
17
+ for (let key of __getOwnPropNames(from))
18
+ if (!__hasOwnProp.call(to, key) && key !== except)
19
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target2) => (target2 = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target2, "default", { value: mod, enumerable: true }) : target2,
29
+ mod
30
+ ));
31
+
32
+ // node_modules/sisteransi/src/index.js
33
+ var require_src = __commonJS({
34
+ "node_modules/sisteransi/src/index.js"(exports, module) {
35
+ "use strict";
36
+ var ESC2 = "\x1B";
37
+ var CSI2 = `${ESC2}[`;
38
+ var beep = "\x07";
39
+ var cursor3 = {
40
+ to(x, y2) {
41
+ if (!y2) return `${CSI2}${x + 1}G`;
42
+ return `${CSI2}${y2 + 1};${x + 1}H`;
43
+ },
44
+ move(x, y2) {
45
+ let ret = "";
46
+ if (x < 0) ret += `${CSI2}${-x}D`;
47
+ else if (x > 0) ret += `${CSI2}${x}C`;
48
+ if (y2 < 0) ret += `${CSI2}${-y2}A`;
49
+ else if (y2 > 0) ret += `${CSI2}${y2}B`;
50
+ return ret;
51
+ },
52
+ up: (count = 1) => `${CSI2}${count}A`,
53
+ down: (count = 1) => `${CSI2}${count}B`,
54
+ forward: (count = 1) => `${CSI2}${count}C`,
55
+ backward: (count = 1) => `${CSI2}${count}D`,
56
+ nextLine: (count = 1) => `${CSI2}E`.repeat(count),
57
+ prevLine: (count = 1) => `${CSI2}F`.repeat(count),
58
+ left: `${CSI2}G`,
59
+ hide: `${CSI2}?25l`,
60
+ show: `${CSI2}?25h`,
61
+ save: `${ESC2}7`,
62
+ restore: `${ESC2}8`
63
+ };
64
+ var scroll = {
65
+ up: (count = 1) => `${CSI2}S`.repeat(count),
66
+ down: (count = 1) => `${CSI2}T`.repeat(count)
67
+ };
68
+ var erase3 = {
69
+ screen: `${CSI2}2J`,
70
+ up: (count = 1) => `${CSI2}1J`.repeat(count),
71
+ down: (count = 1) => `${CSI2}J`.repeat(count),
72
+ line: `${CSI2}2K`,
73
+ lineEnd: `${CSI2}K`,
74
+ lineStart: `${CSI2}1K`,
75
+ lines(count) {
76
+ let clear = "";
77
+ for (let i2 = 0; i2 < count; i2++)
78
+ clear += this.line + (i2 < count - 1 ? cursor3.up() : "");
79
+ if (count)
80
+ clear += cursor3.left;
81
+ return clear;
82
+ }
83
+ };
84
+ module.exports = { cursor: cursor3, scroll, erase: erase3, beep };
85
+ }
86
+ });
87
+
88
+ // src/cli.ts
2
89
  import { readFileSync } from "node:fs";
3
- import { welcome } from "./welcome.js";
4
- // Read at runtime rather than imported: `package.json` sits outside `rootDir`.
5
- const { version } = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
6
- console.log(welcome(version));
90
+ import { readdir as readdir2, stat } from "node:fs/promises";
91
+ import path2 from "node:path";
92
+
93
+ // node_modules/@clack/core/dist/index.mjs
94
+ import { styleText } from "node:util";
95
+ import { stdout, stdin } from "node:process";
96
+ import * as l from "node:readline";
97
+ import l__default from "node:readline";
98
+
99
+ // node_modules/fast-string-truncated-width/dist/utils.js
100
+ var getCodePointsLength = /* @__PURE__ */ (() => {
101
+ const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
102
+ return (input) => {
103
+ let surrogatePairsNr = 0;
104
+ SURROGATE_PAIR_RE.lastIndex = 0;
105
+ while (SURROGATE_PAIR_RE.test(input)) {
106
+ surrogatePairsNr += 1;
107
+ }
108
+ return input.length - surrogatePairsNr;
109
+ };
110
+ })();
111
+ var isFullWidth = (x) => {
112
+ return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
113
+ };
114
+ var isWideNotCJKTNotEmoji = (x) => {
115
+ return x === 8987 || x === 9001 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12771 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 19903 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
116
+ };
117
+
118
+ // node_modules/fast-string-truncated-width/dist/index.js
119
+ var ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
120
+ var CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
121
+ var CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu;
122
+ var TAB_RE = /\t{1,1000}/y;
123
+ var EMOJI_RE = new RegExp("[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F\\u20E3?))*", "yu");
124
+ var LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
125
+ var MODIFIER_RE = new RegExp("\\p{M}+", "gu");
126
+ var NO_TRUNCATION = { limit: Infinity, ellipsis: "" };
127
+ var getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
128
+ const LIMIT = truncationOptions.limit ?? Infinity;
129
+ const ELLIPSIS = truncationOptions.ellipsis ?? "";
130
+ const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION, widthOptions).width : 0);
131
+ const ANSI_WIDTH = 0;
132
+ const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
133
+ const TAB_WIDTH = widthOptions.tabWidth ?? 8;
134
+ const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
135
+ const FULL_WIDTH_WIDTH = 2;
136
+ const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
137
+ const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
138
+ const PARSE_BLOCKS = [
139
+ [LATIN_RE, REGULAR_WIDTH],
140
+ [ANSI_RE, ANSI_WIDTH],
141
+ [CONTROL_RE, CONTROL_WIDTH],
142
+ [TAB_RE, TAB_WIDTH],
143
+ [EMOJI_RE, EMOJI_WIDTH],
144
+ [CJKT_WIDE_RE, WIDE_WIDTH]
145
+ ];
146
+ let indexPrev = 0;
147
+ let index = 0;
148
+ let length = input.length;
149
+ let lengthExtra = 0;
150
+ let truncationEnabled = false;
151
+ let truncationIndex = length;
152
+ let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
153
+ let unmatchedStart = 0;
154
+ let unmatchedEnd = 0;
155
+ let width2 = 0;
156
+ let widthExtra = 0;
157
+ outer: while (true) {
158
+ if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
159
+ const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
160
+ lengthExtra = 0;
161
+ for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
162
+ const codePoint = char.codePointAt(0) || 0;
163
+ if (isFullWidth(codePoint)) {
164
+ widthExtra = FULL_WIDTH_WIDTH;
165
+ } else if (isWideNotCJKTNotEmoji(codePoint)) {
166
+ widthExtra = WIDE_WIDTH;
167
+ } else {
168
+ widthExtra = REGULAR_WIDTH;
169
+ }
170
+ if (width2 + widthExtra > truncationLimit) {
171
+ truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
172
+ }
173
+ if (width2 + widthExtra > LIMIT) {
174
+ truncationEnabled = true;
175
+ break outer;
176
+ }
177
+ lengthExtra += char.length;
178
+ width2 += widthExtra;
179
+ }
180
+ unmatchedStart = unmatchedEnd = 0;
181
+ }
182
+ if (index >= length) {
183
+ break outer;
184
+ }
185
+ for (let i2 = 0, l2 = PARSE_BLOCKS.length; i2 < l2; i2++) {
186
+ const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i2];
187
+ BLOCK_RE.lastIndex = index;
188
+ if (BLOCK_RE.test(input)) {
189
+ lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
190
+ widthExtra = lengthExtra * BLOCK_WIDTH;
191
+ if (width2 + widthExtra > truncationLimit) {
192
+ truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width2) / BLOCK_WIDTH));
193
+ }
194
+ if (width2 + widthExtra > LIMIT) {
195
+ truncationEnabled = true;
196
+ break outer;
197
+ }
198
+ width2 += widthExtra;
199
+ unmatchedStart = indexPrev;
200
+ unmatchedEnd = index;
201
+ index = indexPrev = BLOCK_RE.lastIndex;
202
+ continue outer;
203
+ }
204
+ }
205
+ index += 1;
206
+ }
207
+ return {
208
+ width: truncationEnabled ? truncationLimit : width2,
209
+ index: truncationEnabled ? truncationIndex : length,
210
+ truncated: truncationEnabled,
211
+ ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
212
+ };
213
+ };
214
+ var dist_default = getStringTruncatedWidth;
215
+
216
+ // node_modules/fast-string-width/dist/index.js
217
+ var NO_TRUNCATION2 = {
218
+ limit: Infinity,
219
+ ellipsis: "",
220
+ ellipsisWidth: 0
221
+ };
222
+ var fastStringWidth = (input, options = {}) => {
223
+ return dist_default(input, NO_TRUNCATION2, options).width;
224
+ };
225
+ var dist_default2 = fastStringWidth;
226
+
227
+ // node_modules/fast-wrap-ansi/lib/main.js
228
+ var ESC = "\x1B";
229
+ var CSI = "›";
230
+ var END_CODE = 39;
231
+ var ANSI_ESCAPE_BELL = "\x07";
232
+ var ANSI_CSI = "[";
233
+ var ANSI_OSC = "]";
234
+ var ANSI_SGR_TERMINATOR = "m";
235
+ var ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
236
+ var GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
237
+ var getClosingCode = (openingCode) => {
238
+ if (openingCode >= 30 && openingCode <= 37)
239
+ return 39;
240
+ if (openingCode >= 90 && openingCode <= 97)
241
+ return 39;
242
+ if (openingCode >= 40 && openingCode <= 47)
243
+ return 49;
244
+ if (openingCode >= 100 && openingCode <= 107)
245
+ return 49;
246
+ if (openingCode === 1 || openingCode === 2)
247
+ return 22;
248
+ if (openingCode === 3)
249
+ return 23;
250
+ if (openingCode === 4)
251
+ return 24;
252
+ if (openingCode === 7)
253
+ return 27;
254
+ if (openingCode === 8)
255
+ return 28;
256
+ if (openingCode === 9)
257
+ return 29;
258
+ if (openingCode === 0)
259
+ return 0;
260
+ return void 0;
261
+ };
262
+ var wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
263
+ var wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
264
+ var wrapWord = (rows, word, columns) => {
265
+ const characters = word[Symbol.iterator]();
266
+ let isInsideEscape = false;
267
+ let isInsideLinkEscape = false;
268
+ let lastRow = rows.at(-1);
269
+ let visible = lastRow === void 0 ? 0 : dist_default2(lastRow);
270
+ let currentCharacter = characters.next();
271
+ let nextCharacter = characters.next();
272
+ let rawCharacterIndex = 0;
273
+ while (!currentCharacter.done) {
274
+ const character = currentCharacter.value;
275
+ const characterLength = dist_default2(character);
276
+ if (visible + characterLength <= columns) {
277
+ rows[rows.length - 1] += character;
278
+ } else {
279
+ rows.push(character);
280
+ visible = 0;
281
+ }
282
+ if (character === ESC || character === CSI) {
283
+ isInsideEscape = true;
284
+ isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
285
+ }
286
+ if (isInsideEscape) {
287
+ if (isInsideLinkEscape) {
288
+ if (character === ANSI_ESCAPE_BELL) {
289
+ isInsideEscape = false;
290
+ isInsideLinkEscape = false;
291
+ }
292
+ } else if (character === ANSI_SGR_TERMINATOR) {
293
+ isInsideEscape = false;
294
+ }
295
+ } else {
296
+ visible += characterLength;
297
+ if (visible === columns && !nextCharacter.done) {
298
+ rows.push("");
299
+ visible = 0;
300
+ }
301
+ }
302
+ currentCharacter = nextCharacter;
303
+ nextCharacter = characters.next();
304
+ rawCharacterIndex += character.length;
305
+ }
306
+ lastRow = rows.at(-1);
307
+ if (!visible && lastRow !== void 0 && lastRow.length && rows.length > 1) {
308
+ rows[rows.length - 2] += rows.pop();
309
+ }
310
+ };
311
+ var stringVisibleTrimSpacesRight = (string) => {
312
+ const words2 = string.split(" ");
313
+ let last = words2.length;
314
+ while (last) {
315
+ if (dist_default2(words2[last - 1])) {
316
+ break;
317
+ }
318
+ last--;
319
+ }
320
+ if (last === words2.length) {
321
+ return string;
322
+ }
323
+ return words2.slice(0, last).join(" ") + words2.slice(last).join("");
324
+ };
325
+ var exec = (string, columns, options = {}) => {
326
+ if (options.trim !== false && string.trim() === "") {
327
+ return "";
328
+ }
329
+ let returnValue = "";
330
+ let escapeCode;
331
+ let escapeUrl;
332
+ const words2 = string.split(" ");
333
+ let rows = [""];
334
+ let rowLength = 0;
335
+ for (let index = 0; index < words2.length; index++) {
336
+ const word = words2[index];
337
+ if (options.trim !== false) {
338
+ const row = rows.at(-1) ?? "";
339
+ const trimmed = row.trimStart();
340
+ if (row.length !== trimmed.length) {
341
+ rows[rows.length - 1] = trimmed;
342
+ rowLength = dist_default2(trimmed);
343
+ }
344
+ }
345
+ if (index !== 0) {
346
+ if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
347
+ rows.push("");
348
+ rowLength = 0;
349
+ }
350
+ if (rowLength || options.trim === false) {
351
+ rows[rows.length - 1] += " ";
352
+ rowLength++;
353
+ }
354
+ }
355
+ const wordLength = dist_default2(word);
356
+ if (options.hard && wordLength > columns) {
357
+ const remainingColumns = columns - rowLength;
358
+ const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
359
+ const breaksStartingNextLine = Math.floor((wordLength - 1) / columns);
360
+ if (breaksStartingNextLine < breaksStartingThisLine) {
361
+ rows.push("");
362
+ }
363
+ wrapWord(rows, word, columns);
364
+ rowLength = dist_default2(rows.at(-1) ?? "");
365
+ continue;
366
+ }
367
+ if (rowLength + wordLength > columns && rowLength && wordLength) {
368
+ if (options.wordWrap === false && rowLength < columns) {
369
+ wrapWord(rows, word, columns);
370
+ rowLength = dist_default2(rows.at(-1) ?? "");
371
+ continue;
372
+ }
373
+ rows.push("");
374
+ rowLength = 0;
375
+ }
376
+ if (rowLength + wordLength > columns && options.wordWrap === false) {
377
+ wrapWord(rows, word, columns);
378
+ rowLength = dist_default2(rows.at(-1) ?? "");
379
+ continue;
380
+ }
381
+ rows[rows.length - 1] += word;
382
+ rowLength += wordLength;
383
+ }
384
+ if (options.trim !== false) {
385
+ rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
386
+ }
387
+ const preString = rows.join("\n");
388
+ let inSurrogate = false;
389
+ for (let i2 = 0; i2 < preString.length; i2++) {
390
+ const character = preString[i2];
391
+ returnValue += character;
392
+ if (!inSurrogate) {
393
+ inSurrogate = character >= "\uD800" && character <= "\uDBFF";
394
+ if (inSurrogate) {
395
+ continue;
396
+ }
397
+ } else {
398
+ inSurrogate = false;
399
+ }
400
+ if (character === ESC || character === CSI) {
401
+ GROUP_REGEX.lastIndex = i2 + 1;
402
+ const groupsResult = GROUP_REGEX.exec(preString);
403
+ const groups = groupsResult?.groups;
404
+ if (groups?.code !== void 0) {
405
+ const code = Number.parseFloat(groups.code);
406
+ escapeCode = code === END_CODE ? void 0 : code;
407
+ } else if (groups?.uri !== void 0) {
408
+ escapeUrl = groups.uri.length === 0 ? void 0 : groups.uri;
409
+ }
410
+ }
411
+ if (preString[i2 + 1] === "\n") {
412
+ if (escapeUrl) {
413
+ returnValue += wrapAnsiHyperlink("");
414
+ }
415
+ const closingCode = escapeCode ? getClosingCode(escapeCode) : void 0;
416
+ if (escapeCode && closingCode) {
417
+ returnValue += wrapAnsiCode(closingCode);
418
+ }
419
+ } else if (character === "\n") {
420
+ if (escapeCode && getClosingCode(escapeCode)) {
421
+ returnValue += wrapAnsiCode(escapeCode);
422
+ }
423
+ if (escapeUrl) {
424
+ returnValue += wrapAnsiHyperlink(escapeUrl);
425
+ }
426
+ }
427
+ }
428
+ return returnValue;
429
+ };
430
+ var CRLF_OR_LF = /\r?\n/;
431
+ function wrapAnsi(string, columns, options) {
432
+ return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join("\n");
433
+ }
434
+
435
+ // node_modules/@clack/core/dist/index.mjs
436
+ var import_sisteransi = __toESM(require_src(), 1);
437
+ import { ReadStream } from "node:tty";
438
+ function findCursor(s, o, l2) {
439
+ if (!l2.some((r2) => !r2.disabled))
440
+ return s;
441
+ const t2 = s + o, n3 = Math.max(l2.length - 1, 0), e = t2 < 0 ? n3 : t2 > n3 ? 0 : t2;
442
+ return l2[e]?.disabled ? findCursor(e, o < 0 ? -1 : 1, l2) : e;
443
+ }
444
+ var a$1 = ["up", "down", "left", "right", "space", "enter", "cancel"];
445
+ var t = [
446
+ "January",
447
+ "February",
448
+ "March",
449
+ "April",
450
+ "May",
451
+ "June",
452
+ "July",
453
+ "August",
454
+ "September",
455
+ "October",
456
+ "November",
457
+ "December"
458
+ ];
459
+ var settings = {
460
+ actions: new Set(a$1),
461
+ aliases: /* @__PURE__ */ new Map([
462
+ // vim support
463
+ ["k", "up"],
464
+ ["j", "down"],
465
+ ["h", "left"],
466
+ ["l", "right"],
467
+ ["", "cancel"],
468
+ // opinionated defaults!
469
+ ["escape", "cancel"]
470
+ ]),
471
+ messages: {
472
+ cancel: "Canceled",
473
+ error: "Something went wrong"
474
+ },
475
+ withGuide: true,
476
+ accessible: void 0,
477
+ date: {
478
+ monthNames: [...t],
479
+ messages: {
480
+ required: "Please enter a valid date",
481
+ invalidMonth: "There are only 12 months in a year",
482
+ invalidDay: (n3, e) => `There are only ${n3} days in ${e}`,
483
+ afterMin: (n3) => `Date must be on or after ${n3.toISOString().slice(0, 10)}`,
484
+ beforeMax: (n3) => `Date must be on or before ${n3.toISOString().slice(0, 10)}`
485
+ }
486
+ }
487
+ };
488
+ function isAccessible(n3) {
489
+ if (n3 !== void 0) return n3;
490
+ if (settings.accessible !== void 0) return settings.accessible;
491
+ const e = process.env.ACCESSIBLE;
492
+ return e !== void 0 && e !== "" && e !== "0" && e !== "false";
493
+ }
494
+ function isActionKey(n3, e) {
495
+ if (typeof n3 == "string")
496
+ return settings.aliases.get(n3) === e;
497
+ for (const s of n3)
498
+ if (s !== void 0 && isActionKey(s, e))
499
+ return true;
500
+ return false;
501
+ }
502
+ function diffLines(i2, s) {
503
+ if (i2 === s) return;
504
+ const e = i2.split(`
505
+ `), t2 = s.split(`
506
+ `), r2 = Math.max(e.length, t2.length), f = [];
507
+ for (let n3 = 0; n3 < r2; n3++)
508
+ e[n3] !== t2[n3] && f.push(n3);
509
+ return {
510
+ lines: f,
511
+ numLinesBefore: e.length,
512
+ numLinesAfter: t2.length,
513
+ numLines: r2
514
+ };
515
+ }
516
+ var R = globalThis.process.platform.startsWith("win");
517
+ var CANCEL_SYMBOL = /* @__PURE__ */ Symbol("clack:cancel");
518
+ function isCancel(e) {
519
+ return e === CANCEL_SYMBOL;
520
+ }
521
+ function setRawMode(e, r2) {
522
+ const o = e;
523
+ o.isTTY && o.setRawMode(r2);
524
+ }
525
+ function block({
526
+ input: e = stdin,
527
+ output: r2 = stdout,
528
+ overwrite: o = true,
529
+ hideCursor: n3 = true
530
+ } = {}) {
531
+ const s = l.createInterface({
532
+ input: e,
533
+ output: r2,
534
+ prompt: "",
535
+ tabSize: 1
536
+ });
537
+ l.emitKeypressEvents(e, s), e instanceof ReadStream && e.isTTY && e.setRawMode(true);
538
+ const t2 = (f, { name: a2, sequence: w }) => {
539
+ const c2 = String(f);
540
+ if (isActionKey([c2, a2, w], "cancel")) {
541
+ n3 && r2.write(import_sisteransi.cursor.show), process.exit(0);
542
+ return;
543
+ }
544
+ if (!o) return;
545
+ const i2 = a2 === "return" ? 0 : -1, m2 = a2 === "return" ? -1 : 0;
546
+ l.moveCursor(r2, i2, m2, () => {
547
+ l.clearLine(r2, 1, () => {
548
+ e.once("keypress", t2);
549
+ });
550
+ });
551
+ };
552
+ return n3 && r2.write(import_sisteransi.cursor.hide), e.once("keypress", t2), () => {
553
+ e.off("keypress", t2), n3 && r2.write(import_sisteransi.cursor.show), e instanceof ReadStream && e.isTTY && !R && e.setRawMode(false), s.terminal = false, s.close();
554
+ };
555
+ }
556
+ var getColumns = (e) => "columns" in e && typeof e.columns == "number" ? e.columns : 80;
557
+ var getRows = (e) => "rows" in e && typeof e.rows == "number" ? e.rows : 20;
558
+ function wrapTextWithPrefix(e, r2, o, n3 = o, s = o, t2) {
559
+ const f = getColumns(e ?? stdout);
560
+ return wrapAnsi(r2, f - o.length, {
561
+ hard: true,
562
+ trim: false
563
+ }).split(`
564
+ `).map((c2, i2, m2) => {
565
+ const d = t2 ? t2(c2, i2) : c2;
566
+ return i2 === 0 ? `${n3}${d}` : i2 === m2.length - 1 ? `${s}${d}` : `${o}${d}`;
567
+ }).join(`
568
+ `);
569
+ }
570
+ function runValidation(e, a2) {
571
+ if ("~standard" in e) {
572
+ const n3 = e["~standard"].validate(a2);
573
+ return n3 instanceof Promise ? n3.then((r2) => r2.issues?.at(0)?.message) : n3.issues?.at(0)?.message;
574
+ }
575
+ return e(a2);
576
+ }
577
+ var y = class {
578
+ input;
579
+ output;
580
+ _abortSignal;
581
+ rl;
582
+ opts;
583
+ _render;
584
+ _track = false;
585
+ _prevFrame = "";
586
+ _subscribers = /* @__PURE__ */ new Map();
587
+ _cursor = 0;
588
+ state = "initial";
589
+ error = "";
590
+ value;
591
+ userInput = "";
592
+ /**
593
+ * Whether accessible (static, screen-reader friendly) output is enabled for
594
+ * this prompt, resolved from the `accessible` option, the global setting,
595
+ * and the `ACCESSIBLE` env var.
596
+ */
597
+ get accessible() {
598
+ return isAccessible(this.opts.accessible);
599
+ }
600
+ constructor(t2, e = true) {
601
+ const { input: i2 = stdin, output: s = stdout, render: r2, signal: n3, ...o } = t2;
602
+ this.opts = o, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = r2.bind(this), this._track = e, this._abortSignal = n3, this.input = i2, this.output = s;
603
+ }
604
+ /**
605
+ * Unsubscribe all listeners
606
+ */
607
+ unsubscribe() {
608
+ this._subscribers.clear();
609
+ }
610
+ /**
611
+ * Set a subscriber with opts
612
+ * @param event - The event name
613
+ */
614
+ setSubscriber(t2, e) {
615
+ const i2 = this._subscribers.get(t2) ?? [];
616
+ i2.push(e), this._subscribers.set(t2, i2);
617
+ }
618
+ /**
619
+ * Subscribe to an event
620
+ * @param event - The event name
621
+ * @param cb - The callback
622
+ */
623
+ on(t2, e) {
624
+ this.setSubscriber(t2, { cb: e });
625
+ }
626
+ /**
627
+ * Subscribe to an event once
628
+ * @param event - The event name
629
+ * @param cb - The callback
630
+ */
631
+ once(t2, e) {
632
+ this.setSubscriber(t2, { cb: e, once: true });
633
+ }
634
+ /**
635
+ * Emit an event with data
636
+ * @param event - The event name
637
+ * @param data - The data to pass to the callback
638
+ */
639
+ emit(t2, ...e) {
640
+ const i2 = this._subscribers.get(t2) ?? [], s = [];
641
+ for (const r2 of i2)
642
+ r2.cb(...e), r2.once && s.push(() => i2.splice(i2.indexOf(r2), 1));
643
+ for (const r2 of s)
644
+ r2();
645
+ }
646
+ prompt() {
647
+ return new Promise((t2) => {
648
+ if (this._abortSignal) {
649
+ if (this._abortSignal.aborted)
650
+ return this.state = "cancel", this.close(), t2(CANCEL_SYMBOL);
651
+ this._abortSignal.addEventListener(
652
+ "abort",
653
+ () => {
654
+ this.state = "cancel", this.close();
655
+ },
656
+ { once: true }
657
+ );
658
+ }
659
+ this.rl = l__default.createInterface({
660
+ input: this.input,
661
+ tabSize: 2,
662
+ prompt: "",
663
+ escapeCodeTimeout: 50,
664
+ terminal: true
665
+ }), this.rl.prompt(), this.opts.initialUserInput !== void 0 && this._setUserInput(this.opts.initialUserInput, true), this.input.on("keypress", this.onKeypress), setRawMode(this.input, true), this.output.on("resize", this.render), this.render(), this.once("submit", () => {
666
+ this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t2(this.value);
667
+ }), this.once("cancel", () => {
668
+ this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t2(CANCEL_SYMBOL);
669
+ });
670
+ });
671
+ }
672
+ _isActionKey(t2, e) {
673
+ return t2 === " ";
674
+ }
675
+ _shouldSubmit(t2, e) {
676
+ return true;
677
+ }
678
+ _setValue(t2) {
679
+ this.value = t2, this.emit("value", this.value);
680
+ }
681
+ _setUserInput(t2, e) {
682
+ this.userInput = t2 ?? "", this.emit("userInput", this.userInput), e && this._track && this.rl && (this.rl.write(this.userInput), this._cursor = this.rl.cursor);
683
+ }
684
+ _clearUserInput() {
685
+ this.rl?.write(null, { ctrl: true, name: "u" }), this._setUserInput("");
686
+ }
687
+ async onKeypress(t2, e) {
688
+ if (this.state !== "validating") {
689
+ if (this._track && e.name !== "return" && (e.name && this._isActionKey(t2, e) && this.rl?.write(null, { ctrl: true, name: "h" }), this._cursor = this.rl?.cursor ?? 0, this._setUserInput(this.rl?.line)), this.state === "error" && (this.state = "active"), e?.name && (!this._track && settings.aliases.has(e.name) && this.emit("cursor", settings.aliases.get(e.name)), settings.actions.has(e.name) && this.emit("cursor", e.name)), t2 && (t2.toLowerCase() === "y" || t2.toLowerCase() === "n") && this.emit("confirm", t2.toLowerCase() === "y"), this.emit("key", t2, e), e?.name === "return" && this._shouldSubmit(t2, e)) {
690
+ if (this.opts.validate) {
691
+ const i2 = runValidation(this.opts.validate, this.value);
692
+ let s;
693
+ i2 instanceof Promise ? (this.state = "validating", this.render(), s = await i2) : s = i2, s && (this.error = s instanceof Error ? s.message : s, this.state = "error", this.rl?.write(this.userInput));
694
+ }
695
+ this.state !== "error" && (this.state = "submit");
696
+ }
697
+ isActionKey([t2, e?.name, e?.sequence], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
698
+ }
699
+ }
700
+ close() {
701
+ this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
702
+ `), setRawMode(this.input, false), this.rl?.close(), this.rl = void 0, this.emit(`${this.state}`, this.value), this.unsubscribe();
703
+ }
704
+ restoreCursor() {
705
+ const t2 = wrapAnsi(this._prevFrame, process.stdout.columns, { hard: true, trim: false }).split(`
706
+ `).length - 1;
707
+ this.output.write(import_sisteransi.cursor.move(-999, t2 * -1));
708
+ }
709
+ render() {
710
+ const t2 = wrapAnsi(this._render(this) ?? "", process.stdout.columns, {
711
+ hard: true,
712
+ trim: false
713
+ });
714
+ if (t2 !== this._prevFrame) {
715
+ if (this.state === "initial")
716
+ this.output.write(import_sisteransi.cursor.hide);
717
+ else {
718
+ const e = diffLines(this._prevFrame, t2), i2 = getRows(this.output);
719
+ if (this.restoreCursor(), e) {
720
+ const s = Math.max(0, e.numLinesAfter - i2), r2 = Math.max(0, e.numLinesBefore - i2);
721
+ let n3 = e.lines.find((o) => o >= s);
722
+ if (n3 === void 0) {
723
+ this._prevFrame = t2;
724
+ return;
725
+ }
726
+ if (e.lines.length === 1) {
727
+ this.output.write(import_sisteransi.cursor.move(0, n3 - r2)), this.output.write(import_sisteransi.erase.lines(1));
728
+ const o = t2.split(`
729
+ `);
730
+ this.output.write(o[n3]), this._prevFrame = t2, this.output.write(import_sisteransi.cursor.move(0, o.length - n3 - 1));
731
+ return;
732
+ } else if (e.lines.length > 1) {
733
+ if (s < r2)
734
+ n3 = s;
735
+ else {
736
+ const h2 = n3 - r2;
737
+ h2 > 0 && this.output.write(import_sisteransi.cursor.move(0, h2));
738
+ }
739
+ this.output.write(import_sisteransi.erase.down());
740
+ const f = t2.split(`
741
+ `).slice(n3);
742
+ this.output.write(f.join(`
743
+ `)), this._prevFrame = t2;
744
+ return;
745
+ }
746
+ }
747
+ this.output.write(import_sisteransi.erase.down());
748
+ }
749
+ this.output.write(t2), this.state === "initial" && (this.state = "active"), this._prevFrame = t2;
750
+ }
751
+ }
752
+ };
753
+ var r = class extends y {
754
+ get cursor() {
755
+ return this.value ? 0 : 1;
756
+ }
757
+ get _value() {
758
+ return this.cursor === 0;
759
+ }
760
+ constructor(t2) {
761
+ super(t2, false), this.value = !!t2.initialValue, this.on("userInput", () => {
762
+ this.value = this._value;
763
+ }), this.on("confirm", (i2) => {
764
+ this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = i2, this.state = "submit", this.close();
765
+ }), this.on("cursor", () => {
766
+ this.value = !this.value;
767
+ });
768
+ }
769
+ };
770
+ var a = class extends y {
771
+ options;
772
+ cursor = 0;
773
+ get _value() {
774
+ return this.options[this.cursor]?.value;
775
+ }
776
+ get _enabledOptions() {
777
+ return this.options.filter((e) => e.disabled !== true);
778
+ }
779
+ toggleAll() {
780
+ const e = this._enabledOptions, i2 = this.value !== void 0 && this.value.length === e.length;
781
+ this.value = i2 ? [] : e.map((t2) => t2.value);
782
+ }
783
+ toggleInvert() {
784
+ const e = this.value;
785
+ if (!e)
786
+ return;
787
+ const i2 = this._enabledOptions.filter((t2) => !e.includes(t2.value));
788
+ this.value = i2.map((t2) => t2.value);
789
+ }
790
+ toggleValue() {
791
+ this.value === void 0 && (this.value = []);
792
+ const e = this.value.includes(this._value);
793
+ this.value = e ? this.value.filter((i2) => i2 !== this._value) : [...this.value, this._value];
794
+ }
795
+ constructor(e) {
796
+ super(e, false), this.options = e.options, this.value = [...e.initialValues ?? []];
797
+ const i2 = Math.max(
798
+ this.options.findIndex(({ value: t2 }) => t2 === e.cursorAt),
799
+ 0
800
+ );
801
+ this.cursor = this.options[i2]?.disabled ? findCursor(i2, 1, this.options) : i2, this.on("key", (t2, l2) => {
802
+ l2.name === "a" && this.toggleAll(), l2.name === "i" && this.toggleInvert();
803
+ }), this.on("cursor", (t2) => {
804
+ switch (t2) {
805
+ case "left":
806
+ case "up":
807
+ this.cursor = findCursor(this.cursor, -1, this.options);
808
+ break;
809
+ case "down":
810
+ case "right":
811
+ this.cursor = findCursor(this.cursor, 1, this.options);
812
+ break;
813
+ case "space":
814
+ this.toggleValue();
815
+ break;
816
+ }
817
+ });
818
+ }
819
+ };
820
+ var n$1 = class n extends y {
821
+ options;
822
+ cursor = 0;
823
+ get _selectedValue() {
824
+ return this.options[this.cursor];
825
+ }
826
+ changeValue() {
827
+ const e = this._selectedValue;
828
+ this.value = e === void 0 ? void 0 : e.value;
829
+ }
830
+ constructor(e) {
831
+ super(e, false), this.options = e.options;
832
+ const o = this.options.findIndex(({ value: s }) => s === e.initialValue), t2 = o === -1 ? 0 : o;
833
+ this.cursor = this.options[t2]?.disabled ? findCursor(t2, 1, this.options) : t2, this.changeValue(), this.on("cursor", (s) => {
834
+ switch (s) {
835
+ case "left":
836
+ case "up":
837
+ this.cursor = findCursor(this.cursor, -1, this.options);
838
+ break;
839
+ case "down":
840
+ case "right":
841
+ this.cursor = findCursor(this.cursor, 1, this.options);
842
+ break;
843
+ }
844
+ this.changeValue();
845
+ });
846
+ }
847
+ };
848
+ var n2 = class extends y {
849
+ get userInputWithCursor() {
850
+ if (this.state === "submit")
851
+ return this.userInput;
852
+ const t2 = this.userInput;
853
+ if (this.cursor >= t2.length)
854
+ return `${this.userInput}█`;
855
+ const r2 = t2.slice(0, this.cursor), s = t2.slice(this.cursor, this.cursor + 1), e = t2.slice(this.cursor + 1);
856
+ return `${r2}${styleText("inverse", s)}${e}`;
857
+ }
858
+ get cursor() {
859
+ return this._cursor;
860
+ }
861
+ constructor(t2) {
862
+ super({
863
+ ...t2,
864
+ initialUserInput: t2.initialUserInput ?? t2.initialValue
865
+ }), this.on("userInput", (r2) => {
866
+ this._setValue(r2);
867
+ }), this.on("finalize", () => {
868
+ this.value || (this.value = t2.defaultValue), this.value === void 0 && (this.value = "");
869
+ });
870
+ }
871
+ };
872
+
873
+ // node_modules/@clack/prompts/dist/index.mjs
874
+ import { styleText as styleText2, stripVTControlCharacters } from "node:util";
875
+ import process$1 from "node:process";
876
+ var import_sisteransi2 = __toESM(require_src(), 1);
877
+ function isUnicodeSupported() {
878
+ if (process$1.platform !== "win32") {
879
+ return process$1.env.TERM !== "linux";
880
+ }
881
+ return Boolean(process$1.env.CI) || Boolean(process$1.env.WT_SESSION) || Boolean(process$1.env.TERMINUS_SUBLIME) || process$1.env.ConEmuTask === "{cmd::Cmder}" || process$1.env.TERM_PROGRAM === "Terminus-Sublime" || process$1.env.TERM_PROGRAM === "vscode" || process$1.env.TERM === "xterm-256color" || process$1.env.TERM === "alacritty" || process$1.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
882
+ }
883
+ var unicode = isUnicodeSupported();
884
+ var isCI = () => process.env.CI === "true";
885
+ var unicodeOr = (o, e) => unicode ? o : e;
886
+ var S_STEP_ACTIVE = unicodeOr("◆", "*");
887
+ var S_STEP_CANCEL = unicodeOr("■", "x");
888
+ var S_STEP_ERROR = unicodeOr("▲", "x");
889
+ var S_STEP_SUBMIT = unicodeOr("◇", "o");
890
+ var S_BAR_START = unicodeOr("┌", "T");
891
+ var S_BAR = unicodeOr("│", "|");
892
+ var S_BAR_END = unicodeOr("└", "—");
893
+ var S_BAR_START_RIGHT = unicodeOr("┐", "T");
894
+ var S_BAR_END_RIGHT = unicodeOr("┘", "—");
895
+ var S_RADIO_ACTIVE = unicodeOr("●", ">");
896
+ var S_RADIO_INACTIVE = unicodeOr("○", " ");
897
+ var S_CHECKBOX_ACTIVE = unicodeOr("◻", "[•]");
898
+ var S_CHECKBOX_SELECTED = unicodeOr("◼", "[+]");
899
+ var S_CHECKBOX_INACTIVE = unicodeOr("◻", "[ ]");
900
+ var S_PASSWORD_MASK = unicodeOr("▪", "•");
901
+ var S_BAR_H = unicodeOr("─", "-");
902
+ var S_CORNER_TOP_RIGHT = unicodeOr("╮", "+");
903
+ var S_CONNECT_LEFT = unicodeOr("├", "+");
904
+ var S_CORNER_BOTTOM_RIGHT = unicodeOr("╯", "+");
905
+ var S_CORNER_BOTTOM_LEFT = unicodeOr("╰", "+");
906
+ var S_CORNER_TOP_LEFT = unicodeOr("╭", "+");
907
+ var S_INFO = unicodeOr("●", "•");
908
+ var S_SUCCESS = unicodeOr("◆", "*");
909
+ var S_WARN = unicodeOr("▲", "!");
910
+ var S_ERROR = unicodeOr("■", "x");
911
+ var symbol = (o) => {
912
+ switch (o) {
913
+ case "initial":
914
+ case "active":
915
+ return styleText2("cyan", S_STEP_ACTIVE);
916
+ case "cancel":
917
+ return styleText2("red", S_STEP_CANCEL);
918
+ case "error":
919
+ return styleText2("yellow", S_STEP_ERROR);
920
+ case "submit":
921
+ return styleText2("green", S_STEP_SUBMIT);
922
+ case "validating":
923
+ return styleText2("dim", S_STEP_ACTIVE);
924
+ }
925
+ };
926
+ var symbolBar = (o) => {
927
+ switch (o) {
928
+ case "initial":
929
+ case "active":
930
+ return styleText2("cyan", S_BAR);
931
+ case "cancel":
932
+ return styleText2("red", S_BAR);
933
+ case "error":
934
+ return styleText2("yellow", S_BAR);
935
+ case "submit":
936
+ return styleText2("green", S_BAR);
937
+ }
938
+ };
939
+ function formatInstructionFooter(o, e) {
940
+ const r2 = [`${e ? `${styleText2("cyan", S_BAR)} ` : ""}${o.join(" • ")}`];
941
+ return e && r2.push(styleText2("cyan", S_BAR_END)), r2;
942
+ }
943
+ var I = (l2, e, w, p, b, C2 = false) => {
944
+ let r2 = e, O = 0;
945
+ if (C2)
946
+ for (let i2 = p - 1; i2 >= w; i2--) {
947
+ const m2 = l2[i2];
948
+ if (m2 && (r2 -= m2.length), O++, r2 <= b) break;
949
+ }
950
+ else
951
+ for (let i2 = w; i2 < p; i2++) {
952
+ const m2 = l2[i2];
953
+ if (m2 && (r2 -= m2.length), O++, r2 <= b) break;
954
+ }
955
+ return { lineCount: r2, removals: O };
956
+ };
957
+ var limitOptions = ({
958
+ cursor: l2,
959
+ options: e,
960
+ style: w,
961
+ output: p = process.stdout,
962
+ maxItems: b = Number.POSITIVE_INFINITY,
963
+ columnPadding: C2 = 0,
964
+ rowPadding: r2 = 4
965
+ }) => {
966
+ const i2 = getColumns(p) - C2, m2 = getRows(p), M = styleText2("dim", "..."), v = Math.max(m2 - r2, 0), a2 = Math.max(Math.min(b, v), 5);
967
+ let f = 0;
968
+ l2 >= a2 - 3 && (f = Math.max(
969
+ Math.min(l2 - a2 + 3, e.length - a2),
970
+ 0
971
+ ));
972
+ let d = a2 < e.length && f > 0, c2 = a2 < e.length && f + a2 < e.length;
973
+ const W2 = Math.min(
974
+ f + a2,
975
+ e.length
976
+ ), s = [];
977
+ let g = 0;
978
+ d && g++, c2 && g++;
979
+ const T = f + (d ? 1 : 0), y2 = W2 - (c2 ? 1 : 0);
980
+ for (let t2 = T; t2 < y2; t2++) {
981
+ const n3 = e[t2], o = n3 ? w(n3, t2 === l2) : "", h2 = wrapAnsi(o, i2, {
982
+ hard: true,
983
+ trim: false
984
+ }).split(`
985
+ `);
986
+ s.push(h2), g += h2.length;
987
+ }
988
+ if (g > v) {
989
+ let t2 = 0, n3 = 0, o = g;
990
+ const h2 = l2 - T;
991
+ let u3 = v;
992
+ const L = () => I(s, o, 0, h2, u3), E = () => I(
993
+ s,
994
+ o,
995
+ h2 + 1,
996
+ s.length,
997
+ u3,
998
+ true
999
+ );
1000
+ d ? ({ lineCount: o, removals: t2 } = L(), o > u3 && (c2 || (u3 -= 1), { lineCount: o, removals: n3 } = E())) : (c2 || (u3 -= 1), { lineCount: o, removals: n3 } = E(), o > u3 && (u3 -= 1, { lineCount: o, removals: t2 } = L())), t2 > 0 && (d = true, s.splice(0, t2)), n3 > 0 && (c2 = true, s.splice(s.length - n3, n3));
1001
+ }
1002
+ const x = [];
1003
+ d && x.push(M);
1004
+ for (const t2 of s)
1005
+ for (const n3 of t2)
1006
+ x.push(n3);
1007
+ return c2 && x.push(M), x;
1008
+ };
1009
+ var confirm = (e) => {
1010
+ const a2 = e.active ?? "Yes", o = e.inactive ?? "No";
1011
+ return new r({
1012
+ active: a2,
1013
+ inactive: o,
1014
+ signal: e.signal,
1015
+ input: e.input,
1016
+ output: e.output,
1017
+ initialValue: e.initialValue ?? true,
1018
+ render() {
1019
+ const i2 = e.withGuide ?? settings.withGuide, u3 = `${symbol(this.state)} `, l2 = i2 ? `${styleText2("gray", S_BAR)} ` : "", f = wrapTextWithPrefix(
1020
+ e.output,
1021
+ e.message,
1022
+ l2,
1023
+ u3
1024
+ ), s = `${i2 ? `${styleText2("gray", S_BAR)}
1025
+ ` : ""}${f}
1026
+ `, c2 = this.value ? a2 : o;
1027
+ switch (this.state) {
1028
+ case "submit": {
1029
+ const r2 = i2 ? `${styleText2("gray", S_BAR)} ` : "";
1030
+ return `${s}${r2}${styleText2("dim", c2)}`;
1031
+ }
1032
+ case "cancel": {
1033
+ const r2 = i2 ? `${styleText2("gray", S_BAR)} ` : "";
1034
+ return `${s}${r2}${styleText2(["strikethrough", "dim"], c2)}${i2 ? `
1035
+ ${styleText2("gray", S_BAR)}` : ""}`;
1036
+ }
1037
+ default: {
1038
+ const r2 = i2 ? `${styleText2("cyan", S_BAR)} ` : "", g = i2 ? styleText2("cyan", S_BAR_END) : "";
1039
+ return `${s}${r2}${this.value ? `${styleText2("green", S_RADIO_ACTIVE)} ${a2}` : `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", a2)}`}${e.vertical ? i2 ? `
1040
+ ${styleText2("cyan", S_BAR)} ` : `
1041
+ ` : ` ${styleText2("dim", "/")} `}${this.value ? `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", o)}` : `${styleText2("green", S_RADIO_ACTIVE)} ${o}`}
1042
+ ${g}
1043
+ `;
1044
+ }
1045
+ }
1046
+ }
1047
+ }).prompt();
1048
+ };
1049
+ var MULTISELECT_INSTRUCTIONS = [
1050
+ `${styleText2("dim", "↑/↓")} to navigate`,
1051
+ `${styleText2("dim", "Space:")} select`,
1052
+ `${styleText2("dim", "Enter:")} confirm`
1053
+ ];
1054
+ var m = (i2, u3) => i2.split(`
1055
+ `).map((d) => u3(d)).join(`
1056
+ `);
1057
+ var multiselect = (i2) => {
1058
+ const u3 = (t2, a2) => {
1059
+ const r2 = t2.label ?? String(t2.value);
1060
+ return a2 === "disabled" ? `${styleText2("gray", S_CHECKBOX_INACTIVE)} ${m(r2, (o) => styleText2(["strikethrough", "gray"], o))}${t2.hint ? ` ${styleText2("dim", `(${t2.hint ?? "disabled"})`)}` : ""}` : a2 === "active" ? `${styleText2("cyan", S_CHECKBOX_ACTIVE)} ${r2}${t2.hint ? ` ${styleText2("dim", `(${t2.hint})`)}` : ""}` : a2 === "selected" ? `${styleText2("green", S_CHECKBOX_SELECTED)} ${m(r2, (o) => styleText2("dim", o))}${t2.hint ? ` ${styleText2("dim", `(${t2.hint})`)}` : ""}` : a2 === "cancelled" ? `${m(r2, (o) => styleText2(["strikethrough", "dim"], o))}` : a2 === "active-selected" ? `${styleText2("green", S_CHECKBOX_SELECTED)} ${r2}${t2.hint ? ` ${styleText2("dim", `(${t2.hint})`)}` : ""}` : a2 === "submitted" ? `${m(r2, (o) => styleText2("dim", o))}` : `${styleText2("dim", S_CHECKBOX_INACTIVE)} ${m(r2, (o) => styleText2("dim", o))}`;
1061
+ }, d = i2.required ?? true, x = i2.showInstructions ?? true;
1062
+ return new a({
1063
+ options: i2.options,
1064
+ signal: i2.signal,
1065
+ input: i2.input,
1066
+ output: i2.output,
1067
+ initialValues: i2.initialValues,
1068
+ required: d,
1069
+ cursorAt: i2.cursorAt,
1070
+ validate(t2) {
1071
+ if (d && (t2 === void 0 || t2.length === 0))
1072
+ return `Please select at least one option.
1073
+ ${styleText2(
1074
+ "reset",
1075
+ styleText2(
1076
+ "dim",
1077
+ `Press ${styleText2(["gray", "bgWhite", "inverse"], " space ")} to select, ${styleText2(
1078
+ "gray",
1079
+ styleText2("bgWhite", styleText2("inverse", " enter "))
1080
+ )} to submit`
1081
+ )
1082
+ )}`;
1083
+ },
1084
+ render() {
1085
+ const t2 = i2.withGuide ?? settings.withGuide, a2 = wrapTextWithPrefix(
1086
+ i2.output,
1087
+ i2.message,
1088
+ t2 ? `${symbolBar(this.state)} ` : "",
1089
+ `${symbol(this.state)} `
1090
+ ), r2 = `${t2 ? `${styleText2("gray", S_BAR)}
1091
+ ` : ""}${a2}
1092
+ `, o = this.value ?? [], g = (n3, l2) => {
1093
+ if (n3.disabled)
1094
+ return u3(n3, "disabled");
1095
+ const s = o.includes(n3.value);
1096
+ return l2 && s ? u3(n3, "active-selected") : s ? u3(n3, "selected") : u3(n3, l2 ? "active" : "inactive");
1097
+ };
1098
+ switch (this.state) {
1099
+ case "submit": {
1100
+ const n3 = this.options.filter(({ value: s }) => o.includes(s)).map((s) => u3(s, "submitted")).join(styleText2("dim", ", ")) || styleText2("dim", "none"), l2 = wrapTextWithPrefix(
1101
+ i2.output,
1102
+ n3,
1103
+ t2 ? `${styleText2("gray", S_BAR)} ` : ""
1104
+ );
1105
+ return `${r2}${l2}`;
1106
+ }
1107
+ case "cancel": {
1108
+ const n3 = this.options.filter(({ value: s }) => o.includes(s)).map((s) => u3(s, "cancelled")).join(styleText2("dim", ", "));
1109
+ if (n3.trim() === "")
1110
+ return `${r2}${styleText2("gray", S_BAR)}`;
1111
+ const l2 = wrapTextWithPrefix(
1112
+ i2.output,
1113
+ n3,
1114
+ t2 ? `${styleText2("gray", S_BAR)} ` : ""
1115
+ );
1116
+ return `${r2}${l2}${t2 ? `
1117
+ ${styleText2("gray", S_BAR)}` : ""}`;
1118
+ }
1119
+ case "error": {
1120
+ const n3 = t2 ? `${styleText2("yellow", S_BAR)} ` : "", l2 = this.error.split(`
1121
+ `).map(
1122
+ ($, v) => v === 0 ? `${t2 ? `${styleText2("yellow", S_BAR_END)} ` : ""}${styleText2("yellow", $)}` : ` ${$}`
1123
+ ).join(`
1124
+ `), s = r2.split(`
1125
+ `).length, h2 = l2.split(`
1126
+ `).length + 1;
1127
+ return `${r2}${n3}${limitOptions({
1128
+ output: i2.output,
1129
+ options: this.options,
1130
+ cursor: this.cursor,
1131
+ maxItems: i2.maxItems,
1132
+ columnPadding: n3.length,
1133
+ rowPadding: s + h2,
1134
+ style: g
1135
+ }).join(`
1136
+ ${n3}`)}
1137
+ ${l2}
1138
+ `;
1139
+ }
1140
+ default: {
1141
+ const n3 = t2 ? `${styleText2("cyan", S_BAR)} ` : "", l2 = r2.split(`
1142
+ `).length, s = x ? formatInstructionFooter(MULTISELECT_INSTRUCTIONS, t2) : t2 ? [styleText2("cyan", S_BAR_END)] : [], h2 = s.join(`
1143
+ `), $ = s.length + 1;
1144
+ return `${r2}${n3}${limitOptions({
1145
+ output: i2.output,
1146
+ options: this.options,
1147
+ cursor: this.cursor,
1148
+ maxItems: i2.maxItems,
1149
+ columnPadding: n3.length,
1150
+ rowPadding: l2 + $,
1151
+ style: g
1152
+ }).join(`
1153
+ ${n3}`)}
1154
+ ${h2}
1155
+ `;
1156
+ }
1157
+ }
1158
+ }
1159
+ }).prompt();
1160
+ };
1161
+ var log = {
1162
+ message: (s = [], {
1163
+ symbol: e = styleText2("gray", S_BAR),
1164
+ secondarySymbol: r2 = styleText2("gray", S_BAR),
1165
+ output: m2 = process.stdout,
1166
+ spacing: l2 = 1,
1167
+ withGuide: c2
1168
+ } = {}) => {
1169
+ const t2 = [], o = c2 ?? settings.withGuide, f = o ? r2 : "", O = o ? `${e} ` : "", u3 = o ? `${r2} ` : "";
1170
+ for (let i2 = 0; i2 < l2; i2++)
1171
+ t2.push(f);
1172
+ const g = Array.isArray(s) ? s : s.split(`
1173
+ `);
1174
+ if (g.length > 0) {
1175
+ const [i2, ...y2] = g;
1176
+ i2.length > 0 ? t2.push(`${O}${i2}`) : t2.push(o ? e : "");
1177
+ for (const p of y2)
1178
+ p.length > 0 ? t2.push(`${u3}${p}`) : t2.push(o ? r2 : "");
1179
+ }
1180
+ m2.write(`${t2.join(`
1181
+ `)}
1182
+ `);
1183
+ },
1184
+ info: (s, e) => {
1185
+ log.message(s, { ...e, symbol: styleText2("blue", S_INFO) });
1186
+ },
1187
+ success: (s, e) => {
1188
+ log.message(s, { ...e, symbol: styleText2("green", S_SUCCESS) });
1189
+ },
1190
+ step: (s, e) => {
1191
+ log.message(s, { ...e, symbol: styleText2("green", S_STEP_SUBMIT) });
1192
+ },
1193
+ warn: (s, e) => {
1194
+ log.message(s, { ...e, symbol: styleText2("yellow", S_WARN) });
1195
+ },
1196
+ /** alias for `log.warn()`. */
1197
+ warning: (s, e) => {
1198
+ log.warn(s, e);
1199
+ },
1200
+ error: (s, e) => {
1201
+ log.message(s, { ...e, symbol: styleText2("red", S_ERROR) });
1202
+ }
1203
+ };
1204
+ var cancel = (o = "", t2) => {
1205
+ const i2 = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_END)} ` : "";
1206
+ i2.write(`${e}${styleText2("red", o)}
1207
+
1208
+ `);
1209
+ };
1210
+ var intro = (o = "", t2) => {
1211
+ const i2 = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_START)} ` : "";
1212
+ i2.write(`${e}${o}
1213
+ `);
1214
+ };
1215
+ var outro = (o = "", t2) => {
1216
+ const i2 = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR)}
1217
+ ${styleText2("gray", S_BAR_END)} ` : "";
1218
+ i2.write(`${e}${o}
1219
+
1220
+ `);
1221
+ };
1222
+ var W$1 = (o) => o;
1223
+ var C = (o, e, s) => {
1224
+ const a2 = {
1225
+ hard: true,
1226
+ trim: false
1227
+ }, i2 = wrapAnsi(o, e, a2).split(`
1228
+ `), c2 = i2.reduce((n3, t2) => Math.max(dist_default2(t2), n3), 0), u3 = i2.map(s).reduce((n3, t2) => Math.max(dist_default2(t2), n3), 0), g = e - (u3 - c2);
1229
+ return wrapAnsi(o, g, a2);
1230
+ };
1231
+ var note = (o = "", e = "", s) => {
1232
+ const a2 = s?.output ?? process$1.stdout, i2 = s?.withGuide ?? settings.withGuide, c2 = s?.format ?? W$1, g = ["", ...C(o, getColumns(a2) - 6, c2).split(`
1233
+ `).map(c2), ""], n3 = dist_default2(e), t2 = Math.max(
1234
+ g.reduce((m2, F) => {
1235
+ const O = dist_default2(F);
1236
+ return O > m2 ? O : m2;
1237
+ }, 0),
1238
+ n3
1239
+ ) + 2, h2 = g.map(
1240
+ (m2) => `${styleText2("gray", S_BAR)} ${m2}${" ".repeat(t2 - dist_default2(m2))}${styleText2("gray", S_BAR)}`
1241
+ ).join(`
1242
+ `), T = i2 ? `${styleText2("gray", S_BAR)}
1243
+ ` : "", l$1 = i2 ? S_CONNECT_LEFT : S_CORNER_BOTTOM_LEFT;
1244
+ a2.write(
1245
+ `${T}${styleText2("green", S_STEP_SUBMIT)} ${styleText2("reset", e)} ${styleText2(
1246
+ "gray",
1247
+ S_BAR_H.repeat(Math.max(t2 - n3 - 1, 1)) + S_CORNER_TOP_RIGHT
1248
+ )}
1249
+ ${h2}
1250
+ ${styleText2("gray", l$1 + S_BAR_H.repeat(t2 + 2) + S_CORNER_BOTTOM_RIGHT)}
1251
+ `
1252
+ );
1253
+ };
1254
+ var W = (l2) => styleText2("magenta", l2);
1255
+ var spinner = ({
1256
+ indicator: l2 = "dots",
1257
+ onCancel: h2,
1258
+ output: n3 = process.stdout,
1259
+ cancelMessage: G,
1260
+ errorMessage: O,
1261
+ frames: E = unicode ? ["◒", "◐", "◓", "◑"] : ["•", "o", "O", "0"],
1262
+ delay: F = unicode ? 80 : 120,
1263
+ signal: m2,
1264
+ ...I2
1265
+ } = {}) => {
1266
+ const u3 = isCI();
1267
+ let M, T, d = false, S = false, s = "", p, w = performance.now();
1268
+ const x = getColumns(n3), k = I2?.styleFrame ?? W, g = (e) => {
1269
+ const r2 = e > 1 ? O ?? settings.messages.error : G ?? settings.messages.cancel;
1270
+ S = e === 1, d && (a2(r2, e), S && typeof h2 == "function" && h2());
1271
+ }, f = () => g(2), i2 = () => g(1), A = () => {
1272
+ process.on("uncaughtExceptionMonitor", f), process.on("unhandledRejection", f), process.on("SIGINT", i2), process.on("SIGTERM", i2), process.on("exit", g), m2 && m2.addEventListener("abort", i2);
1273
+ }, H = () => {
1274
+ process.removeListener("uncaughtExceptionMonitor", f), process.removeListener("unhandledRejection", f), process.removeListener("SIGINT", i2), process.removeListener("SIGTERM", i2), process.removeListener("exit", g), m2 && m2.removeEventListener("abort", i2);
1275
+ }, y2 = () => {
1276
+ if (p === void 0) return;
1277
+ u3 && n3.write(`
1278
+ `);
1279
+ const r2 = wrapAnsi(p, x, {
1280
+ hard: true,
1281
+ trim: false
1282
+ }).split(`
1283
+ `);
1284
+ r2.length > 1 && n3.write(import_sisteransi2.cursor.up(r2.length - 1)), n3.write(import_sisteransi2.cursor.to(0)), n3.write(import_sisteransi2.erase.down());
1285
+ }, C2 = (e) => e.replace(/\.+$/, ""), _ = (e) => {
1286
+ const r2 = (performance.now() - e) / 1e3, t2 = Math.floor(r2 / 60), o = Math.floor(r2 % 60);
1287
+ return t2 > 0 ? `[${t2}m ${o}s]` : `[${o}s]`;
1288
+ }, N = I2.withGuide ?? settings.withGuide, P = (e = "") => {
1289
+ d = true, M = block({ output: n3 }), s = C2(e), w = performance.now(), N && n3.write(`${styleText2("gray", S_BAR)}
1290
+ `);
1291
+ let r2 = 0, t2 = 0;
1292
+ A(), T = setInterval(() => {
1293
+ if (u3 && s === p)
1294
+ return;
1295
+ y2(), p = s;
1296
+ const o = k(E[r2]);
1297
+ let v;
1298
+ if (u3)
1299
+ v = `${o} ${s}...`;
1300
+ else if (l2 === "timer")
1301
+ v = `${o} ${s} ${_(w)}`;
1302
+ else {
1303
+ const B = ".".repeat(Math.floor(t2)).slice(0, 3);
1304
+ v = `${o} ${s}${B}`;
1305
+ }
1306
+ const j = wrapAnsi(v, x, {
1307
+ hard: true,
1308
+ trim: false
1309
+ });
1310
+ n3.write(j), r2 = r2 + 1 < E.length ? r2 + 1 : 0, t2 = t2 < 4 ? t2 + 0.125 : 0;
1311
+ }, F);
1312
+ }, a2 = (e = "", r2 = 0, t2 = false) => {
1313
+ if (!d) return;
1314
+ d = false, clearInterval(T), y2();
1315
+ const o = r2 === 0 ? styleText2("green", S_STEP_SUBMIT) : r2 === 1 ? styleText2("red", S_STEP_CANCEL) : styleText2("red", S_STEP_ERROR);
1316
+ s = e ?? s, t2 || (l2 === "timer" ? n3.write(`${o} ${s} ${_(w)}
1317
+ `) : n3.write(`${o} ${s}
1318
+ `)), H(), M();
1319
+ };
1320
+ return {
1321
+ start: P,
1322
+ stop: (e = "") => a2(e, 0),
1323
+ message: (e = "") => {
1324
+ s = C2(e ?? s);
1325
+ },
1326
+ cancel: (e = "") => a2(e, 1),
1327
+ error: (e = "") => a2(e, 2),
1328
+ clear: () => a2("", 0, true),
1329
+ get isCancelled() {
1330
+ return S;
1331
+ }
1332
+ };
1333
+ };
1334
+ var u2 = {
1335
+ light: unicodeOr("─", "-"),
1336
+ heavy: unicodeOr("━", "="),
1337
+ block: unicodeOr("█", "#")
1338
+ };
1339
+ var SELECT_INSTRUCTIONS = [
1340
+ `${styleText2("dim", "↑/↓")} to navigate`,
1341
+ `${styleText2("dim", "Enter:")} confirm`
1342
+ ];
1343
+ var c = (t2, o) => t2.includes(`
1344
+ `) ? t2.split(`
1345
+ `).map((d) => o(d)).join(`
1346
+ `) : o(t2);
1347
+ var select = (t2) => {
1348
+ const o = (n3, m2) => {
1349
+ if (n3 === void 0)
1350
+ return "";
1351
+ const s = n3.label ?? String(n3.value);
1352
+ switch (m2) {
1353
+ case "disabled":
1354
+ return `${styleText2("gray", S_RADIO_INACTIVE)} ${c(s, (i2) => styleText2("gray", i2))}${n3.hint ? ` ${styleText2("dim", `(${n3.hint ?? "disabled"})`)}` : ""}`;
1355
+ case "selected":
1356
+ return `${c(s, (i2) => styleText2("dim", i2))}`;
1357
+ case "active":
1358
+ return `${styleText2("green", S_RADIO_ACTIVE)} ${s}${n3.hint ? ` ${styleText2("dim", `(${n3.hint})`)}` : ""}`;
1359
+ case "cancelled":
1360
+ return `${c(s, (i2) => styleText2(["strikethrough", "dim"], i2))}`;
1361
+ default:
1362
+ return `${styleText2("dim", S_RADIO_INACTIVE)} ${c(s, (i2) => styleText2("dim", i2))}`;
1363
+ }
1364
+ }, d = t2.showInstructions ?? true;
1365
+ return new n$1({
1366
+ options: t2.options,
1367
+ signal: t2.signal,
1368
+ input: t2.input,
1369
+ output: t2.output,
1370
+ initialValue: t2.initialValue,
1371
+ render() {
1372
+ const n3 = t2.withGuide ?? settings.withGuide, m2 = `${symbol(this.state)} `, s = `${symbolBar(this.state)} `, i2 = wrapTextWithPrefix(
1373
+ t2.output,
1374
+ t2.message,
1375
+ s,
1376
+ m2
1377
+ ), u3 = `${n3 ? `${styleText2("gray", S_BAR)}
1378
+ ` : ""}${i2}
1379
+ `;
1380
+ switch (this.state) {
1381
+ case "submit": {
1382
+ const r2 = n3 ? `${styleText2("gray", S_BAR)} ` : "", a2 = wrapTextWithPrefix(
1383
+ t2.output,
1384
+ o(this.options[this.cursor], "selected"),
1385
+ r2
1386
+ );
1387
+ return `${u3}${a2}`;
1388
+ }
1389
+ case "cancel": {
1390
+ const r2 = n3 ? `${styleText2("gray", S_BAR)} ` : "", a2 = wrapTextWithPrefix(
1391
+ t2.output,
1392
+ o(this.options[this.cursor], "cancelled"),
1393
+ r2
1394
+ );
1395
+ return `${u3}${a2}${n3 ? `
1396
+ ${styleText2("gray", S_BAR)}` : ""}`;
1397
+ }
1398
+ default: {
1399
+ const r2 = n3 ? `${styleText2("cyan", S_BAR)} ` : "", a2 = u3.split(`
1400
+ `).length, p = d ? formatInstructionFooter(SELECT_INSTRUCTIONS, n3) : n3 ? [styleText2("cyan", S_BAR_END)] : [], f = p.join(`
1401
+ `), b = p.length + 1;
1402
+ return `${u3}${r2}${limitOptions({
1403
+ output: t2.output,
1404
+ cursor: this.cursor,
1405
+ options: this.options,
1406
+ maxItems: t2.maxItems,
1407
+ columnPadding: r2.length,
1408
+ rowPadding: a2 + b,
1409
+ style: (g, x) => o(g, g.disabled ? "disabled" : x ? "active" : "inactive")
1410
+ }).join(`
1411
+ ${r2}`)}
1412
+ ${f}
1413
+ `;
1414
+ }
1415
+ }
1416
+ }
1417
+ }).prompt();
1418
+ };
1419
+ var i = `${styleText2("gray", S_BAR)} `;
1420
+ var text = (t2) => new n2({
1421
+ validate: t2.validate,
1422
+ placeholder: t2.placeholder,
1423
+ defaultValue: t2.defaultValue,
1424
+ initialValue: t2.initialValue,
1425
+ output: t2.output,
1426
+ signal: t2.signal,
1427
+ input: t2.input,
1428
+ render() {
1429
+ const r2 = t2?.withGuide ?? settings.withGuide, l2 = `${`${r2 ? `${styleText2("gray", S_BAR)}
1430
+ ` : ""}${symbol(this.state)} `}${t2.message}
1431
+ `, d = t2.placeholder && t2.placeholder.length > 0 ? (
1432
+ // biome-ignore lint/style/noNonNullAssertion: guarded by placeholder.length > 0
1433
+ styleText2("inverse", t2.placeholder[0]) + styleText2("dim", t2.placeholder.slice(1))
1434
+ ) : styleText2(["inverse", "hidden"], "_"), o = this.userInput ? this.userInputWithCursor : d, s = this.value ?? "";
1435
+ switch (this.state) {
1436
+ case "validating": {
1437
+ const n3 = r2 ? `${styleText2("cyan", S_BAR)} ` : "", i2 = r2 ? styleText2("cyan", S_BAR_END) : "", c2 = styleText2("dim", o), $ = styleText2("dim", "Validating...");
1438
+ return `${l2}${n3}${c2}
1439
+ ${i2} ${$}
1440
+ `;
1441
+ }
1442
+ case "error": {
1443
+ const n3 = this.error ? ` ${styleText2("yellow", this.error)}` : "", i2 = r2 ? `${styleText2("yellow", S_BAR)} ` : "", c2 = r2 ? styleText2("yellow", S_BAR_END) : "";
1444
+ return `${l2.trim()}
1445
+ ${i2}${o}
1446
+ ${c2}${n3}
1447
+ `;
1448
+ }
1449
+ case "submit": {
1450
+ const n3 = s ? `${r2 ? " " : ""}${styleText2("dim", s)}` : "", i2 = r2 ? styleText2("gray", S_BAR) : "";
1451
+ return `${l2}${i2}${n3}`;
1452
+ }
1453
+ case "cancel": {
1454
+ const n3 = s ? ` ${styleText2(["strikethrough", "dim"], s)}` : "", i2 = r2 ? styleText2("gray", S_BAR) : "";
1455
+ return `${l2}${i2}${n3}${s.trim() ? `
1456
+ ${i2}` : ""}`;
1457
+ }
1458
+ default: {
1459
+ const n3 = r2 ? `${styleText2("cyan", S_BAR)} ` : "", i2 = r2 ? styleText2("cyan", S_BAR_END) : "";
1460
+ return `${l2}${n3}${o}
1461
+ ${i2}
1462
+ `;
1463
+ }
1464
+ }
1465
+ }
1466
+ }).prompt();
1467
+
1468
+ // src/agent/offer/blueprints.ts
1469
+ var BLUEPRINTS = [
1470
+ {
1471
+ value: "generic",
1472
+ label: "Generic",
1473
+ hint: "a delegating assistant, and the one to start from",
1474
+ about: "A delegating assistant: it answers over A2A on a Workers AI model, hands self-contained work to a research sub-agent, and keeps one continuous, self-compacting conversation per caller with a durable memory. Its own Worker, its own wrangler config, its own tenant."
1475
+ }
1476
+ ];
1477
+ var blueprintOf = (arg) => BLUEPRINTS.find((blueprint2) => blueprint2.value === arg.toLowerCase());
1478
+
1479
+ // src/agent/offer/capabilities.ts
1480
+ var CAPABILITIES = [
1481
+ {
1482
+ value: "browser",
1483
+ label: "Read web pages",
1484
+ hint: "@dynamicagents/plugins/browser — needs the BROWSER binding"
1485
+ }
1486
+ ];
1487
+
1488
+ // src/agent/names.ts
1489
+ var TENANT_RE = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
1490
+ var TENANT_MIN = 2;
1491
+ var TENANT_MAX = 32;
1492
+ var LANGUAGE = /* @__PURE__ */ new Set([
1493
+ "arguments",
1494
+ "await",
1495
+ "break",
1496
+ "case",
1497
+ "catch",
1498
+ "class",
1499
+ "const",
1500
+ "constructor",
1501
+ "continue",
1502
+ "debugger",
1503
+ "default",
1504
+ "delete",
1505
+ "do",
1506
+ "else",
1507
+ "enum",
1508
+ "eval",
1509
+ "export",
1510
+ "extends",
1511
+ "false",
1512
+ "finally",
1513
+ "for",
1514
+ "function",
1515
+ "if",
1516
+ "implements",
1517
+ "import",
1518
+ "in",
1519
+ "instanceof",
1520
+ "interface",
1521
+ "let",
1522
+ "new",
1523
+ "null",
1524
+ "package",
1525
+ "private",
1526
+ "protected",
1527
+ "public",
1528
+ "return",
1529
+ "static",
1530
+ "super",
1531
+ "switch",
1532
+ "this",
1533
+ "throw",
1534
+ "true",
1535
+ "try",
1536
+ "typeof",
1537
+ "var",
1538
+ "void",
1539
+ "while",
1540
+ "with",
1541
+ "yield"
1542
+ ]);
1543
+ var RESERVED = /* @__PURE__ */ new Set([
1544
+ "run",
1545
+ "pipeline",
1546
+ "step",
1547
+ "env",
1548
+ "ctx",
1549
+ "name",
1550
+ "copy",
1551
+ "manifest",
1552
+ "plugins",
1553
+ "soul"
1554
+ ]);
1555
+ var COLLIDES = /* @__PURE__ */ new Map([
1556
+ ["a2a", "a2a"],
1557
+ ["agent-model", "agentModel"],
1558
+ ["create-a2-a-worker", "createA2AWorker"],
1559
+ ["define-agent", "defineAgent"],
1560
+ ["handle-artifact-route", "handleArtifactRoute"],
1561
+ ["host-manifest", "hostManifest"],
1562
+ ["manifest", "manifest"],
1563
+ ["plugins", "plugins"],
1564
+ ["step", "StepAgent"],
1565
+ ["task", "TaskHost"],
1566
+ ["turn-task", "turnTask"]
1567
+ ]);
1568
+ var MODEL_ID_RE = /^@cf\/[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*$/;
1569
+ function validateTenant(input) {
1570
+ const value = input.trim();
1571
+ if (value === "") return "Name it something.";
1572
+ if (value.length < TENANT_MIN || value.length > TENANT_MAX) {
1573
+ return `Between ${TENANT_MIN} and ${TENANT_MAX} characters.`;
1574
+ }
1575
+ if (!TENANT_RE.test(value)) {
1576
+ return "Lowercase letters, digits and single dashes, starting with a letter — like `support` or `release-notes`.";
1577
+ }
1578
+ const camel = camelCase(value);
1579
+ if (LANGUAGE.has(camel)) {
1580
+ return `\`${value}\` is a name JavaScript will not let the generated code declare. Pick another.`;
1581
+ }
1582
+ const collision = COLLIDES.get(value);
1583
+ if (collision !== void 0) {
1584
+ return `\`${value}\` would generate \`${collision}\`, which a generated module already has by that name. Pick another.`;
1585
+ }
1586
+ if (RESERVED.has(camel)) {
1587
+ return `\`${value}\` is a name the generated classes already use for something else. Pick another.`;
1588
+ }
1589
+ return void 0;
1590
+ }
1591
+ function validateModelId(input) {
1592
+ const value = input.trim();
1593
+ if (value === "") return "Paste a model id.";
1594
+ if (!MODEL_ID_RE.test(value)) {
1595
+ return "A Workers AI model id looks like `@cf/<org>/<model>`.";
1596
+ }
1597
+ return void 0;
1598
+ }
1599
+ var words = (tenant2) => tenant2.split("-");
1600
+ var displayName = (tenant2) => words(tenant2).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
1601
+ var pascalCase = (tenant2) => words(tenant2).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
1602
+ var camelCase = (tenant2) => {
1603
+ const [first, ...rest] = words(tenant2);
1604
+ return (first ?? "") + rest.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
1605
+ };
1606
+ function names(tenant2) {
1607
+ const pascal = pascalCase(tenant2);
1608
+ const screaming = tenant2.replace(/-/g, "_").toUpperCase();
1609
+ return {
1610
+ tenant: tenant2,
1611
+ pascal,
1612
+ camel: camelCase(tenant2),
1613
+ screaming,
1614
+ dir: `src/agents/${tenant2}`,
1615
+ hostClass: `${pascal}Host`,
1616
+ workflowClass: `${pascal}Workflow`,
1617
+ agentClass: `${pascal}Agent`,
1618
+ childClass: `${pascal}Child`,
1619
+ workflowBinding: `${screaming}_WORKFLOW`,
1620
+ workflowName: `${tenant2}-workflow`
1621
+ };
1622
+ }
1623
+
1624
+ // src/cli/kinds.ts
1625
+ var KINDS = [
1626
+ {
1627
+ value: "gate",
1628
+ label: "Gate",
1629
+ hint: "where people and APIs reach your agents",
1630
+ about: "Gates are the interfaces humans or APIs interact with, like a Slack, WhatsApp or API gate.",
1631
+ ready: false
1632
+ },
1633
+ {
1634
+ value: "leader",
1635
+ label: "Leader",
1636
+ hint: "creates, edits and evaluates a group of agents",
1637
+ about: "A leader is a powerful agent that can create, edit and evaluate a group of agents.",
1638
+ ready: false
1639
+ },
1640
+ {
1641
+ value: "agent",
1642
+ label: "Agent",
1643
+ hint: "one agent, in a Worker of its own",
1644
+ about: "An agent in a deployable Cloudflare Worker of its own: its own wrangler config, its own bindings, its own signing key, reached over A2A as its own tenant. Nothing it does can affect another agent, and several can be brought into one Worker later.",
1645
+ ready: true
1646
+ }
1647
+ ];
1648
+ var kindOf = (arg) => KINDS.find((kind2) => kind2.value === arg.toLowerCase());
1649
+
1650
+ // src/train.ts
1651
+ var TRAIN = {
1652
+ core: ">=0.17.0 <0.18.0",
1653
+ plugins: ">=0.17.0 <0.18.0"
1654
+ };
1655
+ var RUNTIME = {
1656
+ "@cloudflare/think": ">=0.21.0 <0.22.0",
1657
+ agents: ">=0.30.0 <0.31.0",
1658
+ ai: "^7.0.88",
1659
+ /**
1660
+ * Think's own non-optional peer, and core's. A generated project gets it
1661
+ * whichever way, since npm installs a missing peer, so what naming it buys is
1662
+ * a manifest that says what the project runs on.
1663
+ */
1664
+ "@cloudflare/computer": "^0.5.1",
1665
+ "workers-ai-provider": "^4.0.0",
1666
+ /** The A2A protocol's own package: its constants and types. */
1667
+ "@a2a-js/sdk": "^1.2.0",
1668
+ /** A sub-agent's spec declares its input schema in zod. */
1669
+ zod: "^4.6.5"
1670
+ };
1671
+ var TOOLCHAIN = {
1672
+ /**
1673
+ * Paired with {@link WORKERD} as much as `wrangler` is: this pins the
1674
+ * miniflare a generated project's tests boot, and that runtime reads the
1675
+ * compatibility date too.
1676
+ */
1677
+ "@cloudflare/vitest-plugin": "^1.4.7",
1678
+ "@types/node": "^24.19.2",
1679
+ eslint: "^10.10.0",
1680
+ prettier: "^3.9.6",
1681
+ typescript: "^6.0.3",
1682
+ "typescript-eslint": "^8.72.0",
1683
+ /**
1684
+ * **4 until the Workers pool takes 5**, whatever this package tests itself
1685
+ * with. A generated project tests through `@cloudflare/vitest-plugin`, and
1686
+ * on vitest 5 that pool crashes workerd mid-run and the test file it was
1687
+ * running goes unreported — `cloudflare/workers-sdk#16331`, and core's own
1688
+ * `AGENTS.md` is the home of that ceiling and of what to re-check before
1689
+ * lifting it. The whole train sits below it or none of it does, so this
1690
+ * moves with core, plugins and starter and not before them. The caret is
1691
+ * what holds a new project clear in the meantime: an install takes the
1692
+ * newest the range allows, and on `^4` that can never be 5.
1693
+ */
1694
+ vitest: "^4.1.11",
1695
+ wrangler: "^4.152.0"
1696
+ };
1697
+ var WORKERD = "1.20261019.1";
1698
+ function compatibilityDateOf(workerd) {
1699
+ const stamp = /^\d+\.(\d{4})(\d{2})(\d{2})\.\d+$/.exec(workerd);
1700
+ if (stamp === null) {
1701
+ throw new Error(
1702
+ `train: "${workerd}" is not a workerd version (1.YYYYMMDD.N)`
1703
+ );
1704
+ }
1705
+ const [, year, month, day] = stamp;
1706
+ return `${year}-${month}-${day}`;
1707
+ }
1708
+ var COMPATIBILITY_DATE = compatibilityDateOf(WORKERD);
1709
+ var NODE_ENGINE = ">=24";
1710
+ var NODE_VERSION = "24";
1711
+ var DEFAULT_MODEL_ID = "@cf/zai-org/glm-5.3-flash";
1712
+ var MODELS_URL = "https://developers.cloudflare.com/ai/models/";
1713
+
1714
+ // src/cli/messages.ts
1715
+ var WEBSITE = "https://dynamicagents.dev";
1716
+ var title = (version2) => `Dynamic Agents · create-dynamicagents v${version2}`;
1717
+ var question = "What would you like to build?";
1718
+ var whichAgent = "Which agent do you want to create?";
1719
+ var workInProgress = (kind2) => `${kind2.label} scaffolding is a work in progress. Follow updates at ${WEBSITE}`;
1720
+ var nothingBuilt = "Nothing was built.";
1721
+ var width = Math.max(...KINDS.map((kind2) => kind2.value.length));
1722
+ var choices = () => KINDS.map((kind2) => ` ${kind2.value.padEnd(width)} ${kind2.hint}`).join("\n");
1723
+ var COMMAND = "npm create dynamicagents@latest";
1724
+ var DASH_NOTE = "The `--` is npm's, not ours: without it npm keeps the flags for itself.";
1725
+ var FLAGS = [
1726
+ {
1727
+ key: "name",
1728
+ spelled: "--name <tenant>",
1729
+ answers: "its tenant id, and every name derived from it"
1730
+ },
1731
+ {
1732
+ key: "description",
1733
+ spelled: "--description <line>",
1734
+ answers: "one line for its card, and its soul's first line"
1735
+ },
1736
+ {
1737
+ key: "dir",
1738
+ spelled: "--dir <path>",
1739
+ answers: "where to write it, if not a directory named for it"
1740
+ },
1741
+ {
1742
+ key: "model",
1743
+ spelled: "--model <id>",
1744
+ answers: "a Workers AI model id — see the catalogue"
1745
+ },
1746
+ {
1747
+ key: "subagent",
1748
+ spelled: "--no-subagent",
1749
+ answers: "leave out the sub-agent it hands research to"
1750
+ },
1751
+ {
1752
+ key: "browser",
1753
+ spelled: "--browser",
1754
+ answers: "install the browser plugin, its binding, its skill"
1755
+ },
1756
+ { key: "yes", spelled: "--yes", answers: "do not ask for confirmation" },
1757
+ {
1758
+ key: "dry-run",
1759
+ spelled: "--dry-run",
1760
+ answers: "print what would be written, and write nothing"
1761
+ },
1762
+ { key: "help", spelled: "--help, -h", answers: "what you are reading" },
1763
+ {
1764
+ key: "version",
1765
+ spelled: "--version, -v",
1766
+ answers: "the version that would run"
1767
+ }
1768
+ ];
1769
+ var flagColumn = Math.max(...FLAGS.map((flag) => flag.spelled.length));
1770
+ var listed = () => FLAGS.map(
1771
+ (flag) => ` ${flag.spelled.padEnd(flagColumn)} ${flag.answers}`
1772
+ ).join("\n");
1773
+ var example = (indent) => [
1774
+ `${indent}${COMMAND} agent ${BLUEPRINTS[0].value} <dir> -- \\`,
1775
+ `${indent} --name <tenant> --description "<one line>" --yes`
1776
+ ].join("\n");
1777
+ var help = (version2) => [
1778
+ title(version2),
1779
+ "",
1780
+ "Create gates, leaders and agents on Dynamic Agents.",
1781
+ "",
1782
+ "Usage",
1783
+ ` ${COMMAND}`,
1784
+ " Ask what to build, and ask for every answer.",
1785
+ "",
1786
+ example(" "),
1787
+ " Answer up front. A usable answer is not asked for; one that",
1788
+ " will not do is said where it was given.",
1789
+ "",
1790
+ "What it can build",
1791
+ choices(),
1792
+ "",
1793
+ "Flags",
1794
+ listed(),
1795
+ "",
1796
+ DASH_NOTE
1797
+ ].join("\n");
1798
+ var noTerminal = () => [
1799
+ "No terminal to ask in, so name what to build and answer for it:",
1800
+ "",
1801
+ choices(),
1802
+ "",
1803
+ example(""),
1804
+ "",
1805
+ "Flags",
1806
+ listed(),
1807
+ "",
1808
+ DASH_NOTE
1809
+ ].join("\n");
1810
+ var badArgument = (trouble) => [
1811
+ "unknown" in trouble ? unknownFlags(trouble.unknown) : trouble.message,
1812
+ "",
1813
+ "Flags",
1814
+ listed(),
1815
+ "",
1816
+ DASH_NOTE
1817
+ ].join("\n");
1818
+ var unknownFlags = (flags2) => {
1819
+ const quoted2 = flags2.map((flag) => `\`${flag}\``).join(", ");
1820
+ return flags2.length === 1 ? `${quoted2} is not a flag this takes.` : `${quoted2} are not flags this takes.`;
1821
+ };
1822
+ var badValue = (named, value, problem) => [
1823
+ `\`${named} ${JSON.stringify(value)}\` will not do:`,
1824
+ "",
1825
+ ` ${problem}`
1826
+ ].join("\n");
1827
+ var unknownKind = (arg) => [`"${arg}" is not something to build. Name one of:`, "", choices()].join(
1828
+ "\n"
1829
+ );
1830
+ var unknownBlueprint = (arg) => [
1831
+ `"${arg}" is not an agent this can create. Name one of:`,
1832
+ "",
1833
+ BLUEPRINTS.map((b) => ` ${b.value} ${b.hint}`).join("\n")
1834
+ ].join("\n");
1835
+ var askTenant = "What should the agent be called?";
1836
+ var tenantPlaceholder = "support";
1837
+ var askDescription = "In one line, what does it do?";
1838
+ var descriptionPlaceholder = "Answers product questions from the handbook";
1839
+ var askSubAgent = "Give it a sub-agent to hand research to?";
1840
+ var askCapabilities = "Anything else it can do? (space to pick, enter for none)";
1841
+ var askModel = "Which model should it run on?";
1842
+ var defaultModelLabel = `The default — ${DEFAULT_MODEL_ID}`;
1843
+ var otherModelLabel = (hyperlinks2) => `Another one — paste an id from ${link(MODELS_URL, MODELS_URL, hyperlinks2)}`;
1844
+ var askModelId = "Paste the model id";
1845
+ var link = (url, label, hyperlinks2) => hyperlinks2 ? `\x1B]8;;${url}\x07${label}\x1B]8;;\x07` : url;
1846
+ var confirmWrite = "Write it?";
1847
+ function tree(dir, files) {
1848
+ const top = files.filter((file) => !file.path.includes("/")).map((file) => file.path);
1849
+ const dirs = /* @__PURE__ */ new Map();
1850
+ for (const file of files) {
1851
+ const at = file.path.lastIndexOf("/");
1852
+ if (at === -1) continue;
1853
+ const parent = file.path.slice(0, at);
1854
+ dirs.set(parent, (dirs.get(parent) ?? 0) + 1);
1855
+ }
1856
+ const lines = [`${dir}/`];
1857
+ for (const [parent, count] of dirs) {
1858
+ lines.push(` ${parent}/ — ${count === 1 ? "one file" : `${count} files`}`);
1859
+ }
1860
+ lines.push(` ${top.join(" · ")}`);
1861
+ return lines.join("\n");
1862
+ }
1863
+ function nextSteps(dir, tenant2) {
1864
+ return [
1865
+ `cd ${dir}`,
1866
+ "npm run keygen # one signing key — put it in .env",
1867
+ "npm run check # types, format, lint, typecheck",
1868
+ "npm test # the suite, in real workerd",
1869
+ "npm run dev # and when you are ready: npm run deploy",
1870
+ "",
1871
+ `Then write src/agents/${tenant2}/soul.ts — it is the one part nobody else`,
1872
+ `can write for you — and register the tenant \`${tenant2}\` with your`,
1873
+ "gatekeeper at https://<your-worker>/a2a",
1874
+ "",
1875
+ "README.md has the rest; AGENTS.md has the rules."
1876
+ ].join("\n");
1877
+ }
1878
+ var installing = "Installing";
1879
+ var installed = "Installed";
1880
+ var wrote = (dir) => `Wrote ${dir}`;
1881
+ var outroLine = (name) => `${name} is ready. Write its soul, then deploy it.`;
1882
+ var dryRun = "Nothing was written: this was a dry run.";
1883
+ var notEmpty = (named) => `\`${named}\` already has something in it. Name a directory that does not exist yet, or an empty one.`;
1884
+ var cannotRead = (named, problem) => [
1885
+ `\`${named}\` cannot be read, so there is no telling what is there:`,
1886
+ "",
1887
+ ` ${problem}`,
1888
+ "",
1889
+ "Name a directory that does not exist yet, or one you can write to."
1890
+ ].join("\n");
1891
+ var noDescription = () => "Say in one line what the agent does: it goes on its card, and it is the first line of its soul.";
1892
+ var describeTooLong = () => "One line, please — this goes on the agent's card. Say the rest in its soul once it exists.";
1893
+ var describeOneLine = () => "One line means one line: no line breaks. It goes on the agent's card and into its source. Say the rest in its soul once it exists.";
1894
+ var finishByHand = (dir, problem) => [
1895
+ problem,
1896
+ "",
1897
+ `The project is written. Finish it with:`,
1898
+ "",
1899
+ ` cd ${dir}`,
1900
+ " npm install",
1901
+ " npx wrangler types"
1902
+ ].join("\n");
1903
+ var notInstalled = (name) => `${name} is written, but its install did not finish. Run the commands above, then README.md has the rest.`;
1904
+
1905
+ // src/cli/answers.ts
1906
+ var DESCRIPTION_MAX = 200;
1907
+ var LINE_BREAK = /[\n\r\u2028\u2029]/;
1908
+ var asKind = (raw) => {
1909
+ const kind2 = kindOf(raw);
1910
+ return kind2 === void 0 ? { problem: unknownKind(raw) } : { value: kind2 };
1911
+ };
1912
+ var asBlueprint = (raw) => {
1913
+ const blueprint2 = blueprintOf(raw);
1914
+ return blueprint2 === void 0 ? { problem: unknownBlueprint(raw) } : { value: blueprint2 };
1915
+ };
1916
+ var asTenant = (raw) => {
1917
+ const problem = validateTenant(raw);
1918
+ return problem === void 0 ? { value: raw.trim() } : { problem };
1919
+ };
1920
+ var asDescription = (raw) => {
1921
+ const value = raw.trim();
1922
+ if (value === "") return { problem: noDescription() };
1923
+ if (LINE_BREAK.test(value)) return { problem: describeOneLine() };
1924
+ if (value.length > DESCRIPTION_MAX) return { problem: describeTooLong() };
1925
+ return { value };
1926
+ };
1927
+ var asModelId = (raw) => {
1928
+ const problem = validateModelId(raw);
1929
+ return problem === void 0 ? { value: raw.trim() } : { problem };
1930
+ };
1931
+ var whyNot = (judge) => (value) => {
1932
+ const judged = judge(value ?? "");
1933
+ return "problem" in judged ? judged.problem : void 0;
1934
+ };
1935
+ function replyTo(given, judge, where) {
1936
+ if (given === void 0) {
1937
+ if (where.interactive) return { kind: "ask" };
1938
+ if (where.fallback !== void 0) {
1939
+ return { kind: "use", value: where.fallback };
1940
+ }
1941
+ return { kind: "stop", problem: noTerminal() };
1942
+ }
1943
+ const judged = judge(given);
1944
+ if (!("problem" in judged)) return { kind: "use", value: judged.value };
1945
+ if (where.interactive) {
1946
+ return { kind: "ask", problem: judged.problem, initial: given };
1947
+ }
1948
+ return {
1949
+ kind: "stop",
1950
+ problem: where.named === void 0 ? judged.problem : badValue(where.named, given, judged.problem)
1951
+ };
1952
+ }
1953
+
1954
+ // src/cli/args.ts
1955
+ import { parseArgs } from "node:util";
1956
+ var OPTIONS = {
1957
+ name: { type: "string" },
1958
+ description: { type: "string" },
1959
+ dir: { type: "string" },
1960
+ model: { type: "string" },
1961
+ subagent: { type: "boolean" },
1962
+ browser: { type: "boolean" },
1963
+ yes: { type: "boolean" },
1964
+ "dry-run": { type: "boolean" },
1965
+ help: { type: "boolean", short: "h" },
1966
+ version: { type: "boolean", short: "v" }
1967
+ };
1968
+ var parse = (args) => parseArgs({
1969
+ args: [...args],
1970
+ allowPositionals: true,
1971
+ allowNegative: true,
1972
+ options: OPTIONS
1973
+ });
1974
+ function unknownIn(args) {
1975
+ const { tokens } = parseArgs({
1976
+ args: [...args],
1977
+ allowPositionals: true,
1978
+ allowNegative: true,
1979
+ strict: false,
1980
+ tokens: true,
1981
+ options: OPTIONS
1982
+ });
1983
+ const declared = new Set(Object.keys(OPTIONS));
1984
+ const unknown = [];
1985
+ for (const token of tokens) {
1986
+ if (token.kind !== "option") continue;
1987
+ if (declared.has(token.name)) continue;
1988
+ if (!unknown.includes(token.rawName)) unknown.push(token.rawName);
1989
+ }
1990
+ return unknown;
1991
+ }
1992
+ function read(args) {
1993
+ let values;
1994
+ let positionals2;
1995
+ try {
1996
+ ({ values, positionals: positionals2 } = parse(args));
1997
+ } catch (err) {
1998
+ const { code, message } = err;
1999
+ if (code === "ERR_PARSE_ARGS_UNKNOWN_OPTION") {
2000
+ const unknown = unknownIn(args);
2001
+ if (unknown.length > 0) return { want: "trouble", trouble: { unknown } };
2002
+ }
2003
+ return { want: "trouble", trouble: { message } };
2004
+ }
2005
+ if (values.help === true) return { want: "help" };
2006
+ if (values.version === true) return { want: "version" };
2007
+ return { want: "run", flags: values, positionals: positionals2 };
2008
+ }
2009
+
2010
+ // src/cli/install.ts
2011
+ import { execFile } from "node:child_process";
2012
+ import { promisify } from "node:util";
2013
+ var run = promisify(execFile);
2014
+ var NPM_TIMEOUT_MS = 10 * 6e4;
2015
+ var needsShell = (platform) => platform === "win32";
2016
+ async function npm(args, cwd) {
2017
+ try {
2018
+ await run("npm", args, {
2019
+ cwd,
2020
+ timeout: NPM_TIMEOUT_MS,
2021
+ maxBuffer: 32 * 1024 * 1024,
2022
+ windowsHide: true,
2023
+ shell: needsShell(process.platform)
2024
+ });
2025
+ } catch (err) {
2026
+ const { stderr, message } = err;
2027
+ const detail = (stderr ?? "").trim().split("\n").slice(-12).join("\n");
2028
+ throw new Error(
2029
+ `\`npm ${args.join(" ")}\` failed.
2030
+
2031
+ ${detail === "" ? message : detail}`
2032
+ );
2033
+ }
2034
+ }
2035
+ async function installProject(dir, report) {
2036
+ report("Installing dependencies");
2037
+ await npm(["install", "--no-audit", "--no-fund"], dir);
2038
+ report("Generating Worker types");
2039
+ await npm(["exec", "--", "wrangler", "types"], dir);
2040
+ }
2041
+
2042
+ // src/agent/templates/render.ts
2043
+ var MARKER = /^(?:\/\/|#|\*)\s*\$(when|end|block)\b(?:\s+(!?)([A-Za-z]\w*))?\s*$/;
2044
+ var TOKEN = /\$[A-Z][A-Z0-9_]*/g;
2045
+ function render(source, bindings = {}) {
2046
+ const when = bindings.when ?? {};
2047
+ const tokens = bindings.tokens ?? {};
2048
+ const lines = source.split("\n");
2049
+ const regionNames = /* @__PURE__ */ new Set();
2050
+ const tokenNames = /* @__PURE__ */ new Set();
2051
+ for (const line of lines) {
2052
+ const marker = MARKER.exec(line.trim());
2053
+ if (marker === null) {
2054
+ for (const token of line.match(TOKEN) ?? [])
2055
+ tokenNames.add(token.slice(1));
2056
+ continue;
2057
+ }
2058
+ const [, directive, negated, name] = marker;
2059
+ if (name === void 0) continue;
2060
+ if (directive === "when") regionNames.add(name);
2061
+ else if (directive === "block" && negated !== "!") tokenNames.add(name);
2062
+ }
2063
+ for (const name of Object.keys(when)) {
2064
+ if (!regionNames.has(name)) {
2065
+ throw new Error(`render: no "$when ${name}" region in this template`);
2066
+ }
2067
+ }
2068
+ for (const name of Object.keys(tokens)) {
2069
+ if (!tokenNames.has(name)) {
2070
+ throw new Error(`render: nothing in this template reads "$${name}"`);
2071
+ }
2072
+ }
2073
+ const bound = (name, what) => {
2074
+ const value = tokens[name];
2075
+ if (value === void 0) throw new Error(`render: "${what}" is not bound`);
2076
+ return value;
2077
+ };
2078
+ const kept = [];
2079
+ let open;
2080
+ for (const line of lines) {
2081
+ const marker = MARKER.exec(line.trim());
2082
+ if (marker === null) {
2083
+ if (open === void 0 || open.keep) {
2084
+ kept.push(line.replace(TOKEN, (token) => bound(token.slice(1), token)));
2085
+ }
2086
+ continue;
2087
+ }
2088
+ const [, directive, negated, name] = marker;
2089
+ if (directive === "block") {
2090
+ if (name === void 0 || negated === "!") {
2091
+ throw new Error(`render: "$block" names no token in "${line.trim()}"`);
2092
+ }
2093
+ if (open === void 0 || open.keep) {
2094
+ kept.push(bound(name, `$block ${name}`));
2095
+ }
2096
+ continue;
2097
+ }
2098
+ if (directive === "end") {
2099
+ if (name !== void 0) {
2100
+ throw new Error(`render: "$end" takes no name, got "${line.trim()}"`);
2101
+ }
2102
+ if (open === void 0) throw new Error('render: "$end" without "$when"');
2103
+ open = void 0;
2104
+ continue;
2105
+ }
2106
+ if (name === void 0) {
2107
+ throw new Error(`render: "$when" names no flag in "${line.trim()}"`);
2108
+ }
2109
+ if (open !== void 0) {
2110
+ throw new Error(
2111
+ `render: "$when ${name}" nested inside "$when ${open.name}"`
2112
+ );
2113
+ }
2114
+ const flag = when[name];
2115
+ if (flag === void 0) {
2116
+ throw new Error(`render: "$when ${name}" names an unbound flag`);
2117
+ }
2118
+ open = { name, keep: negated === "!" ? !flag : flag };
2119
+ }
2120
+ if (open !== void 0) {
2121
+ throw new Error(`render: "$when ${open.name}" is never closed`);
2122
+ }
2123
+ return kept.join("\n");
2124
+ }
2125
+
2126
+ // src/agent/templates/agent/agent.ts.tpl
2127
+ var agent_ts_default = 'import type { ThinkModel } from "@cloudflare/think";\nimport type { AgentPlugin } from "@dynamicagents/core";\nimport { StepAgent } from "@dynamicagents/core/agent";\n// $when subAgent\nimport type { SubAgentClass } from "@dynamicagents/core/subagent";\n// $end\nimport type { StepJob } from "@dynamicagents/core/workflow";\nimport type { ContextConfig } from "agents/context";\nimport type { LanguageModel } from "ai";\nimport { RETRY_BRIEF } from "@/copy";\nimport { agentModel } from "@/model";\n// $when subAgent\nimport { $CHILD_CLASS } from "./children";\n// $end\nimport { $CAMEL } from "./definition";\nimport { plugins } from "./plugins";\nimport { MEMORY, SOUL } from "./soul";\nimport { TUNING } from "./tuning";\n\n/**\n * $NAME.\n *\n * The turn is `@cloudflare/think`\'s, the step job and delegation are\n * `@dynamicagents/core/agent`\'s, and the A2A task around it is `./host.ts`\'s.\n * What is actually *this agent* is the members below plus `./plugins.ts`,\n * `./soul.ts`$SOUL_FILES and `./tuning.ts` — nothing else in this\n * project is specific to it.\n */\nexport class $AGENT_CLASS extends StepAgent<Env> {\n protected readonly compactAfterTokens = TUNING.compactAfterTokens;\n protected readonly keepRecentTokens = TUNING.keepRecentTokens;\n\n override getModel(): ThinkModel {\n return agentModel(\n this.env,\n { modelId: TUNING.modelId, name: this.name },\n {\n agent: $CAMEL.tenant,\n taskId: this.turnTaskId(),\n phase: "turn"\n }\n );\n }\n\n /** Compaction runs over a history every task shares, so it has no task. */\n protected override compactionModel(): LanguageModel {\n return agentModel(\n this.env,\n { modelId: TUNING.compactionModelId, name: this.name },\n {\n agent: $CAMEL.tenant,\n phase: "compaction"\n }\n );\n }\n\n override configureContext(): ContextConfig[] {\n return [\n { label: "soul", provider: { get: async () => SOUL } },\n { label: "memory", description: MEMORY },\n ...super.configureContext()\n ];\n }\n\n override getPlugins(): AgentPlugin<Env>[] {\n return plugins(this.env);\n }\n\n // $when subAgent\n override getSubAgents(): SubAgentClass[] {\n return [$CHILD_CLASS];\n }\n\n // $end\n /** A retry is told so, and to carry on from what the first attempt left. */\n protected override formatStepJobInput(job: StepJob): string {\n return job.attempt > 1 ? `${RETRY_BRIEF}\\n\\n${job.input}` : job.input;\n }\n}\n';
2128
+
2129
+ // src/agent/templates/agent/agent.ts
2130
+ var agentTs = (spec2, n3) => render(agent_ts_default, {
2131
+ when: { subAgent: spec2.subAgent },
2132
+ tokens: {
2133
+ NAME: spec2.name,
2134
+ AGENT_CLASS: n3.agentClass,
2135
+ CAMEL: n3.camel,
2136
+ CHILD_CLASS: n3.childClass,
2137
+ // Mid-sentence in the class's doc comment, listing the files that are
2138
+ // actually this agent — so a phrase rather than a region, which would
2139
+ // need a line of its own.
2140
+ SOUL_FILES: spec2.subAgent ? ", `./children.ts`" : ""
2141
+ }
2142
+ });
2143
+
2144
+ // src/agent/templates/agent/children.ts.tpl
2145
+ var children_ts_default = 'import type { ThinkModel } from "@cloudflare/think";\nimport type { AgentPlugin, SubAgentSpec } from "@dynamicagents/core";\nimport { SubAgent } from "@dynamicagents/core/subagent";\nimport { z } from "zod";\nimport { agentModel, turnTask } from "@/model";\nimport { $CAMEL } from "./definition";\nimport { plugins } from "./plugins";\nimport { GENERAL_SOUL } from "./soul";\nimport { TUNING } from "./tuning";\n\n/**\n * The catch-all: any self-contained unit of work with no domain of its own.\n *\n * **Awaited.** Research, drafting and reading a page finish well inside the\n * fifteen minutes a turn can last, so the parent waits for the result in the\n * same turn rather than answering in a later one. A sub-agent that may run\n * longer than a turn declares `detached: true` instead — there is nothing in\n * between.\n *\n * A spec is data; the class below binds it. Core refuses to lend a soul, so a\n * sub-agent\'s identity is written here and nowhere else.\n */\nconst GENERAL: SubAgentSpec<{ task: string }> = {\n name: "general",\n description:\n "Hand a self-contained piece of work to a sub-agent and wait for its result: research, drafting, summarizing. It cannot see this conversation, so put everything it needs in the task.",\n inputSchema: z.object({\n task: z\n .string()\n .describe(\n "The work, with everything needed to do it: the sub-agent sees nothing else"\n )\n }),\n soul: GENERAL_SOUL,\n formatInput: (input) => input.task\n};\n\nexport class $CHILD_CLASS extends SubAgent<Env> {\n static override spec = GENERAL as SubAgentSpec<never, never>;\n\n override getModel(): ThinkModel {\n return agentModel(\n this.env,\n { modelId: TUNING.modelId, name: this.name },\n {\n agent: $CAMEL.tenant,\n taskId: turnTask(this.activeTurnMetadata),\n phase: "subagent",\n subAgent: "$CHILD_CLASS"\n }\n );\n }\n\n override getPlugins(): AgentPlugin<Env>[] {\n return plugins(this.env);\n }\n}\n';
2146
+
2147
+ // src/agent/templates/agent/children.ts
2148
+ var childrenTs = (n3) => render(children_ts_default, {
2149
+ tokens: { CAMEL: n3.camel, CHILD_CLASS: n3.childClass }
2150
+ });
2151
+
2152
+ // src/agent/templates/agent/definition.ts.tpl
2153
+ var definition_ts_default = 'import { defineAgent } from "@dynamicagents/core/worker";\nimport { manifest } from "./manifest";\n\n/**\n * How this agent is reached: its tenant id, its card and its Durable Object,\n * declared once. `src/index.ts` mounts the tenant from this.\n *\n * The tenant id is a **public identifier**: a gatekeeper registers against it\n * and it rides in a JWT claim, so changing it later is a re-registration rather\n * than a rename. Every class and binding in this project derives from it.\n */\nexport const $CAMEL = defineAgent({\n tenant: "$TENANT",\n manifest,\n agent: (env: Env) => env.$HOST_CLASS\n});\n';
2154
+
2155
+ // src/agent/templates/agent/definition.ts
2156
+ var definitionTs = (spec2, n3) => render(definition_ts_default, {
2157
+ tokens: { CAMEL: n3.camel, TENANT: spec2.tenant, HOST_CLASS: n3.hostClass }
2158
+ });
2159
+
2160
+ // src/agent/templates/text.ts
2161
+ var PRINT_WIDTH = 80;
2162
+ function quoted(value) {
2163
+ const json = JSON.stringify(value);
2164
+ if (!value.includes('"') || value.includes("'")) return json;
2165
+ return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
2166
+ }
2167
+ function stringProp(key, value, indent = 2) {
2168
+ const pad = " ".repeat(indent);
2169
+ const literal = quoted(value);
2170
+ if (`${pad}${key}: ${literal},`.length <= PRINT_WIDTH) {
2171
+ return `${pad}${key}: ${literal}`;
2172
+ }
2173
+ return `${pad}${key}:
2174
+ ${pad} ${literal}`;
2175
+ }
2176
+ function namedFrom(keyword, names3, from) {
2177
+ const inline = `${keyword} { ${names3.join(", ")} } from ${quoted(from)};`;
2178
+ if (names3.length < 2 || inline.length <= PRINT_WIDTH) return inline;
2179
+ return `${keyword} {
2180
+ ${names3.map((name) => ` ${name}`).join(",\n")}
2181
+ } from ${quoted(from)};`;
2182
+ }
2183
+ function assigned(left, value, indent = 2) {
2184
+ const pad = " ".repeat(indent);
2185
+ const literal = quoted(value);
2186
+ const inline = `${pad}${left} = ${literal};`;
2187
+ if (inline.length <= PRINT_WIDTH) return inline;
2188
+ return `${pad}${left} =
2189
+ ${pad} ${literal};`;
2190
+ }
2191
+ function arrayProp(key, values, indent = 2) {
2192
+ const pad = " ".repeat(indent);
2193
+ const items = values.map(quoted);
2194
+ const inline = `${pad}${key}: [${items.join(", ")}],`;
2195
+ if (inline.length <= PRINT_WIDTH) {
2196
+ return `${pad}${key}: [${items.join(", ")}]`;
2197
+ }
2198
+ return `${pad}${key}: [
2199
+ ${items.map((item) => `${pad} ${item}`).join(",\n")}
2200
+ ${pad}]`;
2201
+ }
2202
+ var jsonArrayProp = (key, values, indent = 2) => arrayProp(quoted(key), values, indent);
2203
+ function jsonObject(entries, indent) {
2204
+ const pad = " ".repeat(indent);
2205
+ const pairs = entries.map(
2206
+ ([key, value]) => `${quoted(key)}: ${quoted(value)}`
2207
+ );
2208
+ const inline = `${pad}{ ${pairs.join(", ")} },`;
2209
+ if (inline.length <= PRINT_WIDTH) return `${pad}{ ${pairs.join(", ")} }`;
2210
+ return `${pad}{
2211
+ ${pairs.map((pair) => `${pad} ${pair}`).join(",\n")}
2212
+ ${pad}}`;
2213
+ }
2214
+ var jsonFile = (value) => `${JSON.stringify(value, null, 2)}
2215
+ `;
2216
+ function mdTable(headers, rows) {
2217
+ const widths = headers.map(
2218
+ (header, column) => Math.max(
2219
+ [...header].length,
2220
+ 3,
2221
+ ...rows.map((row) => [...row[column] ?? ""].length)
2222
+ )
2223
+ );
2224
+ const pad = (cell, column) => cell + " ".repeat(widths[column] - [...cell].length);
2225
+ const render2 = (cells) => `| ${cells.map((cell, column) => pad(cell, column)).join(" | ")} |`;
2226
+ return [
2227
+ render2(headers),
2228
+ `| ${widths.map((width2) => "-".repeat(width2)).join(" | ")} |`,
2229
+ ...rows.map(render2)
2230
+ ].join("\n");
2231
+ }
2232
+
2233
+ // src/agent/templates/agent/host.ts.tpl
2234
+ var host_ts_default = 'import { TaskHost } from "@dynamicagents/core/task";\nimport { copy } from "@/copy";\n\n/**\n * This tenant\'s task host: it owns each A2A task, keyed by the verified caller,\n * and `$WORKFLOW_CLASS` (`./workflow.ts`) runs it as steps. The mechanism is\n * core\'s `/task`; what is here is the words it says and the bindings it uses.\n *\n * **Cancellation is decided by core\'s guarded write, never by a probe.** The\n * ledger flips a task to `canceled` in one write and refuses every later write\n * against it, saying so. A hook added here runs after that flip and acts on it;\n * it never reads the task first and decides.\n *\n * Both bindings are typed `: string` rather than inferred, so a test can\n * subclass this host and point it at a scripted pipeline — `test/worker.ts`\n * does exactly that.\n */\nexport class $HOST_CLASS extends TaskHost<Env> {\n protected readonly copy = copy;\n // $block HOST_BINDINGS\n}\n';
2235
+
2236
+ // src/agent/templates/agent/host.ts
2237
+ var hostTs = (n3) => render(host_ts_default, {
2238
+ tokens: {
2239
+ HOST_CLASS: n3.hostClass,
2240
+ WORKFLOW_CLASS: n3.workflowClass,
2241
+ // Both break after the `=` once the line passes the print width, which a
2242
+ // long tenant id does on its own — so they keep `assigned` and arrive as
2243
+ // a block. `../../formatting.spec.ts` sweeps the ids that reach it.
2244
+ HOST_BINDINGS: [
2245
+ assigned(
2246
+ "protected readonly workflowBinding: string",
2247
+ n3.workflowBinding
2248
+ ),
2249
+ assigned("protected readonly hostBinding: string", n3.hostClass)
2250
+ ].join("\n")
2251
+ }
2252
+ });
2253
+
2254
+ // src/agent/templates/agent/manifest.ts.tpl
2255
+ var manifest_ts_default = 'import type { AgentManifest } from "@dynamicagents/core/a2a";\n\n/**\n * The transport-independent half of this agent\'s AgentCard — everything that\n * does not depend on the request origin. Core adds `supportedInterfaces` (the\n * deployment\'s `/a2a` url, tagged with this agent\'s tenant id) and the security\n * scheme. It is served through `GetExtendedAgentCard`, since the well-known\n * path carries the deployment\'s stub card — `src/host-manifest.ts`.\n *\n * `AgentManifest` is core\'s, derived from the A2A SDK\'s `AgentCard` rather than\n * hand-declared, so a protocol field that gains a requirement fails the build\n * here instead of silently going unadvertised.\n *\n * **The skills are what this agent has.** Adding a capability in\n * `./plugins.ts`, or a sub-agent in `./children.ts`, means a skill here;\n * removing one means removing it. Each skill\'s `inputModes`, `outputModes` and\n * `securityRequirements` are empty, which means "inherit the card\'s" — the\n * default modes below, and the gatekeeper JWT.\n */\nexport const manifest: AgentManifest = {\n // $block CARD_IDENTITY\n version: "0.1.0",\n // `extensions` is a required (repeated) protobuf field in v1.0, and this\n // agent declares no protocol extensions, so it stays empty.\n capabilities: { streaming: false, pushNotifications: true, extensions: [] },\n defaultInputModes: ["text/plain"],\n defaultOutputModes: ["text/plain"],\n skills: [\n // $block SKILLS\n ]\n};\n';
2256
+
2257
+ // src/agent/templates/agent/manifest.ts
2258
+ var CHAT = {
2259
+ id: "chat",
2260
+ name: "Chat",
2261
+ description: "Answer the caller on a Workers AI model, calling tools when useful.",
2262
+ tags: ["chat", "assistant"]
2263
+ };
2264
+ var DELEGATE = {
2265
+ id: "delegate",
2266
+ name: "Research and self-contained work",
2267
+ description: "Hand self-contained pieces of a request to sub-agents, several at once when it splits cleanly, then compose their results into one answer.",
2268
+ tags: ["research", "delegation"]
2269
+ };
2270
+ var BROWSE = {
2271
+ id: "browse",
2272
+ name: "Browse the web",
2273
+ description: "Read and scrape live web pages — render a page as Markdown, extract structured data, or list its links.",
2274
+ tags: ["web", "browser"]
2275
+ };
2276
+ var skill = (it) => {
2277
+ const props = [
2278
+ stringProp("id", it.id, 6),
2279
+ stringProp("name", it.name, 6),
2280
+ stringProp("description", it.description, 6),
2281
+ ` tags: [${it.tags.map(quoted).join(", ")}]`,
2282
+ " examples: []",
2283
+ " inputModes: []",
2284
+ " outputModes: []",
2285
+ " securityRequirements: []"
2286
+ ];
2287
+ return ` {
2288
+ ${props.join(",\n")}
2289
+ }`;
2290
+ };
2291
+ function manifestTs(spec2) {
2292
+ const skills = [
2293
+ CHAT,
2294
+ ...spec2.subAgent ? [DELEGATE] : [],
2295
+ ...spec2.capabilities.includes("browser") ? [BROWSE] : []
2296
+ ];
2297
+ return render(manifest_ts_default, {
2298
+ tokens: {
2299
+ /**
2300
+ * Trailing comma included, and it has to be: a block owns the separators
2301
+ * on its own boundaries, because `trailingComma: "none"` has prettier
2302
+ * strip a comma before what it reads as the last property, and a comment
2303
+ * marker is not a property it can read.
2304
+ */
2305
+ CARD_IDENTITY: `${[
2306
+ stringProp("name", spec2.name),
2307
+ stringProp("description", spec2.description)
2308
+ ].join(",\n")},`,
2309
+ SKILLS: skills.map(skill).join(",\n")
2310
+ }
2311
+ });
2312
+ }
2313
+
2314
+ // src/agent/templates/agent/plugins.ts.tpl
2315
+ var plugins_ts_default = 'import type { AgentPlugin } from "@dynamicagents/core";\n// $when browser\nimport { browser } from "@dynamicagents/plugins/browser";\n// $end\n\n/**\n * The one file you edit to add or remove a capability for this agent.\n *\n * Delete a line and that module leaves the bundle entirely. Nothing in core\n * imports a plugin, and `@dynamicagents/plugins` has no root barrel — the bare\n * specifier does not resolve — so what the agent carries is what is listed\n * here.\n *\n * A plugin declares the bindings and secrets it needs, and core checks them\n * when the agent starts: an installed plugin whose binding is missing from\n * `wrangler.jsonc` fails with a sentence naming the plugin, rather than at the\n * first tool call inside a request someone is waiting on. So a line here and a\n * binding there arrive together.\n *\n * What the model is told about a capability comes from the plugin itself, not\n * from `./soul.ts`: removing a line removes its advice with it.\n * $when subAgent\n *\n * The agent and its `general` sub-agent install the same list. Files are\n * Think\'s own workspace, in each object\'s SQLite, so there is nothing to\n * install for them.\n * $end\n */\n// $when browser\nexport const plugins = (env: Env): AgentPlugin<Env>[] => [\n // Read web pages. Needs the `BROWSER` binding in wrangler.jsonc.\n browser({ binding: env.BROWSER })\n];\n// $end\n// $when !browser\nexport const plugins = (_env: Env): AgentPlugin<Env>[] => [\n // Nothing installed yet. Each capability is one line here plus its binding\n // in wrangler.jsonc plus a skill on the card in ./manifest.ts — for example:\n //\n // import { browser } from "@dynamicagents/plugins/browser";\n // browser({ binding: env.BROWSER })\n //\n // The parameter is `_env` only because nothing reads it yet; the first\n // plugin that needs a binding takes the underscore off.\n];\n// $end\n';
2316
+
2317
+ // src/agent/templates/agent/plugins.ts
2318
+ var pluginsTs = (spec2) => render(plugins_ts_default, {
2319
+ when: {
2320
+ browser: spec2.capabilities.includes("browser"),
2321
+ subAgent: spec2.subAgent
2322
+ }
2323
+ });
2324
+
2325
+ // src/agent/templates/agent/soul.ts.tpl
2326
+ var soul_ts_default = 'import { ASK_GUIDANCE } from "@/copy";\n\n/**\n * This agent\'s soul — its identity and its operating rules.\n *\n * **This file is yours.** Core ships no prompt copy at all, deliberately: a run\n * must never execute under an identity nobody chose. What is below is a first\n * draft from one line of description — read it, and make it say what this agent\n * actually is.\n *\n * **Nothing about a capability belongs here.** Every installed plugin tells the\n * model what it can do in a context block of its own$SUBAGENT_NOTE, so removing one removes\n * its advice with it and this file never mentions something the agent cannot\n * do.\n */\nexport const SOUL = [\n $IDENTITY_LINE,\n "You are reached over the A2A protocol through the Dynamic Agents gatekeeper, on behalf of a person using whatever gate they came in through. Keep replies concise and actionable.",\n "If you cannot do something, or you lack the information, say so plainly rather than guessing.",\n \'A user turn can be wrapped by the gatekeeper in a `<turn from="Name" id="UID" channel="…" at="…">…</turn>` tag — treat those attributes as the authoritative speaker identity, and never author `<turn>` tags yourself.\',\n "The `caller` block only identifies which gatekeeper-agent dispatched this conversation, verified by the gatekeeper JWT — it is not the person speaking to you. Rely on the `<turn>` tag for that.",\n "You keep one continuous conversation with this caller across everything they ask, and a durable `memory` block of stable facts. Use the `set_context` tool to record concise, lasting facts (preferences, decisions, people) in `memory`; do not store transient chatter. `search_history` finds what was said earlier, even once it has scrolled out of view.",\n "Use your tools when they help answer the request, and never fabricate a tool result.",\n "",\n ASK_GUIDANCE\n].join("\\n");\n\n/** What the model is told the `memory` block is for. */\nexport const MEMORY =\n "Stable facts about this caller worth keeping across conversations: preferences, decisions, people. Not transient chatter.";\n// $when subAgent\n\n/**\n * The `general` sub-agent\'s soul.\n *\n * Distinct from the agent\'s own, and the distinction is structural rather than\n * stylistic: a sub-agent has no view of this conversation beyond the task it is\n * handed, so writing it as though it did is how it ends up asking a follow-up\n * question nobody will ever read.\n */\nexport const GENERAL_SOUL = [\n "You are a sub-agent. You are given a single, self-contained task with all necessary context supplied inline.",\n "Complete exactly that task and return a concise, direct result.",\n "Your result is raw material, not a reply: a parent agent composes it — often with other sub-agents\' results — into the single answer the person actually sees. You are never speaking to that person. Return only the substance: no greeting, no preamble, no restating the task, no sign-off.",\n "You have no memory of past conversations and no access to any conversation beyond what the task says.",\n "Do not ask follow-up questions; work only from what you are given.",\n "Use your tools when they help, and never fabricate a tool result."\n].join("\\n");\n// $end\n';
2327
+
2328
+ // src/agent/templates/agent/soul.ts
2329
+ function soulTs(spec2) {
2330
+ return render(soul_ts_default, {
2331
+ when: { subAgent: spec2.subAgent },
2332
+ tokens: {
2333
+ /**
2334
+ * The identity line, as a complete quoted literal rather than as bare
2335
+ * text in a hand-written `"…"`. A description may hold a double quote —
2336
+ * see the `LINE_BREAK` comment in `../../../cli/answers.ts` — and
2337
+ * `quoted()` is what picks the quote style and the escaping for it. The
2338
+ * two spaces of indentation are the file's, not this helper's.
2339
+ */
2340
+ IDENTITY_LINE: quoted(`You are ${spec2.name}. ${spec2.description}`),
2341
+ // Mid-sentence, and across a line break inside a block comment, which is
2342
+ // why it is a phrase and not a region.
2343
+ SUBAGENT_NOTE: spec2.subAgent ? ", and each sub-agent in its\n * tool's description" : ""
2344
+ }
2345
+ });
2346
+ }
2347
+
2348
+ // src/agent/templates/agent/tuning.ts.tpl
2349
+ var tuning_ts_default = "import type { Reconcile } from \"@dynamicagents/core/workflow\";\n\n/**\n * What this agent tunes. Core ships no numbers, so each one here is chosen.\n *\n * Plain exported values rather than anything resolved at import time: on\n * Workers there is no `env` at module scope, and the classes read these when an\n * object runs.\n */\nexport interface AgentTuning {\n /**\n * The Workers AI model the turn runs on. It must call tools reliably over a\n * long context, because a turn ends when the model stops calling them.\n * Every id is at $MODELS_URL\n */\n modelId: string;\n /**\n * The model compaction summarizes with, and **the turn waits for it** — so\n * this is a wall-clock decision on every compaction, not a detail. A smaller\n * model is the usual answer; a large conversation is where a small one starts\n * timing out.\n */\n compactionModelId: string;\n /**\n * Compact once the conversation's estimate crosses this.\n *\n * Compaction is also when Think re-renders the system prompt: until the next\n * one, the agent reads the soul and the memory as they stood when the prompt\n * was last rendered, no matter what has been deployed or written since.\n */\n compactAfterTokens: number;\n /** The recent tail compaction keeps verbatim. */\n keepRecentTokens: number;\n /**\n * How long the pipeline waits for its step job's next event before it pulls\n * the agent and the host for whatever it has not read. That is what an event\n * the platform accepts and never delivers costs: at worst `maxMs`, instead of\n * a task that waits for it forever.\n *\n * A wait that finds nothing doubles the next one, up to `maxMs`, so a\n * question left open for days costs a few hundred wakes out of the ten\n * thousand steps a Workflow instance holds. Lower `afterMs` to notice a lost\n * event sooner, at more wakes per task.\n */\n reconcile: Reconcile;\n}\n\n/**\n * Tight on purpose$WHY_TIGHT.\n * Raise `compactAfterTokens` when the agent keeps losing something it needed,\n * and watch what the turn costs.\n *\n * Watch the prompt too, not only the cost: that number is how stale a long\n * conversation's system prompt can get as much as it is how much each call\n * carries, and a conversation that never reaches it runs to its end on the\n * soul and the memory it started with.\n */\nexport const TUNING: AgentTuning = {\n modelId: $MODEL_ID,\n compactionModelId: $MODEL_ID,\n compactAfterTokens: 16_000,\n keepRecentTokens: 5_000,\n reconcile: { afterMs: 5 * 60_000, maxMs: 30 * 60_000 }\n};\n";
2350
+
2351
+ // src/agent/templates/agent/tuning.ts
2352
+ var tuningTs = (spec2) => render(tuning_ts_default, {
2353
+ tokens: {
2354
+ // A pin, read where it is written rather than copied into the template.
2355
+ MODELS_URL,
2356
+ // Both model ids, as complete quoted literals: a model id comes from the
2357
+ // catalogue or from `--model`, so `quoted()` picks the quoting for it.
2358
+ MODEL_ID: quoted(spec2.modelId),
2359
+ WHY_TIGHT: spec2.subAgent ? ": a delegating agent accumulates sub-agent results fast" : ": a long history is re-sent on every call of the turn"
2360
+ }
2361
+ });
2362
+
2363
+ // src/agent/templates/agent/workflow.ts.tpl
2364
+ var workflow_ts_default = 'import type { WorkflowEvent, WorkflowStep } from "cloudflare:workers";\nimport {\n TaskWorkflow,\n type PipelineResult,\n type TaskParams,\n type TaskStep\n} from "@dynamicagents/core/workflow";\nimport { TUNING } from "./tuning";\n\n/**\n * This tenant\'s pipeline: one step, the whole task, on the caller\'s own\n * `$AGENT_CLASS`. A step before it or after it — a triage, a judge, a\n * second opinion — goes here, and each gets its own `step.agent(...)` call.\n *\n * The step agent is named by its **binding**, never imported: a pipeline that\n * imported the class would pull that agent\'s whole module graph — plugins\n * included — into every bundle this pipeline is part of. Typed `: string` so a\n * test can point it at a scripted agent.\n *\n * `run()` is declared here, as every pipeline must declare it: the runtime\n * resolves the entrypoint on this class, not on its base.\n */\nexport class $WORKFLOW_CLASS extends TaskWorkflow<Env> {\n // $block STEP_AGENT\n\n override run(event: WorkflowEvent<TaskParams>, step: WorkflowStep) {\n return super.run(event, step);\n }\n\n protected async pipeline(\n event: WorkflowEvent<TaskParams>,\n step: TaskStep\n ): Promise<PipelineResult> {\n const reply = await step.agent("main", {\n agent: this.$CAMEL,\n input: event.payload.text,\n reconcile: TUNING.reconcile\n });\n return { reply };\n }\n}\n';
2365
+
2366
+ // src/agent/templates/agent/workflow.ts
2367
+ var workflowTs = (n3) => render(workflow_ts_default, {
2368
+ tokens: {
2369
+ WORKFLOW_CLASS: n3.workflowClass,
2370
+ AGENT_CLASS: n3.agentClass,
2371
+ CAMEL: n3.camel,
2372
+ // Breaks after the `=` past the print width, and the field's own name is
2373
+ // derived too, so the whole line is laid out here.
2374
+ STEP_AGENT: assigned(
2375
+ `protected readonly ${n3.camel}: string`,
2376
+ n3.agentClass
2377
+ )
2378
+ }
2379
+ });
2380
+
2381
+ // src/agent/templates/merge-notes.ts
2382
+ var mergeSteps = (dir) => [
2383
+ {
2384
+ path: `${dir}/`,
2385
+ what: "Copy the whole directory across. Nothing in it reaches outside itself except `@/copy` and `@/model`, which the other project already has."
2386
+ },
2387
+ {
2388
+ path: "src/index.ts",
2389
+ what: "Add the `definition` import, the class exports, and the agent to the `agents` array of `createA2AWorker`."
2390
+ },
2391
+ {
2392
+ path: "src/host-manifest.ts",
2393
+ what: "Name the arriving tenant in the description. It is the only place the deployment's card says what is here."
2394
+ },
2395
+ {
2396
+ path: "wrangler.jsonc",
2397
+ what: "Add its two Durable Object bindings and its `workflows` entry, and create its classes in a **new** migration tag — never one already deployed. `Artifacts` is already there: do not create it twice."
2398
+ },
2399
+ {
2400
+ path: "wrangler.jsonc",
2401
+ what: "Then copy every capability binding the arriving config declares — `browser` is the one this creator writes — with its settings as they stand. A plugin declares the bindings it needs and core checks them when the agent starts, so `plugins.ts` without its binding is an agent that throws on its first request."
2402
+ },
2403
+ {
2404
+ path: "package.json",
2405
+ what: "Union the dependencies. Both projects were generated against the same train, so the ranges agree unless one has been bumped."
2406
+ },
2407
+ {
2408
+ path: ".env.example",
2409
+ what: "Union the secrets, and add any the arriving agent's plugins require to `secrets.required` in wrangler.jsonc."
2410
+ },
2411
+ {
2412
+ path: "test/",
2413
+ what: "Rename the arriving specs as they come across. Every generated project calls them `turn.spec.ts`, `edge.spec.ts`, `soul.spec.ts` and so on, so copying them in overwrites the suite that is already here — `turn.<tenant>.spec.ts`, or a directory per tenant, either reads fine."
2414
+ },
2415
+ {
2416
+ path: "test/worker.ts",
2417
+ what: "Merge rather than copy: the suite runs one test Worker. Add the arriving agent's `Test*` classes, its three bindings to `TestEnv`, its `manifest` import under an alias — both projects import that name — and a second `defineAgent({ tenant, manifest, agent })` to the `agents` array. Without that last one its turn specs call a tenant the test Worker does not serve."
2418
+ },
2419
+ {
2420
+ path: "vitest.config.ts",
2421
+ what: "Add the arriving agent's test-only Durable Object and workflow bindings."
2422
+ },
2423
+ {
2424
+ path: "README.md",
2425
+ what: "It was written for one agent: add the arriving tenant to the registration table and to the list of files worth editing, and stop calling the deployment one agent. A reader who believes the old sentence will register one tenant and wonder where the other went."
2426
+ },
2427
+ {
2428
+ path: "AGENTS.md",
2429
+ what: "The same, starting with the heading and the tenant id in its first lines — and keep this recipe in it, because the next merge is read from there."
2430
+ }
2431
+ ];
2432
+ var MERGE_CAVEAT = "A merge does not move state. Every task, conversation and memory the agent had belongs to the Worker it was deployed as; in the merged Worker it starts empty. Finish or drain what is running before you cut over, and keep the old script deployed until you have.";
2433
+
2434
+ // src/agent/templates/project/AGENTS.md.tpl
2435
+ var AGENTS_md_default = "# AGENTS.md — working in `$TENANT`\n\nOne Worker, one agent. `$NAME` is a **tenant** of this deployment,\nreached over A2A at `/a2a` with `params.tenant` set to `$TENANT`.\n\nAlmost nothing here is framework. The turn is [`@cloudflare/think`][think]'s;\nthe A2A task, the workflow that runs its steps, the step job and delegation to\nsub-agents are [`@dynamicagents/core`][core]'s; optional capabilities are\n[`@dynamicagents/plugins`][plugins]. What lives here is what those deliberately\nrefuse to ship — the words, the numbers, the capabilities this agent has, and\nwhich steps its task runs.\n\n[think]: https://www.npmjs.com/package/@cloudflare/think\n[core]: https://github.com/dynamicagents/core\n[plugins]: https://github.com/dynamicagents/plugins\n\n**A paid Cloudflare Workers plan is a requirement**, not a recommendation: the\nmodel this agent runs on is not served on the free tier$BROWSER_TOO. There is\nno free-tier path in this project.\n\n---\n\n## Where a thing goes\n\n$WHERE_TABLE\n\nIf you find yourself writing durable-execution logic here, that is the signal it\nbelongs in core instead.\n\n**The soul is yours.** Core ships no prompt copy at all, deliberately: a run\nmust never execute under an identity nobody chose. `soul.ts` was seeded from one\nline of description — read it, and make it say what this agent actually is.\n\n---\n\n## Working here\n\n```bash\nnpm run keygen # one signing key for this deployment — see .env.example\nnpm run check # wrangler types, prettier, eslint, tsc (src and test)\nnpm test # vitest, inside real workerd\nnpm run dev # local\nnpm run deploy # and register the tenant with your gatekeeper\n```\n\n`npm test` alone will not catch a type error — vitest transpiles specs without\ntypechecking them — so run `check` before you push. `check` starts with\n`wrangler types --check`, which fails on a stale `worker-configuration.d.ts`:\nrun `npm run types` after any change to `wrangler.jsonc`.\n\n### The tests, and what each is for\n\n$TESTS_TABLE\n\nNothing in the suite reaches the network or a real model: `test/worker.ts` is\nthis Worker with the agent's model swapped for a scripted one, and\n`createAgentHarness` from `@dynamicagents/core/testing` drives a turn the way a\ngatekeeper does. A spec that wants a real model needs a recorded cassette —\n`@dynamicagents/core/testing` ships the recorder; it is deliberately not wired\nup here.\n\n---\n\n## Two things that are easy to get wrong\n\n**1. Cancellation is decided by the guarded write, never by a probe.** Core's\ntask ledger flips a task to `canceled` in one guarded write, and every later\nwrite is refused against it and says so. Read those answers. Calling `getTask`\nfirst and acting second reopens a window in which a cancel lands and the\ngatekeeper still gets a `completed` callback.\n\n**2. A migration tag is applied once, ever.** Anything appended to a tag already\ndeployed is never applied, and the failure surfaces at the first request or at\nthe next deploy. Always add a new tag — `wrangler.jsonc` carries the detail,\nincluding what it takes to actually free a deleted class's storage.\n\n---\n\n## Adding a second agent to this Worker\n\nThis project was generated as one agent in its own Worker, which is what makes\nit simple: one bundle, one config, one deployment, and nothing shared with\nanybody else's agent. Nothing stops it holding more, though. A tenant is\nrequired on every request either way, so mounting a second agent is additive\nrather than a redesign.\n\nTwo generated projects merge mechanically because of how they are laid out:\neverything specific to an agent is in its own directory, including its numbers;\noutside that directory the support files — the toolchain config, `src/copy.ts`,\n`src/model.ts` — are identical in every generated project, and what is left is\nthe short list of wiring points below; and every class, binding and workflow\nname derives from the tenant id, so two agents with different tenant ids cannot\ncollide and nothing has to be renamed.\n\nTo bring another generated agent in:\n\n$MERGE_TABLE\n\nThen `npm run types && npm run check && npm test`.\n\n**$MERGE_CAVEAT**\n\nA tenant id is a public identifier: a gatekeeper registers against it and it\nrides in a JWT claim, so renaming one is a re-registration, not a refactor. Pick\nthe directory and the id once.\n";
2436
+
2437
+ // src/agent/templates/project/agents-md.ts
2438
+ function agentsMd(spec2, n3) {
2439
+ const browserToo = spec2.capabilities.includes("browser") ? ", and neither is Browser Rendering" : "";
2440
+ const where = mdTable(
2441
+ ["You are changing…", "It goes in"],
2442
+ [
2443
+ ["what the agent _is_ — its identity, its rules", `\`${n3.dir}/soul.ts\``],
2444
+ ["which capabilities it has", `\`${n3.dir}/plugins.ts\``],
2445
+ [
2446
+ "the model, when the conversation compacts, or how long a step waits",
2447
+ `\`${n3.dir}/tuning.ts\``
2448
+ ],
2449
+ ["what it advertises to a gatekeeper", `\`${n3.dir}/manifest.ts\``],
2450
+ ["the steps its task runs", `\`${n3.dir}/workflow.ts\``],
2451
+ ...spec2.subAgent ? [["its sub-agent — spec, soul, model", `\`${n3.dir}/children.ts\``]] : [],
2452
+ ["what a person reads when a task ends badly", "`src/copy.ts`"],
2453
+ [
2454
+ "what the model is told about a domain",
2455
+ "the plugin that owns that domain"
2456
+ ],
2457
+ [
2458
+ "cancellation, recovery, idempotency, delegation",
2459
+ "**`@dynamicagents/core`** — not here"
2460
+ ],
2461
+ [
2462
+ "the Durable Object a capability runs in",
2463
+ "**`@dynamicagents/plugins`** — not here"
2464
+ ]
2465
+ ]
2466
+ );
2467
+ const tests = mdTable(
2468
+ ["file", "what it pins"],
2469
+ [
2470
+ [
2471
+ "`test/turn.spec.ts`",
2472
+ "The whole A2A lifecycle on a scripted model: a gatekeeper-signed request reaches the host, the pipeline runs the agent, and the push callback says what happened."
2473
+ ],
2474
+ [
2475
+ "`test/edge.spec.ts`",
2476
+ "The zero-trust edge with no model involved: the signed card, the JWKS, and what an unauthenticated or wrongly-scoped call gets."
2477
+ ],
2478
+ [
2479
+ "`test/soul.spec.ts`",
2480
+ "That the soul stays within its rules as it is rewritten."
2481
+ ],
2482
+ [
2483
+ "`test/manifest.spec.ts`",
2484
+ "That the card advertises what the agent actually has."
2485
+ ],
2486
+ [
2487
+ "`test/tuning.spec.ts`",
2488
+ "That the numbers are consistent with each other."
2489
+ ],
2490
+ [
2491
+ "`test/plugins.spec.ts`",
2492
+ "That every installed plugin's bindings exist in `wrangler.jsonc`."
2493
+ ]
2494
+ ]
2495
+ );
2496
+ const merge = mdTable(
2497
+ ["file", "what to do"],
2498
+ mergeSteps(n3.dir).map((step) => [`\`${step.path}\``, step.what])
2499
+ );
2500
+ return render(AGENTS_md_default, {
2501
+ tokens: {
2502
+ TENANT: spec2.tenant,
2503
+ NAME: spec2.name,
2504
+ BROWSER_TOO: browserToo,
2505
+ // Every table keeps its helper: `mdTable` pads each cell to its
2506
+ // column's width, so the layout depends on the tenant id in it — and
2507
+ // `where` and `merge` vary in their *number of rows* besides.
2508
+ WHERE_TABLE: where,
2509
+ TESTS_TABLE: tests,
2510
+ MERGE_TABLE: merge,
2511
+ MERGE_CAVEAT
2512
+ }
2513
+ });
2514
+ }
2515
+
2516
+ // src/agent/templates/project/eslint.config.js.tpl
2517
+ var eslint_config_js_default = 'import tseslint from "typescript-eslint";\nimport da from "@dynamicagents/core/eslint";\n\nconst LINTED_FILES = ["src/**/*.ts", "test/**/*.ts"];\n\nexport default tseslint.config(\n {\n extends: [...tseslint.configs.recommended],\n files: LINTED_FILES,\n rules: {\n "@typescript-eslint/no-explicit-any": "error",\n "no-unused-expressions": "off",\n // The Agents SDK\'s `this.sql`…`` statements are tagged templates run for\n // their side effect; keep the rule for everything else.\n "@typescript-eslint/no-unused-expressions": [\n "error",\n { allowTaggedTemplates: true }\n ],\n "@typescript-eslint/no-unused-vars": [\n "error",\n {\n argsIgnorePattern: "^_",\n varsIgnorePattern: "^_",\n caughtErrorsIgnorePattern: "^_"\n }\n ]\n }\n },\n {\n // Type-aware pass — enables @deprecated detection without switching the\n // whole config to recommendedTypeChecked and its stricter rule set.\n files: LINTED_FILES,\n plugins: { "@typescript-eslint": tseslint.plugin, da },\n languageOptions: {\n parser: tseslint.parser,\n parserOptions: {\n projectService: true,\n tsconfigRootDir: import.meta.dirname\n }\n },\n rules: {\n "@typescript-eslint/no-deprecated": "error",\n // Covers the object-literal keys `no-deprecated` structurally cannot see —\n // every `generateText({ system: … })`-style options bag.\n "da/no-deprecated-object-properties": "error"\n }\n },\n {\n ignores: [\n "worker-configuration.d.ts",\n "node_modules/",\n ".wrangler/",\n "dist/"\n ]\n }\n);\n';
2518
+
2519
+ // src/agent/templates/project/gitignore.tpl
2520
+ var gitignore_default = "node_modules/\ndist/\n.wrangler/\n*.tsbuildinfo\n*.log\n\n# Secrets. `.env.example` is the one file here that is committed.\n.env\n.env.*\n!.env.example\n\n# Written by `npm run types` from wrangler.jsonc.\nworker-configuration.d.ts\n\n.DS_Store\n";
2521
+
2522
+ // src/agent/templates/project/prettierignore.tpl
2523
+ var prettierignore_default = "node_modules/\ndist/\n.wrangler/\n\n# Written by `npm run types`.\nworker-configuration.d.ts\n";
2524
+
2525
+ // src/agent/templates/project/test-tsconfig.json.tpl
2526
+ var test_tsconfig_json_default = '{\n "extends": "../tsconfig.json",\n "compilerOptions": {\n "types": [\n "../worker-configuration.d.ts",\n "node",\n "@cloudflare/vitest-plugin/types"\n ]\n },\n "include": ["./**/*.ts"]\n}\n';
2527
+
2528
+ // src/agent/templates/project/tsconfig.json.tpl
2529
+ var tsconfig_json_default = '{\n "compilerOptions": {\n "target": "ES2022",\n "module": "ESNext",\n "moduleResolution": "Bundler",\n "lib": ["ES2022"],\n "types": ["./worker-configuration.d.ts", "node"],\n "strict": true,\n "noEmit": true,\n "skipLibCheck": true,\n "esModuleInterop": true,\n "verbatimModuleSyntax": true,\n "isolatedModules": true,\n "paths": {\n "@/*": ["./src/*"]\n }\n },\n "include": ["src/**/*.ts"]\n}\n';
2530
+
2531
+ // src/agent/templates/project/dotfiles.ts
2532
+ var tsconfigJson = tsconfig_json_default;
2533
+ var testTsconfigJson = test_tsconfig_json_default;
2534
+ var prettierrc = jsonFile({ trailingComma: "none" });
2535
+ var nvmrc = `${NODE_VERSION}
2536
+ `;
2537
+ var prettierignore = prettierignore_default;
2538
+ var gitignore = gitignore_default;
2539
+ var eslintConfigJs = eslint_config_js_default;
2540
+
2541
+ // src/agent/templates/project/env.example.tpl
2542
+ var env_example_default = '# Copy to `.env` for local `wrangler dev`. In production set each as a secret:\n# `wrangler secret put <NAME>`, or `wrangler deploy --secrets-file .env`.\n#\n# Wrangler loads `.env`, then `.env.local`, then — when you pass `--env <name>` —\n# `.env.<name>` and `.env.<name>.local`, each overriding the last. So a staging\n# deployment is `.env.staging`, not an edit to wrangler.jsonc. Everything but\n# this example file is gitignored.\n#\n# One caveat: if a `.dev.vars` file exists it wins outright and none of the\n# above is read. This project uses `.env`; keep a single file so there is never\n# a question which one is live.\n\n# One Ed25519 private JWK, on a single line, signing the card this Worker serves\n# and every push-notification callback JWT. It MUST include a `kid`. Generate\n# one with `npm run keygen`.\n#\n# Only the matching PUBLIC key is ever exposed, at /.well-known/jwks.json — the\n# private half never leaves the Worker, and is never configured anywhere else:\n# the Worker derives the public half from it.\nA2A_SIGNING_KEY=\n\n# JSON array of the gatekeeper origins this deployment accepts calls from, e.g.\n# ["https://gatekeeper.example.com"]. A property of this deployment, like the\n# key. Not a traditional secret, but kept out of wrangler.jsonc so it can differ\n# per environment with no code change.\nGATEKEEPER_ORIGINS=\n\n# There is no credential here for the agent\'s own model, deliberately.\n#\n# `$TENANT` runs its model on Workers AI through the `AI` binding, which\n# Cloudflare authenticates for the Worker. There is no key to store and none to\n# rotate, and no AI Gateway token either: the binding does not send one. A\n# gateway 401 means Authenticated Gateway is switched on for the `default` AI\n# Gateway every call goes through — switch it off.\n';
2543
+
2544
+ // src/agent/templates/project/env-example.ts
2545
+ var envExample = (spec2) => render(env_example_default, { tokens: { TENANT: spec2.tenant } });
2546
+
2547
+ // src/agent/templates/project/host-manifest.ts.tpl
2548
+ var host_manifest_ts_default = 'import type { AgentManifest } from "@dynamicagents/core/a2a";\n\n/**\n * The **stub** card served at `/.well-known/agent-card.json`.\n *\n * It describes the deployment, not the agent. The agent is a tenant of this\n * endpoint, so this card exists to be the single conformant, signed AgentCard at\n * the URI RFC 8615 and A2A\'s IANA registration reserve — advertising where to\n * call, which protocol, and that real cards are reachable through\n * `GetExtendedAgentCard`.\n *\n * It cannot list tenants as interfaces: a card carries one interface entry and\n * spec §8.3.2 has clients take the first, so one entry per tenant would just\n * make every client address whichever came first. They go in `description` for a\n * human reading the deploy in a browser, and are registered out of band.\n *\n * **The description must name every mounted tenant.** It is the only place this\n * card says what is here, so a tenant missing from it is a tenant an operator\n * reading the deploy has no way to discover. Mounting a second agent in\n * `src/index.ts` means naming it here too.\n *\n * `skills` is empty for the same reason: the skills belong to the tenants, and a\n * client that picked one from here would have no way to act on it.\n */\nexport const hostManifest: AgentManifest = {\n // $block CARD_IDENTITY\n version: "0.1.0",\n // `extensions` is a required (repeated) protobuf field in v1.0, and this\n // deployment declares no protocol extensions, so it stays empty.\n // `extendedAgentCard` is set by core, which owns that contract.\n capabilities: { streaming: false, pushNotifications: true, extensions: [] },\n defaultInputModes: ["text/plain"],\n defaultOutputModes: ["text/plain"],\n skills: []\n};\n';
2549
+
2550
+ // src/agent/templates/project/host-manifest.ts
2551
+ function hostManifestTs(spec2) {
2552
+ const description2 = `Hosts a Dynamic Agent behind one A2A endpoint. This card describes the deployment rather than the agent — call GetExtendedAgentCard with a tenant id to fetch an agent's own card. Tenants: \`${spec2.tenant}\` (${spec2.description.replace(/\.$/, "")}).`;
2553
+ return render(host_manifest_ts_default, {
2554
+ tokens: {
2555
+ // A block, and with its trailing comma: this description is long enough
2556
+ // to break after the colon in every project, and `stringProp` is what
2557
+ // knows where. See `../agent/manifest.ts` on the comma.
2558
+ CARD_IDENTITY: `${[
2559
+ stringProp("name", spec2.tenant),
2560
+ stringProp("description", description2)
2561
+ ].join(",\n")},`
2562
+ }
2563
+ });
2564
+ }
2565
+
2566
+ // src/agent/templates/dependencies.ts
2567
+ var sorted = (map) => Object.fromEntries(
2568
+ Object.entries(map).sort(([a2], [b]) => a2.localeCompare(b))
2569
+ );
2570
+ function dependenciesFor(spec2) {
2571
+ const deps = {
2572
+ "@dynamicagents/core": TRAIN.core,
2573
+ "@cloudflare/computer": RUNTIME["@cloudflare/computer"],
2574
+ "@cloudflare/think": RUNTIME["@cloudflare/think"],
2575
+ agents: RUNTIME.agents,
2576
+ ai: RUNTIME.ai,
2577
+ "workers-ai-provider": RUNTIME["workers-ai-provider"],
2578
+ "@a2a-js/sdk": RUNTIME["@a2a-js/sdk"]
2579
+ };
2580
+ if (spec2.subAgent) deps.zod = RUNTIME.zod;
2581
+ if (spec2.capabilities.length > 0) {
2582
+ deps["@dynamicagents/plugins"] = TRAIN.plugins;
2583
+ }
2584
+ return sorted(deps);
2585
+ }
2586
+ var devDependenciesFor = () => sorted({ ...TOOLCHAIN });
2587
+
2588
+ // src/agent/templates/project/package-json.ts
2589
+ var packageJson = (spec2) => jsonFile({
2590
+ name: spec2.tenant,
2591
+ version: "0.1.0",
2592
+ private: true,
2593
+ description: spec2.description,
2594
+ type: "module",
2595
+ scripts: {
2596
+ dev: "wrangler dev",
2597
+ deploy: "wrangler deploy",
2598
+ types: "wrangler types",
2599
+ keygen: "da-keys",
2600
+ format: "prettier --write .",
2601
+ lint: "eslint .",
2602
+ check: "wrangler types --check && prettier --check . && eslint . && tsc && tsc -p test/tsconfig.json",
2603
+ test: "vitest run",
2604
+ "test:watch": "vitest"
2605
+ },
2606
+ dependencies: dependenciesFor(spec2),
2607
+ devDependencies: devDependenciesFor(),
2608
+ engines: { node: NODE_ENGINE }
2609
+ });
2610
+
2611
+ // src/agent/templates/project/README.md.tpl
2612
+ var README_md_default = "# $NAME\n\n$DESCRIPTION\n\nA Dynamic Agent on Cloudflare Workers: zero-trust A2A, a durable task\nlifecycle, and one continuous, self-compacting conversation per caller. Built on\n[`@dynamicagents/core`](https://github.com/dynamicagents/core), scaffolded with\n`npm create dynamicagents`.\n\n- **One Worker, one agent.** This deployment serves exactly this agent, as the\n A2A tenant `$TENANT`.$DELEGATION$CAPABILITIES- **Its own everything.** Its own wrangler config, its own bindings, its own\n signing key. Nothing it does can affect another agent.\n\n> **A paid Cloudflare Workers plan is required.** The model this agent runs on is\n> not served on the free tier$BROWSER_NOTE. There is no free-tier\n> configuration of this project.\n\n---\n\n## Quick start\n\n```bash\nnpm run keygen # one Ed25519 key for this deployment\n```\n\nPut the private JWK in `.env` as `A2A_SIGNING_KEY`, and the gatekeeper origins\nyou accept calls from in `GATEKEEPER_ORIGINS`. [`.env.example`](.env.example)\nsays what each one is.\n\n```bash\nnpm run check # types, format, lint, typecheck\nnpm test # the suite, in real workerd\nnpm run dev # local\n```\n\nTo ship, set the same secrets with `wrangler secret put` (or push the file with\n`npx wrangler deploy --secrets-file .env`) and:\n\n```bash\nnpm run deploy\n```\n\nThen register the agent with your gatekeeper:\n\n$REGISTRATION\n\nA tenant is required on every request — there is no default agent and no\nimplicit routing. The card at `/.well-known/agent-card.json` describes the\ndeployment; the agent's own card comes from `GetExtendedAgentCard` with that\ntenant id.\n\n**Keep one origin.** Core derives the card's URL, its `jku` and the token\naudience from the origin a request arrives on, so a second origin advertises a\nsecond audience and a token minted for one will not verify against the other.\n`wrangler.jsonc` says what to change when you move to a domain of your own.\n\n---\n\n## The files you will actually edit\n\n$FILES_TABLE\n\n[`AGENTS.md`](AGENTS.md) is the rest: where everything goes, what the tests\npin, the two invariants worth knowing, and how to bring a second agent into this\nWorker later.\n\n## License\n\nYours.\n";
2613
+
2614
+ // src/agent/templates/project/readme.ts
2615
+ function readmeMd(spec2, n3) {
2616
+ const browser = spec2.capabilities.includes("browser");
2617
+ const delegation = spec2.subAgent ? "\n- **Delegates.** Self-contained pieces of a request go to a sub-agent and come back composed into one answer.\n" : "";
2618
+ const capabilities2 = browser ? "\n- **Reads web pages**, through Browser Rendering.\n" : "";
2619
+ const registration = mdTable(
2620
+ ["endpoint", "tenant id"],
2621
+ [["`https://<your-worker>/a2a`", `\`${spec2.tenant}\``]]
2622
+ );
2623
+ const files = mdTable(
2624
+ ["file", "what it decides"],
2625
+ [
2626
+ [
2627
+ `[\`${n3.dir}/soul.ts\`](${n3.dir}/soul.ts)`,
2628
+ "Who the agent is. **Start here** — it was seeded from one line."
2629
+ ],
2630
+ [
2631
+ `[\`${n3.dir}/plugins.ts\`](${n3.dir}/plugins.ts)`,
2632
+ "What it can do. One line per capability."
2633
+ ],
2634
+ [
2635
+ `[\`${n3.dir}/tuning.ts\`](${n3.dir}/tuning.ts)`,
2636
+ `Its model, when the conversation compacts, and how long a step waits for an event that never arrived. Every model id is at ${MODELS_URL}`
2637
+ ],
2638
+ [
2639
+ `[\`${n3.dir}/manifest.ts\`](${n3.dir}/manifest.ts)`,
2640
+ "What it advertises to a gatekeeper."
2641
+ ],
2642
+ [
2643
+ `[\`${n3.dir}/workflow.ts\`](${n3.dir}/workflow.ts)`,
2644
+ "The steps a task runs. One today."
2645
+ ],
2646
+ [
2647
+ "[`src/copy.ts`](src/copy.ts)",
2648
+ "What a person reads when a task ends badly."
2649
+ ]
2650
+ ]
2651
+ );
2652
+ return render(README_md_default, {
2653
+ tokens: {
2654
+ NAME: spec2.name,
2655
+ DESCRIPTION: spec2.description,
2656
+ TENANT: spec2.tenant,
2657
+ DELEGATION: delegation,
2658
+ CAPABILITIES: capabilities2,
2659
+ BROWSER_NOTE: browser ? ", and neither is Browser Rendering" : "",
2660
+ // Both tables keep their helper: `mdTable` pads every cell to its
2661
+ // column's width, so the layout depends on the tenant id in it.
2662
+ REGISTRATION: registration,
2663
+ FILES_TABLE: files
2664
+ }
2665
+ });
2666
+ }
2667
+
2668
+ // src/agent/templates/project/copy.ts.tpl
2669
+ var copy_ts_default = 'import {\n ASK_USER_TOOL_NAME,\n CHECK_BACK_TOOL_NAME\n} from "@dynamicagents/core/agent";\nimport type { A2ACopy } from "@dynamicagents/core/task";\n\n/**\n * The words this Worker\'s agents say that core refuses to write: what a person\n * reads when a task ends without an answer, and the parts of a soul or a job\'s\n * first message that are not about one agent\'s domain.\n *\n * At the top level rather than inside the agent\'s directory because nothing\n * here names an agent — which is also what lets a second agent share it\n * unchanged.\n */\n\n/** What a person reads when a task ends with no answer to give them. */\nexport const copy: A2ACopy = {\n /** A task whose steps failed. The diagnostic is logged, not shown. */\n failed: "Sorry — something went wrong handling that request.",\n /** A task that finished with nothing to say. */\n emptyReply:\n "I finished, but had nothing to report. Ask again if you expected an answer."\n};\n\n/**\n * When to ask the person, for every soul. `ask_user`\'s own description says\n * what the call does; this says when it is worth a person\'s attention.\n */\nexport const ASK_GUIDANCE = `## When only the person can tell you\n\n\\`${ASK_USER_TOOL_NAME}\\` puts your questions to the person who made this request and stops. Ask when you cannot go on well without something only they can give you: a choice between options that would each change what you do, a fact that is nowhere you can look, or a go-ahead for something they may not want. Do not ask what you can look up, work out, or reasonably assume — say what you assumed instead.`;\n\n/**\n * When to wait, for an agent that has `check_back`. Not in this agent\'s soul\n * yet: add it to `SOUL` when there is something it has to wait on. The two\n * failures to write against are waiting *instead of working*, where each pause\n * reads as progress, and answering *instead of waiting*, where the reply calls\n * the work done pending a review nobody has read.\n */\nexport const WAIT_GUIDANCE = `## When you are waiting on something\n\n\\`${CHECK_BACK_TOOL_NAME}\\` ends this turn and wakes you on the same request later, with the reason you gave. Use it for something you cannot hurry and can look at again — a review being written, a build, a deploy. **When you wake, check the thing you named before deciding anything else.** Never use it to pause between steps you could take now; if you are waiting on a person rather than an event, that is \\`${ASK_USER_TOOL_NAME}\\`.`;\n\n/**\n * Ahead of a job\'s second attempt. A pipeline runs a failed step once more, in\n * the same conversation, so without this the model meets its request twice.\n */\nexport const RETRY_BRIEF =\n "Your previous attempt at this stopped before it finished. Its work is kept: what it said and did is above. Look at what it left first, and carry on from there rather than starting again.";\n';
2670
+
2671
+ // src/agent/templates/project/model.ts.tpl
2672
+ var model_ts_default = 'import type { LanguageModel } from "ai";\nimport {\n gatewayLogFields,\n workersAIModel,\n type GatewayCorrelation\n} from "@dynamicagents/core/model";\n\n/**\n * The one model an agent or a sub-agent runs, as its `getModel()` returns it.\n *\n * One function for every class in this project, because what each call tells AI\n * Gateway about itself has to be spelled the same way everywhere or a log filter\n * on it silently misses the classes that spelled it differently.\n *\n * `sessionAffinity` is the object\'s name: every call an object makes re-sends\n * one history, so anything finer routes a call away from the prefix it is about\n * to re-send.\n *\n * There is no model credential anywhere in this project. Workers AI is reached\n * through the `AI` binding, which Cloudflare authenticates for the Worker.\n */\nexport function agentModel(\n env: Env,\n model: { modelId: string; name: string },\n correlation: GatewayCorrelation\n): LanguageModel {\n return workersAIModel(env, {\n modelId: model.modelId,\n sessionAffinity: model.name,\n ...gatewayLogFields(correlation)\n });\n}\n\n/**\n * The task a sub-agent\'s turn is for. Core stamps it on the dispatch\'s\n * `turnMetadata`, where Think keeps it for a recovered turn too.\n */\nexport function turnTask(metadata: unknown): string | undefined {\n const taskId = (metadata as { taskId?: unknown } | undefined)?.taskId;\n return typeof taskId === "string" ? taskId : undefined;\n}\n';
2673
+
2674
+ // src/agent/templates/project/shared.ts
2675
+ var copyTs = copy_ts_default;
2676
+ var modelTs = model_ts_default;
2677
+
2678
+ // src/agent/templates/project/vitest.config.ts.tpl
2679
+ var vitest_config_ts_default = 'import { defineConfig } from "vitest/config";\nimport { cloudflareTest } from "@cloudflare/vitest-plugin";\nimport path from "node:path";\n// The realm-neutral slice, deliberately. This file runs in **Node**, and the\n// `/testing` barrel pulls in `cloudflare:test`, which fails at load before a\n// single test runs.\nimport {\n GATEKEEPER_ORIGIN,\n TEST_AGENT_PRIVATE_JWK\n} from "@dynamicagents/core/testing/fixtures";\n\n/**\n * The whole suite runs in the Workers runtime (workerd via miniflare) through\n * one `cloudflareTest()` pool.\n *\n * The pool reads `wrangler.jsonc` directly — the compatibility settings, the AI\n * binding, the Durable Objects and their SQLite migration — so this config\n * cannot drift from it. Its `main` is `test/worker.ts`, which is this Worker\n * plus the agent on a scripted model: Workers AI has no local execution mode,\n * so a real model cannot finish a turn here.\n */\n\n// Test defaults for the secrets `wrangler.jsonc` requires. Real env vars — from\n// CI or the shell — take precedence through `??=`. The pool sources\n// `secrets.required` from `process.env` into the worker `env`.\nprocess.env.A2A_SIGNING_KEY ??= JSON.stringify(TEST_AGENT_PRIVATE_JWK);\nprocess.env.GATEKEEPER_ORIGINS ??= JSON.stringify([GATEKEEPER_ORIGIN]);\n\nexport default defineConfig({\n resolve: {\n alias: { "@": path.resolve(import.meta.dirname, "./src") }\n },\n plugins: [\n cloudflareTest({\n wrangler: { configPath: "./wrangler.jsonc" },\n main: "./test/worker.ts",\n // Required, not just the default. Workers AI has no local execution mode\n // — miniflare always proxies `AI` through a remote-connection worker —\n // and leaving this unset makes the pool open that connection per test\n // file, for a binding no spec here calls. `false` avoids it entirely.\n remoteBindings: false,\n miniflare: {\n // Test-only Durable Object bindings: the scripted classes in\n // `test/worker.ts`, which `wrangler.jsonc` knows nothing about.\n // $when subAgent\n //\n // In production a sub-agent needs **no** binding and no\n // `new_sqlite_classes` entry — its storage is a facet created beneath\n // the bound parent agent — but the pool only treats *bound* classes as\n // Durable Object classes, so without one here the parent cannot create\n // it.\n // $end\n durableObjects: {\n // $block DURABLE_OBJECTS\n },\n // The scripted pipeline, beside the real one `wrangler.jsonc` binds.\n workflows: {\n TEST_$WORKFLOW_BINDING: {\n name: "test-$WORKFLOW_NAME",\n className: "$TEST_WORKFLOW_CLASS"\n }\n }\n }\n })\n ],\n test: {\n include: ["test/**/*.spec.ts"],\n // A task runs in a Workflow and on its agent\'s alarms, so a lifecycle spec\n // waits on real scheduling rather than on a promise.\n testTimeout: 60_000,\n hookTimeout: 60_000\n }\n});\n';
2680
+
2681
+ // src/agent/templates/project/vitest-config.ts
2682
+ function vitestConfigTs(spec2, n3) {
2683
+ const T = `Test${n3.pascal}`;
2684
+ const durableObject = (binding, className) => ` ${binding}: {
2685
+ className: "${className}",
2686
+ useSQLite: true
2687
+ }`;
2688
+ return render(vitest_config_ts_default, {
2689
+ when: { subAgent: spec2.subAgent },
2690
+ tokens: {
2691
+ WORKFLOW_BINDING: n3.workflowBinding,
2692
+ WORKFLOW_NAME: n3.workflowName,
2693
+ TEST_WORKFLOW_CLASS: `${T}Workflow`,
2694
+ // Two bindings or three: the count is what the sub-agent changes, and a
2695
+ // list whose length is computed is a block rather than a region, because
2696
+ // which element is last decides where the commas go.
2697
+ DURABLE_OBJECTS: [
2698
+ durableObject(`TEST_${n3.screaming}_HOST`, `${T}Host`),
2699
+ durableObject(`TEST_${n3.screaming}_AGENT`, `${T}Agent`),
2700
+ ...spec2.subAgent ? [durableObject(`TEST_${n3.screaming}_CHILD`, `${T}Child`)] : []
2701
+ ].join(",\n")
2702
+ }
2703
+ });
2704
+ }
2705
+
2706
+ // src/agent/templates/project/index.ts.tpl
2707
+ var index_ts_default = 'import { createA2AWorker } from "@dynamicagents/core/worker";\nimport { Artifacts, handleArtifactRoute } from "@dynamicagents/core/artifacts";\n\nimport { hostManifest } from "./host-manifest";\nimport { $CAMEL } from "./agents/$TENANT/definition";\n\n// Durable Objects and Workflows must be exported from the Worker entry so the\n// runtime can resolve them by class name: the task host, the pipeline it runs\n// each task as, and the step agent the pipeline\'s steps run on.\n// $when subAgent\n//\n// The sub-agent class is a **facet**: it is created beneath its agent, so it\n// needs no wrangler binding and no `new_sqlite_classes` entry — only this\n// export, so `ctx.exports` can resolve it by class name.\n// $end\nexport { $HOST_CLASS } from "./agents/$TENANT/host";\nexport { $WORKFLOW_CLASS } from "./agents/$TENANT/workflow";\nexport { $AGENT_CLASS } from "./agents/$TENANT/agent";\n// $when subAgent\nexport { $CHILD_CLASS } from "./agents/$TENANT/children";\n// $end\n\n// Core\'s own class, re-exported unmodified — there is nothing here to subclass,\n// and a Durable Object namespace is keyed by class name, so this export is what\n// the `ARTIFACTS` binding resolves to. Why it is required rather than optional\n// sits beside that binding in wrangler.jsonc.\nexport { Artifacts };\n\n/**\n * One Worker, one agent, addressed by A2A `tenant`.\n *\n * ```\n * /.well-known/agent-card.json the stub card for this deployment\n * /.well-known/jwks.json the public key, verifying every card it signs\n * /a2a the agent, picked by params.tenant\n * ```\n *\n * A tenant is required on every request: there is no default agent and no\n * implicit routing, and that holds with one agent exactly as it would with\n * twenty. `AgentInterface.tenant` is the A2A mechanism for it, and §8.3.2\n * requires a client to send the value the interface it selected declared.\n *\n * The card is why it is a tenant rather than a path prefix: its location is a\n * **well-known URI**, which RFC 8615 defines per-authority, so this origin\n * serves exactly one card and a gatekeeper pins one key for whatever is behind\n * it. That card is a stub (`./host-manifest.ts`); the agent\'s own comes from\n * `GetExtendedAgentCard`.\n *\n * **A second agent in this Worker** is another directory under `./agents/`,\n * another `defineAgent` imported above, another name in `agents` below, and its\n * own bindings and migration tag — AGENTS.md carries the whole recipe.\n */\nconst a2a = createA2AWorker<Env>({\n manifest: hostManifest,\n agents: [$CAMEL]\n});\n\nexport default {\n /**\n * The artifact links first, everything else after — and the order is the\n * requirement, not a preference.\n *\n * `handleArtifactRoute` answers `null` for every path it does not claim, so\n * in front it costs the A2A router nothing and takes nothing from it. Behind\n * it, `/a/<token>` reaches a router that knows nothing about the prefix, and\n * what that costs is a link that opens onto the wrong answer rather than a\n * failure anyone notices. The artifact routes are not A2A and deliberately\n * sit outside it: no gatekeeper token, no tenant, and the token in the path is\n * the whole credential.\n */\n async fetch(request: Request, env: Env): Promise<Response> {\n return (await handleArtifactRoute(request, env)) ?? a2a(request, env);\n }\n} satisfies ExportedHandler<Env>;\n';
2708
+
2709
+ // src/agent/templates/project/worker-index.ts
2710
+ var indexTs = (spec2, n3) => render(index_ts_default, {
2711
+ when: { subAgent: spec2.subAgent },
2712
+ tokens: {
2713
+ TENANT: spec2.tenant,
2714
+ CAMEL: n3.camel,
2715
+ HOST_CLASS: n3.hostClass,
2716
+ WORKFLOW_CLASS: n3.workflowClass,
2717
+ AGENT_CLASS: n3.agentClass,
2718
+ CHILD_CLASS: n3.childClass
2719
+ }
2720
+ });
2721
+
2722
+ // src/agent/templates/project/wrangler.jsonc.tpl
2723
+ var wrangler_jsonc_default = '/**\n * One Worker, one agent.\n *\n * The agent is a **tenant** of this deployment, routed by `src/index.ts` on the\n * A2A `params.tenant`. That holds with one agent exactly as it would with\n * several, which is what makes adding a second one additive: another directory\n * under `src/agents/`, another block in each list below, and a new migration\n * tag. AGENTS.md carries the recipe.\n *\n * https://developers.cloudflare.com/workers/wrangler/configuration/\n */\n{\n "$schema": "node_modules/wrangler/config-schema.json",\n "name": "$TENANT",\n "main": "src/index.ts",\n // The date is the runtime: a workerd version *is* a release date, and this is\n // the one the pinned wrangler version installs. No `compatibility_flags`\n // beside it, and that is the date\'s doing — `nodejs_compat` is on by default\n // from 2026-08-04, so declaring it here would say nothing this date does not\n // already say.\n "compatibility_date": "$COMPATIBILITY_DATE",\n\n // **One origin, and keep it.**\n //\n // Core derives the card\'s interface URL, its `jku` and the token audience it\n // verifies from `new URL(request.url).origin`. A second origin therefore\n // advertises a second audience, and a gatekeeper token minted for one does\n // not verify against the other — it could only ever serve a card nobody can\n // call.\n //\n // `workers_dev` is on so the first deploy is reachable at a URL you already\n // have. Moving to a domain of your own is one change: turn it off, declare\n // the route, deploy, and re-register the tenant with your gatekeeper against\n // the new origin.\n //\n // "workers_dev": false,\n // "routes": [{ "pattern": "agents.example.com", "custom_domain": true }]\n "workers_dev": true,\n\n "observability": {\n "enabled": true\n },\n\n // --- required by core -----------------------------------------------------\n\n // Workers AI backs the agent\'s model, through AI Gateway. There is no model\n // credential in this project: Cloudflare authenticates this binding for the\n // Worker. `remote: true` reflects reality — Workers AI has no local execution\n // mode and always hits remote resources — and suppresses wrangler\'s per-run\n // warning; the test pool turns it off (vitest.config.ts) so no connection is\n // opened per test file.\n "ai": {\n "binding": "AI",\n "remote": true\n },\n // $when browser\n\n // `@dynamicagents/plugins/browser`, installed in\n // $DIR/plugins.ts. Browser Rendering is a paid-plan\n // binding, and `remote: true` is required for it under `wrangler dev`.\n "browser": {\n "binding": "BROWSER",\n "remote": true\n },\n // $end\n\n // The agent\'s task host, which holds a caller\'s A2A tasks, and the step agent\n // its pipeline runs on, which holds the SQLite-backed Session — one\n // continuous history plus writable memory. Both are keyed by the verified\n // caller, which is what makes a task unreachable from any other caller by\n // construction.\n //\n // A host\'s binding is named as its class: `hostBinding` in\n // $DIR/host.ts names it, and the pipeline reaches the\n // host through it.\n //\n // $when subAgent\n // The sub-agent class (`$CHILD_CLASS`) is deliberately absent. It is a\n // facet created beneath its agent, so it needs no binding and no\n // `new_sqlite_classes` entry — only its export from src/index.ts. It does\n // need a test-only binding; see the comment in vitest.config.ts.\n //\n // $end\n // `ARTIFACTS` is **not optional**. Core files every sub-agent note on the\n // task\'s transcript and posts a link instead of the note, so an agent Durable\n // Object that starts without this binding throws `ArtifactsNotBoundError`\n // naming every part of the wiring — the route delegation at the top of\n // `fetch` in src/index.ts included, since without that one an artifact URL\n // falls through to routes that know nothing about it. The class is core\'s\n // own, re-exported unchanged from src/index.ts, and one object serves the\n // whole deployment: a reader arrives holding a token and nothing else, so the\n // object it reaches cannot be keyed by task.\n "durable_objects": {\n "bindings": [\n // $block DO_BINDINGS\n ]\n },\n\n // **A tag is applied once, ever.** Anything appended to a tag already\n // deployed is simply never applied: the class is never created, and the\n // failure surfaces far from this file — at the first request to the agent, or\n // at deploy with "New version of script does not export class \'X\' which is\n // depended on by existing Durable Objects". Always add a new tag.\n //\n // Removing a class from the code reclaims nothing on its own either: every\n // object it created keeps its storage, unreachable and still billed.\n // `deleted_classes` in a new tag is the line that frees them, and it is\n // irreversible.\n "migrations": [\n {\n // $block MIGRATION_V1\n }\n ],\n\n // The agent\'s pipeline: every task is an instance, its id the task\'s. The\n // name is derived from the tenant id rather than from this Worker, so moving\n // the agent into another Worker never renames it — a rename would abandon\n // every instance still running under the old name.\n "workflows": [\n {\n "name": "$WORKFLOW_NAME",\n "binding": "$WORKFLOW_BINDING",\n "class_name": "$WORKFLOW_CLASS"\n }\n ],\n\n // What an operator fills in; `.env.example` says what each one is. Declared\n // here because `secrets.required` is what drives type generation and\n // `wrangler dev`\'s missing-secret warnings — so a name left here and unset is\n // typed as a definite string that is undefined at runtime.\n "secrets": {\n "required": ["A2A_SIGNING_KEY", "GATEKEEPER_ORIGINS"]\n }\n}\n';
2724
+
2725
+ // src/agent/templates/project/wrangler.ts
2726
+ function wranglerJsonc(spec2, n3) {
2727
+ const bindings = [
2728
+ [n3.hostClass, n3.hostClass],
2729
+ [n3.agentClass, n3.agentClass],
2730
+ ["Artifacts", "ARTIFACTS"]
2731
+ ].map(
2732
+ ([className, name]) => jsonObject(
2733
+ [
2734
+ ["class_name", className],
2735
+ ["name", name]
2736
+ ],
2737
+ 6
2738
+ )
2739
+ ).join(",\n");
2740
+ return render(wrangler_jsonc_default, {
2741
+ when: {
2742
+ browser: spec2.capabilities.includes("browser"),
2743
+ subAgent: spec2.subAgent
2744
+ },
2745
+ tokens: {
2746
+ TENANT: spec2.tenant,
2747
+ COMPATIBILITY_DATE,
2748
+ DIR: n3.dir,
2749
+ CHILD_CLASS: n3.childClass,
2750
+ WORKFLOW_NAME: n3.workflowName,
2751
+ WORKFLOW_BINDING: n3.workflowBinding,
2752
+ WORKFLOW_CLASS: n3.workflowClass,
2753
+ // The two lists that keep their helper, because a long tenant id is what
2754
+ // decides their layout: `jsonObject` goes one property per line and
2755
+ // `jsonArrayProp` one element per line once the line passes the print
2756
+ // width, and `../../formatting.spec.ts` sweeps tenant ids across it.
2757
+ DO_BINDINGS: bindings,
2758
+ /**
2759
+ * The tag is static, and is in here anyway: a `$block` cannot stand
2760
+ * where the property before it would need a trailing comma, because
2761
+ * `trailingComma: "none"` has prettier strip a comma before what it
2762
+ * reads as the last property — and a comment is not one. So the block is
2763
+ * the whole migration rather than its second line.
2764
+ */
2765
+ MIGRATION_V1: [
2766
+ ' "tag": "v1"',
2767
+ jsonArrayProp(
2768
+ "new_sqlite_classes",
2769
+ [n3.hostClass, n3.agentClass, "Artifacts"],
2770
+ 6
2771
+ )
2772
+ ].join(",\n")
2773
+ }
2774
+ });
2775
+ }
2776
+
2777
+ // src/agent/templates/test/edge.spec.ts.tpl
2778
+ var edge_spec_ts_default = 'import { describe, expect, it } from "vitest";\nimport { env } from "cloudflare:workers";\nimport { AGENT_CARD_PATH } from "@a2a-js/sdk";\nimport {\n AGENT_ORIGIN,\n createAgentHarness,\n TEST_AGENT_PRIVATE_JWK\n} from "@dynamicagents/core/testing";\nimport worker from "@/index";\n\n/**\n * What the deployment serves before anybody is authenticated, and what it\n * refuses.\n *\n * Every assertion here is about core\'s edge as **this project** configures it:\n * the card it serves is this project\'s `host-manifest.ts`, the key is the one in\n * `.env`, and the tenant is the one `src/index.ts` mounts. No model runs, so\n * this is the spec that still passes when a turn is broken.\n */\n\n/** The one tenant this Worker mounts, and the name on its card. */\nconst TENANT = "$TENANT";\nconst NAME = $NAME_LITERAL;\n\nconst harness = createAgentHarness({ worker, env, tenant: TENANT });\n\nconst get = (path: string) =>\n worker.fetch(new Request(`${AGENT_ORIGIN}${path}`), env);\n\nconst sendMessage = (tenant: string) => ({\n jsonrpc: "2.0",\n id: 1,\n method: "SendMessage",\n params: { tenant }\n});\n\ndescribe("discovery", () => {\n it("serves one signed stub card at the well-known path", async () => {\n // One card per origin, because a well-known URI is per-authority (RFC 8615)\n // and A2A registered this path with IANA. The agent\'s own card comes from\n // `GetExtendedAgentCard` below.\n const res = await get(`/${AGENT_CARD_PATH}`);\n expect(res.status).toBe(200);\n\n const card = await res.json<{\n name: string;\n capabilities: { extendedAgentCard: boolean };\n supportedInterfaces: { url: string; tenant: string }[];\n signatures: { protected: string }[];\n }>();\n\n // It describes the deployment, and names no tenant.\n expect(card.supportedInterfaces[0]!.tenant ?? "").toBe("");\n expect(card.supportedInterfaces[0]!.url).toBe(`${AGENT_ORIGIN}/a2a`);\n expect(card.capabilities.extendedAgentCard).toBe(true);\n\n // Signed by this deployment\'s key, and pointing a verifier at where the\n // public half is served.\n const header = JSON.parse(\n atob(card.signatures[0]!.protected.replace(/-/g, "+").replace(/_/g, "/"))\n ) as { jku: string; alg: string };\n expect(header.jku).toBe(`${AGENT_ORIGIN}/.well-known/jwks.json`);\n expect(header.alg).toBe("EdDSA");\n });\n\n it("serves the public half of the signing key, and only that", async () => {\n const res = await get("/.well-known/jwks.json");\n expect(res.status).toBe(200);\n\n const body = await res.json<{ keys: Record<string, unknown>[] }>();\n expect(body.keys[0]!.kid).toBe(TEST_AGENT_PRIVATE_JWK.kid);\n // The private half must never be served.\n expect(body.keys[0]!).not.toHaveProperty("d");\n });\n\n it("returns the agent\'s own card for its tenant", async () => {\n using _ = harness.interceptGatekeeper();\n\n const res = await harness.rpc({\n jsonrpc: "2.0",\n id: 1,\n method: "GetExtendedAgentCard",\n params: { tenant: TENANT }\n });\n const body = await res.json<{\n result: { name: string; supportedInterfaces: { tenant: string }[] };\n }>();\n\n expect(body.result.name).toBe(NAME);\n expect(body.result.supportedInterfaces[0]!.tenant).toBe(TENANT);\n });\n});\n\ndescribe("what it refuses", () => {\n it("refuses an unauthenticated call", async () => {\n const res = await worker.fetch(\n new Request(`${AGENT_ORIGIN}/a2a`, {\n method: "POST",\n headers: { "content-type": "application/json" },\n body: JSON.stringify(sendMessage(TENANT))\n }),\n env\n );\n expect(res.status).toBe(401);\n });\n\n it("refuses a token minted for another tenant", async () => {\n // Every agent behind one gatekeeper shares an audience, so the tenant claim\n // is what separates them — and this is the assertion that says so. It holds\n // with one agent mounted exactly as it would with several.\n using _ = harness.interceptGatekeeper();\n\n const res = await harness.rpc(sendMessage(TENANT), {\n token: await harness.token({ tenant: "somebody-else" })\n });\n expect(res.status).toBe(401);\n });\n});\n';
2779
+
2780
+ // src/agent/templates/test/edge-spec.ts
2781
+ var edgeSpec = (spec2) => render(edge_spec_ts_default, {
2782
+ tokens: {
2783
+ TENANT: spec2.tenant,
2784
+ // `JSON.stringify` rather than `quoted()`, which is what this template
2785
+ // has always written: the two differ only for a name holding a double
2786
+ // quote, and changing it would change what a user receives.
2787
+ NAME_LITERAL: JSON.stringify(spec2.name)
2788
+ }
2789
+ });
2790
+
2791
+ // src/agent/templates/test/worker.ts.tpl
2792
+ var worker_ts_default = 'import type { ThinkModel } from "@cloudflare/think";\nimport type { WorkflowEvent, WorkflowStep } from "cloudflare:workers";\nimport { handleArtifactRoute } from "@dynamicagents/core/artifacts";\n// $when subAgent\nimport type { SubAgentClass } from "@dynamicagents/core/subagent";\n// $end\nimport {\n // $when subAgent\n call,\n // $end\n scriptedModel,\n type MockStep,\n type ModelTurnView\n} from "@dynamicagents/core/testing";\nimport { createA2AWorker, defineAgent } from "@dynamicagents/core/worker";\nimport type { TaskParams } from "@dynamicagents/core/workflow";\nimport { RETRY_BRIEF } from "@/copy";\nimport { hostManifest } from "@/host-manifest";\nimport { $AGENT_CLASS } from "@/agents/$TENANT/agent";\n// $when subAgent\nimport { $CHILD_CLASS } from "@/agents/$TENANT/children";\n// $end\nimport { $HOST_CLASS } from "@/agents/$TENANT/host";\nimport { manifest } from "@/agents/$TENANT/manifest";\nimport { $WORKFLOW_CLASS } from "@/agents/$TENANT/workflow";\n\n/**\n * The Worker the suite runs: this project\'s own, plus the agent on a scripted\n * model.\n *\n * Workers AI has no local execution mode, so the real `getModel()` cannot\n * finish a turn here. Each `Test*` class below is the real one with only its\n * model swapped$SUBAGENT_NOTE, behind the real host and the real pipeline\n * pointed at it, so a spec drives the agent\'s actual plugins, soul, card and\n * lifecycle through core\'s A2A edge. They are bound for tests only, in\n * `vitest.config.ts`.\n *\n * Every production class is re-exported, because the runtime resolves a Durable\n * Object by class name and the pool loads this module in place of\n * `src/index.ts`.\n */\n\nexport * from "@/index";\n\nexport interface TestEnv extends Env {\n $TEST_HOST_BINDING: DurableObjectNamespace<$TEST_HOST_CLASS>;\n $TEST_AGENT_BINDING: DurableObjectNamespace<$TEST_AGENT_CLASS>;\n $TEST_WORKFLOW_BINDING: Workflow<TaskParams>;\n}\n\n/** `prefix:rest` → `rest`. */\nfunction after(text: string, prefix: string): string | undefined {\n return text.startsWith(prefix) ? text.slice(prefix.length) : undefined;\n}\n\n// $when subAgent\n/** The text of the most recent tool result, as the model was shown it. */\nfunction lastToolOutput(view: ModelTurnView): string {\n for (let i = view.prompt.length - 1; i >= 0; i--) {\n const message = view.prompt[i]!;\n if (message.role !== "tool") continue;\n const part = message.content.find((p) => p.type === "tool-result") as\n { output?: { value: unknown } } | undefined;\n const value = part?.output?.value;\n return typeof value === "string" ? value : JSON.stringify(value);\n }\n return "";\n}\n\n// $end\n/**\n * The agent\'s script, keyed on the message that started the turn rather than on\n * a queue: a retry, a follow-up turn and a recovered one all consume steps, and\n * which call comes next is not something a spec controls.\n *\n * A retry arrives with `RETRY_BRIEF` in front of the original text, which is\n * how `flaky` tells its second attempt from its first.\n */\nfunction script(view: ModelTurnView): MockStep {\n const retry = view.lastUserText.startsWith(RETRY_BRIEF);\n const text = retry\n ? view.lastUserText.slice(RETRY_BRIEF.length).trimStart()\n : view.lastUserText;\n\n // Fails every attempt, so the task settles failed in this project\'s words.\n if (text === "boom") return { error: "told to fail" };\n // Fails the first attempt only: the retry\'s brief is what recovers it.\n if (text === "flaky") {\n return retry ? { text: "recovered" } : { error: "told to fail once" };\n }\n\n // $when subAgent\n // `delegate:<task>` hands the task to the sub-agent and then answers with\n // what it reported, which is what proves the result came back.\n const delegate = after(text, "delegate:");\n if (delegate !== undefined) {\n return view.answered\n ? { text: lastToolOutput(view) }\n : call("general", { task: delegate }, "Delegating.");\n }\n\n // $end\n return { text: after(text, "echo:") ?? text };\n}\n\nexport class $TEST_AGENT_CLASS extends $AGENT_CLASS {\n override getModel(): ThinkModel {\n return scriptedModel(script);\n }\n // $when subAgent\n\n override getSubAgents(): SubAgentClass[] {\n return [$TEST_CHILD_CLASS];\n }\n // $end\n}\n\n// $when subAgent\n/** The sub-agent, answering from a script of its own. */\nexport class $TEST_CHILD_CLASS extends $CHILD_CLASS {\n static override spec = $CHILD_CLASS.spec;\n\n override getModel(): ThinkModel {\n return scriptedModel((view) => ({\n text: `child did: ${view.lastUserText}`\n }));\n }\n}\n\n// $end\n/** The real host, pointed at the scripted pipeline. */\nexport class $TEST_HOST_CLASS extends $HOST_CLASS {\n // $block HOST_BINDINGS\n}\n\n/**\n * The real pipeline, on the scripted agent. It declares `run()`, as every\n * pipeline must.\n */\nexport class $TEST_WORKFLOW_CLASS extends $WORKFLOW_CLASS {\n // $block STEP_AGENT\n override run(event: WorkflowEvent<TaskParams>, step: WorkflowStep) {\n return super.run(event, step);\n }\n}\n\nconst a2a = createA2AWorker<TestEnv>({\n manifest: hostManifest,\n agents: [\n defineAgent({\n tenant: "$TENANT",\n manifest,\n agent: (env: TestEnv) => env.$TEST_HOST_BINDING\n })\n ]\n});\n\nexport default {\n async fetch(request: Request, env: TestEnv): Promise<Response> {\n return (await handleArtifactRoute(request, env)) ?? a2a(request, env);\n }\n} satisfies ExportedHandler<TestEnv>;\n';
2793
+
2794
+ // src/agent/templates/test/test-worker.ts
2795
+ function testWorkerTs(spec2, n3) {
2796
+ const T = `Test${n3.pascal}`;
2797
+ return render(worker_ts_default, {
2798
+ when: { subAgent: spec2.subAgent },
2799
+ tokens: {
2800
+ TENANT: spec2.tenant,
2801
+ AGENT_CLASS: n3.agentClass,
2802
+ HOST_CLASS: n3.hostClass,
2803
+ WORKFLOW_CLASS: n3.workflowClass,
2804
+ CHILD_CLASS: n3.childClass,
2805
+ TEST_AGENT_CLASS: `${T}Agent`,
2806
+ TEST_HOST_CLASS: `${T}Host`,
2807
+ TEST_WORKFLOW_CLASS: `${T}Workflow`,
2808
+ TEST_CHILD_CLASS: `${T}Child`,
2809
+ // A token each rather than `TEST_$SCREAMING_HOST`, which the
2810
+ // longest-run match would read as the single token `$SCREAMING_HOST`.
2811
+ TEST_HOST_BINDING: `TEST_${n3.screaming}_HOST`,
2812
+ TEST_AGENT_BINDING: `TEST_${n3.screaming}_AGENT`,
2813
+ TEST_WORKFLOW_BINDING: `TEST_${n3.workflowBinding}`,
2814
+ SUBAGENT_NOTE: spec2.subAgent ? " — and its sub-agent's —" : "",
2815
+ // The overrides that break after the `=` past the print width.
2816
+ HOST_BINDINGS: [
2817
+ assigned(
2818
+ "protected override readonly workflowBinding",
2819
+ `TEST_${n3.workflowBinding}`
2820
+ ),
2821
+ assigned(
2822
+ "protected override readonly hostBinding",
2823
+ `TEST_${n3.screaming}_HOST`
2824
+ )
2825
+ ].join("\n"),
2826
+ STEP_AGENT: assigned(
2827
+ `protected override readonly ${n3.camel}`,
2828
+ `TEST_${n3.screaming}_AGENT`
2829
+ )
2830
+ }
2831
+ });
2832
+ }
2833
+
2834
+ // src/agent/templates/test/turn.spec.ts.tpl
2835
+ var turn_spec_ts_default = 'import { describe, expect, it } from "vitest";\nimport { env } from "cloudflare:workers";\nimport {\n createAgentHarness,\n TERMINAL_CALLBACK_STATES,\n type AgentHarness\n} from "@dynamicagents/core/testing";\nimport { copy } from "@/copy";\nimport worker, { type TestEnv } from "./worker";\n\n/**\n * `$TENANT`\'s A2A lifecycle, driven end to end through core\'s edge, its host\n * and its pipeline on a scripted model: every scenario goes in as a\n * gatekeeper-signed `SendMessage` and comes out as push callbacks.\n *\n * Core\'s own suite holds the lifecycle itself. What is checked here is that\n * **this** agent is wired into it: its host runs its pipeline on it, its soul\n * and plugins load, its retry is briefed$SUBAGENT_NOTE, and its words are the ones a\n * caller reads when something goes wrong.\n *\n * **One caller per spec.** An object runs its turns one at a time, so two specs\n * sharing a caller would serialize and see each other\'s callbacks.\n */\n\nconst testEnv = env as unknown as TestEnv;\n\nfunction harnessFor(label: string): AgentHarness {\n return createAgentHarness({\n worker,\n env: testEnv,\n tenant: "$TENANT",\n identity: {\n key: `$TENANT:${label}:${crypto.randomUUID()}`,\n name: "Spec Caller",\n kind: "custom",\n workspaceId: 1\n }\n });\n}\n\nconst pause = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\ndescribe("$TENANT", () => {\n it("answers a turn and calls back exactly once", async () => {\n const harness = harnessFor("turn");\n using _ = harness.interceptGatekeeper();\n\n const accepted = await harness.send("echo:hello there");\n const done = await harness.waitForTerminal(accepted.id);\n expect(done.state).toBe("TASK_STATE_COMPLETED");\n expect(done.text).toBe("hello there");\n\n await pause(300);\n const terminals = harness.callbacks.filter(\n (c) => c.taskId === accepted.id && TERMINAL_CALLBACK_STATES.has(c.state)\n );\n expect(terminals).toHaveLength(1);\n });\n\n it("runs a failed step once more, briefed as a retry", async () => {\n const harness = harnessFor("flaky");\n using _ = harness.interceptGatekeeper();\n\n const accepted = await harness.send("flaky");\n const done = await harness.waitForTerminal(accepted.id);\n expect(done.state).toBe("TASK_STATE_COMPLETED");\n // What `RETRY_BRIEF` (src/copy.ts) bought: the second attempt knows it is\n // one, and carries on rather than starting again.\n expect(done.text).toBe("recovered");\n });\n\n it("fails a turn that errors every time, in this project\'s words", async () => {\n const harness = harnessFor("boom");\n using _ = harness.interceptGatekeeper();\n\n const accepted = await harness.send("boom");\n const failed = await harness.waitForTerminal(accepted.id);\n expect(failed.state).toBe("TASK_STATE_FAILED");\n // The agent\'s words, from src/copy.ts — core ships none.\n expect(failed.text).toBe(copy.failed);\n });\n // $when subAgent\n\n it("hands a self-contained task to its sub-agent and composes the result", async () => {\n const harness = harnessFor("delegate");\n using _ = harness.interceptGatekeeper();\n\n const accepted = await harness.send("delegate:summarize the handbook");\n const done = await harness.waitForTerminal(accepted.id);\n expect(done.state).toBe("TASK_STATE_COMPLETED");\n expect(done.text).toContain("child did: summarize the handbook");\n });\n // $end\n});\n';
2836
+
2837
+ // src/agent/templates/test/turn-spec.ts
2838
+ var turnSpec = (spec2) => render(turn_spec_ts_default, {
2839
+ when: { subAgent: spec2.subAgent },
2840
+ tokens: {
2841
+ TENANT: spec2.tenant,
2842
+ SUBAGENT_NOTE: spec2.subAgent ? ", its sub-agent is reachable under\n * the tool name its model is told" : ""
2843
+ }
2844
+ });
2845
+
2846
+ // src/agent/templates/test/manifest.spec.ts.tpl
2847
+ var manifest_spec_ts_default = 'import { describe, expect, it } from "vitest";\nimport { env } from "cloudflare:workers";\nimport { manifest } from "@/agents/$TENANT/manifest";\nimport { hostManifest } from "@/host-manifest";\nimport { plugins } from "@/agents/$TENANT/plugins";\n\n/**\n * The card a gatekeeper registers from.\n *\n * What it says is what callers believe this agent can do, so the assertions\n * here are about it staying true to the agent rather than about its prose.\n */\n\ndescribe("the agent card", () => {\n it("names the agent and describes it", () => {\n expect(manifest.name).not.toBe("");\n expect(manifest.description).not.toBe("");\n });\n\n it("gives every skill a unique id, a name and a description", () => {\n const ids = manifest.skills.map((skill) => skill.id);\n expect(new Set(ids).size).toBe(ids.length);\n for (const skill of manifest.skills) {\n expect(skill.id).not.toBe("");\n expect(skill.name).not.toBe("");\n expect(skill.description).not.toBe("");\n }\n });\n\n it("declares the protocol fields core cannot default", () => {\n // `extensions` is a required (repeated) protobuf field in v1.0: empty is a\n // declaration, absent is a protocol error. `capabilities` itself is\n // optional in the SDK\'s type, which is why it is read through `?.` here.\n expect(manifest.capabilities?.extensions).toEqual([]);\n expect(manifest.capabilities?.pushNotifications).toBe(true);\n });\n\n it("advertises a browse skill only when the browser plugin is installed", () => {\n // The assertion that keeps the card honest: a skill nobody can call is\n // worse than a short card. `plugins()` is read rather than a literal, so\n // adding or removing a capability fails here until the card follows.\n const installed = plugins(env).map((plugin) => plugin.name);\n const browses = manifest.skills.some((skill) => skill.id === "browse");\n expect(browses).toBe(installed.includes("browser"));\n });\n});\n\n/** The tenant this Worker mounts, as its stub card has to name it. */\nconst TENANT = "$TENANT";\n\ndescribe("the deployment\'s stub card", () => {\n it("names every tenant this Worker mounts", () => {\n // It is the only place this card says what is here, so a tenant missing\n // from it is a tenant an operator reading the deploy cannot discover.\n expect(hostManifest.description).toContain(TENANT);\n // The skills belong to the tenants: a client picking one from here would\n // have no way to act on it.\n expect(hostManifest.skills).toEqual([]);\n });\n});\n';
2848
+
2849
+ // src/agent/templates/test/plugins.spec.ts.tpl
2850
+ var plugins_spec_ts_default = 'import { describe, expect, it } from "vitest";\nimport { env } from "cloudflare:workers";\nimport { plugins } from "@/agents/$TENANT/plugins";\n\n/**\n * The capabilities this agent installs, against the bindings this project\n * actually declares.\n *\n * A plugin declares what it needs and core checks it when the agent starts, so\n * a capability added without its `wrangler.jsonc` binding is an agent that\n * throws on its first request. This spec is that check, run in a second rather\n * than in production: it reads the `env` the pool builds from\n * `wrangler.jsonc`, so it fails the moment the two disagree.\n */\n\ndescribe("plugins", () => {\n it("installs each capability once", () => {\n const names = plugins(env).map((plugin) => plugin.name);\n expect(new Set(names).size).toBe(names.length);\n });\n\n it("has every binding and secret its plugins require", () => {\n const missing: string[] = [];\n for (const plugin of plugins(env)) {\n const required = [\n ...(plugin.requires?.bindings ?? []),\n ...(plugin.requires?.secrets ?? [])\n ];\n for (const key of required) {\n if ((env as unknown as Record<string, unknown>)[key] == null) {\n missing.push(`${plugin.name} needs ${key}`);\n }\n }\n }\n expect(missing).toEqual([]);\n });\n});\n';
2851
+
2852
+ // src/agent/templates/test/soul.spec.ts.tpl
2853
+ var soul_spec_ts_default = 'import { describe, expect, it } from "vitest";\nimport { ASK_GUIDANCE } from "@/copy";\n// $block SOUL_IMPORT\n\n/**\n * The rules the soul has to keep, as it is rewritten.\n *\n * It **will** be rewritten — it is the one file core refuses to ship and the\n * first one to edit. These are the two things easy to break while doing it.\n */\n\ndescribe("SOUL", () => {\n it("says who the agent is and when to ask the person", () => {\n expect(SOUL).toContain($NAME_LITERAL);\n // `ask_user` stops the task and puts a question to a person. The guidance\n // for when that is worth doing is shared copy, not this agent\'s words.\n expect(SOUL).toContain(ASK_GUIDANCE);\n });\n\n it("describes no capability", () => {\n // Every plugin tells the model what it can do in a context block of its\n // own$SUBAGENT_NOTE — so removing one removes its advice with it. A\n // capability named here would outlive the capability.\n for (const claim of ["you can browse", "you have access to"]) {\n expect(SOUL.toLowerCase()).not.toContain(claim);\n }\n });\n\n it("tells the model what memory is for", () => {\n expect(MEMORY).not.toBe("");\n });\n});\n// $when subAgent\n\ndescribe("GENERAL_SOUL", () => {\n it("writes to a sub-agent that cannot see this conversation", () => {\n // The distinction is structural rather than stylistic: a sub-agent is\n // handed one self-contained task and nothing else, so a soul written as\n // though it could see the conversation is how it ends up asking a follow-up\n // question nobody will ever read.\n expect(GENERAL_SOUL).toContain("self-contained");\n expect(GENERAL_SOUL).toMatch(/do not ask follow-up questions/i);\n });\n});\n// $end\n';
2854
+
2855
+ // src/agent/templates/test/tuning.spec.ts.tpl
2856
+ var tuning_spec_ts_default = 'import { describe, expect, it } from "vitest";\nimport { TUNING } from "@/agents/$TENANT/tuning";\n\n/**\n * The numbers. Core ships none, so these are the project\'s — and two of them\n * are wrong in ways nothing else notices until a long conversation.\n */\n\ndescribe("TUNING", () => {\n it("keeps less than it compacts", () => {\n // The tail kept verbatim has to fit inside the budget that triggers\n // compaction, or compaction can never make the history smaller.\n expect(TUNING.keepRecentTokens).toBeLessThan(TUNING.compactAfterTokens);\n });\n\n it("backs off from a floor rather than down to one", () => {\n // The wait doubles from `afterMs` up to `maxMs`, so a ceiling below the\n // floor is a backoff that never happens and a number that reads as if it\n // bounds something.\n expect(TUNING.reconcile.afterMs).toBeLessThanOrEqual(\n TUNING.reconcile.maxMs\n );\n });\n\n it("names models the catalogue has", () => {\n const modelId = $MODEL_ID_RE;\n expect(TUNING.modelId).toMatch(modelId);\n expect(TUNING.compactionModelId).toMatch(modelId);\n });\n});\n';
2857
+
2858
+ // src/agent/templates/test/unit-specs.ts
2859
+ var soulSpec = (spec2) => render(soul_spec_ts_default, {
2860
+ when: { subAgent: spec2.subAgent },
2861
+ tokens: {
2862
+ /**
2863
+ * The one import here that is laid out rather than written: with the
2864
+ * sub-agent's `GENERAL_SOUL` it is three names, and prettier breaks it
2865
+ * one per line once a long tenant pushes the line past the print width.
2866
+ */
2867
+ SOUL_IMPORT: namedFrom(
2868
+ "import",
2869
+ ["MEMORY", "SOUL", ...spec2.subAgent ? ["GENERAL_SOUL"] : []],
2870
+ `@/agents/${spec2.tenant}/soul`
2871
+ ),
2872
+ NAME_LITERAL: JSON.stringify(spec2.name),
2873
+ SUBAGENT_NOTE: spec2.subAgent ? ", and each sub-agent in its tool's description" : ""
2874
+ }
2875
+ });
2876
+ var manifestSpec = (spec2) => render(manifest_spec_ts_default, { tokens: { TENANT: spec2.tenant } });
2877
+ var tuningSpec = (spec2) => render(tuning_spec_ts_default, {
2878
+ tokens: {
2879
+ TENANT: spec2.tenant,
2880
+ // The same regex the CLI validated the id with, read from `../../names.ts`
2881
+ // rather than written twice: a generated project asserting a rule this
2882
+ // one does not enforce is a project that fails its own suite.
2883
+ MODEL_ID_RE: MODEL_ID_RE.toString()
2884
+ }
2885
+ });
2886
+ var pluginsSpec = (spec2) => render(plugins_spec_ts_default, { tokens: { TENANT: spec2.tenant } });
2887
+
2888
+ // src/agent/files.ts
2889
+ function projectFiles(spec2) {
2890
+ const n3 = names(spec2.tenant);
2891
+ const file = (path3, contents) => ({
2892
+ path: path3,
2893
+ contents
2894
+ });
2895
+ return [
2896
+ file("package.json", packageJson(spec2)),
2897
+ file("wrangler.jsonc", wranglerJsonc(spec2, n3)),
2898
+ file("tsconfig.json", tsconfigJson),
2899
+ file("vitest.config.ts", vitestConfigTs(spec2, n3)),
2900
+ file("eslint.config.js", eslintConfigJs),
2901
+ file(".prettierrc", prettierrc),
2902
+ file(".prettierignore", prettierignore),
2903
+ file(".gitignore", gitignore),
2904
+ file(".nvmrc", nvmrc),
2905
+ file(".env.example", envExample(spec2)),
2906
+ file("README.md", readmeMd(spec2, n3)),
2907
+ file("AGENTS.md", agentsMd(spec2, n3)),
2908
+ file("src/index.ts", indexTs(spec2, n3)),
2909
+ file("src/host-manifest.ts", hostManifestTs(spec2)),
2910
+ file("src/copy.ts", copyTs),
2911
+ file("src/model.ts", modelTs),
2912
+ file(`${n3.dir}/definition.ts`, definitionTs(spec2, n3)),
2913
+ file(`${n3.dir}/host.ts`, hostTs(n3)),
2914
+ file(`${n3.dir}/workflow.ts`, workflowTs(n3)),
2915
+ file(`${n3.dir}/agent.ts`, agentTs(spec2, n3)),
2916
+ ...spec2.subAgent ? [file(`${n3.dir}/children.ts`, childrenTs(n3))] : [],
2917
+ file(`${n3.dir}/manifest.ts`, manifestTs(spec2)),
2918
+ file(`${n3.dir}/plugins.ts`, pluginsTs(spec2)),
2919
+ file(`${n3.dir}/soul.ts`, soulTs(spec2)),
2920
+ file(`${n3.dir}/tuning.ts`, tuningTs(spec2)),
2921
+ file("test/tsconfig.json", testTsconfigJson),
2922
+ file("test/worker.ts", testWorkerTs(spec2, n3)),
2923
+ file("test/turn.spec.ts", turnSpec(spec2)),
2924
+ file("test/edge.spec.ts", edgeSpec(spec2)),
2925
+ file("test/soul.spec.ts", soulSpec(spec2)),
2926
+ file("test/manifest.spec.ts", manifestSpec(spec2)),
2927
+ file("test/tuning.spec.ts", tuningSpec(spec2)),
2928
+ file("test/plugins.spec.ts", pluginsSpec(spec2))
2929
+ ];
2930
+ }
2931
+
2932
+ // src/cli/existing.ts
2933
+ var IGNORABLE = [
2934
+ // A repository made before the tool ran.
2935
+ ".git",
2936
+ ".hg",
2937
+ ".svn",
2938
+ // The placeholder that made the empty directory in the first place.
2939
+ ".gitkeep",
2940
+ ".keep",
2941
+ // An editor was opened on it.
2942
+ ".idea",
2943
+ ".vscode",
2944
+ // Finder and Explorer, writing without being asked.
2945
+ ".DS_Store",
2946
+ "Thumbs.db",
2947
+ "desktop.ini"
2948
+ ];
2949
+ var names2 = new Set(IGNORABLE.map((entry) => entry.toLowerCase()));
2950
+ var ignorable = (entry) => names2.has(entry.toLowerCase());
2951
+ var blocking = (entries) => entries.filter((entry) => !ignorable(entry));
2952
+
2953
+ // src/cli/plan.ts
2954
+ var stateOf = (entries) => entries.length === 0 ? "empty" : blocking(entries).length === 0 ? "ignorable" : "occupied";
2955
+ var whyNotTarget = (target2) => target2.state === "occupied" ? notEmpty(target2.named) : void 0;
2956
+ function plan(spec2, target2) {
2957
+ const refuse = (problem2) => ({ ok: false, problem: problem2 });
2958
+ const answers = [
2959
+ asBlueprint(spec2.blueprint),
2960
+ asTenant(spec2.tenant),
2961
+ asModelId(spec2.modelId),
2962
+ asDescription(spec2.description)
2963
+ ];
2964
+ for (const answer of answers) {
2965
+ if ("problem" in answer) return refuse(answer.problem);
2966
+ }
2967
+ const problem = whyNotTarget(target2);
2968
+ if (problem !== void 0) return refuse(problem);
2969
+ return { ok: true, plan: { spec: spec2, target: target2, files: projectFiles(spec2) } };
2970
+ }
2971
+
2972
+ // src/cli/write.ts
2973
+ import {
2974
+ lstat,
2975
+ mkdir,
2976
+ mkdtemp,
2977
+ readdir,
2978
+ rename,
2979
+ rm,
2980
+ rmdir,
2981
+ writeFile
2982
+ } from "node:fs/promises";
2983
+ import path from "node:path";
2984
+ var TargetChanged = class extends Error {
2985
+ constructor(target2, found) {
2986
+ super(`${target2} is no longer empty: ${found.join(", ")}`);
2987
+ this.target = target2;
2988
+ this.found = found;
2989
+ this.name = "TargetChanged";
2990
+ }
2991
+ target;
2992
+ found;
2993
+ };
2994
+ async function entriesAt(dir) {
2995
+ try {
2996
+ return await readdir(dir);
2997
+ } catch (err) {
2998
+ const { code } = err;
2999
+ if (code === "ENOENT") return [];
3000
+ if (code === "ENOTDIR") throw new TargetChanged(dir, [path.basename(dir)]);
3001
+ throw err;
3002
+ }
3003
+ }
3004
+ var taken = (at) => lstat(at).then(
3005
+ () => true,
3006
+ () => false
3007
+ );
3008
+ async function commitEntries(staging, target2) {
3009
+ const landed = [];
3010
+ try {
3011
+ for (const entry of (await readdir(staging)).sort()) {
3012
+ const to = path.join(target2, entry);
3013
+ if (await taken(to)) throw new TargetChanged(target2, [entry]);
3014
+ await rename(path.join(staging, entry), to);
3015
+ landed.push(entry);
3016
+ }
3017
+ } catch (err) {
3018
+ for (const entry of landed.reverse()) {
3019
+ await rename(path.join(target2, entry), path.join(staging, entry)).catch(
3020
+ () => void 0
3021
+ );
3022
+ }
3023
+ throw err;
3024
+ }
3025
+ await rmdir(staging).catch(() => void 0);
3026
+ }
3027
+ async function commit(staging, target2) {
3028
+ const existing = await entriesAt(target2);
3029
+ if (existing.length === 0) {
3030
+ await rmdir(target2).catch(() => void 0);
3031
+ await rename(staging, target2);
3032
+ return;
3033
+ }
3034
+ const blocked = blocking(existing);
3035
+ if (blocked.length > 0) throw new TargetChanged(target2, blocked);
3036
+ await commitEntries(staging, target2);
3037
+ }
3038
+ async function writeProject(target2, files) {
3039
+ const parent = path.dirname(target2);
3040
+ await mkdir(parent, { recursive: true });
3041
+ const staging = await mkdtemp(path.join(parent, ".dynamicagents-"));
3042
+ try {
3043
+ for (const file of files) {
3044
+ const full = path.join(staging, file.path);
3045
+ await mkdir(path.dirname(full), { recursive: true });
3046
+ await writeFile(full, file.contents, "utf8");
3047
+ }
3048
+ await commit(staging, target2);
3049
+ } catch (err) {
3050
+ await rm(staging, { recursive: true, force: true });
3051
+ throw err;
3052
+ }
3053
+ }
3054
+
3055
+ // src/cli.ts
3056
+ var { version } = JSON.parse(
3057
+ readFileSync(new URL("../package.json", import.meta.url), "utf8")
3058
+ );
3059
+ var argv = read(process.argv.slice(2));
3060
+ var print = (text2) => new Promise((resolve) => {
3061
+ process.stdout.write(`${text2}
3062
+ `, () => resolve());
3063
+ });
3064
+ if (argv.want === "help") {
3065
+ await print(help(version));
3066
+ process.exit(0);
3067
+ }
3068
+ if (argv.want === "version") {
3069
+ await print(version);
3070
+ process.exit(0);
3071
+ }
3072
+ var interactive = process.stdin.isTTY === true;
3073
+ var hyperlinks = interactive && (process.env.TERM_PROGRAM !== void 0 || process.env.WT_SESSION !== void 0);
3074
+ function stop(message) {
3075
+ log.error(message);
3076
+ cancel(nothingBuilt);
3077
+ process.exit(1);
3078
+ }
3079
+ function answered(value) {
3080
+ if (isCancel(value)) {
3081
+ cancel(nothingBuilt);
3082
+ process.exit(1);
3083
+ }
3084
+ return value;
3085
+ }
3086
+ async function settle(reply, ask) {
3087
+ if (reply.kind === "use") return reply.value;
3088
+ if (reply.kind === "stop") stop(reply.problem);
3089
+ if (reply.problem !== void 0) log.warn(reply.problem);
3090
+ return answered(await ask(reply.initial));
3091
+ }
3092
+ var typed = (answer) => typeof answer === "string" ? answer.trim() : answer;
3093
+ async function optional(flag, ask, fallback) {
3094
+ if (flag !== void 0) return flag;
3095
+ if (!interactive) return fallback;
3096
+ return answered(await ask());
3097
+ }
3098
+ intro(title(version));
3099
+ if (argv.want === "trouble") stop(badArgument(argv.trouble));
3100
+ var { flags, positionals } = argv;
3101
+ async function targetState(dir) {
3102
+ try {
3103
+ const info = await stat(dir);
3104
+ if (!info.isDirectory()) return "occupied";
3105
+ return stateOf(await readdir2(dir));
3106
+ } catch (err) {
3107
+ if (err.code !== "ENOENT") throw err;
3108
+ return "free";
3109
+ }
3110
+ }
3111
+ async function targetAt(named) {
3112
+ const dir = path2.resolve(process.cwd(), named);
3113
+ let state;
3114
+ try {
3115
+ state = await targetState(dir);
3116
+ } catch (err) {
3117
+ stop(cannotRead(named, err.message));
3118
+ }
3119
+ const target2 = { named, dir, state };
3120
+ const problem = whyNotTarget(target2);
3121
+ if (problem !== void 0) stop(problem);
3122
+ return target2;
3123
+ }
3124
+ var askModelId2 = (initial) => text({
3125
+ message: askModelId,
3126
+ placeholder: DEFAULT_MODEL_ID,
3127
+ initialValue: initial,
3128
+ validate: whyNot(asModelId)
3129
+ });
3130
+ async function chooseModel() {
3131
+ const choice = answered(
3132
+ await select({
3133
+ message: askModel,
3134
+ options: [
3135
+ { value: "default", label: defaultModelLabel },
3136
+ { value: "other", label: otherModelLabel(hyperlinks) }
3137
+ ]
3138
+ })
3139
+ );
3140
+ if (choice === "default") return DEFAULT_MODEL_ID;
3141
+ return typed(await askModelId2());
3142
+ }
3143
+ var kind = await settle(
3144
+ replyTo(positionals[0], asKind, { interactive }),
3145
+ () => select({
3146
+ message: question,
3147
+ options: KINDS.map((entry) => ({
3148
+ value: entry,
3149
+ label: entry.label,
3150
+ hint: entry.hint
3151
+ }))
3152
+ })
3153
+ );
3154
+ if (!kind.ready) {
3155
+ note(kind.about, kind.label, { format: (line) => line.trimStart() });
3156
+ outro(workInProgress(kind));
3157
+ process.exit(0);
3158
+ }
3159
+ var namedDir = flags.dir ?? positionals[2];
3160
+ var judgedDir = namedDir === void 0 ? void 0 : await targetAt(namedDir);
3161
+ var blueprint = await settle(
3162
+ replyTo(positionals[1], asBlueprint, { interactive }),
3163
+ () => select({
3164
+ message: whichAgent,
3165
+ options: BLUEPRINTS.map((entry) => ({
3166
+ value: entry,
3167
+ label: entry.label,
3168
+ hint: entry.hint
3169
+ }))
3170
+ })
3171
+ );
3172
+ var tenant = await settle(
3173
+ replyTo(flags.name, asTenant, { interactive, named: "--name" }),
3174
+ async (initial) => typed(
3175
+ await text({
3176
+ message: askTenant,
3177
+ placeholder: tenantPlaceholder,
3178
+ initialValue: initial,
3179
+ validate: whyNot(asTenant)
3180
+ })
3181
+ )
3182
+ );
3183
+ var description = await settle(
3184
+ replyTo(flags.description, asDescription, {
3185
+ interactive,
3186
+ named: "--description"
3187
+ }),
3188
+ async (initial) => typed(
3189
+ await text({
3190
+ message: askDescription,
3191
+ placeholder: descriptionPlaceholder,
3192
+ initialValue: initial,
3193
+ validate: whyNot(asDescription)
3194
+ })
3195
+ )
3196
+ );
3197
+ var subAgent = await optional(
3198
+ flags.subagent,
3199
+ () => confirm({ message: askSubAgent, initialValue: true }),
3200
+ true
3201
+ );
3202
+ var capabilities = await optional(
3203
+ flags.browser === true ? ["browser"] : flags.browser === false ? [] : void 0,
3204
+ () => multiselect({
3205
+ message: askCapabilities,
3206
+ options: CAPABILITIES.map((capability) => ({
3207
+ value: capability.value,
3208
+ label: capability.label,
3209
+ hint: capability.hint
3210
+ })),
3211
+ // Nothing is pre-selected: a capability arrives because it was asked for,
3212
+ // never because it was the default.
3213
+ initialValues: [],
3214
+ required: false
3215
+ }),
3216
+ []
3217
+ );
3218
+ var modelId = await settle(
3219
+ replyTo(flags.model, asModelId, {
3220
+ interactive,
3221
+ named: "--model",
3222
+ fallback: DEFAULT_MODEL_ID
3223
+ }),
3224
+ // A `--model` that will not do means a model was chosen deliberately, so the
3225
+ // menu is skipped and the id itself is asked for, on what was typed.
3226
+ async (initial) => initial === void 0 ? chooseModel() : typed(await askModelId2(initial))
3227
+ );
3228
+ var target = judgedDir ?? await targetAt(tenant);
3229
+ var spec = {
3230
+ tenant,
3231
+ name: displayName(tenant),
3232
+ description,
3233
+ blueprint: blueprint.value,
3234
+ subAgent,
3235
+ capabilities,
3236
+ modelId
3237
+ };
3238
+ var planned = plan(spec, target);
3239
+ if (!planned.ok) stop(planned.problem);
3240
+ note(tree(target.named, planned.plan.files), blueprint.label);
3241
+ if (flags["dry-run"] === true) {
3242
+ outro(dryRun);
3243
+ process.exit(0);
3244
+ }
3245
+ if (flags.yes !== true && interactive) {
3246
+ const go = answered(await confirm({ message: confirmWrite }));
3247
+ if (!go) {
3248
+ cancel(nothingBuilt);
3249
+ process.exit(1);
3250
+ }
3251
+ }
3252
+ try {
3253
+ await writeProject(target.dir, planned.plan.files);
3254
+ } catch (err) {
3255
+ if (!(err instanceof TargetChanged)) throw err;
3256
+ stop(notEmpty(target.named));
3257
+ }
3258
+ log.success(wrote(target.named));
3259
+ var installing2 = spinner();
3260
+ installing2.start(installing);
3261
+ try {
3262
+ await installProject(target.dir, (step) => installing2.message(step));
3263
+ installing2.stop(installed);
3264
+ } catch (err) {
3265
+ installing2.stop(installing);
3266
+ log.error(finishByHand(target.named, err.message));
3267
+ cancel(notInstalled(spec.name));
3268
+ process.exit(1);
3269
+ }
3270
+ note(nextSteps(target.named, tenant), "Next");
3271
+ outro(outroLine(spec.name));