@moxxy/cli 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +1792 -592
- package/dist/bin.js.map +1 -1
- package/dist/sidecar.js +92 -2
- package/dist/sidecar.js.map +1 -1
- package/dist/skills/add-provider.md +7 -3
- package/package.json +2 -2
package/dist/bin.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { z as z$1, defineProvider, definePlugin, defineTool, MoxxyError, writeFileAtomic, asTurnId, defineMode, asPluginId, defineChannel, defineTunnelProvider, createMutex, defineWorkflowExecutor, toFriendlyError, estimateTextTokens, classifyHttpStatus, createStuckLoopDetector, runCompactionIfNeeded, runElisionIfNeeded, collectProviderStream, usageEventFields, isContextOverflowError, emitRequestsAndDetectStuck, executeToolUses, buildSystemPromptWithSkills, projectMessages, defineCompactor, defineCacheStrategy, denyByDefaultResolver, createAllowListResolver, zodToJsonSchema, runSingleShotTurn, bearerTokenMatches, resolveChannelToken, estimateContextTokens, readRequestBody,
|
|
3
|
+
import { z as z$1, defineProvider, definePlugin, defineTool, MoxxyError, writeFileAtomic, asTurnId, defineMode, asPluginId, defineChannel, defineTunnelProvider, createMutex, defineWorkflowExecutor, toFriendlyError, estimateTextTokens, classifyHttpStatus, createStuckLoopDetector, runCompactionIfNeeded, runElisionIfNeeded, collectProviderStream, usageEventFields, isContextOverflowError, emitRequestsAndDetectStuck, executeToolUses, buildSystemPromptWithSkills, projectMessages, defineCompactor, defineCacheStrategy, denyByDefaultResolver, createAllowListResolver, zodToJsonSchema, moxxyPath, runSingleShotTurn, bearerTokenMatches, resolveChannelToken, rotateChannelToken, estimateContextTokens, readRequestBody, MOXXY_WS_SUBPROTOCOL, defineEmbedder, bearerGuard, tokenFromWsProtocolHeader, skillFrontmatterSchema, asSkillId, getInstallHint, moxxyHome, defineTranscriber, summarizeTokensByModel, migrateModeName, createDeferredPermissionResolver, classifyNetworkError, addModelTotals, ISOLATION_RANK, moxxyPackageSchema, defineCommand, createCallbackResolver, autoAllowResolver, asSessionId, asToolCallId, defineViewRenderer, DEFAULT_VIEW_TAGS, evaluateToolRule, summarizeSessionTokensFromEvents, asEventId } from '@moxxy/sdk';
|
|
4
4
|
import * as fs27 from 'fs';
|
|
5
5
|
import fs27__default, { existsSync, promises, ReadStream, readFileSync, statSync, readdirSync, mkdirSync, writeFileSync, unlinkSync, renameSync, watch, createReadStream } from 'fs';
|
|
6
6
|
import * as path3 from 'path';
|
|
7
|
-
import path3__default, { basename } from 'path';
|
|
7
|
+
import path3__default, { join, dirname, basename } from 'path';
|
|
8
8
|
import { z } from 'zod';
|
|
9
9
|
import * as os5 from 'os';
|
|
10
10
|
import os5__default, { homedir, userInfo } from 'os';
|
|
@@ -22,7 +22,7 @@ import V3, { stdin, stdout, env, cwd } from 'process';
|
|
|
22
22
|
import tty, { ReadStream as ReadStream$1 } from 'tty';
|
|
23
23
|
import { once, EventEmitter } from 'events';
|
|
24
24
|
import { Buffer as Buffer$1 } from 'buffer';
|
|
25
|
-
import { readFile, mkdir, unlink, writeFile } from 'fs/promises';
|
|
25
|
+
import { readFile, mkdir, open, rm, stat, rename as rename$1, unlink, writeFile } from 'fs/promises';
|
|
26
26
|
import { spawn, spawnSync } from 'child_process';
|
|
27
27
|
import { deprecate, inspect, styleText } from 'util';
|
|
28
28
|
import { ReadableStream as ReadableStream$1 } from 'stream/web';
|
|
@@ -192,6 +192,7 @@ var init_log = __esm({
|
|
|
192
192
|
EventLog = class {
|
|
193
193
|
events = [];
|
|
194
194
|
listeners = /* @__PURE__ */ new Set();
|
|
195
|
+
clearListeners = /* @__PURE__ */ new Set();
|
|
195
196
|
now;
|
|
196
197
|
constructor(seed = [], opts = {}) {
|
|
197
198
|
this.now = opts.now ?? Date.now;
|
|
@@ -250,25 +251,44 @@ var init_log = __esm({
|
|
|
250
251
|
const snapshot = [...this.listeners];
|
|
251
252
|
for (const fn of snapshot) {
|
|
252
253
|
try {
|
|
253
|
-
void fn(event)
|
|
254
|
+
void Promise.resolve(fn(event)).catch(() => {
|
|
255
|
+
});
|
|
254
256
|
} catch {
|
|
255
257
|
}
|
|
256
258
|
}
|
|
257
259
|
}
|
|
258
260
|
/**
|
|
259
|
-
* Drop every event from the log. Used by `/new`
|
|
260
|
-
*
|
|
261
|
+
* Drop every event from the log. Used by `/new` to start a fresh
|
|
262
|
+
* session without rebuilding the entire Session object — the
|
|
261
263
|
* registries, resolvers, and active provider stay; only the
|
|
262
|
-
* conversation context vanishes.
|
|
263
|
-
* notified
|
|
264
|
-
*
|
|
265
|
-
*
|
|
264
|
+
* conversation context vanishes. Per-event listeners are NOT
|
|
265
|
+
* notified (there's no "event removed" event in the schema), but
|
|
266
|
+
* {@link onClear} subscribers fire — that's how the persistence
|
|
267
|
+
* sidecar truncates its JSONL (so `--resume` can't resurrect wiped
|
|
268
|
+
* history) and how the runner broadcasts a reset to attached
|
|
269
|
+
* mirrors, in lockstep with the wipe.
|
|
266
270
|
*
|
|
267
271
|
* Safe to call only when no turn is in flight — callers should abort
|
|
268
272
|
* their AbortController and await any pending runTurn() first.
|
|
269
273
|
*/
|
|
270
274
|
clear() {
|
|
271
275
|
this.events.length = 0;
|
|
276
|
+
const snapshot = [...this.clearListeners];
|
|
277
|
+
for (const fn of snapshot) {
|
|
278
|
+
try {
|
|
279
|
+
fn();
|
|
280
|
+
} catch {
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Subscribe to {@link clear}. Fires synchronously after the events array
|
|
286
|
+
* empties, so a listener reading the log observes the post-wipe state.
|
|
287
|
+
* Returns the unsubscribe callback.
|
|
288
|
+
*/
|
|
289
|
+
onClear(fn) {
|
|
290
|
+
this.clearListeners.add(fn);
|
|
291
|
+
return () => this.clearListeners.delete(fn);
|
|
272
292
|
}
|
|
273
293
|
asReader() {
|
|
274
294
|
return this;
|
|
@@ -1583,11 +1603,11 @@ function build(tokens, src) {
|
|
|
1583
1603
|
if (!tok.selfClose)
|
|
1584
1604
|
stack.push(node);
|
|
1585
1605
|
} else {
|
|
1586
|
-
const
|
|
1587
|
-
if (!
|
|
1606
|
+
const open2 = stack.pop();
|
|
1607
|
+
if (!open2)
|
|
1588
1608
|
fail(src, tok.pos, `unexpected closing tag </${tok.tag}>`);
|
|
1589
|
-
if (
|
|
1590
|
-
fail(src, tok.pos, `mismatched closing tag: expected </${
|
|
1609
|
+
if (open2.tag !== tok.tag) {
|
|
1610
|
+
fail(src, tok.pos, `mismatched closing tag: expected </${open2.tag}>, got </${tok.tag}>`);
|
|
1591
1611
|
}
|
|
1592
1612
|
}
|
|
1593
1613
|
}
|
|
@@ -2140,8 +2160,8 @@ var init_tools2 = __esm({
|
|
|
2140
2160
|
const parseResult = tool.inputSchema.safeParse(input);
|
|
2141
2161
|
if (!parseResult.success) {
|
|
2142
2162
|
const issues = parseResult.error.issues.map((iss) => {
|
|
2143
|
-
const
|
|
2144
|
-
return `${
|
|
2163
|
+
const path60 = iss.path.length ? iss.path.join(".") : "(root)";
|
|
2164
|
+
return `${path60}: ${iss.message}`;
|
|
2145
2165
|
}).join("; ");
|
|
2146
2166
|
throw new Error(`Invalid input for ${name}: ${issues}`);
|
|
2147
2167
|
}
|
|
@@ -2813,19 +2833,25 @@ var init_logger = __esm({
|
|
|
2813
2833
|
}
|
|
2814
2834
|
});
|
|
2815
2835
|
function wrapWithPolicy(inner, engine, getToolRule) {
|
|
2836
|
+
const policyDecision = (call) => {
|
|
2837
|
+
const policy = engine.check(call);
|
|
2838
|
+
if (policy)
|
|
2839
|
+
return policy;
|
|
2840
|
+
return evaluateToolRule(getToolRule(call.name), call);
|
|
2841
|
+
};
|
|
2816
2842
|
return new Proxy(inner, {
|
|
2817
2843
|
get(target, prop, receiver) {
|
|
2818
2844
|
if (prop === "check") {
|
|
2819
2845
|
return async (call, ctx) => {
|
|
2820
|
-
const
|
|
2821
|
-
if (
|
|
2822
|
-
return
|
|
2823
|
-
const toolDecision = evaluateToolRule(getToolRule(call.name), call);
|
|
2824
|
-
if (toolDecision)
|
|
2825
|
-
return toolDecision;
|
|
2846
|
+
const decided = policyDecision(call);
|
|
2847
|
+
if (decided)
|
|
2848
|
+
return decided;
|
|
2826
2849
|
return target.check(call, ctx);
|
|
2827
2850
|
};
|
|
2828
2851
|
}
|
|
2852
|
+
if (prop === "policyCheck") {
|
|
2853
|
+
return async (call) => policyDecision(call);
|
|
2854
|
+
}
|
|
2829
2855
|
return Reflect.get(target, prop, receiver);
|
|
2830
2856
|
}
|
|
2831
2857
|
});
|
|
@@ -3007,6 +3033,18 @@ var init_session = __esm({
|
|
|
3007
3033
|
setApprovalResolver(resolver2) {
|
|
3008
3034
|
this.approvalResolver = resolver2;
|
|
3009
3035
|
}
|
|
3036
|
+
/**
|
|
3037
|
+
* `SessionLike.reset` — the authoritative `/new`. Clears the event log;
|
|
3038
|
+
* the log's clear listeners propagate the wipe to whatever observes it
|
|
3039
|
+
* (the persistence sidecar truncates its JSONL so `--resume` sees an
|
|
3040
|
+
* empty session; a wrapping RunnerServer broadcasts a reset so attached
|
|
3041
|
+
* mirrors clear in lockstep). Registries, resolvers, and the active
|
|
3042
|
+
* provider survive — only the conversation context vanishes. Callers
|
|
3043
|
+
* must abort any in-flight turn first (same contract as `log.clear()`).
|
|
3044
|
+
*/
|
|
3045
|
+
async reset() {
|
|
3046
|
+
this.log.clear();
|
|
3047
|
+
}
|
|
3010
3048
|
/**
|
|
3011
3049
|
* Graceful shutdown: fire every plugin's `onShutdown` hook, then abort
|
|
3012
3050
|
* the session. Idempotent — safe to call multiple times (subsequent
|
|
@@ -3746,7 +3784,7 @@ async function readIndex(dir = defaultSessionsDir()) {
|
|
|
3746
3784
|
}));
|
|
3747
3785
|
return metas.filter((_2, index) => checks[index]).sort((a2, b3) => b3.lastActivity.localeCompare(a2.lastActivity));
|
|
3748
3786
|
}
|
|
3749
|
-
async function restoreEvents(sessionId, dir = defaultSessionsDir()) {
|
|
3787
|
+
async function restoreEvents(sessionId, dir = defaultSessionsDir(), logger = createLogger()) {
|
|
3750
3788
|
const logPath = path3.join(dir, `${sessionId}.jsonl`);
|
|
3751
3789
|
let raw;
|
|
3752
3790
|
try {
|
|
@@ -3755,12 +3793,40 @@ async function restoreEvents(sessionId, dir = defaultSessionsDir()) {
|
|
|
3755
3793
|
throw new Error(`Session not found: ${sessionId}`);
|
|
3756
3794
|
}
|
|
3757
3795
|
const events = [];
|
|
3796
|
+
let corruptLines = 0;
|
|
3758
3797
|
for (const line of raw.split("\n")) {
|
|
3759
3798
|
if (!line.trim())
|
|
3760
3799
|
continue;
|
|
3761
3800
|
try {
|
|
3762
3801
|
events.push(JSON.parse(line));
|
|
3763
3802
|
} catch {
|
|
3803
|
+
corruptLines += 1;
|
|
3804
|
+
}
|
|
3805
|
+
}
|
|
3806
|
+
let resequenced = 0;
|
|
3807
|
+
for (let i2 = 0; i2 < events.length; i2 += 1) {
|
|
3808
|
+
if (events[i2].seq !== i2) {
|
|
3809
|
+
events[i2] = { ...events[i2], seq: i2 };
|
|
3810
|
+
resequenced += 1;
|
|
3811
|
+
}
|
|
3812
|
+
}
|
|
3813
|
+
if (corruptLines > 0 || resequenced > 0) {
|
|
3814
|
+
logger.warn("session log restored with gaps \u2014 re-sequenced to keep full history replayable", {
|
|
3815
|
+
sessionId,
|
|
3816
|
+
path: logPath,
|
|
3817
|
+
corruptLines,
|
|
3818
|
+
resequencedEvents: resequenced,
|
|
3819
|
+
restoredEvents: events.length
|
|
3820
|
+
});
|
|
3821
|
+
try {
|
|
3822
|
+
const repaired = events.map((e3) => JSON.stringify(e3) + "\n").join("");
|
|
3823
|
+
await writeFileAtomic(logPath, repaired);
|
|
3824
|
+
} catch (err) {
|
|
3825
|
+
logger.warn("failed to rewrite repaired session log on disk", {
|
|
3826
|
+
sessionId,
|
|
3827
|
+
path: logPath,
|
|
3828
|
+
error: err instanceof Error ? err.message : String(err)
|
|
3829
|
+
});
|
|
3764
3830
|
}
|
|
3765
3831
|
}
|
|
3766
3832
|
return events;
|
|
@@ -3784,6 +3850,7 @@ function isSessionMeta(v3) {
|
|
|
3784
3850
|
var SessionPersistence;
|
|
3785
3851
|
var init_persistence = __esm({
|
|
3786
3852
|
"../core/dist/sessions/persistence.js"() {
|
|
3853
|
+
init_logger();
|
|
3787
3854
|
SessionPersistence = class {
|
|
3788
3855
|
dir;
|
|
3789
3856
|
id;
|
|
@@ -3797,9 +3864,17 @@ var init_persistence = __esm({
|
|
|
3797
3864
|
*/
|
|
3798
3865
|
writeQueue = createMutex();
|
|
3799
3866
|
closed = false;
|
|
3867
|
+
logger;
|
|
3868
|
+
/**
|
|
3869
|
+
* Latched while event-log writes are failing. Doubles as the warn-once
|
|
3870
|
+
* gate: only the first failure of a streak logs; a subsequent successful
|
|
3871
|
+
* write clears the latch (and re-arms the warning).
|
|
3872
|
+
*/
|
|
3873
|
+
writeDegraded = false;
|
|
3800
3874
|
constructor(opts) {
|
|
3801
3875
|
this.dir = opts.dir ?? defaultSessionsDir();
|
|
3802
3876
|
this.id = String(opts.sessionId);
|
|
3877
|
+
this.logger = opts.logger ?? createLogger();
|
|
3803
3878
|
this.logPath = path3.join(this.dir, `${this.id}.jsonl`);
|
|
3804
3879
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3805
3880
|
this.meta = {
|
|
@@ -3817,6 +3892,12 @@ var init_persistence = __esm({
|
|
|
3817
3892
|
* Subscribe to the log; returns the unsubscribe callback. The first
|
|
3818
3893
|
* call also writes the initial index row so `moxxy resume` lists
|
|
3819
3894
|
* the session before any events arrive.
|
|
3895
|
+
*
|
|
3896
|
+
* Also subscribes to the log's `clear()`, truncating the JSONL in
|
|
3897
|
+
* lockstep so a `/new` wipe can't resurrect on `--resume`. The
|
|
3898
|
+
* session keeps its id and file: post-reset events restart at seq 0
|
|
3899
|
+
* in the same (now empty) JSONL, matching how the in-memory log
|
|
3900
|
+
* reuses the same Session object.
|
|
3820
3901
|
*/
|
|
3821
3902
|
attach(log) {
|
|
3822
3903
|
void this.ensureDir().then(() => this.ensureLogFile()).then(() => this.scheduleIndexWrite()).catch(() => void 0);
|
|
@@ -3825,9 +3906,15 @@ var init_persistence = __esm({
|
|
|
3825
3906
|
return;
|
|
3826
3907
|
this.enqueueAppend(event);
|
|
3827
3908
|
});
|
|
3909
|
+
const unsubClear = log.onClear(() => {
|
|
3910
|
+
if (this.closed)
|
|
3911
|
+
return;
|
|
3912
|
+
this.enqueueTruncate();
|
|
3913
|
+
});
|
|
3828
3914
|
return () => {
|
|
3829
3915
|
this.closed = true;
|
|
3830
3916
|
unsub();
|
|
3917
|
+
unsubClear();
|
|
3831
3918
|
this.scheduleIndexWrite();
|
|
3832
3919
|
};
|
|
3833
3920
|
}
|
|
@@ -3853,7 +3940,48 @@ var init_persistence = __esm({
|
|
|
3853
3940
|
};
|
|
3854
3941
|
this.scheduleIndexWrite();
|
|
3855
3942
|
const line = JSON.stringify(event) + "\n";
|
|
3856
|
-
void this.writeQueue.run(() => promises.appendFile(this.logPath, line, "utf8")).catch(() =>
|
|
3943
|
+
void this.writeQueue.run(() => promises.appendFile(this.logPath, line, "utf8")).then(() => this.noteWriteOk()).catch((err) => this.noteWriteFailure("append", err));
|
|
3944
|
+
}
|
|
3945
|
+
/**
|
|
3946
|
+
* True while event-log writes are failing (history is no longer being
|
|
3947
|
+
* persisted). Cleared automatically by the next successful write.
|
|
3948
|
+
*/
|
|
3949
|
+
get degraded() {
|
|
3950
|
+
return this.writeDegraded;
|
|
3951
|
+
}
|
|
3952
|
+
noteWriteOk() {
|
|
3953
|
+
if (!this.writeDegraded)
|
|
3954
|
+
return;
|
|
3955
|
+
this.writeDegraded = false;
|
|
3956
|
+
this.logger.info("session event-log writes recovered", { path: this.logPath });
|
|
3957
|
+
}
|
|
3958
|
+
noteWriteFailure(op, err) {
|
|
3959
|
+
const alreadyDegraded = this.writeDegraded;
|
|
3960
|
+
this.writeDegraded = true;
|
|
3961
|
+
if (alreadyDegraded)
|
|
3962
|
+
return;
|
|
3963
|
+
this.logger.warn("session event-log write failed \u2014 history persistence degraded (resume will miss these events)", {
|
|
3964
|
+
op,
|
|
3965
|
+
path: this.logPath,
|
|
3966
|
+
sessionId: this.id,
|
|
3967
|
+
error: err instanceof Error ? err.message : String(err)
|
|
3968
|
+
});
|
|
3969
|
+
}
|
|
3970
|
+
/**
|
|
3971
|
+
* Mirror a `log.clear()` on disk: truncate the JSONL and reset the
|
|
3972
|
+
* sidecar's counters. Rides the same write queue as appends, so
|
|
3973
|
+
* pre-clear appends flush first and post-clear appends land in the
|
|
3974
|
+
* fresh (empty) file — ordering matches the in-memory log exactly.
|
|
3975
|
+
*/
|
|
3976
|
+
enqueueTruncate() {
|
|
3977
|
+
this.meta = {
|
|
3978
|
+
...this.meta,
|
|
3979
|
+
eventCount: 0,
|
|
3980
|
+
firstPrompt: null,
|
|
3981
|
+
lastActivity: (/* @__PURE__ */ new Date()).toISOString()
|
|
3982
|
+
};
|
|
3983
|
+
this.scheduleIndexWrite();
|
|
3984
|
+
void this.writeQueue.run(() => promises.writeFile(this.logPath, "", "utf8")).then(() => this.noteWriteOk()).catch((err) => this.noteWriteFailure("truncate", err));
|
|
3857
3985
|
}
|
|
3858
3986
|
scheduleIndexWrite() {
|
|
3859
3987
|
if (this.indexUpdateScheduled)
|
|
@@ -4303,7 +4431,7 @@ var require_jiti = __commonJS({
|
|
|
4303
4431
|
function V4() {
|
|
4304
4432
|
return 10 !== n3.getToken() ? (k3(3, [], [2, 5]), false) : (P3(false), 6 === n3.getToken() ? (I3(":"), T2(), U3() || k3(4, [], [2, 5])) : k3(5, [], [2, 5]), a3.pop(), true);
|
|
4305
4433
|
}
|
|
4306
|
-
function
|
|
4434
|
+
function z62() {
|
|
4307
4435
|
l3(), T2();
|
|
4308
4436
|
let e6 = false;
|
|
4309
4437
|
for (; 2 !== n3.getToken() && 17 !== n3.getToken(); ) {
|
|
@@ -4330,14 +4458,14 @@ var require_jiti = __commonJS({
|
|
|
4330
4458
|
case 3:
|
|
4331
4459
|
return G3();
|
|
4332
4460
|
case 1:
|
|
4333
|
-
return
|
|
4461
|
+
return z62();
|
|
4334
4462
|
case 10:
|
|
4335
4463
|
return P3(true);
|
|
4336
4464
|
default:
|
|
4337
4465
|
return J2();
|
|
4338
4466
|
}
|
|
4339
4467
|
}
|
|
4340
|
-
return r2(T2, "scanNext"), r2(k3, "handleError"), r2(P3, "parseString"), r2(J2, "parseLiteral"), r2(V4, "parseProperty"), r2(
|
|
4468
|
+
return r2(T2, "scanNext"), r2(k3, "handleError"), r2(P3, "parseString"), r2(J2, "parseLiteral"), r2(V4, "parseProperty"), r2(z62, "parseObject"), r2(G3, "parseArray"), r2(U3, "parseValue"), T2(), 17 === n3.getToken() ? !!i4.allowEmptyContent || (k3(4, [], []), false) : U3() ? (17 !== n3.getToken() && k3(9, [], []), true) : (k3(4, [], []), false);
|
|
4341
4469
|
}
|
|
4342
4470
|
new Array(W3).fill(0).map((e5, t4) => "\n" + " ".repeat(t4)), new Array(W3).fill(0).map((e5, t4) => "\r" + " ".repeat(t4)), new Array(W3).fill(0).map((e5, t4) => "\r\n" + " ".repeat(t4)), new Array(W3).fill(0).map((e5, t4) => "\n" + " ".repeat(t4)), new Array(W3).fill(0).map((e5, t4) => "\r" + " ".repeat(t4)), new Array(W3).fill(0).map((e5, t4) => "\r\n" + " ".repeat(t4)), (function(e5) {
|
|
4343
4471
|
e5.DEFAULT = { allowTrailingComma: false };
|
|
@@ -8054,17 +8182,17 @@ var require_visit = __commonJS({
|
|
|
8054
8182
|
visit.BREAK = BREAK;
|
|
8055
8183
|
visit.SKIP = SKIP;
|
|
8056
8184
|
visit.REMOVE = REMOVE;
|
|
8057
|
-
function visit_(key, node, visitor,
|
|
8058
|
-
const ctrl = callVisitor(key, node, visitor,
|
|
8185
|
+
function visit_(key, node, visitor, path60) {
|
|
8186
|
+
const ctrl = callVisitor(key, node, visitor, path60);
|
|
8059
8187
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
8060
|
-
replaceNode(key,
|
|
8061
|
-
return visit_(key, ctrl, visitor,
|
|
8188
|
+
replaceNode(key, path60, ctrl);
|
|
8189
|
+
return visit_(key, ctrl, visitor, path60);
|
|
8062
8190
|
}
|
|
8063
8191
|
if (typeof ctrl !== "symbol") {
|
|
8064
8192
|
if (identity.isCollection(node)) {
|
|
8065
|
-
|
|
8193
|
+
path60 = Object.freeze(path60.concat(node));
|
|
8066
8194
|
for (let i2 = 0; i2 < node.items.length; ++i2) {
|
|
8067
|
-
const ci = visit_(i2, node.items[i2], visitor,
|
|
8195
|
+
const ci = visit_(i2, node.items[i2], visitor, path60);
|
|
8068
8196
|
if (typeof ci === "number")
|
|
8069
8197
|
i2 = ci - 1;
|
|
8070
8198
|
else if (ci === BREAK)
|
|
@@ -8075,13 +8203,13 @@ var require_visit = __commonJS({
|
|
|
8075
8203
|
}
|
|
8076
8204
|
}
|
|
8077
8205
|
} else if (identity.isPair(node)) {
|
|
8078
|
-
|
|
8079
|
-
const ck = visit_("key", node.key, visitor,
|
|
8206
|
+
path60 = Object.freeze(path60.concat(node));
|
|
8207
|
+
const ck = visit_("key", node.key, visitor, path60);
|
|
8080
8208
|
if (ck === BREAK)
|
|
8081
8209
|
return BREAK;
|
|
8082
8210
|
else if (ck === REMOVE)
|
|
8083
8211
|
node.key = null;
|
|
8084
|
-
const cv = visit_("value", node.value, visitor,
|
|
8212
|
+
const cv = visit_("value", node.value, visitor, path60);
|
|
8085
8213
|
if (cv === BREAK)
|
|
8086
8214
|
return BREAK;
|
|
8087
8215
|
else if (cv === REMOVE)
|
|
@@ -8102,17 +8230,17 @@ var require_visit = __commonJS({
|
|
|
8102
8230
|
visitAsync.BREAK = BREAK;
|
|
8103
8231
|
visitAsync.SKIP = SKIP;
|
|
8104
8232
|
visitAsync.REMOVE = REMOVE;
|
|
8105
|
-
async function visitAsync_(key, node, visitor,
|
|
8106
|
-
const ctrl = await callVisitor(key, node, visitor,
|
|
8233
|
+
async function visitAsync_(key, node, visitor, path60) {
|
|
8234
|
+
const ctrl = await callVisitor(key, node, visitor, path60);
|
|
8107
8235
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
8108
|
-
replaceNode(key,
|
|
8109
|
-
return visitAsync_(key, ctrl, visitor,
|
|
8236
|
+
replaceNode(key, path60, ctrl);
|
|
8237
|
+
return visitAsync_(key, ctrl, visitor, path60);
|
|
8110
8238
|
}
|
|
8111
8239
|
if (typeof ctrl !== "symbol") {
|
|
8112
8240
|
if (identity.isCollection(node)) {
|
|
8113
|
-
|
|
8241
|
+
path60 = Object.freeze(path60.concat(node));
|
|
8114
8242
|
for (let i2 = 0; i2 < node.items.length; ++i2) {
|
|
8115
|
-
const ci = await visitAsync_(i2, node.items[i2], visitor,
|
|
8243
|
+
const ci = await visitAsync_(i2, node.items[i2], visitor, path60);
|
|
8116
8244
|
if (typeof ci === "number")
|
|
8117
8245
|
i2 = ci - 1;
|
|
8118
8246
|
else if (ci === BREAK)
|
|
@@ -8123,13 +8251,13 @@ var require_visit = __commonJS({
|
|
|
8123
8251
|
}
|
|
8124
8252
|
}
|
|
8125
8253
|
} else if (identity.isPair(node)) {
|
|
8126
|
-
|
|
8127
|
-
const ck = await visitAsync_("key", node.key, visitor,
|
|
8254
|
+
path60 = Object.freeze(path60.concat(node));
|
|
8255
|
+
const ck = await visitAsync_("key", node.key, visitor, path60);
|
|
8128
8256
|
if (ck === BREAK)
|
|
8129
8257
|
return BREAK;
|
|
8130
8258
|
else if (ck === REMOVE)
|
|
8131
8259
|
node.key = null;
|
|
8132
|
-
const cv = await visitAsync_("value", node.value, visitor,
|
|
8260
|
+
const cv = await visitAsync_("value", node.value, visitor, path60);
|
|
8133
8261
|
if (cv === BREAK)
|
|
8134
8262
|
return BREAK;
|
|
8135
8263
|
else if (cv === REMOVE)
|
|
@@ -8156,23 +8284,23 @@ var require_visit = __commonJS({
|
|
|
8156
8284
|
}
|
|
8157
8285
|
return visitor;
|
|
8158
8286
|
}
|
|
8159
|
-
function callVisitor(key, node, visitor,
|
|
8287
|
+
function callVisitor(key, node, visitor, path60) {
|
|
8160
8288
|
if (typeof visitor === "function")
|
|
8161
|
-
return visitor(key, node,
|
|
8289
|
+
return visitor(key, node, path60);
|
|
8162
8290
|
if (identity.isMap(node))
|
|
8163
|
-
return visitor.Map?.(key, node,
|
|
8291
|
+
return visitor.Map?.(key, node, path60);
|
|
8164
8292
|
if (identity.isSeq(node))
|
|
8165
|
-
return visitor.Seq?.(key, node,
|
|
8293
|
+
return visitor.Seq?.(key, node, path60);
|
|
8166
8294
|
if (identity.isPair(node))
|
|
8167
|
-
return visitor.Pair?.(key, node,
|
|
8295
|
+
return visitor.Pair?.(key, node, path60);
|
|
8168
8296
|
if (identity.isScalar(node))
|
|
8169
|
-
return visitor.Scalar?.(key, node,
|
|
8297
|
+
return visitor.Scalar?.(key, node, path60);
|
|
8170
8298
|
if (identity.isAlias(node))
|
|
8171
|
-
return visitor.Alias?.(key, node,
|
|
8299
|
+
return visitor.Alias?.(key, node, path60);
|
|
8172
8300
|
return void 0;
|
|
8173
8301
|
}
|
|
8174
|
-
function replaceNode(key,
|
|
8175
|
-
const parent =
|
|
8302
|
+
function replaceNode(key, path60, node) {
|
|
8303
|
+
const parent = path60[path60.length - 1];
|
|
8176
8304
|
if (identity.isCollection(parent)) {
|
|
8177
8305
|
parent.items[key] = node;
|
|
8178
8306
|
} else if (identity.isPair(parent)) {
|
|
@@ -8773,10 +8901,10 @@ var require_Collection = __commonJS({
|
|
|
8773
8901
|
var createNode2 = require_createNode();
|
|
8774
8902
|
var identity = require_identity();
|
|
8775
8903
|
var Node = require_Node();
|
|
8776
|
-
function collectionFromPath(schema,
|
|
8904
|
+
function collectionFromPath(schema, path60, value) {
|
|
8777
8905
|
let v3 = value;
|
|
8778
|
-
for (let i2 =
|
|
8779
|
-
const k3 =
|
|
8906
|
+
for (let i2 = path60.length - 1; i2 >= 0; --i2) {
|
|
8907
|
+
const k3 = path60[i2];
|
|
8780
8908
|
if (typeof k3 === "number" && Number.isInteger(k3) && k3 >= 0) {
|
|
8781
8909
|
const a2 = [];
|
|
8782
8910
|
a2[k3] = v3;
|
|
@@ -8795,7 +8923,7 @@ var require_Collection = __commonJS({
|
|
|
8795
8923
|
sourceObjects: /* @__PURE__ */ new Map()
|
|
8796
8924
|
});
|
|
8797
8925
|
}
|
|
8798
|
-
var isEmptyPath = (
|
|
8926
|
+
var isEmptyPath = (path60) => path60 == null || typeof path60 === "object" && !!path60[Symbol.iterator]().next().done;
|
|
8799
8927
|
var Collection = class extends Node.NodeBase {
|
|
8800
8928
|
constructor(type, schema) {
|
|
8801
8929
|
super(type);
|
|
@@ -8825,11 +8953,11 @@ var require_Collection = __commonJS({
|
|
|
8825
8953
|
* be a Pair instance or a `{ key, value }` object, which may not have a key
|
|
8826
8954
|
* that already exists in the map.
|
|
8827
8955
|
*/
|
|
8828
|
-
addIn(
|
|
8829
|
-
if (isEmptyPath(
|
|
8956
|
+
addIn(path60, value) {
|
|
8957
|
+
if (isEmptyPath(path60))
|
|
8830
8958
|
this.add(value);
|
|
8831
8959
|
else {
|
|
8832
|
-
const [key, ...rest] =
|
|
8960
|
+
const [key, ...rest] = path60;
|
|
8833
8961
|
const node = this.get(key, true);
|
|
8834
8962
|
if (identity.isCollection(node))
|
|
8835
8963
|
node.addIn(rest, value);
|
|
@@ -8843,8 +8971,8 @@ var require_Collection = __commonJS({
|
|
|
8843
8971
|
* Removes a value from the collection.
|
|
8844
8972
|
* @returns `true` if the item was found and removed.
|
|
8845
8973
|
*/
|
|
8846
|
-
deleteIn(
|
|
8847
|
-
const [key, ...rest] =
|
|
8974
|
+
deleteIn(path60) {
|
|
8975
|
+
const [key, ...rest] = path60;
|
|
8848
8976
|
if (rest.length === 0)
|
|
8849
8977
|
return this.delete(key);
|
|
8850
8978
|
const node = this.get(key, true);
|
|
@@ -8858,8 +8986,8 @@ var require_Collection = __commonJS({
|
|
|
8858
8986
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
8859
8987
|
* `true` (collections are always returned intact).
|
|
8860
8988
|
*/
|
|
8861
|
-
getIn(
|
|
8862
|
-
const [key, ...rest] =
|
|
8989
|
+
getIn(path60, keepScalar) {
|
|
8990
|
+
const [key, ...rest] = path60;
|
|
8863
8991
|
const node = this.get(key, true);
|
|
8864
8992
|
if (rest.length === 0)
|
|
8865
8993
|
return !keepScalar && identity.isScalar(node) ? node.value : node;
|
|
@@ -8877,8 +9005,8 @@ var require_Collection = __commonJS({
|
|
|
8877
9005
|
/**
|
|
8878
9006
|
* Checks if the collection includes a value with the key `key`.
|
|
8879
9007
|
*/
|
|
8880
|
-
hasIn(
|
|
8881
|
-
const [key, ...rest] =
|
|
9008
|
+
hasIn(path60) {
|
|
9009
|
+
const [key, ...rest] = path60;
|
|
8882
9010
|
if (rest.length === 0)
|
|
8883
9011
|
return this.has(key);
|
|
8884
9012
|
const node = this.get(key, true);
|
|
@@ -8888,8 +9016,8 @@ var require_Collection = __commonJS({
|
|
|
8888
9016
|
* Sets a value in this collection. For `!!set`, `value` needs to be a
|
|
8889
9017
|
* boolean to add/remove the item from the set.
|
|
8890
9018
|
*/
|
|
8891
|
-
setIn(
|
|
8892
|
-
const [key, ...rest] =
|
|
9019
|
+
setIn(path60, value) {
|
|
9020
|
+
const [key, ...rest] = path60;
|
|
8893
9021
|
if (rest.length === 0) {
|
|
8894
9022
|
this.set(key, value);
|
|
8895
9023
|
} else {
|
|
@@ -11369,9 +11497,9 @@ var require_Document = __commonJS({
|
|
|
11369
11497
|
this.contents.add(value);
|
|
11370
11498
|
}
|
|
11371
11499
|
/** Adds a value to the document. */
|
|
11372
|
-
addIn(
|
|
11500
|
+
addIn(path60, value) {
|
|
11373
11501
|
if (assertCollection(this.contents))
|
|
11374
|
-
this.contents.addIn(
|
|
11502
|
+
this.contents.addIn(path60, value);
|
|
11375
11503
|
}
|
|
11376
11504
|
/**
|
|
11377
11505
|
* Create a new `Alias` node, ensuring that the target `node` has the required anchor.
|
|
@@ -11446,14 +11574,14 @@ var require_Document = __commonJS({
|
|
|
11446
11574
|
* Removes a value from the document.
|
|
11447
11575
|
* @returns `true` if the item was found and removed.
|
|
11448
11576
|
*/
|
|
11449
|
-
deleteIn(
|
|
11450
|
-
if (Collection.isEmptyPath(
|
|
11577
|
+
deleteIn(path60) {
|
|
11578
|
+
if (Collection.isEmptyPath(path60)) {
|
|
11451
11579
|
if (this.contents == null)
|
|
11452
11580
|
return false;
|
|
11453
11581
|
this.contents = null;
|
|
11454
11582
|
return true;
|
|
11455
11583
|
}
|
|
11456
|
-
return assertCollection(this.contents) ? this.contents.deleteIn(
|
|
11584
|
+
return assertCollection(this.contents) ? this.contents.deleteIn(path60) : false;
|
|
11457
11585
|
}
|
|
11458
11586
|
/**
|
|
11459
11587
|
* Returns item at `key`, or `undefined` if not found. By default unwraps
|
|
@@ -11468,10 +11596,10 @@ var require_Document = __commonJS({
|
|
|
11468
11596
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
11469
11597
|
* `true` (collections are always returned intact).
|
|
11470
11598
|
*/
|
|
11471
|
-
getIn(
|
|
11472
|
-
if (Collection.isEmptyPath(
|
|
11599
|
+
getIn(path60, keepScalar) {
|
|
11600
|
+
if (Collection.isEmptyPath(path60))
|
|
11473
11601
|
return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
|
|
11474
|
-
return identity.isCollection(this.contents) ? this.contents.getIn(
|
|
11602
|
+
return identity.isCollection(this.contents) ? this.contents.getIn(path60, keepScalar) : void 0;
|
|
11475
11603
|
}
|
|
11476
11604
|
/**
|
|
11477
11605
|
* Checks if the document includes a value with the key `key`.
|
|
@@ -11482,10 +11610,10 @@ var require_Document = __commonJS({
|
|
|
11482
11610
|
/**
|
|
11483
11611
|
* Checks if the document includes a value at `path`.
|
|
11484
11612
|
*/
|
|
11485
|
-
hasIn(
|
|
11486
|
-
if (Collection.isEmptyPath(
|
|
11613
|
+
hasIn(path60) {
|
|
11614
|
+
if (Collection.isEmptyPath(path60))
|
|
11487
11615
|
return this.contents !== void 0;
|
|
11488
|
-
return identity.isCollection(this.contents) ? this.contents.hasIn(
|
|
11616
|
+
return identity.isCollection(this.contents) ? this.contents.hasIn(path60) : false;
|
|
11489
11617
|
}
|
|
11490
11618
|
/**
|
|
11491
11619
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
@@ -11502,13 +11630,13 @@ var require_Document = __commonJS({
|
|
|
11502
11630
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
11503
11631
|
* boolean to add/remove the item from the set.
|
|
11504
11632
|
*/
|
|
11505
|
-
setIn(
|
|
11506
|
-
if (Collection.isEmptyPath(
|
|
11633
|
+
setIn(path60, value) {
|
|
11634
|
+
if (Collection.isEmptyPath(path60)) {
|
|
11507
11635
|
this.contents = value;
|
|
11508
11636
|
} else if (this.contents == null) {
|
|
11509
|
-
this.contents = Collection.collectionFromPath(this.schema, Array.from(
|
|
11637
|
+
this.contents = Collection.collectionFromPath(this.schema, Array.from(path60), value);
|
|
11510
11638
|
} else if (assertCollection(this.contents)) {
|
|
11511
|
-
this.contents.setIn(
|
|
11639
|
+
this.contents.setIn(path60, value);
|
|
11512
11640
|
}
|
|
11513
11641
|
}
|
|
11514
11642
|
/**
|
|
@@ -13448,9 +13576,9 @@ var require_cst_visit = __commonJS({
|
|
|
13448
13576
|
visit.BREAK = BREAK;
|
|
13449
13577
|
visit.SKIP = SKIP;
|
|
13450
13578
|
visit.REMOVE = REMOVE;
|
|
13451
|
-
visit.itemAtPath = (cst,
|
|
13579
|
+
visit.itemAtPath = (cst, path60) => {
|
|
13452
13580
|
let item = cst;
|
|
13453
|
-
for (const [field, index] of
|
|
13581
|
+
for (const [field, index] of path60) {
|
|
13454
13582
|
const tok = item?.[field];
|
|
13455
13583
|
if (tok && "items" in tok) {
|
|
13456
13584
|
item = tok.items[index];
|
|
@@ -13459,23 +13587,23 @@ var require_cst_visit = __commonJS({
|
|
|
13459
13587
|
}
|
|
13460
13588
|
return item;
|
|
13461
13589
|
};
|
|
13462
|
-
visit.parentCollection = (cst,
|
|
13463
|
-
const parent = visit.itemAtPath(cst,
|
|
13464
|
-
const field =
|
|
13590
|
+
visit.parentCollection = (cst, path60) => {
|
|
13591
|
+
const parent = visit.itemAtPath(cst, path60.slice(0, -1));
|
|
13592
|
+
const field = path60[path60.length - 1][0];
|
|
13465
13593
|
const coll = parent?.[field];
|
|
13466
13594
|
if (coll && "items" in coll)
|
|
13467
13595
|
return coll;
|
|
13468
13596
|
throw new Error("Parent collection not found");
|
|
13469
13597
|
};
|
|
13470
|
-
function _visit(
|
|
13471
|
-
let ctrl = visitor(item,
|
|
13598
|
+
function _visit(path60, item, visitor) {
|
|
13599
|
+
let ctrl = visitor(item, path60);
|
|
13472
13600
|
if (typeof ctrl === "symbol")
|
|
13473
13601
|
return ctrl;
|
|
13474
13602
|
for (const field of ["key", "value"]) {
|
|
13475
13603
|
const token = item[field];
|
|
13476
13604
|
if (token && "items" in token) {
|
|
13477
13605
|
for (let i2 = 0; i2 < token.items.length; ++i2) {
|
|
13478
|
-
const ci = _visit(Object.freeze(
|
|
13606
|
+
const ci = _visit(Object.freeze(path60.concat([[field, i2]])), token.items[i2], visitor);
|
|
13479
13607
|
if (typeof ci === "number")
|
|
13480
13608
|
i2 = ci - 1;
|
|
13481
13609
|
else if (ci === BREAK)
|
|
@@ -13486,10 +13614,10 @@ var require_cst_visit = __commonJS({
|
|
|
13486
13614
|
}
|
|
13487
13615
|
}
|
|
13488
13616
|
if (typeof ctrl === "function" && field === "key")
|
|
13489
|
-
ctrl = ctrl(item,
|
|
13617
|
+
ctrl = ctrl(item, path60);
|
|
13490
13618
|
}
|
|
13491
13619
|
}
|
|
13492
|
-
return typeof ctrl === "function" ? ctrl(item,
|
|
13620
|
+
return typeof ctrl === "function" ? ctrl(item, path60) : ctrl;
|
|
13493
13621
|
}
|
|
13494
13622
|
exports.visit = visit;
|
|
13495
13623
|
}
|
|
@@ -16211,14 +16339,14 @@ var require_url_state_machine = __commonJS({
|
|
|
16211
16339
|
return url2.replace(/\u0009|\u000A|\u000D/g, "");
|
|
16212
16340
|
}
|
|
16213
16341
|
function shortenPath(url2) {
|
|
16214
|
-
const
|
|
16215
|
-
if (
|
|
16342
|
+
const path60 = url2.path;
|
|
16343
|
+
if (path60.length === 0) {
|
|
16216
16344
|
return;
|
|
16217
16345
|
}
|
|
16218
|
-
if (url2.scheme === "file" &&
|
|
16346
|
+
if (url2.scheme === "file" && path60.length === 1 && isNormalizedWindowsDriveLetter(path60[0])) {
|
|
16219
16347
|
return;
|
|
16220
16348
|
}
|
|
16221
|
-
|
|
16349
|
+
path60.pop();
|
|
16222
16350
|
}
|
|
16223
16351
|
function includesCredentials(url2) {
|
|
16224
16352
|
return url2.username !== "" || url2.password !== "";
|
|
@@ -22721,25 +22849,25 @@ function kt(e3, t2, r2, o2, n2, a2) {
|
|
|
22721
22849
|
m(e4);
|
|
22722
22850
|
}
|
|
22723
22851
|
function B2() {
|
|
22724
|
-
return v3 = "closed", r2 ? L3() :
|
|
22852
|
+
return v3 = "closed", r2 ? L3() : z62((() => (Ge(t2) && (T2 = rt(t2), R4 = t2._state), T2 || "closed" === R4 ? c(void 0) : "erroring" === R4 || "errored" === R4 ? d(_2) : (T2 = true, l2.close()))), false, void 0), null;
|
|
22725
22853
|
}
|
|
22726
22854
|
function A3(e4) {
|
|
22727
|
-
return w4 || (v3 = "errored", s2 = e4, o2 ? L3(true, e4) :
|
|
22855
|
+
return w4 || (v3 = "errored", s2 = e4, o2 ? L3(true, e4) : z62((() => l2.abort(e4)), true, e4)), null;
|
|
22728
22856
|
}
|
|
22729
22857
|
function j3(e4) {
|
|
22730
|
-
return S2 || (R4 = "errored", _2 = e4, n2 ? L3(true, e4) :
|
|
22858
|
+
return S2 || (R4 = "errored", _2 = e4, n2 ? L3(true, e4) : z62((() => i2.cancel(e4)), true, e4)), null;
|
|
22731
22859
|
}
|
|
22732
22860
|
if (void 0 !== a2 && (k3 = () => {
|
|
22733
22861
|
const e4 = void 0 !== a2.reason ? a2.reason : new Wt("Aborted", "AbortError"), t3 = [];
|
|
22734
|
-
o2 || t3.push((() => "writable" === R4 ? l2.abort(e4) : c(void 0))), n2 || t3.push((() => "readable" === v3 ? i2.cancel(e4) : c(void 0))),
|
|
22862
|
+
o2 || t3.push((() => "writable" === R4 ? l2.abort(e4) : c(void 0))), n2 || t3.push((() => "readable" === v3 ? i2.cancel(e4) : c(void 0))), z62((() => Promise.all(t3.map(((e5) => e5())))), true, e4);
|
|
22735
22863
|
}, a2.aborted ? k3() : a2.addEventListener("abort", k3)), Vt(e3) && (v3 = e3._state, s2 = e3._storedError), Ge(t2) && (R4 = t2._state, _2 = t2._storedError, T2 = rt(t2)), Vt(e3) && Ge(t2) && (q3 = true, g2()), "errored" === v3) A3(s2);
|
|
22736
22864
|
else if ("erroring" === R4 || "errored" === R4) j3(_2);
|
|
22737
22865
|
else if ("closed" === v3) B2();
|
|
22738
22866
|
else if (T2 || "closed" === R4) {
|
|
22739
22867
|
const e4 = new TypeError("the destination writable stream closed before all data could be piped to it");
|
|
22740
|
-
n2 ? L3(true, e4) :
|
|
22868
|
+
n2 ? L3(true, e4) : z62((() => i2.cancel(e4)), true, e4);
|
|
22741
22869
|
}
|
|
22742
|
-
function
|
|
22870
|
+
function z62(e4, t3, r3) {
|
|
22743
22871
|
function o3() {
|
|
22744
22872
|
return "writable" !== R4 || T2 ? n3() : h((function() {
|
|
22745
22873
|
let e5;
|
|
@@ -22754,7 +22882,7 @@ function kt(e3, t2, r2, o2, n2, a2) {
|
|
|
22754
22882
|
w4 || (w4 = true, q3 ? o3() : h(C3, o3));
|
|
22755
22883
|
}
|
|
22756
22884
|
function L3(e4, t3) {
|
|
22757
|
-
|
|
22885
|
+
z62(void 0, e4, t3);
|
|
22758
22886
|
}
|
|
22759
22887
|
function F3(e4, t3) {
|
|
22760
22888
|
return S2 = true, l2.releaseLock(), i2.releaseLock(), void 0 !== a2 && a2.removeEventListener("abort", k3), e4 ? W3(t3) : P3(void 0), null;
|
|
@@ -25441,14 +25569,14 @@ __export(fileFromPath_exports, {
|
|
|
25441
25569
|
fileFromPathSync: () => fileFromPathSync,
|
|
25442
25570
|
isFile: () => isFile
|
|
25443
25571
|
});
|
|
25444
|
-
function createFileFromPath(
|
|
25572
|
+
function createFileFromPath(path60, { mtimeMs, size }, filenameOrOptions, options = {}) {
|
|
25445
25573
|
let filename;
|
|
25446
25574
|
if (isPlainObject_default2(filenameOrOptions)) {
|
|
25447
25575
|
[options, filename] = [filenameOrOptions, void 0];
|
|
25448
25576
|
} else {
|
|
25449
25577
|
filename = filenameOrOptions;
|
|
25450
25578
|
}
|
|
25451
|
-
const file = new FileFromPath({ path:
|
|
25579
|
+
const file = new FileFromPath({ path: path60, size, lastModified: mtimeMs });
|
|
25452
25580
|
if (!filename) {
|
|
25453
25581
|
filename = file.name;
|
|
25454
25582
|
}
|
|
@@ -25457,13 +25585,13 @@ function createFileFromPath(path59, { mtimeMs, size }, filenameOrOptions, option
|
|
|
25457
25585
|
lastModified: file.lastModified
|
|
25458
25586
|
});
|
|
25459
25587
|
}
|
|
25460
|
-
function fileFromPathSync(
|
|
25461
|
-
const stats = statSync(
|
|
25462
|
-
return createFileFromPath(
|
|
25588
|
+
function fileFromPathSync(path60, filenameOrOptions, options = {}) {
|
|
25589
|
+
const stats = statSync(path60);
|
|
25590
|
+
return createFileFromPath(path60, stats, filenameOrOptions, options);
|
|
25463
25591
|
}
|
|
25464
|
-
async function fileFromPath2(
|
|
25465
|
-
const stats = await promises.stat(
|
|
25466
|
-
return createFileFromPath(
|
|
25592
|
+
async function fileFromPath2(path60, filenameOrOptions, options) {
|
|
25593
|
+
const stats = await promises.stat(path60);
|
|
25594
|
+
return createFileFromPath(path60, stats, filenameOrOptions, options);
|
|
25467
25595
|
}
|
|
25468
25596
|
var import_node_domexception, __classPrivateFieldSet4, __classPrivateFieldGet5, _FileFromPath_path, _FileFromPath_start, MESSAGE, FileFromPath;
|
|
25469
25597
|
var init_fileFromPath = __esm({
|
|
@@ -32919,7 +33047,7 @@ var require_bot = __commonJS({
|
|
|
32919
33047
|
} else
|
|
32920
33048
|
debugErr(error2);
|
|
32921
33049
|
debugErr(`Call to getUpdates failed, retrying in ${sleepSeconds} seconds ...`);
|
|
32922
|
-
await
|
|
33050
|
+
await sleep5(sleepSeconds);
|
|
32923
33051
|
}
|
|
32924
33052
|
};
|
|
32925
33053
|
exports.Bot = Bot3;
|
|
@@ -32939,7 +33067,7 @@ var require_bot = __commonJS({
|
|
|
32939
33067
|
} else if (error2.error_code === 429) {
|
|
32940
33068
|
const retryAfter = error2.parameters.retry_after;
|
|
32941
33069
|
if (typeof retryAfter === "number") {
|
|
32942
|
-
await
|
|
33070
|
+
await sleep5(retryAfter, signal);
|
|
32943
33071
|
lastDelay = INITIAL_DELAY;
|
|
32944
33072
|
} else {
|
|
32945
33073
|
delay = true;
|
|
@@ -32949,7 +33077,7 @@ var require_bot = __commonJS({
|
|
|
32949
33077
|
}
|
|
32950
33078
|
if (delay) {
|
|
32951
33079
|
if (lastDelay !== INITIAL_DELAY) {
|
|
32952
|
-
await
|
|
33080
|
+
await sleep5(lastDelay, signal);
|
|
32953
33081
|
}
|
|
32954
33082
|
const TWENTY_MINUTES = 20 * 60 * 1e3;
|
|
32955
33083
|
lastDelay = Math.min(TWENTY_MINUTES, 2 * lastDelay);
|
|
@@ -32973,7 +33101,7 @@ var require_bot = __commonJS({
|
|
|
32973
33101
|
}
|
|
32974
33102
|
return result.value;
|
|
32975
33103
|
}
|
|
32976
|
-
async function
|
|
33104
|
+
async function sleep5(seconds, signal) {
|
|
32977
33105
|
let handle2;
|
|
32978
33106
|
let reject;
|
|
32979
33107
|
function abort() {
|
|
@@ -41595,8 +41723,8 @@ var require_utils2 = __commonJS({
|
|
|
41595
41723
|
}
|
|
41596
41724
|
return ind;
|
|
41597
41725
|
}
|
|
41598
|
-
function removeDotSegments(
|
|
41599
|
-
let input =
|
|
41726
|
+
function removeDotSegments(path60) {
|
|
41727
|
+
let input = path60;
|
|
41600
41728
|
const output = [];
|
|
41601
41729
|
let nextSlash = -1;
|
|
41602
41730
|
let len = 0;
|
|
@@ -41847,8 +41975,8 @@ var require_schemes = __commonJS({
|
|
|
41847
41975
|
wsComponent.secure = void 0;
|
|
41848
41976
|
}
|
|
41849
41977
|
if (wsComponent.resourceName) {
|
|
41850
|
-
const [
|
|
41851
|
-
wsComponent.path =
|
|
41978
|
+
const [path60, query] = wsComponent.resourceName.split("?");
|
|
41979
|
+
wsComponent.path = path60 && path60 !== "/" ? path60 : void 0;
|
|
41852
41980
|
wsComponent.query = query;
|
|
41853
41981
|
wsComponent.resourceName = void 0;
|
|
41854
41982
|
}
|
|
@@ -46006,7 +46134,7 @@ var require_windows = __commonJS({
|
|
|
46006
46134
|
module.exports = isexe;
|
|
46007
46135
|
isexe.sync = sync;
|
|
46008
46136
|
var fs43 = __require("fs");
|
|
46009
|
-
function checkPathExt(
|
|
46137
|
+
function checkPathExt(path60, options) {
|
|
46010
46138
|
var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
|
|
46011
46139
|
if (!pathext) {
|
|
46012
46140
|
return true;
|
|
@@ -46017,25 +46145,25 @@ var require_windows = __commonJS({
|
|
|
46017
46145
|
}
|
|
46018
46146
|
for (var i2 = 0; i2 < pathext.length; i2++) {
|
|
46019
46147
|
var p3 = pathext[i2].toLowerCase();
|
|
46020
|
-
if (p3 &&
|
|
46148
|
+
if (p3 && path60.substr(-p3.length).toLowerCase() === p3) {
|
|
46021
46149
|
return true;
|
|
46022
46150
|
}
|
|
46023
46151
|
}
|
|
46024
46152
|
return false;
|
|
46025
46153
|
}
|
|
46026
|
-
function checkStat(
|
|
46027
|
-
if (!
|
|
46154
|
+
function checkStat(stat2, path60, options) {
|
|
46155
|
+
if (!stat2.isSymbolicLink() && !stat2.isFile()) {
|
|
46028
46156
|
return false;
|
|
46029
46157
|
}
|
|
46030
|
-
return checkPathExt(
|
|
46158
|
+
return checkPathExt(path60, options);
|
|
46031
46159
|
}
|
|
46032
|
-
function isexe(
|
|
46033
|
-
fs43.stat(
|
|
46034
|
-
cb(er2, er2 ? false : checkStat(
|
|
46160
|
+
function isexe(path60, options, cb) {
|
|
46161
|
+
fs43.stat(path60, function(er2, stat2) {
|
|
46162
|
+
cb(er2, er2 ? false : checkStat(stat2, path60, options));
|
|
46035
46163
|
});
|
|
46036
46164
|
}
|
|
46037
|
-
function sync(
|
|
46038
|
-
return checkStat(fs43.statSync(
|
|
46165
|
+
function sync(path60, options) {
|
|
46166
|
+
return checkStat(fs43.statSync(path60), path60, options);
|
|
46039
46167
|
}
|
|
46040
46168
|
}
|
|
46041
46169
|
});
|
|
@@ -46046,21 +46174,21 @@ var require_mode = __commonJS({
|
|
|
46046
46174
|
module.exports = isexe;
|
|
46047
46175
|
isexe.sync = sync;
|
|
46048
46176
|
var fs43 = __require("fs");
|
|
46049
|
-
function isexe(
|
|
46050
|
-
fs43.stat(
|
|
46051
|
-
cb(er2, er2 ? false : checkStat(
|
|
46177
|
+
function isexe(path60, options, cb) {
|
|
46178
|
+
fs43.stat(path60, function(er2, stat2) {
|
|
46179
|
+
cb(er2, er2 ? false : checkStat(stat2, options));
|
|
46052
46180
|
});
|
|
46053
46181
|
}
|
|
46054
|
-
function sync(
|
|
46055
|
-
return checkStat(fs43.statSync(
|
|
46182
|
+
function sync(path60, options) {
|
|
46183
|
+
return checkStat(fs43.statSync(path60), options);
|
|
46056
46184
|
}
|
|
46057
|
-
function checkStat(
|
|
46058
|
-
return
|
|
46185
|
+
function checkStat(stat2, options) {
|
|
46186
|
+
return stat2.isFile() && checkMode(stat2, options);
|
|
46059
46187
|
}
|
|
46060
|
-
function checkMode(
|
|
46061
|
-
var mod =
|
|
46062
|
-
var uid =
|
|
46063
|
-
var gid =
|
|
46188
|
+
function checkMode(stat2, options) {
|
|
46189
|
+
var mod = stat2.mode;
|
|
46190
|
+
var uid = stat2.uid;
|
|
46191
|
+
var gid = stat2.gid;
|
|
46064
46192
|
var myUid = options.uid !== void 0 ? options.uid : process.getuid && process.getuid();
|
|
46065
46193
|
var myGid = options.gid !== void 0 ? options.gid : process.getgid && process.getgid();
|
|
46066
46194
|
var u2 = parseInt("100", 8);
|
|
@@ -46085,7 +46213,7 @@ var require_isexe = __commonJS({
|
|
|
46085
46213
|
}
|
|
46086
46214
|
module.exports = isexe;
|
|
46087
46215
|
isexe.sync = sync;
|
|
46088
|
-
function isexe(
|
|
46216
|
+
function isexe(path60, options, cb) {
|
|
46089
46217
|
if (typeof options === "function") {
|
|
46090
46218
|
cb = options;
|
|
46091
46219
|
options = {};
|
|
@@ -46095,7 +46223,7 @@ var require_isexe = __commonJS({
|
|
|
46095
46223
|
throw new TypeError("callback not provided");
|
|
46096
46224
|
}
|
|
46097
46225
|
return new Promise(function(resolve12, reject) {
|
|
46098
|
-
isexe(
|
|
46226
|
+
isexe(path60, options || {}, function(er2, is) {
|
|
46099
46227
|
if (er2) {
|
|
46100
46228
|
reject(er2);
|
|
46101
46229
|
} else {
|
|
@@ -46104,7 +46232,7 @@ var require_isexe = __commonJS({
|
|
|
46104
46232
|
});
|
|
46105
46233
|
});
|
|
46106
46234
|
}
|
|
46107
|
-
core(
|
|
46235
|
+
core(path60, options || {}, function(er2, is) {
|
|
46108
46236
|
if (er2) {
|
|
46109
46237
|
if (er2.code === "EACCES" || options && options.ignoreErrors) {
|
|
46110
46238
|
er2 = null;
|
|
@@ -46114,9 +46242,9 @@ var require_isexe = __commonJS({
|
|
|
46114
46242
|
cb(er2, is);
|
|
46115
46243
|
});
|
|
46116
46244
|
}
|
|
46117
|
-
function sync(
|
|
46245
|
+
function sync(path60, options) {
|
|
46118
46246
|
try {
|
|
46119
|
-
return core.sync(
|
|
46247
|
+
return core.sync(path60, options || {});
|
|
46120
46248
|
} catch (er2) {
|
|
46121
46249
|
if (options && options.ignoreErrors || er2.code === "EACCES") {
|
|
46122
46250
|
return false;
|
|
@@ -46132,7 +46260,7 @@ var require_isexe = __commonJS({
|
|
|
46132
46260
|
var require_which = __commonJS({
|
|
46133
46261
|
"../../node_modules/.pnpm/which@2.0.2/node_modules/which/which.js"(exports, module) {
|
|
46134
46262
|
var isWindows3 = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
|
|
46135
|
-
var
|
|
46263
|
+
var path60 = __require("path");
|
|
46136
46264
|
var COLON = isWindows3 ? ";" : ":";
|
|
46137
46265
|
var isexe = require_isexe();
|
|
46138
46266
|
var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
|
|
@@ -46170,7 +46298,7 @@ var require_which = __commonJS({
|
|
|
46170
46298
|
return opt.all && found.length ? resolve12(found) : reject(getNotFoundError(cmd));
|
|
46171
46299
|
const ppRaw = pathEnv[i2];
|
|
46172
46300
|
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
46173
|
-
const pCmd =
|
|
46301
|
+
const pCmd = path60.join(pathPart, cmd);
|
|
46174
46302
|
const p3 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
46175
46303
|
resolve12(subStep(p3, i2, 0));
|
|
46176
46304
|
});
|
|
@@ -46197,7 +46325,7 @@ var require_which = __commonJS({
|
|
|
46197
46325
|
for (let i2 = 0; i2 < pathEnv.length; i2++) {
|
|
46198
46326
|
const ppRaw = pathEnv[i2];
|
|
46199
46327
|
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
46200
|
-
const pCmd =
|
|
46328
|
+
const pCmd = path60.join(pathPart, cmd);
|
|
46201
46329
|
const p3 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
46202
46330
|
for (let j3 = 0; j3 < pathExt.length; j3++) {
|
|
46203
46331
|
const cur = p3 + pathExt[j3];
|
|
@@ -46243,7 +46371,7 @@ var require_path_key = __commonJS({
|
|
|
46243
46371
|
// ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.js
|
|
46244
46372
|
var require_resolveCommand = __commonJS({
|
|
46245
46373
|
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.js"(exports, module) {
|
|
46246
|
-
var
|
|
46374
|
+
var path60 = __require("path");
|
|
46247
46375
|
var which = require_which();
|
|
46248
46376
|
var getPathKey = require_path_key();
|
|
46249
46377
|
function resolveCommandAttempt(parsed, withoutPathExt) {
|
|
@@ -46261,7 +46389,7 @@ var require_resolveCommand = __commonJS({
|
|
|
46261
46389
|
try {
|
|
46262
46390
|
resolved = which.sync(parsed.command, {
|
|
46263
46391
|
path: env3[getPathKey({ env: env3 })],
|
|
46264
|
-
pathExt: withoutPathExt ?
|
|
46392
|
+
pathExt: withoutPathExt ? path60.delimiter : void 0
|
|
46265
46393
|
});
|
|
46266
46394
|
} catch (e3) {
|
|
46267
46395
|
} finally {
|
|
@@ -46270,7 +46398,7 @@ var require_resolveCommand = __commonJS({
|
|
|
46270
46398
|
}
|
|
46271
46399
|
}
|
|
46272
46400
|
if (resolved) {
|
|
46273
|
-
resolved =
|
|
46401
|
+
resolved = path60.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
|
|
46274
46402
|
}
|
|
46275
46403
|
return resolved;
|
|
46276
46404
|
}
|
|
@@ -46321,8 +46449,8 @@ var require_shebang_command = __commonJS({
|
|
|
46321
46449
|
if (!match) {
|
|
46322
46450
|
return null;
|
|
46323
46451
|
}
|
|
46324
|
-
const [
|
|
46325
|
-
const binary =
|
|
46452
|
+
const [path60, argument] = match[0].replace(/#! ?/, "").split(" ");
|
|
46453
|
+
const binary = path60.split("/").pop();
|
|
46326
46454
|
if (binary === "env") {
|
|
46327
46455
|
return argument;
|
|
46328
46456
|
}
|
|
@@ -46355,7 +46483,7 @@ var require_readShebang = __commonJS({
|
|
|
46355
46483
|
// ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.js
|
|
46356
46484
|
var require_parse = __commonJS({
|
|
46357
46485
|
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.js"(exports, module) {
|
|
46358
|
-
var
|
|
46486
|
+
var path60 = __require("path");
|
|
46359
46487
|
var resolveCommand = require_resolveCommand();
|
|
46360
46488
|
var escape4 = require_escape();
|
|
46361
46489
|
var readShebang = require_readShebang();
|
|
@@ -46380,7 +46508,7 @@ var require_parse = __commonJS({
|
|
|
46380
46508
|
const needsShell = !isExecutableRegExp.test(commandFile);
|
|
46381
46509
|
if (parsed.options.forceShell || needsShell) {
|
|
46382
46510
|
const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
|
|
46383
|
-
parsed.command =
|
|
46511
|
+
parsed.command = path60.normalize(parsed.command);
|
|
46384
46512
|
parsed.command = escape4.command(parsed.command);
|
|
46385
46513
|
parsed.args = parsed.args.map((arg) => escape4.argument(arg, needsDoubleEscapeMetaChars));
|
|
46386
46514
|
const shellCommand = [parsed.command].concat(parsed.args).join(" ");
|
|
@@ -46974,11 +47102,11 @@ var init_dist3 = __esm({
|
|
|
46974
47102
|
return;
|
|
46975
47103
|
}
|
|
46976
47104
|
const decoder = new TextDecoder(), reader = body.getReader();
|
|
46977
|
-
let
|
|
47105
|
+
let open2 = true;
|
|
46978
47106
|
do {
|
|
46979
47107
|
const { done, value } = await reader.read();
|
|
46980
|
-
value && __privateGet(this, _parser).feed(decoder.decode(value, { stream: !done })), done && (
|
|
46981
|
-
} while (
|
|
47108
|
+
value && __privateGet(this, _parser).feed(decoder.decode(value, { stream: !done })), done && (open2 = false, __privateGet(this, _parser).reset(), __privateMethod(this, _EventSource_instances, scheduleReconnect_fn).call(this));
|
|
47109
|
+
} while (open2);
|
|
46982
47110
|
}), __privateAdd(this, _onFetchError, (err) => {
|
|
46983
47111
|
__privateSet(this, _controller, void 0), !(err.name === "AbortError" || err.type === "aborted") && __privateMethod(this, _EventSource_instances, scheduleReconnect_fn).call(this, flattenError(err));
|
|
46984
47112
|
}), __privateAdd(this, _onEvent, (event) => {
|
|
@@ -49505,10 +49633,10 @@ var require_react_production_min = __commonJS({
|
|
|
49505
49633
|
var w4 = /* @__PURE__ */ Symbol.for("react.suspense");
|
|
49506
49634
|
var x4 = /* @__PURE__ */ Symbol.for("react.memo");
|
|
49507
49635
|
var y2 = /* @__PURE__ */ Symbol.for("react.lazy");
|
|
49508
|
-
var
|
|
49636
|
+
var z62 = Symbol.iterator;
|
|
49509
49637
|
function A3(a2) {
|
|
49510
49638
|
if (null === a2 || "object" !== typeof a2) return null;
|
|
49511
|
-
a2 =
|
|
49639
|
+
a2 = z62 && a2[z62] || a2["@@iterator"];
|
|
49512
49640
|
return "function" === typeof a2 ? a2 : null;
|
|
49513
49641
|
}
|
|
49514
49642
|
var B2 = { isMounted: function() {
|
|
@@ -52315,7 +52443,7 @@ var init_yoga_wasm_base64_esm = __esm({
|
|
|
52315
52443
|
h3.noExitRuntime || true;
|
|
52316
52444
|
"object" != typeof WebAssembly && x4("no native wasm support detected");
|
|
52317
52445
|
var fa, ha = false;
|
|
52318
|
-
function
|
|
52446
|
+
function z62(a2, b3, c2) {
|
|
52319
52447
|
c2 = b3 + c2;
|
|
52320
52448
|
for (var d2 = ""; !(b3 >= c2); ) {
|
|
52321
52449
|
var e3 = a2[b3++];
|
|
@@ -52965,7 +53093,7 @@ var init_yoga_wasm_base64_esm = __esm({
|
|
|
52965
53093
|
return b3;
|
|
52966
53094
|
}, Jb = {
|
|
52967
53095
|
l: function(a2, b3, c2, d2) {
|
|
52968
|
-
x4("Assertion failed: " + (a2 ?
|
|
53096
|
+
x4("Assertion failed: " + (a2 ? z62(A3, a2) : "") + ", at: " + [b3 ? b3 ? z62(A3, b3) : "" : "unknown filename", c2, d2 ? d2 ? z62(A3, d2) : "" : "unknown function"]);
|
|
52969
53097
|
},
|
|
52970
53098
|
q: function(a2, b3, c2) {
|
|
52971
53099
|
a2 = N2(a2);
|
|
@@ -53218,7 +53346,7 @@ var init_yoga_wasm_base64_esm = __esm({
|
|
|
53218
53346
|
if (c2) for (var g2 = f3, k3 = 0; k3 <= e3; ++k3) {
|
|
53219
53347
|
var m3 = f3 + k3;
|
|
53220
53348
|
if (k3 == e3 || 0 == A3[m3]) {
|
|
53221
|
-
g2 = g2 ?
|
|
53349
|
+
g2 = g2 ? z62(A3, g2, m3 - g2) : "";
|
|
53222
53350
|
if (void 0 === l2) var l2 = g2;
|
|
53223
53351
|
else l2 += String.fromCharCode(0), l2 += g2;
|
|
53224
53352
|
g2 = m3 + 1;
|
|
@@ -53415,7 +53543,7 @@ var init_yoga_wasm_base64_esm = __esm({
|
|
|
53415
53543
|
b3 += 8;
|
|
53416
53544
|
for (var m3 = 0; m3 < k3; m3++) {
|
|
53417
53545
|
var l2 = A3[g2 + m3], n2 = Fb[a2];
|
|
53418
|
-
0 === l2 || 10 === l2 ? ((1 === a2 ? ea : v3)(
|
|
53546
|
+
0 === l2 || 10 === l2 ? ((1 === a2 ? ea : v3)(z62(n2, 0)), n2.length = 0) : n2.push(l2);
|
|
53419
53547
|
}
|
|
53420
53548
|
e3 += k3;
|
|
53421
53549
|
}
|
|
@@ -53903,7 +54031,7 @@ var require_scheduler_production_min = __commonJS({
|
|
|
53903
54031
|
var u2 = 1;
|
|
53904
54032
|
var v3 = null;
|
|
53905
54033
|
var y2 = 3;
|
|
53906
|
-
var
|
|
54034
|
+
var z62 = false;
|
|
53907
54035
|
var A3 = false;
|
|
53908
54036
|
var B2 = false;
|
|
53909
54037
|
var D3 = "function" === typeof setTimeout ? setTimeout : null;
|
|
@@ -53930,7 +54058,7 @@ var require_scheduler_production_min = __commonJS({
|
|
|
53930
54058
|
function J2(a2, b3) {
|
|
53931
54059
|
A3 = false;
|
|
53932
54060
|
B2 && (B2 = false, E3(L3), L3 = -1);
|
|
53933
|
-
|
|
54061
|
+
z62 = true;
|
|
53934
54062
|
var c2 = y2;
|
|
53935
54063
|
try {
|
|
53936
54064
|
G3(b3);
|
|
@@ -53954,7 +54082,7 @@ var require_scheduler_production_min = __commonJS({
|
|
|
53954
54082
|
}
|
|
53955
54083
|
return w4;
|
|
53956
54084
|
} finally {
|
|
53957
|
-
v3 = null, y2 = c2,
|
|
54085
|
+
v3 = null, y2 = c2, z62 = false;
|
|
53958
54086
|
}
|
|
53959
54087
|
}
|
|
53960
54088
|
var N2 = false;
|
|
@@ -54011,7 +54139,7 @@ var require_scheduler_production_min = __commonJS({
|
|
|
54011
54139
|
a2.callback = null;
|
|
54012
54140
|
};
|
|
54013
54141
|
exports.unstable_continueExecution = function() {
|
|
54014
|
-
A3 ||
|
|
54142
|
+
A3 || z62 || (A3 = true, I2(J2));
|
|
54015
54143
|
};
|
|
54016
54144
|
exports.unstable_forceFrameRate = function(a2) {
|
|
54017
54145
|
0 > a2 || 125 < a2 ? console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported") : P3 = 0 < a2 ? Math.floor(1e3 / a2) : 5;
|
|
@@ -54084,7 +54212,7 @@ var require_scheduler_production_min = __commonJS({
|
|
|
54084
54212
|
}
|
|
54085
54213
|
e3 = c2 + e3;
|
|
54086
54214
|
a2 = { id: u2++, callback: b3, priorityLevel: a2, startTime: c2, expirationTime: e3, sortIndex: -1 };
|
|
54087
|
-
c2 > d2 ? (a2.sortIndex = c2, f3(t2, a2), null === h3(r2) && a2 === h3(t2) && (B2 ? (E3(L3), L3 = -1) : B2 = true, K4(H3, c2 - d2))) : (a2.sortIndex = e3, f3(r2, a2), A3 ||
|
|
54215
|
+
c2 > d2 ? (a2.sortIndex = c2, f3(t2, a2), null === h3(r2) && a2 === h3(t2) && (B2 ? (E3(L3), L3 = -1) : B2 = true, K4(H3, c2 - d2))) : (a2.sortIndex = e3, f3(r2, a2), A3 || z62 || (A3 = true, I2(J2)));
|
|
54088
54216
|
return a2;
|
|
54089
54217
|
};
|
|
54090
54218
|
exports.unstable_shouldYield = M2;
|
|
@@ -54841,7 +54969,7 @@ var require_react_reconciler_production_min = __commonJS({
|
|
|
54841
54969
|
gc[hc] = a2.current;
|
|
54842
54970
|
a2.current = b3;
|
|
54843
54971
|
}
|
|
54844
|
-
var jc = {}, x4 = ic(jc),
|
|
54972
|
+
var jc = {}, x4 = ic(jc), z62 = ic(false), kc = jc;
|
|
54845
54973
|
function mc(a2, b3) {
|
|
54846
54974
|
var c2 = a2.type.contextTypes;
|
|
54847
54975
|
if (!c2) return jc;
|
|
@@ -54857,13 +54985,13 @@ var require_react_reconciler_production_min = __commonJS({
|
|
|
54857
54985
|
return null !== a2 && void 0 !== a2;
|
|
54858
54986
|
}
|
|
54859
54987
|
function nc() {
|
|
54860
|
-
q3(
|
|
54988
|
+
q3(z62);
|
|
54861
54989
|
q3(x4);
|
|
54862
54990
|
}
|
|
54863
54991
|
function oc(a2, b3, c2) {
|
|
54864
54992
|
if (x4.current !== jc) throw Error(n2(168));
|
|
54865
54993
|
v3(x4, b3);
|
|
54866
|
-
v3(
|
|
54994
|
+
v3(z62, c2);
|
|
54867
54995
|
}
|
|
54868
54996
|
function pc(a2, b3, c2) {
|
|
54869
54997
|
var d2 = a2.stateNode;
|
|
@@ -54877,14 +55005,14 @@ var require_react_reconciler_production_min = __commonJS({
|
|
|
54877
55005
|
a2 = (a2 = a2.stateNode) && a2.__reactInternalMemoizedMergedChildContext || jc;
|
|
54878
55006
|
kc = x4.current;
|
|
54879
55007
|
v3(x4, a2);
|
|
54880
|
-
v3(
|
|
55008
|
+
v3(z62, z62.current);
|
|
54881
55009
|
return true;
|
|
54882
55010
|
}
|
|
54883
55011
|
function rc(a2, b3, c2) {
|
|
54884
55012
|
var d2 = a2.stateNode;
|
|
54885
55013
|
if (!d2) throw Error(n2(169));
|
|
54886
|
-
c2 ? (a2 = pc(a2, b3, kc), d2.__reactInternalMemoizedMergedChildContext = a2, q3(
|
|
54887
|
-
v3(
|
|
55014
|
+
c2 ? (a2 = pc(a2, b3, kc), d2.__reactInternalMemoizedMergedChildContext = a2, q3(z62), q3(x4), v3(x4, a2)) : q3(z62);
|
|
55015
|
+
v3(z62, c2);
|
|
54888
55016
|
}
|
|
54889
55017
|
var tc = Math.clz32 ? Math.clz32 : sc, uc = Math.log, vc = Math.LN2;
|
|
54890
55018
|
function sc(a2) {
|
|
@@ -56482,7 +56610,7 @@ var require_react_reconciler_production_min = __commonJS({
|
|
|
56482
56610
|
g2.state = p3;
|
|
56483
56611
|
ke2(b3, d2, g2, e3);
|
|
56484
56612
|
k3 = b3.memoizedState;
|
|
56485
|
-
h3 !== d2 || p3 !== k3 ||
|
|
56613
|
+
h3 !== d2 || p3 !== k3 || z62.current || de2 ? ("function" === typeof m3 && (yf(b3, c2, m3, d2), k3 = b3.memoizedState), (h3 = de2 || Af(b3, c2, h3, d2, p3, k3, l2)) ? (r2 || "function" !== typeof g2.UNSAFE_componentWillMount && "function" !== typeof g2.componentWillMount || ("function" === typeof g2.componentWillMount && g2.componentWillMount(), "function" === typeof g2.UNSAFE_componentWillMount && g2.UNSAFE_componentWillMount()), "function" === typeof g2.componentDidMount && (b3.flags |= 4194308)) : ("function" === typeof g2.componentDidMount && (b3.flags |= 4194308), b3.memoizedProps = d2, b3.memoizedState = k3), g2.props = d2, g2.state = k3, g2.context = l2, d2 = h3) : ("function" === typeof g2.componentDidMount && (b3.flags |= 4194308), d2 = false);
|
|
56486
56614
|
} else {
|
|
56487
56615
|
g2 = b3.stateNode;
|
|
56488
56616
|
fe2(a2, b3);
|
|
@@ -56500,7 +56628,7 @@ var require_react_reconciler_production_min = __commonJS({
|
|
|
56500
56628
|
g2.state = p3;
|
|
56501
56629
|
ke2(b3, d2, g2, e3);
|
|
56502
56630
|
var w4 = b3.memoizedState;
|
|
56503
|
-
h3 !== r2 || p3 !== w4 ||
|
|
56631
|
+
h3 !== r2 || p3 !== w4 || z62.current || de2 ? ("function" === typeof B2 && (yf(b3, c2, B2, d2), w4 = b3.memoizedState), (l2 = de2 || Af(b3, c2, l2, d2, p3, w4, k3) || false) ? (m3 || "function" !== typeof g2.UNSAFE_componentWillUpdate && "function" !== typeof g2.componentWillUpdate || ("function" === typeof g2.componentWillUpdate && g2.componentWillUpdate(d2, w4, k3), "function" === typeof g2.UNSAFE_componentWillUpdate && g2.UNSAFE_componentWillUpdate(d2, w4, k3)), "function" === typeof g2.componentDidUpdate && (b3.flags |= 4), "function" === typeof g2.getSnapshotBeforeUpdate && (b3.flags |= 1024)) : ("function" !== typeof g2.componentDidUpdate || h3 === a2.memoizedProps && p3 === a2.memoizedState || (b3.flags |= 4), "function" !== typeof g2.getSnapshotBeforeUpdate || h3 === a2.memoizedProps && p3 === a2.memoizedState || (b3.flags |= 1024), b3.memoizedProps = d2, b3.memoizedState = w4), g2.props = d2, g2.state = w4, g2.context = k3, d2 = l2) : ("function" !== typeof g2.componentDidUpdate || h3 === a2.memoizedProps && p3 === a2.memoizedState || (b3.flags |= 4), "function" !== typeof g2.getSnapshotBeforeUpdate || h3 === a2.memoizedProps && p3 === a2.memoizedState || (b3.flags |= 1024), d2 = false);
|
|
56504
56632
|
}
|
|
56505
56633
|
return dg(a2, b3, c2, d2, f3, e3);
|
|
56506
56634
|
}
|
|
@@ -56969,7 +57097,7 @@ var require_react_reconciler_production_min = __commonJS({
|
|
|
56969
57097
|
case 3:
|
|
56970
57098
|
c2 = b3.stateNode;
|
|
56971
57099
|
te3();
|
|
56972
|
-
q3(
|
|
57100
|
+
q3(z62);
|
|
56973
57101
|
q3(x4);
|
|
56974
57102
|
ye3();
|
|
56975
57103
|
c2.pendingContext && (c2.context = c2.pendingContext, c2.pendingContext = null);
|
|
@@ -57112,7 +57240,7 @@ var require_react_reconciler_production_min = __commonJS({
|
|
|
57112
57240
|
case 1:
|
|
57113
57241
|
return A3(b3.type) && nc(), a2 = b3.flags, a2 & 65536 ? (b3.flags = a2 & -65537 | 128, b3) : null;
|
|
57114
57242
|
case 3:
|
|
57115
|
-
return te3(), q3(
|
|
57243
|
+
return te3(), q3(z62), q3(x4), ye3(), a2 = b3.flags, 0 !== (a2 & 65536) && 0 === (a2 & 128) ? (b3.flags = a2 & -65537 | 128, b3) : null;
|
|
57116
57244
|
case 5:
|
|
57117
57245
|
return ve2(b3), null;
|
|
57118
57246
|
case 13:
|
|
@@ -58167,7 +58295,7 @@ var require_react_reconciler_production_min = __commonJS({
|
|
|
58167
58295
|
break;
|
|
58168
58296
|
case 3:
|
|
58169
58297
|
te3();
|
|
58170
|
-
q3(
|
|
58298
|
+
q3(z62);
|
|
58171
58299
|
q3(x4);
|
|
58172
58300
|
ye3();
|
|
58173
58301
|
break;
|
|
@@ -58644,7 +58772,7 @@ var require_react_reconciler_production_min = __commonJS({
|
|
|
58644
58772
|
}
|
|
58645
58773
|
var ai;
|
|
58646
58774
|
ai = function(a2, b3, c2) {
|
|
58647
|
-
if (null !== a2) if (a2.memoizedProps !== b3.pendingProps ||
|
|
58775
|
+
if (null !== a2) if (a2.memoizedProps !== b3.pendingProps || z62.current) G3 = true;
|
|
58648
58776
|
else {
|
|
58649
58777
|
if (0 === (a2.lanes & c2) && 0 === (b3.flags & 128)) return G3 = false, sg(a2, b3, c2);
|
|
58650
58778
|
G3 = 0 !== (a2.flags & 131072) ? true : false;
|
|
@@ -58753,7 +58881,7 @@ var require_react_reconciler_production_min = __commonJS({
|
|
|
58753
58881
|
g2 = e3.value;
|
|
58754
58882
|
Vd(b3, d2, g2);
|
|
58755
58883
|
if (null !== f3) if (Vc(f3.value, g2)) {
|
|
58756
|
-
if (f3.children === e3.children && !
|
|
58884
|
+
if (f3.children === e3.children && !z62.current) {
|
|
58757
58885
|
b3 = Tf(a2, b3, c2);
|
|
58758
58886
|
break a;
|
|
58759
58887
|
}
|
|
@@ -74168,10 +74296,10 @@ var require_react_reconciler_development = __commonJS({
|
|
|
74168
74296
|
var setErrorHandler = null;
|
|
74169
74297
|
var setSuspenseHandler = null;
|
|
74170
74298
|
{
|
|
74171
|
-
var copyWithDeleteImpl = function(obj,
|
|
74172
|
-
var key =
|
|
74299
|
+
var copyWithDeleteImpl = function(obj, path60, index2) {
|
|
74300
|
+
var key = path60[index2];
|
|
74173
74301
|
var updated = isArray(obj) ? obj.slice() : assign({}, obj);
|
|
74174
|
-
if (index2 + 1 ===
|
|
74302
|
+
if (index2 + 1 === path60.length) {
|
|
74175
74303
|
if (isArray(updated)) {
|
|
74176
74304
|
updated.splice(key, 1);
|
|
74177
74305
|
} else {
|
|
@@ -74179,11 +74307,11 @@ var require_react_reconciler_development = __commonJS({
|
|
|
74179
74307
|
}
|
|
74180
74308
|
return updated;
|
|
74181
74309
|
}
|
|
74182
|
-
updated[key] = copyWithDeleteImpl(obj[key],
|
|
74310
|
+
updated[key] = copyWithDeleteImpl(obj[key], path60, index2 + 1);
|
|
74183
74311
|
return updated;
|
|
74184
74312
|
};
|
|
74185
|
-
var copyWithDelete = function(obj,
|
|
74186
|
-
return copyWithDeleteImpl(obj,
|
|
74313
|
+
var copyWithDelete = function(obj, path60) {
|
|
74314
|
+
return copyWithDeleteImpl(obj, path60, 0);
|
|
74187
74315
|
};
|
|
74188
74316
|
var copyWithRenameImpl = function(obj, oldPath, newPath, index2) {
|
|
74189
74317
|
var oldKey = oldPath[index2];
|
|
@@ -74221,17 +74349,17 @@ var require_react_reconciler_development = __commonJS({
|
|
|
74221
74349
|
}
|
|
74222
74350
|
return copyWithRenameImpl(obj, oldPath, newPath, 0);
|
|
74223
74351
|
};
|
|
74224
|
-
var copyWithSetImpl = function(obj,
|
|
74225
|
-
if (index2 >=
|
|
74352
|
+
var copyWithSetImpl = function(obj, path60, index2, value) {
|
|
74353
|
+
if (index2 >= path60.length) {
|
|
74226
74354
|
return value;
|
|
74227
74355
|
}
|
|
74228
|
-
var key =
|
|
74356
|
+
var key = path60[index2];
|
|
74229
74357
|
var updated = isArray(obj) ? obj.slice() : assign({}, obj);
|
|
74230
|
-
updated[key] = copyWithSetImpl(obj[key],
|
|
74358
|
+
updated[key] = copyWithSetImpl(obj[key], path60, index2 + 1, value);
|
|
74231
74359
|
return updated;
|
|
74232
74360
|
};
|
|
74233
|
-
var copyWithSet = function(obj,
|
|
74234
|
-
return copyWithSetImpl(obj,
|
|
74361
|
+
var copyWithSet = function(obj, path60, value) {
|
|
74362
|
+
return copyWithSetImpl(obj, path60, 0, value);
|
|
74235
74363
|
};
|
|
74236
74364
|
var findHook = function(fiber, id) {
|
|
74237
74365
|
var currentHook2 = fiber.memoizedState;
|
|
@@ -74241,10 +74369,10 @@ var require_react_reconciler_development = __commonJS({
|
|
|
74241
74369
|
}
|
|
74242
74370
|
return currentHook2;
|
|
74243
74371
|
};
|
|
74244
|
-
overrideHookState = function(fiber, id,
|
|
74372
|
+
overrideHookState = function(fiber, id, path60, value) {
|
|
74245
74373
|
var hook = findHook(fiber, id);
|
|
74246
74374
|
if (hook !== null) {
|
|
74247
|
-
var newState = copyWithSet(hook.memoizedState,
|
|
74375
|
+
var newState = copyWithSet(hook.memoizedState, path60, value);
|
|
74248
74376
|
hook.memoizedState = newState;
|
|
74249
74377
|
hook.baseState = newState;
|
|
74250
74378
|
fiber.memoizedProps = assign({}, fiber.memoizedProps);
|
|
@@ -74254,10 +74382,10 @@ var require_react_reconciler_development = __commonJS({
|
|
|
74254
74382
|
}
|
|
74255
74383
|
}
|
|
74256
74384
|
};
|
|
74257
|
-
overrideHookStateDeletePath = function(fiber, id,
|
|
74385
|
+
overrideHookStateDeletePath = function(fiber, id, path60) {
|
|
74258
74386
|
var hook = findHook(fiber, id);
|
|
74259
74387
|
if (hook !== null) {
|
|
74260
|
-
var newState = copyWithDelete(hook.memoizedState,
|
|
74388
|
+
var newState = copyWithDelete(hook.memoizedState, path60);
|
|
74261
74389
|
hook.memoizedState = newState;
|
|
74262
74390
|
hook.baseState = newState;
|
|
74263
74391
|
fiber.memoizedProps = assign({}, fiber.memoizedProps);
|
|
@@ -74280,8 +74408,8 @@ var require_react_reconciler_development = __commonJS({
|
|
|
74280
74408
|
}
|
|
74281
74409
|
}
|
|
74282
74410
|
};
|
|
74283
|
-
overrideProps = function(fiber,
|
|
74284
|
-
fiber.pendingProps = copyWithSet(fiber.memoizedProps,
|
|
74411
|
+
overrideProps = function(fiber, path60, value) {
|
|
74412
|
+
fiber.pendingProps = copyWithSet(fiber.memoizedProps, path60, value);
|
|
74285
74413
|
if (fiber.alternate) {
|
|
74286
74414
|
fiber.alternate.pendingProps = fiber.pendingProps;
|
|
74287
74415
|
}
|
|
@@ -74290,8 +74418,8 @@ var require_react_reconciler_development = __commonJS({
|
|
|
74290
74418
|
scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp);
|
|
74291
74419
|
}
|
|
74292
74420
|
};
|
|
74293
|
-
overridePropsDeletePath = function(fiber,
|
|
74294
|
-
fiber.pendingProps = copyWithDelete(fiber.memoizedProps,
|
|
74421
|
+
overridePropsDeletePath = function(fiber, path60) {
|
|
74422
|
+
fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path60);
|
|
74295
74423
|
if (fiber.alternate) {
|
|
74296
74424
|
fiber.alternate.pendingProps = fiber.pendingProps;
|
|
74297
74425
|
}
|
|
@@ -78818,7 +78946,7 @@ var require_stream = __commonJS({
|
|
|
78818
78946
|
};
|
|
78819
78947
|
duplex._final = function(callback) {
|
|
78820
78948
|
if (ws.readyState === ws.CONNECTING) {
|
|
78821
|
-
ws.once("open", function
|
|
78949
|
+
ws.once("open", function open2() {
|
|
78822
78950
|
duplex._final(callback);
|
|
78823
78951
|
});
|
|
78824
78952
|
return;
|
|
@@ -78839,7 +78967,7 @@ var require_stream = __commonJS({
|
|
|
78839
78967
|
};
|
|
78840
78968
|
duplex._write = function(chunk, encoding, callback) {
|
|
78841
78969
|
if (ws.readyState === ws.CONNECTING) {
|
|
78842
|
-
ws.once("open", function
|
|
78970
|
+
ws.once("open", function open2() {
|
|
78843
78971
|
duplex._write(chunk, encoding, callback);
|
|
78844
78972
|
});
|
|
78845
78973
|
return;
|
|
@@ -80204,18 +80332,18 @@ var init_source = __esm({
|
|
|
80204
80332
|
}
|
|
80205
80333
|
}
|
|
80206
80334
|
});
|
|
80207
|
-
createStyler = (
|
|
80335
|
+
createStyler = (open2, close, parent) => {
|
|
80208
80336
|
let openAll;
|
|
80209
80337
|
let closeAll;
|
|
80210
80338
|
if (parent === void 0) {
|
|
80211
|
-
openAll =
|
|
80339
|
+
openAll = open2;
|
|
80212
80340
|
closeAll = close;
|
|
80213
80341
|
} else {
|
|
80214
|
-
openAll = parent.openAll +
|
|
80342
|
+
openAll = parent.openAll + open2;
|
|
80215
80343
|
closeAll = close + parent.closeAll;
|
|
80216
80344
|
}
|
|
80217
80345
|
return {
|
|
80218
|
-
open,
|
|
80346
|
+
open: open2,
|
|
80219
80347
|
close,
|
|
80220
80348
|
openAll,
|
|
80221
80349
|
closeAll,
|
|
@@ -81733,8 +81861,8 @@ var init_ErrorOverview = __esm({
|
|
|
81733
81861
|
init_dist7();
|
|
81734
81862
|
init_Box();
|
|
81735
81863
|
init_Text();
|
|
81736
|
-
cleanupPath = (
|
|
81737
|
-
return
|
|
81864
|
+
cleanupPath = (path60) => {
|
|
81865
|
+
return path60?.replace(`file://${cwd()}/`, "");
|
|
81738
81866
|
};
|
|
81739
81867
|
stackUtils = new import_stack_utils.default({
|
|
81740
81868
|
cwd: cwd(),
|
|
@@ -86081,8 +86209,8 @@ function readClipboardImageDarwin() {
|
|
|
86081
86209
|
return null;
|
|
86082
86210
|
}
|
|
86083
86211
|
try {
|
|
86084
|
-
const
|
|
86085
|
-
if (
|
|
86212
|
+
const stat2 = statSync(target);
|
|
86213
|
+
if (stat2.size === 0) {
|
|
86086
86214
|
unlinkSync(target);
|
|
86087
86215
|
return null;
|
|
86088
86216
|
}
|
|
@@ -88412,7 +88540,6 @@ var init_SessionView = __esm({
|
|
|
88412
88540
|
const ctrl = turn.turnControllerRef.current;
|
|
88413
88541
|
if (ctrl && !ctrl.signal.aborted)
|
|
88414
88542
|
ctrl.abort("user reset");
|
|
88415
|
-
session.log.clear();
|
|
88416
88543
|
setOverlay(null);
|
|
88417
88544
|
for (const p3 of permissions.pendingPermissions) {
|
|
88418
88545
|
p3.resolve({ mode: "deny", reason: "/new \u2014 session reset" });
|
|
@@ -88423,8 +88550,18 @@ var init_SessionView = __esm({
|
|
|
88423
88550
|
setYolo(false);
|
|
88424
88551
|
turn.queueRef.current = [];
|
|
88425
88552
|
turn.setQueueCount(0);
|
|
88426
|
-
if (
|
|
88427
|
-
|
|
88553
|
+
if (typeof session.reset === "function") {
|
|
88554
|
+
void session.reset().then(() => {
|
|
88555
|
+
if (notice)
|
|
88556
|
+
setSystemNotice(notice);
|
|
88557
|
+
}, (err) => {
|
|
88558
|
+
setSystemNotice(`/new failed: ${err instanceof Error ? err.message : String(err)} \u2014 history NOT cleared`);
|
|
88559
|
+
});
|
|
88560
|
+
} else {
|
|
88561
|
+
session.log.clear();
|
|
88562
|
+
if (notice)
|
|
88563
|
+
setSystemNotice(notice);
|
|
88564
|
+
}
|
|
88428
88565
|
};
|
|
88429
88566
|
const handleSubmit = async (text) => {
|
|
88430
88567
|
setSystemNotice(null);
|
|
@@ -90202,11 +90339,11 @@ var require_dijkstra = __commonJS({
|
|
|
90202
90339
|
var predecessors = {};
|
|
90203
90340
|
var costs = {};
|
|
90204
90341
|
costs[s2] = 0;
|
|
90205
|
-
var
|
|
90206
|
-
|
|
90342
|
+
var open2 = dijkstra.PriorityQueue.make();
|
|
90343
|
+
open2.push(s2, 0);
|
|
90207
90344
|
var closest, u2, v3, cost_of_s_to_u, adjacent_nodes, cost_of_e, cost_of_s_to_u_plus_cost_of_e, cost_of_s_to_v, first_visit;
|
|
90208
|
-
while (!
|
|
90209
|
-
closest =
|
|
90345
|
+
while (!open2.empty()) {
|
|
90346
|
+
closest = open2.pop();
|
|
90210
90347
|
u2 = closest.value;
|
|
90211
90348
|
cost_of_s_to_u = closest.cost;
|
|
90212
90349
|
adjacent_nodes = graph[u2] || {};
|
|
@@ -90218,7 +90355,7 @@ var require_dijkstra = __commonJS({
|
|
|
90218
90355
|
first_visit = typeof costs[v3] === "undefined";
|
|
90219
90356
|
if (first_visit || cost_of_s_to_v > cost_of_s_to_u_plus_cost_of_e) {
|
|
90220
90357
|
costs[v3] = cost_of_s_to_u_plus_cost_of_e;
|
|
90221
|
-
|
|
90358
|
+
open2.push(v3, cost_of_s_to_u_plus_cost_of_e);
|
|
90222
90359
|
predecessors[v3] = u2;
|
|
90223
90360
|
}
|
|
90224
90361
|
}
|
|
@@ -90464,10 +90601,10 @@ var require_segments = __commonJS({
|
|
|
90464
90601
|
const segs = getSegmentsFromString(data, Utils.isKanjiModeEnabled());
|
|
90465
90602
|
const nodes = buildNodes(segs);
|
|
90466
90603
|
const graph = buildGraph(nodes, version);
|
|
90467
|
-
const
|
|
90604
|
+
const path60 = dijkstra.find_path(graph.map, "start", "end");
|
|
90468
90605
|
const optimizedSegs = [];
|
|
90469
|
-
for (let i2 = 1; i2 <
|
|
90470
|
-
optimizedSegs.push(graph.table[
|
|
90606
|
+
for (let i2 = 1; i2 < path60.length - 1; i2++) {
|
|
90607
|
+
optimizedSegs.push(graph.table[path60[i2]].node);
|
|
90471
90608
|
}
|
|
90472
90609
|
return exports.fromArray(mergeSegments(optimizedSegs));
|
|
90473
90610
|
};
|
|
@@ -92919,7 +93056,7 @@ var require_png2 = __commonJS({
|
|
|
92919
93056
|
});
|
|
92920
93057
|
png.pack();
|
|
92921
93058
|
};
|
|
92922
|
-
exports.renderToFile = function renderToFile(
|
|
93059
|
+
exports.renderToFile = function renderToFile(path60, qrData, options, cb) {
|
|
92923
93060
|
if (typeof cb === "undefined") {
|
|
92924
93061
|
cb = options;
|
|
92925
93062
|
options = void 0;
|
|
@@ -92930,7 +93067,7 @@ var require_png2 = __commonJS({
|
|
|
92930
93067
|
called = true;
|
|
92931
93068
|
cb.apply(null, args);
|
|
92932
93069
|
};
|
|
92933
|
-
const stream = fs43.createWriteStream(
|
|
93070
|
+
const stream = fs43.createWriteStream(path60);
|
|
92934
93071
|
stream.on("error", done);
|
|
92935
93072
|
stream.on("close", done);
|
|
92936
93073
|
exports.renderToFileStream(stream, qrData, options);
|
|
@@ -92992,14 +93129,14 @@ var require_utf8 = __commonJS({
|
|
|
92992
93129
|
}
|
|
92993
93130
|
return output;
|
|
92994
93131
|
};
|
|
92995
|
-
exports.renderToFile = function renderToFile(
|
|
93132
|
+
exports.renderToFile = function renderToFile(path60, qrData, options, cb) {
|
|
92996
93133
|
if (typeof cb === "undefined") {
|
|
92997
93134
|
cb = options;
|
|
92998
93135
|
options = void 0;
|
|
92999
93136
|
}
|
|
93000
93137
|
const fs43 = __require("fs");
|
|
93001
93138
|
const utf8 = exports.render(qrData, options);
|
|
93002
|
-
fs43.writeFile(
|
|
93139
|
+
fs43.writeFile(path60, utf8, cb);
|
|
93003
93140
|
};
|
|
93004
93141
|
}
|
|
93005
93142
|
});
|
|
@@ -93120,7 +93257,7 @@ var require_svg_tag = __commonJS({
|
|
|
93120
93257
|
return str2;
|
|
93121
93258
|
}
|
|
93122
93259
|
function qrToPath(data, size, margin) {
|
|
93123
|
-
let
|
|
93260
|
+
let path60 = "";
|
|
93124
93261
|
let moveBy = 0;
|
|
93125
93262
|
let newRow = false;
|
|
93126
93263
|
let lineLength = 0;
|
|
@@ -93131,19 +93268,19 @@ var require_svg_tag = __commonJS({
|
|
|
93131
93268
|
if (data[i2]) {
|
|
93132
93269
|
lineLength++;
|
|
93133
93270
|
if (!(i2 > 0 && col > 0 && data[i2 - 1])) {
|
|
93134
|
-
|
|
93271
|
+
path60 += newRow ? svgCmd("M", col + margin, 0.5 + row + margin) : svgCmd("m", moveBy, 0);
|
|
93135
93272
|
moveBy = 0;
|
|
93136
93273
|
newRow = false;
|
|
93137
93274
|
}
|
|
93138
93275
|
if (!(col + 1 < size && data[i2 + 1])) {
|
|
93139
|
-
|
|
93276
|
+
path60 += svgCmd("h", lineLength);
|
|
93140
93277
|
lineLength = 0;
|
|
93141
93278
|
}
|
|
93142
93279
|
} else {
|
|
93143
93280
|
moveBy++;
|
|
93144
93281
|
}
|
|
93145
93282
|
}
|
|
93146
|
-
return
|
|
93283
|
+
return path60;
|
|
93147
93284
|
}
|
|
93148
93285
|
exports.render = function render2(qrData, options, cb) {
|
|
93149
93286
|
const opts = Utils.getOptions(options);
|
|
@@ -93151,10 +93288,10 @@ var require_svg_tag = __commonJS({
|
|
|
93151
93288
|
const data = qrData.modules.data;
|
|
93152
93289
|
const qrcodesize = size + opts.margin * 2;
|
|
93153
93290
|
const bg = !opts.color.light.a ? "" : "<path " + getColorAttrib(opts.color.light, "fill") + ' d="M0 0h' + qrcodesize + "v" + qrcodesize + 'H0z"/>';
|
|
93154
|
-
const
|
|
93291
|
+
const path60 = "<path " + getColorAttrib(opts.color.dark, "stroke") + ' d="' + qrToPath(data, size, opts.margin) + '"/>';
|
|
93155
93292
|
const viewBox = 'viewBox="0 0 ' + qrcodesize + " " + qrcodesize + '"';
|
|
93156
93293
|
const width = !opts.width ? "" : 'width="' + opts.width + '" height="' + opts.width + '" ';
|
|
93157
|
-
const svgTag = '<svg xmlns="http://www.w3.org/2000/svg" ' + width + viewBox + ' shape-rendering="crispEdges">' + bg +
|
|
93294
|
+
const svgTag = '<svg xmlns="http://www.w3.org/2000/svg" ' + width + viewBox + ' shape-rendering="crispEdges">' + bg + path60 + "</svg>\n";
|
|
93158
93295
|
if (typeof cb === "function") {
|
|
93159
93296
|
cb(null, svgTag);
|
|
93160
93297
|
}
|
|
@@ -93168,7 +93305,7 @@ var require_svg = __commonJS({
|
|
|
93168
93305
|
"../../node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/svg.js"(exports) {
|
|
93169
93306
|
var svgTagRenderer = require_svg_tag();
|
|
93170
93307
|
exports.render = svgTagRenderer.render;
|
|
93171
|
-
exports.renderToFile = function renderToFile(
|
|
93308
|
+
exports.renderToFile = function renderToFile(path60, qrData, options, cb) {
|
|
93172
93309
|
if (typeof cb === "undefined") {
|
|
93173
93310
|
cb = options;
|
|
93174
93311
|
options = void 0;
|
|
@@ -93176,7 +93313,7 @@ var require_svg = __commonJS({
|
|
|
93176
93313
|
const fs43 = __require("fs");
|
|
93177
93314
|
const svgTag = exports.render(qrData, options);
|
|
93178
93315
|
const xmlStr = '<?xml version="1.0" encoding="utf-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' + svgTag;
|
|
93179
|
-
fs43.writeFile(
|
|
93316
|
+
fs43.writeFile(path60, xmlStr, cb);
|
|
93180
93317
|
};
|
|
93181
93318
|
}
|
|
93182
93319
|
});
|
|
@@ -93334,8 +93471,8 @@ var require_server = __commonJS({
|
|
|
93334
93471
|
cb
|
|
93335
93472
|
};
|
|
93336
93473
|
}
|
|
93337
|
-
function getTypeFromFilename(
|
|
93338
|
-
return
|
|
93474
|
+
function getTypeFromFilename(path60) {
|
|
93475
|
+
return path60.slice((path60.lastIndexOf(".") - 1 >>> 0) + 2).toLowerCase();
|
|
93339
93476
|
}
|
|
93340
93477
|
function getRendererFromType(type) {
|
|
93341
93478
|
switch (type) {
|
|
@@ -93399,17 +93536,17 @@ var require_server = __commonJS({
|
|
|
93399
93536
|
const renderer2 = getRendererFromType(params.opts.type);
|
|
93400
93537
|
return render2(renderer2.renderToBuffer, text, params);
|
|
93401
93538
|
};
|
|
93402
|
-
exports.toFile = function toFile3(
|
|
93403
|
-
if (typeof
|
|
93539
|
+
exports.toFile = function toFile3(path60, text, opts, cb) {
|
|
93540
|
+
if (typeof path60 !== "string" || !(typeof text === "string" || typeof text === "object")) {
|
|
93404
93541
|
throw new Error("Invalid argument");
|
|
93405
93542
|
}
|
|
93406
93543
|
if (arguments.length < 3 && !canPromise()) {
|
|
93407
93544
|
throw new Error("Too few arguments provided");
|
|
93408
93545
|
}
|
|
93409
93546
|
const params = checkParams(text, opts, cb);
|
|
93410
|
-
const type = params.opts.type || getTypeFromFilename(
|
|
93547
|
+
const type = params.opts.type || getTypeFromFilename(path60);
|
|
93411
93548
|
const renderer2 = getRendererFromType(type);
|
|
93412
|
-
const renderToFile = renderer2.renderToFile.bind(null,
|
|
93549
|
+
const renderToFile = renderer2.renderToFile.bind(null, path60);
|
|
93413
93550
|
return render2(renderToFile, text, params);
|
|
93414
93551
|
};
|
|
93415
93552
|
exports.toFileStream = function toFileStream(stream, text, opts) {
|
|
@@ -95215,6 +95352,9 @@ var VaultStore = class {
|
|
|
95215
95352
|
// whole-file rewrite. open() is also chained through this so two
|
|
95216
95353
|
// parallel `open()` calls never both derive a fresh salt.
|
|
95217
95354
|
mutex = createMutex();
|
|
95355
|
+
// stat() fingerprint of the file as of our last load/sync/persist; lets
|
|
95356
|
+
// syncFromDisk() skip the read+parse when nothing else has written.
|
|
95357
|
+
lastSynced = null;
|
|
95218
95358
|
constructor(opts) {
|
|
95219
95359
|
this.filePath = opts.filePath;
|
|
95220
95360
|
this.keySource = opts.keySource;
|
|
@@ -95292,6 +95432,49 @@ var VaultStore = class {
|
|
|
95292
95432
|
throw new VaultPassphraseError(this.filePath);
|
|
95293
95433
|
}
|
|
95294
95434
|
}
|
|
95435
|
+
/**
|
|
95436
|
+
* Fold other writers' entries in from the on-disk file. Historically the
|
|
95437
|
+
* vault persisted a whole-file snapshot of THIS instance's memory, so a
|
|
95438
|
+
* write from any other `VaultStore` (another moxxy process, or a second
|
|
95439
|
+
* instance in this one) was silently clobbered by our next persist —
|
|
95440
|
+
* last-writer-wins, fatal for single-use rotated OAuth refresh tokens.
|
|
95441
|
+
* Now every read and every mutation first re-reads the file (mtime/size
|
|
95442
|
+
* gated, so the common no-other-writer case costs one `stat`) and merges:
|
|
95443
|
+
* - key on both sides → newer `updatedAt` wins (ISO timestamps);
|
|
95444
|
+
* - key only on disk → adopt it (another writer added it);
|
|
95445
|
+
* - key only in memory → drop it (every mutation persists before
|
|
95446
|
+
* returning, so a key missing on disk was deleted by another writer).
|
|
95447
|
+
* Skipped when the on-disk salt differs (vault wiped/recreated — those
|
|
95448
|
+
* entries are undecryptable under our master key) or the file is
|
|
95449
|
+
* unreadable/corrupt (keep memory; the next persist restores a good file).
|
|
95450
|
+
*
|
|
95451
|
+
* Must be called while holding `this.mutex`.
|
|
95452
|
+
*/
|
|
95453
|
+
async syncFromDisk() {
|
|
95454
|
+
if (!this.file)
|
|
95455
|
+
return;
|
|
95456
|
+
let st3;
|
|
95457
|
+
try {
|
|
95458
|
+
st3 = await promises.stat(this.filePath);
|
|
95459
|
+
} catch (err) {
|
|
95460
|
+
if (isEnoent(err))
|
|
95461
|
+
return;
|
|
95462
|
+
throw err;
|
|
95463
|
+
}
|
|
95464
|
+
if (this.lastSynced && st3.mtimeMs === this.lastSynced.mtimeMs && st3.size === this.lastSynced.size) {
|
|
95465
|
+
return;
|
|
95466
|
+
}
|
|
95467
|
+
let parsed;
|
|
95468
|
+
try {
|
|
95469
|
+
parsed = JSON.parse(await promises.readFile(this.filePath, "utf8"));
|
|
95470
|
+
} catch {
|
|
95471
|
+
return;
|
|
95472
|
+
}
|
|
95473
|
+
if (parsed.version !== 1 || parsed.kdf !== "scrypt" || parsed.salt !== this.file.salt)
|
|
95474
|
+
return;
|
|
95475
|
+
this.file = { ...this.file, entries: mergeEntries(this.file.entries, parsed.entries ?? {}) };
|
|
95476
|
+
this.lastSynced = { mtimeMs: st3.mtimeMs, size: st3.size };
|
|
95477
|
+
}
|
|
95295
95478
|
/**
|
|
95296
95479
|
* Crash-atomic write: serialize to a sibling tmp file, then rename. POSIX
|
|
95297
95480
|
* rename is atomic, so a crash mid-write leaves the previous vault intact
|
|
@@ -95301,12 +95484,19 @@ var VaultStore = class {
|
|
|
95301
95484
|
if (!this.file)
|
|
95302
95485
|
return;
|
|
95303
95486
|
await writeFileAtomic(this.filePath, JSON.stringify(this.file, null, 2), { mode: 384 });
|
|
95487
|
+
try {
|
|
95488
|
+
const st3 = await promises.stat(this.filePath);
|
|
95489
|
+
this.lastSynced = { mtimeMs: st3.mtimeMs, size: st3.size };
|
|
95490
|
+
} catch {
|
|
95491
|
+
this.lastSynced = null;
|
|
95492
|
+
}
|
|
95304
95493
|
}
|
|
95305
95494
|
async set(name, value, tags) {
|
|
95306
95495
|
await this.open();
|
|
95307
95496
|
return this.mutex.run(async () => {
|
|
95308
95497
|
if (!this.file || !this.masterKey)
|
|
95309
95498
|
throw new Error("vault not open");
|
|
95499
|
+
await this.syncFromDisk();
|
|
95310
95500
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
95311
95501
|
const existing = this.file.entries[name];
|
|
95312
95502
|
const blob = encrypt(value, this.masterKey);
|
|
@@ -95327,6 +95517,7 @@ var VaultStore = class {
|
|
|
95327
95517
|
}
|
|
95328
95518
|
async get(name) {
|
|
95329
95519
|
await this.open();
|
|
95520
|
+
await this.mutex.run(() => this.syncFromDisk());
|
|
95330
95521
|
if (!this.file || !this.masterKey)
|
|
95331
95522
|
throw new Error("vault not open");
|
|
95332
95523
|
const entry = this.file.entries[name];
|
|
@@ -95336,6 +95527,7 @@ var VaultStore = class {
|
|
|
95336
95527
|
}
|
|
95337
95528
|
async has(name) {
|
|
95338
95529
|
await this.open();
|
|
95530
|
+
await this.mutex.run(() => this.syncFromDisk());
|
|
95339
95531
|
return Boolean(this.file?.entries[name]);
|
|
95340
95532
|
}
|
|
95341
95533
|
async delete(name) {
|
|
@@ -95343,6 +95535,7 @@ var VaultStore = class {
|
|
|
95343
95535
|
return this.mutex.run(async () => {
|
|
95344
95536
|
if (!this.file)
|
|
95345
95537
|
return false;
|
|
95538
|
+
await this.syncFromDisk();
|
|
95346
95539
|
if (!(name in this.file.entries))
|
|
95347
95540
|
return false;
|
|
95348
95541
|
const { [name]: _removed, ...rest } = this.file.entries;
|
|
@@ -95353,6 +95546,7 @@ var VaultStore = class {
|
|
|
95353
95546
|
}
|
|
95354
95547
|
async list() {
|
|
95355
95548
|
await this.open();
|
|
95549
|
+
await this.mutex.run(() => this.syncFromDisk());
|
|
95356
95550
|
if (!this.file)
|
|
95357
95551
|
return [];
|
|
95358
95552
|
return Object.entries(this.file.entries).map(([name, e3]) => ({
|
|
@@ -95363,6 +95557,18 @@ var VaultStore = class {
|
|
|
95363
95557
|
}));
|
|
95364
95558
|
}
|
|
95365
95559
|
};
|
|
95560
|
+
function mergeEntries(memory, disk) {
|
|
95561
|
+
const merged = { ...disk };
|
|
95562
|
+
for (const [name, mine] of Object.entries(memory)) {
|
|
95563
|
+
const theirs = merged[name];
|
|
95564
|
+
if (theirs && theirs.updatedAt >= mine.updatedAt)
|
|
95565
|
+
continue;
|
|
95566
|
+
if (!theirs)
|
|
95567
|
+
continue;
|
|
95568
|
+
merged[name] = mine;
|
|
95569
|
+
}
|
|
95570
|
+
return merged;
|
|
95571
|
+
}
|
|
95366
95572
|
function isEnoent(err) {
|
|
95367
95573
|
return err instanceof Error && "code" in err && err.code === "ENOENT";
|
|
95368
95574
|
}
|
|
@@ -97174,13 +97380,13 @@ var MultipartBody = class {
|
|
|
97174
97380
|
}
|
|
97175
97381
|
};
|
|
97176
97382
|
var fileFromPathWarned = false;
|
|
97177
|
-
async function fileFromPath3(
|
|
97383
|
+
async function fileFromPath3(path60, ...args) {
|
|
97178
97384
|
const { fileFromPath: _fileFromPath } = await Promise.resolve().then(() => (init_fileFromPath(), fileFromPath_exports));
|
|
97179
97385
|
if (!fileFromPathWarned) {
|
|
97180
|
-
console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(
|
|
97386
|
+
console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path60)}) instead`);
|
|
97181
97387
|
fileFromPathWarned = true;
|
|
97182
97388
|
}
|
|
97183
|
-
return await _fileFromPath(
|
|
97389
|
+
return await _fileFromPath(path60, ...args);
|
|
97184
97390
|
}
|
|
97185
97391
|
var defaultHttpAgent = new import_agentkeepalive.default({ keepAlive: true, timeout: 5 * 60 * 1e3 });
|
|
97186
97392
|
var defaultHttpsAgent = new import_agentkeepalive.default.HttpsAgent({ keepAlive: true, timeout: 5 * 60 * 1e3 });
|
|
@@ -97903,29 +98109,29 @@ var APIClient = class {
|
|
|
97903
98109
|
defaultIdempotencyKey() {
|
|
97904
98110
|
return `stainless-node-retry-${uuid4()}`;
|
|
97905
98111
|
}
|
|
97906
|
-
get(
|
|
97907
|
-
return this.methodRequest("get",
|
|
98112
|
+
get(path60, opts) {
|
|
98113
|
+
return this.methodRequest("get", path60, opts);
|
|
97908
98114
|
}
|
|
97909
|
-
post(
|
|
97910
|
-
return this.methodRequest("post",
|
|
98115
|
+
post(path60, opts) {
|
|
98116
|
+
return this.methodRequest("post", path60, opts);
|
|
97911
98117
|
}
|
|
97912
|
-
patch(
|
|
97913
|
-
return this.methodRequest("patch",
|
|
98118
|
+
patch(path60, opts) {
|
|
98119
|
+
return this.methodRequest("patch", path60, opts);
|
|
97914
98120
|
}
|
|
97915
|
-
put(
|
|
97916
|
-
return this.methodRequest("put",
|
|
98121
|
+
put(path60, opts) {
|
|
98122
|
+
return this.methodRequest("put", path60, opts);
|
|
97917
98123
|
}
|
|
97918
|
-
delete(
|
|
97919
|
-
return this.methodRequest("delete",
|
|
98124
|
+
delete(path60, opts) {
|
|
98125
|
+
return this.methodRequest("delete", path60, opts);
|
|
97920
98126
|
}
|
|
97921
|
-
methodRequest(method,
|
|
98127
|
+
methodRequest(method, path60, opts) {
|
|
97922
98128
|
return this.request(Promise.resolve(opts).then(async (opts2) => {
|
|
97923
98129
|
const body = opts2 && isBlobLike(opts2?.body) ? new DataView(await opts2.body.arrayBuffer()) : opts2?.body instanceof DataView ? opts2.body : opts2?.body instanceof ArrayBuffer ? new DataView(opts2.body) : opts2 && ArrayBuffer.isView(opts2?.body) ? new DataView(opts2.body.buffer) : opts2?.body;
|
|
97924
|
-
return { method, path:
|
|
98130
|
+
return { method, path: path60, ...opts2, body };
|
|
97925
98131
|
}));
|
|
97926
98132
|
}
|
|
97927
|
-
getAPIList(
|
|
97928
|
-
return this.requestAPIList(Page3, { method: "get", path:
|
|
98133
|
+
getAPIList(path60, Page3, opts) {
|
|
98134
|
+
return this.requestAPIList(Page3, { method: "get", path: path60, ...opts });
|
|
97929
98135
|
}
|
|
97930
98136
|
calculateContentLength(body) {
|
|
97931
98137
|
if (typeof body === "string") {
|
|
@@ -97944,10 +98150,10 @@ var APIClient = class {
|
|
|
97944
98150
|
}
|
|
97945
98151
|
buildRequest(inputOptions, { retryCount = 0 } = {}) {
|
|
97946
98152
|
const options = { ...inputOptions };
|
|
97947
|
-
const { method, path:
|
|
98153
|
+
const { method, path: path60, query, headers = {} } = options;
|
|
97948
98154
|
const body = ArrayBuffer.isView(options.body) || options.__binaryRequest && typeof options.body === "string" ? options.body : isMultipartBody(options.body) ? options.body.body : options.body ? JSON.stringify(options.body, null, 2) : null;
|
|
97949
98155
|
const contentLength = this.calculateContentLength(body);
|
|
97950
|
-
const url2 = this.buildURL(
|
|
98156
|
+
const url2 = this.buildURL(path60, query);
|
|
97951
98157
|
if ("timeout" in options)
|
|
97952
98158
|
validatePositiveInteger("timeout", options.timeout);
|
|
97953
98159
|
options.timeout = options.timeout ?? this.timeout;
|
|
@@ -98071,8 +98277,8 @@ var APIClient = class {
|
|
|
98071
98277
|
const request = this.makeRequest(options, null);
|
|
98072
98278
|
return new PagePromise(this, request, Page3);
|
|
98073
98279
|
}
|
|
98074
|
-
buildURL(
|
|
98075
|
-
const url2 = isAbsoluteURL(
|
|
98280
|
+
buildURL(path60, query) {
|
|
98281
|
+
const url2 = isAbsoluteURL(path60) ? new URL(path60) : new URL(this.baseURL + (this.baseURL.endsWith("/") && path60.startsWith("/") ? path60.slice(1) : path60));
|
|
98076
98282
|
const defaultQuery = this.defaultQuery();
|
|
98077
98283
|
if (!isEmptyObj(defaultQuery)) {
|
|
98078
98284
|
query = { ...defaultQuery, ...query };
|
|
@@ -101225,13 +101431,13 @@ var MultipartBody2 = class {
|
|
|
101225
101431
|
}
|
|
101226
101432
|
};
|
|
101227
101433
|
var fileFromPathWarned2 = false;
|
|
101228
|
-
async function fileFromPath5(
|
|
101434
|
+
async function fileFromPath5(path60, ...args) {
|
|
101229
101435
|
const { fileFromPath: _fileFromPath } = await Promise.resolve().then(() => (init_fileFromPath(), fileFromPath_exports));
|
|
101230
101436
|
if (!fileFromPathWarned2) {
|
|
101231
|
-
console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(
|
|
101437
|
+
console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path60)}) instead`);
|
|
101232
101438
|
fileFromPathWarned2 = true;
|
|
101233
101439
|
}
|
|
101234
|
-
return await _fileFromPath(
|
|
101440
|
+
return await _fileFromPath(path60, ...args);
|
|
101235
101441
|
}
|
|
101236
101442
|
var defaultHttpAgent2 = new import_agentkeepalive2.default({ keepAlive: true, timeout: 5 * 60 * 1e3 });
|
|
101237
101443
|
var defaultHttpsAgent2 = new import_agentkeepalive2.default.HttpsAgent({ keepAlive: true, timeout: 5 * 60 * 1e3 });
|
|
@@ -102009,29 +102215,29 @@ var APIClient2 = class {
|
|
|
102009
102215
|
defaultIdempotencyKey() {
|
|
102010
102216
|
return `stainless-node-retry-${uuid42()}`;
|
|
102011
102217
|
}
|
|
102012
|
-
get(
|
|
102013
|
-
return this.methodRequest("get",
|
|
102218
|
+
get(path60, opts) {
|
|
102219
|
+
return this.methodRequest("get", path60, opts);
|
|
102014
102220
|
}
|
|
102015
|
-
post(
|
|
102016
|
-
return this.methodRequest("post",
|
|
102221
|
+
post(path60, opts) {
|
|
102222
|
+
return this.methodRequest("post", path60, opts);
|
|
102017
102223
|
}
|
|
102018
|
-
patch(
|
|
102019
|
-
return this.methodRequest("patch",
|
|
102224
|
+
patch(path60, opts) {
|
|
102225
|
+
return this.methodRequest("patch", path60, opts);
|
|
102020
102226
|
}
|
|
102021
|
-
put(
|
|
102022
|
-
return this.methodRequest("put",
|
|
102227
|
+
put(path60, opts) {
|
|
102228
|
+
return this.methodRequest("put", path60, opts);
|
|
102023
102229
|
}
|
|
102024
|
-
delete(
|
|
102025
|
-
return this.methodRequest("delete",
|
|
102230
|
+
delete(path60, opts) {
|
|
102231
|
+
return this.methodRequest("delete", path60, opts);
|
|
102026
102232
|
}
|
|
102027
|
-
methodRequest(method,
|
|
102233
|
+
methodRequest(method, path60, opts) {
|
|
102028
102234
|
return this.request(Promise.resolve(opts).then(async (opts2) => {
|
|
102029
102235
|
const body = opts2 && isBlobLike2(opts2?.body) ? new DataView(await opts2.body.arrayBuffer()) : opts2?.body instanceof DataView ? opts2.body : opts2?.body instanceof ArrayBuffer ? new DataView(opts2.body) : opts2 && ArrayBuffer.isView(opts2?.body) ? new DataView(opts2.body.buffer) : opts2?.body;
|
|
102030
|
-
return { method, path:
|
|
102236
|
+
return { method, path: path60, ...opts2, body };
|
|
102031
102237
|
}));
|
|
102032
102238
|
}
|
|
102033
|
-
getAPIList(
|
|
102034
|
-
return this.requestAPIList(Page3, { method: "get", path:
|
|
102239
|
+
getAPIList(path60, Page3, opts) {
|
|
102240
|
+
return this.requestAPIList(Page3, { method: "get", path: path60, ...opts });
|
|
102035
102241
|
}
|
|
102036
102242
|
calculateContentLength(body) {
|
|
102037
102243
|
if (typeof body === "string") {
|
|
@@ -102050,10 +102256,10 @@ var APIClient2 = class {
|
|
|
102050
102256
|
}
|
|
102051
102257
|
buildRequest(inputOptions, { retryCount = 0 } = {}) {
|
|
102052
102258
|
const options = { ...inputOptions };
|
|
102053
|
-
const { method, path:
|
|
102259
|
+
const { method, path: path60, query, headers = {} } = options;
|
|
102054
102260
|
const body = ArrayBuffer.isView(options.body) || options.__binaryRequest && typeof options.body === "string" ? options.body : isMultipartBody2(options.body) ? options.body.body : options.body ? JSON.stringify(options.body, null, 2) : null;
|
|
102055
102261
|
const contentLength = this.calculateContentLength(body);
|
|
102056
|
-
const url2 = this.buildURL(
|
|
102262
|
+
const url2 = this.buildURL(path60, query);
|
|
102057
102263
|
if ("timeout" in options)
|
|
102058
102264
|
validatePositiveInteger2("timeout", options.timeout);
|
|
102059
102265
|
options.timeout = options.timeout ?? this.timeout;
|
|
@@ -102169,8 +102375,8 @@ var APIClient2 = class {
|
|
|
102169
102375
|
const request = this.makeRequest(options, null);
|
|
102170
102376
|
return new PagePromise2(this, request, Page3);
|
|
102171
102377
|
}
|
|
102172
|
-
buildURL(
|
|
102173
|
-
const url2 = isAbsoluteURL2(
|
|
102378
|
+
buildURL(path60, query) {
|
|
102379
|
+
const url2 = isAbsoluteURL2(path60) ? new URL(path60) : new URL(this.baseURL + (this.baseURL.endsWith("/") && path60.startsWith("/") ? path60.slice(1) : path60));
|
|
102174
102380
|
const defaultQuery = this.defaultQuery();
|
|
102175
102381
|
if (!isEmptyObj2(defaultQuery)) {
|
|
102176
102382
|
query = { ...defaultQuery, ...query };
|
|
@@ -107550,11 +107756,11 @@ function buildAuthUrl(input) {
|
|
|
107550
107756
|
}
|
|
107551
107757
|
async function runAuthorizationCodeFlow(opts) {
|
|
107552
107758
|
const port = opts.redirectPort ?? 8765;
|
|
107553
|
-
const
|
|
107759
|
+
const path60 = opts.redirectPath ?? "/callback";
|
|
107554
107760
|
const codeVerifier = generateCodeVerifier();
|
|
107555
107761
|
const codeChallenge = computeCodeChallenge(codeVerifier);
|
|
107556
107762
|
const state = generateState();
|
|
107557
|
-
const redirectUri = `http://localhost:${port}${
|
|
107763
|
+
const redirectUri = `http://localhost:${port}${path60}`;
|
|
107558
107764
|
const authUrl = buildAuthUrl({
|
|
107559
107765
|
authUrl: opts.authUrl,
|
|
107560
107766
|
clientId: opts.clientId,
|
|
@@ -107566,7 +107772,7 @@ async function runAuthorizationCodeFlow(opts) {
|
|
|
107566
107772
|
});
|
|
107567
107773
|
const codePromise = waitForCallback({
|
|
107568
107774
|
port,
|
|
107569
|
-
path:
|
|
107775
|
+
path: path60,
|
|
107570
107776
|
expectedState: state,
|
|
107571
107777
|
timeoutMs: opts.timeoutMs ?? 3e5,
|
|
107572
107778
|
...opts.signal ? { signal: opts.signal } : {}
|
|
@@ -107914,11 +108120,11 @@ function buildOauthAuthorizeTool(deps) {
|
|
|
107914
108120
|
const { computeCodeChallenge: computeCodeChallenge2 } = await Promise.resolve().then(() => (init_pkce(), pkce_exports));
|
|
107915
108121
|
const challenge = computeCodeChallenge2(verifier);
|
|
107916
108122
|
const port = input.redirectPort ?? 8765;
|
|
107917
|
-
const
|
|
108123
|
+
const path60 = input.redirectPath ?? "/callback";
|
|
107918
108124
|
const url2 = buildAuthUrl({
|
|
107919
108125
|
authUrl: input.authUrl,
|
|
107920
108126
|
clientId: input.clientId,
|
|
107921
|
-
redirectUri: `http://localhost:${port}${
|
|
108127
|
+
redirectUri: `http://localhost:${port}${path60}`,
|
|
107922
108128
|
scopes: input.scopes,
|
|
107923
108129
|
codeChallenge: challenge,
|
|
107924
108130
|
state,
|
|
@@ -108060,7 +108266,7 @@ async function runOauthLogin(profile, ctx) {
|
|
|
108060
108266
|
}
|
|
108061
108267
|
async function runBrowserFlow(profile, ctx) {
|
|
108062
108268
|
const port = profile.redirect?.port ?? 8765;
|
|
108063
|
-
const
|
|
108269
|
+
const path60 = profile.redirect?.path ?? "/callback";
|
|
108064
108270
|
const serviceName = profile.displayName ?? profile.id;
|
|
108065
108271
|
return runAuthorizationCodeFlow({
|
|
108066
108272
|
authUrl: profile.authUrl,
|
|
@@ -108069,7 +108275,7 @@ async function runBrowserFlow(profile, ctx) {
|
|
|
108069
108275
|
...profile.clientSecret ? { clientSecret: profile.clientSecret } : {},
|
|
108070
108276
|
scopes: profile.scopes,
|
|
108071
108277
|
redirectPort: port,
|
|
108072
|
-
redirectPath:
|
|
108278
|
+
redirectPath: path60,
|
|
108073
108279
|
...profile.extraAuthParams ? { extraAuthParams: profile.extraAuthParams } : {},
|
|
108074
108280
|
timeoutMs: DEFAULT_BROWSER_TIMEOUT_MS,
|
|
108075
108281
|
...ctx.signal ? { signal: ctx.signal } : {},
|
|
@@ -108081,7 +108287,7 @@ If your browser doesn't open automatically, paste this URL:
|
|
|
108081
108287
|
|
|
108082
108288
|
${url2}
|
|
108083
108289
|
|
|
108084
|
-
Waiting for callback on http://localhost:${port}${
|
|
108290
|
+
Waiting for callback on http://localhost:${port}${path60} (5 min timeout)\u2026
|
|
108085
108291
|
|
|
108086
108292
|
`);
|
|
108087
108293
|
}
|
|
@@ -108125,6 +108331,81 @@ Polling every ${Math.round(init3.intervalMs / 1e3)}s (${Math.round(init3.expires
|
|
|
108125
108331
|
...ctx.signal ? { signal: ctx.signal } : {}
|
|
108126
108332
|
});
|
|
108127
108333
|
}
|
|
108334
|
+
var DEFAULT_STALE_MS = 6e4;
|
|
108335
|
+
var DEFAULT_POLL_MS = 150;
|
|
108336
|
+
var DEFAULT_WAIT_MS = 3e4;
|
|
108337
|
+
var inProcessLocks = /* @__PURE__ */ new Map();
|
|
108338
|
+
async function withCredentialLock(key, fn, opts = {}) {
|
|
108339
|
+
const safe2 = sanitizeKey(key);
|
|
108340
|
+
let mutex = inProcessLocks.get(safe2);
|
|
108341
|
+
if (!mutex) {
|
|
108342
|
+
mutex = createMutex();
|
|
108343
|
+
inProcessLocks.set(safe2, mutex);
|
|
108344
|
+
}
|
|
108345
|
+
return mutex.run(async () => {
|
|
108346
|
+
const release = await acquireFileLock(join(opts.dir ?? moxxyPath("locks"), `${safe2}.lock`), opts.staleMs ?? DEFAULT_STALE_MS, opts.pollMs ?? DEFAULT_POLL_MS, opts.waitMs ?? DEFAULT_WAIT_MS);
|
|
108347
|
+
try {
|
|
108348
|
+
return await fn();
|
|
108349
|
+
} finally {
|
|
108350
|
+
await release();
|
|
108351
|
+
}
|
|
108352
|
+
});
|
|
108353
|
+
}
|
|
108354
|
+
function isAuthRejection(err) {
|
|
108355
|
+
return err instanceof MoxxyError && (err.code === "AUTH_INVALID" || err.code === "AUTH_DENIED" || err.code === "AUTH_EXPIRED" || err.code === "PROVIDER_BAD_REQUEST");
|
|
108356
|
+
}
|
|
108357
|
+
function sanitizeKey(key) {
|
|
108358
|
+
return key.replace(/[^a-zA-Z0-9._-]+/g, "_");
|
|
108359
|
+
}
|
|
108360
|
+
async function acquireFileLock(lockPath, staleMs, pollMs, waitMs) {
|
|
108361
|
+
const deadline = Date.now() + waitMs;
|
|
108362
|
+
try {
|
|
108363
|
+
await mkdir(dirname(lockPath), { recursive: true });
|
|
108364
|
+
} catch {
|
|
108365
|
+
return async () => {
|
|
108366
|
+
};
|
|
108367
|
+
}
|
|
108368
|
+
for (; ; ) {
|
|
108369
|
+
try {
|
|
108370
|
+
const handle2 = await open(lockPath, "wx");
|
|
108371
|
+
try {
|
|
108372
|
+
await handle2.writeFile(`${process.pid} ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
108373
|
+
`, "utf8");
|
|
108374
|
+
} finally {
|
|
108375
|
+
await handle2.close().catch(() => {
|
|
108376
|
+
});
|
|
108377
|
+
}
|
|
108378
|
+
return async () => {
|
|
108379
|
+
await rm(lockPath, { force: true }).catch(() => {
|
|
108380
|
+
});
|
|
108381
|
+
};
|
|
108382
|
+
} catch (err) {
|
|
108383
|
+
if (err.code !== "EEXIST") {
|
|
108384
|
+
return async () => {
|
|
108385
|
+
};
|
|
108386
|
+
}
|
|
108387
|
+
}
|
|
108388
|
+
try {
|
|
108389
|
+
const st3 = await stat(lockPath);
|
|
108390
|
+
if (Date.now() - st3.mtimeMs > staleMs) {
|
|
108391
|
+
await rm(lockPath, { force: true }).catch(() => {
|
|
108392
|
+
});
|
|
108393
|
+
continue;
|
|
108394
|
+
}
|
|
108395
|
+
} catch {
|
|
108396
|
+
continue;
|
|
108397
|
+
}
|
|
108398
|
+
if (Date.now() >= deadline)
|
|
108399
|
+
return async () => {
|
|
108400
|
+
};
|
|
108401
|
+
await sleep4(pollMs);
|
|
108402
|
+
}
|
|
108403
|
+
}
|
|
108404
|
+
function sleep4(ms) {
|
|
108405
|
+
return new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
108406
|
+
}
|
|
108407
|
+
|
|
108408
|
+
// ../plugin-oauth/dist/ensure-fresh.js
|
|
108128
108409
|
async function ensureFreshTokens(profile, vault, opts = {}) {
|
|
108129
108410
|
const stored = await readStoredCreds(vault, profile.id);
|
|
108130
108411
|
if (!stored) {
|
|
@@ -108138,6 +108419,16 @@ async function ensureFreshTokens(profile, vault, opts = {}) {
|
|
|
108138
108419
|
if (!opts.force && !isExpired(stored.tokenSet, opts.skewMs)) {
|
|
108139
108420
|
return { tokens: stored.tokenSet, extras: stored.extras };
|
|
108140
108421
|
}
|
|
108422
|
+
return withCredentialLock(`oauth-${profile.id}`, async () => {
|
|
108423
|
+
const current = await readStoredCreds(vault, profile.id) ?? stored;
|
|
108424
|
+
const rotatedMeanwhile = current.tokenSet.accessToken !== stored.tokenSet.accessToken;
|
|
108425
|
+
if (!isExpired(current.tokenSet, opts.skewMs) && (!opts.force || rotatedMeanwhile)) {
|
|
108426
|
+
return { tokens: current.tokenSet, extras: current.extras };
|
|
108427
|
+
}
|
|
108428
|
+
return refreshAndStore(profile, vault, current);
|
|
108429
|
+
});
|
|
108430
|
+
}
|
|
108431
|
+
async function refreshAndStore(profile, vault, stored, retried = false) {
|
|
108141
108432
|
if (!stored.tokenSet.refreshToken) {
|
|
108142
108433
|
throw new MoxxyError({
|
|
108143
108434
|
code: "AUTH_EXPIRED",
|
|
@@ -108155,6 +108446,12 @@ async function ensureFreshTokens(profile, vault, opts = {}) {
|
|
|
108155
108446
|
refreshToken: stored.tokenSet.refreshToken
|
|
108156
108447
|
});
|
|
108157
108448
|
} catch (err) {
|
|
108449
|
+
if (!retried && isAuthRejection(err)) {
|
|
108450
|
+
const latest = await readStoredCreds(vault, profile.id);
|
|
108451
|
+
if (latest?.tokenSet.refreshToken && latest.tokenSet.refreshToken !== stored.tokenSet.refreshToken) {
|
|
108452
|
+
return refreshAndStore(profile, vault, latest, true);
|
|
108453
|
+
}
|
|
108454
|
+
}
|
|
108158
108455
|
const net3 = classifyNetworkError(err, { url: stored.tokenUrl, provider: profile.id });
|
|
108159
108456
|
if (net3)
|
|
108160
108457
|
throw net3;
|
|
@@ -108278,8 +108575,6 @@ function buildOauthPlugin(opts) {
|
|
|
108278
108575
|
]
|
|
108279
108576
|
});
|
|
108280
108577
|
}
|
|
108281
|
-
|
|
108282
|
-
// ../plugin-provider-openai-codex/dist/oauth.js
|
|
108283
108578
|
var CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
108284
108579
|
var ISSUER = "https://auth.openai.com";
|
|
108285
108580
|
var AUTHORIZE_URL = `${ISSUER}/oauth/authorize`;
|
|
@@ -108678,6 +108973,7 @@ var CodexProvider = class {
|
|
|
108678
108973
|
models = codexModels;
|
|
108679
108974
|
tokens;
|
|
108680
108975
|
onTokensRefreshed;
|
|
108976
|
+
reloadTokens;
|
|
108681
108977
|
defaultModel;
|
|
108682
108978
|
fetchImpl;
|
|
108683
108979
|
sessionIdProvider;
|
|
@@ -108686,6 +108982,8 @@ var CodexProvider = class {
|
|
|
108686
108982
|
this.tokens = config.tokens;
|
|
108687
108983
|
if (config.onTokensRefreshed)
|
|
108688
108984
|
this.onTokensRefreshed = config.onTokensRefreshed;
|
|
108985
|
+
if (config.reloadTokens)
|
|
108986
|
+
this.reloadTokens = config.reloadTokens;
|
|
108689
108987
|
this.defaultModel = config.defaultModel ?? DEFAULT_CODEX_MODEL;
|
|
108690
108988
|
this.fetchImpl = config.fetch ?? fetch;
|
|
108691
108989
|
const defaultSessionId = webcrypto.randomUUID();
|
|
@@ -108753,19 +109051,52 @@ var CodexProvider = class {
|
|
|
108753
109051
|
return;
|
|
108754
109052
|
await this.refreshNow();
|
|
108755
109053
|
}
|
|
109054
|
+
/**
|
|
109055
|
+
* Refresh + persist under the per-credential lock. The refresh token is
|
|
109056
|
+
* SINGLE-USE (rotated + invalidated on every refresh), so concurrent
|
|
109057
|
+
* refreshers — a second stream in this process, the whisper-stt
|
|
109058
|
+
* transcriber sharing this credential, or another moxxy process — must
|
|
109059
|
+
* serialize and coalesce: whoever holds the lock refreshes once, everyone
|
|
109060
|
+
* queued behind it adopts the rotated bundle instead of burning it.
|
|
109061
|
+
*/
|
|
108756
109062
|
async refreshNow() {
|
|
108757
|
-
|
|
109063
|
+
const entry = this.tokens;
|
|
109064
|
+
if (!entry) {
|
|
108758
109065
|
throw new Error("Cannot refresh \u2014 no stored tokens.");
|
|
108759
109066
|
}
|
|
108760
|
-
|
|
108761
|
-
|
|
108762
|
-
|
|
108763
|
-
|
|
108764
|
-
|
|
108765
|
-
|
|
108766
|
-
|
|
109067
|
+
await withCredentialLock(`oauth-${this.name}`, async () => {
|
|
109068
|
+
if (this.tokens && this.tokens.access !== entry.access)
|
|
109069
|
+
return;
|
|
109070
|
+
let attempt = this.tokens ?? entry;
|
|
109071
|
+
if (this.reloadTokens) {
|
|
109072
|
+
const latest = await this.reloadTokens().catch(() => null);
|
|
109073
|
+
if (latest && latest.access !== attempt.access && latest.expires > Date.now() + 6e4) {
|
|
109074
|
+
this.tokens = withAccountId(latest, latest.accountId ?? attempt.accountId);
|
|
109075
|
+
return;
|
|
109076
|
+
}
|
|
109077
|
+
if (latest?.refresh)
|
|
109078
|
+
attempt = { ...attempt, refresh: latest.refresh };
|
|
109079
|
+
}
|
|
109080
|
+
let next;
|
|
109081
|
+
try {
|
|
109082
|
+
next = await refreshTokens(attempt.refresh, this.fetchImpl);
|
|
109083
|
+
} catch (err) {
|
|
109084
|
+
const latest = isAuthRejection(err) && this.reloadTokens ? await this.reloadTokens().catch(() => null) : null;
|
|
109085
|
+
if (!latest?.refresh || latest.refresh === attempt.refresh)
|
|
109086
|
+
throw err;
|
|
109087
|
+
next = await refreshTokens(latest.refresh, this.fetchImpl);
|
|
109088
|
+
}
|
|
109089
|
+
const merged = withAccountId(next, next.accountId ?? attempt.accountId);
|
|
109090
|
+
this.tokens = merged;
|
|
109091
|
+
if (this.onTokensRefreshed) {
|
|
109092
|
+
await this.onTokensRefreshed(merged);
|
|
109093
|
+
}
|
|
109094
|
+
});
|
|
108767
109095
|
}
|
|
108768
109096
|
};
|
|
109097
|
+
function withAccountId(tokens, accountId) {
|
|
109098
|
+
return accountId ? { access: tokens.access, refresh: tokens.refresh, expires: tokens.expires, accountId } : { access: tokens.access, refresh: tokens.refresh, expires: tokens.expires };
|
|
109099
|
+
}
|
|
108769
109100
|
|
|
108770
109101
|
// ../plugin-provider-openai-codex/dist/profile.js
|
|
108771
109102
|
var CODEX_PROVIDER_ID = "openai-codex";
|
|
@@ -109002,9 +109333,9 @@ async function ensureFreshClaudeTokens(vault) {
|
|
|
109002
109333
|
const stored = await readStoredCreds(vault, CLAUDE_CODE_PROVIDER_ID);
|
|
109003
109334
|
if (!stored)
|
|
109004
109335
|
return null;
|
|
109005
|
-
const { tokenSet
|
|
109336
|
+
const { tokenSet } = stored;
|
|
109006
109337
|
if (tokenSet.refreshToken && isExpired(tokenSet)) {
|
|
109007
|
-
const refreshed = await
|
|
109338
|
+
const refreshed = await refreshClaudeUnderLock(vault, stored);
|
|
109008
109339
|
return { accessToken: refreshed.accessToken, ...refreshed.expiresAt !== void 0 ? { expiresAt: refreshed.expiresAt } : {}, canRefresh: true };
|
|
109009
109340
|
}
|
|
109010
109341
|
return {
|
|
@@ -109023,9 +109354,39 @@ async function refreshClaudeAccessToken(vault) {
|
|
|
109023
109354
|
context: { provider: CLAUDE_CODE_PROVIDER_ID }
|
|
109024
109355
|
});
|
|
109025
109356
|
}
|
|
109026
|
-
const refreshed = await
|
|
109357
|
+
const refreshed = await refreshClaudeUnderLock(vault, stored);
|
|
109027
109358
|
return { token: refreshed.accessToken, ...refreshed.expiresAt !== void 0 ? { expiresAt: refreshed.expiresAt } : {} };
|
|
109028
109359
|
}
|
|
109360
|
+
async function refreshClaudeUnderLock(vault, baseline) {
|
|
109361
|
+
return withCredentialLock(`oauth-${CLAUDE_CODE_PROVIDER_ID}`, async () => {
|
|
109362
|
+
const current = await readStoredCreds(vault, CLAUDE_CODE_PROVIDER_ID) ?? baseline;
|
|
109363
|
+
if (current.tokenSet.accessToken !== baseline.tokenSet.accessToken && !isExpired(current.tokenSet)) {
|
|
109364
|
+
return current.tokenSet;
|
|
109365
|
+
}
|
|
109366
|
+
const refreshToken = current.tokenSet.refreshToken ?? baseline.tokenSet.refreshToken;
|
|
109367
|
+
if (!refreshToken) {
|
|
109368
|
+
throw new MoxxyError({
|
|
109369
|
+
code: "AUTH_EXPIRED",
|
|
109370
|
+
message: "Claude token expired and no refresh_token is stored.",
|
|
109371
|
+
hint: "Run `moxxy login claude-code` again, or refresh `CLAUDE_CODE_OAUTH_TOKEN` via `claude setup-token`.",
|
|
109372
|
+
context: { provider: CLAUDE_CODE_PROVIDER_ID }
|
|
109373
|
+
});
|
|
109374
|
+
}
|
|
109375
|
+
const email = current.extras.account_email ?? baseline.extras.account_email;
|
|
109376
|
+
try {
|
|
109377
|
+
return await refreshAndPersist(vault, refreshToken, email);
|
|
109378
|
+
} catch (err) {
|
|
109379
|
+
if (isAuthRejection(err)) {
|
|
109380
|
+
const latest = await readStoredCreds(vault, CLAUDE_CODE_PROVIDER_ID);
|
|
109381
|
+
const latestRefresh = latest?.tokenSet.refreshToken;
|
|
109382
|
+
if (latestRefresh && latestRefresh !== refreshToken) {
|
|
109383
|
+
return refreshAndPersist(vault, latestRefresh, latest.extras.account_email ?? email);
|
|
109384
|
+
}
|
|
109385
|
+
}
|
|
109386
|
+
throw err;
|
|
109387
|
+
}
|
|
109388
|
+
});
|
|
109389
|
+
}
|
|
109029
109390
|
var fetchImpl = fetch;
|
|
109030
109391
|
var openBrowserImpl = openInBrowser;
|
|
109031
109392
|
var sleepImpl = (ms) => new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
@@ -109480,6 +109841,49 @@ function globToRegExp(pattern) {
|
|
|
109480
109841
|
}
|
|
109481
109842
|
|
|
109482
109843
|
// ../tools-builtin/dist/bash.js
|
|
109844
|
+
var OUTPUT_LIMIT = 2e5;
|
|
109845
|
+
var STREAM_RETAIN_CAP = OUTPUT_LIMIT + 4096;
|
|
109846
|
+
var SIGKILL_GRACE_MS = 2e3;
|
|
109847
|
+
function killTree(child, signal) {
|
|
109848
|
+
if (child.pid === void 0)
|
|
109849
|
+
return;
|
|
109850
|
+
if (process.platform === "win32") {
|
|
109851
|
+
if (child.exitCode === null && child.signalCode === null)
|
|
109852
|
+
child.kill(signal);
|
|
109853
|
+
return;
|
|
109854
|
+
}
|
|
109855
|
+
try {
|
|
109856
|
+
process.kill(-child.pid, signal);
|
|
109857
|
+
} catch (e3) {
|
|
109858
|
+
if (e3.code !== "ESRCH") {
|
|
109859
|
+
if (child.exitCode === null && child.signalCode === null)
|
|
109860
|
+
child.kill(signal);
|
|
109861
|
+
}
|
|
109862
|
+
}
|
|
109863
|
+
}
|
|
109864
|
+
function boundedSink(cap) {
|
|
109865
|
+
let text = "";
|
|
109866
|
+
let dropped = 0;
|
|
109867
|
+
return {
|
|
109868
|
+
push(b3) {
|
|
109869
|
+
const s2 = b3.toString("utf8");
|
|
109870
|
+
const room = cap - text.length;
|
|
109871
|
+
if (room >= s2.length) {
|
|
109872
|
+
text += s2;
|
|
109873
|
+
} else {
|
|
109874
|
+
if (room > 0)
|
|
109875
|
+
text += s2.slice(0, room);
|
|
109876
|
+
dropped += s2.length - Math.max(room, 0);
|
|
109877
|
+
}
|
|
109878
|
+
},
|
|
109879
|
+
get text() {
|
|
109880
|
+
return text;
|
|
109881
|
+
},
|
|
109882
|
+
get dropped() {
|
|
109883
|
+
return dropped;
|
|
109884
|
+
}
|
|
109885
|
+
};
|
|
109886
|
+
}
|
|
109483
109887
|
var bashTool = defineTool({
|
|
109484
109888
|
name: "Bash",
|
|
109485
109889
|
description: "Run a shell command via /bin/sh. Respects the abort signal. Returns combined stdout/stderr with exit code.",
|
|
@@ -109516,41 +109920,60 @@ var bashTool = defineTool({
|
|
|
109516
109920
|
const child = spawn("/bin/sh", ["-lc", command], {
|
|
109517
109921
|
cwd: cwd2 ?? ctx.cwd,
|
|
109518
109922
|
env: env3 ? { ...process.env, ...env3 } : process.env,
|
|
109519
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
109520
|
-
|
|
109521
|
-
|
|
109522
|
-
|
|
109523
|
-
|
|
109524
|
-
|
|
109525
|
-
});
|
|
109526
|
-
child.stderr.on("data", (b3) => {
|
|
109527
|
-
err += b3.toString("utf8");
|
|
109923
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
109924
|
+
// Own process group on POSIX so timeout/abort can kill the whole
|
|
109925
|
+
// tree via a negative-pid signal. `detached` only detaches the
|
|
109926
|
+
// controlling terminal/group — our piped stdio and exit reporting
|
|
109927
|
+
// are unaffected. Not meaningful on win32 (would open a console).
|
|
109928
|
+
detached: process.platform !== "win32"
|
|
109528
109929
|
});
|
|
109930
|
+
const out = boundedSink(STREAM_RETAIN_CAP);
|
|
109931
|
+
const err = boundedSink(STREAM_RETAIN_CAP);
|
|
109932
|
+
child.stdout.on("data", out.push);
|
|
109933
|
+
child.stderr.on("data", err.push);
|
|
109934
|
+
let killTimer;
|
|
109935
|
+
const terminate2 = () => {
|
|
109936
|
+
killTree(child, "SIGTERM");
|
|
109937
|
+
killTimer ??= setTimeout(() => {
|
|
109938
|
+
killTree(child, "SIGKILL");
|
|
109939
|
+
}, SIGKILL_GRACE_MS);
|
|
109940
|
+
killTimer.unref();
|
|
109941
|
+
};
|
|
109529
109942
|
const timer = setTimeout(() => {
|
|
109530
|
-
|
|
109943
|
+
terminate2();
|
|
109531
109944
|
reject(new MoxxyError({
|
|
109532
109945
|
code: "ABORTED",
|
|
109533
109946
|
message: `Bash timed out after ${timeoutMs}ms: ${command}`
|
|
109534
109947
|
}));
|
|
109535
109948
|
}, timeoutMs);
|
|
109536
109949
|
const onAbort = () => {
|
|
109537
|
-
|
|
109950
|
+
terminate2();
|
|
109538
109951
|
};
|
|
109539
109952
|
ctx.signal.addEventListener("abort", onAbort, { once: true });
|
|
109540
109953
|
child.on("error", (e3) => {
|
|
109541
109954
|
clearTimeout(timer);
|
|
109955
|
+
if (killTimer !== void 0)
|
|
109956
|
+
clearTimeout(killTimer);
|
|
109542
109957
|
ctx.signal.removeEventListener("abort", onAbort);
|
|
109543
109958
|
reject(e3);
|
|
109544
109959
|
});
|
|
109545
109960
|
child.on("close", (code) => {
|
|
109546
109961
|
clearTimeout(timer);
|
|
109962
|
+
if (killTimer !== void 0)
|
|
109963
|
+
clearTimeout(killTimer);
|
|
109547
109964
|
ctx.signal.removeEventListener("abort", onAbort);
|
|
109548
|
-
const combined = (out ? `[stdout]
|
|
109549
|
-
${out.trimEnd()}
|
|
109550
|
-
` : "") + (err ? `[stderr]
|
|
109551
|
-
${err.trimEnd()}
|
|
109965
|
+
const combined = (out.text ? `[stdout]
|
|
109966
|
+
${out.text.trimEnd()}
|
|
109967
|
+
` : "") + (err.text ? `[stderr]
|
|
109968
|
+
${err.text.trimEnd()}
|
|
109552
109969
|
` : "") + `[exit ${code ?? "null"}]`;
|
|
109553
|
-
|
|
109970
|
+
const dropped = out.dropped + err.dropped;
|
|
109971
|
+
if (dropped === 0) {
|
|
109972
|
+
resolve12(clampString(combined, OUTPUT_LIMIT));
|
|
109973
|
+
} else {
|
|
109974
|
+
resolve12(combined.slice(0, OUTPUT_LIMIT) + `
|
|
109975
|
+
... [truncated ${combined.length + dropped - OUTPUT_LIMIT} chars]`);
|
|
109976
|
+
}
|
|
109554
109977
|
});
|
|
109555
109978
|
});
|
|
109556
109979
|
}
|
|
@@ -110238,9 +110661,15 @@ async function* runGoalMode(ctx) {
|
|
|
110238
110661
|
});
|
|
110239
110662
|
return;
|
|
110240
110663
|
}
|
|
110664
|
+
const sessionResolver = ctx.permissions;
|
|
110241
110665
|
const autoApprove = {
|
|
110242
110666
|
name: "goal-auto-approve",
|
|
110243
|
-
check: async () =>
|
|
110667
|
+
check: async (call, permCtx) => {
|
|
110668
|
+
const policy = await sessionResolver.policyCheck?.(call, permCtx) ?? null;
|
|
110669
|
+
if (policy)
|
|
110670
|
+
return policy;
|
|
110671
|
+
return { mode: "allow", reason: "goal mode runs tools unattended (auto-approve)" };
|
|
110672
|
+
}
|
|
110244
110673
|
};
|
|
110245
110674
|
const goalCtx = {
|
|
110246
110675
|
...ctx,
|
|
@@ -112497,12 +112926,20 @@ async function performSessionAction(ctx, action, notice, state, deps, cb) {
|
|
|
112497
112926
|
if (state.turnController && !state.turnController.signal.aborted) {
|
|
112498
112927
|
state.turnController.abort("user reset");
|
|
112499
112928
|
}
|
|
112500
|
-
state.session.log.clear();
|
|
112501
112929
|
deps.framePump.resetRenderer();
|
|
112502
112930
|
cb.setYolo(false);
|
|
112503
112931
|
cb.setAwaitingApprovalText(null);
|
|
112504
112932
|
deps.approvalResolver.abortAll("session reset");
|
|
112505
112933
|
deps.permissionResolver.abortAll("session reset");
|
|
112934
|
+
try {
|
|
112935
|
+
if (typeof state.session.reset === "function")
|
|
112936
|
+
await state.session.reset();
|
|
112937
|
+
else
|
|
112938
|
+
state.session.log.clear();
|
|
112939
|
+
} catch (err) {
|
|
112940
|
+
await ctx.reply(`\u26A0 /new failed: ${err instanceof Error ? err.message : String(err)} \u2014 history NOT cleared`);
|
|
112941
|
+
return;
|
|
112942
|
+
}
|
|
112506
112943
|
await ctx.reply(`\u2713 ${notice ?? "new session \u2014 conversation history cleared"}`);
|
|
112507
112944
|
}
|
|
112508
112945
|
}
|
|
@@ -114302,6 +114739,13 @@ var HttpChannel = class {
|
|
|
114302
114739
|
authToken;
|
|
114303
114740
|
logger;
|
|
114304
114741
|
server = null;
|
|
114742
|
+
boundPortValue = 0;
|
|
114743
|
+
/** The actual TCP port the server bound to after {@link start}. Equals the
|
|
114744
|
+
* configured port, or the OS-assigned one when `port: 0` (ephemeral) — so
|
|
114745
|
+
* callers (and tests) can address the server without guessing a free port. */
|
|
114746
|
+
get boundPort() {
|
|
114747
|
+
return this.boundPortValue;
|
|
114748
|
+
}
|
|
114305
114749
|
constructor(opts = {}) {
|
|
114306
114750
|
this.port = opts.port ?? 3737;
|
|
114307
114751
|
this.host = opts.host ?? "127.0.0.1";
|
|
@@ -114341,9 +114785,11 @@ var HttpChannel = class {
|
|
|
114341
114785
|
const listening = new Promise((resolve12, reject) => {
|
|
114342
114786
|
server.once("error", reject);
|
|
114343
114787
|
server.listen(this.port, this.host, () => {
|
|
114788
|
+
const addr = server.address();
|
|
114789
|
+
this.boundPortValue = typeof addr === "object" && addr ? addr.port : this.port;
|
|
114344
114790
|
this.logger?.info?.("http channel listening", {
|
|
114345
114791
|
host: this.host,
|
|
114346
|
-
port: this.
|
|
114792
|
+
port: this.boundPortValue,
|
|
114347
114793
|
authEnabled: this.authToken !== null
|
|
114348
114794
|
});
|
|
114349
114795
|
resolve12();
|
|
@@ -114472,8 +114918,16 @@ var EventProjector = class {
|
|
|
114472
114918
|
}
|
|
114473
114919
|
}
|
|
114474
114920
|
};
|
|
114475
|
-
|
|
114476
|
-
|
|
114921
|
+
var clientFrameSchema = z.discriminatedUnion("kind", [
|
|
114922
|
+
z.object({ kind: z.literal("prompt"), text: z.string() }),
|
|
114923
|
+
z.object({
|
|
114924
|
+
kind: z.literal("action"),
|
|
114925
|
+
actionId: z.string(),
|
|
114926
|
+
viewId: z.string().nullable(),
|
|
114927
|
+
action: z.object({ name: z.string(), params: z.record(z.unknown()).optional() }),
|
|
114928
|
+
formValues: z.record(z.string())
|
|
114929
|
+
})
|
|
114930
|
+
]);
|
|
114477
114931
|
function actionPrompt(action, formValues) {
|
|
114478
114932
|
const payload = JSON.stringify({ action: action.name, ...action.params ? { params: action.params } : {}, values: formValues });
|
|
114479
114933
|
return [
|
|
@@ -114485,54 +114939,74 @@ function actionPrompt(action, formValues) {
|
|
|
114485
114939
|
}
|
|
114486
114940
|
|
|
114487
114941
|
// ../plugin-channel-web/dist/channel.js
|
|
114942
|
+
var MAX_FRAME_BYTES = 256 * 1024;
|
|
114943
|
+
var DROP_WARN_INTERVAL_MS = 1e4;
|
|
114488
114944
|
function isAddrInUse(err) {
|
|
114489
114945
|
return !!err && typeof err === "object" && err.code === "EADDRINUSE";
|
|
114490
114946
|
}
|
|
114491
|
-
async function
|
|
114492
|
-
if (process.platform === "win32")
|
|
114493
|
-
return;
|
|
114947
|
+
async function captureStdout(cmd, args) {
|
|
114494
114948
|
const { spawn: spawn17 } = await import('child_process');
|
|
114495
|
-
|
|
114949
|
+
return await new Promise((resolve12) => {
|
|
114496
114950
|
let out = "";
|
|
114497
114951
|
try {
|
|
114498
|
-
const child = spawn17("
|
|
114499
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
114500
|
-
});
|
|
114952
|
+
const child = spawn17(cmd, [...args], { stdio: ["ignore", "pipe", "ignore"] });
|
|
114501
114953
|
child.stdout.on("data", (b3) => {
|
|
114502
114954
|
out += b3.toString();
|
|
114503
114955
|
});
|
|
114504
|
-
child.on("error", () => resolve12(
|
|
114505
|
-
child.on("close", () =>
|
|
114506
|
-
const found = /* @__PURE__ */ new Set();
|
|
114507
|
-
for (const line of out.split("\n")) {
|
|
114508
|
-
const n2 = parseInt(line.trim(), 10);
|
|
114509
|
-
if (Number.isFinite(n2) && n2 > 0)
|
|
114510
|
-
found.add(n2);
|
|
114511
|
-
}
|
|
114512
|
-
resolve12([...found]);
|
|
114513
|
-
});
|
|
114956
|
+
child.on("error", () => resolve12(""));
|
|
114957
|
+
child.on("close", () => resolve12(out));
|
|
114514
114958
|
} catch {
|
|
114515
|
-
resolve12(
|
|
114959
|
+
resolve12("");
|
|
114516
114960
|
}
|
|
114517
114961
|
});
|
|
114518
|
-
|
|
114519
|
-
|
|
114520
|
-
|
|
114962
|
+
}
|
|
114963
|
+
async function pidsListeningOn(port) {
|
|
114964
|
+
if (process.platform === "win32")
|
|
114965
|
+
return [];
|
|
114966
|
+
const out = await captureStdout("lsof", ["-t", `-iTCP:${port}`, "-sTCP:LISTEN"]);
|
|
114967
|
+
const found = /* @__PURE__ */ new Set();
|
|
114968
|
+
for (const line of out.split("\n")) {
|
|
114969
|
+
const n2 = parseInt(line.trim(), 10);
|
|
114970
|
+
if (Number.isFinite(n2) && n2 > 0)
|
|
114971
|
+
found.add(n2);
|
|
114972
|
+
}
|
|
114973
|
+
return [...found];
|
|
114974
|
+
}
|
|
114975
|
+
async function pidCommand(pid) {
|
|
114976
|
+
return (await captureStdout("ps", ["-p", String(pid), "-o", "command="])).trim();
|
|
114977
|
+
}
|
|
114978
|
+
function looksLikeMoxxy(command) {
|
|
114979
|
+
return command.length > 0 && /moxxy/i.test(command);
|
|
114980
|
+
}
|
|
114981
|
+
async function freeTcpPortIfMoxxy(port, logger) {
|
|
114982
|
+
if (process.platform === "win32")
|
|
114983
|
+
return false;
|
|
114984
|
+
const pids = (await pidsListeningOn(port)).filter((pid) => pid !== process.pid);
|
|
114985
|
+
if (pids.length === 0)
|
|
114986
|
+
return false;
|
|
114987
|
+
const holders = await Promise.all(pids.map(async (pid) => ({ pid, command: await pidCommand(pid) })));
|
|
114988
|
+
const foreign = holders.filter((h3) => !looksLikeMoxxy(h3.command));
|
|
114989
|
+
if (foreign.length > 0) {
|
|
114990
|
+
logger?.warn?.(`port ${port} is held by non-moxxy process(es); not killing them`, {
|
|
114991
|
+
holders: foreign.map((h3) => `${h3.pid}: ${h3.command || "<unknown command>"}`)
|
|
114992
|
+
});
|
|
114993
|
+
return false;
|
|
114994
|
+
}
|
|
114995
|
+
for (const { pid } of holders) {
|
|
114521
114996
|
try {
|
|
114522
114997
|
process.kill(pid, "SIGTERM");
|
|
114523
114998
|
} catch {
|
|
114524
114999
|
}
|
|
114525
115000
|
}
|
|
114526
115001
|
await new Promise((r2) => setTimeout(r2, 400));
|
|
114527
|
-
for (const pid of
|
|
114528
|
-
if (pid === process.pid)
|
|
114529
|
-
continue;
|
|
115002
|
+
for (const { pid } of holders) {
|
|
114530
115003
|
try {
|
|
114531
115004
|
process.kill(pid, 0);
|
|
114532
115005
|
process.kill(pid, "SIGKILL");
|
|
114533
115006
|
} catch {
|
|
114534
115007
|
}
|
|
114535
115008
|
}
|
|
115009
|
+
return true;
|
|
114536
115010
|
}
|
|
114537
115011
|
var PUBLIC_DIR = path3.join(path3.dirname(fileURLToPath(import.meta.url)), "public");
|
|
114538
115012
|
var WebChannel = class {
|
|
@@ -114557,6 +115031,8 @@ var WebChannel = class {
|
|
|
114557
115031
|
tunnel = null;
|
|
114558
115032
|
tunnelBase = null;
|
|
114559
115033
|
viewSeq = 0;
|
|
115034
|
+
droppedFrames = 0;
|
|
115035
|
+
lastDropWarnAt = 0;
|
|
114560
115036
|
constructor(opts = {}) {
|
|
114561
115037
|
this.port = opts.port ?? 4040;
|
|
114562
115038
|
this.host = opts.host ?? "127.0.0.1";
|
|
@@ -114591,14 +115067,19 @@ var WebChannel = class {
|
|
|
114591
115067
|
void this.handleHttp(req, res);
|
|
114592
115068
|
});
|
|
114593
115069
|
this.server = server;
|
|
115070
|
+
await this.bindServerWithRetry(server);
|
|
114594
115071
|
const wss = new import_websocket_server.default({
|
|
114595
115072
|
server,
|
|
114596
115073
|
path: "/ws",
|
|
115074
|
+
// Frames past this are dropped at the socket layer (ws closes with
|
|
115075
|
+
// 1009) instead of being buffered into memory. onMessage applies a
|
|
115076
|
+
// tighter MAX_FRAME_BYTES cap of its own.
|
|
115077
|
+
maxPayload: 1024 * 1024,
|
|
114597
115078
|
verifyClient: (info) => this.validToken(info.req.url)
|
|
114598
115079
|
});
|
|
114599
115080
|
this.wss = wss;
|
|
114600
115081
|
wss.on("connection", (ws) => this.onConnection(ws));
|
|
114601
|
-
|
|
115082
|
+
wss.on("error", (err) => this.logger?.warn?.("web socket server error", { err: String(err) }));
|
|
114602
115083
|
await this.openTunnel();
|
|
114603
115084
|
this.publishSurface?.({ url: this.shareUrl, nextViewId: () => `v_srv_${++this.viewSeq}` });
|
|
114604
115085
|
this.publishControls?.({ retunnel: () => this.retunnel() });
|
|
@@ -114606,11 +115087,13 @@ var WebChannel = class {
|
|
|
114606
115087
|
return { running, stop: () => this.stop() };
|
|
114607
115088
|
}
|
|
114608
115089
|
/**
|
|
114609
|
-
* Bind the HTTP server, with
|
|
114610
|
-
*
|
|
114611
|
-
*
|
|
114612
|
-
*
|
|
114613
|
-
*
|
|
115090
|
+
* Bind the HTTP server, with recovery if the port is already in use.
|
|
115091
|
+
* A stale `moxxy serve` from a prior install often leaves 4040 bound
|
|
115092
|
+
* even after its unix socket has been released — if (and only if) the
|
|
115093
|
+
* holder is verifiably a moxxy process we kill it and retry. Anything
|
|
115094
|
+
* else (ngrok's local UI also defaults to 4040) is never signalled;
|
|
115095
|
+
* we bind an ephemeral port instead and log loudly which port the
|
|
115096
|
+
* surface actually got (the share URL embeds the real port either way).
|
|
114614
115097
|
*/
|
|
114615
115098
|
async bindServerWithRetry(server) {
|
|
114616
115099
|
const tryListen = () => new Promise((resolve12, reject) => {
|
|
@@ -114632,13 +115115,26 @@ var WebChannel = class {
|
|
|
114632
115115
|
});
|
|
114633
115116
|
try {
|
|
114634
115117
|
await tryListen();
|
|
115118
|
+
return;
|
|
114635
115119
|
} catch (err) {
|
|
114636
115120
|
if (!isAddrInUse(err))
|
|
114637
115121
|
throw err;
|
|
114638
|
-
this.logger?.warn?.(`web channel port ${this.port} in use; freeing and retrying`);
|
|
114639
|
-
await freeTcpPort(this.port).catch(() => void 0);
|
|
114640
|
-
await tryListen();
|
|
114641
115122
|
}
|
|
115123
|
+
const requested = this.port;
|
|
115124
|
+
const freed = await freeTcpPortIfMoxxy(requested, this.logger).catch(() => false);
|
|
115125
|
+
if (freed) {
|
|
115126
|
+
this.logger?.warn?.(`web channel port ${requested} was held by a stale moxxy process; freed it, retrying`);
|
|
115127
|
+
try {
|
|
115128
|
+
await tryListen();
|
|
115129
|
+
return;
|
|
115130
|
+
} catch (err) {
|
|
115131
|
+
if (!isAddrInUse(err))
|
|
115132
|
+
throw err;
|
|
115133
|
+
}
|
|
115134
|
+
}
|
|
115135
|
+
this.port = 0;
|
|
115136
|
+
await tryListen();
|
|
115137
|
+
this.logger?.warn?.(`web channel port ${requested} was in use by another process; bound ephemeral port ${this.port} instead`, { requestedPort: requested, boundPort: this.port, url: this.url });
|
|
114642
115138
|
}
|
|
114643
115139
|
/**
|
|
114644
115140
|
* (Re-)open the tunnel via the active provider, closing any prior one FIRST so
|
|
@@ -114744,13 +115240,31 @@ var WebChannel = class {
|
|
|
114744
115240
|
for (const frame of this.views.values())
|
|
114745
115241
|
this.send(ws, frame);
|
|
114746
115242
|
}
|
|
115243
|
+
/**
|
|
115244
|
+
* Handle a browser → server frame. This is a trust boundary (tunnels put
|
|
115245
|
+
* it on the public internet): every frame is schema-validated before any
|
|
115246
|
+
* field access, and invalid ones are dropped — a thrown error in a ws
|
|
115247
|
+
* 'message' listener escalates to a process-level uncaughtException.
|
|
115248
|
+
*/
|
|
114747
115249
|
onMessage(ws, data) {
|
|
114748
|
-
|
|
115250
|
+
const raw = String(data);
|
|
115251
|
+
if (raw.length > MAX_FRAME_BYTES) {
|
|
115252
|
+
this.dropFrame("oversized frame");
|
|
115253
|
+
return;
|
|
115254
|
+
}
|
|
115255
|
+
let parsed;
|
|
114749
115256
|
try {
|
|
114750
|
-
|
|
115257
|
+
parsed = JSON.parse(raw);
|
|
114751
115258
|
} catch {
|
|
115259
|
+
this.dropFrame("invalid JSON");
|
|
114752
115260
|
return;
|
|
114753
115261
|
}
|
|
115262
|
+
const result = clientFrameSchema.safeParse(parsed);
|
|
115263
|
+
if (!result.success) {
|
|
115264
|
+
this.dropFrame("schema mismatch");
|
|
115265
|
+
return;
|
|
115266
|
+
}
|
|
115267
|
+
const frame = result.data;
|
|
114754
115268
|
if (frame.kind === "prompt") {
|
|
114755
115269
|
if (frame.text.trim())
|
|
114756
115270
|
void this.drive(frame.text);
|
|
@@ -114765,6 +115279,18 @@ var WebChannel = class {
|
|
|
114765
115279
|
void this.drive(actionPrompt(frame.action, frame.formValues));
|
|
114766
115280
|
}
|
|
114767
115281
|
}
|
|
115282
|
+
/** Count a dropped inbound frame; warn at most once per window (no log spam). */
|
|
115283
|
+
dropFrame(reason) {
|
|
115284
|
+
this.droppedFrames += 1;
|
|
115285
|
+
const now = Date.now();
|
|
115286
|
+
if (now - this.lastDropWarnAt < DROP_WARN_INTERVAL_MS)
|
|
115287
|
+
return;
|
|
115288
|
+
this.lastDropWarnAt = now;
|
|
115289
|
+
this.logger?.warn?.("web channel dropped invalid client frame(s)", {
|
|
115290
|
+
reason,
|
|
115291
|
+
droppedTotal: this.droppedFrames
|
|
115292
|
+
});
|
|
115293
|
+
}
|
|
114768
115294
|
async drive(prompt) {
|
|
114769
115295
|
if (!this.session || this.busy)
|
|
114770
115296
|
return;
|
|
@@ -115056,28 +115582,65 @@ buildWebChannelPlugin();
|
|
|
115056
115582
|
// ../ipc-server-ws/dist/ws-transport.js
|
|
115057
115583
|
init_wrapper();
|
|
115058
115584
|
var BEARER = "Bearer ";
|
|
115059
|
-
function checkWsAuth(req, expected) {
|
|
115585
|
+
function checkWsAuth(req, expected, opts = {}) {
|
|
115060
115586
|
const guard2 = bearerGuard(expected);
|
|
115061
115587
|
const auth2 = req.headers.authorization;
|
|
115062
115588
|
if (auth2 && auth2.startsWith(BEARER) && guard2(auth2.slice(BEARER.length)))
|
|
115063
115589
|
return true;
|
|
115064
|
-
|
|
115065
|
-
|
|
115066
|
-
|
|
115067
|
-
|
|
115068
|
-
|
|
115590
|
+
const fromProtocol = tokenFromWsProtocolHeader(req.headers["sec-websocket-protocol"]);
|
|
115591
|
+
if (fromProtocol !== null && guard2(fromProtocol))
|
|
115592
|
+
return true;
|
|
115593
|
+
if (opts.allowQueryToken) {
|
|
115594
|
+
try {
|
|
115595
|
+
const url2 = new URL(req.url ?? "/", "http://localhost");
|
|
115596
|
+
if (guard2(url2.searchParams.get("t")))
|
|
115597
|
+
return true;
|
|
115598
|
+
} catch {
|
|
115599
|
+
}
|
|
115069
115600
|
}
|
|
115070
115601
|
return false;
|
|
115071
115602
|
}
|
|
115603
|
+
function checkWsOrigin(req, allowedOrigins = []) {
|
|
115604
|
+
const origin = req.headers.origin;
|
|
115605
|
+
if (!origin)
|
|
115606
|
+
return true;
|
|
115607
|
+
const lower2 = origin.toLowerCase();
|
|
115608
|
+
return allowedOrigins.some((allowed) => allowed.toLowerCase() === lower2);
|
|
115609
|
+
}
|
|
115072
115610
|
|
|
115073
115611
|
// ../ipc-server-ws/dist/ws-transport.js
|
|
115612
|
+
var DEFAULT_MAX_CONNECTIONS = 8;
|
|
115613
|
+
var DEFAULT_MAX_BUFFERED_BYTES = 4 * 1024 * 1024;
|
|
115614
|
+
var DEFAULT_BUFFER_STALL_GRACE_MS = 1e4;
|
|
115615
|
+
var SlowReaderGuard = class {
|
|
115616
|
+
limitBytes;
|
|
115617
|
+
graceMs;
|
|
115618
|
+
stalledSinceMs = null;
|
|
115619
|
+
constructor(limitBytes = DEFAULT_MAX_BUFFERED_BYTES, graceMs = DEFAULT_BUFFER_STALL_GRACE_MS) {
|
|
115620
|
+
this.limitBytes = limitBytes;
|
|
115621
|
+
this.graceMs = graceMs;
|
|
115622
|
+
}
|
|
115623
|
+
check(bufferedAmount, nowMs) {
|
|
115624
|
+
if (bufferedAmount <= this.limitBytes) {
|
|
115625
|
+
this.stalledSinceMs = null;
|
|
115626
|
+
return "ok";
|
|
115627
|
+
}
|
|
115628
|
+
if (this.stalledSinceMs === null) {
|
|
115629
|
+
this.stalledSinceMs = nowMs;
|
|
115630
|
+
return "ok";
|
|
115631
|
+
}
|
|
115632
|
+
return nowMs - this.stalledSinceMs >= this.graceMs ? "terminate" : "ok";
|
|
115633
|
+
}
|
|
115634
|
+
};
|
|
115074
115635
|
var WsTransport = class {
|
|
115075
115636
|
ws;
|
|
115637
|
+
guard;
|
|
115076
115638
|
frameHandler = null;
|
|
115077
115639
|
closeHandler = null;
|
|
115078
115640
|
closeEmitted = false;
|
|
115079
|
-
constructor(ws) {
|
|
115641
|
+
constructor(ws, guard2) {
|
|
115080
115642
|
this.ws = ws;
|
|
115643
|
+
this.guard = guard2;
|
|
115081
115644
|
ws.on("message", (data) => {
|
|
115082
115645
|
let parsed;
|
|
115083
115646
|
try {
|
|
@@ -115091,8 +115654,14 @@ var WsTransport = class {
|
|
|
115091
115654
|
ws.on("error", (err) => this.emitClose(err));
|
|
115092
115655
|
}
|
|
115093
115656
|
send(frame) {
|
|
115094
|
-
if (this.ws.readyState
|
|
115095
|
-
|
|
115657
|
+
if (this.ws.readyState !== this.ws.OPEN)
|
|
115658
|
+
return;
|
|
115659
|
+
if (this.guard.check(this.ws.bufferedAmount, Date.now()) === "terminate") {
|
|
115660
|
+
console.warn(`[moxxy] ws bridge: evicting slow reader (${this.ws.bufferedAmount} bytes unread past grace)`);
|
|
115661
|
+
this.ws.terminate();
|
|
115662
|
+
return;
|
|
115663
|
+
}
|
|
115664
|
+
this.ws.send(JSON.stringify(frame));
|
|
115096
115665
|
}
|
|
115097
115666
|
onFrame(handler) {
|
|
115098
115667
|
this.frameHandler = handler;
|
|
@@ -115115,15 +115684,35 @@ async function createWebSocketTransportServer(opts) {
|
|
|
115115
115684
|
throw new Error("createWebSocketTransportServer: authToken is required \u2014 this surface is network-reachable");
|
|
115116
115685
|
}
|
|
115117
115686
|
const host = opts.host ?? "127.0.0.1";
|
|
115687
|
+
const maxConnections = opts.maxConnections ?? DEFAULT_MAX_CONNECTIONS;
|
|
115688
|
+
let currentToken = opts.authToken;
|
|
115689
|
+
let connections = 0;
|
|
115118
115690
|
const wss = new import_websocket_server.default({
|
|
115119
115691
|
host,
|
|
115120
115692
|
port: opts.port,
|
|
115121
115693
|
maxPayload: opts.maxPayloadBytes ?? 64 * 1024 * 1024,
|
|
115122
|
-
verifyClient: (info) =>
|
|
115694
|
+
verifyClient: (info) => {
|
|
115695
|
+
if (!checkWsOrigin(info.req, opts.allowedOrigins)) {
|
|
115696
|
+
console.warn(`[moxxy] ws bridge: rejected browser-origin upgrade (Origin: ${String(info.req.headers.origin)})`);
|
|
115697
|
+
return false;
|
|
115698
|
+
}
|
|
115699
|
+
if (connections >= maxConnections) {
|
|
115700
|
+
console.warn(`[moxxy] ws bridge: rejected upgrade \u2014 connection cap (${maxConnections}) reached`);
|
|
115701
|
+
return false;
|
|
115702
|
+
}
|
|
115703
|
+
return checkWsAuth(info.req, currentToken, { allowQueryToken: opts.allowQueryToken });
|
|
115704
|
+
},
|
|
115705
|
+
// When the client offers subprotocols (the moxxy.bearer.* convention),
|
|
115706
|
+
// select the moxxy protocol WITHOUT echoing the token-bearing entry back.
|
|
115707
|
+
handleProtocols: (protocols) => protocols.has(MOXXY_WS_SUBPROTOCOL) ? MOXXY_WS_SUBPROTOCOL : false
|
|
115123
115708
|
});
|
|
115124
115709
|
const connectionHandlers = [];
|
|
115125
115710
|
wss.on("connection", (ws) => {
|
|
115126
|
-
|
|
115711
|
+
connections += 1;
|
|
115712
|
+
ws.once("close", () => {
|
|
115713
|
+
connections -= 1;
|
|
115714
|
+
});
|
|
115715
|
+
const transport = new WsTransport(ws, new SlowReaderGuard(opts.maxBufferedBytes, opts.bufferStallGraceMs));
|
|
115127
115716
|
for (const handler of connectionHandlers)
|
|
115128
115717
|
handler(transport);
|
|
115129
115718
|
});
|
|
@@ -115131,13 +115720,24 @@ async function createWebSocketTransportServer(opts) {
|
|
|
115131
115720
|
wss.once("error", reject);
|
|
115132
115721
|
wss.once("listening", resolve12);
|
|
115133
115722
|
});
|
|
115723
|
+
const bound = wss.address();
|
|
115724
|
+
const boundPort = typeof bound === "object" && bound !== null ? bound.port : opts.port;
|
|
115134
115725
|
return {
|
|
115135
|
-
address: `ws://${host}:${
|
|
115726
|
+
address: `ws://${host}:${boundPort}`,
|
|
115136
115727
|
onConnection(handler) {
|
|
115137
115728
|
connectionHandlers.push(handler);
|
|
115138
115729
|
},
|
|
115730
|
+
rotateAuthToken(next) {
|
|
115731
|
+
currentToken = next;
|
|
115732
|
+
for (const client of wss.clients)
|
|
115733
|
+
client.terminate();
|
|
115734
|
+
},
|
|
115139
115735
|
close() {
|
|
115140
|
-
return new Promise((resolve12) =>
|
|
115736
|
+
return new Promise((resolve12) => {
|
|
115737
|
+
for (const client of wss.clients)
|
|
115738
|
+
client.terminate();
|
|
115739
|
+
wss.close(() => resolve12());
|
|
115740
|
+
});
|
|
115141
115741
|
}
|
|
115142
115742
|
};
|
|
115143
115743
|
}
|
|
@@ -115268,6 +115868,12 @@ var JsonRpcPeer = class {
|
|
|
115268
115868
|
this.closeHandlers.length = 0;
|
|
115269
115869
|
}
|
|
115270
115870
|
};
|
|
115871
|
+
var stderrLogger = {
|
|
115872
|
+
warn: (msg, meta) => process.stderr.write(`[moxxy-runner] WARN ${msg} ${meta ? JSON.stringify(meta) : ""}
|
|
115873
|
+
`),
|
|
115874
|
+
error: (msg, meta) => process.stderr.write(`[moxxy-runner] ERROR ${msg} ${meta ? JSON.stringify(meta) : ""}
|
|
115875
|
+
`)
|
|
115876
|
+
};
|
|
115271
115877
|
var NdjsonTransport = class {
|
|
115272
115878
|
socket;
|
|
115273
115879
|
buffer = "";
|
|
@@ -115322,10 +115928,12 @@ var NdjsonTransport = class {
|
|
|
115322
115928
|
this.socket.end();
|
|
115323
115929
|
}
|
|
115324
115930
|
};
|
|
115325
|
-
async function createUnixSocketServer(socketPath) {
|
|
115931
|
+
async function createUnixSocketServer(socketPath, logger = stderrLogger) {
|
|
115326
115932
|
if (process.platform !== "win32") {
|
|
115327
115933
|
await reclaimStaleSocket(socketPath);
|
|
115328
|
-
|
|
115934
|
+
secureSocketDir(path3__default.dirname(socketPath), logger);
|
|
115935
|
+
} else {
|
|
115936
|
+
warnWindowsPipeAclOnce(logger, socketPath);
|
|
115329
115937
|
}
|
|
115330
115938
|
const connectionHandlers = [];
|
|
115331
115939
|
const server = net.createServer((socket) => {
|
|
@@ -115343,7 +115951,11 @@ async function createUnixSocketServer(socketPath) {
|
|
|
115343
115951
|
if (process.platform !== "win32") {
|
|
115344
115952
|
try {
|
|
115345
115953
|
fs27__default.chmodSync(socketPath, 384);
|
|
115346
|
-
} catch {
|
|
115954
|
+
} catch (err) {
|
|
115955
|
+
logger.error("failed to chmod runner socket to 0600", {
|
|
115956
|
+
socketPath,
|
|
115957
|
+
error: err instanceof Error ? err.message : String(err)
|
|
115958
|
+
});
|
|
115347
115959
|
}
|
|
115348
115960
|
}
|
|
115349
115961
|
return {
|
|
@@ -115380,6 +115992,31 @@ function connectUnixSocket(socketPath) {
|
|
|
115380
115992
|
});
|
|
115381
115993
|
});
|
|
115382
115994
|
}
|
|
115995
|
+
function secureSocketDir(dir, logger) {
|
|
115996
|
+
fs27__default.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
115997
|
+
try {
|
|
115998
|
+
const st3 = fs27__default.statSync(dir);
|
|
115999
|
+
if ((st3.mode & 63) === 0)
|
|
116000
|
+
return;
|
|
116001
|
+
if (typeof process.getuid === "function" && st3.uid !== process.getuid()) {
|
|
116002
|
+
logger.warn("runner socket directory is accessible to other users and not owned by this process; cannot tighten to 0700", { dir });
|
|
116003
|
+
return;
|
|
116004
|
+
}
|
|
116005
|
+
fs27__default.chmodSync(dir, 448);
|
|
116006
|
+
} catch (err) {
|
|
116007
|
+
logger.error("failed to restrict runner socket directory to 0700", {
|
|
116008
|
+
dir,
|
|
116009
|
+
error: err instanceof Error ? err.message : String(err)
|
|
116010
|
+
});
|
|
116011
|
+
}
|
|
116012
|
+
}
|
|
116013
|
+
var warnedWindowsPipeAcl = false;
|
|
116014
|
+
function warnWindowsPipeAclOnce(logger, pipePath) {
|
|
116015
|
+
if (warnedWindowsPipeAcl)
|
|
116016
|
+
return;
|
|
116017
|
+
warnedWindowsPipeAcl = true;
|
|
116018
|
+
logger.warn("runner named pipe relies on the Windows default DACL (creator/SYSTEM/Administrators: full control; Everyone: read-only) - no explicit ACL is applied", { pipePath });
|
|
116019
|
+
}
|
|
115383
116020
|
async function reclaimStaleSocket(socketPath) {
|
|
115384
116021
|
if (!fs27__default.existsSync(socketPath))
|
|
115385
116022
|
return;
|
|
@@ -115425,7 +116062,7 @@ function isRunnerUp(socketPath = runnerSocketPath()) {
|
|
|
115425
116062
|
|
|
115426
116063
|
// ../runner/dist/server.js
|
|
115427
116064
|
init_dist();
|
|
115428
|
-
var RUNNER_PROTOCOL_VERSION =
|
|
116065
|
+
var RUNNER_PROTOCOL_VERSION = 3;
|
|
115429
116066
|
var RunnerMethod = {
|
|
115430
116067
|
/** client->server: handshake; returns the initial info snapshot. */
|
|
115431
116068
|
Attach: "attach",
|
|
@@ -115435,6 +116072,14 @@ var RunnerMethod = {
|
|
|
115435
116072
|
RunTurn: "runTurn",
|
|
115436
116073
|
/** client->server: abort an in-flight turn. */
|
|
115437
116074
|
Abort: "abort",
|
|
116075
|
+
/**
|
|
116076
|
+
* client->server: `/new` — abort every in-flight turn, clear the runner's
|
|
116077
|
+
* authoritative event log (and, via the log's clear listeners, truncate
|
|
116078
|
+
* the persisted session JSONL so `--resume` can't resurrect the wiped
|
|
116079
|
+
* history). The runner broadcasts the `session.reset` notification to ALL
|
|
116080
|
+
* attached clients so every mirror clears in lockstep.
|
|
116081
|
+
*/
|
|
116082
|
+
SessionReset: "session.reset",
|
|
115438
116083
|
/** client->server: declare which resolvers this client will answer. */
|
|
115439
116084
|
SetResolver: "setResolver",
|
|
115440
116085
|
/** client->server: switch the active mode. */
|
|
@@ -115472,7 +116117,14 @@ var RunnerNotification = {
|
|
|
115472
116117
|
/** A turn finished (cleanly or with an error). */
|
|
115473
116118
|
TurnComplete: "turn.complete",
|
|
115474
116119
|
/** The registry snapshot changed (plugin reload, mode switch, …). */
|
|
115475
|
-
InfoChanged: "info.changed"
|
|
116120
|
+
InfoChanged: "info.changed",
|
|
116121
|
+
/**
|
|
116122
|
+
* The runner's event log was reset (`/new` from any client, or a
|
|
116123
|
+
* self-hosting channel clearing the local log directly). Mirrors MUST
|
|
116124
|
+
* clear: post-reset events restart at seq 0, which a seq-contiguous
|
|
116125
|
+
* mirror only accepts from an empty log.
|
|
116126
|
+
*/
|
|
116127
|
+
SessionReset: "session.reset"
|
|
115476
116128
|
};
|
|
115477
116129
|
var attachmentSchema = z.object({
|
|
115478
116130
|
kind: z.string(),
|
|
@@ -115539,6 +116191,7 @@ var RunnerServer = class {
|
|
|
115539
116191
|
turnControllers = /* @__PURE__ */ new Map();
|
|
115540
116192
|
scope = new AsyncLocalStorage();
|
|
115541
116193
|
logUnsub;
|
|
116194
|
+
logClearUnsub;
|
|
115542
116195
|
modesUnsub;
|
|
115543
116196
|
/**
|
|
115544
116197
|
* Resolvers for unscoped (local) turns - the fall-through path. Seeded from
|
|
@@ -115557,6 +116210,7 @@ var RunnerServer = class {
|
|
|
115557
116210
|
this.installRoutingResolvers();
|
|
115558
116211
|
this.transport.onConnection((t2) => this.onConnection(t2));
|
|
115559
116212
|
this.logUnsub = session.log.subscribe((event) => this.broadcastEvent(event));
|
|
116213
|
+
this.logClearUnsub = session.log.onClear(() => this.broadcast(RunnerNotification.SessionReset, {}));
|
|
115560
116214
|
this.modesUnsub = session.modes.onActiveChange(() => this.broadcastInfo());
|
|
115561
116215
|
}
|
|
115562
116216
|
get address() {
|
|
@@ -115567,6 +116221,7 @@ var RunnerServer = class {
|
|
|
115567
116221
|
return;
|
|
115568
116222
|
this.closed = true;
|
|
115569
116223
|
this.logUnsub();
|
|
116224
|
+
this.logClearUnsub();
|
|
115570
116225
|
this.modesUnsub();
|
|
115571
116226
|
for (const client of this.clients)
|
|
115572
116227
|
client.peer.close();
|
|
@@ -115588,7 +116243,8 @@ var RunnerServer = class {
|
|
|
115588
116243
|
peer.handle(RunnerMethod.Attach, (raw) => this.handleAttach(client, raw));
|
|
115589
116244
|
peer.handle(RunnerMethod.GetInfo, () => this.session.getInfo());
|
|
115590
116245
|
peer.handle(RunnerMethod.RunTurn, (raw) => this.handleRunTurn(client, raw));
|
|
115591
|
-
peer.handle(RunnerMethod.Abort, (raw) => this.handleAbort(raw));
|
|
116246
|
+
peer.handle(RunnerMethod.Abort, (raw) => this.handleAbort(client, raw));
|
|
116247
|
+
peer.handle(RunnerMethod.SessionReset, () => this.handleSessionReset());
|
|
115592
116248
|
peer.handle(RunnerMethod.SetResolver, (raw) => this.handleSetResolver(client, raw));
|
|
115593
116249
|
peer.handle(RunnerMethod.ModeSetActive, (raw) => this.handleModeSetActive(raw));
|
|
115594
116250
|
peer.handle(RunnerMethod.ProviderSetActive, (raw) => this.handleProviderSetActive(raw));
|
|
@@ -115607,7 +116263,7 @@ var RunnerServer = class {
|
|
|
115607
116263
|
onDisconnect(client) {
|
|
115608
116264
|
this.clients.delete(client);
|
|
115609
116265
|
for (const turnId of client.turns) {
|
|
115610
|
-
this.turnControllers.get(turnId)?.abort("owning client disconnected");
|
|
116266
|
+
this.turnControllers.get(turnId)?.controller.abort("owning client disconnected");
|
|
115611
116267
|
}
|
|
115612
116268
|
}
|
|
115613
116269
|
// --- request handlers ----------------------------------------------------
|
|
@@ -115631,7 +116287,7 @@ var RunnerServer = class {
|
|
|
115631
116287
|
const params = runTurnParamsSchema.parse(raw);
|
|
115632
116288
|
const turnId = newTurnId();
|
|
115633
116289
|
const controller = new AbortController();
|
|
115634
|
-
this.turnControllers.set(turnId, controller);
|
|
116290
|
+
this.turnControllers.set(turnId, { controller, owner: client });
|
|
115635
116291
|
client.turns.add(turnId);
|
|
115636
116292
|
const opts = {
|
|
115637
116293
|
turnId,
|
|
@@ -115660,9 +116316,39 @@ var RunnerServer = class {
|
|
|
115660
116316
|
});
|
|
115661
116317
|
return { turnId };
|
|
115662
116318
|
}
|
|
115663
|
-
handleAbort(raw) {
|
|
116319
|
+
handleAbort(client, raw) {
|
|
115664
116320
|
const params = abortParamsSchema.parse(raw);
|
|
115665
|
-
this.turnControllers.get(params.turnId)
|
|
116321
|
+
const entry = this.turnControllers.get(params.turnId);
|
|
116322
|
+
if (!entry)
|
|
116323
|
+
return {};
|
|
116324
|
+
if (entry.owner !== client) {
|
|
116325
|
+
this.session.logger.warn("cross-client abort", {
|
|
116326
|
+
turnId: params.turnId,
|
|
116327
|
+
ownerRole: entry.owner.role,
|
|
116328
|
+
abortingRole: client.role
|
|
116329
|
+
});
|
|
116330
|
+
if (process.env.MOXXY_RUNNER_STRICT_ABORT === "1") {
|
|
116331
|
+
throw new Error(`turn ${params.turnId} was started by '${entry.owner.role}'; cross-client abort denied (MOXXY_RUNNER_STRICT_ABORT=1)`);
|
|
116332
|
+
}
|
|
116333
|
+
}
|
|
116334
|
+
entry.controller.abort("client requested abort");
|
|
116335
|
+
return {};
|
|
116336
|
+
}
|
|
116337
|
+
/**
|
|
116338
|
+
* `/new` from any attached client. Aborts every in-flight turn (whoever
|
|
116339
|
+
* started it — the wipe is session-global), then clears the authoritative
|
|
116340
|
+
* log. The clear cascades: the log's clear listeners broadcast the
|
|
116341
|
+
* `session.reset` notification to all attached mirrors (wired in the
|
|
116342
|
+
* ctor) and truncate the persistence sidecar's JSONL. An aborted turn may
|
|
116343
|
+
* still flush a final event after the wipe; it lands in the fresh log at
|
|
116344
|
+
* seq 0+ and is broadcast AFTER the reset notification (single ordered
|
|
116345
|
+
* socket), so mirrors stay contiguous either way.
|
|
116346
|
+
*/
|
|
116347
|
+
handleSessionReset() {
|
|
116348
|
+
for (const entry of this.turnControllers.values()) {
|
|
116349
|
+
entry.controller.abort("session reset");
|
|
116350
|
+
}
|
|
116351
|
+
this.session.log.clear();
|
|
115666
116352
|
return {};
|
|
115667
116353
|
}
|
|
115668
116354
|
handleSetResolver(client, raw) {
|
|
@@ -115873,7 +116559,7 @@ function defaultApproval(request) {
|
|
|
115873
116559
|
return { optionId: request.defaultOptionId ?? request.options[0]?.id ?? "" };
|
|
115874
116560
|
}
|
|
115875
116561
|
async function startRunnerServer(session, opts = {}) {
|
|
115876
|
-
const transport = opts.transport ?? await createUnixSocketServer(opts.socketPath ?? runnerSocketPath());
|
|
116562
|
+
const transport = opts.transport ?? await createUnixSocketServer(opts.socketPath ?? runnerSocketPath(), session.logger);
|
|
115877
116563
|
return new RunnerServer(session, transport);
|
|
115878
116564
|
}
|
|
115879
116565
|
|
|
@@ -115962,6 +116648,9 @@ var RemoteSession = class {
|
|
|
115962
116648
|
this.peer.on(RunnerNotification.InfoChanged, (params) => {
|
|
115963
116649
|
this.info = params.info;
|
|
115964
116650
|
});
|
|
116651
|
+
this.peer.on(RunnerNotification.SessionReset, () => {
|
|
116652
|
+
this.mirror.clear();
|
|
116653
|
+
});
|
|
115965
116654
|
this.peer.handle(RunnerMethod.PermissionCheck, (params) => {
|
|
115966
116655
|
const { call, ctx } = params;
|
|
115967
116656
|
if (!this.permissionResolver) {
|
|
@@ -116019,6 +116708,17 @@ var RemoteSession = class {
|
|
|
116019
116708
|
get log() {
|
|
116020
116709
|
return this.mirror;
|
|
116021
116710
|
}
|
|
116711
|
+
/**
|
|
116712
|
+
* `SessionLike.reset` — server-authoritative `/new`. The runner aborts
|
|
116713
|
+
* in-flight turns, clears its log + persisted JSONL, and broadcasts
|
|
116714
|
+
* `session.reset`; our mirror clears when that notification lands (it is
|
|
116715
|
+
* sent before this RPC's reply on the same ordered socket, so the mirror
|
|
116716
|
+
* is already empty by the time this resolves). Rejects when the runner is
|
|
116717
|
+
* unreachable — callers must surface that instead of claiming success.
|
|
116718
|
+
*/
|
|
116719
|
+
async reset() {
|
|
116720
|
+
await this.peer.request(RunnerMethod.SessionReset, {});
|
|
116721
|
+
}
|
|
116022
116722
|
getInfo() {
|
|
116023
116723
|
return this.requireInfo();
|
|
116024
116724
|
}
|
|
@@ -116317,13 +117017,41 @@ async function killAndUnlinkRunner(socketPath, ports = DEFAULT_RUNNER_PORTS) {
|
|
|
116317
117017
|
}
|
|
116318
117018
|
async function killProcessOwning(socketPath) {
|
|
116319
117019
|
const pids = await pidsListeningOnSocket(socketPath);
|
|
116320
|
-
for (const pid of pids)
|
|
116321
|
-
await
|
|
117020
|
+
for (const pid of pids) {
|
|
117021
|
+
if (await isMoxxyProcess(pid))
|
|
117022
|
+
await terminate(pid);
|
|
117023
|
+
}
|
|
116322
117024
|
}
|
|
116323
117025
|
async function killProcessOnPort(port) {
|
|
116324
117026
|
const pids = await pidsListeningOnPort(port);
|
|
116325
|
-
for (const pid of pids)
|
|
116326
|
-
await
|
|
117027
|
+
for (const pid of pids) {
|
|
117028
|
+
if (await isMoxxyProcess(pid))
|
|
117029
|
+
await terminate(pid);
|
|
117030
|
+
}
|
|
117031
|
+
}
|
|
117032
|
+
async function isMoxxyProcess(pid) {
|
|
117033
|
+
if (!Number.isFinite(pid) || pid <= 0 || pid === process.pid)
|
|
117034
|
+
return false;
|
|
117035
|
+
const command = await pidCommand2(pid);
|
|
117036
|
+
return command.length > 0 && /moxxy/i.test(command);
|
|
117037
|
+
}
|
|
117038
|
+
async function pidCommand2(pid) {
|
|
117039
|
+
const { spawn: spawn17 } = await import('child_process');
|
|
117040
|
+
return await new Promise((resolve12) => {
|
|
117041
|
+
let out = "";
|
|
117042
|
+
try {
|
|
117043
|
+
const child = spawn17("ps", ["-p", String(pid), "-o", "command="], {
|
|
117044
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
117045
|
+
});
|
|
117046
|
+
child.stdout.on("data", (b3) => {
|
|
117047
|
+
out += b3.toString();
|
|
117048
|
+
});
|
|
117049
|
+
child.on("error", () => resolve12(""));
|
|
117050
|
+
child.on("close", () => resolve12(out.trim()));
|
|
117051
|
+
} catch {
|
|
117052
|
+
resolve12("");
|
|
117053
|
+
}
|
|
117054
|
+
});
|
|
116327
117055
|
}
|
|
116328
117056
|
async function terminate(pid) {
|
|
116329
117057
|
if (!Number.isFinite(pid) || pid <= 0 || pid === process.pid)
|
|
@@ -116767,13 +117495,17 @@ var MobileSessionHost = class {
|
|
|
116767
117495
|
resolve12(response);
|
|
116768
117496
|
}
|
|
116769
117497
|
};
|
|
117498
|
+
var TOKEN_FILE = "mobile-token";
|
|
116770
117499
|
function resolveMobileToken(configured) {
|
|
116771
117500
|
return resolveChannelToken({
|
|
116772
117501
|
configured,
|
|
116773
117502
|
envVar: "MOXXY_MOBILE_TOKEN",
|
|
116774
|
-
fileName:
|
|
117503
|
+
fileName: TOKEN_FILE
|
|
116775
117504
|
});
|
|
116776
117505
|
}
|
|
117506
|
+
function rotateMobileToken() {
|
|
117507
|
+
return rotateChannelToken({ fileName: TOKEN_FILE });
|
|
117508
|
+
}
|
|
116777
117509
|
function normalizeTunnelChoice(raw) {
|
|
116778
117510
|
const v3 = (process.env.MOXXY_MOBILE_TUNNEL ?? raw ?? "localhost").trim().toLowerCase();
|
|
116779
117511
|
if (v3 === "cloudflared" || v3 === "ngrok")
|
|
@@ -116787,6 +117519,18 @@ function tunnelProviderFor(choice) {
|
|
|
116787
117519
|
return ngrokTunnel;
|
|
116788
117520
|
return null;
|
|
116789
117521
|
}
|
|
117522
|
+
function resolveBindHost(configured) {
|
|
117523
|
+
const v3 = (process.env.MOXXY_MOBILE_HOST ?? configured ?? "").trim();
|
|
117524
|
+
return v3.length > 0 ? v3 : "127.0.0.1";
|
|
117525
|
+
}
|
|
117526
|
+
function isLoopbackHost(host) {
|
|
117527
|
+
const h3 = host.trim().toLowerCase();
|
|
117528
|
+
return h3 === "localhost" || h3 === "::1" || h3 === "[::1]" || h3.startsWith("127.");
|
|
117529
|
+
}
|
|
117530
|
+
function isWildcardHost(host) {
|
|
117531
|
+
const h3 = host.trim().toLowerCase();
|
|
117532
|
+
return h3 === "0.0.0.0" || h3 === "::" || h3 === "[::]";
|
|
117533
|
+
}
|
|
116790
117534
|
function lanHost(fallback) {
|
|
116791
117535
|
for (const list of Object.values(os5__default.networkInterfaces())) {
|
|
116792
117536
|
for (const ni of list ?? []) {
|
|
@@ -116796,6 +117540,11 @@ function lanHost(fallback) {
|
|
|
116796
117540
|
}
|
|
116797
117541
|
return fallback;
|
|
116798
117542
|
}
|
|
117543
|
+
function advertisedHost(bindHost) {
|
|
117544
|
+
if (isWildcardHost(bindHost))
|
|
117545
|
+
return lanHost("127.0.0.1");
|
|
117546
|
+
return bindHost;
|
|
117547
|
+
}
|
|
116799
117548
|
function buildConnectUrl(opts) {
|
|
116800
117549
|
const t2 = encodeURIComponent(opts.token);
|
|
116801
117550
|
if (opts.tunnelUrl) {
|
|
@@ -116808,7 +117557,7 @@ function buildConnectUrl(opts) {
|
|
|
116808
117557
|
|
|
116809
117558
|
// ../plugin-channel-mobile/dist/qr.js
|
|
116810
117559
|
var import_qrcode = __toESM(require_lib3());
|
|
116811
|
-
async function printConnectInfo(url2, token) {
|
|
117560
|
+
async function printConnectInfo(url2, token, hint) {
|
|
116812
117561
|
let qr2 = "";
|
|
116813
117562
|
try {
|
|
116814
117563
|
qr2 = await import_qrcode.default.toString(url2, { type: "terminal", small: true });
|
|
@@ -116822,6 +117571,10 @@ async function printConnectInfo(url2, token) {
|
|
|
116822
117571
|
qr2,
|
|
116823
117572
|
` url: ${url2}`,
|
|
116824
117573
|
` token: ${token}`,
|
|
117574
|
+
...hint ? ["", ` \u2139 ${hint}`] : [],
|
|
117575
|
+
"",
|
|
117576
|
+
" (rotate the pairing token \u2014 invalidating this QR and every paired app \u2014",
|
|
117577
|
+
" by deleting ~/.moxxy/mobile-token and restarting the channel)",
|
|
116825
117578
|
""
|
|
116826
117579
|
];
|
|
116827
117580
|
console.log(lines.join("\n"));
|
|
@@ -116842,7 +117595,7 @@ var MobileChannel = class {
|
|
|
116842
117595
|
tunnel = null;
|
|
116843
117596
|
constructor(opts = {}) {
|
|
116844
117597
|
this.port = opts.port ?? DEFAULT_PORT;
|
|
116845
|
-
this.bindHost = opts.bindHost
|
|
117598
|
+
this.bindHost = resolveBindHost(opts.bindHost);
|
|
116846
117599
|
this.token = resolveMobileToken(opts.token);
|
|
116847
117600
|
this.tunnelChoice = normalizeTunnelChoice(opts.tunnel);
|
|
116848
117601
|
this.logger = opts.logger;
|
|
@@ -116851,6 +117604,19 @@ var MobileChannel = class {
|
|
|
116851
117604
|
check: (call, ctx) => this.host ? this.host.permissionResolver.check(call, ctx) : Promise.resolve({ mode: "deny" })
|
|
116852
117605
|
};
|
|
116853
117606
|
}
|
|
117607
|
+
/**
|
|
117608
|
+
* Rotate the pairing token: persist a fresh secret, re-key the live server
|
|
117609
|
+
* (every connected app is terminated — a leaked QR/token stops working
|
|
117610
|
+
* immediately), and return the new token so the caller can re-display
|
|
117611
|
+
* pairing info. The printed QR also documents the manual path (delete
|
|
117612
|
+
* `~/.moxxy/mobile-token` + restart). Env/config-supplied tokens take
|
|
117613
|
+
* precedence at resolve time and must be rotated at their source.
|
|
117614
|
+
*/
|
|
117615
|
+
rotateToken() {
|
|
117616
|
+
this.token = rotateMobileToken();
|
|
117617
|
+
this.server?.rotateAuthToken(this.token);
|
|
117618
|
+
return this.token;
|
|
117619
|
+
}
|
|
116854
117620
|
async start(startOpts) {
|
|
116855
117621
|
const bus = new WebSocketCommandBus();
|
|
116856
117622
|
const host = new MobileSessionHost(bus, startOpts.session);
|
|
@@ -116860,7 +117626,12 @@ var MobileChannel = class {
|
|
|
116860
117626
|
const server = await startWsBridge(bus, {
|
|
116861
117627
|
port: this.port,
|
|
116862
117628
|
host: this.bindHost,
|
|
116863
|
-
authToken: this.token
|
|
117629
|
+
authToken: this.token,
|
|
117630
|
+
// Back-compat ONLY: the QR this channel prints embeds the token as `?t=`
|
|
117631
|
+
// (pairing payload); current apps strip it and authenticate via the
|
|
117632
|
+
// Sec-WebSocket-Protocol bearer entry, but older installed builds still
|
|
117633
|
+
// connect with the token in the WS URL.
|
|
117634
|
+
allowQueryToken: true
|
|
116864
117635
|
});
|
|
116865
117636
|
this.server = server;
|
|
116866
117637
|
this.logger?.info?.("mobile channel listening", { address: server.address });
|
|
@@ -116872,7 +117643,7 @@ var MobileChannel = class {
|
|
|
116872
117643
|
tunnelUrl = this.tunnel.url;
|
|
116873
117644
|
this.logger?.info?.("mobile tunnel open", { provider: provider.name, url: tunnelUrl });
|
|
116874
117645
|
} catch (err) {
|
|
116875
|
-
this.logger?.warn?.("mobile tunnel failed; using
|
|
117646
|
+
this.logger?.warn?.("mobile tunnel failed; using the local URL", {
|
|
116876
117647
|
provider: provider.name,
|
|
116877
117648
|
err: String(err)
|
|
116878
117649
|
});
|
|
@@ -116880,11 +117651,12 @@ var MobileChannel = class {
|
|
|
116880
117651
|
}
|
|
116881
117652
|
const connectUrl = buildConnectUrl({
|
|
116882
117653
|
tunnelUrl,
|
|
116883
|
-
localHost:
|
|
117654
|
+
localHost: advertisedHost(this.bindHost),
|
|
116884
117655
|
port: this.port,
|
|
116885
117656
|
token: this.token
|
|
116886
117657
|
});
|
|
116887
|
-
|
|
117658
|
+
const loopbackOnly = !tunnelUrl && isLoopbackHost(this.bindHost);
|
|
117659
|
+
await printConnectInfo(connectUrl, this.token, loopbackOnly ? "Bound to loopback \u2014 this QR only works on THIS machine (e.g. an iOS/Android\n simulator). For a real phone: opt in to a LAN bind with MOXXY_MOBILE_HOST=0.0.0.0\n (or channels.mobile.bindHost in moxxy.config.ts), or use a tunnel\n (channels.mobile.tunnel: 'cloudflared' | 'ngrok', or MOXXY_MOBILE_TUNNEL)." : void 0);
|
|
116888
117660
|
let resolveRunning;
|
|
116889
117661
|
const running = new Promise((resolve12) => {
|
|
116890
117662
|
resolveRunning = resolve12;
|
|
@@ -117023,11 +117795,12 @@ function extractFirstTagBlock(html, selector) {
|
|
|
117023
117795
|
function escapeReSelector(s2) {
|
|
117024
117796
|
return s2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
117025
117797
|
}
|
|
117026
|
-
|
|
117027
|
-
|
|
117028
|
-
|
|
117029
|
-
|
|
117030
|
-
|
|
117798
|
+
var SsrfBlockedError = class extends Error {
|
|
117799
|
+
constructor(message) {
|
|
117800
|
+
super(message);
|
|
117801
|
+
this.name = "SsrfBlockedError";
|
|
117802
|
+
}
|
|
117803
|
+
};
|
|
117031
117804
|
var defaultResolver = async (host) => (await lookup(host, { all: true })).map((a2) => a2.address);
|
|
117032
117805
|
var resolver = defaultResolver;
|
|
117033
117806
|
function isBlockedIpv4(ip) {
|
|
@@ -117074,32 +117847,23 @@ function isBlockedIp(ip) {
|
|
|
117074
117847
|
return isBlockedIpv6(ip);
|
|
117075
117848
|
return true;
|
|
117076
117849
|
}
|
|
117077
|
-
async function assertPublicUrl(raw) {
|
|
117850
|
+
async function assertPublicUrl(raw, label3 = "request") {
|
|
117078
117851
|
let u2;
|
|
117079
117852
|
try {
|
|
117080
117853
|
u2 = new URL(raw);
|
|
117081
117854
|
} catch {
|
|
117082
|
-
throw new
|
|
117855
|
+
throw new SsrfBlockedError(`${label3}: invalid URL: ${raw}`);
|
|
117083
117856
|
}
|
|
117084
117857
|
if (u2.protocol !== "http:" && u2.protocol !== "https:") {
|
|
117085
|
-
throw new
|
|
117086
|
-
code: "INTERNAL",
|
|
117087
|
-
message: `web_fetch: refusing non-HTTP(S) scheme "${u2.protocol}"`
|
|
117088
|
-
});
|
|
117858
|
+
throw new SsrfBlockedError(`${label3}: refusing non-HTTP(S) scheme "${u2.protocol}"`);
|
|
117089
117859
|
}
|
|
117090
117860
|
const host = u2.hostname.replace(/^\[|\]$/g, "");
|
|
117091
117861
|
if (host === "localhost" || host.endsWith(".localhost")) {
|
|
117092
|
-
throw new
|
|
117093
|
-
code: "INTERNAL",
|
|
117094
|
-
message: `web_fetch: refusing to fetch loopback host "${host}"`
|
|
117095
|
-
});
|
|
117862
|
+
throw new SsrfBlockedError(`${label3}: refusing to fetch loopback host "${host}"`);
|
|
117096
117863
|
}
|
|
117097
117864
|
if (isIP(host)) {
|
|
117098
117865
|
if (isBlockedIp(host))
|
|
117099
|
-
throw new
|
|
117100
|
-
code: "INTERNAL",
|
|
117101
|
-
message: `web_fetch: refusing private/loopback address "${host}"`
|
|
117102
|
-
});
|
|
117866
|
+
throw new SsrfBlockedError(`${label3}: refusing private/loopback address "${host}"`);
|
|
117103
117867
|
return;
|
|
117104
117868
|
}
|
|
117105
117869
|
let addrs;
|
|
@@ -117110,11 +117874,23 @@ async function assertPublicUrl(raw) {
|
|
|
117110
117874
|
}
|
|
117111
117875
|
for (const addr of addrs) {
|
|
117112
117876
|
if (isBlockedIp(addr)) {
|
|
117113
|
-
throw new
|
|
117114
|
-
|
|
117115
|
-
|
|
117116
|
-
|
|
117877
|
+
throw new SsrfBlockedError(`${label3}: host "${host}" resolves to a private/loopback address (${addr})`);
|
|
117878
|
+
}
|
|
117879
|
+
}
|
|
117880
|
+
}
|
|
117881
|
+
|
|
117882
|
+
// ../plugin-browser/dist/web-fetch.js
|
|
117883
|
+
var MAX_BYTES_DEFAULT = 2 * 1024 * 1024;
|
|
117884
|
+
var MAX_REDIRECTS_DEFAULT = 5;
|
|
117885
|
+
var FETCH_TIMEOUT_MS_DEFAULT = 2e4;
|
|
117886
|
+
async function assertPublicUrlForWebFetch(raw) {
|
|
117887
|
+
try {
|
|
117888
|
+
await assertPublicUrl(raw, "web_fetch");
|
|
117889
|
+
} catch (err) {
|
|
117890
|
+
if (err instanceof SsrfBlockedError) {
|
|
117891
|
+
throw new MoxxyError({ code: "INTERNAL", message: err.message });
|
|
117117
117892
|
}
|
|
117893
|
+
throw err;
|
|
117118
117894
|
}
|
|
117119
117895
|
}
|
|
117120
117896
|
var webFetchTool = defineTool({
|
|
@@ -117182,7 +117958,7 @@ var webFetchTool = defineTool({
|
|
|
117182
117958
|
async function fetchFollowRedirects(initialUrl, opts) {
|
|
117183
117959
|
let current = initialUrl;
|
|
117184
117960
|
for (let hop = 0; hop <= opts.maxRedirects; hop++) {
|
|
117185
|
-
await
|
|
117961
|
+
await assertPublicUrlForWebFetch(current);
|
|
117186
117962
|
const res = await fetch(current, {
|
|
117187
117963
|
method: opts.method,
|
|
117188
117964
|
headers: opts.headers,
|
|
@@ -117261,8 +118037,11 @@ var actionSchema = z$1.union([
|
|
|
117261
118037
|
z$1.object({
|
|
117262
118038
|
kind: z$1.literal("goto"),
|
|
117263
118039
|
// `z.string().url()` accepts file:// and javascript: URLs, which would be
|
|
117264
|
-
// forwarded verbatim to Playwright `page.goto`.
|
|
117265
|
-
//
|
|
118040
|
+
// forwarded verbatim to Playwright `page.goto`. This refine is only a fast
|
|
118041
|
+
// schema-level scheme check; the full SSRF guard (loopback/private/
|
|
118042
|
+
// link-local/metadata IPs, DNS resolution — same `assertPublicUrl` as
|
|
118043
|
+
// web_fetch) runs in the handler before the RPC AND again inside the
|
|
118044
|
+
// sidecar's goto dispatch.
|
|
117266
118045
|
url: z$1.string().url().refine((u2) => /^https?:\/\//i.test(u2), "only http(s) URLs allowed"),
|
|
117267
118046
|
waitUntil: z$1.enum(["load", "domcontentloaded", "networkidle"]).optional(),
|
|
117268
118047
|
timeoutMs: z$1.number().int().positive().max(12e4).optional()
|
|
@@ -117457,7 +118236,7 @@ function defaultSpawn(scriptPath) {
|
|
|
117457
118236
|
function buildBrowserSessionTool(deps) {
|
|
117458
118237
|
return defineTool({
|
|
117459
118238
|
name: "browser_session",
|
|
117460
|
-
description: "Drive a real browser (Playwright). Use for pages that need JS execution, clicks, form fills, or screenshots. For simple GETs prefer web_fetch (no extra deps). Calls within a session share one page.",
|
|
118239
|
+
description: "Drive a real browser (Playwright). Use for pages that need JS execution, clicks, form fills, or screenshots. For simple GETs prefer web_fetch (no extra deps). Calls within a session share one page. Navigation is restricted to public http(s) origins: goto URLs and top-level/iframe navigations (including redirects) to loopback, private (RFC-1918), link-local/metadata, or CGNAT addresses are blocked. Residual risk: subresource requests (img/fetch/script) issued by a loaded page are NOT filtered, so a hostile page can still send blind requests at internal services.",
|
|
117461
118240
|
inputSchema: z$1.object({
|
|
117462
118241
|
action: actionSchema
|
|
117463
118242
|
}),
|
|
@@ -117484,6 +118263,14 @@ function buildBrowserSessionTool(deps) {
|
|
|
117484
118263
|
try {
|
|
117485
118264
|
switch (action.kind) {
|
|
117486
118265
|
case "goto":
|
|
118266
|
+
try {
|
|
118267
|
+
await assertPublicUrl(action.url, "browser_session");
|
|
118268
|
+
} catch (err) {
|
|
118269
|
+
if (err instanceof SsrfBlockedError) {
|
|
118270
|
+
throw new MoxxyError({ code: "INTERNAL", message: err.message });
|
|
118271
|
+
}
|
|
118272
|
+
throw err;
|
|
118273
|
+
}
|
|
117487
118274
|
return await call("goto", {
|
|
117488
118275
|
url: action.url,
|
|
117489
118276
|
waitUntil: action.waitUntil,
|
|
@@ -118095,8 +118882,8 @@ var removeProviderInput = z$1.object({
|
|
|
118095
118882
|
name: providerNameSchema
|
|
118096
118883
|
});
|
|
118097
118884
|
var testProviderInput = z$1.object({
|
|
118098
|
-
baseURL: z$1.string().url(),
|
|
118099
|
-
|
|
118885
|
+
baseURL: z$1.string().url().describe("Vendor API base URL to probe, e.g. https://api.deepseek.com."),
|
|
118886
|
+
keyName: z$1.string().regex(/^[A-Z][A-Z0-9_]*$/).describe("NAME of the vault secret holding the API key (e.g. DEEPSEEK_API_KEY). The key is resolved from the vault inside the tool \u2014 never ask the user for the plaintext key and never pass one as a tool argument. Have them store it first: /vault set <NAME> <key>.")
|
|
118100
118887
|
});
|
|
118101
118888
|
function buildProviderAdminPlugin(opts) {
|
|
118102
118889
|
const { providerRegistry, configPath } = opts;
|
|
@@ -118137,6 +118924,7 @@ function buildProviderAdminPlugin(opts) {
|
|
|
118137
118924
|
providerRegistry.unregister(entry.name);
|
|
118138
118925
|
throw err;
|
|
118139
118926
|
}
|
|
118927
|
+
const vaultKeyName2 = entry.envVar ?? `${entry.name.toUpperCase()}_API_KEY`;
|
|
118140
118928
|
return {
|
|
118141
118929
|
ok: true,
|
|
118142
118930
|
name: entry.name,
|
|
@@ -118146,7 +118934,7 @@ function buildProviderAdminPlugin(opts) {
|
|
|
118146
118934
|
models: entry.models.map((m3) => m3.id),
|
|
118147
118935
|
path: configPath ?? providersConfigPath(),
|
|
118148
118936
|
replaced: wasRegistered,
|
|
118149
|
-
note: `Provider "${entry.name}" is live in this session. Have the USER store the API key by running: /vault set ${
|
|
118937
|
+
note: `Provider "${entry.name}" is live in this session. Have the USER store the API key by running: /vault set ${vaultKeyName2} <key> \u2014 never ask them to paste the key to you. Once stored, you can verify it with provider_test (baseURL + keyName "${vaultKeyName2}") \u2014 it resolves the key from the vault itself. Switch with the /provider command or set provider.name in moxxy.config.ts.`
|
|
118150
118938
|
};
|
|
118151
118939
|
}
|
|
118152
118940
|
}),
|
|
@@ -118188,10 +118976,28 @@ function buildProviderAdminPlugin(opts) {
|
|
|
118188
118976
|
}),
|
|
118189
118977
|
defineTool({
|
|
118190
118978
|
name: "provider_test",
|
|
118191
|
-
description: "Probe an OpenAI-compatible endpoint
|
|
118979
|
+
description: "Probe an OpenAI-compatible endpoint by calling /v1/models. Takes the NAME of a vault secret (e.g. ZAI_API_KEY) and resolves the API key via the vault inside the handler \u2014 the plaintext key never enters the conversation or logs. Have the USER store the key first with /vault set <NAME> <key>, then call this to confirm the baseURL + key are valid (typically before provider_add). Returns { ok: true } on success or { ok: false, message } with the vendor error verbatim.",
|
|
118192
118980
|
inputSchema: testProviderInput,
|
|
118193
118981
|
permission: { action: "prompt" },
|
|
118194
|
-
|
|
118982
|
+
// The plaintext key is resolved HERE, at call time, via ctx.getSecret —
|
|
118983
|
+
// it never appears as tool input/output, so it stays out of the model
|
|
118984
|
+
// context, the runner session log, and the desktop NDJSON log.
|
|
118985
|
+
handler: async ({ baseURL, keyName: keyName2 }, ctx) => {
|
|
118986
|
+
if (!ctx.getSecret) {
|
|
118987
|
+
return {
|
|
118988
|
+
ok: false,
|
|
118989
|
+
message: "provider_test: this session has no secret vault wired in (ctx.getSecret is unavailable), so the key cannot be resolved. Register the provider with provider_add and have the user verify the key with `moxxy doctor` instead."
|
|
118990
|
+
};
|
|
118991
|
+
}
|
|
118992
|
+
const apiKey = await ctx.getSecret(keyName2);
|
|
118993
|
+
if (!apiKey) {
|
|
118994
|
+
return {
|
|
118995
|
+
ok: false,
|
|
118996
|
+
message: `provider_test: no vault secret named "${keyName2}". Ask the USER to store it by running: /vault set ${keyName2} <key> \u2014 then call provider_test again with keyName "${keyName2}". Never ask them to paste the key into the conversation.`
|
|
118997
|
+
};
|
|
118998
|
+
}
|
|
118999
|
+
return validateKey2(apiKey, { baseURL });
|
|
119000
|
+
}
|
|
118195
119001
|
})
|
|
118196
119002
|
],
|
|
118197
119003
|
hooks: {
|
|
@@ -119828,7 +120634,7 @@ function readHeader(headers, name) {
|
|
|
119828
120634
|
return v3[0] ?? null;
|
|
119829
120635
|
return v3 ?? null;
|
|
119830
120636
|
}
|
|
119831
|
-
function readJsonPath(body,
|
|
120637
|
+
function readJsonPath(body, path60) {
|
|
119832
120638
|
let parsed;
|
|
119833
120639
|
try {
|
|
119834
120640
|
parsed = JSON.parse(body.toString("utf8"));
|
|
@@ -119836,7 +120642,7 @@ function readJsonPath(body, path59) {
|
|
|
119836
120642
|
return null;
|
|
119837
120643
|
}
|
|
119838
120644
|
let cur = parsed;
|
|
119839
|
-
for (const seg of
|
|
120645
|
+
for (const seg of path60.split(".")) {
|
|
119840
120646
|
if (cur === null || cur === void 0 || typeof cur !== "object")
|
|
119841
120647
|
return null;
|
|
119842
120648
|
cur = cur[seg];
|
|
@@ -120204,22 +121010,36 @@ var webhookTriggerSchema = z.object({
|
|
|
120204
121010
|
lastResult: z.enum(["ok", "error"]).optional(),
|
|
120205
121011
|
lastError: z.string().optional()
|
|
120206
121012
|
});
|
|
120207
|
-
var
|
|
121013
|
+
var looseFileSchema = z.object({
|
|
120208
121014
|
version: z.literal(1),
|
|
120209
|
-
triggers: z.array(
|
|
121015
|
+
triggers: z.array(z.unknown())
|
|
120210
121016
|
});
|
|
120211
121017
|
function defaultWebhooksFile() {
|
|
120212
121018
|
return moxxyPath("webhooks.json");
|
|
120213
121019
|
}
|
|
120214
121020
|
var WebhookStore = class {
|
|
120215
121021
|
file;
|
|
121022
|
+
logger;
|
|
120216
121023
|
cache = null;
|
|
121024
|
+
loadWarningMsg = null;
|
|
120217
121025
|
mutex = createMutex();
|
|
120218
121026
|
constructor(opts = {}) {
|
|
120219
121027
|
this.file = opts.file ?? defaultWebhooksFile();
|
|
121028
|
+
this.logger = opts.logger;
|
|
120220
121029
|
}
|
|
120221
121030
|
invalidate() {
|
|
120222
121031
|
this.cache = null;
|
|
121032
|
+
this.loadWarningMsg = null;
|
|
121033
|
+
}
|
|
121034
|
+
/**
|
|
121035
|
+
* Human-readable description of any corruption encountered while loading
|
|
121036
|
+
* the store file (corrupt file preserved aside, or invalid entries
|
|
121037
|
+
* quarantined), or `null` when the load was clean. Tools surface this so
|
|
121038
|
+
* the user learns about it instead of silently losing triggers.
|
|
121039
|
+
*/
|
|
121040
|
+
async loadWarning() {
|
|
121041
|
+
await this.ensureLoaded();
|
|
121042
|
+
return this.loadWarningMsg;
|
|
120223
121043
|
}
|
|
120224
121044
|
async list() {
|
|
120225
121045
|
await this.ensureLoaded();
|
|
@@ -120297,17 +121117,85 @@ var WebhookStore = class {
|
|
|
120297
121117
|
async ensureLoaded() {
|
|
120298
121118
|
if (this.cache)
|
|
120299
121119
|
return;
|
|
121120
|
+
this.loadWarningMsg = null;
|
|
121121
|
+
let raw;
|
|
120300
121122
|
try {
|
|
120301
|
-
|
|
120302
|
-
const parsed = fileSchema3.safeParse(JSON.parse(raw));
|
|
120303
|
-
this.cache = parsed.success ? [...parsed.data.triggers] : [];
|
|
121123
|
+
raw = await readFile(this.file, "utf8");
|
|
120304
121124
|
} catch (err) {
|
|
120305
121125
|
if (err.code === "ENOENT") {
|
|
120306
121126
|
this.cache = [];
|
|
120307
|
-
|
|
120308
|
-
this.cache = [];
|
|
121127
|
+
return;
|
|
120309
121128
|
}
|
|
121129
|
+
throw new Error(`webhooks store: cannot read ${this.file}: ${err instanceof Error ? err.message : String(err)} \u2014 refusing to load (and write) until the file is readable again`);
|
|
121130
|
+
}
|
|
121131
|
+
let json;
|
|
121132
|
+
try {
|
|
121133
|
+
json = JSON.parse(raw);
|
|
121134
|
+
} catch {
|
|
121135
|
+
await this.preserveCorruptFile("is not valid JSON");
|
|
121136
|
+
return;
|
|
121137
|
+
}
|
|
121138
|
+
const file = looseFileSchema.safeParse(json);
|
|
121139
|
+
if (!file.success) {
|
|
121140
|
+
await this.preserveCorruptFile("does not match the expected { version: 1, triggers: [...] } shape");
|
|
121141
|
+
return;
|
|
120310
121142
|
}
|
|
121143
|
+
const valid = [];
|
|
121144
|
+
const invalid = [];
|
|
121145
|
+
file.data.triggers.forEach((entry, index) => {
|
|
121146
|
+
const parsed = webhookTriggerSchema.safeParse(entry);
|
|
121147
|
+
if (parsed.success) {
|
|
121148
|
+
valid.push(parsed.data);
|
|
121149
|
+
} else {
|
|
121150
|
+
invalid.push({
|
|
121151
|
+
index,
|
|
121152
|
+
entry,
|
|
121153
|
+
issues: parsed.error.issues.map((i2) => `${i2.path.join(".") || "(root)"}: ${i2.message}`).join("; ")
|
|
121154
|
+
});
|
|
121155
|
+
}
|
|
121156
|
+
});
|
|
121157
|
+
if (invalid.length > 0)
|
|
121158
|
+
await this.quarantineEntries(invalid);
|
|
121159
|
+
this.cache = valid;
|
|
121160
|
+
}
|
|
121161
|
+
/**
|
|
121162
|
+
* The file exists but is unparseable/mis-shaped. Rename it aside (rename,
|
|
121163
|
+
* not copy — nothing may remain at the live path that a later persist()
|
|
121164
|
+
* could clobber while it is the only copy), then start empty. If the
|
|
121165
|
+
* rename itself fails the error propagates and the store refuses to
|
|
121166
|
+
* operate, which is the safe direction.
|
|
121167
|
+
*/
|
|
121168
|
+
async preserveCorruptFile(reason) {
|
|
121169
|
+
const preserved = `${this.file}.corrupt-${timestampSlug()}`;
|
|
121170
|
+
await rename$1(this.file, preserved);
|
|
121171
|
+
this.loadWarningMsg = `the webhook trigger store (${this.file}) ${reason}; the original file was preserved at ${preserved} and the store restarted empty. Previously configured triggers (and their secrets) are recoverable from that file \u2014 repair it by hand or recreate the triggers.`;
|
|
121172
|
+
this.logger?.error?.("webhooks: store file corrupt \u2014 preserved aside, starting empty", {
|
|
121173
|
+
file: this.file,
|
|
121174
|
+
preserved,
|
|
121175
|
+
reason
|
|
121176
|
+
});
|
|
121177
|
+
this.cache = [];
|
|
121178
|
+
}
|
|
121179
|
+
/**
|
|
121180
|
+
* The file parses but some entries fail validation. Keep the valid ones,
|
|
121181
|
+
* write the rest (verbatim, with their zod issues) to a 0600 sidecar so
|
|
121182
|
+
* they stay recoverable after the next persist() drops them.
|
|
121183
|
+
*/
|
|
121184
|
+
async quarantineEntries(invalid) {
|
|
121185
|
+
const quarantine = `${this.file}.quarantine-${timestampSlug()}`;
|
|
121186
|
+
const payload = JSON.stringify({
|
|
121187
|
+
quarantinedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
121188
|
+
source: this.file,
|
|
121189
|
+
entries: invalid
|
|
121190
|
+
}, null, 2);
|
|
121191
|
+
await writeFileAtomic(quarantine, payload, { mode: 384 });
|
|
121192
|
+
this.loadWarningMsg = `${invalid.length} trigger entr${invalid.length === 1 ? "y" : "ies"} in ${this.file} failed schema validation and ${invalid.length === 1 ? "was" : "were"} quarantined to ${quarantine} (valid triggers were kept). Inspect that file to repair or recreate them.`;
|
|
121193
|
+
this.logger?.error?.("webhooks: invalid trigger entries quarantined", {
|
|
121194
|
+
file: this.file,
|
|
121195
|
+
quarantine,
|
|
121196
|
+
count: invalid.length,
|
|
121197
|
+
issues: invalid.map((i2) => ({ index: i2.index, issues: i2.issues }))
|
|
121198
|
+
});
|
|
120311
121199
|
}
|
|
120312
121200
|
async mutate(fn) {
|
|
120313
121201
|
await this.mutex.run(async () => {
|
|
@@ -120322,6 +121210,9 @@ var WebhookStore = class {
|
|
|
120322
121210
|
await writeFileAtomic(this.file, payload);
|
|
120323
121211
|
}
|
|
120324
121212
|
};
|
|
121213
|
+
function timestampSlug() {
|
|
121214
|
+
return (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
121215
|
+
}
|
|
120325
121216
|
|
|
120326
121217
|
// ../plugin-webhooks/dist/describe.js
|
|
120327
121218
|
function describeTrigger(trigger, publicUrl) {
|
|
@@ -120450,9 +121341,25 @@ async function startTunnel(opts) {
|
|
|
120450
121341
|
}
|
|
120451
121342
|
};
|
|
120452
121343
|
}
|
|
121344
|
+
function defaultWebhookSecretsDir() {
|
|
121345
|
+
return moxxyPath("webhooks-secrets");
|
|
121346
|
+
}
|
|
120453
121347
|
function generateSecret() {
|
|
120454
121348
|
return randomBytes(32).toString("hex");
|
|
120455
121349
|
}
|
|
121350
|
+
function maskSecret(secret) {
|
|
121351
|
+
return `${secret.slice(0, 4)}\u2026`;
|
|
121352
|
+
}
|
|
121353
|
+
function secretFilePath(dir, triggerName) {
|
|
121354
|
+
return path3__default.join(dir, `${triggerName}.secret`);
|
|
121355
|
+
}
|
|
121356
|
+
async function writeSecretFile(dir, triggerName, secret) {
|
|
121357
|
+
await mkdir(dir, { recursive: true, mode: 448 });
|
|
121358
|
+
const file = secretFilePath(dir, triggerName);
|
|
121359
|
+
await writeFileAtomic(file, `${secret}
|
|
121360
|
+
`, { mode: 384 });
|
|
121361
|
+
return file;
|
|
121362
|
+
}
|
|
120456
121363
|
var verificationInputSchema = z$1.discriminatedUnion("type", [
|
|
120457
121364
|
z$1.object({ type: z$1.literal("none") }),
|
|
120458
121365
|
z$1.object({
|
|
@@ -120505,10 +121412,11 @@ function fullUrl(publicUrl, triggerId) {
|
|
|
120505
121412
|
}
|
|
120506
121413
|
function buildWebhookTools(deps) {
|
|
120507
121414
|
const { store, config, dispatcher, tunnelHandle } = deps;
|
|
121415
|
+
const secretsDir = deps.secretsDir ?? defaultWebhookSecretsDir();
|
|
120508
121416
|
return [
|
|
120509
121417
|
defineTool({
|
|
120510
121418
|
name: "webhook_create",
|
|
120511
|
-
description:
|
|
121419
|
+
description: "Create a webhook trigger. When an external system POSTs to the returned URL and verification (and any filters) pass, the configured prompt fires as a turn on the ACTIVE session (not an isolated one \u2014 output lands in the shared event log). `allowedTools` is enforced per fire: a non-empty list restricts the fire to exactly those tools (any other tool call is denied); an empty list leaves the session's full tool set available under its normal permission rules.\n\nVerification picks the auth model:\n \u2022 `none` \u2014 no auth. Anyone reaching the URL fires the trigger. Local-only.\n \u2022 `bearer` \u2014 secret in `Authorization: Bearer <secret>`. Simplest shared-secret.\n \u2022 `hmac` \u2014 HMAC over the body, compared to a signature header. The user should paste the header name + signature prefix + algorithm from the external system's webhook documentation. Use `scheme:\"stripe\"` for systems that sign `<timestamp>.<body>` and pack it into a comma-separated header.\n\nFor `bearer`/`hmac`, if `secret` is omitted a strong 32-byte random secret is generated. For security the secret is NEVER returned here (tool results persist in session logs): the result carries `generatedSecret` with a masked preview plus the path of an owner-only file holding the full value \u2014 relay that path so the USER opens it themselves and pastes the secret into the external system. Do not read the file into the conversation.\n\n`filters` decides whether a verified delivery actually fires the prompt:\n \u2022 `include` \u2014 fire only if at least one rule matches (or empty = fire on everything)\n \u2022 `exclude` \u2014 never fire if any rule matches\nEach rule reads ONE field (a header or a dot-separated JSON path in the body) and compares it against `equals` (any-of) or `matches` (regex).\n\nPrompt placeholders: `{body}`, `{body_json}`, `{header.<name>}`, `{method}`, `{path}`, `{trigger_name}`, `{fired_at}`. The prompt is the runbook the model reads on every delivery \u2014 write it that way.",
|
|
120512
121420
|
inputSchema: z$1.object({
|
|
120513
121421
|
name: z$1.string().min(1).max(120).regex(/^[a-z0-9][a-z0-9-]*$/i, "name must be slug-like"),
|
|
120514
121422
|
prompt: z$1.string().min(1),
|
|
@@ -120541,10 +121449,19 @@ function buildWebhookTools(deps) {
|
|
|
120541
121449
|
} else {
|
|
120542
121450
|
guidance.push(`Paste this URL into the external system's webhook config: ${url2}`);
|
|
120543
121451
|
}
|
|
121452
|
+
let generatedSecret = null;
|
|
120544
121453
|
if (secretIssued) {
|
|
120545
|
-
|
|
121454
|
+
const file = await writeSecretFile(secretsDir, trigger.name, secretIssued);
|
|
121455
|
+
generatedSecret = { masked: maskSecret(secretIssued), path: file };
|
|
121456
|
+
guidance.push(`A strong secret was generated for this trigger (preview: ${generatedSecret.masked}). For security it is NOT included in this response \u2014 the full value was written to ${file} (owner-only file). Tell the user to open that file themselves (e.g. \`cat ${file}\`) and paste the value into the external system's webhook secret field, then delete the file once configured. Do NOT read the file into the conversation.`);
|
|
120546
121457
|
}
|
|
120547
|
-
|
|
121458
|
+
const storeWarning = await store.loadWarning();
|
|
121459
|
+
return {
|
|
121460
|
+
trigger: describeTrigger(trigger, cfg.publicUrl),
|
|
121461
|
+
generatedSecret,
|
|
121462
|
+
guidance,
|
|
121463
|
+
...storeWarning ? { storeWarning } : {}
|
|
121464
|
+
};
|
|
120548
121465
|
}
|
|
120549
121466
|
}),
|
|
120550
121467
|
defineTool({
|
|
@@ -120557,10 +121474,12 @@ function buildWebhookTools(deps) {
|
|
|
120557
121474
|
const triggers = await store.list();
|
|
120558
121475
|
const cfg = await config.get();
|
|
120559
121476
|
const filtered = includeDisabled ? triggers : triggers.filter((t2) => t2.enabled);
|
|
121477
|
+
const storeWarning = await store.loadWarning();
|
|
120560
121478
|
return {
|
|
120561
121479
|
publicUrl: cfg.publicUrl ?? null,
|
|
120562
121480
|
listener: { host: cfg.host, port: cfg.port },
|
|
120563
|
-
triggers: filtered.map((t2) => describeTrigger(t2, cfg.publicUrl))
|
|
121481
|
+
triggers: filtered.map((t2) => describeTrigger(t2, cfg.publicUrl)),
|
|
121482
|
+
...storeWarning ? { storeWarning } : {}
|
|
120564
121483
|
};
|
|
120565
121484
|
}
|
|
120566
121485
|
}),
|
|
@@ -120569,7 +121488,15 @@ function buildWebhookTools(deps) {
|
|
|
120569
121488
|
description: "Permanently remove a webhook trigger by id. Does NOT touch any subscription registered on the external side \u2014 the user must also delete the webhook from the source's dashboard, otherwise it'll keep retrying.",
|
|
120570
121489
|
inputSchema: z$1.object({ id: z$1.string().min(1) }),
|
|
120571
121490
|
permission: { action: "prompt" },
|
|
120572
|
-
handler: async ({ id }) =>
|
|
121491
|
+
handler: async ({ id }) => {
|
|
121492
|
+
const trigger = await store.get(id);
|
|
121493
|
+
const deleted = await store.delete(id);
|
|
121494
|
+
if (deleted && trigger) {
|
|
121495
|
+
await rm(secretFilePath(secretsDir, trigger.name), { force: true }).catch(() => {
|
|
121496
|
+
});
|
|
121497
|
+
}
|
|
121498
|
+
return { deleted };
|
|
121499
|
+
}
|
|
120573
121500
|
}),
|
|
120574
121501
|
defineTool({
|
|
120575
121502
|
name: "webhook_update",
|
|
@@ -120646,7 +121573,8 @@ function buildWebhookTools(deps) {
|
|
|
120646
121573
|
} : { running: false },
|
|
120647
121574
|
cliAvailable: { cloudflared: cloudflaredOk, ngrok: ngrokOk },
|
|
120648
121575
|
triggerCount: triggers.length,
|
|
120649
|
-
enabledCount: triggers.filter((t2) => t2.enabled).length
|
|
121576
|
+
enabledCount: triggers.filter((t2) => t2.enabled).length,
|
|
121577
|
+
...await store.loadWarning().then((w4) => w4 ? { storeWarning: w4 } : {})
|
|
120650
121578
|
};
|
|
120651
121579
|
}
|
|
120652
121580
|
}),
|
|
@@ -120829,8 +121757,8 @@ async function buildSetupGuide(deps) {
|
|
|
120829
121757
|
askUser: "If verification is `bearer` or `hmac`, do you already have the secret from the external system, or should I generate one for you?\n \u2022 If they already created the webhook on the source's side and the docs gave them a signing secret, paste it here.\n \u2022 If they're about to create the webhook, I can generate a strong random one and they will paste it into the source.",
|
|
120830
121758
|
recordAs: "verification.secret",
|
|
120831
121759
|
hints: [
|
|
120832
|
-
"Omit `secret` in `webhook_create` to auto-generate. The response
|
|
120833
|
-
"Never log the secret. Never echo
|
|
121760
|
+
"Omit `secret` in `webhook_create` to auto-generate. The full value is written to an owner-only file (the response's `generatedSecret.path`) instead of being returned \u2014 relay the path and have the USER open the file and paste the value into the external system themselves.",
|
|
121761
|
+
"Never log the secret. Never read the secret file into the conversation or echo the value in messages."
|
|
120834
121762
|
]
|
|
120835
121763
|
});
|
|
120836
121764
|
steps.push({
|
|
@@ -120859,7 +121787,7 @@ async function buildSetupGuide(deps) {
|
|
|
120859
121787
|
steps.push({
|
|
120860
121788
|
step: 7,
|
|
120861
121789
|
title: "Prompt + tools",
|
|
120862
|
-
askUser: "What should the agent DO when a delivery fires? Describe the runbook. Then: which tools should it have access to (read-only fetch? bash? a specific MCP tool?)?
|
|
121790
|
+
askUser: "What should the agent DO when a delivery fires? Describe the runbook. Then: which tools should it have access to (read-only fetch? bash? a specific MCP tool?)? A non-empty `allowedTools` is enforced \u2014 the fire can only execute the listed tools; everything else is denied. An empty list gives the fire the FULL tool set of the active session (fires are not isolated), so list only what you trust.",
|
|
120863
121791
|
recordAs: "prompt + allowedTools",
|
|
120864
121792
|
hints: [
|
|
120865
121793
|
"Use placeholders like `{body_json}` so the prompt sees the actual delivery payload.",
|
|
@@ -120871,8 +121799,8 @@ async function buildSetupGuide(deps) {
|
|
|
120871
121799
|
title: "Create the trigger",
|
|
120872
121800
|
nextToolCall: "webhook_create",
|
|
120873
121801
|
hints: [
|
|
120874
|
-
"Call `webhook_create` with the collected fields. Capture `
|
|
120875
|
-
"Relay both to the user: the URL goes into the external system's webhook config; the secret
|
|
121802
|
+
"Call `webhook_create` with the collected fields. Capture `generatedSecret` (masked preview + file path) and `trigger.url` from the response.",
|
|
121803
|
+
"Relay both to the user: the URL goes into the external system's webhook config; the secret lives in the file at `generatedSecret.path` \u2014 the user opens it themselves and pastes the value into the external system's signing-secret field."
|
|
120876
121804
|
]
|
|
120877
121805
|
});
|
|
120878
121806
|
steps.push({
|
|
@@ -120892,7 +121820,7 @@ async function buildSetupGuide(deps) {
|
|
|
120892
121820
|
|
|
120893
121821
|
// ../plugin-webhooks/dist/index.js
|
|
120894
121822
|
function buildWebhooksPlugin(opts) {
|
|
120895
|
-
const store = opts.store ?? new WebhookStore();
|
|
121823
|
+
const store = opts.store ?? new WebhookStore(opts.logger ? { logger: opts.logger } : {});
|
|
120896
121824
|
const config = opts.config ?? new WebhookConfigStore();
|
|
120897
121825
|
const dispatcher = new WebhookDispatcher({
|
|
120898
121826
|
store,
|
|
@@ -122488,8 +123416,8 @@ function findCycle(steps) {
|
|
|
122488
123416
|
}
|
|
122489
123417
|
function formatIssues(error2) {
|
|
122490
123418
|
return error2.issues.map((iss) => {
|
|
122491
|
-
const
|
|
122492
|
-
return `${
|
|
123419
|
+
const path60 = iss.path.join(".") || "(root)";
|
|
123420
|
+
return `${path60}: ${iss.message}`;
|
|
122493
123421
|
});
|
|
122494
123422
|
}
|
|
122495
123423
|
function validateWorkflow(raw) {
|
|
@@ -123558,6 +124486,7 @@ var BUILTIN_WORKFLOWS_DIR = path3.resolve(__dirname2, "../workflows");
|
|
|
123558
124486
|
|
|
123559
124487
|
// src/setup/workflows.ts
|
|
123560
124488
|
var PLUGIN_ID3 = asPluginId(WORKFLOWS_PLUGIN_NAME);
|
|
124489
|
+
var MAX_AFTER_WORKFLOW_CHAIN = 8;
|
|
123561
124490
|
function buildWorkflowsIntegration(args) {
|
|
123562
124491
|
const { session, scheduleStore, logger } = args;
|
|
123563
124492
|
const store = new WorkflowStore({
|
|
@@ -123567,6 +124496,8 @@ function buildWorkflowsIntegration(args) {
|
|
|
123567
124496
|
});
|
|
123568
124497
|
const watchers = [];
|
|
123569
124498
|
const inFlight = /* @__PURE__ */ new Set();
|
|
124499
|
+
const cyclicTriggers = /* @__PURE__ */ new Set();
|
|
124500
|
+
const warnedCycles = /* @__PURE__ */ new Set();
|
|
123570
124501
|
async function runNow(input) {
|
|
123571
124502
|
const entry = await store.get(input.name);
|
|
123572
124503
|
if (!entry) return { ok: false, steps: [], output: "", error: `no workflow named "${input.name}"` };
|
|
@@ -123602,7 +124533,9 @@ function buildWorkflowsIntegration(args) {
|
|
|
123602
124533
|
source: "plugin",
|
|
123603
124534
|
pluginId: PLUGIN_ID3,
|
|
123604
124535
|
subtype,
|
|
123605
|
-
|
|
124536
|
+
// Stamp the causal chain onto the completion event so the
|
|
124537
|
+
// afterWorkflow subscription can detect cycles/depth per-run.
|
|
124538
|
+
payload: subtype === "workflow_completed" && input.chain && input.chain.length > 0 ? { ...payload, triggerChain: [...input.chain] } : payload
|
|
123606
124539
|
}),
|
|
123607
124540
|
...logger ? { logger } : {}
|
|
123608
124541
|
},
|
|
@@ -123639,6 +124572,12 @@ function buildWorkflowsIntegration(args) {
|
|
|
123639
124572
|
};
|
|
123640
124573
|
async function syncSchedules() {
|
|
123641
124574
|
const all = await store.list();
|
|
124575
|
+
applyAfterWorkflowCycleGuard({
|
|
124576
|
+
workflows: all.map((w4) => w4.workflow),
|
|
124577
|
+
disabled: cyclicTriggers,
|
|
124578
|
+
warned: warnedCycles,
|
|
124579
|
+
...logger ? { logger } : {}
|
|
124580
|
+
});
|
|
123642
124581
|
for (const { workflow } of all) {
|
|
123643
124582
|
const sched = workflow.enabled ? workflow.on?.schedule : void 0;
|
|
123644
124583
|
if (sched && (sched.cron || sched.runAt)) {
|
|
@@ -123669,23 +124608,24 @@ function buildWorkflowsIntegration(args) {
|
|
|
123669
124608
|
}
|
|
123670
124609
|
const unsubscribe = session.log.subscribe((event) => {
|
|
123671
124610
|
if (event.type !== "plugin_event" || event.subtype !== "workflow_completed") return;
|
|
123672
|
-
const
|
|
124611
|
+
const payload = event.payload;
|
|
124612
|
+
const completed = payload?.name;
|
|
123673
124613
|
if (!completed) return;
|
|
124614
|
+
const chain = Array.isArray(payload?.triggerChain) ? payload.triggerChain.filter((n2) => typeof n2 === "string") : [];
|
|
123674
124615
|
void (async () => {
|
|
123675
|
-
|
|
123676
|
-
|
|
123677
|
-
|
|
123678
|
-
|
|
123679
|
-
|
|
123680
|
-
|
|
123681
|
-
|
|
123682
|
-
|
|
123683
|
-
|
|
123684
|
-
|
|
123685
|
-
|
|
123686
|
-
|
|
123687
|
-
|
|
123688
|
-
})();
|
|
124616
|
+
await fireAfterWorkflowDependents({
|
|
124617
|
+
completed,
|
|
124618
|
+
chain,
|
|
124619
|
+
workflows: (await store.list()).map((w4) => w4.workflow),
|
|
124620
|
+
disabled: cyclicTriggers,
|
|
124621
|
+
run: runNow,
|
|
124622
|
+
...logger ? { logger } : {}
|
|
124623
|
+
});
|
|
124624
|
+
})().catch(
|
|
124625
|
+
(err) => logger?.warn?.("workflows: afterWorkflow dispatch failed", {
|
|
124626
|
+
err: err instanceof Error ? err.message : String(err)
|
|
124627
|
+
})
|
|
124628
|
+
);
|
|
123689
124629
|
});
|
|
123690
124630
|
async function startFileWatchers() {
|
|
123691
124631
|
for (const w4 of watchers.splice(0)) w4.close();
|
|
@@ -123744,6 +124684,104 @@ function buildWorkflowsIntegration(args) {
|
|
|
123744
124684
|
}
|
|
123745
124685
|
};
|
|
123746
124686
|
}
|
|
124687
|
+
function detectAfterWorkflowCycles(workflows) {
|
|
124688
|
+
const enabled = /* @__PURE__ */ new Map();
|
|
124689
|
+
for (const w4 of workflows) if (w4.enabled) enabled.set(w4.name, w4);
|
|
124690
|
+
const edges = /* @__PURE__ */ new Map();
|
|
124691
|
+
for (const name of enabled.keys()) edges.set(name, []);
|
|
124692
|
+
for (const w4 of enabled.values()) {
|
|
124693
|
+
for (const dep of [w4.on?.afterWorkflow ?? []].flat()) {
|
|
124694
|
+
if (enabled.has(dep)) edges.get(dep).push(w4.name);
|
|
124695
|
+
}
|
|
124696
|
+
}
|
|
124697
|
+
let counter = 0;
|
|
124698
|
+
const index = /* @__PURE__ */ new Map();
|
|
124699
|
+
const lowlink = /* @__PURE__ */ new Map();
|
|
124700
|
+
const onStack = /* @__PURE__ */ new Set();
|
|
124701
|
+
const stack = [];
|
|
124702
|
+
const cycles = [];
|
|
124703
|
+
const visit = (v3) => {
|
|
124704
|
+
index.set(v3, counter);
|
|
124705
|
+
lowlink.set(v3, counter);
|
|
124706
|
+
counter++;
|
|
124707
|
+
stack.push(v3);
|
|
124708
|
+
onStack.add(v3);
|
|
124709
|
+
for (const w4 of edges.get(v3) ?? []) {
|
|
124710
|
+
if (!index.has(w4)) {
|
|
124711
|
+
visit(w4);
|
|
124712
|
+
lowlink.set(v3, Math.min(lowlink.get(v3), lowlink.get(w4)));
|
|
124713
|
+
} else if (onStack.has(w4)) {
|
|
124714
|
+
lowlink.set(v3, Math.min(lowlink.get(v3), index.get(w4)));
|
|
124715
|
+
}
|
|
124716
|
+
}
|
|
124717
|
+
if (lowlink.get(v3) === index.get(v3)) {
|
|
124718
|
+
const scc = [];
|
|
124719
|
+
for (; ; ) {
|
|
124720
|
+
const w4 = stack.pop();
|
|
124721
|
+
onStack.delete(w4);
|
|
124722
|
+
scc.push(w4);
|
|
124723
|
+
if (w4 === v3) break;
|
|
124724
|
+
}
|
|
124725
|
+
if (scc.length > 1 || (edges.get(v3) ?? []).includes(v3)) cycles.push(scc.reverse());
|
|
124726
|
+
}
|
|
124727
|
+
};
|
|
124728
|
+
for (const name of enabled.keys()) if (!index.has(name)) visit(name);
|
|
124729
|
+
return cycles;
|
|
124730
|
+
}
|
|
124731
|
+
function applyAfterWorkflowCycleGuard(args) {
|
|
124732
|
+
const cycles = detectAfterWorkflowCycles(args.workflows);
|
|
124733
|
+
args.disabled.clear();
|
|
124734
|
+
for (const cycle of cycles) {
|
|
124735
|
+
for (const name of cycle) args.disabled.add(name);
|
|
124736
|
+
const key = [...cycle].sort().join(" -> ");
|
|
124737
|
+
if (args.warned.has(key)) continue;
|
|
124738
|
+
args.warned.add(key);
|
|
124739
|
+
args.logger?.warn?.(
|
|
124740
|
+
`workflows: afterWorkflow trigger cycle detected (${cycle.join(" -> ")} -> ${cycle[0]}); auto-refire is disabled for these workflows \u2014 run them manually or break the cycle`,
|
|
124741
|
+
{ cycle: [...cycle] }
|
|
124742
|
+
);
|
|
124743
|
+
}
|
|
124744
|
+
}
|
|
124745
|
+
async function fireAfterWorkflowDependents(args) {
|
|
124746
|
+
const { completed, workflows, disabled, run: run2, logger } = args;
|
|
124747
|
+
const nextChain = [...args.chain, completed];
|
|
124748
|
+
for (const workflow of workflows) {
|
|
124749
|
+
if (!workflow.enabled || !workflow.on?.afterWorkflow) continue;
|
|
124750
|
+
if (![workflow.on.afterWorkflow].flat().includes(completed)) continue;
|
|
124751
|
+
if (disabled.has(workflow.name)) {
|
|
124752
|
+
logger?.info?.("workflows: afterWorkflow auto-refire disabled by the cycle guard; skipping", {
|
|
124753
|
+
workflow: workflow.name,
|
|
124754
|
+
after: completed
|
|
124755
|
+
});
|
|
124756
|
+
continue;
|
|
124757
|
+
}
|
|
124758
|
+
if (nextChain.includes(workflow.name)) {
|
|
124759
|
+
logger?.warn?.(
|
|
124760
|
+
`workflows: refusing afterWorkflow re-fire \u2014 trigger cycle (${[...nextChain, workflow.name].join(" -> ")}); "${workflow.name}" already ran in this chain`,
|
|
124761
|
+
{ workflow: workflow.name, chain: [...nextChain] }
|
|
124762
|
+
);
|
|
124763
|
+
continue;
|
|
124764
|
+
}
|
|
124765
|
+
if (nextChain.length >= MAX_AFTER_WORKFLOW_CHAIN) {
|
|
124766
|
+
logger?.warn?.(
|
|
124767
|
+
`workflows: refusing afterWorkflow re-fire \u2014 chain depth cap of ${MAX_AFTER_WORKFLOW_CHAIN} reached (${nextChain.join(" -> ")} -> ${workflow.name})`,
|
|
124768
|
+
{ workflow: workflow.name, chain: [...nextChain] }
|
|
124769
|
+
);
|
|
124770
|
+
continue;
|
|
124771
|
+
}
|
|
124772
|
+
logger?.info?.("workflows: afterWorkflow trigger", {
|
|
124773
|
+
workflow: workflow.name,
|
|
124774
|
+
after: completed,
|
|
124775
|
+
depth: nextChain.length
|
|
124776
|
+
});
|
|
124777
|
+
await run2({ name: workflow.name, trigger: `after:${completed}`, chain: nextChain }).catch(
|
|
124778
|
+
(err) => logger?.warn?.("workflows: afterWorkflow run failed", {
|
|
124779
|
+
workflow: workflow.name,
|
|
124780
|
+
err: err instanceof Error ? err.message : String(err)
|
|
124781
|
+
})
|
|
124782
|
+
);
|
|
124783
|
+
}
|
|
124784
|
+
}
|
|
123747
124785
|
function activeModel(session) {
|
|
123748
124786
|
return safeActiveProvider(session)?.models[0]?.id ?? "claude-sonnet-4-6";
|
|
123749
124787
|
}
|
|
@@ -124152,11 +125190,12 @@ function buildSchedulerRunner(session) {
|
|
|
124152
125190
|
init_dist();
|
|
124153
125191
|
function buildWebhookRunner(session) {
|
|
124154
125192
|
return {
|
|
124155
|
-
runPrompt: async ({ prompt, model }) => {
|
|
125193
|
+
runPrompt: async ({ prompt, model, allowedTools, triggerName }) => {
|
|
125194
|
+
const target = scopedSessionView(session, allowedTools, triggerName);
|
|
124156
125195
|
let text = "";
|
|
124157
125196
|
let lastError = null;
|
|
124158
125197
|
try {
|
|
124159
|
-
for await (const event of runTurn(
|
|
125198
|
+
for await (const event of runTurn(target, prompt, model ? { model } : {})) {
|
|
124160
125199
|
if (event.type === "assistant_message") {
|
|
124161
125200
|
text = event.content;
|
|
124162
125201
|
if (event.stopReason === "error") lastError = "turn ended with error stop reason";
|
|
@@ -124171,6 +125210,88 @@ function buildWebhookRunner(session) {
|
|
|
124171
125210
|
}
|
|
124172
125211
|
};
|
|
124173
125212
|
}
|
|
125213
|
+
function scopedSessionView(session, allowedTools, triggerName) {
|
|
125214
|
+
if (allowedTools.length === 0) return session;
|
|
125215
|
+
const allowed = new Set(allowedTools);
|
|
125216
|
+
const denyReason = (name) => `Tool '${name}' is not in webhook trigger '${triggerName}' allowedTools`;
|
|
125217
|
+
const resolver2 = {
|
|
125218
|
+
name: `webhook-allowed-tools(${triggerName})`,
|
|
125219
|
+
async check(call, ctx) {
|
|
125220
|
+
if (!allowed.has(call.name)) {
|
|
125221
|
+
return { mode: "deny", reason: denyReason(call.name) };
|
|
125222
|
+
}
|
|
125223
|
+
return session.resolver.check(call, ctx);
|
|
125224
|
+
},
|
|
125225
|
+
// The allow-list is POLICY, so it must also surface through the
|
|
125226
|
+
// prompt-free `policyCheck` probe — auto-approving modes (goal mode)
|
|
125227
|
+
// consult only this and skip `check`'s prompt path entirely. Without
|
|
125228
|
+
// it, a goal-mode webhook fire would auto-approve tools outside the
|
|
125229
|
+
// trigger's allowedTools.
|
|
125230
|
+
async policyCheck(call, ctx) {
|
|
125231
|
+
if (!allowed.has(call.name)) {
|
|
125232
|
+
return { mode: "deny", reason: denyReason(call.name) };
|
|
125233
|
+
}
|
|
125234
|
+
return await session.resolver.policyCheck?.(call, ctx) ?? null;
|
|
125235
|
+
}
|
|
125236
|
+
};
|
|
125237
|
+
const parent = session.tools;
|
|
125238
|
+
const tools = {
|
|
125239
|
+
list: () => parent.list().filter((t2) => allowed.has(t2.name)),
|
|
125240
|
+
get: (name) => allowed.has(name) ? parent.get(name) : void 0,
|
|
125241
|
+
has: (name) => allowed.has(name) && parent.has(name),
|
|
125242
|
+
register: (tool) => parent.register(tool),
|
|
125243
|
+
unregister: (name) => parent.unregister(name),
|
|
125244
|
+
execute: (name, input, signal, opts) => {
|
|
125245
|
+
if (!allowed.has(name)) return Promise.reject(new Error(denyReason(name)));
|
|
125246
|
+
return parent.execute(name, input, signal, opts);
|
|
125247
|
+
}
|
|
125248
|
+
};
|
|
125249
|
+
return {
|
|
125250
|
+
get id() {
|
|
125251
|
+
return session.id;
|
|
125252
|
+
},
|
|
125253
|
+
get log() {
|
|
125254
|
+
return session.log;
|
|
125255
|
+
},
|
|
125256
|
+
get signal() {
|
|
125257
|
+
return session.signal;
|
|
125258
|
+
},
|
|
125259
|
+
tools,
|
|
125260
|
+
get skills() {
|
|
125261
|
+
return session.skills;
|
|
125262
|
+
},
|
|
125263
|
+
get providers() {
|
|
125264
|
+
return session.providers;
|
|
125265
|
+
},
|
|
125266
|
+
get modes() {
|
|
125267
|
+
return session.modes;
|
|
125268
|
+
},
|
|
125269
|
+
get compactors() {
|
|
125270
|
+
return session.compactors;
|
|
125271
|
+
},
|
|
125272
|
+
get cacheStrategies() {
|
|
125273
|
+
return session.cacheStrategies;
|
|
125274
|
+
},
|
|
125275
|
+
resolver: resolver2,
|
|
125276
|
+
get approvalResolver() {
|
|
125277
|
+
return session.approvalResolver;
|
|
125278
|
+
},
|
|
125279
|
+
get elisionSettings() {
|
|
125280
|
+
return session.elisionSettings;
|
|
125281
|
+
},
|
|
125282
|
+
get lazyTools() {
|
|
125283
|
+
return session.lazyTools;
|
|
125284
|
+
},
|
|
125285
|
+
get dispatcher() {
|
|
125286
|
+
return session.dispatcher;
|
|
125287
|
+
},
|
|
125288
|
+
get pluginHost() {
|
|
125289
|
+
return session.pluginHost;
|
|
125290
|
+
},
|
|
125291
|
+
startTurn: () => session.startTurn(),
|
|
125292
|
+
appContext: () => session.appContext()
|
|
125293
|
+
};
|
|
125294
|
+
}
|
|
124174
125295
|
|
|
124175
125296
|
// src/setup/register-plugins.ts
|
|
124176
125297
|
init_dist();
|
|
@@ -124412,7 +125533,12 @@ async function resolveOAuthCodex(vault) {
|
|
|
124412
125533
|
tokens,
|
|
124413
125534
|
onTokensRefreshed: async (next) => {
|
|
124414
125535
|
await persistCodexTokens(vault, next);
|
|
124415
|
-
}
|
|
125536
|
+
},
|
|
125537
|
+
// Cross-process recovery: when a refresh hits invalid_grant because another
|
|
125538
|
+
// moxxy process already rotated the single-use refresh token, the provider
|
|
125539
|
+
// re-reads the vault through this hook and retries once with the fresher
|
|
125540
|
+
// token instead of forcing a re-login.
|
|
125541
|
+
reloadTokens: () => readStoredTokens(vault)
|
|
124416
125542
|
};
|
|
124417
125543
|
}
|
|
124418
125544
|
|
|
@@ -124689,6 +125815,18 @@ async function setupSessionWithConfig(opts) {
|
|
|
124689
125815
|
pluginRegistration
|
|
124690
125816
|
};
|
|
124691
125817
|
}
|
|
125818
|
+
async function probeSession(opts, read, boot = setupSessionWithConfig) {
|
|
125819
|
+
const result = await boot({
|
|
125820
|
+
...opts,
|
|
125821
|
+
skipInitHooks: true,
|
|
125822
|
+
disableSessionPersistence: true
|
|
125823
|
+
});
|
|
125824
|
+
try {
|
|
125825
|
+
return await read(result);
|
|
125826
|
+
} finally {
|
|
125827
|
+
await result.session.close("probe-complete").catch(() => void 0);
|
|
125828
|
+
}
|
|
125829
|
+
}
|
|
124692
125830
|
|
|
124693
125831
|
// src/argv-helpers.ts
|
|
124694
125832
|
function argvToSetupOptions(argv, overrides = {}) {
|
|
@@ -124728,8 +125866,8 @@ function useColor() {
|
|
|
124728
125866
|
return Boolean(process.stdout.isTTY);
|
|
124729
125867
|
}
|
|
124730
125868
|
var ENABLED = useColor();
|
|
124731
|
-
function wrap(
|
|
124732
|
-
return (s2) => ENABLED ? `\x1B[${
|
|
125869
|
+
function wrap(open2, close) {
|
|
125870
|
+
return (s2) => ENABLED ? `\x1B[${open2}m${s2}\x1B[${close}m` : s2;
|
|
124733
125871
|
}
|
|
124734
125872
|
var colors = {
|
|
124735
125873
|
bold: wrap(1, 22),
|
|
@@ -125504,13 +126642,15 @@ async function runSelfHostedTui(argv, tuiOpts, standalone) {
|
|
|
125504
126642
|
let needsInit = sources.length === 0;
|
|
125505
126643
|
if (!needsInit) {
|
|
125506
126644
|
try {
|
|
125507
|
-
const
|
|
125508
|
-
|
|
125509
|
-
|
|
125510
|
-
|
|
125511
|
-
|
|
125512
|
-
|
|
125513
|
-
|
|
126645
|
+
const hasProvider = await probeSession(
|
|
126646
|
+
{
|
|
126647
|
+
...argvToSetupOptions(argv),
|
|
126648
|
+
tolerateNoProvider: true,
|
|
126649
|
+
skipKeyPrompt: true
|
|
126650
|
+
},
|
|
126651
|
+
({ session }) => Boolean(session.providers.getActiveName())
|
|
126652
|
+
);
|
|
126653
|
+
if (!hasProvider) needsInit = true;
|
|
125514
126654
|
} catch {
|
|
125515
126655
|
needsInit = true;
|
|
125516
126656
|
}
|
|
@@ -125887,8 +127027,8 @@ async function runPluginNewCommand(argv) {
|
|
|
125887
127027
|
const force = hasBoolFlag(argv, "force");
|
|
125888
127028
|
const root = here ? path3.join(process.cwd(), name) : path3.join(os5.homedir(), ".moxxy", "plugins", name);
|
|
125889
127029
|
try {
|
|
125890
|
-
const
|
|
125891
|
-
if (
|
|
127030
|
+
const stat2 = await promises.stat(root);
|
|
127031
|
+
if (stat2.isDirectory() && !force) {
|
|
125892
127032
|
printError(`refusing to overwrite ${root} (pass --force to allow)`);
|
|
125893
127033
|
return 1;
|
|
125894
127034
|
}
|
|
@@ -126046,12 +127186,14 @@ ${HELP4}`);
|
|
|
126046
127186
|
}
|
|
126047
127187
|
}
|
|
126048
127188
|
async function runList(argv) {
|
|
126049
|
-
const
|
|
126050
|
-
|
|
126051
|
-
|
|
126052
|
-
|
|
126053
|
-
|
|
126054
|
-
|
|
127189
|
+
const loaded = await probeSession(
|
|
127190
|
+
argvToSetupOptions(argv, {
|
|
127191
|
+
skipKeyPrompt: true,
|
|
127192
|
+
tolerateNoProvider: true,
|
|
127193
|
+
skipProviderActivation: true
|
|
127194
|
+
}),
|
|
127195
|
+
({ session }) => session.pluginHost.list()
|
|
127196
|
+
);
|
|
126055
127197
|
const disabled = await loadDisabledPackageNames();
|
|
126056
127198
|
const installed = /* @__PURE__ */ new Set([...loaded.map((p3) => p3.name), ...disabled]);
|
|
126057
127199
|
const nameCol = Math.max(8, ...loaded.map((p3) => p3.name.length), ...[...disabled].map((n2) => n2.length));
|
|
@@ -126324,24 +127466,37 @@ function errMsg2(err) {
|
|
|
126324
127466
|
// src/commands/run-channel.ts
|
|
126325
127467
|
async function runChannelByName(name, argv) {
|
|
126326
127468
|
if (name === "tui") return runTuiWithBootstrap(argv);
|
|
126327
|
-
const
|
|
126328
|
-
|
|
126329
|
-
|
|
126330
|
-
|
|
126331
|
-
|
|
126332
|
-
|
|
126333
|
-
|
|
126334
|
-
|
|
126335
|
-
|
|
127469
|
+
const outcome = await probeSession(
|
|
127470
|
+
argvToSetupOptions(argv, {
|
|
127471
|
+
skipKeyPrompt: true,
|
|
127472
|
+
tolerateNoProvider: true,
|
|
127473
|
+
skipProviderActivation: true
|
|
127474
|
+
}),
|
|
127475
|
+
async ({ session, vault, config }) => {
|
|
127476
|
+
const def = session.channels.get(name);
|
|
127477
|
+
if (!def) {
|
|
127478
|
+
printError(
|
|
127479
|
+
`unknown channel: ${name}
|
|
126336
127480
|
Available:
|
|
126337
127481
|
` + session.channels.list().map((d2) => ` ${d2.name} - ${d2.description}
|
|
126338
127482
|
`).join("")
|
|
126339
|
-
|
|
126340
|
-
|
|
126341
|
-
|
|
126342
|
-
|
|
126343
|
-
|
|
126344
|
-
|
|
127483
|
+
);
|
|
127484
|
+
return { code: 2 };
|
|
127485
|
+
}
|
|
127486
|
+
if (def.interactiveCommand && process.stdin.isTTY === true && argv.flags["no-wizard"] !== true && argv.flags["__skipWizard"] !== true && !hasBoolFlag(argv, "standalone") && !await isRunnerUp()) {
|
|
127487
|
+
return {
|
|
127488
|
+
code: await runChannelSubcommand(def, def.interactiveCommand, {
|
|
127489
|
+
session,
|
|
127490
|
+
vault,
|
|
127491
|
+
config,
|
|
127492
|
+
argv
|
|
127493
|
+
})
|
|
127494
|
+
};
|
|
127495
|
+
}
|
|
127496
|
+
return "start-headless";
|
|
127497
|
+
}
|
|
127498
|
+
);
|
|
127499
|
+
if (outcome !== "start-headless") return outcome.code;
|
|
126345
127500
|
return startRegisteredChannel(name, argv);
|
|
126346
127501
|
}
|
|
126347
127502
|
async function runChannelSubcommand(def, subName, ctx) {
|
|
@@ -126393,62 +127548,74 @@ async function runChannelsCommand(argv) {
|
|
|
126393
127548
|
if (!name || name === "list") {
|
|
126394
127549
|
return runList2();
|
|
126395
127550
|
}
|
|
126396
|
-
const
|
|
126397
|
-
|
|
126398
|
-
|
|
126399
|
-
|
|
126400
|
-
|
|
126401
|
-
|
|
126402
|
-
|
|
126403
|
-
|
|
126404
|
-
|
|
127551
|
+
const outcome = await probeSession(
|
|
127552
|
+
argvToSetupOptions(argv, {
|
|
127553
|
+
skipKeyPrompt: true,
|
|
127554
|
+
tolerateNoProvider: true,
|
|
127555
|
+
skipProviderActivation: true
|
|
127556
|
+
}),
|
|
127557
|
+
async ({ session, vault, config }) => {
|
|
127558
|
+
const def = session.channels.get(name);
|
|
127559
|
+
if (!def) {
|
|
127560
|
+
printError(
|
|
127561
|
+
`unknown channel: ${name}
|
|
126405
127562
|
Available:
|
|
126406
127563
|
` + session.channels.list().map((d2) => ` ${d2.name} \u2014 ${d2.description}
|
|
126407
127564
|
`).join("")
|
|
126408
|
-
|
|
126409
|
-
|
|
126410
|
-
|
|
126411
|
-
|
|
126412
|
-
|
|
126413
|
-
|
|
126414
|
-
|
|
126415
|
-
|
|
126416
|
-
|
|
126417
|
-
|
|
126418
|
-
|
|
126419
|
-
|
|
126420
|
-
|
|
127565
|
+
);
|
|
127566
|
+
return { code: 2 };
|
|
127567
|
+
}
|
|
127568
|
+
if (!sub) {
|
|
127569
|
+
if (helpRequested(argv)) {
|
|
127570
|
+
process.stdout.write(formatChannelHelp(def));
|
|
127571
|
+
return { code: 0 };
|
|
127572
|
+
}
|
|
127573
|
+
return "run-channel";
|
|
127574
|
+
}
|
|
127575
|
+
const subcommand = def.subcommands?.[sub];
|
|
127576
|
+
if (!subcommand) {
|
|
127577
|
+
const available = def.subcommands ? Object.entries(def.subcommands).map(([n2, c2]) => ` ${name} ${n2} \u2014 ${c2.description}
|
|
126421
127578
|
`).join("") : " (none)\n";
|
|
126422
|
-
|
|
126423
|
-
|
|
127579
|
+
printError(
|
|
127580
|
+
`unknown '${name}' subcommand: ${sub}
|
|
126424
127581
|
Available subcommands:
|
|
126425
127582
|
${available}`
|
|
126426
|
-
|
|
126427
|
-
|
|
126428
|
-
|
|
126429
|
-
|
|
126430
|
-
|
|
126431
|
-
|
|
126432
|
-
|
|
126433
|
-
|
|
126434
|
-
|
|
126435
|
-
|
|
126436
|
-
|
|
126437
|
-
|
|
126438
|
-
|
|
127583
|
+
);
|
|
127584
|
+
return { code: 2 };
|
|
127585
|
+
}
|
|
127586
|
+
if (helpRequested(argv)) {
|
|
127587
|
+
process.stdout.write(formatSubcommandHelp(name, sub, subcommand));
|
|
127588
|
+
return { code: 0 };
|
|
127589
|
+
}
|
|
127590
|
+
return {
|
|
127591
|
+
code: await runChannelSubcommand(def, sub, {
|
|
127592
|
+
session,
|
|
127593
|
+
vault,
|
|
127594
|
+
config,
|
|
127595
|
+
argv: { ...argv, positional: rest }
|
|
127596
|
+
})
|
|
127597
|
+
};
|
|
127598
|
+
}
|
|
127599
|
+
);
|
|
127600
|
+
if (outcome !== "run-channel") return outcome.code;
|
|
127601
|
+
return runChannelByName(name, argv);
|
|
126439
127602
|
}
|
|
126440
127603
|
async function runList2() {
|
|
126441
|
-
const {
|
|
126442
|
-
|
|
126443
|
-
|
|
127604
|
+
const { entries, config } = await probeSession(
|
|
127605
|
+
argvToSetupOptions(
|
|
127606
|
+
{ flags: {} },
|
|
127607
|
+
{ skipKeyPrompt: true, tolerateNoProvider: true, skipProviderActivation: true }
|
|
127608
|
+
),
|
|
127609
|
+
async ({ session, vault, config: config2 }) => ({
|
|
127610
|
+
config: config2,
|
|
127611
|
+
entries: await session.channels.listWithAvailability({
|
|
127612
|
+
cwd: process.cwd(),
|
|
127613
|
+
vault,
|
|
127614
|
+
logger: session.logger,
|
|
127615
|
+
options: {}
|
|
127616
|
+
})
|
|
127617
|
+
})
|
|
126444
127618
|
);
|
|
126445
|
-
const deps = {
|
|
126446
|
-
cwd: process.cwd(),
|
|
126447
|
-
vault,
|
|
126448
|
-
logger: session.logger,
|
|
126449
|
-
options: {}
|
|
126450
|
-
};
|
|
126451
|
-
const entries = await session.channels.listWithAvailability(deps);
|
|
126452
127619
|
const nameCol = Math.max(8, ...entries.map((e3) => e3.def.name.length));
|
|
126453
127620
|
for (const { def, availability } of entries) {
|
|
126454
127621
|
const namePadded = def.name.padEnd(nameCol);
|
|
@@ -126773,12 +127940,12 @@ ${HELP6}`);
|
|
|
126773
127940
|
}
|
|
126774
127941
|
}
|
|
126775
127942
|
async function statOf(entry) {
|
|
126776
|
-
const
|
|
127943
|
+
const stat2 = await promises.stat(entry.path).catch(() => null);
|
|
126777
127944
|
return {
|
|
126778
127945
|
entry,
|
|
126779
|
-
size:
|
|
126780
|
-
createdAt: new Date(entry.frontmatter.createdAt ??
|
|
126781
|
-
updatedAt: new Date(entry.frontmatter.updatedAt ??
|
|
127946
|
+
size: stat2?.size ?? entry.body.length,
|
|
127947
|
+
createdAt: new Date(entry.frontmatter.createdAt ?? stat2?.birthtime ?? Date.now()),
|
|
127948
|
+
updatedAt: new Date(entry.frontmatter.updatedAt ?? stat2?.mtime ?? Date.now())
|
|
126782
127949
|
};
|
|
126783
127950
|
}
|
|
126784
127951
|
function groupByType(stats) {
|
|
@@ -127455,13 +128622,17 @@ async function stepInstallDaemon(skipDaemon) {
|
|
|
127455
128622
|
}
|
|
127456
128623
|
async function stepTelegramStatus() {
|
|
127457
128624
|
try {
|
|
127458
|
-
const {
|
|
127459
|
-
|
|
127460
|
-
|
|
127461
|
-
|
|
127462
|
-
|
|
127463
|
-
|
|
127464
|
-
|
|
128625
|
+
const { hasToken, chatRaw } = await probeSession(
|
|
128626
|
+
{
|
|
128627
|
+
cwd: process.cwd(),
|
|
128628
|
+
skipKeyPrompt: true,
|
|
128629
|
+
tolerateNoProvider: true
|
|
128630
|
+
},
|
|
128631
|
+
async ({ vault }) => ({
|
|
128632
|
+
hasToken: await vault.has("telegram_bot_token"),
|
|
128633
|
+
chatRaw: await vault.get("telegram_authorized_chat_id")
|
|
128634
|
+
})
|
|
128635
|
+
);
|
|
127465
128636
|
const hasChat = !!chatRaw;
|
|
127466
128637
|
if (hasToken && hasChat) {
|
|
127467
128638
|
process.stdout.write(
|
|
@@ -127631,27 +128802,30 @@ async function runScheduleCommand(argv) {
|
|
|
127631
128802
|
}
|
|
127632
128803
|
if (sub === "setup") return await runScheduleSetup(argv);
|
|
127633
128804
|
if (sub === "daemon") return await runDaemon(argv);
|
|
127634
|
-
|
|
127635
|
-
|
|
127636
|
-
|
|
127637
|
-
|
|
127638
|
-
|
|
127639
|
-
|
|
127640
|
-
|
|
127641
|
-
|
|
127642
|
-
|
|
127643
|
-
|
|
127644
|
-
|
|
127645
|
-
|
|
127646
|
-
|
|
127647
|
-
|
|
127648
|
-
|
|
127649
|
-
|
|
127650
|
-
|
|
127651
|
-
|
|
127652
|
-
|
|
127653
|
-
|
|
127654
|
-
|
|
128805
|
+
if (sub === "run") return runScheduleNow(argv);
|
|
128806
|
+
return probeSession(
|
|
128807
|
+
{
|
|
128808
|
+
cwd: process.cwd(),
|
|
128809
|
+
skipKeyPrompt: true,
|
|
128810
|
+
tolerateNoProvider: true
|
|
128811
|
+
},
|
|
128812
|
+
async ({ scheduler }) => {
|
|
128813
|
+
switch (sub) {
|
|
128814
|
+
case "list":
|
|
128815
|
+
return listSchedules(scheduler.store);
|
|
128816
|
+
case "add":
|
|
128817
|
+
return addSchedule(scheduler.store, argv);
|
|
128818
|
+
case "remove":
|
|
128819
|
+
return removeSchedule(scheduler.store, argv);
|
|
128820
|
+
case "enable":
|
|
128821
|
+
case "disable":
|
|
128822
|
+
return toggleSchedule(scheduler.store, argv, sub);
|
|
128823
|
+
default:
|
|
128824
|
+
process.stderr.write(colors.red(`unknown subcommand: ${sub}`) + "\n" + SCHEDULE_HELP);
|
|
128825
|
+
return 2;
|
|
128826
|
+
}
|
|
128827
|
+
}
|
|
128828
|
+
);
|
|
127655
128829
|
}
|
|
127656
128830
|
|
|
127657
128831
|
// src/commands/doctor.ts
|
|
@@ -129265,6 +130439,31 @@ function describeCauseChain(err) {
|
|
|
129265
130439
|
return chain.join("\n");
|
|
129266
130440
|
}
|
|
129267
130441
|
|
|
130442
|
+
// src/process-guards.ts
|
|
130443
|
+
function installProcessGuards() {
|
|
130444
|
+
if (guardsInstalled) return;
|
|
130445
|
+
guardsInstalled = true;
|
|
130446
|
+
process.on("unhandledRejection", (reason) => {
|
|
130447
|
+
process.stderr.write(
|
|
130448
|
+
colors.red("[moxxy] unhandled promise rejection (process kept alive):") + "\n" + formatErrorForCli(reason, { debug: debugEnabled() }) + "\n"
|
|
130449
|
+
);
|
|
130450
|
+
});
|
|
130451
|
+
process.on("uncaughtException", (err) => {
|
|
130452
|
+
process.exitCode = 1;
|
|
130453
|
+
const msg = colors.red("[moxxy] uncaught exception \u2014 exiting:") + "\n" + formatErrorForCli(err, { debug: debugEnabled() }) + "\n";
|
|
130454
|
+
const backstop = setTimeout(() => process.exit(1), 250);
|
|
130455
|
+
process.stderr.write(msg, () => {
|
|
130456
|
+
clearTimeout(backstop);
|
|
130457
|
+
process.exit(1);
|
|
130458
|
+
});
|
|
130459
|
+
});
|
|
130460
|
+
}
|
|
130461
|
+
var guardsInstalled = false;
|
|
130462
|
+
function debugEnabled() {
|
|
130463
|
+
const v3 = process.env.MOXXY_DEBUG;
|
|
130464
|
+
return v3 === "1" || v3 === "true";
|
|
130465
|
+
}
|
|
130466
|
+
|
|
129268
130467
|
// src/bin.ts
|
|
129269
130468
|
var SECTIONS = [
|
|
129270
130469
|
{
|
|
@@ -129421,16 +130620,15 @@ async function main() {
|
|
|
129421
130620
|
if (handler) return handler(argv);
|
|
129422
130621
|
let isChannel = false;
|
|
129423
130622
|
try {
|
|
129424
|
-
|
|
129425
|
-
|
|
129426
|
-
|
|
129427
|
-
|
|
129428
|
-
|
|
129429
|
-
|
|
129430
|
-
|
|
129431
|
-
|
|
129432
|
-
|
|
129433
|
-
isChannel = session.channels.has(argv.command);
|
|
130623
|
+
isChannel = await probeSession(
|
|
130624
|
+
{
|
|
130625
|
+
cwd: process.cwd(),
|
|
130626
|
+
skipKeyPrompt: true,
|
|
130627
|
+
tolerateNoProvider: true,
|
|
130628
|
+
skipProviderActivation: true
|
|
130629
|
+
},
|
|
130630
|
+
({ session }) => session.channels.has(argv.command)
|
|
130631
|
+
);
|
|
129434
130632
|
} catch {
|
|
129435
130633
|
}
|
|
129436
130634
|
if (isChannel) {
|
|
@@ -129441,6 +130639,8 @@ async function main() {
|
|
|
129441
130639
|
);
|
|
129442
130640
|
return 2;
|
|
129443
130641
|
}
|
|
130642
|
+
process.title = ["moxxy", ...process.argv.slice(2)].join(" ");
|
|
130643
|
+
installProcessGuards();
|
|
129444
130644
|
main().then(
|
|
129445
130645
|
(code) => process.exit(code),
|
|
129446
130646
|
(err) => {
|