An idle game that runs beside Claude Code, fed only by the work Claude does for you

CC Idle as a Claude Code mod: the game runs in a pane beside the transcript, fed by Claude Code's own events. No tmux, no daemon, no hook shims.
Requires Claude Code v2.1.287 or later.
/plugin marketplace add RichardAtCT/cc-idle
/plugin install cc-idle@cc-idle
Or try it from a clone for one session: claude --plugin-dir ./plugins/cc-idle.
To pick up new commits from main inside Claude Code, refresh the marketplace, then load the new version into the running session. No restart is needed.
/plugin marketplace update cc-idle
/reload-plugins
If the new version does not appear, type /plugin, open cc-idle under the installed plugins, choose update, then run /reload-plugins again. From a shell, the same update is:
claude plugin marketplace update cc-idle && claude plugin update cc-idle@cc-idle
plugin.json sets no version on purpose. Claude Code then uses the commit SHA as the version, so every merge to main is an update. claude plugin validate warns about the missing version; ignore that warning.
/idle. It works mid-turn, so you can play while Claude works. Until you have played once, a toast tells you so.→ line under the header names the next useful move when there is one./idle also gives the pane the keyboard. Esc hands it back to the prompt. /idle close closes the pane.| Key | Action |
|---|---|
g / r / d | Buy a GPU / rack / datacenter in the focused region |
a | Acknowledge the region's incident (the post-mortem pays engineering) |
n | Next region |
h | Hire a researcher |
e | Run an experiment |
s | Ship the generation (asks y / n first) |
v | Breakthrough tree (1–6 buy, v back) |
c | Talk to the board (Enter on an empty line goes back) |
i | How to play (i back) |
The original TUI's tab and P became n and s, because a mod's hotkeys must be a single lowercase letter or digit, and Tab and the arrow keys stay Claude Code's.
A board member of your lab lives in the pane. It is Haiku, run through your own Claude Code session, so each line it says is one small Haiku call on your account.

c to open the board, type a short line (80 characters at most) and press Enter. It answers in one line. The text field takes every key, so Enter on an empty line goes back to the game. Esc hands the keyboard to the prompt, as on every screen.| Claude Code event | Becomes | Economy |
|---|---|---|
turn.start (main loop) | UserPromptSubmit | the region is hot; the turn's accrual starts |
turn.step (every model request, subagents too) | TokenUsage | output tokens → Compute, live |
tool.call succeeded | PostToolUse | Edit/Write/Bash → engineering, Read/Search/Fetch → research data |
tool.call errored | PostToolUse (failed) | an incident |
turn.complete (subagent) | SubagentStop | a training run |
turn.complete (main, answered) | Stop | milestone shipped: completion bonus and reputation |
session.end | SessionEnd | the session leaves its region |
The mod builds the same v1 envelopes the shell hooks wrote, so the engine in packages/game, its balance constants and the replay/backtest tooling are unchanged.
One economy for all your sessions. Every Claude Code session running the mod shares one save in $.store. Each session applies events locally at once, then about a second later re-reads the save, replays its queued events on top and writes it back. Every 5 seconds it picks up the other sessions' writes. Only a write that lands between another session's read and its write is lost.
What it touches. claude plugin validate plugins/cc-idle lists every call the mod makes: $.store, $.state, $.ui, $.clock, $.model.complete, $.command.register, $.session.id and $.session.cwd. Its only model calls are the board's Haiku calls. It makes no filesystem, network or process calls. It never denies or rewrites a tool call, prompt or turn: every hook passes its event on unchanged.
hooks/register.js is generated. Its sources are in packages/mod/src, bundled with the pure game engine and zod by pnpm --filter @ccidle/mod build. A mod loads no packages and has no Node, so everything it needs travels in that one file.
pnpm --filter @ccidle/mod build # regenerate hooks/register.js
pnpm --filter @ccidle/mod test # sync, telemetry and view unit tests (vitest)
pnpm --filter @ccidle/mod typecheck # against the mods API types in packages/mod/types
claude plugin validate plugins/cc-idle
claude plugin test plugins/cc-idle # hooks and pane tests in Claude Code's own test engine
packages/mod/types/claude-code.d.ts is the mods API declaration file that Claude Code 2.1.287 writes. When Claude Code updates, copy in the new one; don't edit it by hand.
hooks/register.js 5714 lines1// GENERATED by packages/mod/build.mjs from packages/mod/src and packages/game. Do not edit by hand.
2var __defProp = Object.defineProperty;
3var __export = (target, all) => {
4 for (var name in all)
5 __defProp(target, name, { get: all[name], enumerable: true });
6};
7
8// src/register.tsx
9import { atom, read, update } from "claude-code";
10
11// ../game/src/balance.ts
12var INFRA_TIERS = [
13 { id: "gpu", name: "GPU", baseCost: 500, costGrowth: 1.15, multiplier: 0.02, requiresPrevious: 0, glyph: "\u25AA" },
14 { id: "rack", name: "Rack", baseCost: 12e3, costGrowth: 1.18, multiplier: 0.3, requiresPrevious: 8, glyph: "\u25AE" },
15 { id: "datacenter", name: "Datacenter", baseCost: 25e4, costGrowth: 1.22, multiplier: 2, requiresPrevious: 4, glyph: "\u2B22" }
16];
17var BALANCE = {
18 compute: {
19 /** Compute (FLOPS) granted per weighted output token. */
20 perOutputToken: 1,
21 /**
22 * Diminishing returns (PRD §5): per region, the first
23 * `fullRateTokensPerWindow` output tokens in a rolling `windowMs` window
24 * convert at full rate; beyond that the marginal rate is
25 * 1 / (1 + log2(windowTokens / fullRateTokensPerWindow)).
26 */
27 fullRateTokensPerWindow: 4e4,
28 windowMs: 36e5,
29 /** Retroactive completion multiplier on a turn's accrual when it ends in Stop. */
30 turnCompletionBonus: 0.25,
31 /** Small flat Compute granted to every live region on any Stop (PRD §4). */
32 stopAllRegionBonus: 10
33 },
34 engineering: {
35 /** Engineering per successful engineering-class tool call. */
36 perToolCall: 2,
37 /** Engineering granted for acknowledging an incident ("post-mortem"). */
38 postMortem: 3
39 },
40 research: {
41 /** Research Data per successful research-class tool call. */
42 perToolCall: 1
43 },
44 reputation: {
45 /** Reputation per clean Stop (completed turn). */
46 perStop: 1,
47 /** Open question #1 resolved per the PRD lean: a mirror, not a treadmill. */
48 decayPerDay: 0
49 },
50 /** Tool classification for resource accrual (PRD §3). */
51 tools: {
52 engineering: ["Edit", "Write", "MultiEdit", "NotebookEdit", "Bash"],
53 research: ["Read", "WebSearch", "WebFetch", "Grep", "Glob"]
54 },
55 lab: {
56 /** First researcher's cost in Engineering; geometric growth per hire. */
57 hireBaseCost: 60,
58 hireCostGrowth: 1.35,
59 /** Hire cap = 1 + floor(reputation / reputationPerHireSlot) — the §3 soft gate. */
60 reputationPerHireSlot: 5,
61 /** Each researcher adds this to the lab progress multiplier. */
62 progressPerResearcher: 0.25,
63 /** Manual experiment: costs and Model Progress payout. */
64 experimentDataCost: 25,
65 experimentEngineeringCost: 10,
66 experimentProgress: 10,
67 /** Training run (fires on SubagentStop): Research Data consumed per run. */
68 trainingDataCost: 15,
69 /** Progress payout = base + perMinute × clamped subagent minutes. */
70 trainingBaseProgress: 5,
71 trainingProgressPerMinute: 4,
72 trainingMaxMinutes: 30,
73 /** Assumed duration when the SubagentStop payload carries none. */
74 trainingDefaultMinutes: 2,
75 /** Compute payout per training-run minute (scaled by the region multiplier). */
76 trainingComputePerMinute: 100,
77 /**
78 * With no Research Data banked a run still pays this fraction — training
79 * never blocks (PRD §1.4), data just makes it much better.
80 */
81 trainingMinEfficiency: 0.25
82 },
83 generations: {
84 /** Model Progress required to ship Gen-1; geometric growth per generation. */
85 baseProgress: 100,
86 progressGrowth: 2.5,
87 /** Breakthroughs banked per shipped generation, plus overshoot bonus below. */
88 breakthroughsPerShip: 3,
89 /** +1 Breakthrough per whole extra multiple of the threshold, capped here. */
90 overshootBonusCap: 3
91 },
92 incidents: {
93 /** Frequency caps (PRD §6): alert fatigue guard. */
94 maxActivePerRegion: 3,
95 minIntervalMs: 6e4,
96 /** Multiplicative regional debuff per active incident (mild by design). */
97 debuffPerIncident: 0.08,
98 /** Floor so a noisy region never drops below half rate. */
99 debuffFloor: 0.5
100 },
101 /** Bounded narration log kept in game state for the TUI feed. */
102 logLimit: 100
103};
104function tierCost(tier, owned) {
105 return Math.ceil(tier.baseCost * Math.pow(tier.costGrowth, owned));
106}
107function hireCost(researchers) {
108 return Math.ceil(BALANCE.lab.hireBaseCost * Math.pow(BALANCE.lab.hireCostGrowth, researchers));
109}
110function generationThreshold(generation) {
111 return Math.ceil(
112 BALANCE.generations.baseProgress * Math.pow(BALANCE.generations.progressGrowth, generation - 1)
113 );
114}
115function hireCap(reputation) {
116 return 1 + Math.floor(reputation / BALANCE.lab.reputationPerHireSlot);
117}
118
119// ../game/src/content.ts
120var INCIDENT_FLAVOURS = [
121 "GPU thermal event in hall B",
122 "eval regression on the nightly suite",
123 "on-call page: gradient overflow",
124 "checkpoint corruption detected",
125 "dataloader stall in shard 7",
126 "spot capacity reclaimed mid-epoch",
127 "network fabric flapping",
128 "cooling loop pressure warning"
129];
130var BREAKTHROUGH_NODES = [
131 {
132 id: "quantization",
133 name: "Quantization",
134 description: "+20% Compute conversion per level",
135 maxLevel: 5,
136 cost: (level) => 1 + level
137 },
138 {
139 id: "synthetic-data",
140 name: "Synthetic Data",
141 description: "+25% Research Data per level",
142 maxLevel: 5,
143 cost: (level) => 1 + level
144 },
145 {
146 id: "scaling-laws",
147 name: "Scaling Laws",
148 description: "+25% Model Progress from training & experiments per level",
149 maxLevel: 5,
150 cost: (level) => 1 + level
151 },
152 {
153 id: "self-healing",
154 name: "Self-Healing Infra",
155 description: "incidents auto-acknowledge (post-mortem included)",
156 maxLevel: 1,
157 cost: () => 2
158 },
159 {
160 id: "procurement",
161 name: "Procurement Bots",
162 description: "auto-buy GPUs whenever a region can afford them",
163 maxLevel: 1,
164 cost: () => 2
165 },
166 {
167 id: "blueprints",
168 name: "Reference Designs",
169 description: "each new generation starts with 4 GPUs per region per level",
170 maxLevel: 3,
171 cost: (level) => 2 + level
172 }
173];
174function breakthroughNode(id) {
175 return BREAKTHROUGH_NODES.find((node) => node.id === id);
176}
177
178// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
179var external_exports = {};
180__export(external_exports, {
181 BRAND: () => BRAND,
182 DIRTY: () => DIRTY,
183 EMPTY_PATH: () => EMPTY_PATH,
184 INVALID: () => INVALID,
185 NEVER: () => NEVER,
186 OK: () => OK,
187 ParseStatus: () => ParseStatus,
188 Schema: () => ZodType,
189 ZodAny: () => ZodAny,
190 ZodArray: () => ZodArray,
191 ZodBigInt: () => ZodBigInt,
192 ZodBoolean: () => ZodBoolean,
193 ZodBranded: () => ZodBranded,
194 ZodCatch: () => ZodCatch,
195 ZodDate: () => ZodDate,
196 ZodDefault: () => ZodDefault,
197 ZodDiscriminatedUnion: () => ZodDiscriminatedUnion,
198 ZodEffects: () => ZodEffects,
199 ZodEnum: () => ZodEnum,
200 ZodError: () => ZodError,
201 ZodFirstPartyTypeKind: () => ZodFirstPartyTypeKind,
202 ZodFunction: () => ZodFunction,
203 ZodIntersection: () => ZodIntersection,
204 ZodIssueCode: () => ZodIssueCode,
205 ZodLazy: () => ZodLazy,
206 ZodLiteral: () => ZodLiteral,
207 ZodMap: () => ZodMap,
208 ZodNaN: () => ZodNaN,
209 ZodNativeEnum: () => ZodNativeEnum,
210 ZodNever: () => ZodNever,
211 ZodNull: () => ZodNull,
212 ZodNullable: () => ZodNullable,
213 ZodNumber: () => ZodNumber,
214 ZodObject: () => ZodObject,
215 ZodOptional: () => ZodOptional,
216 ZodParsedType: () => ZodParsedType,
217 ZodPipeline: () => ZodPipeline,
218 ZodPromise: () => ZodPromise,
219 ZodReadonly: () => ZodReadonly,
220 ZodRecord: () => ZodRecord,
221 ZodSchema: () => ZodType,
222 ZodSet: () => ZodSet,
223 ZodString: () => ZodString,
224 ZodSymbol: () => ZodSymbol,
225 ZodTransformer: () => ZodEffects,
226 ZodTuple: () => ZodTuple,
227 ZodType: () => ZodType,
228 ZodUndefined: () => ZodUndefined,
229 ZodUnion: () => ZodUnion,
230 ZodUnknown: () => ZodUnknown,
231 ZodVoid: () => ZodVoid,
232 addIssueToContext: () => addIssueToContext,
233 any: () => anyType,
234 array: () => arrayType,
235 bigint: () => bigIntType,
236 boolean: () => booleanType,
237 coerce: () => coerce,
238 custom: () => custom,
239 date: () => dateType,
240 datetimeRegex: () => datetimeRegex,
241 defaultErrorMap: () => en_default,
242 discriminatedUnion: () => discriminatedUnionType,
243 effect: () => effectsType,
244 enum: () => enumType,
245 function: () => functionType,
246 getErrorMap: () => getErrorMap,
247 getParsedType: () => getParsedType,
248 instanceof: () => instanceOfType,
249 intersection: () => intersectionType,
250 isAborted: () => isAborted,
251 isAsync: () => isAsync,
252 isDirty: () => isDirty,
253 isValid: () => isValid,
254 late: () => late,
255 lazy: () => lazyType,
256 literal: () => literalType,
257 makeIssue: () => makeIssue,
258 map: () => mapType,
259 nan: () => nanType,
260 nativeEnum: () => nativeEnumType,
261 never: () => neverType,
262 null: () => nullType,
263 nullable: () => nullableType,
264 number: () => numberType,
265 object: () => objectType,
266 objectUtil: () => objectUtil,
267 oboolean: () => oboolean,
268 onumber: () => onumber,
269 optional: () => optionalType,
270 ostring: () => ostring,
271 pipeline: () => pipelineType,
272 preprocess: () => preprocessType,
273 promise: () => promiseType,
274 quotelessJson: () => quotelessJson,
275 record: () => recordType,
276 set: () => setType,
277 setErrorMap: () => setErrorMap,
278 strictObject: () => strictObjectType,
279 string: () => stringType,
280 symbol: () => symbolType,
281 transformer: () => effectsType,
282 tuple: () => tupleType,
283 undefined: () => undefinedType,
284 union: () => unionType,
285 unknown: () => unknownType,
286 util: () => util,
287 void: () => voidType
288});
289
290// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js
291var util;
292(function(util2) {
293 util2.assertEqual = (_) => {
294 };
295 function assertIs(_arg) {
296 }
297 util2.assertIs = assertIs;
298 function assertNever(_x) {
299 throw new Error();
300 }
301 util2.assertNever = assertNever;
302 util2.arrayToEnum = (items) => {
303 const obj = {};
304 for (const item of items) {
305 obj[item] = item;
306 }
307 return obj;
308 };
309 util2.getValidEnumValues = (obj) => {
310 const validKeys = util2.objectKeys(obj).filter((k) => typeof obj[obj[k]] !== "number");
311 const filtered = {};
312 for (const k of validKeys) {
313 filtered[k] = obj[k];
314 }
315 return util2.objectValues(filtered);
316 };
317 util2.objectValues = (obj) => {
318 return util2.objectKeys(obj).map(function(e) {
319 return obj[e];
320 });
321 };
322 util2.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object) => {
323 const keys = [];
324 for (const key in object) {
325 if (Object.prototype.hasOwnProperty.call(object, key)) {
326 keys.push(key);
327 }
328 }
329 return keys;
330 };
331 util2.find = (arr, checker) => {
332 for (const item of arr) {
333 if (checker(item))
334 return item;
335 }
336 return void 0;
337 };
338 util2.isInteger = typeof Number.isInteger === "function" ? (val) => Number.isInteger(val) : (val) => typeof val === "number" && Number.isFinite(val) && Math.floor(val) === val;
339 function joinValues(array, separator = " | ") {
340 return array.map((val) => typeof val === "string" ? `'${val}'` : val).join(separator);
341 }
342 util2.joinValues = joinValues;
343 util2.jsonStringifyReplacer = (_, value) => {
344 if (typeof value === "bigint") {
345 return value.toString();
346 }
347 return value;
348 };
349})(util || (util = {}));
350var objectUtil;
351(function(objectUtil2) {
352 objectUtil2.mergeShapes = (first, second) => {
353 return {
354 ...first,
355 ...second
356 // second overwrites first
357 };
358 };
359})(objectUtil || (objectUtil = {}));
360var ZodParsedType = util.arrayToEnum([
361 "string",
362 "nan",
363 "number",
364 "integer",
365 "float",
366 "boolean",
367 "date",
368 "bigint",
369 "symbol",
370 "function",
371 "undefined",
372 "null",
373 "array",
374 "object",
375 "unknown",
376 "promise",
377 "void",
378 "never",
379 "map",
380 "set"
381]);
382var getParsedType = (data) => {
383 const t = typeof data;
384 switch (t) {
385 case "undefined":
386 return ZodParsedType.undefined;
387 case "string":
388 return ZodParsedType.string;
389 case "number":
390 return Number.isNaN(data) ? ZodParsedType.nan : ZodParsedType.number;
391 case "boolean":
392 return ZodParsedType.boolean;
393 case "function":
394 return ZodParsedType.function;
395 case "bigint":
396 return ZodParsedType.bigint;
397 case "symbol":
398 return ZodParsedType.symbol;
399 case "object":
400 if (Array.isArray(data)) {
401 return ZodParsedType.array;
402 }
403 if (data === null) {
404 return ZodParsedType.null;
405 }
406 if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") {
407 return ZodParsedType.promise;
408 }
409 if (typeof Map !== "undefined" && data instanceof Map) {
410 return ZodParsedType.map;
411 }
412 if (typeof Set !== "undefined" && data instanceof Set) {
413 return ZodParsedType.set;
414 }
415 if (typeof Date !== "undefined" && data instanceof Date) {
416 return ZodParsedType.date;
417 }
418 return ZodParsedType.object;
419 default:
420 return ZodParsedType.unknown;
421 }
422};
423
424// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js
425var ZodIssueCode = util.arrayToEnum([
426 "invalid_type",
427 "invalid_literal",
428 "custom",
429 "invalid_union",
430 "invalid_union_discriminator",
431 "invalid_enum_value",
432 "unrecognized_keys",
433 "invalid_arguments",
434 "invalid_return_type",
435 "invalid_date",
436 "invalid_string",
437 "too_small",
438 "too_big",
439 "invalid_intersection_types",
440 "not_multiple_of",
441 "not_finite"
442]);
443var quotelessJson = (obj) => {
444 const json = JSON.stringify(obj, null, 2);
445 return json.replace(/"([^"]+)":/g, "$1:");
446};
447var ZodError = class _ZodError extends Error {
448 get errors() {
449 return this.issues;
450 }
451 constructor(issues) {
452 super();
453 this.issues = [];
454 this.addIssue = (sub) => {
455 this.issues = [...this.issues, sub];
456 };
457 this.addIssues = (subs = []) => {
458 this.issues = [...this.issues, ...subs];
459 };
460 const actualProto = new.target.prototype;
461 if (Object.setPrototypeOf) {
462 Object.setPrototypeOf(this, actualProto);
463 } else {
464 this.__proto__ = actualProto;
465 }
466 this.name = "ZodError";
467 this.issues = issues;
468 }
469 format(_mapper) {
470 const mapper = _mapper || function(issue) {
471 return issue.message;
472 };
473 const fieldErrors = { _errors: [] };
474 const processError = (error) => {
475 for (const issue of error.issues) {
476 if (issue.code === "invalid_union") {
477 issue.unionErrors.map(processError);
478 } else if (issue.code === "invalid_return_type") {
479 processError(issue.returnTypeError);
480 } else if (issue.code === "invalid_arguments") {
481 processError(issue.argumentsError);
482 } else if (issue.path.length === 0) {
483 fieldErrors._errors.push(mapper(issue));
484 } else {
485 let curr = fieldErrors;
486 let i = 0;
487 while (i < issue.path.length) {
488 const el = issue.path[i];
489 const terminal = i === issue.path.length - 1;
490 if (!terminal) {
491 curr[el] = curr[el] || { _errors: [] };
492 } else {
493 curr[el] = curr[el] || { _errors: [] };
494 curr[el]._errors.push(mapper(issue));
495 }
496 curr = curr[el];
497 i++;
498 }
499 }
500 }
501 };
502 processError(this);
503 return fieldErrors;
504 }
505 static assert(value) {
506 if (!(value instanceof _ZodError)) {
507 throw new Error(`Not a ZodError: ${value}`);
508 }
509 }
510 toString() {
511 return this.message;
512 }
513 get message() {
514 return JSON.stringify(this.issues, util.jsonStringifyReplacer, 2);
515 }
516 get isEmpty() {
517 return this.issues.length === 0;
518 }
519 flatten(mapper = (issue) => issue.message) {
520 const fieldErrors = {};
521 const formErrors = [];
522 for (const sub of this.issues) {
523 if (sub.path.length > 0) {
524 const firstEl = sub.path[0];
525 fieldErrors[firstEl] = fieldErrors[firstEl] || [];
526 fieldErrors[firstEl].push(mapper(sub));
527 } else {
528 formErrors.push(mapper(sub));
529 }
530 }
531 return { formErrors, fieldErrors };
532 }
533 get formErrors() {
534 return this.flatten();
535 }
536};
537ZodError.create = (issues) => {
538 const error = new ZodError(issues);
539 return error;
540};
541
542// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.js
543var errorMap = (issue, _ctx) => {
544 let message;
545 switch (issue.code) {
546 case ZodIssueCode.invalid_type:
547 if (issue.received === ZodParsedType.undefined) {
548 message = "Required";
549 } else {
550 message = `Expected ${issue.expected}, received ${issue.received}`;
551 }
552 break;
553 case ZodIssueCode.invalid_literal:
554 message = `Invalid literal value, expected ${JSON.stringify(issue.expected, util.jsonStringifyReplacer)}`;
555 break;
556 case ZodIssueCode.unrecognized_keys:
557 message = `Unrecognized key(s) in object: ${util.joinValues(issue.keys, ", ")}`;
558 break;
559 case ZodIssueCode.invalid_union:
560 message = `Invalid input`;
561 break;
562 case ZodIssueCode.invalid_union_discriminator:
563 message = `Invalid discriminator value. Expected ${util.joinValues(issue.options)}`;
564 break;
565 case ZodIssueCode.invalid_enum_value:
566 message = `Invalid enum value. Expected ${util.joinValues(issue.options)}, received '${issue.received}'`;
567 break;
568 case ZodIssueCode.invalid_arguments:
569 message = `Invalid function arguments`;
570 break;
571 case ZodIssueCode.invalid_return_type:
572 message = `Invalid function return type`;
573 break;
574 case ZodIssueCode.invalid_date:
575 message = `Invalid date`;
576 break;
577 case ZodIssueCode.invalid_string:
578 if (typeof issue.validation === "object") {
579 if ("includes" in issue.validation) {
580 message = `Invalid input: must include "${issue.validation.includes}"`;
581 if (typeof issue.validation.position === "number") {
582 message = `${message} at one or more positions greater than or equal to ${issue.validation.position}`;
583 }
584 } else if ("startsWith" in issue.validation) {
585 message = `Invalid input: must start with "${issue.validation.startsWith}"`;
586 } else if ("endsWith" in issue.validation) {
587 message = `Invalid input: must end with "${issue.validation.endsWith}"`;
588 } else {
589 util.assertNever(issue.validation);
590 }
591 } else if (issue.validation !== "regex") {
592 message = `Invalid ${issue.validation}`;
593 } else {
594 message = "Invalid";
595 }
596 break;
597 case ZodIssueCode.too_small:
598 if (issue.type === "array")
599 message = `Array must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `more than`} ${issue.minimum} element(s)`;
600 else if (issue.type === "string")
601 message = `String must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `over`} ${issue.minimum} character(s)`;
602 else if (issue.type === "number")
603 message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;
604 else if (issue.type === "bigint")
605 message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;
606 else if (issue.type === "date")
607 message = `Date must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${new Date(Number(issue.minimum))}`;
608 else
609 message = "Invalid input";
610 break;
611 case ZodIssueCode.too_big:
612 if (issue.type === "array")
613 message = `Array must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `less than`} ${issue.maximum} element(s)`;
614 else if (issue.type === "string")
615 message = `String must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `under`} ${issue.maximum} character(s)`;
616 else if (issue.type === "number")
617 message = `Number must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`;
618 else if (issue.type === "bigint")
619 message = `BigInt must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`;
620 else if (issue.type === "date")
621 message = `Date must be ${issue.exact ? `exactly` : issue.inclusive ? `smaller than or equal to` : `smaller than`} ${new Date(Number(issue.maximum))}`;
622 else
623 message = "Invalid input";
624 break;
625 case ZodIssueCode.custom:
626 message = `Invalid input`;
627 break;
628 case ZodIssueCode.invalid_intersection_types:
629 message = `Intersection results could not be merged`;
630 break;
631 case ZodIssueCode.not_multiple_of:
632 message = `Number must be a multiple of ${issue.multipleOf}`;
633 break;
634 case ZodIssueCode.not_finite:
635 message = "Number must be finite";
636 break;
637 default:
638 message = _ctx.defaultError;
639 util.assertNever(issue);
640 }
641 return { message };
642};
643var en_default = errorMap;
644
645// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js
646var overrideErrorMap = en_default;
647function setErrorMap(map) {
648 overrideErrorMap = map;
649}
650function getErrorMap() {
651 return overrideErrorMap;
652}
653
654// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
655var makeIssue = (params) => {
656 const { data, path, errorMaps, issueData } = params;
657 const fullPath = [...path, ...issueData.path || []];
658 const fullIssue = {
659 ...issueData,
660 path: fullPath
661 };
662 if (issueData.message !== void 0) {
663 return {
664 ...issueData,
665 path: fullPath,
666 message: issueData.message
667 };
668 }
669 let errorMessage = "";
670 const maps = errorMaps.filter((m) => !!m).slice().reverse();
671 for (const map of maps) {
672 errorMessage = map(fullIssue, { data, defaultError: errorMessage }).message;
673 }
674 return {
675 ...issueData,
676 path: fullPath,
677 message: errorMessage
678 };
679};
680var EMPTY_PATH = [];
681function addIssueToContext(ctx, issueData) {
682 const overrideMap = getErrorMap();
683 const issue = makeIssue({
684 issueData,
685 data: ctx.data,
686 path: ctx.path,
687 errorMaps: [
688 ctx.common.contextualErrorMap,
689 // contextual error map is first priority
690 ctx.schemaErrorMap,
691 // then schema-bound map if available
692 overrideMap,
693 // then global override map
694 overrideMap === en_default ? void 0 : en_default
695 // then global default map
696 ].filter((x) => !!x)
697 });
698 ctx.common.issues.push(issue);
699}
700var ParseStatus = class _ParseStatus {
701 constructor() {
702 this.value = "valid";
703 }
704 dirty() {
705 if (this.value === "valid")
706 this.value = "dirty";
707 }
708 abort() {
709 if (this.value !== "aborted")
710 this.value = "aborted";
711 }
712 static mergeArray(status, results) {
713 const arrayValue = [];
714 for (const s of results) {
715 if (s.status === "aborted")
716 return INVALID;
717 if (s.status === "dirty")
718 status.dirty();
719 arrayValue.push(s.value);
720 }
721 return { status: status.value, value: arrayValue };
722 }
723 static async mergeObjectAsync(status, pairs) {
724 const syncPairs = [];
725 for (const pair of pairs) {
726 const key = await pair.key;
727 const value = await pair.value;
728 syncPairs.push({
729 key,
730 value
731 });
732 }
733 return _ParseStatus.mergeObjectSync(status, syncPairs);
734 }
735 static mergeObjectSync(status, pairs) {
736 const finalObject = {};
737 for (const pair of pairs) {
738 const { key, value } = pair;
739 if (key.status === "aborted")
740 return INVALID;
741 if (value.status === "aborted")
742 return INVALID;
743 if (key.status === "dirty")
744 status.dirty();
745 if (value.status === "dirty")
746 status.dirty();
747 if (key.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) {
748 finalObject[key.value] = value.value;
749 }
750 }
751 return { status: status.value, value: finalObject };
752 }
753};
754var INVALID = Object.freeze({
755 status: "aborted"
756});
757var DIRTY = (value) => ({ status: "dirty", value });
758var OK = (value) => ({ status: "valid", value });
759var isAborted = (x) => x.status === "aborted";
760var isDirty = (x) => x.status === "dirty";
761var isValid = (x) => x.status === "valid";
762var isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise;
763
764// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/errorUtil.js
765var errorUtil;
766(function(errorUtil2) {
767 errorUtil2.errToObj = (message) => typeof message === "string" ? { message } : message || {};
768 errorUtil2.toString = (message) => typeof message === "string" ? message : message?.message;
769})(errorUtil || (errorUtil = {}));
770
771// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
772var ParseInputLazyPath = class {
773 constructor(parent, value, path, key) {
774 this._cachedPath = [];
775 this.parent = parent;
776 this.data = value;
777 this._path = path;
778 this._key = key;
779 }
780 get path() {
781 if (!this._cachedPath.length) {
782 if (Array.isArray(this._key)) {
783 this._cachedPath.push(...this._path, ...this._key);
784 } else {
785 this._cachedPath.push(...this._path, this._key);
786 }
787 }
788 return this._cachedPath;
789 }
790};
791var handleResult = (ctx, result) => {
792 if (isValid(result)) {
793 return { success: true, data: result.value };
794 } else {
795 if (!ctx.common.issues.length) {
796 throw new Error("Validation failed but no issues detected.");
797 }
798 return {
799 success: false,
800 get error() {
801 if (this._error)
802 return this._error;
803 const error = new ZodError(ctx.common.issues);
804 this._error = error;
805 return this._error;
806 }
807 };
808 }
809};
810function processCreateParams(params) {
811 if (!params)
812 return {};
813 const { errorMap: errorMap2, invalid_type_error, required_error, description } = params;
814 if (errorMap2 && (invalid_type_error || required_error)) {
815 throw new Error(`Can't use "invalid_type_error" or "required_error" in conjunction with custom error map.`);
816 }
817 if (errorMap2)
818 return { errorMap: errorMap2, description };
819 const customMap = (iss, ctx) => {
820 const { message } = params;
821 if (iss.code === "invalid_enum_value") {
822 return { message: message ?? ctx.defaultError };
823 }
824 if (typeof ctx.data === "undefined") {
825 return { message: message ?? required_error ?? ctx.defaultError };
826 }
827 if (iss.code !== "invalid_type")
828 return { message: ctx.defaultError };
829 return { message: message ?? invalid_type_error ?? ctx.defaultError };
830 };
831 return { errorMap: customMap, description };
832}
833var ZodType = class {
834 get description() {
835 return this._def.description;
836 }
837 _getType(input) {
838 return getParsedType(input.data);
839 }
840 _getOrReturnCtx(input, ctx) {
841 return ctx || {
842 common: input.parent.common,
843 data: input.data,
844 parsedType: getParsedType(input.data),
845 schemaErrorMap: this._def.errorMap,
846 path: input.path,
847 parent: input.parent
848 };
849 }
850 _processInputParams(input) {
851 return {
852 status: new ParseStatus(),
853 ctx: {
854 common: input.parent.common,
855 data: input.data,
856 parsedType: getParsedType(input.data),
857 schemaErrorMap: this._def.errorMap,
858 path: input.path,
859 parent: input.parent
860 }
861 };
862 }
863 _parseSync(input) {
864 const result = this._parse(input);
865 if (isAsync(result)) {
866 throw new Error("Synchronous parse encountered promise.");
867 }
868 return result;
869 }
870 _parseAsync(input) {
871 const result = this._parse(input);
872 return Promise.resolve(result);
873 }
874 parse(data, params) {
875 const result = this.safeParse(data, params);
876 if (result.success)
877 return result.data;
878 throw result.error;
879 }
880 safeParse(data, params) {
881 const ctx = {
882 common: {
883 issues: [],
884 async: params?.async ?? false,
885 contextualErrorMap: params?.errorMap
886 },
887 path: params?.path || [],
888 schemaErrorMap: this._def.errorMap,
889 parent: null,
890 data,
891 parsedType: getParsedType(data)
892 };
893 const result = this._parseSync({ data, path: ctx.path, parent: ctx });
894 return handleResult(ctx, result);
895 }
896 "~validate"(data) {
897 const ctx = {
898 common: {
899 issues: [],
900 async: !!this["~standard"].async
901 },
902 path: [],
903 schemaErrorMap: this._def.errorMap,
904 parent: null,
905 data,
906 parsedType: getParsedType(data)
907 };
908 if (!this["~standard"].async) {
909 try {
910 const result = this._parseSync({ data, path: [], parent: ctx });
911 return isValid(result) ? {
912 value: result.value
913 } : {
914 issues: ctx.common.issues
915 };
916 } catch (err) {
917 if (err?.message?.toLowerCase()?.includes("encountered")) {
918 this["~standard"].async = true;
919 }
920 ctx.common = {
921 issues: [],
922 async: true
923 };
924 }
925 }
926 return this._parseAsync({ data, path: [], parent: ctx }).then((result) => isValid(result) ? {
927 value: result.value
928 } : {
929 issues: ctx.common.issues
930 });
931 }
932 async parseAsync(data, params) {
933 const result = await this.safeParseAsync(data, params);
934 if (result.success)
935 return result.data;
936 throw result.error;
937 }
938 async safeParseAsync(data, params) {
939 const ctx = {
940 common: {
941 issues: [],
942 contextualErrorMap: params?.errorMap,
943 async: true
944 },
945 path: params?.path || [],
946 schemaErrorMap: this._def.errorMap,
947 parent: null,
948 data,
949 parsedType: getParsedType(data)
950 };
951 const maybeAsyncResult = this._parse({ data, path: ctx.path, parent: ctx });
952 const result = await (isAsync(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult));
953 return handleResult(ctx, result);
954 }
955 refine(check, message) {
956 const getIssueProperties = (val) => {
957 if (typeof message === "string" || typeof message === "undefined") {
958 return { message };
959 } else if (typeof message === "function") {
960 return message(val);
961 } else {
962 return message;
963 }
964 };
965 return this._refinement((val, ctx) => {
966 const result = check(val);
967 const setError = () => ctx.addIssue({
968 code: ZodIssueCode.custom,
969 ...getIssueProperties(val)
970 });
971 if (typeof Promise !== "undefined" && result instanceof Promise) {
972 return result.then((data) => {
973 if (!data) {
974 setError();
975 return false;
976 } else {
977 return true;
978 }
979 });
980 }
981 if (!result) {
982 setError();
983 return false;
984 } else {
985 return true;
986 }
987 });
988 }
989 refinement(check, refinementData) {
990 return this._refinement((val, ctx) => {
991 if (!check(val)) {
992 ctx.addIssue(typeof refinementData === "function" ? refinementData(val, ctx) : refinementData);
993 return false;
994 } else {
995 return true;
996 }
997 });
998 }
999 _refinement(refinement) {
1000 return new ZodEffects({
1001 schema: this,
1002 typeName: ZodFirstPartyTypeKind.ZodEffects,
1003 effect: { type: "refinement", refinement }
1004 });
1005 }
1006 superRefine(refinement) {
1007 return this._refinement(refinement);
1008 }
1009 constructor(def) {
1010 this.spa = this.safeParseAsync;
1011 this._def = def;
1012 this.parse = this.parse.bind(this);
1013 this.safeParse = this.safeParse.bind(this);
1014 this.parseAsync = this.parseAsync.bind(this);
1015 this.safeParseAsync = this.safeParseAsync.bind(this);
1016 this.spa = this.spa.bind(this);
1017 this.refine = this.refine.bind(this);
1018 this.refinement = this.refinement.bind(this);
1019 this.superRefine = this.superRefine.bind(this);
1020 this.optional = this.optional.bind(this);
1021 this.nullable = this.nullable.bind(this);
1022 this.nullish = this.nullish.bind(this);
1023 this.array = this.array.bind(this);
1024 this.promise = this.promise.bind(this);
1025 this.or = this.or.bind(this);
1026 this.and = this.and.bind(this);
1027 this.transform = this.transform.bind(this);
1028 this.brand = this.brand.bind(this);
1029 this.default = this.default.bind(this);
1030 this.catch = this.catch.bind(this);
1031 this.describe = this.describe.bind(this);
1032 this.pipe = this.pipe.bind(this);
1033 this.readonly = this.readonly.bind(this);
1034 this.isNullable = this.isNullable.bind(this);
1035 this.isOptional = this.isOptional.bind(this);
1036 this["~standard"] = {
1037 version: 1,
1038 vendor: "zod",
1039 validate: (data) => this["~validate"](data)
1040 };
1041 }
1042 optional() {
1043 return ZodOptional.create(this, this._def);
1044 }
1045 nullable() {
1046 return ZodNullable.create(this, this._def);
1047 }
1048 nullish() {
1049 return this.nullable().optional();
1050 }
1051 array() {
1052 return ZodArray.create(this);
1053 }
1054 promise() {
1055 return ZodPromise.create(this, this._def);
1056 }
1057 or(option) {
1058 return ZodUnion.create([this, option], this._def);
1059 }
1060 and(incoming) {
1061 return ZodIntersection.create(this, incoming, this._def);
1062 }
1063 transform(transform) {
1064 return new ZodEffects({
1065 ...processCreateParams(this._def),
1066 schema: this,
1067 typeName: ZodFirstPartyTypeKind.ZodEffects,
1068 effect: { type: "transform", transform }
1069 });
1070 }
1071 default(def) {
1072 const defaultValueFunc = typeof def === "function" ? def : () => def;
1073 return new ZodDefault({
1074 ...processCreateParams(this._def),
1075 innerType: this,
1076 defaultValue: defaultValueFunc,
1077 typeName: ZodFirstPartyTypeKind.ZodDefault
1078 });
1079 }
1080 brand() {
1081 return new ZodBranded({
1082 typeName: ZodFirstPartyTypeKind.ZodBranded,
1083 type: this,
1084 ...processCreateParams(this._def)
1085 });
1086 }
1087 catch(def) {
1088 const catchValueFunc = typeof def === "function" ? def : () => def;
1089 return new ZodCatch({
1090 ...processCreateParams(this._def),
1091 innerType: this,
1092 catchValue: catchValueFunc,
1093 typeName: ZodFirstPartyTypeKind.ZodCatch
1094 });
1095 }
1096 describe(description) {
1097 const This = this.constructor;
1098 return new This({
1099 ...this._def,
1100 description
1101 });
1102 }
1103 pipe(target) {
1104 return ZodPipeline.create(this, target);
1105 }
1106 readonly() {
1107 return ZodReadonly.create(this);
1108 }
1109 isOptional() {
1110 return this.safeParse(void 0).success;
1111 }
1112 isNullable() {
1113 return this.safeParse(null).success;
1114 }
1115};
1116var cuidRegex = /^c[^\s-]{8,}$/i;
1117var cuid2Regex = /^[0-9a-z]+$/;
1118var ulidRegex = /^[0-9A-HJKMNP-TV-Z]{26}$/i;
1119var uuidRegex = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i;
1120var nanoidRegex = /^[a-z0-9_-]{21}$/i;
1121var jwtRegex = /^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/;
1122var durationRegex = /^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/;
1123var emailRegex = /^(?!\.)(?!.*\.\.)([A-Z0-9_'+\-\.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\-]*\.)+[A-Z]{2,}$/i;
1124var _emojiRegex = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`;
1125var emojiRegex;
1126var ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;
1127var ipv4CidrRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/(3[0-2]|[12]?[0-9])$/;
1128var ipv6Regex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
1129var ipv6CidrRegex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
1130var base64Regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
1131var base64urlRegex = /^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$/;
1132var dateRegexSource = `((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))`;
1133var dateRegex = new RegExp(`^${dateRegexSource}$`);
1134function timeRegexSource(args) {
1135 let secondsRegexSource = `[0-5]\\d`;
1136 if (args.precision) {
1137 secondsRegexSource = `${secondsRegexSource}\\.\\d{${args.precision}}`;
1138 } else if (args.precision == null) {
1139 secondsRegexSource = `${secondsRegexSource}(\\.\\d+)?`;
1140 }
1141 const secondsQuantifier = args.precision ? "+" : "?";
1142 return `([01]\\d|2[0-3]):[0-5]\\d(:${secondsRegexSource})${secondsQuantifier}`;
1143}
1144function timeRegex(args) {
1145 return new RegExp(`^${timeRegexSource(args)}$`);
1146}
1147function datetimeRegex(args) {
1148 let regex = `${dateRegexSource}T${timeRegexSource(args)}`;
1149 const opts = [];
1150 opts.push(args.local ? `Z?` : `Z`);
1151 if (args.offset)
1152 opts.push(`([+-]\\d{2}:?\\d{2})`);
1153 regex = `${regex}(${opts.join("|")})`;
1154 return new RegExp(`^${regex}$`);
1155}
1156function isValidIP(ip, version) {
1157 if ((version === "v4" || !version) && ipv4Regex.test(ip)) {
1158 return true;
1159 }
1160 if ((version === "v6" || !version) && ipv6Regex.test(ip)) {
1161 return true;
1162 }
1163 return false;
1164}
1165function isValidJWT(jwt, alg) {
1166 if (!jwtRegex.test(jwt))
1167 return false;
1168 try {
1169 const [header] = jwt.split(".");
1170 if (!header)
1171 return false;
1172 const base64 = header.replace(/-/g, "+").replace(/_/g, "/").padEnd(header.length + (4 - header.length % 4) % 4, "=");
1173 const decoded = JSON.parse(atob(base64));
1174 if (typeof decoded !== "object" || decoded === null)
1175 return false;
1176 if ("typ" in decoded && decoded?.typ !== "JWT")
1177 return false;
1178 if (!decoded.alg)
1179 return false;
1180 if (alg && decoded.alg !== alg)
1181 return false;
1182 return true;
1183 } catch {
1184 return false;
1185 }
1186}
1187function isValidCidr(ip, version) {
1188 if ((version === "v4" || !version) && ipv4CidrRegex.test(ip)) {
1189 return true;
1190 }
1191 if ((version === "v6" || !version) && ipv6CidrRegex.test(ip)) {
1192 return true;
1193 }
1194 return false;
1195}
1196var ZodString = class _ZodString extends ZodType {
1197 _parse(input) {
1198 if (this._def.coerce) {
1199 input.data = String(input.data);
1200 }types/index.d.ts 24 lines1// The cc-idle mod's $.state contract: session-scoped UI state the pane draws from.
2// The economy itself lives in $.store (shared by every session), not here.
3
4/** Which screen the pane shows. 'help' is also the welcome a new player sees first; 'chat' talks to the board. */
5export type IdleView = 'main' | 'tree' | 'confirm-ship' | 'help' | 'chat';
6
7/** Why Claude Code is waiting on the person, or '' while it isn't. */
8export type IdleNeedsYou = '' | 'done' | 'permission' | 'question';
9
10declare module 'claude-code' {
11 interface PluginState {
12 'cc-idle': {
13 /** Bumped whenever the economy changes, so the pane redraws. */
14 rev: number;
15 view: IdleView;
16 /** Index of the focused region, in founding order. */
17 region: number;
18 needsYou: IdleNeedsYou;
19 /** Bumped whenever the board chat changes, so the pane redraws. */
20 board: number;
21 };
22 }
23}
24