@astrohacker/factory 0.0.0-stage → 0.1.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.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +23 -2
  3. package/dist/ahfact.js +1947 -0
  4. package/package.json +28 -4
package/dist/ahfact.js ADDED
@@ -0,0 +1,1947 @@
1
+ #!/usr/bin/env node
2
+
3
+ // cli/ahfact.ts
4
+ import { execFileSync } from "node:child_process";
5
+ import { chmod, mkdir, readdir, readFile, rm, writeFile } from "node:fs/promises";
6
+ import { homedir, hostname } from "node:os";
7
+ import { join } from "node:path";
8
+ import { parseArgs } from "node:util";
9
+
10
+ // node_modules/@orpc/shared/dist/index.mjs
11
+ function resolveMaybeOptionalOptions(rest) {
12
+ return rest[0] ?? {};
13
+ }
14
+ function toArray(value) {
15
+ return Array.isArray(value) ? value : value === undefined || value === null ? [] : [value];
16
+ }
17
+ var DEFAULT_MAX_BIGINT_DIGITS = 4300;
18
+ var BIGINT_PATTERN = /^-?(?:0|[1-9]\d*)$/;
19
+ function parseBigIntString(value, maxDigits) {
20
+ const digits = value.startsWith("-") ? value.length - 1 : value.length;
21
+ if (digits > maxDigits || !BIGINT_PATTERN.test(value)) {
22
+ return;
23
+ }
24
+ return BigInt(value);
25
+ }
26
+ var ORPC_NAME = "orpc";
27
+ var ORPC_SHARED_PACKAGE_NAME = "@orpc/shared";
28
+ var ORPC_SHARED_PACKAGE_VERSION = "1.16.2";
29
+
30
+ class AbortError extends Error {
31
+ constructor(...rest) {
32
+ super(...rest);
33
+ this.name = "AbortError";
34
+ }
35
+ }
36
+ function once(fn) {
37
+ let cached;
38
+ return () => {
39
+ if (cached) {
40
+ return cached.result;
41
+ }
42
+ const result = fn();
43
+ cached = { result };
44
+ return result;
45
+ };
46
+ }
47
+ function sequential(fn) {
48
+ let lastOperationPromise = Promise.resolve();
49
+ return (...args) => {
50
+ return lastOperationPromise = lastOperationPromise.catch(() => {}).then(() => {
51
+ return fn(...args);
52
+ });
53
+ };
54
+ }
55
+ var SPAN_ERROR_STATUS = 2;
56
+ var GLOBAL_OTEL_CONFIG_KEY = `__${ORPC_SHARED_PACKAGE_NAME}@${ORPC_SHARED_PACKAGE_VERSION}/otel/config__`;
57
+ function getGlobalOtelConfig() {
58
+ return globalThis[GLOBAL_OTEL_CONFIG_KEY];
59
+ }
60
+ function startSpan(name, options = {}, context) {
61
+ const tracer = getGlobalOtelConfig()?.tracer;
62
+ return tracer?.startSpan(name, options, context);
63
+ }
64
+ function setSpanError(span, error, options = {}) {
65
+ if (!span) {
66
+ return;
67
+ }
68
+ const exception = toOtelException(error);
69
+ span.recordException(exception);
70
+ if (!options.signal?.aborted || options.signal.reason !== error) {
71
+ span.setStatus({
72
+ code: SPAN_ERROR_STATUS,
73
+ message: exception.message
74
+ });
75
+ }
76
+ }
77
+ function toOtelException(error) {
78
+ if (error instanceof Error) {
79
+ const exception = {
80
+ message: error.message,
81
+ name: error.name,
82
+ stack: error.stack
83
+ };
84
+ if ("code" in error && (typeof error.code === "string" || typeof error.code === "number")) {
85
+ exception.code = error.code;
86
+ }
87
+ return exception;
88
+ }
89
+ return { message: String(error) };
90
+ }
91
+ async function runWithSpan({ name, context, ...options }, fn) {
92
+ const tracer = getGlobalOtelConfig()?.tracer;
93
+ if (!tracer) {
94
+ return fn();
95
+ }
96
+ const callback = async (span) => {
97
+ try {
98
+ return await fn(span);
99
+ } catch (e) {
100
+ setSpanError(span, e, options);
101
+ throw e;
102
+ } finally {
103
+ span.end();
104
+ }
105
+ };
106
+ if (context) {
107
+ return tracer.startActiveSpan(name, options, context, callback);
108
+ } else {
109
+ return tracer.startActiveSpan(name, options, callback);
110
+ }
111
+ }
112
+ async function runInSpanContext(span, fn) {
113
+ const otelConfig = getGlobalOtelConfig();
114
+ if (!span || !otelConfig) {
115
+ return fn();
116
+ }
117
+ const ctx = otelConfig.trace.setSpan(otelConfig.context.active(), span);
118
+ return otelConfig.context.with(ctx, fn);
119
+ }
120
+ function isAsyncIteratorObject(maybe) {
121
+ if (!maybe || typeof maybe !== "object") {
122
+ return false;
123
+ }
124
+ return "next" in maybe && typeof maybe.next === "function" && Symbol.asyncIterator in maybe && typeof maybe[Symbol.asyncIterator] === "function";
125
+ }
126
+ var fallbackAsyncDisposeSymbol = Symbol.for("asyncDispose");
127
+ var asyncDisposeSymbol = Symbol.asyncDispose ?? fallbackAsyncDisposeSymbol;
128
+
129
+ class AsyncIteratorClass {
130
+ #isDone = false;
131
+ #isExecuteComplete = false;
132
+ #cleanup;
133
+ #next;
134
+ constructor(next, cleanup) {
135
+ this.#cleanup = cleanup;
136
+ this.#next = sequential(async () => {
137
+ if (this.#isDone) {
138
+ return { done: true, value: undefined };
139
+ }
140
+ try {
141
+ const result = await next();
142
+ if (result.done) {
143
+ this.#isDone = true;
144
+ }
145
+ return result;
146
+ } catch (err) {
147
+ this.#isDone = true;
148
+ throw err;
149
+ } finally {
150
+ if (this.#isDone && !this.#isExecuteComplete) {
151
+ this.#isExecuteComplete = true;
152
+ await this.#cleanup("next");
153
+ }
154
+ }
155
+ });
156
+ }
157
+ next() {
158
+ return this.#next();
159
+ }
160
+ async return(value) {
161
+ this.#isDone = true;
162
+ if (!this.#isExecuteComplete) {
163
+ this.#isExecuteComplete = true;
164
+ await this.#cleanup("return");
165
+ }
166
+ return { done: true, value };
167
+ }
168
+ async throw(err) {
169
+ this.#isDone = true;
170
+ if (!this.#isExecuteComplete) {
171
+ this.#isExecuteComplete = true;
172
+ await this.#cleanup("throw");
173
+ }
174
+ throw err;
175
+ }
176
+ async[asyncDisposeSymbol]() {
177
+ this.#isDone = true;
178
+ if (!this.#isExecuteComplete) {
179
+ this.#isExecuteComplete = true;
180
+ await this.#cleanup("dispose");
181
+ }
182
+ }
183
+ [Symbol.asyncIterator]() {
184
+ return this;
185
+ }
186
+ }
187
+ function asyncIteratorWithSpan({ name, ...options }, iterator) {
188
+ let span;
189
+ return new AsyncIteratorClass(async () => {
190
+ span ??= startSpan(name);
191
+ try {
192
+ const result = await runInSpanContext(span, () => iterator.next());
193
+ span?.addEvent(result.done ? "completed" : "yielded");
194
+ return result;
195
+ } catch (err) {
196
+ setSpanError(span, err, options);
197
+ throw err;
198
+ }
199
+ }, async (reason) => {
200
+ try {
201
+ if (reason !== "next") {
202
+ await runInSpanContext(span, () => iterator.return?.());
203
+ }
204
+ } catch (err) {
205
+ setSpanError(span, err, options);
206
+ throw err;
207
+ } finally {
208
+ span?.end();
209
+ }
210
+ });
211
+ }
212
+ function intercept(interceptors, options, main) {
213
+ const next = (options2, index) => {
214
+ const interceptor = interceptors[index];
215
+ if (!interceptor) {
216
+ return main(options2);
217
+ }
218
+ return interceptor({
219
+ ...options2,
220
+ next: (newOptions = options2) => next(newOptions, index + 1)
221
+ });
222
+ };
223
+ return next(options, 0);
224
+ }
225
+ function parseEmptyableJSON(text) {
226
+ if (!text) {
227
+ return;
228
+ }
229
+ return JSON.parse(text);
230
+ }
231
+ function stringifyJSON(value) {
232
+ return JSON.stringify(value);
233
+ }
234
+ function getConstructor(value) {
235
+ if (!isTypescriptObject(value)) {
236
+ return null;
237
+ }
238
+ return Object.getPrototypeOf(value)?.constructor;
239
+ }
240
+ function isObject(value) {
241
+ if (!value || typeof value !== "object") {
242
+ return false;
243
+ }
244
+ const proto = Object.getPrototypeOf(value);
245
+ return proto === Object.prototype || !proto || !proto.constructor;
246
+ }
247
+ function isTypescriptObject(value) {
248
+ return !!value && (typeof value === "object" || typeof value === "function");
249
+ }
250
+ function setOwn(object, key, value) {
251
+ if (key === "__proto__") {
252
+ Object.defineProperty(object, key, {
253
+ value,
254
+ writable: true,
255
+ enumerable: true,
256
+ configurable: true
257
+ });
258
+ } else {
259
+ object[key] = value;
260
+ }
261
+ }
262
+ function copyOnWrite(parent, key, original) {
263
+ const value = parent[key];
264
+ if (value !== original) {
265
+ return value;
266
+ }
267
+ let copy;
268
+ if (Array.isArray(value)) {
269
+ copy = value.slice();
270
+ } else if (isObject(value)) {
271
+ copy = { ...value };
272
+ } else {
273
+ return value;
274
+ }
275
+ setOwn(parent, key, copy);
276
+ return copy;
277
+ }
278
+ function value(value2, ...args) {
279
+ if (typeof value2 === "function") {
280
+ return value2(...args);
281
+ }
282
+ return value2;
283
+ }
284
+ function preventNativeAwait(target) {
285
+ return new Proxy(target, {
286
+ get(target2, prop, receiver) {
287
+ const value2 = Reflect.get(target2, prop, receiver);
288
+ if (prop !== "then" || typeof value2 !== "function") {
289
+ return value2;
290
+ }
291
+ return new Proxy(value2, {
292
+ apply(targetFn, thisArg, args) {
293
+ if (args.length !== 2 || args.some((arg) => !isNativeFunction(arg))) {
294
+ return Reflect.apply(targetFn, thisArg, args);
295
+ }
296
+ let shouldOmit = true;
297
+ args[0].call(thisArg, preventNativeAwait(new Proxy(target2, {
298
+ get: (target3, prop2, receiver2) => {
299
+ if (shouldOmit && prop2 === "then") {
300
+ shouldOmit = false;
301
+ return;
302
+ }
303
+ return Reflect.get(target3, prop2, receiver2);
304
+ }
305
+ })));
306
+ }
307
+ });
308
+ }
309
+ });
310
+ }
311
+ var NATIVE_FUNCTION_REGEX = /^\s*function\s*\(\)\s*\{\s*\[native code\]\s*\}\s*$/;
312
+ function isNativeFunction(fn) {
313
+ return typeof fn === "function" && NATIVE_FUNCTION_REGEX.test(fn.toString());
314
+ }
315
+ var REGEXP_FLAGS = /^[dgimsuvy]*$/;
316
+ function isValidRegExpFlags(flags) {
317
+ return REGEXP_FLAGS.test(flags) && new Set(flags).size === flags.length && !(flags.includes("u") && flags.includes("v"));
318
+ }
319
+ function createLazyRegExp(pattern, flags) {
320
+ let compiled;
321
+ let lastIndex = 0;
322
+ const compile = () => {
323
+ if (compiled === undefined) {
324
+ compiled = new RegExp(pattern, flags);
325
+ compiled.lastIndex = lastIndex;
326
+ }
327
+ return compiled;
328
+ };
329
+ return new Proxy(Object.create(RegExp.prototype), {
330
+ get(_, prop) {
331
+ if (prop === Symbol.toStringTag) {
332
+ return "RegExp";
333
+ }
334
+ if (compiled === undefined) {
335
+ if (prop === "lastIndex") {
336
+ return lastIndex;
337
+ }
338
+ if (!(prop in RegExp.prototype)) {
339
+ return;
340
+ }
341
+ }
342
+ const target = compile();
343
+ const value = Reflect.get(target, prop, target);
344
+ return typeof value === "function" && prop !== "constructor" ? value.bind(target) : value;
345
+ },
346
+ set(_, prop, value) {
347
+ if (compiled === undefined && prop === "lastIndex") {
348
+ lastIndex = value;
349
+ return true;
350
+ }
351
+ const target = compile();
352
+ return Reflect.set(target, prop, value, target);
353
+ },
354
+ has(_, prop) {
355
+ if (compiled === undefined) {
356
+ return prop === "lastIndex" || prop in RegExp.prototype;
357
+ }
358
+ return Reflect.has(compiled, prop);
359
+ }
360
+ });
361
+ }
362
+ function tryDecodeURIComponent(value) {
363
+ try {
364
+ return decodeURIComponent(value);
365
+ } catch {
366
+ return value;
367
+ }
368
+ }
369
+
370
+ // node_modules/@orpc/client/dist/shared/client.DeR0HTYb.mjs
371
+ var ORPC_CLIENT_PACKAGE_NAME = "@orpc/client";
372
+ var ORPC_CLIENT_PACKAGE_VERSION = "1.16.2";
373
+ var RECURSIVE_CLIENT_UNWRAP_KEYS = /* @__PURE__ */ new Set([
374
+ "bind",
375
+ "valueOf",
376
+ "toString",
377
+ "toJSON"
378
+ ]);
379
+ var COMMON_ORPC_ERROR_DEFS = {
380
+ BAD_REQUEST: {
381
+ status: 400,
382
+ message: "Bad Request"
383
+ },
384
+ UNAUTHORIZED: {
385
+ status: 401,
386
+ message: "Unauthorized"
387
+ },
388
+ FORBIDDEN: {
389
+ status: 403,
390
+ message: "Forbidden"
391
+ },
392
+ NOT_FOUND: {
393
+ status: 404,
394
+ message: "Not Found"
395
+ },
396
+ METHOD_NOT_SUPPORTED: {
397
+ status: 405,
398
+ message: "Method Not Supported"
399
+ },
400
+ NOT_ACCEPTABLE: {
401
+ status: 406,
402
+ message: "Not Acceptable"
403
+ },
404
+ TIMEOUT: {
405
+ status: 408,
406
+ message: "Request Timeout"
407
+ },
408
+ CONFLICT: {
409
+ status: 409,
410
+ message: "Conflict"
411
+ },
412
+ PRECONDITION_FAILED: {
413
+ status: 412,
414
+ message: "Precondition Failed"
415
+ },
416
+ PAYLOAD_TOO_LARGE: {
417
+ status: 413,
418
+ message: "Payload Too Large"
419
+ },
420
+ UNSUPPORTED_MEDIA_TYPE: {
421
+ status: 415,
422
+ message: "Unsupported Media Type"
423
+ },
424
+ UNPROCESSABLE_CONTENT: {
425
+ status: 422,
426
+ message: "Unprocessable Content"
427
+ },
428
+ TOO_MANY_REQUESTS: {
429
+ status: 429,
430
+ message: "Too Many Requests"
431
+ },
432
+ CLIENT_CLOSED_REQUEST: {
433
+ status: 499,
434
+ message: "Client Closed Request"
435
+ },
436
+ INTERNAL_SERVER_ERROR: {
437
+ status: 500,
438
+ message: "Internal Server Error"
439
+ },
440
+ NOT_IMPLEMENTED: {
441
+ status: 501,
442
+ message: "Not Implemented"
443
+ },
444
+ BAD_GATEWAY: {
445
+ status: 502,
446
+ message: "Bad Gateway"
447
+ },
448
+ SERVICE_UNAVAILABLE: {
449
+ status: 503,
450
+ message: "Service Unavailable"
451
+ },
452
+ GATEWAY_TIMEOUT: {
453
+ status: 504,
454
+ message: "Gateway Timeout"
455
+ }
456
+ };
457
+ function fallbackORPCErrorStatus(code, status) {
458
+ return status ?? COMMON_ORPC_ERROR_DEFS[code]?.status ?? 500;
459
+ }
460
+ function fallbackORPCErrorMessage(code, message) {
461
+ return message || COMMON_ORPC_ERROR_DEFS[code]?.message || code;
462
+ }
463
+ var globalORPCErrorConstructors;
464
+
465
+ class ORPCError extends Error {
466
+ defined;
467
+ code;
468
+ status;
469
+ data;
470
+ static {
471
+ const GLOBAL_ORPC_ERROR_CONSTRUCTORS_SYMBOL = Symbol.for(`__${ORPC_CLIENT_PACKAGE_NAME}@${ORPC_CLIENT_PACKAGE_VERSION}/error/ORPC_ERROR_CONSTRUCTORS__`);
472
+ globalThis[GLOBAL_ORPC_ERROR_CONSTRUCTORS_SYMBOL] ??= /* @__PURE__ */ new WeakSet;
473
+ globalORPCErrorConstructors = globalThis[GLOBAL_ORPC_ERROR_CONSTRUCTORS_SYMBOL];
474
+ globalORPCErrorConstructors.add(ORPCError);
475
+ }
476
+ constructor(code, ...rest) {
477
+ const options = resolveMaybeOptionalOptions(rest);
478
+ if (options.status !== undefined && !isORPCErrorStatus(options.status)) {
479
+ throw new Error("[ORPCError] Invalid error status code.");
480
+ }
481
+ const message = fallbackORPCErrorMessage(code, options.message);
482
+ super(message, options);
483
+ this.code = code;
484
+ this.status = fallbackORPCErrorStatus(code, options.status);
485
+ this.defined = options.defined ?? false;
486
+ this.data = options.data;
487
+ }
488
+ toJSON() {
489
+ return {
490
+ defined: this.defined,
491
+ code: this.code,
492
+ status: this.status,
493
+ message: this.message,
494
+ data: this.data
495
+ };
496
+ }
497
+ static [Symbol.hasInstance](instance) {
498
+ if (globalORPCErrorConstructors.has(this)) {
499
+ const constructor = getConstructor(instance);
500
+ if (constructor && globalORPCErrorConstructors.has(constructor)) {
501
+ return true;
502
+ }
503
+ }
504
+ return super[Symbol.hasInstance](instance);
505
+ }
506
+ }
507
+ function toORPCError(error) {
508
+ return error instanceof ORPCError ? error : new ORPCError("INTERNAL_SERVER_ERROR", {
509
+ message: "Internal server error",
510
+ cause: error
511
+ });
512
+ }
513
+ function isORPCErrorStatus(status) {
514
+ return status < 200 || status >= 400;
515
+ }
516
+ function isORPCErrorJson(json) {
517
+ if (!isObject(json)) {
518
+ return false;
519
+ }
520
+ const validKeys = ["defined", "code", "status", "message", "data"];
521
+ if (Object.keys(json).some((k) => !validKeys.includes(k))) {
522
+ return false;
523
+ }
524
+ return "defined" in json && typeof json.defined === "boolean" && "code" in json && typeof json.code === "string" && "status" in json && typeof json.status === "number" && isORPCErrorStatus(json.status) && "message" in json && typeof json.message === "string";
525
+ }
526
+ function createORPCErrorFromJson(json, options = {}) {
527
+ return new ORPCError(json.code, {
528
+ ...options,
529
+ ...json
530
+ });
531
+ }
532
+ // node_modules/@orpc/standard-server/dist/index.mjs
533
+ class EventEncoderError extends TypeError {
534
+ }
535
+
536
+ class EventDecoderError extends TypeError {
537
+ }
538
+
539
+ class ErrorEvent extends Error {
540
+ data;
541
+ constructor(options) {
542
+ super(options?.message ?? "An error event was received", options);
543
+ this.data = options?.data;
544
+ }
545
+ }
546
+ var LINE_ENDING_REGEX$1 = /\r\n|\r(?!\n)|\n/;
547
+ var MESSAGE_DELIMITER_REGEX = /(?:\r\n|\r(?!\n)|\n){2}/;
548
+ var MESSAGE_DELIMITER_GLOBAL_REGEX = /(?:\r\n|\r(?!\n)|\n){2}/g;
549
+ var CR = 13;
550
+ var LF = 10;
551
+ var SPACE = 32;
552
+ function decodeEventMessage(encoded) {
553
+ const message = {
554
+ data: undefined,
555
+ event: undefined,
556
+ id: undefined,
557
+ retry: undefined,
558
+ comments: []
559
+ };
560
+ for (const line of encoded.split(LINE_ENDING_REGEX$1)) {
561
+ if (line === "") {
562
+ continue;
563
+ }
564
+ const index = line.indexOf(":");
565
+ const value = index === -1 ? "" : line.slice(line.charCodeAt(index + 1) === SPACE ? index + 2 : index + 1);
566
+ if (index === 0) {
567
+ message.comments.push(value);
568
+ continue;
569
+ }
570
+ switch (index === -1 ? line : line.slice(0, index)) {
571
+ case "data":
572
+ message.data = message.data === undefined ? value : `${message.data}
573
+ ${value}`;
574
+ break;
575
+ case "event":
576
+ message.event = value;
577
+ break;
578
+ case "id":
579
+ message.id = value;
580
+ break;
581
+ case "retry": {
582
+ const maybeInteger = Number.parseInt(value, 10);
583
+ if (maybeInteger >= 0 && maybeInteger.toString() === value) {
584
+ message.retry = maybeInteger;
585
+ }
586
+ break;
587
+ }
588
+ }
589
+ }
590
+ return message;
591
+ }
592
+
593
+ class EventDecoder {
594
+ constructor(options = {}) {
595
+ this.options = options;
596
+ }
597
+ pending = [];
598
+ tail = "";
599
+ discardLeadingLF = false;
600
+ feed(chunk) {
601
+ if (chunk === "") {
602
+ return;
603
+ }
604
+ if (this.discardLeadingLF) {
605
+ this.discardLeadingLF = false;
606
+ if (chunk.charCodeAt(0) === LF) {
607
+ chunk = chunk.slice(1);
608
+ if (chunk === "") {
609
+ return;
610
+ }
611
+ }
612
+ }
613
+ const scan = this.tail + chunk;
614
+ if (!MESSAGE_DELIMITER_REGEX.test(scan)) {
615
+ this.pending.push(chunk);
616
+ this.tail = scan.slice(-3);
617
+ return;
618
+ }
619
+ this.pending.push(chunk);
620
+ const buffered = this.pending.length === 1 ? chunk : this.pending.join("");
621
+ const offset = buffered.length - scan.length;
622
+ const parts = [];
623
+ let start = 0;
624
+ for (const match of scan.matchAll(MESSAGE_DELIMITER_GLOBAL_REGEX)) {
625
+ parts.push(buffered.slice(start, offset + match.index));
626
+ start = offset + match.index + match[0].length;
627
+ }
628
+ const incomplete = buffered.slice(start);
629
+ this.pending.length = 0;
630
+ this.tail = incomplete.slice(-3);
631
+ if (incomplete === "") {
632
+ this.discardLeadingLF = chunk.charCodeAt(chunk.length - 1) === CR;
633
+ } else {
634
+ this.pending.push(incomplete);
635
+ }
636
+ for (const encoded of parts) {
637
+ const message = decodeEventMessage(encoded);
638
+ if (this.options.onEvent) {
639
+ this.options.onEvent(message);
640
+ }
641
+ }
642
+ }
643
+ end() {
644
+ if (this.pending.length !== 0) {
645
+ throw new EventDecoderError("Event Iterator ended before complete");
646
+ }
647
+ }
648
+ }
649
+
650
+ class EventDecoderStream extends TransformStream {
651
+ constructor() {
652
+ let decoder;
653
+ super({
654
+ start(controller) {
655
+ decoder = new EventDecoder({
656
+ onEvent: (event) => {
657
+ controller.enqueue(event);
658
+ }
659
+ });
660
+ },
661
+ transform(chunk) {
662
+ decoder.feed(chunk);
663
+ },
664
+ flush() {
665
+ decoder.end();
666
+ }
667
+ });
668
+ }
669
+ }
670
+ var LINE_ENDING_REGEX = /\r\n|[\n\r]/;
671
+ var LINE_ENDING_GLOBAL_REGEX = /\r\n|[\n\r]/g;
672
+ function containsLineBreak(value) {
673
+ return LINE_ENDING_REGEX.test(value);
674
+ }
675
+ function assertEventId(id) {
676
+ if (containsLineBreak(id)) {
677
+ throw new EventEncoderError("Event's id must not contain a carriage return or newline character");
678
+ }
679
+ }
680
+ function assertEventName(event) {
681
+ if (containsLineBreak(event)) {
682
+ throw new EventEncoderError("Event's event must not contain a carriage return or newline character");
683
+ }
684
+ }
685
+ function assertEventRetry(retry) {
686
+ if (!Number.isInteger(retry) || retry < 0) {
687
+ throw new EventEncoderError("Event's retry must be a integer and >= 0");
688
+ }
689
+ }
690
+ function assertEventComment(comment) {
691
+ if (containsLineBreak(comment)) {
692
+ throw new EventEncoderError("Event's comment must not contain a carriage return or newline character");
693
+ }
694
+ }
695
+ function encodeEventData(data) {
696
+ if (data === undefined) {
697
+ return "";
698
+ }
699
+ return `data: ${data.replace(LINE_ENDING_GLOBAL_REGEX, `
700
+ data: `)}
701
+ `;
702
+ }
703
+ function encodeEventComments(comments) {
704
+ let output = "";
705
+ for (const comment of comments ?? []) {
706
+ assertEventComment(comment);
707
+ output += `: ${comment}
708
+ `;
709
+ }
710
+ return output;
711
+ }
712
+ function encodeEventMessage(message) {
713
+ let output = "";
714
+ output += encodeEventComments(message.comments);
715
+ if (message.event !== undefined) {
716
+ assertEventName(message.event);
717
+ output += `event: ${message.event}
718
+ `;
719
+ }
720
+ if (message.retry !== undefined) {
721
+ assertEventRetry(message.retry);
722
+ output += `retry: ${message.retry}
723
+ `;
724
+ }
725
+ if (message.id !== undefined) {
726
+ assertEventId(message.id);
727
+ output += `id: ${message.id}
728
+ `;
729
+ }
730
+ output += encodeEventData(message.data);
731
+ output += `
732
+ `;
733
+ return output;
734
+ }
735
+ var EVENT_SOURCE_META_SYMBOL = Symbol("ORPC_EVENT_SOURCE_META");
736
+ function withEventMeta(container, meta) {
737
+ if (meta.id === undefined && meta.retry === undefined && !meta.comments?.length) {
738
+ return container;
739
+ }
740
+ if (meta.id !== undefined) {
741
+ assertEventId(meta.id);
742
+ }
743
+ if (meta.retry !== undefined) {
744
+ assertEventRetry(meta.retry);
745
+ }
746
+ if (meta.comments !== undefined) {
747
+ for (const comment of meta.comments) {
748
+ assertEventComment(comment);
749
+ }
750
+ }
751
+ return new Proxy(container, {
752
+ get(target, prop, receiver) {
753
+ if (prop === EVENT_SOURCE_META_SYMBOL) {
754
+ return meta;
755
+ }
756
+ return Reflect.get(target, prop, receiver);
757
+ }
758
+ });
759
+ }
760
+ function getEventMeta(container) {
761
+ return isTypescriptObject(container) ? Reflect.get(container, EVENT_SOURCE_META_SYMBOL) : undefined;
762
+ }
763
+ function generateContentDisposition(filename, disposition = "inline") {
764
+ const encodedFileName = filename.replace(/[^\x20-\x7E]/g, "_").replace(/"/g, "\\\"");
765
+ const encodedFilenameStar = encodeURIComponent(filename).replace(/['()*]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`).replace(/%(7C|60|5E)/g, (str, hex) => String.fromCharCode(Number.parseInt(hex, 16)));
766
+ return `${disposition}; filename="${encodedFileName}"; filename*=utf-8''${encodedFilenameStar}`;
767
+ }
768
+ function getFilenameFromContentDisposition(contentDisposition) {
769
+ const encodedFilenameStarMatch = contentDisposition.match(/filename\*=(UTF-8'')?([^;]*)/i);
770
+ if (encodedFilenameStarMatch && typeof encodedFilenameStarMatch[2] === "string") {
771
+ return tryDecodeURIComponent(encodedFilenameStarMatch[2]);
772
+ }
773
+ const encodedFilenameMatch = contentDisposition.match(/filename="((?:\\"|[^"])*)"/i);
774
+ if (encodedFilenameMatch && typeof encodedFilenameMatch[1] === "string") {
775
+ return encodedFilenameMatch[1].replace(/\\"/g, '"');
776
+ }
777
+ }
778
+ function mergeStandardHeaders(a, b) {
779
+ const merged = { ...a };
780
+ for (const key in b) {
781
+ if (Array.isArray(b[key])) {
782
+ merged[key] = [...toArray(merged[key]), ...b[key]];
783
+ } else if (b[key] !== undefined) {
784
+ if (Array.isArray(merged[key])) {
785
+ merged[key] = [...merged[key], b[key]];
786
+ } else if (merged[key] !== undefined) {
787
+ merged[key] = [merged[key], b[key]];
788
+ } else {
789
+ merged[key] = b[key];
790
+ }
791
+ }
792
+ }
793
+ return merged;
794
+ }
795
+
796
+ // node_modules/@orpc/client/dist/shared/client.BLtwTQUg.mjs
797
+ function mapEventIterator(iterator, maps) {
798
+ const mapError = async (error) => {
799
+ let mappedError = await maps.error(error);
800
+ if (mappedError !== error) {
801
+ const meta = getEventMeta(error);
802
+ if (meta && isTypescriptObject(mappedError)) {
803
+ mappedError = withEventMeta(mappedError, meta);
804
+ }
805
+ }
806
+ return mappedError;
807
+ };
808
+ return new AsyncIteratorClass(async () => {
809
+ const { done, value } = await (async () => {
810
+ try {
811
+ return await iterator.next();
812
+ } catch (error) {
813
+ throw await mapError(error);
814
+ }
815
+ })();
816
+ let mappedValue = await maps.value(value, done);
817
+ if (mappedValue !== value) {
818
+ const meta = getEventMeta(value);
819
+ if (meta && isTypescriptObject(mappedValue)) {
820
+ mappedValue = withEventMeta(mappedValue, meta);
821
+ }
822
+ }
823
+ return { done, value: mappedValue };
824
+ }, async () => {
825
+ try {
826
+ await iterator.return?.();
827
+ } catch (error) {
828
+ throw await mapError(error);
829
+ }
830
+ });
831
+ }
832
+
833
+ // node_modules/@orpc/client/dist/index.mjs
834
+ function resolveFriendlyClientOptions(options) {
835
+ return {
836
+ ...options,
837
+ context: options.context ?? {}
838
+ };
839
+ }
840
+ function createORPCClient(link, options = {}) {
841
+ const path = options.path ?? [];
842
+ const procedureClient = async (...[input, options2 = {}]) => {
843
+ return await link.call(path, input, resolveFriendlyClientOptions(options2));
844
+ };
845
+ const recursive = new Proxy(procedureClient, {
846
+ get(target, key) {
847
+ if (typeof key !== "string" || RECURSIVE_CLIENT_UNWRAP_KEYS.has(key)) {
848
+ return Reflect.get(target, key);
849
+ }
850
+ return createORPCClient(link, {
851
+ ...options,
852
+ path: [...path, key]
853
+ });
854
+ }
855
+ });
856
+ return preventNativeAwait(recursive);
857
+ }
858
+
859
+ // node_modules/@orpc/standard-server-fetch/dist/index.mjs
860
+ function toEventIterator(stream, options = {}) {
861
+ const eventStream = stream?.pipeThrough(new TextDecoderStream).pipeThrough(new EventDecoderStream);
862
+ const reader = eventStream?.getReader();
863
+ let span;
864
+ let isCancelled = false;
865
+ return new AsyncIteratorClass(async () => {
866
+ span ??= startSpan("consume_event_iterator_stream");
867
+ try {
868
+ while (true) {
869
+ if (reader === undefined) {
870
+ return { done: true, value: undefined };
871
+ }
872
+ const { done, value } = await runInSpanContext(span, () => reader.read());
873
+ if (done) {
874
+ if (isCancelled) {
875
+ throw new AbortError("Stream was cancelled");
876
+ }
877
+ return { done: true, value: undefined };
878
+ }
879
+ const event = value.event ?? (value.data !== undefined ? "message" : undefined);
880
+ switch (event) {
881
+ case "message": {
882
+ let message = parseEmptyableJSON(value.data);
883
+ if (isTypescriptObject(message)) {
884
+ message = withEventMeta(message, value);
885
+ }
886
+ span?.addEvent("message");
887
+ return { done: false, value: message };
888
+ }
889
+ case "error": {
890
+ let error = new ErrorEvent({
891
+ data: parseEmptyableJSON(value.data)
892
+ });
893
+ error = withEventMeta(error, value);
894
+ span?.addEvent("error");
895
+ throw error;
896
+ }
897
+ case "done":
898
+ case "close": {
899
+ let done2 = parseEmptyableJSON(value.data);
900
+ if (isTypescriptObject(done2)) {
901
+ done2 = withEventMeta(done2, value);
902
+ }
903
+ span?.addEvent("done");
904
+ return { done: true, value: done2 };
905
+ }
906
+ default: {
907
+ span?.addEvent("maybe_keepalive");
908
+ }
909
+ }
910
+ }
911
+ } catch (e) {
912
+ if (!(e instanceof ErrorEvent)) {
913
+ setSpanError(span, e, options);
914
+ }
915
+ throw e;
916
+ }
917
+ }, async (reason) => {
918
+ try {
919
+ if (reason !== "next") {
920
+ isCancelled = true;
921
+ span?.addEvent("cancelled");
922
+ }
923
+ await runInSpanContext(span, () => reader?.cancel());
924
+ } catch (e) {
925
+ setSpanError(span, e, options);
926
+ throw e;
927
+ } finally {
928
+ span?.end();
929
+ }
930
+ });
931
+ }
932
+ function toEventStream(iterator, options = {}) {
933
+ const keepAliveEnabled = options.eventIteratorKeepAliveEnabled ?? true;
934
+ const keepAliveInterval = options.eventIteratorKeepAliveInterval ?? 5000;
935
+ const keepAliveComment = options.eventIteratorKeepAliveComment ?? "";
936
+ const initialCommentEnabled = options.eventIteratorInitialCommentEnabled ?? true;
937
+ const initialComment = options.eventIteratorInitialComment ?? "";
938
+ let cancelled = false;
939
+ let timeout;
940
+ let span;
941
+ const stream = new ReadableStream({
942
+ start(controller) {
943
+ span = startSpan("stream_event_iterator");
944
+ if (initialCommentEnabled) {
945
+ controller.enqueue(encodeEventMessage({
946
+ comments: [initialComment]
947
+ }));
948
+ }
949
+ },
950
+ async pull(controller) {
951
+ try {
952
+ if (keepAliveEnabled) {
953
+ timeout = setInterval(() => {
954
+ controller.enqueue(encodeEventMessage({
955
+ comments: [keepAliveComment]
956
+ }));
957
+ span?.addEvent("keepalive");
958
+ }, keepAliveInterval);
959
+ }
960
+ const value = await runInSpanContext(span, () => iterator.next());
961
+ clearInterval(timeout);
962
+ if (cancelled) {
963
+ return;
964
+ }
965
+ const meta = getEventMeta(value.value);
966
+ if (!value.done || value.value !== undefined || meta !== undefined) {
967
+ const event = value.done ? "done" : "message";
968
+ controller.enqueue(encodeEventMessage({
969
+ ...meta,
970
+ event,
971
+ data: stringifyJSON(value.value)
972
+ }));
973
+ span?.addEvent(event);
974
+ }
975
+ if (value.done) {
976
+ controller.close();
977
+ span?.end();
978
+ }
979
+ } catch (err) {
980
+ clearInterval(timeout);
981
+ if (cancelled) {
982
+ return;
983
+ }
984
+ if (err instanceof ErrorEvent) {
985
+ controller.enqueue(encodeEventMessage({
986
+ ...getEventMeta(err),
987
+ event: "error",
988
+ data: stringifyJSON(err.data)
989
+ }));
990
+ span?.addEvent("error");
991
+ controller.close();
992
+ } else {
993
+ setSpanError(span, err);
994
+ controller.error(err);
995
+ }
996
+ span?.end();
997
+ }
998
+ },
999
+ async cancel() {
1000
+ try {
1001
+ cancelled = true;
1002
+ clearInterval(timeout);
1003
+ span?.addEvent("cancelled");
1004
+ await runInSpanContext(span, () => iterator.return?.());
1005
+ } catch (e) {
1006
+ setSpanError(span, e);
1007
+ throw e;
1008
+ } finally {
1009
+ span?.end();
1010
+ }
1011
+ }
1012
+ }).pipeThrough(new TextEncoderStream);
1013
+ return stream;
1014
+ }
1015
+ function toStandardBody(re, options = {}) {
1016
+ return runWithSpan({ name: "parse_standard_body", signal: options.signal }, async () => {
1017
+ const contentDisposition = re.headers.get("content-disposition");
1018
+ if (typeof contentDisposition === "string") {
1019
+ const fileName = getFilenameFromContentDisposition(contentDisposition) ?? "blob";
1020
+ const blob2 = await re.blob();
1021
+ return new File([blob2], fileName, {
1022
+ type: blob2.type
1023
+ });
1024
+ }
1025
+ const contentType = re.headers.get("content-type");
1026
+ if (!contentType || contentType.startsWith("application/json")) {
1027
+ const text = await re.text();
1028
+ return parseEmptyableJSON(text);
1029
+ }
1030
+ if (contentType.startsWith("multipart/form-data")) {
1031
+ return await re.formData();
1032
+ }
1033
+ if (contentType.startsWith("application/x-www-form-urlencoded")) {
1034
+ const text = await re.text();
1035
+ return new URLSearchParams(text);
1036
+ }
1037
+ if (contentType.startsWith("text/event-stream")) {
1038
+ return toEventIterator(re.body, options);
1039
+ }
1040
+ if (contentType.startsWith("text/plain")) {
1041
+ return await re.text();
1042
+ }
1043
+ const blob = await re.blob();
1044
+ return new File([blob], "blob", {
1045
+ type: blob.type
1046
+ });
1047
+ });
1048
+ }
1049
+ function toFetchBody(body, headers, options = {}) {
1050
+ if (body instanceof ReadableStream) {
1051
+ return body;
1052
+ }
1053
+ const currentContentDisposition = headers.get("content-disposition");
1054
+ headers.delete("content-type");
1055
+ headers.delete("content-disposition");
1056
+ if (body === undefined) {
1057
+ return;
1058
+ }
1059
+ if (body instanceof Blob) {
1060
+ headers.set("content-type", body.type);
1061
+ headers.set("content-length", body.size.toString());
1062
+ headers.set("content-disposition", currentContentDisposition ?? generateContentDisposition(body instanceof File ? body.name : "blob"));
1063
+ return body;
1064
+ }
1065
+ if (body instanceof FormData) {
1066
+ return body;
1067
+ }
1068
+ if (body instanceof URLSearchParams) {
1069
+ return body;
1070
+ }
1071
+ if (isAsyncIteratorObject(body)) {
1072
+ headers.set("content-type", "text/event-stream");
1073
+ return toEventStream(body, options);
1074
+ }
1075
+ headers.set("content-type", "application/json");
1076
+ return stringifyJSON(body);
1077
+ }
1078
+ function toStandardHeaders(headers, standardHeaders = {}) {
1079
+ headers.forEach((value, key) => {
1080
+ if (Array.isArray(standardHeaders[key])) {
1081
+ standardHeaders[key].push(value);
1082
+ } else if (standardHeaders[key] !== undefined) {
1083
+ standardHeaders[key] = [standardHeaders[key], value];
1084
+ } else {
1085
+ standardHeaders[key] = value;
1086
+ }
1087
+ });
1088
+ return standardHeaders;
1089
+ }
1090
+ function toFetchHeaders(headers, fetchHeaders = new Headers) {
1091
+ for (const [key, value] of Object.entries(headers)) {
1092
+ if (Array.isArray(value)) {
1093
+ for (const v of value) {
1094
+ fetchHeaders.append(key, v);
1095
+ }
1096
+ } else if (value !== undefined) {
1097
+ fetchHeaders.append(key, value);
1098
+ }
1099
+ }
1100
+ return fetchHeaders;
1101
+ }
1102
+ function toFetchRequest(request, options = {}) {
1103
+ const headers = toFetchHeaders(request.headers);
1104
+ const body = toFetchBody(request.body, headers, options);
1105
+ return new Request(request.url, {
1106
+ signal: request.signal,
1107
+ method: request.method,
1108
+ headers,
1109
+ body
1110
+ });
1111
+ }
1112
+ function toStandardLazyResponse(response, options = {}) {
1113
+ return {
1114
+ body: once(() => toStandardBody(response, options)),
1115
+ status: response.status,
1116
+ get headers() {
1117
+ const headers = toStandardHeaders(response.headers);
1118
+ Object.defineProperty(this, "headers", { value: headers, writable: true });
1119
+ return headers;
1120
+ },
1121
+ set headers(value) {
1122
+ Object.defineProperty(this, "headers", { value, writable: true });
1123
+ }
1124
+ };
1125
+ }
1126
+
1127
+ // node_modules/@orpc/client/dist/shared/client.BmCiDGqJ.mjs
1128
+ class CompositeStandardLinkPlugin {
1129
+ plugins;
1130
+ constructor(plugins = []) {
1131
+ this.plugins = [...plugins].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
1132
+ }
1133
+ init(options) {
1134
+ for (const plugin of this.plugins) {
1135
+ plugin.init?.(options);
1136
+ }
1137
+ }
1138
+ }
1139
+
1140
+ class StandardLink {
1141
+ constructor(codec, sender, options = {}) {
1142
+ this.codec = codec;
1143
+ this.sender = sender;
1144
+ const plugin = new CompositeStandardLinkPlugin(options.plugins);
1145
+ plugin.init(options);
1146
+ this.interceptors = toArray(options.interceptors);
1147
+ this.clientInterceptors = toArray(options.clientInterceptors);
1148
+ }
1149
+ interceptors;
1150
+ clientInterceptors;
1151
+ call(path, input, options) {
1152
+ return runWithSpan({ name: `${ORPC_NAME}.${path.join("/")}`, signal: options.signal }, (span) => {
1153
+ span?.setAttribute("rpc.system", ORPC_NAME);
1154
+ span?.setAttribute("rpc.method", path.join("."));
1155
+ if (isAsyncIteratorObject(input)) {
1156
+ input = asyncIteratorWithSpan({ name: "consume_event_iterator_input", signal: options.signal }, input);
1157
+ }
1158
+ return intercept(this.interceptors, { ...options, path, input }, async ({ path: path2, input: input2, ...options2 }) => {
1159
+ const otelConfig = getGlobalOtelConfig();
1160
+ let otelContext;
1161
+ const currentSpan = otelConfig?.trace.getActiveSpan() ?? span;
1162
+ if (currentSpan && otelConfig) {
1163
+ otelContext = otelConfig?.trace.setSpan(otelConfig.context.active(), currentSpan);
1164
+ }
1165
+ const request = await runWithSpan({ name: "encode_request", context: otelContext }, () => this.codec.encode(path2, input2, options2));
1166
+ const response = await intercept(this.clientInterceptors, { ...options2, input: input2, path: path2, request }, ({ input: input3, path: path3, request: request2, ...options3 }) => {
1167
+ return runWithSpan({ name: "send_request", signal: options3.signal, context: otelContext }, () => this.sender.call(request2, options3, path3, input3));
1168
+ });
1169
+ const output = await runWithSpan({ name: "decode_response", context: otelContext }, () => this.codec.decode(response, options2, path2, input2));
1170
+ if (isAsyncIteratorObject(output)) {
1171
+ return asyncIteratorWithSpan({ name: "consume_event_iterator_output", signal: options2.signal }, output);
1172
+ }
1173
+ return output;
1174
+ });
1175
+ });
1176
+ }
1177
+ }
1178
+ var STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES = {
1179
+ BIGINT: 0,
1180
+ DATE: 1,
1181
+ NAN: 2,
1182
+ UNDEFINED: 3,
1183
+ URL: 4,
1184
+ REGEXP: 5,
1185
+ SET: 6,
1186
+ MAP: 7
1187
+ };
1188
+ var BUILT_IN_TYPES = new Set(Object.values(STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES));
1189
+ var SERIALIZED_REGEXP_FORMAT = /^\/(.*)\/([a-z]*)$/;
1190
+ function invalidSerializedData(detail) {
1191
+ return new TypeError(`Invalid RPC serialized data: ${detail}`);
1192
+ }
1193
+ function invalidSerializedType(type, name, expected) {
1194
+ return invalidSerializedData(`type ${type} (${name}) expects ${expected}.`);
1195
+ }
1196
+
1197
+ class StandardRPCJsonSerializer {
1198
+ customSerializers;
1199
+ constructor(options = {}) {
1200
+ this.customSerializers = options.customJsonSerializers ?? [];
1201
+ if (this.customSerializers.length !== new Set(this.customSerializers.map((custom) => custom.type)).size) {
1202
+ throw new Error("Custom serializer type must be unique.");
1203
+ }
1204
+ }
1205
+ serialize(data, segments = [], meta = [], maps = [], blobs = []) {
1206
+ for (const custom of this.customSerializers) {
1207
+ if (custom.condition(data)) {
1208
+ const result = this.serialize(custom.serialize(data), segments, meta, maps, blobs);
1209
+ meta.push([custom.type, ...segments]);
1210
+ return result;
1211
+ }
1212
+ }
1213
+ if (data instanceof Blob) {
1214
+ maps.push(segments);
1215
+ blobs.push(data);
1216
+ return [data, meta, maps, blobs];
1217
+ }
1218
+ if (typeof data === "bigint") {
1219
+ meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.BIGINT, ...segments]);
1220
+ return [data.toString(), meta, maps, blobs];
1221
+ }
1222
+ if (data instanceof Date) {
1223
+ meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.DATE, ...segments]);
1224
+ if (Number.isNaN(data.getTime())) {
1225
+ return [null, meta, maps, blobs];
1226
+ }
1227
+ return [data.toISOString(), meta, maps, blobs];
1228
+ }
1229
+ if (Number.isNaN(data)) {
1230
+ meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.NAN, ...segments]);
1231
+ return [null, meta, maps, blobs];
1232
+ }
1233
+ if (data instanceof URL) {
1234
+ meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.URL, ...segments]);
1235
+ return [data.toString(), meta, maps, blobs];
1236
+ }
1237
+ if (data instanceof RegExp) {
1238
+ meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.REGEXP, ...segments]);
1239
+ return [data.toString(), meta, maps, blobs];
1240
+ }
1241
+ if (data instanceof Set) {
1242
+ const result = this.serialize(Array.from(data), segments, meta, maps, blobs);
1243
+ meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.SET, ...segments]);
1244
+ return result;
1245
+ }
1246
+ if (data instanceof Map) {
1247
+ const result = this.serialize(Array.from(data.entries()), segments, meta, maps, blobs);
1248
+ meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.MAP, ...segments]);
1249
+ return result;
1250
+ }
1251
+ if (Array.isArray(data)) {
1252
+ const json = data.map((v, i) => {
1253
+ if (v === undefined) {
1254
+ meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.UNDEFINED, ...segments, i]);
1255
+ return null;
1256
+ }
1257
+ return this.serialize(v, [...segments, i], meta, maps, blobs)[0];
1258
+ });
1259
+ return [json, meta, maps, blobs];
1260
+ }
1261
+ if (isObject(data)) {
1262
+ const json = {};
1263
+ for (const k in data) {
1264
+ if (k === "toJSON" && typeof data[k] === "function") {
1265
+ continue;
1266
+ }
1267
+ json[k] = this.serialize(data[k], [...segments, k], meta, maps, blobs)[0];
1268
+ }
1269
+ return [json, meta, maps, blobs];
1270
+ }
1271
+ return [data, meta, maps, blobs];
1272
+ }
1273
+ deserialize(json, meta, maps, getBlob) {
1274
+ const ref = { data: json };
1275
+ const input = { data: json };
1276
+ if (maps && getBlob) {
1277
+ maps.forEach((segments, i) => {
1278
+ const blob = getBlob(i);
1279
+ if (!(blob instanceof Blob)) {
1280
+ throw invalidSerializedData(`blob ${i} is not a Blob.`);
1281
+ }
1282
+ let original = input;
1283
+ let currentRef = ref;
1284
+ let preSegment = "data";
1285
+ segments.forEach((segment) => {
1286
+ original = original[preSegment];
1287
+ currentRef = copyOnWrite(currentRef, preSegment, original);
1288
+ preSegment = segment;
1289
+ if (!Object.hasOwn(currentRef, preSegment)) {
1290
+ throw invalidSerializedData(`segment "${preSegment}" does not exist.`);
1291
+ }
1292
+ });
1293
+ currentRef[preSegment] = blob;
1294
+ });
1295
+ }
1296
+ for (const item of meta) {
1297
+ const type = item[0];
1298
+ const custom = this.customSerializers.find((custom2) => custom2.type === type);
1299
+ if (custom === undefined && !BUILT_IN_TYPES.has(type)) {
1300
+ continue;
1301
+ }
1302
+ let original = input;
1303
+ let currentRef = ref;
1304
+ let preSegment = "data";
1305
+ for (let i = 1;i < item.length; i++) {
1306
+ original = original[preSegment];
1307
+ currentRef = copyOnWrite(currentRef, preSegment, original);
1308
+ preSegment = item[i];
1309
+ if (!Object.hasOwn(currentRef, preSegment)) {
1310
+ throw invalidSerializedData(`segment "${preSegment}" does not exist.`);
1311
+ }
1312
+ }
1313
+ if (custom !== undefined) {
1314
+ currentRef[preSegment] = custom.deserialize(currentRef[preSegment]);
1315
+ continue;
1316
+ }
1317
+ const serialized = currentRef[preSegment];
1318
+ switch (type) {
1319
+ case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.BIGINT: {
1320
+ if (typeof serialized !== "string") {
1321
+ throw invalidSerializedType(type, "bigint", "a string");
1322
+ }
1323
+ const value = parseBigIntString(serialized, DEFAULT_MAX_BIGINT_DIGITS);
1324
+ if (value === undefined) {
1325
+ throw invalidSerializedType(type, "bigint", `a decimal integer string of at most ${DEFAULT_MAX_BIGINT_DIGITS} digits`);
1326
+ }
1327
+ currentRef[preSegment] = value;
1328
+ break;
1329
+ }
1330
+ case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.DATE:
1331
+ if (typeof serialized !== "string" && serialized !== null) {
1332
+ throw invalidSerializedType(type, "date", "a string or null");
1333
+ }
1334
+ currentRef[preSegment] = new Date(serialized ?? Number.NaN);
1335
+ break;
1336
+ case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.NAN:
1337
+ if (serialized !== null) {
1338
+ throw invalidSerializedType(type, "nan", "null");
1339
+ }
1340
+ currentRef[preSegment] = Number.NaN;
1341
+ break;
1342
+ case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.UNDEFINED:
1343
+ if (serialized !== null) {
1344
+ throw invalidSerializedType(type, "undefined", "null");
1345
+ }
1346
+ currentRef[preSegment] = undefined;
1347
+ break;
1348
+ case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.URL:
1349
+ if (typeof serialized !== "string") {
1350
+ throw invalidSerializedType(type, "url", "a string");
1351
+ }
1352
+ currentRef[preSegment] = new URL(serialized);
1353
+ break;
1354
+ case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.REGEXP: {
1355
+ if (typeof serialized !== "string") {
1356
+ throw invalidSerializedType(type, "regexp", "a string");
1357
+ }
1358
+ const match = serialized.match(SERIALIZED_REGEXP_FORMAT);
1359
+ if (match === null || !isValidRegExpFlags(match[2])) {
1360
+ throw invalidSerializedData(`type ${type} (regexp) expects a "/pattern/flags" string.`);
1361
+ }
1362
+ currentRef[preSegment] = createLazyRegExp(match[1], match[2]);
1363
+ break;
1364
+ }
1365
+ case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.SET:
1366
+ if (!Array.isArray(serialized)) {
1367
+ throw invalidSerializedType(type, "set", "an array");
1368
+ }
1369
+ currentRef[preSegment] = new Set(serialized);
1370
+ break;
1371
+ case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.MAP:
1372
+ if (!Array.isArray(serialized)) {
1373
+ throw invalidSerializedType(type, "map", "an array");
1374
+ }
1375
+ currentRef[preSegment] = new Map(serialized);
1376
+ break;
1377
+ }
1378
+ }
1379
+ return ref.data;
1380
+ }
1381
+ }
1382
+ function toHttpPath(path) {
1383
+ return `/${path.map(encodeURIComponent).join("/")}`;
1384
+ }
1385
+ function toStandardHeaders2(headers) {
1386
+ if (typeof headers.forEach === "function") {
1387
+ return toStandardHeaders(headers);
1388
+ }
1389
+ return headers;
1390
+ }
1391
+ function getMalformedResponseErrorCode(status) {
1392
+ return Object.entries(COMMON_ORPC_ERROR_DEFS).find(([, def]) => def.status === status)?.[0] ?? "MALFORMED_ORPC_ERROR_RESPONSE";
1393
+ }
1394
+
1395
+ class StandardRPCLinkCodec {
1396
+ constructor(serializer, options) {
1397
+ this.serializer = serializer;
1398
+ this.baseUrl = options.url;
1399
+ this.maxUrlLength = options.maxUrlLength ?? 2083;
1400
+ this.fallbackMethod = options.fallbackMethod ?? "POST";
1401
+ this.expectedMethod = options.method ?? this.fallbackMethod;
1402
+ this.headers = options.headers ?? {};
1403
+ }
1404
+ baseUrl;
1405
+ maxUrlLength;
1406
+ fallbackMethod;
1407
+ expectedMethod;
1408
+ headers;
1409
+ async encode(path, input, options) {
1410
+ let headers = toStandardHeaders2(await value(this.headers, options, path, input));
1411
+ if (options.lastEventId !== undefined) {
1412
+ headers = mergeStandardHeaders(headers, { "last-event-id": options.lastEventId });
1413
+ }
1414
+ const expectedMethod = await value(this.expectedMethod, options, path, input);
1415
+ const baseUrl = await value(this.baseUrl, options, path, input);
1416
+ const url = new URL(baseUrl);
1417
+ url.pathname = `${url.pathname.replace(/\/$/, "")}${toHttpPath(path)}`;
1418
+ const serialized = this.serializer.serialize(input);
1419
+ if (expectedMethod === "GET" && !(serialized instanceof FormData) && !isAsyncIteratorObject(serialized)) {
1420
+ const maxUrlLength = await value(this.maxUrlLength, options, path, input);
1421
+ const getUrl = new URL(url);
1422
+ getUrl.searchParams.append("data", stringifyJSON(serialized));
1423
+ if (getUrl.toString().length <= maxUrlLength) {
1424
+ return {
1425
+ body: undefined,
1426
+ method: expectedMethod,
1427
+ headers,
1428
+ url: getUrl,
1429
+ signal: options.signal
1430
+ };
1431
+ }
1432
+ }
1433
+ return {
1434
+ url,
1435
+ method: expectedMethod === "GET" ? this.fallbackMethod : expectedMethod,
1436
+ headers,
1437
+ body: serialized,
1438
+ signal: options.signal
1439
+ };
1440
+ }
1441
+ async decode(response) {
1442
+ if (response.status >= 300 && response.status < 400) {
1443
+ throw new Error(`Unexpected redirect response (status ${response.status}): RPCLink does not follow redirects.`);
1444
+ }
1445
+ const isOk = !isORPCErrorStatus(response.status);
1446
+ const deserialized = await (async () => {
1447
+ let isBodyOk = false;
1448
+ try {
1449
+ const body = await response.body();
1450
+ isBodyOk = true;
1451
+ return this.serializer.deserialize(body);
1452
+ } catch (error) {
1453
+ if (!isBodyOk) {
1454
+ throw new Error("Cannot parse response body, please check the response body and content-type.", {
1455
+ cause: error
1456
+ });
1457
+ }
1458
+ throw new Error("Invalid RPC response format.", {
1459
+ cause: error
1460
+ });
1461
+ }
1462
+ })();
1463
+ if (!isOk) {
1464
+ if (isORPCErrorJson(deserialized)) {
1465
+ throw createORPCErrorFromJson(deserialized);
1466
+ }
1467
+ throw new ORPCError(getMalformedResponseErrorCode(response.status), {
1468
+ status: response.status,
1469
+ data: { ...response, body: deserialized }
1470
+ });
1471
+ }
1472
+ return deserialized;
1473
+ }
1474
+ }
1475
+
1476
+ class StandardRPCSerializer {
1477
+ constructor(jsonSerializer) {
1478
+ this.jsonSerializer = jsonSerializer;
1479
+ }
1480
+ serialize(data) {
1481
+ if (isAsyncIteratorObject(data)) {
1482
+ return mapEventIterator(data, {
1483
+ value: async (value) => this.#serialize(value, false),
1484
+ error: async (e) => {
1485
+ return new ErrorEvent({
1486
+ data: this.#serialize(toORPCError(e).toJSON(), false),
1487
+ cause: e
1488
+ });
1489
+ }
1490
+ });
1491
+ }
1492
+ return this.#serialize(data, true);
1493
+ }
1494
+ #serialize(data, enableFormData) {
1495
+ const [json, meta_, maps, blobs] = this.jsonSerializer.serialize(data);
1496
+ const meta = meta_.length === 0 ? undefined : meta_;
1497
+ if (!enableFormData || blobs.length === 0) {
1498
+ return {
1499
+ json,
1500
+ meta
1501
+ };
1502
+ }
1503
+ const form = new FormData;
1504
+ form.set("data", stringifyJSON({ json, meta, maps }));
1505
+ blobs.forEach((blob, i) => {
1506
+ form.set(i.toString(), blob);
1507
+ });
1508
+ return form;
1509
+ }
1510
+ deserialize(data) {
1511
+ if (isAsyncIteratorObject(data)) {
1512
+ return mapEventIterator(data, {
1513
+ value: async (value) => this.#deserialize(value),
1514
+ error: async (e) => {
1515
+ if (!(e instanceof ErrorEvent)) {
1516
+ return e;
1517
+ }
1518
+ const deserialized = this.#deserialize(e.data);
1519
+ if (isORPCErrorJson(deserialized)) {
1520
+ return createORPCErrorFromJson(deserialized, { cause: e });
1521
+ }
1522
+ return new ErrorEvent({
1523
+ data: deserialized,
1524
+ cause: e
1525
+ });
1526
+ }
1527
+ });
1528
+ }
1529
+ return this.#deserialize(data);
1530
+ }
1531
+ #deserialize(data) {
1532
+ if (data === undefined) {
1533
+ return;
1534
+ }
1535
+ if (!(data instanceof FormData)) {
1536
+ return this.jsonSerializer.deserialize(data.json, data.meta ?? []);
1537
+ }
1538
+ const serialized = JSON.parse(data.get("data"));
1539
+ return this.jsonSerializer.deserialize(serialized.json, serialized.meta ?? [], serialized.maps, (i) => data.get(i.toString()));
1540
+ }
1541
+ }
1542
+
1543
+ class StandardRPCLink extends StandardLink {
1544
+ constructor(linkClient, options) {
1545
+ const jsonSerializer = new StandardRPCJsonSerializer(options);
1546
+ const serializer = new StandardRPCSerializer(jsonSerializer);
1547
+ const linkCodec = new StandardRPCLinkCodec(serializer, options);
1548
+ super(linkCodec, linkClient, options);
1549
+ }
1550
+ }
1551
+
1552
+ // node_modules/@orpc/client/dist/adapters/fetch/index.mjs
1553
+ class CompositeLinkFetchPlugin extends CompositeStandardLinkPlugin {
1554
+ initRuntimeAdapter(options) {
1555
+ for (const plugin of this.plugins) {
1556
+ plugin.initRuntimeAdapter?.(options);
1557
+ }
1558
+ }
1559
+ }
1560
+
1561
+ class LinkFetchClient {
1562
+ fetch;
1563
+ toFetchRequestOptions;
1564
+ adapterInterceptors;
1565
+ constructor(options) {
1566
+ const plugin = new CompositeLinkFetchPlugin(options.plugins);
1567
+ plugin.initRuntimeAdapter(options);
1568
+ this.fetch = options.fetch ?? globalThis.fetch.bind(globalThis);
1569
+ this.toFetchRequestOptions = options;
1570
+ this.adapterInterceptors = toArray(options.adapterInterceptors);
1571
+ }
1572
+ async call(standardRequest, options, path, input) {
1573
+ const request = toFetchRequest(standardRequest, this.toFetchRequestOptions);
1574
+ const fetchResponse = await intercept(this.adapterInterceptors, { ...options, request, path, input, init: { redirect: "manual" } }, ({ request: request2, path: path2, input: input2, init, ...options2 }) => this.fetch(request2, init, options2, path2, input2));
1575
+ const lazyResponse = toStandardLazyResponse(fetchResponse, { signal: request.signal });
1576
+ return lazyResponse;
1577
+ }
1578
+ }
1579
+
1580
+ class RPCLink extends StandardRPCLink {
1581
+ constructor(options) {
1582
+ const linkClient = new LinkFetchClient(options);
1583
+ super(linkClient, options);
1584
+ }
1585
+ }
1586
+
1587
+ // app/lib/github.ts
1588
+ var NAME = /^[A-Za-z0-9_.-]+$/;
1589
+ function parseGitHubRemote(remote) {
1590
+ const text = remote.trim();
1591
+ let path = null;
1592
+ const scp = /^(?:[A-Za-z0-9_.-]+@)?github\.com:(.+)$/i.exec(text);
1593
+ if (scp) {
1594
+ path = scp[1];
1595
+ } else {
1596
+ try {
1597
+ const url = new URL(text);
1598
+ if (!["https:", "http:", "ssh:", "git:"].includes(url.protocol))
1599
+ return null;
1600
+ if (url.hostname.toLowerCase() !== "github.com" && url.hostname.toLowerCase() !== "www.github.com")
1601
+ return null;
1602
+ path = url.pathname;
1603
+ } catch {
1604
+ return null;
1605
+ }
1606
+ }
1607
+ const parts = path.replace(/^\/+/, "").replace(/\/+$/, "").replace(/\.git$/i, "").split("/");
1608
+ if (parts.length !== 2)
1609
+ return null;
1610
+ const [owner, name] = parts;
1611
+ if (!NAME.test(owner) || !NAME.test(name) || name === "." || name === "..")
1612
+ return null;
1613
+ return `${owner}/${name}`;
1614
+ }
1615
+
1616
+ // cli/ahfact.ts
1617
+ var DEFAULT_SERVER = "https://ahfact.com";
1618
+ var sleep = (ms) => new Promise((done) => setTimeout(done, ms));
1619
+ var HELP = `ahfact: work with the Astrohacker Factory from the command line.
1620
+
1621
+ You, once per computer:
1622
+ ahfact login [--machine M] sign the CLI in; approve the code in the browser
1623
+ ahfact logout revoke this computer's CLI token
1624
+ ahfact whoami who the CLI acts as, and this checkout's project and worker
1625
+
1626
+ Projects (a project is a GitHub repository):
1627
+ ahfact project add [--slug S] [--name N] [--repo OWNER/NAME]
1628
+ register this checkout's origin (or --repo)
1629
+ ahfact project show this checkout's project
1630
+ ahfact project list
1631
+
1632
+ Workers (one per project, harness and computer):
1633
+ ahfact worker start --harness H [--machine M]
1634
+ create or reuse this checkout's worker and save its token
1635
+ ahfact worker whoami the worker this checkout's commands act as
1636
+ ahfact wait [--timeout SECONDS] lease the next job, waiting until one comes (or the timeout)
1637
+ ahfact next [--wait SECONDS] one attempt, waiting at most 55 seconds; prints null if none
1638
+ ahfact leases the worker's live leases, to resume after a restart
1639
+ ahfact heartbeat say "still here"
1640
+
1641
+ Jobs:
1642
+ ahfact job create --kind K --subject S --title T [--harness H] [--machine M] [--exclude AGENT]...
1643
+
1644
+ Subagents, for the lease they hold:
1645
+ ahfact log LEASE MESSAGE report progress; renews the lease
1646
+ ahfact renew LEASE renew without a message
1647
+ ahfact ref LEASE AGENT_ID record the harness's id for this subagent
1648
+ ahfact done LEASE [MESSAGE] the job is finished
1649
+ ahfact release LEASE [MESSAGE] hand the job back to the queue
1650
+
1651
+ Options and environment:
1652
+ --server URL / AHFACT_URL the factory (default ${DEFAULT_SERVER})
1653
+ --worker NAME / AHFACT_WORKER act as this worker
1654
+ --harness H / AHFACT_HARNESS pick this checkout's worker by harness
1655
+ --machine M / AHFACT_MACHINE this computer's short name (default: the one given at login)
1656
+ Credentials live in ~/.config/ahfact/, mode 0600.`;
1657
+
1658
+ class UsageError extends Error {
1659
+ }
1660
+ function configDir() {
1661
+ return join(process.env["XDG_CONFIG_HOME"] ?? join(homedir(), ".config"), "ahfact");
1662
+ }
1663
+ function hostOf(server) {
1664
+ return new URL(server).host.replace(/[^A-Za-z0-9.-]/g, "_");
1665
+ }
1666
+ async function writePrivate(file, value) {
1667
+ await mkdir(join(file, ".."), { recursive: true, mode: 448 });
1668
+ await writeFile(file, JSON.stringify(value, null, 2) + `
1669
+ `, { mode: 384 });
1670
+ await chmod(file, 384);
1671
+ }
1672
+ async function readJson(file) {
1673
+ try {
1674
+ return JSON.parse(await readFile(file, "utf8"));
1675
+ } catch {
1676
+ return null;
1677
+ }
1678
+ }
1679
+ var personFile = (server) => join(configDir(), "people", `${hostOf(server)}.json`);
1680
+ var workerFile = (worker) => join(configDir(), "workers", `${worker}.json`);
1681
+ async function loadPerson(server) {
1682
+ const cred = await readJson(personFile(server));
1683
+ if (cred === null || cred.server !== server)
1684
+ throw new UsageError(`Not signed in to ${server}. Run: ahfact login`);
1685
+ return cred;
1686
+ }
1687
+ async function allWorkers(server) {
1688
+ let files = [];
1689
+ try {
1690
+ files = (await readdir(join(configDir(), "workers"))).filter((f) => f.endsWith(".json"));
1691
+ } catch {}
1692
+ const creds = [];
1693
+ for (const f of files) {
1694
+ const cred = await readJson(join(configDir(), "workers", f));
1695
+ if (cred !== null && cred.server === server)
1696
+ creds.push(cred);
1697
+ }
1698
+ return creds;
1699
+ }
1700
+ function checkoutRepo() {
1701
+ try {
1702
+ const url = execFileSync("git", ["remote", "get-url", "origin"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
1703
+ return parseGitHubRemote(url);
1704
+ } catch {
1705
+ return null;
1706
+ }
1707
+ }
1708
+ function requireRepo(explicit) {
1709
+ if (explicit) {
1710
+ const repo = parseGitHubRemote(explicit) ?? (/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(explicit) ? explicit : null);
1711
+ if (repo === null)
1712
+ throw new UsageError(`Not a GitHub repository: ${explicit}`);
1713
+ return repo;
1714
+ }
1715
+ const repo = checkoutRepo();
1716
+ if (repo === null)
1717
+ throw new UsageError("This directory has no GitHub origin. Run in a checkout, or pass --repo OWNER/NAME.");
1718
+ return repo;
1719
+ }
1720
+ async function loadWorker(server, opts) {
1721
+ const all = await allWorkers(server);
1722
+ const named = opts.worker ?? process.env["AHFACT_WORKER"];
1723
+ if (named) {
1724
+ const found = all.find((c) => c.worker === named);
1725
+ if (!found)
1726
+ throw new UsageError(`Worker ${named} has no saved token for ${server}. Run: ahfact worker start --harness H`);
1727
+ return found;
1728
+ }
1729
+ const repo = checkoutRepo();
1730
+ const harness = opts.harness ?? process.env["AHFACT_HARNESS"];
1731
+ let candidates = repo === null ? all : all.filter((c) => c.repo.toLowerCase() === repo.toLowerCase());
1732
+ if (harness)
1733
+ candidates = candidates.filter((c) => c.harness === harness);
1734
+ if (candidates.length === 1)
1735
+ return candidates[0];
1736
+ if (candidates.length === 0) {
1737
+ throw new UsageError(`No worker for ${repo ?? "this directory"}${harness ? ` on ${harness}` : ""}. Run: ahfact worker start --harness H`);
1738
+ }
1739
+ throw new UsageError(`Several workers match (${candidates.map((c) => c.worker).join(", ")}). Pick one with --worker, AHFACT_WORKER or AHFACT_HARNESS.`);
1740
+ }
1741
+ function client(server, token) {
1742
+ const link = new RPCLink({
1743
+ url: `${server}/rpc`,
1744
+ headers: () => token ? { authorization: `Bearer ${token}` } : {}
1745
+ });
1746
+ return createORPCClient(link);
1747
+ }
1748
+ function print(value) {
1749
+ process.stdout.write(JSON.stringify(value, null, 2) + `
1750
+ `);
1751
+ }
1752
+ function hint(text) {
1753
+ process.stderr.write(text + `
1754
+ `);
1755
+ }
1756
+ function defaultMachine() {
1757
+ return (process.env["AHFACT_MACHINE"] ?? hostname().split(".")[0]).toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 32);
1758
+ }
1759
+ async function login(server, machineFlag) {
1760
+ const machine = machineFlag ?? defaultMachine();
1761
+ const api = client(server);
1762
+ const started = await api.device.start({ machine });
1763
+ hint(`To sign in the ahfact CLI on ${machine}, open:
1764
+
1765
+ ${started.verificationUrl}
1766
+
1767
+ and check the code is ${started.userCode}. Waiting for approval…`);
1768
+ for (;; ) {
1769
+ if (Date.now() > new Date(started.expiresAt).getTime())
1770
+ throw new UsageError("The sign-in request expired. Run login again.");
1771
+ await sleep(started.interval * 1000);
1772
+ const polled = await api.device.poll({ deviceCode: started.deviceCode });
1773
+ if (polled.status === "pending")
1774
+ continue;
1775
+ if (polled.status !== "approved")
1776
+ throw new UsageError(`Sign-in ${polled.status}.`);
1777
+ const file = personFile(server);
1778
+ await writePrivate(file, { server, email: polled.email, machine, token: polled.token });
1779
+ hint(`Signed in as ${polled.email}. Token saved to ${file}.`);
1780
+ print({ email: polled.email, machine, server });
1781
+ return;
1782
+ }
1783
+ }
1784
+ var str = (values, key) => {
1785
+ const v = values[key];
1786
+ return typeof v === "string" ? v : undefined;
1787
+ };
1788
+ async function main(argv) {
1789
+ const { values, positionals } = parseArgs({
1790
+ args: argv,
1791
+ allowPositionals: true,
1792
+ options: {
1793
+ server: { type: "string" },
1794
+ worker: { type: "string" },
1795
+ repo: { type: "string" },
1796
+ slug: { type: "string" },
1797
+ name: { type: "string" },
1798
+ harness: { type: "string" },
1799
+ machine: { type: "string" },
1800
+ wait: { type: "string" },
1801
+ timeout: { type: "string" },
1802
+ kind: { type: "string" },
1803
+ subject: { type: "string" },
1804
+ title: { type: "string" },
1805
+ exclude: { type: "string", multiple: true },
1806
+ help: { type: "boolean", short: "h" }
1807
+ }
1808
+ });
1809
+ const [command, sub, ...rest] = positionals;
1810
+ if (values.help || command === undefined || command === "help") {
1811
+ hint(HELP);
1812
+ return;
1813
+ }
1814
+ const server = (str(values, "server") ?? process.env["AHFACT_URL"] ?? DEFAULT_SERVER).replace(/\/+$/, "");
1815
+ const asPerson = async () => client(server, (await loadPerson(server)).token);
1816
+ const asWorker = async () => client(server, (await loadWorker(server, { worker: values.worker, harness: values.harness })).token);
1817
+ const leaseArgs = [sub, ...rest];
1818
+ const leaseId = () => {
1819
+ const id = leaseArgs[0];
1820
+ if (!id)
1821
+ throw new UsageError(`${command} needs a lease id.`);
1822
+ return id;
1823
+ };
1824
+ const message = (from) => leaseArgs.slice(from).join(" ");
1825
+ switch (command) {
1826
+ case "login":
1827
+ return login(server, values.machine);
1828
+ case "logout": {
1829
+ const cred = await readJson(personFile(server));
1830
+ if (cred !== null) {
1831
+ try {
1832
+ await client(server, cred.token).auth.logout();
1833
+ } catch {}
1834
+ await rm(personFile(server), { force: true });
1835
+ }
1836
+ return print({ signedOut: cred !== null, server });
1837
+ }
1838
+ case "whoami": {
1839
+ const cred = await readJson(personFile(server));
1840
+ const person = cred === null ? null : await client(server, cred.token).auth.me().catch(() => null);
1841
+ const repo = checkoutRepo();
1842
+ const workers = (await allWorkers(server)).filter((c) => repo !== null && c.repo.toLowerCase() === repo.toLowerCase());
1843
+ return print({ server, person: person && { email: person.email, machine: cred.machine }, repo, workers: workers.map((w) => w.worker) });
1844
+ }
1845
+ case "project": {
1846
+ const api = await asPerson();
1847
+ if (sub === "add") {
1848
+ return print(await api.projects.add({ repo: requireRepo(values.repo), slug: values.slug, name: values.name }));
1849
+ }
1850
+ if (sub === "show")
1851
+ return print(await api.projects.get({ repo: requireRepo(values.repo) }));
1852
+ if (sub === "list")
1853
+ return print(await api.projects.list());
1854
+ throw new UsageError("Usage: ahfact project add|show|list");
1855
+ }
1856
+ case "worker": {
1857
+ if (sub === "whoami")
1858
+ return print(await (await asWorker()).worker.whoami());
1859
+ if (sub !== "start")
1860
+ throw new UsageError("Usage: ahfact worker start --harness H | ahfact worker whoami");
1861
+ const cred = await loadPerson(server);
1862
+ const harness = values.harness ?? process.env["AHFACT_HARNESS"];
1863
+ if (!harness)
1864
+ throw new UsageError("worker start needs --harness (claude, codex, grok, …) or AHFACT_HARNESS.");
1865
+ const machine = values.machine ?? process.env["AHFACT_MACHINE"] ?? cred.machine;
1866
+ const repo = requireRepo(values.repo);
1867
+ const started = await client(server, cred.token).workers.start({ project: { repo }, harness, machine });
1868
+ const file = workerFile(started.worker);
1869
+ await writePrivate(file, { server, worker: started.worker, token: started.token, repo, harness, machine });
1870
+ hint(`Worker ${started.worker} is ready. Token saved to ${file}. Next: ahfact wait`);
1871
+ return print({ worker: started.worker, repo, harness, machine });
1872
+ }
1873
+ case "heartbeat":
1874
+ return print(await (await asWorker()).worker.heartbeat());
1875
+ case "leases":
1876
+ return print(await (await asWorker()).worker.leases());
1877
+ case "next":
1878
+ return print(await (await asWorker()).worker.next({ wait: Number(values.wait ?? 0) }));
1879
+ case "wait": {
1880
+ const api = await asWorker();
1881
+ const timeout = values.timeout === undefined ? Infinity : Number(values.timeout) * 1000;
1882
+ const deadline = Date.now() + timeout;
1883
+ for (;; ) {
1884
+ const left = Math.ceil((deadline - Date.now()) / 1000);
1885
+ const claim = await api.worker.next({ wait: Math.max(0, Math.min(55, left)) });
1886
+ if (claim !== null)
1887
+ return print(claim);
1888
+ if (Date.now() >= deadline)
1889
+ return print(null);
1890
+ }
1891
+ }
1892
+ case "job": {
1893
+ if (sub !== "create")
1894
+ throw new UsageError("Usage: ahfact job create --kind K --subject S --title T");
1895
+ if (!values.kind || !values.subject || !values.title)
1896
+ throw new UsageError("job create needs --kind, --subject and --title.");
1897
+ const job = {
1898
+ kind: values.kind,
1899
+ subject: values.subject,
1900
+ title: values.title,
1901
+ requirements: { harness: values.harness, machine: values.machine },
1902
+ excludedAgents: values.exclude ?? []
1903
+ };
1904
+ if (values.worker ?? process.env["AHFACT_WORKER"])
1905
+ return print(await (await asWorker()).worker.createJob(job));
1906
+ return print(await (await asPerson()).jobs.create({ ...job, project: { repo: requireRepo(values.repo) } }));
1907
+ }
1908
+ case "log": {
1909
+ const text = message(1);
1910
+ if (text === "")
1911
+ throw new UsageError("log needs a message.");
1912
+ return print(await (await asWorker()).lease.log({ leaseId: leaseId(), message: text }));
1913
+ }
1914
+ case "renew":
1915
+ return print(await (await asWorker()).lease.renew({ leaseId: leaseId() }));
1916
+ case "ref": {
1917
+ const ref = leaseArgs[1];
1918
+ if (!ref)
1919
+ throw new UsageError("ref needs the subagent's id.");
1920
+ return print(await (await asWorker()).lease.setAgentRef({ leaseId: leaseId(), ref }));
1921
+ }
1922
+ case "done":
1923
+ return print(await (await asWorker()).lease.done({ leaseId: leaseId(), message: message(1) }));
1924
+ case "release":
1925
+ return print(await (await asWorker()).lease.release({ leaseId: leaseId(), message: message(1) }));
1926
+ default:
1927
+ throw new UsageError(`Unknown command ${command}. Run: ahfact help`);
1928
+ }
1929
+ }
1930
+ try {
1931
+ await main(process.argv.slice(2));
1932
+ } catch (error) {
1933
+ if (error instanceof UsageError) {
1934
+ hint(`ahfact: ${error.message}`);
1935
+ process.exit(2);
1936
+ }
1937
+ if (error instanceof ORPCError) {
1938
+ process.stderr.write(JSON.stringify({ error: error.code, message: error.message }) + `
1939
+ `);
1940
+ process.exit(1);
1941
+ }
1942
+ if (error instanceof Error && /fetch|ECONNREFUSED|Unable to connect/i.test(error.message)) {
1943
+ hint(`ahfact: cannot reach the factory: ${error.message}`);
1944
+ process.exit(3);
1945
+ }
1946
+ throw error;
1947
+ }