@moxxy/cli 0.7.2 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/bin.js +2069 -691
- package/dist/bin.js.map +1 -1
- package/package.json +2 -2
package/dist/bin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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,
|
|
3
|
+
import { z as z$1, defineProvider, definePlugin, defineTool, MoxxyError, writeFileAtomic, asTurnId, defineMode, asPluginId, defineChannel, defineTunnelProvider, spawnCliTunnel, isCliTunnelAvailable, createMutex, defineWorkflowExecutor, toFriendlyError, estimateTextTokens, classifyHttpStatus, createStuckLoopDetector, runCompactionIfNeeded, runElisionIfNeeded, collectProviderStream, usageEventFields, isContextOverflowError, emitRequestsAndDetectStuck, executeToolUses, buildSystemPromptWithSkills, projectMessages, defineCompactor, defineCacheStrategy, denyByDefaultResolver, createAllowListResolver, moxxyPath, zodToJsonSchema, runSingleShotTurn, bearerTokenMatches, resolveChannelToken, rotateChannelToken, estimateContextTokens as estimateContextTokens$1, 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, isSafeViewUrl, evaluateToolRule, summarizeSessionTokensFromEvents, computeElisionState, toolResultStubbed, toolResultStub, toolResultBytes, conversationalStubbed, conversationalStub, 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';
|
|
@@ -20,7 +20,7 @@ import * as z4mini from 'zod/v4-mini';
|
|
|
20
20
|
import * as z24 from 'zod/v4';
|
|
21
21
|
import V3, { stdin, stdout, env, cwd } from 'process';
|
|
22
22
|
import tty, { ReadStream as ReadStream$1 } from 'tty';
|
|
23
|
-
import {
|
|
23
|
+
import { EventEmitter } from 'events';
|
|
24
24
|
import { Buffer as Buffer$1 } from 'buffer';
|
|
25
25
|
import { readFile, mkdir, open, rm, stat, rename as rename$1, unlink, writeFile } from 'fs/promises';
|
|
26
26
|
import { spawn, spawnSync } from 'child_process';
|
|
@@ -433,18 +433,29 @@ var init_tools = __esm({
|
|
|
433
433
|
}
|
|
434
434
|
});
|
|
435
435
|
|
|
436
|
-
// ../core/dist/subagents/
|
|
437
|
-
function
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
async spawnAll(specs) {
|
|
443
|
-
return Promise.all(specs.map((s2) => runOne(rt3, s2)));
|
|
444
|
-
}
|
|
445
|
-
};
|
|
436
|
+
// ../core/dist/subagents/registry.js
|
|
437
|
+
function registerRetainedChild(session) {
|
|
438
|
+
retained.set(String(session.childSessionId), session);
|
|
439
|
+
}
|
|
440
|
+
function getRetainedChild(childSessionId) {
|
|
441
|
+
return retained.get(String(childSessionId));
|
|
446
442
|
}
|
|
447
|
-
|
|
443
|
+
function releaseRetainedChild(childSessionId) {
|
|
444
|
+
retained.delete(String(childSessionId));
|
|
445
|
+
}
|
|
446
|
+
function clearRetainedChildren() {
|
|
447
|
+
retained.clear();
|
|
448
|
+
}
|
|
449
|
+
var retained;
|
|
450
|
+
var init_registry = __esm({
|
|
451
|
+
"../core/dist/subagents/registry.js"() {
|
|
452
|
+
retained = /* @__PURE__ */ new Map();
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
// ../core/dist/subagents/run-child.js
|
|
457
|
+
async function runChildTurn(args) {
|
|
458
|
+
const { rt: rt3, spec, retainSession } = args;
|
|
448
459
|
const { parentSession, parentTurnId } = rt3;
|
|
449
460
|
const childSessionId = newSessionId();
|
|
450
461
|
const childTurnId = newTurnId();
|
|
@@ -456,6 +467,73 @@ async function runOne(rt3, spec) {
|
|
|
456
467
|
const { strategy, strategyName } = resolved;
|
|
457
468
|
const toolRegistry = spec.allowedTools && spec.allowedTools.length > 0 ? buildFilteredToolRegistry(parentSession.tools, new Set(spec.allowedTools)) : parentSession.tools;
|
|
458
469
|
const childLog = new EventLog();
|
|
470
|
+
const spawner = createSubagentSpawner(rt3);
|
|
471
|
+
const childCtx = buildChildContext(rt3, spec, childSessionId, childTurnId, toolRegistry, childLog, spawner);
|
|
472
|
+
const capture = await executeChildLoop({
|
|
473
|
+
rt: rt3,
|
|
474
|
+
spec,
|
|
475
|
+
label: label3,
|
|
476
|
+
childSessionId,
|
|
477
|
+
childTurnId,
|
|
478
|
+
childLog,
|
|
479
|
+
childCtx,
|
|
480
|
+
strategy,
|
|
481
|
+
strategyName,
|
|
482
|
+
emitCompleted: !retainSession
|
|
483
|
+
});
|
|
484
|
+
if (retainSession) {
|
|
485
|
+
registerRetainedChild({
|
|
486
|
+
label: label3,
|
|
487
|
+
childSessionId,
|
|
488
|
+
childTurnId,
|
|
489
|
+
childLog,
|
|
490
|
+
childCtx,
|
|
491
|
+
spec,
|
|
492
|
+
strategy,
|
|
493
|
+
strategyName,
|
|
494
|
+
parentSession,
|
|
495
|
+
parentTurnId
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
return capture.result;
|
|
499
|
+
}
|
|
500
|
+
async function continueChildTurn(args) {
|
|
501
|
+
const retained2 = getRetainedChild(args.childSessionId);
|
|
502
|
+
if (!retained2) {
|
|
503
|
+
throw new Error(`no retained subagent session for "${String(args.childSessionId)}"`);
|
|
504
|
+
}
|
|
505
|
+
await retained2.childLog.append({
|
|
506
|
+
type: "user_prompt",
|
|
507
|
+
sessionId: retained2.childSessionId,
|
|
508
|
+
turnId: retained2.childTurnId,
|
|
509
|
+
source: "user",
|
|
510
|
+
text: args.prompt
|
|
511
|
+
});
|
|
512
|
+
const rt3 = {
|
|
513
|
+
parentSession: retained2.parentSession,
|
|
514
|
+
parentTurnId: retained2.parentTurnId,
|
|
515
|
+
parentSignal: retained2.childCtx.signal,
|
|
516
|
+
parentModel: retained2.childCtx.model
|
|
517
|
+
};
|
|
518
|
+
const capture = await executeChildLoop({
|
|
519
|
+
rt: rt3,
|
|
520
|
+
spec: retained2.spec,
|
|
521
|
+
label: args.label ?? retained2.label,
|
|
522
|
+
childSessionId: retained2.childSessionId,
|
|
523
|
+
childTurnId: retained2.childTurnId,
|
|
524
|
+
childLog: retained2.childLog,
|
|
525
|
+
childCtx: retained2.childCtx,
|
|
526
|
+
strategy: retained2.strategy,
|
|
527
|
+
strategyName: retained2.strategyName,
|
|
528
|
+
emitCompleted: true,
|
|
529
|
+
skipStartEvent: true
|
|
530
|
+
});
|
|
531
|
+
releaseRetainedChild(args.childSessionId);
|
|
532
|
+
return capture.result;
|
|
533
|
+
}
|
|
534
|
+
async function executeChildLoop(args) {
|
|
535
|
+
const { rt: rt3, spec, label: label3, childSessionId, childTurnId, childLog, childCtx, strategy, strategyName, emitCompleted, skipStartEvent } = args;
|
|
536
|
+
const { parentSession, parentTurnId } = rt3;
|
|
459
537
|
const capture = { text: "", stopReason: "end_turn", error: null };
|
|
460
538
|
const unsubCapture = childLog.subscribe((e3) => {
|
|
461
539
|
if (e3.type === "assistant_message") {
|
|
@@ -468,15 +546,16 @@ async function runOne(rt3, spec) {
|
|
|
468
546
|
}
|
|
469
547
|
});
|
|
470
548
|
const unsubStream = childLog.subscribe((childEvt) => streamChildEventToParent(parentSession, parentTurnId, label3, childSessionId, childEvt));
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
549
|
+
if (!skipStartEvent) {
|
|
550
|
+
await emitSubagentStart(parentSession, parentTurnId, label3, childSessionId, spec, strategyName);
|
|
551
|
+
await childLog.append({
|
|
552
|
+
type: "user_prompt",
|
|
553
|
+
sessionId: childSessionId,
|
|
554
|
+
turnId: childTurnId,
|
|
555
|
+
source: "user",
|
|
556
|
+
text: spec.prompt
|
|
557
|
+
});
|
|
558
|
+
}
|
|
480
559
|
try {
|
|
481
560
|
for await (const _2 of strategy.run(childCtx)) {
|
|
482
561
|
void _2;
|
|
@@ -494,8 +573,10 @@ async function runOne(rt3, spec) {
|
|
|
494
573
|
stopReason: capture.error ? "error" : capture.stopReason,
|
|
495
574
|
...capture.error ? { error: { message: capture.error } } : {}
|
|
496
575
|
};
|
|
497
|
-
|
|
498
|
-
|
|
576
|
+
if (emitCompleted) {
|
|
577
|
+
await emitSubagentCompleted(parentSession, parentTurnId, label3, childSessionId, capture.text, result.stopReason, capture.error);
|
|
578
|
+
}
|
|
579
|
+
return { result };
|
|
499
580
|
}
|
|
500
581
|
async function resolveStrategy(parentSession, parentTurnId, label3, childSessionId, spec, requestedStrategy) {
|
|
501
582
|
const exact = parentSession.modes.list().find((s2) => s2.name === requestedStrategy);
|
|
@@ -519,7 +600,7 @@ async function resolveStrategy(parentSession, parentTurnId, label3, childSession
|
|
|
519
600
|
}
|
|
520
601
|
};
|
|
521
602
|
}
|
|
522
|
-
function buildChildContext(rt3, spec, childSessionId, childTurnId, toolRegistry, childLog) {
|
|
603
|
+
function buildChildContext(rt3, spec, childSessionId, childTurnId, toolRegistry, childLog, spawner) {
|
|
523
604
|
const { parentSession, parentSignal, parentModel } = rt3;
|
|
524
605
|
return {
|
|
525
606
|
sessionId: childSessionId,
|
|
@@ -543,20 +624,40 @@ function buildChildContext(rt3, spec, childSessionId, childTurnId, toolRegistry,
|
|
|
543
624
|
signal: parentSignal,
|
|
544
625
|
// child cancels when parent cancels
|
|
545
626
|
maxIterations: spec.maxIterations ?? 50,
|
|
546
|
-
subagents:
|
|
547
|
-
...rt3,
|
|
548
|
-
parentTurnId: childTurnId
|
|
549
|
-
// grand-children attach to this child's turn
|
|
550
|
-
}),
|
|
627
|
+
subagents: spawner,
|
|
551
628
|
emit: (event) => childLog.append(event)
|
|
552
629
|
};
|
|
553
630
|
}
|
|
554
|
-
|
|
555
|
-
|
|
631
|
+
function createSubagentSpawner(rt3) {
|
|
632
|
+
return {
|
|
633
|
+
async spawn(spec) {
|
|
634
|
+
return runChildTurn({ rt: rt3, spec, retainSession: spec.retainSession === true });
|
|
635
|
+
},
|
|
636
|
+
async spawnAll(specs) {
|
|
637
|
+
return Promise.all(specs.map((s2) => runChildTurn({ rt: rt3, spec: s2, retainSession: s2.retainSession === true })));
|
|
638
|
+
},
|
|
639
|
+
async continue(args) {
|
|
640
|
+
return continueChildTurn(args);
|
|
641
|
+
},
|
|
642
|
+
release(childSessionId) {
|
|
643
|
+
releaseRetainedChild(childSessionId);
|
|
644
|
+
}
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
var init_run_child = __esm({
|
|
648
|
+
"../core/dist/subagents/run-child.js"() {
|
|
556
649
|
init_log();
|
|
557
650
|
init_factory();
|
|
558
651
|
init_events();
|
|
559
652
|
init_tools();
|
|
653
|
+
init_registry();
|
|
654
|
+
}
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
// ../core/dist/subagents/spawn.js
|
|
658
|
+
var init_spawn = __esm({
|
|
659
|
+
"../core/dist/subagents/spawn.js"() {
|
|
660
|
+
init_run_child();
|
|
560
661
|
}
|
|
561
662
|
});
|
|
562
663
|
|
|
@@ -564,6 +665,7 @@ var init_spawn = __esm({
|
|
|
564
665
|
var init_subagents = __esm({
|
|
565
666
|
"../core/dist/subagents.js"() {
|
|
566
667
|
init_spawn();
|
|
668
|
+
init_registry();
|
|
567
669
|
}
|
|
568
670
|
});
|
|
569
671
|
|
|
@@ -2153,8 +2255,8 @@ var init_tools2 = __esm({
|
|
|
2153
2255
|
const parseResult = tool.inputSchema.safeParse(input);
|
|
2154
2256
|
if (!parseResult.success) {
|
|
2155
2257
|
const issues = parseResult.error.issues.map((iss) => {
|
|
2156
|
-
const
|
|
2157
|
-
return `${
|
|
2258
|
+
const path61 = iss.path.length ? iss.path.join(".") : "(root)";
|
|
2259
|
+
return `${path61}: ${iss.message}`;
|
|
2158
2260
|
}).join("; ");
|
|
2159
2261
|
throw new Error(`Invalid input for ${name}: ${issues}`);
|
|
2160
2262
|
}
|
|
@@ -2879,6 +2981,7 @@ var init_session = __esm({
|
|
|
2879
2981
|
init_engine();
|
|
2880
2982
|
init_resolvers();
|
|
2881
2983
|
init_logger();
|
|
2984
|
+
init_registry();
|
|
2882
2985
|
Session = class {
|
|
2883
2986
|
id;
|
|
2884
2987
|
cwd;
|
|
@@ -3053,6 +3156,7 @@ var init_session = __esm({
|
|
|
3053
3156
|
try {
|
|
3054
3157
|
await this.dispatcher.dispatchShutdown(this.appContext());
|
|
3055
3158
|
} finally {
|
|
3159
|
+
clearRetainedChildren();
|
|
3056
3160
|
this.abort(reason);
|
|
3057
3161
|
}
|
|
3058
3162
|
}
|
|
@@ -7986,6 +8090,7 @@ __export(dist_exports, {
|
|
|
7986
8090
|
autoAllowResolver: () => autoAllowResolver,
|
|
7987
8091
|
buildSkillIndexPrompt: () => buildSkillIndexPrompt,
|
|
7988
8092
|
buildSynthesizeSkillPlugin: () => buildSynthesizeSkillPlugin,
|
|
8093
|
+
clearRetainedChildren: () => clearRetainedChildren,
|
|
7989
8094
|
clearUsageStats: () => clearUsageStats,
|
|
7990
8095
|
collectTurn: () => collectTurn,
|
|
7991
8096
|
countNodes: () => countNodes,
|
|
@@ -8142,17 +8247,17 @@ var require_visit = __commonJS({
|
|
|
8142
8247
|
visit.BREAK = BREAK;
|
|
8143
8248
|
visit.SKIP = SKIP;
|
|
8144
8249
|
visit.REMOVE = REMOVE;
|
|
8145
|
-
function visit_(key, node, visitor,
|
|
8146
|
-
const ctrl = callVisitor(key, node, visitor,
|
|
8250
|
+
function visit_(key, node, visitor, path61) {
|
|
8251
|
+
const ctrl = callVisitor(key, node, visitor, path61);
|
|
8147
8252
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
8148
|
-
replaceNode(key,
|
|
8149
|
-
return visit_(key, ctrl, visitor,
|
|
8253
|
+
replaceNode(key, path61, ctrl);
|
|
8254
|
+
return visit_(key, ctrl, visitor, path61);
|
|
8150
8255
|
}
|
|
8151
8256
|
if (typeof ctrl !== "symbol") {
|
|
8152
8257
|
if (identity.isCollection(node)) {
|
|
8153
|
-
|
|
8258
|
+
path61 = Object.freeze(path61.concat(node));
|
|
8154
8259
|
for (let i2 = 0; i2 < node.items.length; ++i2) {
|
|
8155
|
-
const ci = visit_(i2, node.items[i2], visitor,
|
|
8260
|
+
const ci = visit_(i2, node.items[i2], visitor, path61);
|
|
8156
8261
|
if (typeof ci === "number")
|
|
8157
8262
|
i2 = ci - 1;
|
|
8158
8263
|
else if (ci === BREAK)
|
|
@@ -8163,13 +8268,13 @@ var require_visit = __commonJS({
|
|
|
8163
8268
|
}
|
|
8164
8269
|
}
|
|
8165
8270
|
} else if (identity.isPair(node)) {
|
|
8166
|
-
|
|
8167
|
-
const ck = visit_("key", node.key, visitor,
|
|
8271
|
+
path61 = Object.freeze(path61.concat(node));
|
|
8272
|
+
const ck = visit_("key", node.key, visitor, path61);
|
|
8168
8273
|
if (ck === BREAK)
|
|
8169
8274
|
return BREAK;
|
|
8170
8275
|
else if (ck === REMOVE)
|
|
8171
8276
|
node.key = null;
|
|
8172
|
-
const cv = visit_("value", node.value, visitor,
|
|
8277
|
+
const cv = visit_("value", node.value, visitor, path61);
|
|
8173
8278
|
if (cv === BREAK)
|
|
8174
8279
|
return BREAK;
|
|
8175
8280
|
else if (cv === REMOVE)
|
|
@@ -8190,17 +8295,17 @@ var require_visit = __commonJS({
|
|
|
8190
8295
|
visitAsync.BREAK = BREAK;
|
|
8191
8296
|
visitAsync.SKIP = SKIP;
|
|
8192
8297
|
visitAsync.REMOVE = REMOVE;
|
|
8193
|
-
async function visitAsync_(key, node, visitor,
|
|
8194
|
-
const ctrl = await callVisitor(key, node, visitor,
|
|
8298
|
+
async function visitAsync_(key, node, visitor, path61) {
|
|
8299
|
+
const ctrl = await callVisitor(key, node, visitor, path61);
|
|
8195
8300
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
8196
|
-
replaceNode(key,
|
|
8197
|
-
return visitAsync_(key, ctrl, visitor,
|
|
8301
|
+
replaceNode(key, path61, ctrl);
|
|
8302
|
+
return visitAsync_(key, ctrl, visitor, path61);
|
|
8198
8303
|
}
|
|
8199
8304
|
if (typeof ctrl !== "symbol") {
|
|
8200
8305
|
if (identity.isCollection(node)) {
|
|
8201
|
-
|
|
8306
|
+
path61 = Object.freeze(path61.concat(node));
|
|
8202
8307
|
for (let i2 = 0; i2 < node.items.length; ++i2) {
|
|
8203
|
-
const ci = await visitAsync_(i2, node.items[i2], visitor,
|
|
8308
|
+
const ci = await visitAsync_(i2, node.items[i2], visitor, path61);
|
|
8204
8309
|
if (typeof ci === "number")
|
|
8205
8310
|
i2 = ci - 1;
|
|
8206
8311
|
else if (ci === BREAK)
|
|
@@ -8211,13 +8316,13 @@ var require_visit = __commonJS({
|
|
|
8211
8316
|
}
|
|
8212
8317
|
}
|
|
8213
8318
|
} else if (identity.isPair(node)) {
|
|
8214
|
-
|
|
8215
|
-
const ck = await visitAsync_("key", node.key, visitor,
|
|
8319
|
+
path61 = Object.freeze(path61.concat(node));
|
|
8320
|
+
const ck = await visitAsync_("key", node.key, visitor, path61);
|
|
8216
8321
|
if (ck === BREAK)
|
|
8217
8322
|
return BREAK;
|
|
8218
8323
|
else if (ck === REMOVE)
|
|
8219
8324
|
node.key = null;
|
|
8220
|
-
const cv = await visitAsync_("value", node.value, visitor,
|
|
8325
|
+
const cv = await visitAsync_("value", node.value, visitor, path61);
|
|
8221
8326
|
if (cv === BREAK)
|
|
8222
8327
|
return BREAK;
|
|
8223
8328
|
else if (cv === REMOVE)
|
|
@@ -8244,23 +8349,23 @@ var require_visit = __commonJS({
|
|
|
8244
8349
|
}
|
|
8245
8350
|
return visitor;
|
|
8246
8351
|
}
|
|
8247
|
-
function callVisitor(key, node, visitor,
|
|
8352
|
+
function callVisitor(key, node, visitor, path61) {
|
|
8248
8353
|
if (typeof visitor === "function")
|
|
8249
|
-
return visitor(key, node,
|
|
8354
|
+
return visitor(key, node, path61);
|
|
8250
8355
|
if (identity.isMap(node))
|
|
8251
|
-
return visitor.Map?.(key, node,
|
|
8356
|
+
return visitor.Map?.(key, node, path61);
|
|
8252
8357
|
if (identity.isSeq(node))
|
|
8253
|
-
return visitor.Seq?.(key, node,
|
|
8358
|
+
return visitor.Seq?.(key, node, path61);
|
|
8254
8359
|
if (identity.isPair(node))
|
|
8255
|
-
return visitor.Pair?.(key, node,
|
|
8360
|
+
return visitor.Pair?.(key, node, path61);
|
|
8256
8361
|
if (identity.isScalar(node))
|
|
8257
|
-
return visitor.Scalar?.(key, node,
|
|
8362
|
+
return visitor.Scalar?.(key, node, path61);
|
|
8258
8363
|
if (identity.isAlias(node))
|
|
8259
|
-
return visitor.Alias?.(key, node,
|
|
8364
|
+
return visitor.Alias?.(key, node, path61);
|
|
8260
8365
|
return void 0;
|
|
8261
8366
|
}
|
|
8262
|
-
function replaceNode(key,
|
|
8263
|
-
const parent =
|
|
8367
|
+
function replaceNode(key, path61, node) {
|
|
8368
|
+
const parent = path61[path61.length - 1];
|
|
8264
8369
|
if (identity.isCollection(parent)) {
|
|
8265
8370
|
parent.items[key] = node;
|
|
8266
8371
|
} else if (identity.isPair(parent)) {
|
|
@@ -8861,10 +8966,10 @@ var require_Collection = __commonJS({
|
|
|
8861
8966
|
var createNode2 = require_createNode();
|
|
8862
8967
|
var identity = require_identity();
|
|
8863
8968
|
var Node = require_Node();
|
|
8864
|
-
function collectionFromPath(schema,
|
|
8969
|
+
function collectionFromPath(schema, path61, value) {
|
|
8865
8970
|
let v3 = value;
|
|
8866
|
-
for (let i2 =
|
|
8867
|
-
const k3 =
|
|
8971
|
+
for (let i2 = path61.length - 1; i2 >= 0; --i2) {
|
|
8972
|
+
const k3 = path61[i2];
|
|
8868
8973
|
if (typeof k3 === "number" && Number.isInteger(k3) && k3 >= 0) {
|
|
8869
8974
|
const a2 = [];
|
|
8870
8975
|
a2[k3] = v3;
|
|
@@ -8883,7 +8988,7 @@ var require_Collection = __commonJS({
|
|
|
8883
8988
|
sourceObjects: /* @__PURE__ */ new Map()
|
|
8884
8989
|
});
|
|
8885
8990
|
}
|
|
8886
|
-
var isEmptyPath = (
|
|
8991
|
+
var isEmptyPath = (path61) => path61 == null || typeof path61 === "object" && !!path61[Symbol.iterator]().next().done;
|
|
8887
8992
|
var Collection = class extends Node.NodeBase {
|
|
8888
8993
|
constructor(type, schema) {
|
|
8889
8994
|
super(type);
|
|
@@ -8913,11 +9018,11 @@ var require_Collection = __commonJS({
|
|
|
8913
9018
|
* be a Pair instance or a `{ key, value }` object, which may not have a key
|
|
8914
9019
|
* that already exists in the map.
|
|
8915
9020
|
*/
|
|
8916
|
-
addIn(
|
|
8917
|
-
if (isEmptyPath(
|
|
9021
|
+
addIn(path61, value) {
|
|
9022
|
+
if (isEmptyPath(path61))
|
|
8918
9023
|
this.add(value);
|
|
8919
9024
|
else {
|
|
8920
|
-
const [key, ...rest] =
|
|
9025
|
+
const [key, ...rest] = path61;
|
|
8921
9026
|
const node = this.get(key, true);
|
|
8922
9027
|
if (identity.isCollection(node))
|
|
8923
9028
|
node.addIn(rest, value);
|
|
@@ -8931,8 +9036,8 @@ var require_Collection = __commonJS({
|
|
|
8931
9036
|
* Removes a value from the collection.
|
|
8932
9037
|
* @returns `true` if the item was found and removed.
|
|
8933
9038
|
*/
|
|
8934
|
-
deleteIn(
|
|
8935
|
-
const [key, ...rest] =
|
|
9039
|
+
deleteIn(path61) {
|
|
9040
|
+
const [key, ...rest] = path61;
|
|
8936
9041
|
if (rest.length === 0)
|
|
8937
9042
|
return this.delete(key);
|
|
8938
9043
|
const node = this.get(key, true);
|
|
@@ -8946,8 +9051,8 @@ var require_Collection = __commonJS({
|
|
|
8946
9051
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
8947
9052
|
* `true` (collections are always returned intact).
|
|
8948
9053
|
*/
|
|
8949
|
-
getIn(
|
|
8950
|
-
const [key, ...rest] =
|
|
9054
|
+
getIn(path61, keepScalar) {
|
|
9055
|
+
const [key, ...rest] = path61;
|
|
8951
9056
|
const node = this.get(key, true);
|
|
8952
9057
|
if (rest.length === 0)
|
|
8953
9058
|
return !keepScalar && identity.isScalar(node) ? node.value : node;
|
|
@@ -8965,8 +9070,8 @@ var require_Collection = __commonJS({
|
|
|
8965
9070
|
/**
|
|
8966
9071
|
* Checks if the collection includes a value with the key `key`.
|
|
8967
9072
|
*/
|
|
8968
|
-
hasIn(
|
|
8969
|
-
const [key, ...rest] =
|
|
9073
|
+
hasIn(path61) {
|
|
9074
|
+
const [key, ...rest] = path61;
|
|
8970
9075
|
if (rest.length === 0)
|
|
8971
9076
|
return this.has(key);
|
|
8972
9077
|
const node = this.get(key, true);
|
|
@@ -8976,8 +9081,8 @@ var require_Collection = __commonJS({
|
|
|
8976
9081
|
* Sets a value in this collection. For `!!set`, `value` needs to be a
|
|
8977
9082
|
* boolean to add/remove the item from the set.
|
|
8978
9083
|
*/
|
|
8979
|
-
setIn(
|
|
8980
|
-
const [key, ...rest] =
|
|
9084
|
+
setIn(path61, value) {
|
|
9085
|
+
const [key, ...rest] = path61;
|
|
8981
9086
|
if (rest.length === 0) {
|
|
8982
9087
|
this.set(key, value);
|
|
8983
9088
|
} else {
|
|
@@ -11457,9 +11562,9 @@ var require_Document = __commonJS({
|
|
|
11457
11562
|
this.contents.add(value);
|
|
11458
11563
|
}
|
|
11459
11564
|
/** Adds a value to the document. */
|
|
11460
|
-
addIn(
|
|
11565
|
+
addIn(path61, value) {
|
|
11461
11566
|
if (assertCollection(this.contents))
|
|
11462
|
-
this.contents.addIn(
|
|
11567
|
+
this.contents.addIn(path61, value);
|
|
11463
11568
|
}
|
|
11464
11569
|
/**
|
|
11465
11570
|
* Create a new `Alias` node, ensuring that the target `node` has the required anchor.
|
|
@@ -11534,14 +11639,14 @@ var require_Document = __commonJS({
|
|
|
11534
11639
|
* Removes a value from the document.
|
|
11535
11640
|
* @returns `true` if the item was found and removed.
|
|
11536
11641
|
*/
|
|
11537
|
-
deleteIn(
|
|
11538
|
-
if (Collection.isEmptyPath(
|
|
11642
|
+
deleteIn(path61) {
|
|
11643
|
+
if (Collection.isEmptyPath(path61)) {
|
|
11539
11644
|
if (this.contents == null)
|
|
11540
11645
|
return false;
|
|
11541
11646
|
this.contents = null;
|
|
11542
11647
|
return true;
|
|
11543
11648
|
}
|
|
11544
|
-
return assertCollection(this.contents) ? this.contents.deleteIn(
|
|
11649
|
+
return assertCollection(this.contents) ? this.contents.deleteIn(path61) : false;
|
|
11545
11650
|
}
|
|
11546
11651
|
/**
|
|
11547
11652
|
* Returns item at `key`, or `undefined` if not found. By default unwraps
|
|
@@ -11556,10 +11661,10 @@ var require_Document = __commonJS({
|
|
|
11556
11661
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
11557
11662
|
* `true` (collections are always returned intact).
|
|
11558
11663
|
*/
|
|
11559
|
-
getIn(
|
|
11560
|
-
if (Collection.isEmptyPath(
|
|
11664
|
+
getIn(path61, keepScalar) {
|
|
11665
|
+
if (Collection.isEmptyPath(path61))
|
|
11561
11666
|
return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
|
|
11562
|
-
return identity.isCollection(this.contents) ? this.contents.getIn(
|
|
11667
|
+
return identity.isCollection(this.contents) ? this.contents.getIn(path61, keepScalar) : void 0;
|
|
11563
11668
|
}
|
|
11564
11669
|
/**
|
|
11565
11670
|
* Checks if the document includes a value with the key `key`.
|
|
@@ -11570,10 +11675,10 @@ var require_Document = __commonJS({
|
|
|
11570
11675
|
/**
|
|
11571
11676
|
* Checks if the document includes a value at `path`.
|
|
11572
11677
|
*/
|
|
11573
|
-
hasIn(
|
|
11574
|
-
if (Collection.isEmptyPath(
|
|
11678
|
+
hasIn(path61) {
|
|
11679
|
+
if (Collection.isEmptyPath(path61))
|
|
11575
11680
|
return this.contents !== void 0;
|
|
11576
|
-
return identity.isCollection(this.contents) ? this.contents.hasIn(
|
|
11681
|
+
return identity.isCollection(this.contents) ? this.contents.hasIn(path61) : false;
|
|
11577
11682
|
}
|
|
11578
11683
|
/**
|
|
11579
11684
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
@@ -11590,13 +11695,13 @@ var require_Document = __commonJS({
|
|
|
11590
11695
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
11591
11696
|
* boolean to add/remove the item from the set.
|
|
11592
11697
|
*/
|
|
11593
|
-
setIn(
|
|
11594
|
-
if (Collection.isEmptyPath(
|
|
11698
|
+
setIn(path61, value) {
|
|
11699
|
+
if (Collection.isEmptyPath(path61)) {
|
|
11595
11700
|
this.contents = value;
|
|
11596
11701
|
} else if (this.contents == null) {
|
|
11597
|
-
this.contents = Collection.collectionFromPath(this.schema, Array.from(
|
|
11702
|
+
this.contents = Collection.collectionFromPath(this.schema, Array.from(path61), value);
|
|
11598
11703
|
} else if (assertCollection(this.contents)) {
|
|
11599
|
-
this.contents.setIn(
|
|
11704
|
+
this.contents.setIn(path61, value);
|
|
11600
11705
|
}
|
|
11601
11706
|
}
|
|
11602
11707
|
/**
|
|
@@ -13536,9 +13641,9 @@ var require_cst_visit = __commonJS({
|
|
|
13536
13641
|
visit.BREAK = BREAK;
|
|
13537
13642
|
visit.SKIP = SKIP;
|
|
13538
13643
|
visit.REMOVE = REMOVE;
|
|
13539
|
-
visit.itemAtPath = (cst,
|
|
13644
|
+
visit.itemAtPath = (cst, path61) => {
|
|
13540
13645
|
let item = cst;
|
|
13541
|
-
for (const [field, index] of
|
|
13646
|
+
for (const [field, index] of path61) {
|
|
13542
13647
|
const tok = item?.[field];
|
|
13543
13648
|
if (tok && "items" in tok) {
|
|
13544
13649
|
item = tok.items[index];
|
|
@@ -13547,23 +13652,23 @@ var require_cst_visit = __commonJS({
|
|
|
13547
13652
|
}
|
|
13548
13653
|
return item;
|
|
13549
13654
|
};
|
|
13550
|
-
visit.parentCollection = (cst,
|
|
13551
|
-
const parent = visit.itemAtPath(cst,
|
|
13552
|
-
const field =
|
|
13655
|
+
visit.parentCollection = (cst, path61) => {
|
|
13656
|
+
const parent = visit.itemAtPath(cst, path61.slice(0, -1));
|
|
13657
|
+
const field = path61[path61.length - 1][0];
|
|
13553
13658
|
const coll = parent?.[field];
|
|
13554
13659
|
if (coll && "items" in coll)
|
|
13555
13660
|
return coll;
|
|
13556
13661
|
throw new Error("Parent collection not found");
|
|
13557
13662
|
};
|
|
13558
|
-
function _visit(
|
|
13559
|
-
let ctrl = visitor(item,
|
|
13663
|
+
function _visit(path61, item, visitor) {
|
|
13664
|
+
let ctrl = visitor(item, path61);
|
|
13560
13665
|
if (typeof ctrl === "symbol")
|
|
13561
13666
|
return ctrl;
|
|
13562
13667
|
for (const field of ["key", "value"]) {
|
|
13563
13668
|
const token = item[field];
|
|
13564
13669
|
if (token && "items" in token) {
|
|
13565
13670
|
for (let i2 = 0; i2 < token.items.length; ++i2) {
|
|
13566
|
-
const ci = _visit(Object.freeze(
|
|
13671
|
+
const ci = _visit(Object.freeze(path61.concat([[field, i2]])), token.items[i2], visitor);
|
|
13567
13672
|
if (typeof ci === "number")
|
|
13568
13673
|
i2 = ci - 1;
|
|
13569
13674
|
else if (ci === BREAK)
|
|
@@ -13574,10 +13679,10 @@ var require_cst_visit = __commonJS({
|
|
|
13574
13679
|
}
|
|
13575
13680
|
}
|
|
13576
13681
|
if (typeof ctrl === "function" && field === "key")
|
|
13577
|
-
ctrl = ctrl(item,
|
|
13682
|
+
ctrl = ctrl(item, path61);
|
|
13578
13683
|
}
|
|
13579
13684
|
}
|
|
13580
|
-
return typeof ctrl === "function" ? ctrl(item,
|
|
13685
|
+
return typeof ctrl === "function" ? ctrl(item, path61) : ctrl;
|
|
13581
13686
|
}
|
|
13582
13687
|
exports.visit = visit;
|
|
13583
13688
|
}
|
|
@@ -14875,14 +14980,14 @@ var require_parser = __commonJS({
|
|
|
14875
14980
|
case "scalar":
|
|
14876
14981
|
case "single-quoted-scalar":
|
|
14877
14982
|
case "double-quoted-scalar": {
|
|
14878
|
-
const
|
|
14983
|
+
const fs44 = this.flowScalar(this.type);
|
|
14879
14984
|
if (atNextItem || it4.value) {
|
|
14880
|
-
map2.items.push({ start, key:
|
|
14985
|
+
map2.items.push({ start, key: fs44, sep: [] });
|
|
14881
14986
|
this.onKeyLine = true;
|
|
14882
14987
|
} else if (it4.sep) {
|
|
14883
|
-
this.stack.push(
|
|
14988
|
+
this.stack.push(fs44);
|
|
14884
14989
|
} else {
|
|
14885
|
-
Object.assign(it4, { key:
|
|
14990
|
+
Object.assign(it4, { key: fs44, sep: [] });
|
|
14886
14991
|
this.onKeyLine = true;
|
|
14887
14992
|
}
|
|
14888
14993
|
return;
|
|
@@ -15010,13 +15115,13 @@ var require_parser = __commonJS({
|
|
|
15010
15115
|
case "scalar":
|
|
15011
15116
|
case "single-quoted-scalar":
|
|
15012
15117
|
case "double-quoted-scalar": {
|
|
15013
|
-
const
|
|
15118
|
+
const fs44 = this.flowScalar(this.type);
|
|
15014
15119
|
if (!it4 || it4.value)
|
|
15015
|
-
fc.items.push({ start: [], key:
|
|
15120
|
+
fc.items.push({ start: [], key: fs44, sep: [] });
|
|
15016
15121
|
else if (it4.sep)
|
|
15017
|
-
this.stack.push(
|
|
15122
|
+
this.stack.push(fs44);
|
|
15018
15123
|
else
|
|
15019
|
-
Object.assign(it4, { key:
|
|
15124
|
+
Object.assign(it4, { key: fs44, sep: [] });
|
|
15020
15125
|
return;
|
|
15021
15126
|
}
|
|
15022
15127
|
case "flow-map-end":
|
|
@@ -16299,14 +16404,14 @@ var require_url_state_machine = __commonJS({
|
|
|
16299
16404
|
return url2.replace(/\u0009|\u000A|\u000D/g, "");
|
|
16300
16405
|
}
|
|
16301
16406
|
function shortenPath(url2) {
|
|
16302
|
-
const
|
|
16303
|
-
if (
|
|
16407
|
+
const path61 = url2.path;
|
|
16408
|
+
if (path61.length === 0) {
|
|
16304
16409
|
return;
|
|
16305
16410
|
}
|
|
16306
|
-
if (url2.scheme === "file" &&
|
|
16411
|
+
if (url2.scheme === "file" && path61.length === 1 && isNormalizedWindowsDriveLetter(path61[0])) {
|
|
16307
16412
|
return;
|
|
16308
16413
|
}
|
|
16309
|
-
|
|
16414
|
+
path61.pop();
|
|
16310
16415
|
}
|
|
16311
16416
|
function includesCredentials(url2) {
|
|
16312
16417
|
return url2.username !== "" || url2.password !== "";
|
|
@@ -25529,14 +25634,14 @@ __export(fileFromPath_exports, {
|
|
|
25529
25634
|
fileFromPathSync: () => fileFromPathSync,
|
|
25530
25635
|
isFile: () => isFile
|
|
25531
25636
|
});
|
|
25532
|
-
function createFileFromPath(
|
|
25637
|
+
function createFileFromPath(path61, { mtimeMs, size }, filenameOrOptions, options = {}) {
|
|
25533
25638
|
let filename;
|
|
25534
25639
|
if (isPlainObject_default2(filenameOrOptions)) {
|
|
25535
25640
|
[options, filename] = [filenameOrOptions, void 0];
|
|
25536
25641
|
} else {
|
|
25537
25642
|
filename = filenameOrOptions;
|
|
25538
25643
|
}
|
|
25539
|
-
const file = new FileFromPath({ path:
|
|
25644
|
+
const file = new FileFromPath({ path: path61, size, lastModified: mtimeMs });
|
|
25540
25645
|
if (!filename) {
|
|
25541
25646
|
filename = file.name;
|
|
25542
25647
|
}
|
|
@@ -25545,13 +25650,13 @@ function createFileFromPath(path60, { mtimeMs, size }, filenameOrOptions, option
|
|
|
25545
25650
|
lastModified: file.lastModified
|
|
25546
25651
|
});
|
|
25547
25652
|
}
|
|
25548
|
-
function fileFromPathSync(
|
|
25549
|
-
const stats = statSync(
|
|
25550
|
-
return createFileFromPath(
|
|
25653
|
+
function fileFromPathSync(path61, filenameOrOptions, options = {}) {
|
|
25654
|
+
const stats = statSync(path61);
|
|
25655
|
+
return createFileFromPath(path61, stats, filenameOrOptions, options);
|
|
25551
25656
|
}
|
|
25552
|
-
async function fileFromPath2(
|
|
25553
|
-
const stats = await promises.stat(
|
|
25554
|
-
return createFileFromPath(
|
|
25657
|
+
async function fileFromPath2(path61, filenameOrOptions, options) {
|
|
25658
|
+
const stats = await promises.stat(path61);
|
|
25659
|
+
return createFileFromPath(path61, stats, filenameOrOptions, options);
|
|
25555
25660
|
}
|
|
25556
25661
|
var import_node_domexception, __classPrivateFieldSet4, __classPrivateFieldGet5, _FileFromPath_path, _FileFromPath_start, MESSAGE, FileFromPath;
|
|
25557
25662
|
var init_fileFromPath = __esm({
|
|
@@ -41683,8 +41788,8 @@ var require_utils2 = __commonJS({
|
|
|
41683
41788
|
}
|
|
41684
41789
|
return ind;
|
|
41685
41790
|
}
|
|
41686
|
-
function removeDotSegments(
|
|
41687
|
-
let input =
|
|
41791
|
+
function removeDotSegments(path61) {
|
|
41792
|
+
let input = path61;
|
|
41688
41793
|
const output = [];
|
|
41689
41794
|
let nextSlash = -1;
|
|
41690
41795
|
let len = 0;
|
|
@@ -41935,8 +42040,8 @@ var require_schemes = __commonJS({
|
|
|
41935
42040
|
wsComponent.secure = void 0;
|
|
41936
42041
|
}
|
|
41937
42042
|
if (wsComponent.resourceName) {
|
|
41938
|
-
const [
|
|
41939
|
-
wsComponent.path =
|
|
42043
|
+
const [path61, query] = wsComponent.resourceName.split("?");
|
|
42044
|
+
wsComponent.path = path61 && path61 !== "/" ? path61 : void 0;
|
|
41940
42045
|
wsComponent.query = query;
|
|
41941
42046
|
wsComponent.resourceName = void 0;
|
|
41942
42047
|
}
|
|
@@ -45283,12 +45388,12 @@ var require_dist2 = __commonJS({
|
|
|
45283
45388
|
throw new Error(`Unknown format "${name}"`);
|
|
45284
45389
|
return f3;
|
|
45285
45390
|
};
|
|
45286
|
-
function addFormats(ajv, list,
|
|
45391
|
+
function addFormats(ajv, list, fs44, exportName) {
|
|
45287
45392
|
var _a3;
|
|
45288
45393
|
var _b;
|
|
45289
45394
|
(_a3 = (_b = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
45290
45395
|
for (const f3 of list)
|
|
45291
|
-
ajv.addFormat(f3,
|
|
45396
|
+
ajv.addFormat(f3, fs44[f3]);
|
|
45292
45397
|
}
|
|
45293
45398
|
module.exports = exports = formatsPlugin;
|
|
45294
45399
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -46093,8 +46198,8 @@ var require_windows = __commonJS({
|
|
|
46093
46198
|
"../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/windows.js"(exports, module) {
|
|
46094
46199
|
module.exports = isexe;
|
|
46095
46200
|
isexe.sync = sync;
|
|
46096
|
-
var
|
|
46097
|
-
function checkPathExt(
|
|
46201
|
+
var fs44 = __require("fs");
|
|
46202
|
+
function checkPathExt(path61, options) {
|
|
46098
46203
|
var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
|
|
46099
46204
|
if (!pathext) {
|
|
46100
46205
|
return true;
|
|
@@ -46105,25 +46210,25 @@ var require_windows = __commonJS({
|
|
|
46105
46210
|
}
|
|
46106
46211
|
for (var i2 = 0; i2 < pathext.length; i2++) {
|
|
46107
46212
|
var p3 = pathext[i2].toLowerCase();
|
|
46108
|
-
if (p3 &&
|
|
46213
|
+
if (p3 && path61.substr(-p3.length).toLowerCase() === p3) {
|
|
46109
46214
|
return true;
|
|
46110
46215
|
}
|
|
46111
46216
|
}
|
|
46112
46217
|
return false;
|
|
46113
46218
|
}
|
|
46114
|
-
function checkStat(stat2,
|
|
46219
|
+
function checkStat(stat2, path61, options) {
|
|
46115
46220
|
if (!stat2.isSymbolicLink() && !stat2.isFile()) {
|
|
46116
46221
|
return false;
|
|
46117
46222
|
}
|
|
46118
|
-
return checkPathExt(
|
|
46223
|
+
return checkPathExt(path61, options);
|
|
46119
46224
|
}
|
|
46120
|
-
function isexe(
|
|
46121
|
-
|
|
46122
|
-
cb(er2, er2 ? false : checkStat(stat2,
|
|
46225
|
+
function isexe(path61, options, cb) {
|
|
46226
|
+
fs44.stat(path61, function(er2, stat2) {
|
|
46227
|
+
cb(er2, er2 ? false : checkStat(stat2, path61, options));
|
|
46123
46228
|
});
|
|
46124
46229
|
}
|
|
46125
|
-
function sync(
|
|
46126
|
-
return checkStat(
|
|
46230
|
+
function sync(path61, options) {
|
|
46231
|
+
return checkStat(fs44.statSync(path61), path61, options);
|
|
46127
46232
|
}
|
|
46128
46233
|
}
|
|
46129
46234
|
});
|
|
@@ -46133,14 +46238,14 @@ var require_mode = __commonJS({
|
|
|
46133
46238
|
"../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/mode.js"(exports, module) {
|
|
46134
46239
|
module.exports = isexe;
|
|
46135
46240
|
isexe.sync = sync;
|
|
46136
|
-
var
|
|
46137
|
-
function isexe(
|
|
46138
|
-
|
|
46241
|
+
var fs44 = __require("fs");
|
|
46242
|
+
function isexe(path61, options, cb) {
|
|
46243
|
+
fs44.stat(path61, function(er2, stat2) {
|
|
46139
46244
|
cb(er2, er2 ? false : checkStat(stat2, options));
|
|
46140
46245
|
});
|
|
46141
46246
|
}
|
|
46142
|
-
function sync(
|
|
46143
|
-
return checkStat(
|
|
46247
|
+
function sync(path61, options) {
|
|
46248
|
+
return checkStat(fs44.statSync(path61), options);
|
|
46144
46249
|
}
|
|
46145
46250
|
function checkStat(stat2, options) {
|
|
46146
46251
|
return stat2.isFile() && checkMode(stat2, options);
|
|
@@ -46173,7 +46278,7 @@ var require_isexe = __commonJS({
|
|
|
46173
46278
|
}
|
|
46174
46279
|
module.exports = isexe;
|
|
46175
46280
|
isexe.sync = sync;
|
|
46176
|
-
function isexe(
|
|
46281
|
+
function isexe(path61, options, cb) {
|
|
46177
46282
|
if (typeof options === "function") {
|
|
46178
46283
|
cb = options;
|
|
46179
46284
|
options = {};
|
|
@@ -46183,7 +46288,7 @@ var require_isexe = __commonJS({
|
|
|
46183
46288
|
throw new TypeError("callback not provided");
|
|
46184
46289
|
}
|
|
46185
46290
|
return new Promise(function(resolve12, reject) {
|
|
46186
|
-
isexe(
|
|
46291
|
+
isexe(path61, options || {}, function(er2, is) {
|
|
46187
46292
|
if (er2) {
|
|
46188
46293
|
reject(er2);
|
|
46189
46294
|
} else {
|
|
@@ -46192,7 +46297,7 @@ var require_isexe = __commonJS({
|
|
|
46192
46297
|
});
|
|
46193
46298
|
});
|
|
46194
46299
|
}
|
|
46195
|
-
core(
|
|
46300
|
+
core(path61, options || {}, function(er2, is) {
|
|
46196
46301
|
if (er2) {
|
|
46197
46302
|
if (er2.code === "EACCES" || options && options.ignoreErrors) {
|
|
46198
46303
|
er2 = null;
|
|
@@ -46202,9 +46307,9 @@ var require_isexe = __commonJS({
|
|
|
46202
46307
|
cb(er2, is);
|
|
46203
46308
|
});
|
|
46204
46309
|
}
|
|
46205
|
-
function sync(
|
|
46310
|
+
function sync(path61, options) {
|
|
46206
46311
|
try {
|
|
46207
|
-
return core.sync(
|
|
46312
|
+
return core.sync(path61, options || {});
|
|
46208
46313
|
} catch (er2) {
|
|
46209
46314
|
if (options && options.ignoreErrors || er2.code === "EACCES") {
|
|
46210
46315
|
return false;
|
|
@@ -46220,7 +46325,7 @@ var require_isexe = __commonJS({
|
|
|
46220
46325
|
var require_which = __commonJS({
|
|
46221
46326
|
"../../node_modules/.pnpm/which@2.0.2/node_modules/which/which.js"(exports, module) {
|
|
46222
46327
|
var isWindows3 = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
|
|
46223
|
-
var
|
|
46328
|
+
var path61 = __require("path");
|
|
46224
46329
|
var COLON = isWindows3 ? ";" : ":";
|
|
46225
46330
|
var isexe = require_isexe();
|
|
46226
46331
|
var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
|
|
@@ -46258,7 +46363,7 @@ var require_which = __commonJS({
|
|
|
46258
46363
|
return opt.all && found.length ? resolve12(found) : reject(getNotFoundError(cmd));
|
|
46259
46364
|
const ppRaw = pathEnv[i2];
|
|
46260
46365
|
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
46261
|
-
const pCmd =
|
|
46366
|
+
const pCmd = path61.join(pathPart, cmd);
|
|
46262
46367
|
const p3 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
46263
46368
|
resolve12(subStep(p3, i2, 0));
|
|
46264
46369
|
});
|
|
@@ -46285,7 +46390,7 @@ var require_which = __commonJS({
|
|
|
46285
46390
|
for (let i2 = 0; i2 < pathEnv.length; i2++) {
|
|
46286
46391
|
const ppRaw = pathEnv[i2];
|
|
46287
46392
|
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
46288
|
-
const pCmd =
|
|
46393
|
+
const pCmd = path61.join(pathPart, cmd);
|
|
46289
46394
|
const p3 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
46290
46395
|
for (let j3 = 0; j3 < pathExt.length; j3++) {
|
|
46291
46396
|
const cur = p3 + pathExt[j3];
|
|
@@ -46331,7 +46436,7 @@ var require_path_key = __commonJS({
|
|
|
46331
46436
|
// ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.js
|
|
46332
46437
|
var require_resolveCommand = __commonJS({
|
|
46333
46438
|
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.js"(exports, module) {
|
|
46334
|
-
var
|
|
46439
|
+
var path61 = __require("path");
|
|
46335
46440
|
var which = require_which();
|
|
46336
46441
|
var getPathKey = require_path_key();
|
|
46337
46442
|
function resolveCommandAttempt(parsed, withoutPathExt) {
|
|
@@ -46349,7 +46454,7 @@ var require_resolveCommand = __commonJS({
|
|
|
46349
46454
|
try {
|
|
46350
46455
|
resolved = which.sync(parsed.command, {
|
|
46351
46456
|
path: env3[getPathKey({ env: env3 })],
|
|
46352
|
-
pathExt: withoutPathExt ?
|
|
46457
|
+
pathExt: withoutPathExt ? path61.delimiter : void 0
|
|
46353
46458
|
});
|
|
46354
46459
|
} catch (e3) {
|
|
46355
46460
|
} finally {
|
|
@@ -46358,7 +46463,7 @@ var require_resolveCommand = __commonJS({
|
|
|
46358
46463
|
}
|
|
46359
46464
|
}
|
|
46360
46465
|
if (resolved) {
|
|
46361
|
-
resolved =
|
|
46466
|
+
resolved = path61.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
|
|
46362
46467
|
}
|
|
46363
46468
|
return resolved;
|
|
46364
46469
|
}
|
|
@@ -46409,8 +46514,8 @@ var require_shebang_command = __commonJS({
|
|
|
46409
46514
|
if (!match) {
|
|
46410
46515
|
return null;
|
|
46411
46516
|
}
|
|
46412
|
-
const [
|
|
46413
|
-
const binary =
|
|
46517
|
+
const [path61, argument] = match[0].replace(/#! ?/, "").split(" ");
|
|
46518
|
+
const binary = path61.split("/").pop();
|
|
46414
46519
|
if (binary === "env") {
|
|
46415
46520
|
return argument;
|
|
46416
46521
|
}
|
|
@@ -46422,16 +46527,16 @@ var require_shebang_command = __commonJS({
|
|
|
46422
46527
|
// ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.js
|
|
46423
46528
|
var require_readShebang = __commonJS({
|
|
46424
46529
|
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.js"(exports, module) {
|
|
46425
|
-
var
|
|
46530
|
+
var fs44 = __require("fs");
|
|
46426
46531
|
var shebangCommand = require_shebang_command();
|
|
46427
46532
|
function readShebang(command) {
|
|
46428
46533
|
const size = 150;
|
|
46429
46534
|
const buffer = Buffer.alloc(size);
|
|
46430
46535
|
let fd;
|
|
46431
46536
|
try {
|
|
46432
|
-
fd =
|
|
46433
|
-
|
|
46434
|
-
|
|
46537
|
+
fd = fs44.openSync(command, "r");
|
|
46538
|
+
fs44.readSync(fd, buffer, 0, size, 0);
|
|
46539
|
+
fs44.closeSync(fd);
|
|
46435
46540
|
} catch (e3) {
|
|
46436
46541
|
}
|
|
46437
46542
|
return shebangCommand(buffer.toString());
|
|
@@ -46443,7 +46548,7 @@ var require_readShebang = __commonJS({
|
|
|
46443
46548
|
// ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.js
|
|
46444
46549
|
var require_parse = __commonJS({
|
|
46445
46550
|
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.js"(exports, module) {
|
|
46446
|
-
var
|
|
46551
|
+
var path61 = __require("path");
|
|
46447
46552
|
var resolveCommand = require_resolveCommand();
|
|
46448
46553
|
var escape4 = require_escape();
|
|
46449
46554
|
var readShebang = require_readShebang();
|
|
@@ -46468,7 +46573,7 @@ var require_parse = __commonJS({
|
|
|
46468
46573
|
const needsShell = !isExecutableRegExp.test(commandFile);
|
|
46469
46574
|
if (parsed.options.forceShell || needsShell) {
|
|
46470
46575
|
const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
|
|
46471
|
-
parsed.command =
|
|
46576
|
+
parsed.command = path61.normalize(parsed.command);
|
|
46472
46577
|
parsed.command = escape4.command(parsed.command);
|
|
46473
46578
|
parsed.args = parsed.args.map((arg) => escape4.argument(arg, needsDoubleEscapeMetaChars));
|
|
46474
46579
|
const shellCommand = [parsed.command].concat(parsed.args).join(" ");
|
|
@@ -46556,7 +46661,7 @@ var require_cross_spawn = __commonJS({
|
|
|
46556
46661
|
var cp = __require("child_process");
|
|
46557
46662
|
var parse2 = require_parse();
|
|
46558
46663
|
var enoent = require_enoent();
|
|
46559
|
-
function
|
|
46664
|
+
function spawn14(command, args, options) {
|
|
46560
46665
|
const parsed = parse2(command, args, options);
|
|
46561
46666
|
const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
|
|
46562
46667
|
enoent.hookChildProcess(spawned, parsed);
|
|
@@ -46568,8 +46673,8 @@ var require_cross_spawn = __commonJS({
|
|
|
46568
46673
|
result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
|
|
46569
46674
|
return result;
|
|
46570
46675
|
}
|
|
46571
|
-
module.exports =
|
|
46572
|
-
module.exports.spawn =
|
|
46676
|
+
module.exports = spawn14;
|
|
46677
|
+
module.exports.spawn = spawn14;
|
|
46573
46678
|
module.exports.sync = spawnSync5;
|
|
46574
46679
|
module.exports._parse = parse2;
|
|
46575
46680
|
module.exports._enoent = enoent;
|
|
@@ -74297,10 +74402,10 @@ var require_react_reconciler_development = __commonJS({
|
|
|
74297
74402
|
var setErrorHandler = null;
|
|
74298
74403
|
var setSuspenseHandler = null;
|
|
74299
74404
|
{
|
|
74300
|
-
var copyWithDeleteImpl = function(obj,
|
|
74301
|
-
var key =
|
|
74405
|
+
var copyWithDeleteImpl = function(obj, path61, index2) {
|
|
74406
|
+
var key = path61[index2];
|
|
74302
74407
|
var updated = isArray(obj) ? obj.slice() : assign({}, obj);
|
|
74303
|
-
if (index2 + 1 ===
|
|
74408
|
+
if (index2 + 1 === path61.length) {
|
|
74304
74409
|
if (isArray(updated)) {
|
|
74305
74410
|
updated.splice(key, 1);
|
|
74306
74411
|
} else {
|
|
@@ -74308,11 +74413,11 @@ var require_react_reconciler_development = __commonJS({
|
|
|
74308
74413
|
}
|
|
74309
74414
|
return updated;
|
|
74310
74415
|
}
|
|
74311
|
-
updated[key] = copyWithDeleteImpl(obj[key],
|
|
74416
|
+
updated[key] = copyWithDeleteImpl(obj[key], path61, index2 + 1);
|
|
74312
74417
|
return updated;
|
|
74313
74418
|
};
|
|
74314
|
-
var copyWithDelete = function(obj,
|
|
74315
|
-
return copyWithDeleteImpl(obj,
|
|
74419
|
+
var copyWithDelete = function(obj, path61) {
|
|
74420
|
+
return copyWithDeleteImpl(obj, path61, 0);
|
|
74316
74421
|
};
|
|
74317
74422
|
var copyWithRenameImpl = function(obj, oldPath, newPath, index2) {
|
|
74318
74423
|
var oldKey = oldPath[index2];
|
|
@@ -74350,17 +74455,17 @@ var require_react_reconciler_development = __commonJS({
|
|
|
74350
74455
|
}
|
|
74351
74456
|
return copyWithRenameImpl(obj, oldPath, newPath, 0);
|
|
74352
74457
|
};
|
|
74353
|
-
var copyWithSetImpl = function(obj,
|
|
74354
|
-
if (index2 >=
|
|
74458
|
+
var copyWithSetImpl = function(obj, path61, index2, value) {
|
|
74459
|
+
if (index2 >= path61.length) {
|
|
74355
74460
|
return value;
|
|
74356
74461
|
}
|
|
74357
|
-
var key =
|
|
74462
|
+
var key = path61[index2];
|
|
74358
74463
|
var updated = isArray(obj) ? obj.slice() : assign({}, obj);
|
|
74359
|
-
updated[key] = copyWithSetImpl(obj[key],
|
|
74464
|
+
updated[key] = copyWithSetImpl(obj[key], path61, index2 + 1, value);
|
|
74360
74465
|
return updated;
|
|
74361
74466
|
};
|
|
74362
|
-
var copyWithSet = function(obj,
|
|
74363
|
-
return copyWithSetImpl(obj,
|
|
74467
|
+
var copyWithSet = function(obj, path61, value) {
|
|
74468
|
+
return copyWithSetImpl(obj, path61, 0, value);
|
|
74364
74469
|
};
|
|
74365
74470
|
var findHook = function(fiber, id) {
|
|
74366
74471
|
var currentHook2 = fiber.memoizedState;
|
|
@@ -74370,10 +74475,10 @@ var require_react_reconciler_development = __commonJS({
|
|
|
74370
74475
|
}
|
|
74371
74476
|
return currentHook2;
|
|
74372
74477
|
};
|
|
74373
|
-
overrideHookState = function(fiber, id,
|
|
74478
|
+
overrideHookState = function(fiber, id, path61, value) {
|
|
74374
74479
|
var hook = findHook(fiber, id);
|
|
74375
74480
|
if (hook !== null) {
|
|
74376
|
-
var newState = copyWithSet(hook.memoizedState,
|
|
74481
|
+
var newState = copyWithSet(hook.memoizedState, path61, value);
|
|
74377
74482
|
hook.memoizedState = newState;
|
|
74378
74483
|
hook.baseState = newState;
|
|
74379
74484
|
fiber.memoizedProps = assign({}, fiber.memoizedProps);
|
|
@@ -74383,10 +74488,10 @@ var require_react_reconciler_development = __commonJS({
|
|
|
74383
74488
|
}
|
|
74384
74489
|
}
|
|
74385
74490
|
};
|
|
74386
|
-
overrideHookStateDeletePath = function(fiber, id,
|
|
74491
|
+
overrideHookStateDeletePath = function(fiber, id, path61) {
|
|
74387
74492
|
var hook = findHook(fiber, id);
|
|
74388
74493
|
if (hook !== null) {
|
|
74389
|
-
var newState = copyWithDelete(hook.memoizedState,
|
|
74494
|
+
var newState = copyWithDelete(hook.memoizedState, path61);
|
|
74390
74495
|
hook.memoizedState = newState;
|
|
74391
74496
|
hook.baseState = newState;
|
|
74392
74497
|
fiber.memoizedProps = assign({}, fiber.memoizedProps);
|
|
@@ -74409,8 +74514,8 @@ var require_react_reconciler_development = __commonJS({
|
|
|
74409
74514
|
}
|
|
74410
74515
|
}
|
|
74411
74516
|
};
|
|
74412
|
-
overrideProps = function(fiber,
|
|
74413
|
-
fiber.pendingProps = copyWithSet(fiber.memoizedProps,
|
|
74517
|
+
overrideProps = function(fiber, path61, value) {
|
|
74518
|
+
fiber.pendingProps = copyWithSet(fiber.memoizedProps, path61, value);
|
|
74414
74519
|
if (fiber.alternate) {
|
|
74415
74520
|
fiber.alternate.pendingProps = fiber.pendingProps;
|
|
74416
74521
|
}
|
|
@@ -74419,8 +74524,8 @@ var require_react_reconciler_development = __commonJS({
|
|
|
74419
74524
|
scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp);
|
|
74420
74525
|
}
|
|
74421
74526
|
};
|
|
74422
|
-
overridePropsDeletePath = function(fiber,
|
|
74423
|
-
fiber.pendingProps = copyWithDelete(fiber.memoizedProps,
|
|
74527
|
+
overridePropsDeletePath = function(fiber, path61) {
|
|
74528
|
+
fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path61);
|
|
74424
74529
|
if (fiber.alternate) {
|
|
74425
74530
|
fiber.alternate.pendingProps = fiber.pendingProps;
|
|
74426
74531
|
}
|
|
@@ -81862,8 +81967,8 @@ var init_ErrorOverview = __esm({
|
|
|
81862
81967
|
init_dist7();
|
|
81863
81968
|
init_Box();
|
|
81864
81969
|
init_Text();
|
|
81865
|
-
cleanupPath = (
|
|
81866
|
-
return
|
|
81970
|
+
cleanupPath = (path61) => {
|
|
81971
|
+
return path61?.replace(`file://${cwd()}/`, "");
|
|
81867
81972
|
};
|
|
81868
81973
|
stackUtils = new import_stack_utils.default({
|
|
81869
81974
|
cwd: cwd(),
|
|
@@ -86352,8 +86457,8 @@ function readClipboardImageLinux() {
|
|
|
86352
86457
|
if (result.status === 0 && result.stdout && result.stdout.length > 0) {
|
|
86353
86458
|
const target = nextCachePath();
|
|
86354
86459
|
try {
|
|
86355
|
-
const
|
|
86356
|
-
|
|
86460
|
+
const fs44 = __require("fs");
|
|
86461
|
+
fs44.writeFileSync(target, result.stdout);
|
|
86357
86462
|
} catch {
|
|
86358
86463
|
return null;
|
|
86359
86464
|
}
|
|
@@ -88004,6 +88109,8 @@ var init_WorkflowsPanel = __esm({
|
|
|
88004
88109
|
const [loading, setLoading] = import_react55.default.useState(true);
|
|
88005
88110
|
const [busy, setBusy] = import_react55.default.useState(false);
|
|
88006
88111
|
const [status, setStatus] = import_react55.default.useState(null);
|
|
88112
|
+
const [pending, setPending] = import_react55.default.useState(null);
|
|
88113
|
+
const [reply2, setReply] = import_react55.default.useState("");
|
|
88007
88114
|
const reload = import_react55.default.useCallback(async () => {
|
|
88008
88115
|
if (!view) {
|
|
88009
88116
|
setLoading(false);
|
|
@@ -88021,7 +88128,7 @@ var init_WorkflowsPanel = __esm({
|
|
|
88021
88128
|
import_react55.default.useEffect(() => {
|
|
88022
88129
|
void reload();
|
|
88023
88130
|
}, [reload]);
|
|
88024
|
-
const active = !busy && !!view && rows.length > 0;
|
|
88131
|
+
const active = !busy && !pending && !!view && rows.length > 0;
|
|
88025
88132
|
const run2 = import_react55.default.useCallback(async (wf) => {
|
|
88026
88133
|
if (!view || busy)
|
|
88027
88134
|
return;
|
|
@@ -88033,6 +88140,17 @@ var init_WorkflowsPanel = __esm({
|
|
|
88033
88140
|
setStatus(`running "${wf.name}"\u2026`);
|
|
88034
88141
|
try {
|
|
88035
88142
|
const result = await view.run(wf.name);
|
|
88143
|
+
if (result.status === "paused" && result.runId) {
|
|
88144
|
+
const askStep = result.steps.find((s2) => s2.status === "awaiting_input");
|
|
88145
|
+
setPending({
|
|
88146
|
+
runId: result.runId,
|
|
88147
|
+
label: askStep?.id ?? wf.name,
|
|
88148
|
+
prompt: result.output || "The workflow is waiting for your input."
|
|
88149
|
+
});
|
|
88150
|
+
setReply("");
|
|
88151
|
+
setStatus(`\u23F8 "${wf.name}" is waiting for your reply \u2014 type it and press Enter (Esc cancels).`);
|
|
88152
|
+
return;
|
|
88153
|
+
}
|
|
88036
88154
|
const marks = result.steps.map((s2) => `${stepMark(s2.status)}${s2.id}`).join(" ");
|
|
88037
88155
|
setStatus(result.ok ? `\u2713 ${wf.name} completed \u2014 ${marks}` : `\u2717 ${wf.name} failed: ${result.error ?? ""} \u2014 ${marks}`);
|
|
88038
88156
|
} catch (err) {
|
|
@@ -88042,6 +88160,35 @@ var init_WorkflowsPanel = __esm({
|
|
|
88042
88160
|
void reload();
|
|
88043
88161
|
}
|
|
88044
88162
|
}, [view, busy, reload]);
|
|
88163
|
+
const submitReply = import_react55.default.useCallback(async (pendingRun, text) => {
|
|
88164
|
+
if (!view?.resume) {
|
|
88165
|
+
setStatus("resume not supported by this session");
|
|
88166
|
+
return;
|
|
88167
|
+
}
|
|
88168
|
+
const answer = text.trim();
|
|
88169
|
+
if (!answer)
|
|
88170
|
+
return;
|
|
88171
|
+
setPending(null);
|
|
88172
|
+
setReply("");
|
|
88173
|
+
setBusy(true);
|
|
88174
|
+
setStatus(`resuming "${pendingRun.label}"\u2026`);
|
|
88175
|
+
try {
|
|
88176
|
+
const result = await view.resume(pendingRun.runId, answer);
|
|
88177
|
+
if (result.status === "paused" && result.runId) {
|
|
88178
|
+
const askStep = result.steps.find((s2) => s2.status === "awaiting_input");
|
|
88179
|
+
setPending({ runId: result.runId, label: askStep?.id ?? pendingRun.label, prompt: result.output });
|
|
88180
|
+
setStatus("\u23F8 waiting again \u2014 type your reply and press Enter (Esc cancels).");
|
|
88181
|
+
} else {
|
|
88182
|
+
const marks = result.steps.map((s2) => `${stepMark(s2.status)}${s2.id}`).join(" ");
|
|
88183
|
+
setStatus(result.ok ? `\u2713 resumed & completed \u2014 ${marks}` : `\u2717 resume failed: ${result.error ?? ""} \u2014 ${marks}`);
|
|
88184
|
+
}
|
|
88185
|
+
} catch (err) {
|
|
88186
|
+
setStatus(`\u2717 resume errored: ${err instanceof Error ? err.message : String(err)}`);
|
|
88187
|
+
} finally {
|
|
88188
|
+
setBusy(false);
|
|
88189
|
+
void reload();
|
|
88190
|
+
}
|
|
88191
|
+
}, [view, reload]);
|
|
88045
88192
|
const scroll = useScrollableList({
|
|
88046
88193
|
total: rows.length,
|
|
88047
88194
|
windowSize: WINDOW4,
|
|
@@ -88067,6 +88214,26 @@ var init_WorkflowsPanel = __esm({
|
|
|
88067
88214
|
void run2(wf);
|
|
88068
88215
|
}
|
|
88069
88216
|
}, { isActive: active });
|
|
88217
|
+
use_input_default((input, key) => {
|
|
88218
|
+
if (!pending)
|
|
88219
|
+
return;
|
|
88220
|
+
if (key.escape) {
|
|
88221
|
+
setPending(null);
|
|
88222
|
+
setReply("");
|
|
88223
|
+
setStatus("reply cancelled \u2014 the run stays paused (re-run to resume).");
|
|
88224
|
+
return;
|
|
88225
|
+
}
|
|
88226
|
+
if (key.return) {
|
|
88227
|
+
void submitReply(pending, reply2);
|
|
88228
|
+
return;
|
|
88229
|
+
}
|
|
88230
|
+
if (key.backspace || key.delete) {
|
|
88231
|
+
setReply((r2) => r2.slice(0, -1));
|
|
88232
|
+
return;
|
|
88233
|
+
}
|
|
88234
|
+
if (input && !key.ctrl && !key.meta)
|
|
88235
|
+
setReply((r2) => r2 + input);
|
|
88236
|
+
}, { isActive: !busy && !!pending });
|
|
88070
88237
|
const termWidth = process.stdout.columns ?? 80;
|
|
88071
88238
|
const descWidth = Math.max(16, termWidth - NAME_COL3 - SCOPE_COL2 - TRIG_COL - 12);
|
|
88072
88239
|
const slice = rows.slice(scroll.visible.start, scroll.visible.end);
|
|
@@ -88076,7 +88243,7 @@ var init_WorkflowsPanel = __esm({
|
|
|
88076
88243
|
const absoluteIndex = scroll.visible.start + i2;
|
|
88077
88244
|
const focused = absoluteIndex === scroll.cursor;
|
|
88078
88245
|
return (0, import_jsx_runtime27.jsxs)(Box_default, { children: [(0, import_jsx_runtime27.jsx)(Text, { ...focused ? {} : { dimColor: true }, children: focused ? "\u203A " : " " }), (0, import_jsx_runtime27.jsx)(Text, { color: wf.enabled ? Colors.active : void 0, dimColor: !wf.enabled, children: wf.enabled ? "\u25CF " : "\u25CB " }), (0, import_jsx_runtime27.jsx)(Box_default, { width: NAME_COL3, children: (0, import_jsx_runtime27.jsx)(Text, { bold: focused, children: truncate8(wf.name, NAME_COL3 - 1) }) }), (0, import_jsx_runtime27.jsx)(Box_default, { width: SCOPE_COL2, children: (0, import_jsx_runtime27.jsx)(Text, { dimColor: true, children: wf.scope }) }), (0, import_jsx_runtime27.jsx)(Box_default, { width: TRIG_COL, children: (0, import_jsx_runtime27.jsx)(Text, { dimColor: true, wrap: "truncate", children: wf.triggers }) }), (0, import_jsx_runtime27.jsx)(Box_default, { width: descWidth, children: (0, import_jsx_runtime27.jsx)(Text, { dimColor: true, wrap: "truncate", children: oneLine5(wf.description) }) })] }, wf.name);
|
|
88079
|
-
}), scroll.canScrollDown ? (0, import_jsx_runtime27.jsx)(Text, { dimColor: true, children: ` \u2193 ${rows.length - scroll.visible.end} more below` }) : null, status ? (0, import_jsx_runtime27.jsx)(Box_default, { marginTop: 1, children: (0, import_jsx_runtime27.jsx)(Text, { wrap: "truncate-end", children: status }) }) : null] });
|
|
88246
|
+
}), scroll.canScrollDown ? (0, import_jsx_runtime27.jsx)(Text, { dimColor: true, children: ` \u2193 ${rows.length - scroll.visible.end} more below` }) : null, pending ? (0, import_jsx_runtime27.jsxs)(Box_default, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: Colors.active, paddingX: 1, children: [(0, import_jsx_runtime27.jsxs)(Text, { color: Colors.active, children: ["\u23F8 Workflow waiting \xB7 ", pending.label] }), pending.prompt ? (0, import_jsx_runtime27.jsx)(Text, { wrap: "wrap", children: oneLine5(pending.prompt).slice(0, 280) }) : null, (0, import_jsx_runtime27.jsxs)(Box_default, { marginTop: 1, children: [(0, import_jsx_runtime27.jsx)(Text, { children: "reply \u203A " }), (0, import_jsx_runtime27.jsx)(Text, { children: reply2 || " " })] }), (0, import_jsx_runtime27.jsx)(Text, { dimColor: true, children: "Enter send \xB7 Esc cancel" })] }) : null, status ? (0, import_jsx_runtime27.jsx)(Box_default, { marginTop: 1, children: (0, import_jsx_runtime27.jsx)(Text, { wrap: "truncate-end", children: status }) }) : null] });
|
|
88080
88247
|
};
|
|
88081
88248
|
}
|
|
88082
88249
|
});
|
|
@@ -90717,10 +90884,10 @@ var require_segments = __commonJS({
|
|
|
90717
90884
|
const segs = getSegmentsFromString(data, Utils.isKanjiModeEnabled());
|
|
90718
90885
|
const nodes = buildNodes(segs);
|
|
90719
90886
|
const graph = buildGraph(nodes, version);
|
|
90720
|
-
const
|
|
90887
|
+
const path61 = dijkstra.find_path(graph.map, "start", "end");
|
|
90721
90888
|
const optimizedSegs = [];
|
|
90722
|
-
for (let i2 = 1; i2 <
|
|
90723
|
-
optimizedSegs.push(graph.table[
|
|
90889
|
+
for (let i2 = 1; i2 < path61.length - 1; i2++) {
|
|
90890
|
+
optimizedSegs.push(graph.table[path61[i2]].node);
|
|
90724
90891
|
}
|
|
90725
90892
|
return exports.fromArray(mergeSegments(optimizedSegs));
|
|
90726
90893
|
};
|
|
@@ -93131,7 +93298,7 @@ var require_utils4 = __commonJS({
|
|
|
93131
93298
|
// ../../node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/png.js
|
|
93132
93299
|
var require_png2 = __commonJS({
|
|
93133
93300
|
"../../node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/png.js"(exports) {
|
|
93134
|
-
var
|
|
93301
|
+
var fs44 = __require("fs");
|
|
93135
93302
|
var PNG = require_png().PNG;
|
|
93136
93303
|
var Utils = require_utils4();
|
|
93137
93304
|
exports.render = function render2(qrData, options) {
|
|
@@ -93172,7 +93339,7 @@ var require_png2 = __commonJS({
|
|
|
93172
93339
|
});
|
|
93173
93340
|
png.pack();
|
|
93174
93341
|
};
|
|
93175
|
-
exports.renderToFile = function renderToFile(
|
|
93342
|
+
exports.renderToFile = function renderToFile(path61, qrData, options, cb) {
|
|
93176
93343
|
if (typeof cb === "undefined") {
|
|
93177
93344
|
cb = options;
|
|
93178
93345
|
options = void 0;
|
|
@@ -93183,7 +93350,7 @@ var require_png2 = __commonJS({
|
|
|
93183
93350
|
called = true;
|
|
93184
93351
|
cb.apply(null, args);
|
|
93185
93352
|
};
|
|
93186
|
-
const stream =
|
|
93353
|
+
const stream = fs44.createWriteStream(path61);
|
|
93187
93354
|
stream.on("error", done);
|
|
93188
93355
|
stream.on("close", done);
|
|
93189
93356
|
exports.renderToFileStream(stream, qrData, options);
|
|
@@ -93245,14 +93412,14 @@ var require_utf8 = __commonJS({
|
|
|
93245
93412
|
}
|
|
93246
93413
|
return output;
|
|
93247
93414
|
};
|
|
93248
|
-
exports.renderToFile = function renderToFile(
|
|
93415
|
+
exports.renderToFile = function renderToFile(path61, qrData, options, cb) {
|
|
93249
93416
|
if (typeof cb === "undefined") {
|
|
93250
93417
|
cb = options;
|
|
93251
93418
|
options = void 0;
|
|
93252
93419
|
}
|
|
93253
|
-
const
|
|
93420
|
+
const fs44 = __require("fs");
|
|
93254
93421
|
const utf8 = exports.render(qrData, options);
|
|
93255
|
-
|
|
93422
|
+
fs44.writeFile(path61, utf8, cb);
|
|
93256
93423
|
};
|
|
93257
93424
|
}
|
|
93258
93425
|
});
|
|
@@ -93373,7 +93540,7 @@ var require_svg_tag = __commonJS({
|
|
|
93373
93540
|
return str2;
|
|
93374
93541
|
}
|
|
93375
93542
|
function qrToPath(data, size, margin) {
|
|
93376
|
-
let
|
|
93543
|
+
let path61 = "";
|
|
93377
93544
|
let moveBy = 0;
|
|
93378
93545
|
let newRow = false;
|
|
93379
93546
|
let lineLength = 0;
|
|
@@ -93384,19 +93551,19 @@ var require_svg_tag = __commonJS({
|
|
|
93384
93551
|
if (data[i2]) {
|
|
93385
93552
|
lineLength++;
|
|
93386
93553
|
if (!(i2 > 0 && col > 0 && data[i2 - 1])) {
|
|
93387
|
-
|
|
93554
|
+
path61 += newRow ? svgCmd("M", col + margin, 0.5 + row + margin) : svgCmd("m", moveBy, 0);
|
|
93388
93555
|
moveBy = 0;
|
|
93389
93556
|
newRow = false;
|
|
93390
93557
|
}
|
|
93391
93558
|
if (!(col + 1 < size && data[i2 + 1])) {
|
|
93392
|
-
|
|
93559
|
+
path61 += svgCmd("h", lineLength);
|
|
93393
93560
|
lineLength = 0;
|
|
93394
93561
|
}
|
|
93395
93562
|
} else {
|
|
93396
93563
|
moveBy++;
|
|
93397
93564
|
}
|
|
93398
93565
|
}
|
|
93399
|
-
return
|
|
93566
|
+
return path61;
|
|
93400
93567
|
}
|
|
93401
93568
|
exports.render = function render2(qrData, options, cb) {
|
|
93402
93569
|
const opts = Utils.getOptions(options);
|
|
@@ -93404,10 +93571,10 @@ var require_svg_tag = __commonJS({
|
|
|
93404
93571
|
const data = qrData.modules.data;
|
|
93405
93572
|
const qrcodesize = size + opts.margin * 2;
|
|
93406
93573
|
const bg = !opts.color.light.a ? "" : "<path " + getColorAttrib(opts.color.light, "fill") + ' d="M0 0h' + qrcodesize + "v" + qrcodesize + 'H0z"/>';
|
|
93407
|
-
const
|
|
93574
|
+
const path61 = "<path " + getColorAttrib(opts.color.dark, "stroke") + ' d="' + qrToPath(data, size, opts.margin) + '"/>';
|
|
93408
93575
|
const viewBox = 'viewBox="0 0 ' + qrcodesize + " " + qrcodesize + '"';
|
|
93409
93576
|
const width = !opts.width ? "" : 'width="' + opts.width + '" height="' + opts.width + '" ';
|
|
93410
|
-
const svgTag = '<svg xmlns="http://www.w3.org/2000/svg" ' + width + viewBox + ' shape-rendering="crispEdges">' + bg +
|
|
93577
|
+
const svgTag = '<svg xmlns="http://www.w3.org/2000/svg" ' + width + viewBox + ' shape-rendering="crispEdges">' + bg + path61 + "</svg>\n";
|
|
93411
93578
|
if (typeof cb === "function") {
|
|
93412
93579
|
cb(null, svgTag);
|
|
93413
93580
|
}
|
|
@@ -93421,15 +93588,15 @@ var require_svg = __commonJS({
|
|
|
93421
93588
|
"../../node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/svg.js"(exports) {
|
|
93422
93589
|
var svgTagRenderer = require_svg_tag();
|
|
93423
93590
|
exports.render = svgTagRenderer.render;
|
|
93424
|
-
exports.renderToFile = function renderToFile(
|
|
93591
|
+
exports.renderToFile = function renderToFile(path61, qrData, options, cb) {
|
|
93425
93592
|
if (typeof cb === "undefined") {
|
|
93426
93593
|
cb = options;
|
|
93427
93594
|
options = void 0;
|
|
93428
93595
|
}
|
|
93429
|
-
const
|
|
93596
|
+
const fs44 = __require("fs");
|
|
93430
93597
|
const svgTag = exports.render(qrData, options);
|
|
93431
93598
|
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;
|
|
93432
|
-
|
|
93599
|
+
fs44.writeFile(path61, xmlStr, cb);
|
|
93433
93600
|
};
|
|
93434
93601
|
}
|
|
93435
93602
|
});
|
|
@@ -93587,8 +93754,8 @@ var require_server = __commonJS({
|
|
|
93587
93754
|
cb
|
|
93588
93755
|
};
|
|
93589
93756
|
}
|
|
93590
|
-
function getTypeFromFilename(
|
|
93591
|
-
return
|
|
93757
|
+
function getTypeFromFilename(path61) {
|
|
93758
|
+
return path61.slice((path61.lastIndexOf(".") - 1 >>> 0) + 2).toLowerCase();
|
|
93592
93759
|
}
|
|
93593
93760
|
function getRendererFromType(type) {
|
|
93594
93761
|
switch (type) {
|
|
@@ -93652,17 +93819,17 @@ var require_server = __commonJS({
|
|
|
93652
93819
|
const renderer2 = getRendererFromType(params.opts.type);
|
|
93653
93820
|
return render2(renderer2.renderToBuffer, text, params);
|
|
93654
93821
|
};
|
|
93655
|
-
exports.toFile = function toFile3(
|
|
93656
|
-
if (typeof
|
|
93822
|
+
exports.toFile = function toFile3(path61, text, opts, cb) {
|
|
93823
|
+
if (typeof path61 !== "string" || !(typeof text === "string" || typeof text === "object")) {
|
|
93657
93824
|
throw new Error("Invalid argument");
|
|
93658
93825
|
}
|
|
93659
93826
|
if (arguments.length < 3 && !canPromise()) {
|
|
93660
93827
|
throw new Error("Too few arguments provided");
|
|
93661
93828
|
}
|
|
93662
93829
|
const params = checkParams(text, opts, cb);
|
|
93663
|
-
const type = params.opts.type || getTypeFromFilename(
|
|
93830
|
+
const type = params.opts.type || getTypeFromFilename(path61);
|
|
93664
93831
|
const renderer2 = getRendererFromType(type);
|
|
93665
|
-
const renderToFile = renderer2.renderToFile.bind(null,
|
|
93832
|
+
const renderToFile = renderer2.renderToFile.bind(null, path61);
|
|
93666
93833
|
return render2(renderToFile, text, params);
|
|
93667
93834
|
};
|
|
93668
93835
|
exports.toFileStream = function toFileStream(stream, text, opts) {
|
|
@@ -94482,14 +94649,14 @@ var require_util2 = __commonJS({
|
|
|
94482
94649
|
}
|
|
94483
94650
|
const port = url2.port != null ? url2.port : url2.protocol === "https:" ? 443 : 80;
|
|
94484
94651
|
let origin = url2.origin != null ? url2.origin : `${url2.protocol || ""}//${url2.hostname || ""}:${port}`;
|
|
94485
|
-
let
|
|
94652
|
+
let path61 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`;
|
|
94486
94653
|
if (origin[origin.length - 1] === "/") {
|
|
94487
94654
|
origin = origin.slice(0, origin.length - 1);
|
|
94488
94655
|
}
|
|
94489
|
-
if (
|
|
94490
|
-
|
|
94656
|
+
if (path61 && path61[0] !== "/") {
|
|
94657
|
+
path61 = `/${path61}`;
|
|
94491
94658
|
}
|
|
94492
|
-
return new URL(`${origin}${
|
|
94659
|
+
return new URL(`${origin}${path61}`);
|
|
94493
94660
|
}
|
|
94494
94661
|
if (!isHttpOrHttpsPrefixed(url2.origin || url2.protocol)) {
|
|
94495
94662
|
throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
|
|
@@ -94939,39 +95106,39 @@ var require_diagnostics = __commonJS({
|
|
|
94939
95106
|
});
|
|
94940
95107
|
diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => {
|
|
94941
95108
|
const {
|
|
94942
|
-
request: { method, path:
|
|
95109
|
+
request: { method, path: path61, origin }
|
|
94943
95110
|
} = evt;
|
|
94944
|
-
debuglog("sending request to %s %s/%s", method, origin,
|
|
95111
|
+
debuglog("sending request to %s %s/%s", method, origin, path61);
|
|
94945
95112
|
});
|
|
94946
95113
|
diagnosticsChannel.channel("undici:request:headers").subscribe((evt) => {
|
|
94947
95114
|
const {
|
|
94948
|
-
request: { method, path:
|
|
95115
|
+
request: { method, path: path61, origin },
|
|
94949
95116
|
response: { statusCode }
|
|
94950
95117
|
} = evt;
|
|
94951
95118
|
debuglog(
|
|
94952
95119
|
"received response to %s %s/%s - HTTP %d",
|
|
94953
95120
|
method,
|
|
94954
95121
|
origin,
|
|
94955
|
-
|
|
95122
|
+
path61,
|
|
94956
95123
|
statusCode
|
|
94957
95124
|
);
|
|
94958
95125
|
});
|
|
94959
95126
|
diagnosticsChannel.channel("undici:request:trailers").subscribe((evt) => {
|
|
94960
95127
|
const {
|
|
94961
|
-
request: { method, path:
|
|
95128
|
+
request: { method, path: path61, origin }
|
|
94962
95129
|
} = evt;
|
|
94963
|
-
debuglog("trailers received from %s %s/%s", method, origin,
|
|
95130
|
+
debuglog("trailers received from %s %s/%s", method, origin, path61);
|
|
94964
95131
|
});
|
|
94965
95132
|
diagnosticsChannel.channel("undici:request:error").subscribe((evt) => {
|
|
94966
95133
|
const {
|
|
94967
|
-
request: { method, path:
|
|
95134
|
+
request: { method, path: path61, origin },
|
|
94968
95135
|
error: error2
|
|
94969
95136
|
} = evt;
|
|
94970
95137
|
debuglog(
|
|
94971
95138
|
"request to %s %s/%s errored - %s",
|
|
94972
95139
|
method,
|
|
94973
95140
|
origin,
|
|
94974
|
-
|
|
95141
|
+
path61,
|
|
94975
95142
|
error2.message
|
|
94976
95143
|
);
|
|
94977
95144
|
});
|
|
@@ -95020,9 +95187,9 @@ var require_diagnostics = __commonJS({
|
|
|
95020
95187
|
});
|
|
95021
95188
|
diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => {
|
|
95022
95189
|
const {
|
|
95023
|
-
request: { method, path:
|
|
95190
|
+
request: { method, path: path61, origin }
|
|
95024
95191
|
} = evt;
|
|
95025
|
-
debuglog("sending request to %s %s/%s", method, origin,
|
|
95192
|
+
debuglog("sending request to %s %s/%s", method, origin, path61);
|
|
95026
95193
|
});
|
|
95027
95194
|
}
|
|
95028
95195
|
diagnosticsChannel.channel("undici:websocket:open").subscribe((evt) => {
|
|
@@ -95084,7 +95251,7 @@ var require_request = __commonJS({
|
|
|
95084
95251
|
var kHandler = /* @__PURE__ */ Symbol("handler");
|
|
95085
95252
|
var Request4 = class {
|
|
95086
95253
|
constructor(origin, {
|
|
95087
|
-
path:
|
|
95254
|
+
path: path61,
|
|
95088
95255
|
method,
|
|
95089
95256
|
body,
|
|
95090
95257
|
headers,
|
|
@@ -95099,11 +95266,11 @@ var require_request = __commonJS({
|
|
|
95099
95266
|
expectContinue,
|
|
95100
95267
|
servername
|
|
95101
95268
|
}, handler) {
|
|
95102
|
-
if (typeof
|
|
95269
|
+
if (typeof path61 !== "string") {
|
|
95103
95270
|
throw new InvalidArgumentError("path must be a string");
|
|
95104
|
-
} else if (
|
|
95271
|
+
} else if (path61[0] !== "/" && !(path61.startsWith("http://") || path61.startsWith("https://")) && method !== "CONNECT") {
|
|
95105
95272
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
95106
|
-
} else if (invalidPathRegex.test(
|
|
95273
|
+
} else if (invalidPathRegex.test(path61)) {
|
|
95107
95274
|
throw new InvalidArgumentError("invalid request path");
|
|
95108
95275
|
}
|
|
95109
95276
|
if (typeof method !== "string") {
|
|
@@ -95169,7 +95336,7 @@ var require_request = __commonJS({
|
|
|
95169
95336
|
this.completed = false;
|
|
95170
95337
|
this.aborted = false;
|
|
95171
95338
|
this.upgrade = upgrade || null;
|
|
95172
|
-
this.path = query ? buildURL(
|
|
95339
|
+
this.path = query ? buildURL(path61, query) : path61;
|
|
95173
95340
|
this.origin = origin;
|
|
95174
95341
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
|
|
95175
95342
|
this.blocking = blocking == null ? false : blocking;
|
|
@@ -99707,7 +99874,7 @@ var require_client_h1 = __commonJS({
|
|
|
99707
99874
|
return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT";
|
|
99708
99875
|
}
|
|
99709
99876
|
function writeH1(client, request) {
|
|
99710
|
-
const { method, path:
|
|
99877
|
+
const { method, path: path61, host, upgrade, blocking, reset } = request;
|
|
99711
99878
|
let { body, headers, contentLength } = request;
|
|
99712
99879
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
|
|
99713
99880
|
if (util.isFormDataLike(body)) {
|
|
@@ -99773,7 +99940,7 @@ var require_client_h1 = __commonJS({
|
|
|
99773
99940
|
if (blocking) {
|
|
99774
99941
|
socket[kBlocking] = true;
|
|
99775
99942
|
}
|
|
99776
|
-
let header = `${method} ${
|
|
99943
|
+
let header = `${method} ${path61} HTTP/1.1\r
|
|
99777
99944
|
`;
|
|
99778
99945
|
if (typeof host === "string") {
|
|
99779
99946
|
header += `host: ${host}\r
|
|
@@ -100298,7 +100465,7 @@ var require_client_h2 = __commonJS({
|
|
|
100298
100465
|
}
|
|
100299
100466
|
function writeH2(client, request) {
|
|
100300
100467
|
const session = client[kHTTP2Session];
|
|
100301
|
-
const { method, path:
|
|
100468
|
+
const { method, path: path61, host, upgrade, expectContinue, signal, headers: reqHeaders } = request;
|
|
100302
100469
|
let { body } = request;
|
|
100303
100470
|
if (upgrade) {
|
|
100304
100471
|
util.errorRequest(client, request, new Error("Upgrade not supported for H2"));
|
|
@@ -100365,7 +100532,7 @@ var require_client_h2 = __commonJS({
|
|
|
100365
100532
|
});
|
|
100366
100533
|
return true;
|
|
100367
100534
|
}
|
|
100368
|
-
headers[HTTP2_HEADER_PATH] =
|
|
100535
|
+
headers[HTTP2_HEADER_PATH] = path61;
|
|
100369
100536
|
headers[HTTP2_HEADER_SCHEME] = "https";
|
|
100370
100537
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
100371
100538
|
if (body && typeof body.read === "function") {
|
|
@@ -100717,9 +100884,9 @@ var require_redirect_handler = __commonJS({
|
|
|
100717
100884
|
return this.handler.onHeaders(statusCode, headers, resume, statusText);
|
|
100718
100885
|
}
|
|
100719
100886
|
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
|
|
100720
|
-
const
|
|
100887
|
+
const path61 = search ? `${pathname}${search}` : pathname;
|
|
100721
100888
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
|
|
100722
|
-
this.opts.path =
|
|
100889
|
+
this.opts.path = path61;
|
|
100723
100890
|
this.opts.origin = origin;
|
|
100724
100891
|
this.opts.maxRedirections = 0;
|
|
100725
100892
|
this.opts.query = null;
|
|
@@ -101944,10 +102111,10 @@ var require_proxy_agent = __commonJS({
|
|
|
101944
102111
|
};
|
|
101945
102112
|
const {
|
|
101946
102113
|
origin,
|
|
101947
|
-
path:
|
|
102114
|
+
path: path61 = "/",
|
|
101948
102115
|
headers = {}
|
|
101949
102116
|
} = opts;
|
|
101950
|
-
opts.path = origin +
|
|
102117
|
+
opts.path = origin + path61;
|
|
101951
102118
|
if (!("host" in headers) && !("Host" in headers)) {
|
|
101952
102119
|
const { host } = new URL3(origin);
|
|
101953
102120
|
headers.host = host;
|
|
@@ -103855,20 +104022,20 @@ var require_mock_utils = __commonJS({
|
|
|
103855
104022
|
}
|
|
103856
104023
|
return true;
|
|
103857
104024
|
}
|
|
103858
|
-
function safeUrl(
|
|
103859
|
-
if (typeof
|
|
103860
|
-
return
|
|
104025
|
+
function safeUrl(path61) {
|
|
104026
|
+
if (typeof path61 !== "string") {
|
|
104027
|
+
return path61;
|
|
103861
104028
|
}
|
|
103862
|
-
const pathSegments =
|
|
104029
|
+
const pathSegments = path61.split("?");
|
|
103863
104030
|
if (pathSegments.length !== 2) {
|
|
103864
|
-
return
|
|
104031
|
+
return path61;
|
|
103865
104032
|
}
|
|
103866
104033
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
103867
104034
|
qp.sort();
|
|
103868
104035
|
return [...pathSegments, qp.toString()].join("?");
|
|
103869
104036
|
}
|
|
103870
|
-
function matchKey(mockDispatch2, { path:
|
|
103871
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
104037
|
+
function matchKey(mockDispatch2, { path: path61, method, body, headers }) {
|
|
104038
|
+
const pathMatch = matchValue(mockDispatch2.path, path61);
|
|
103872
104039
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
103873
104040
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
103874
104041
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -103890,7 +104057,7 @@ var require_mock_utils = __commonJS({
|
|
|
103890
104057
|
function getMockDispatch(mockDispatches, key) {
|
|
103891
104058
|
const basePath = key.query ? buildURL(key.path, key.query) : key.path;
|
|
103892
104059
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
103893
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
104060
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path61 }) => matchValue(safeUrl(path61), resolvedPath));
|
|
103894
104061
|
if (matchedMockDispatches.length === 0) {
|
|
103895
104062
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
103896
104063
|
}
|
|
@@ -103928,9 +104095,9 @@ var require_mock_utils = __commonJS({
|
|
|
103928
104095
|
}
|
|
103929
104096
|
}
|
|
103930
104097
|
function buildKey(opts) {
|
|
103931
|
-
const { path:
|
|
104098
|
+
const { path: path61, method, body, headers, query } = opts;
|
|
103932
104099
|
return {
|
|
103933
|
-
path:
|
|
104100
|
+
path: path61,
|
|
103934
104101
|
method,
|
|
103935
104102
|
body,
|
|
103936
104103
|
headers,
|
|
@@ -104388,10 +104555,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
104388
104555
|
}
|
|
104389
104556
|
format(pendingInterceptors) {
|
|
104390
104557
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
104391
|
-
({ method, path:
|
|
104558
|
+
({ method, path: path61, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
|
104392
104559
|
Method: method,
|
|
104393
104560
|
Origin: origin,
|
|
104394
|
-
Path:
|
|
104561
|
+
Path: path61,
|
|
104395
104562
|
"Status code": statusCode,
|
|
104396
104563
|
Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
|
|
104397
104564
|
Invocations: timesInvoked,
|
|
@@ -109230,9 +109397,9 @@ var require_util7 = __commonJS({
|
|
|
109230
109397
|
}
|
|
109231
109398
|
}
|
|
109232
109399
|
}
|
|
109233
|
-
function validateCookiePath(
|
|
109234
|
-
for (let i2 = 0; i2 <
|
|
109235
|
-
const code =
|
|
109400
|
+
function validateCookiePath(path61) {
|
|
109401
|
+
for (let i2 = 0; i2 < path61.length; ++i2) {
|
|
109402
|
+
const code = path61.charCodeAt(i2);
|
|
109236
109403
|
if (code < 32 || // exclude CTLs (0-31)
|
|
109237
109404
|
code === 127 || // DEL
|
|
109238
109405
|
code === 59) {
|
|
@@ -111892,11 +112059,11 @@ var require_undici = __commonJS({
|
|
|
111892
112059
|
if (typeof opts.path !== "string") {
|
|
111893
112060
|
throw new InvalidArgumentError("invalid opts.path");
|
|
111894
112061
|
}
|
|
111895
|
-
let
|
|
112062
|
+
let path61 = opts.path;
|
|
111896
112063
|
if (!opts.path.startsWith("/")) {
|
|
111897
|
-
|
|
112064
|
+
path61 = `/${path61}`;
|
|
111898
112065
|
}
|
|
111899
|
-
url2 = new URL(util.parseOrigin(url2).origin +
|
|
112066
|
+
url2 = new URL(util.parseOrigin(url2).origin + path61);
|
|
111900
112067
|
} else {
|
|
111901
112068
|
if (!opts) {
|
|
111902
112069
|
opts = typeof url2 === "object" ? url2 : {};
|
|
@@ -113793,7 +113960,12 @@ var VaultStore = class {
|
|
|
113793
113960
|
}
|
|
113794
113961
|
const parsed = JSON.parse(raw);
|
|
113795
113962
|
if (parsed.version !== 1 || parsed.kdf !== "scrypt") {
|
|
113796
|
-
throw new
|
|
113963
|
+
throw new MoxxyError({
|
|
113964
|
+
code: "VAULT_CORRUPT",
|
|
113965
|
+
message: `Unsupported vault file: version=${parsed.version} kdf=${parsed.kdf}`,
|
|
113966
|
+
hint: `This vault was written by an incompatible version. Back up and remove ${this.filePath} to re-initialize.`,
|
|
113967
|
+
context: { filePath: this.filePath }
|
|
113968
|
+
});
|
|
113797
113969
|
}
|
|
113798
113970
|
this.file = parsed;
|
|
113799
113971
|
const salt = Buffer.from(parsed.salt, "base64");
|
|
@@ -113977,8 +114149,6 @@ function firstEntry(entries) {
|
|
|
113977
114149
|
}
|
|
113978
114150
|
return void 0;
|
|
113979
114151
|
}
|
|
113980
|
-
|
|
113981
|
-
// ../plugin-vault/dist/placeholder.js
|
|
113982
114152
|
var PLACEHOLDER_RE = /\$\{vault:([A-Za-z0-9_.-]+)\}/g;
|
|
113983
114153
|
async function resolveString(input, vault) {
|
|
113984
114154
|
PLACEHOLDER_RE.lastIndex = 0;
|
|
@@ -113992,8 +114162,14 @@ async function resolveString(input, vault) {
|
|
|
113992
114162
|
const values = /* @__PURE__ */ new Map();
|
|
113993
114163
|
for (const name of names) {
|
|
113994
114164
|
const value = await vault.get(name);
|
|
113995
|
-
if (value === null)
|
|
113996
|
-
throw new
|
|
114165
|
+
if (value === null) {
|
|
114166
|
+
throw new MoxxyError({
|
|
114167
|
+
code: "CONFIG_INVALID",
|
|
114168
|
+
message: `vault: missing required entry '${name}' referenced in config`,
|
|
114169
|
+
hint: `Add it with \`/vault set ${name} <value>\` (or the \`vault_set\` tool), then retry.`,
|
|
114170
|
+
context: { name }
|
|
114171
|
+
});
|
|
114172
|
+
}
|
|
113997
114173
|
values.set(name, value);
|
|
113998
114174
|
}
|
|
113999
114175
|
return input.replace(PLACEHOLDER_RE, (_match, name) => values.get(name) ?? "");
|
|
@@ -114118,8 +114294,14 @@ ${vaultCommandUsage()}` };
|
|
|
114118
114294
|
permission: { action: "prompt" },
|
|
114119
114295
|
handler: async ({ name }) => {
|
|
114120
114296
|
const value = await vault.get(name);
|
|
114121
|
-
if (value === null)
|
|
114122
|
-
throw new
|
|
114297
|
+
if (value === null) {
|
|
114298
|
+
throw new MoxxyError({
|
|
114299
|
+
code: "TOOL_ERROR",
|
|
114300
|
+
message: `vault: '${name}' not found`,
|
|
114301
|
+
hint: "Use `vault_list` to see stored entry names.",
|
|
114302
|
+
context: { name }
|
|
114303
|
+
});
|
|
114304
|
+
}
|
|
114123
114305
|
return value;
|
|
114124
114306
|
}
|
|
114125
114307
|
}),
|
|
@@ -115826,13 +116008,13 @@ var MultipartBody = class {
|
|
|
115826
116008
|
}
|
|
115827
116009
|
};
|
|
115828
116010
|
var fileFromPathWarned = false;
|
|
115829
|
-
async function fileFromPath3(
|
|
116011
|
+
async function fileFromPath3(path61, ...args) {
|
|
115830
116012
|
const { fileFromPath: _fileFromPath } = await Promise.resolve().then(() => (init_fileFromPath(), fileFromPath_exports));
|
|
115831
116013
|
if (!fileFromPathWarned) {
|
|
115832
|
-
console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(
|
|
116014
|
+
console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path61)}) instead`);
|
|
115833
116015
|
fileFromPathWarned = true;
|
|
115834
116016
|
}
|
|
115835
|
-
return await _fileFromPath(
|
|
116017
|
+
return await _fileFromPath(path61, ...args);
|
|
115836
116018
|
}
|
|
115837
116019
|
var defaultHttpAgent = new import_agentkeepalive.default({ keepAlive: true, timeout: 5 * 60 * 1e3 });
|
|
115838
116020
|
var defaultHttpsAgent = new import_agentkeepalive.default.HttpsAgent({ keepAlive: true, timeout: 5 * 60 * 1e3 });
|
|
@@ -116555,29 +116737,29 @@ var APIClient = class {
|
|
|
116555
116737
|
defaultIdempotencyKey() {
|
|
116556
116738
|
return `stainless-node-retry-${uuid4()}`;
|
|
116557
116739
|
}
|
|
116558
|
-
get(
|
|
116559
|
-
return this.methodRequest("get",
|
|
116740
|
+
get(path61, opts) {
|
|
116741
|
+
return this.methodRequest("get", path61, opts);
|
|
116560
116742
|
}
|
|
116561
|
-
post(
|
|
116562
|
-
return this.methodRequest("post",
|
|
116743
|
+
post(path61, opts) {
|
|
116744
|
+
return this.methodRequest("post", path61, opts);
|
|
116563
116745
|
}
|
|
116564
|
-
patch(
|
|
116565
|
-
return this.methodRequest("patch",
|
|
116746
|
+
patch(path61, opts) {
|
|
116747
|
+
return this.methodRequest("patch", path61, opts);
|
|
116566
116748
|
}
|
|
116567
|
-
put(
|
|
116568
|
-
return this.methodRequest("put",
|
|
116749
|
+
put(path61, opts) {
|
|
116750
|
+
return this.methodRequest("put", path61, opts);
|
|
116569
116751
|
}
|
|
116570
|
-
delete(
|
|
116571
|
-
return this.methodRequest("delete",
|
|
116752
|
+
delete(path61, opts) {
|
|
116753
|
+
return this.methodRequest("delete", path61, opts);
|
|
116572
116754
|
}
|
|
116573
|
-
methodRequest(method,
|
|
116755
|
+
methodRequest(method, path61, opts) {
|
|
116574
116756
|
return this.request(Promise.resolve(opts).then(async (opts2) => {
|
|
116575
116757
|
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;
|
|
116576
|
-
return { method, path:
|
|
116758
|
+
return { method, path: path61, ...opts2, body };
|
|
116577
116759
|
}));
|
|
116578
116760
|
}
|
|
116579
|
-
getAPIList(
|
|
116580
|
-
return this.requestAPIList(Page3, { method: "get", path:
|
|
116761
|
+
getAPIList(path61, Page3, opts) {
|
|
116762
|
+
return this.requestAPIList(Page3, { method: "get", path: path61, ...opts });
|
|
116581
116763
|
}
|
|
116582
116764
|
calculateContentLength(body) {
|
|
116583
116765
|
if (typeof body === "string") {
|
|
@@ -116596,10 +116778,10 @@ var APIClient = class {
|
|
|
116596
116778
|
}
|
|
116597
116779
|
buildRequest(inputOptions, { retryCount = 0 } = {}) {
|
|
116598
116780
|
const options = { ...inputOptions };
|
|
116599
|
-
const { method, path:
|
|
116781
|
+
const { method, path: path61, query, headers = {} } = options;
|
|
116600
116782
|
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;
|
|
116601
116783
|
const contentLength = this.calculateContentLength(body);
|
|
116602
|
-
const url2 = this.buildURL(
|
|
116784
|
+
const url2 = this.buildURL(path61, query);
|
|
116603
116785
|
if ("timeout" in options)
|
|
116604
116786
|
validatePositiveInteger("timeout", options.timeout);
|
|
116605
116787
|
options.timeout = options.timeout ?? this.timeout;
|
|
@@ -116723,8 +116905,8 @@ var APIClient = class {
|
|
|
116723
116905
|
const request = this.makeRequest(options, null);
|
|
116724
116906
|
return new PagePromise(this, request, Page3);
|
|
116725
116907
|
}
|
|
116726
|
-
buildURL(
|
|
116727
|
-
const url2 = isAbsoluteURL(
|
|
116908
|
+
buildURL(path61, query) {
|
|
116909
|
+
const url2 = isAbsoluteURL(path61) ? new URL(path61) : new URL(this.baseURL + (this.baseURL.endsWith("/") && path61.startsWith("/") ? path61.slice(1) : path61));
|
|
116728
116910
|
const defaultQuery = this.defaultQuery();
|
|
116729
116911
|
if (!isEmptyObj(defaultQuery)) {
|
|
116730
116912
|
query = { ...defaultQuery, ...query };
|
|
@@ -119135,9 +119317,9 @@ function toAnthropicTools(tools, opts = {}) {
|
|
|
119135
119317
|
|
|
119136
119318
|
// ../plugin-provider-anthropic/dist/provider.js
|
|
119137
119319
|
var anthropicModels = [
|
|
119138
|
-
{ id: "claude-opus-4-7", contextWindow:
|
|
119139
|
-
{ id: "claude-sonnet-4-6", contextWindow:
|
|
119140
|
-
{ id: "claude-haiku-4-5-20251001", contextWindow: 2e5, maxOutputTokens:
|
|
119320
|
+
{ id: "claude-opus-4-7", contextWindow: 1e6, maxOutputTokens: 128e3, supportsTools: true, supportsStreaming: true, supportsImages: true, supportsDocuments: true },
|
|
119321
|
+
{ id: "claude-sonnet-4-6", contextWindow: 1e6, maxOutputTokens: 64e3, supportsTools: true, supportsStreaming: true, supportsImages: true, supportsDocuments: true },
|
|
119322
|
+
{ id: "claude-haiku-4-5-20251001", contextWindow: 2e5, maxOutputTokens: 64e3, supportsTools: true, supportsStreaming: true, supportsImages: true, supportsDocuments: true }
|
|
119141
119323
|
];
|
|
119142
119324
|
var AnthropicProvider = class {
|
|
119143
119325
|
name;
|
|
@@ -119396,9 +119578,13 @@ var AnthropicProvider = class {
|
|
|
119396
119578
|
try {
|
|
119397
119579
|
const result = await this.client.messages.countTokens({
|
|
119398
119580
|
model: req.model || this.defaultModel,
|
|
119399
|
-
system: systemForCount,
|
|
119581
|
+
...systemForCount !== void 0 ? { system: systemForCount } : {},
|
|
119582
|
+
// NARROW cast: our hand-rolled message/tool shapes carry `media_type:
|
|
119583
|
+
// string`, which the SDK narrows to a literal union it can't see we
|
|
119584
|
+
// never violate. The method itself is fully typed (no `as unknown` on
|
|
119585
|
+
// the resource anymore); only these two args need the structural cast.
|
|
119400
119586
|
messages,
|
|
119401
|
-
tools
|
|
119587
|
+
...tools !== void 0 ? { tools } : {}
|
|
119402
119588
|
});
|
|
119403
119589
|
return result.input_tokens;
|
|
119404
119590
|
} catch {
|
|
@@ -119883,13 +120069,13 @@ var MultipartBody2 = class {
|
|
|
119883
120069
|
}
|
|
119884
120070
|
};
|
|
119885
120071
|
var fileFromPathWarned2 = false;
|
|
119886
|
-
async function fileFromPath5(
|
|
120072
|
+
async function fileFromPath5(path61, ...args) {
|
|
119887
120073
|
const { fileFromPath: _fileFromPath } = await Promise.resolve().then(() => (init_fileFromPath(), fileFromPath_exports));
|
|
119888
120074
|
if (!fileFromPathWarned2) {
|
|
119889
|
-
console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(
|
|
120075
|
+
console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path61)}) instead`);
|
|
119890
120076
|
fileFromPathWarned2 = true;
|
|
119891
120077
|
}
|
|
119892
|
-
return await _fileFromPath(
|
|
120078
|
+
return await _fileFromPath(path61, ...args);
|
|
119893
120079
|
}
|
|
119894
120080
|
var defaultHttpAgent2 = new import_agentkeepalive2.default({ keepAlive: true, timeout: 5 * 60 * 1e3 });
|
|
119895
120081
|
var defaultHttpsAgent2 = new import_agentkeepalive2.default.HttpsAgent({ keepAlive: true, timeout: 5 * 60 * 1e3 });
|
|
@@ -120667,29 +120853,29 @@ var APIClient2 = class {
|
|
|
120667
120853
|
defaultIdempotencyKey() {
|
|
120668
120854
|
return `stainless-node-retry-${uuid42()}`;
|
|
120669
120855
|
}
|
|
120670
|
-
get(
|
|
120671
|
-
return this.methodRequest("get",
|
|
120856
|
+
get(path61, opts) {
|
|
120857
|
+
return this.methodRequest("get", path61, opts);
|
|
120672
120858
|
}
|
|
120673
|
-
post(
|
|
120674
|
-
return this.methodRequest("post",
|
|
120859
|
+
post(path61, opts) {
|
|
120860
|
+
return this.methodRequest("post", path61, opts);
|
|
120675
120861
|
}
|
|
120676
|
-
patch(
|
|
120677
|
-
return this.methodRequest("patch",
|
|
120862
|
+
patch(path61, opts) {
|
|
120863
|
+
return this.methodRequest("patch", path61, opts);
|
|
120678
120864
|
}
|
|
120679
|
-
put(
|
|
120680
|
-
return this.methodRequest("put",
|
|
120865
|
+
put(path61, opts) {
|
|
120866
|
+
return this.methodRequest("put", path61, opts);
|
|
120681
120867
|
}
|
|
120682
|
-
delete(
|
|
120683
|
-
return this.methodRequest("delete",
|
|
120868
|
+
delete(path61, opts) {
|
|
120869
|
+
return this.methodRequest("delete", path61, opts);
|
|
120684
120870
|
}
|
|
120685
|
-
methodRequest(method,
|
|
120871
|
+
methodRequest(method, path61, opts) {
|
|
120686
120872
|
return this.request(Promise.resolve(opts).then(async (opts2) => {
|
|
120687
120873
|
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;
|
|
120688
|
-
return { method, path:
|
|
120874
|
+
return { method, path: path61, ...opts2, body };
|
|
120689
120875
|
}));
|
|
120690
120876
|
}
|
|
120691
|
-
getAPIList(
|
|
120692
|
-
return this.requestAPIList(Page3, { method: "get", path:
|
|
120877
|
+
getAPIList(path61, Page3, opts) {
|
|
120878
|
+
return this.requestAPIList(Page3, { method: "get", path: path61, ...opts });
|
|
120693
120879
|
}
|
|
120694
120880
|
calculateContentLength(body) {
|
|
120695
120881
|
if (typeof body === "string") {
|
|
@@ -120708,10 +120894,10 @@ var APIClient2 = class {
|
|
|
120708
120894
|
}
|
|
120709
120895
|
buildRequest(inputOptions, { retryCount = 0 } = {}) {
|
|
120710
120896
|
const options = { ...inputOptions };
|
|
120711
|
-
const { method, path:
|
|
120897
|
+
const { method, path: path61, query, headers = {} } = options;
|
|
120712
120898
|
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;
|
|
120713
120899
|
const contentLength = this.calculateContentLength(body);
|
|
120714
|
-
const url2 = this.buildURL(
|
|
120900
|
+
const url2 = this.buildURL(path61, query);
|
|
120715
120901
|
if ("timeout" in options)
|
|
120716
120902
|
validatePositiveInteger2("timeout", options.timeout);
|
|
120717
120903
|
options.timeout = options.timeout ?? this.timeout;
|
|
@@ -120827,8 +121013,8 @@ var APIClient2 = class {
|
|
|
120827
121013
|
const request = this.makeRequest(options, null);
|
|
120828
121014
|
return new PagePromise2(this, request, Page3);
|
|
120829
121015
|
}
|
|
120830
|
-
buildURL(
|
|
120831
|
-
const url2 = isAbsoluteURL2(
|
|
121016
|
+
buildURL(path61, query) {
|
|
121017
|
+
const url2 = isAbsoluteURL2(path61) ? new URL(path61) : new URL(this.baseURL + (this.baseURL.endsWith("/") && path61.startsWith("/") ? path61.slice(1) : path61));
|
|
120832
121018
|
const defaultQuery = this.defaultQuery();
|
|
120833
121019
|
if (!isEmptyObj2(defaultQuery)) {
|
|
120834
121020
|
query = { ...defaultQuery, ...query };
|
|
@@ -126216,11 +126402,11 @@ function buildAuthUrl(input) {
|
|
|
126216
126402
|
}
|
|
126217
126403
|
async function runAuthorizationCodeFlow(opts) {
|
|
126218
126404
|
const port = opts.redirectPort ?? 8765;
|
|
126219
|
-
const
|
|
126405
|
+
const path61 = opts.redirectPath ?? "/callback";
|
|
126220
126406
|
const codeVerifier = generateCodeVerifier();
|
|
126221
126407
|
const codeChallenge = computeCodeChallenge(codeVerifier);
|
|
126222
126408
|
const state = generateState();
|
|
126223
|
-
const redirectUri = `http://localhost:${port}${
|
|
126409
|
+
const redirectUri = `http://localhost:${port}${path61}`;
|
|
126224
126410
|
const authUrl = buildAuthUrl({
|
|
126225
126411
|
authUrl: opts.authUrl,
|
|
126226
126412
|
clientId: opts.clientId,
|
|
@@ -126232,7 +126418,7 @@ async function runAuthorizationCodeFlow(opts) {
|
|
|
126232
126418
|
});
|
|
126233
126419
|
const codePromise = waitForCallback({
|
|
126234
126420
|
port,
|
|
126235
|
-
path:
|
|
126421
|
+
path: path61,
|
|
126236
126422
|
expectedState: state,
|
|
126237
126423
|
timeoutMs: opts.timeoutMs ?? 3e5,
|
|
126238
126424
|
...opts.signal ? { signal: opts.signal } : {}
|
|
@@ -126546,7 +126732,10 @@ function buildOauthAuthorizeTool(deps) {
|
|
|
126546
126732
|
let tokens;
|
|
126547
126733
|
if (mode === "device") {
|
|
126548
126734
|
if (!input.deviceUrl) {
|
|
126549
|
-
throw new
|
|
126735
|
+
throw new MoxxyError({
|
|
126736
|
+
code: "TOOL_ERROR",
|
|
126737
|
+
message: 'mode="device" requires `deviceUrl` (the provider\'s device-authorization endpoint)'
|
|
126738
|
+
});
|
|
126550
126739
|
}
|
|
126551
126740
|
tokens = await runDeviceCodeFlow({
|
|
126552
126741
|
deviceUrl: input.deviceUrl,
|
|
@@ -126572,7 +126761,10 @@ function buildOauthAuthorizeTool(deps) {
|
|
|
126572
126761
|
});
|
|
126573
126762
|
} else {
|
|
126574
126763
|
if (!input.authUrl) {
|
|
126575
|
-
throw new
|
|
126764
|
+
throw new MoxxyError({
|
|
126765
|
+
code: "TOOL_ERROR",
|
|
126766
|
+
message: 'mode="loopback" requires `authUrl` (the provider\'s authorization endpoint)'
|
|
126767
|
+
});
|
|
126576
126768
|
}
|
|
126577
126769
|
if (input.noOpen) {
|
|
126578
126770
|
const verifier = generateCodeVerifier();
|
|
@@ -126580,11 +126772,11 @@ function buildOauthAuthorizeTool(deps) {
|
|
|
126580
126772
|
const { computeCodeChallenge: computeCodeChallenge2 } = await Promise.resolve().then(() => (init_pkce(), pkce_exports));
|
|
126581
126773
|
const challenge = computeCodeChallenge2(verifier);
|
|
126582
126774
|
const port = input.redirectPort ?? 8765;
|
|
126583
|
-
const
|
|
126775
|
+
const path61 = input.redirectPath ?? "/callback";
|
|
126584
126776
|
const url2 = buildAuthUrl({
|
|
126585
126777
|
authUrl: input.authUrl,
|
|
126586
126778
|
clientId: input.clientId,
|
|
126587
|
-
redirectUri: `http://localhost:${port}${
|
|
126779
|
+
redirectUri: `http://localhost:${port}${path61}`,
|
|
126588
126780
|
scopes: input.scopes,
|
|
126589
126781
|
codeChallenge: challenge,
|
|
126590
126782
|
state,
|
|
@@ -126726,7 +126918,7 @@ async function runOauthLogin(profile, ctx) {
|
|
|
126726
126918
|
}
|
|
126727
126919
|
async function runBrowserFlow(profile, ctx) {
|
|
126728
126920
|
const port = profile.redirect?.port ?? 8765;
|
|
126729
|
-
const
|
|
126921
|
+
const path61 = profile.redirect?.path ?? "/callback";
|
|
126730
126922
|
const serviceName = profile.displayName ?? profile.id;
|
|
126731
126923
|
return runAuthorizationCodeFlow({
|
|
126732
126924
|
authUrl: profile.authUrl,
|
|
@@ -126735,7 +126927,7 @@ async function runBrowserFlow(profile, ctx) {
|
|
|
126735
126927
|
...profile.clientSecret ? { clientSecret: profile.clientSecret } : {},
|
|
126736
126928
|
scopes: profile.scopes,
|
|
126737
126929
|
redirectPort: port,
|
|
126738
|
-
redirectPath:
|
|
126930
|
+
redirectPath: path61,
|
|
126739
126931
|
...profile.extraAuthParams ? { extraAuthParams: profile.extraAuthParams } : {},
|
|
126740
126932
|
timeoutMs: DEFAULT_BROWSER_TIMEOUT_MS,
|
|
126741
126933
|
...ctx.signal ? { signal: ctx.signal } : {},
|
|
@@ -126747,7 +126939,7 @@ If your browser doesn't open automatically, paste this URL:
|
|
|
126747
126939
|
|
|
126748
126940
|
${url2}
|
|
126749
126941
|
|
|
126750
|
-
Waiting for callback on http://localhost:${port}${
|
|
126942
|
+
Waiting for callback on http://localhost:${port}${path61} (5 min timeout)\u2026
|
|
126751
126943
|
|
|
126752
126944
|
`);
|
|
126753
126945
|
}
|
|
@@ -133523,11 +133715,11 @@ function isAddrInUse(err) {
|
|
|
133523
133715
|
return !!err && typeof err === "object" && err.code === "EADDRINUSE";
|
|
133524
133716
|
}
|
|
133525
133717
|
async function captureStdout(cmd, args) {
|
|
133526
|
-
const { spawn:
|
|
133718
|
+
const { spawn: spawn14 } = await import('child_process');
|
|
133527
133719
|
return await new Promise((resolve12) => {
|
|
133528
133720
|
let out = "";
|
|
133529
133721
|
try {
|
|
133530
|
-
const child =
|
|
133722
|
+
const child = spawn14(cmd, [...args], { stdio: ["ignore", "pipe", "ignore"] });
|
|
133531
133723
|
child.stdout.on("data", (b3) => {
|
|
133532
133724
|
out += b3.toString();
|
|
133533
133725
|
});
|
|
@@ -133903,161 +134095,30 @@ var WebChannel = class {
|
|
|
133903
134095
|
}
|
|
133904
134096
|
}
|
|
133905
134097
|
};
|
|
133906
|
-
|
|
133907
|
-
// ../plugin-channel-web/dist/child-cleanup.js
|
|
133908
|
-
var live = /* @__PURE__ */ new Set();
|
|
133909
|
-
var hooked = false;
|
|
133910
|
-
function killChild(child) {
|
|
133911
|
-
if (child.exitCode != null || child.signalCode != null)
|
|
133912
|
-
return;
|
|
133913
|
-
try {
|
|
133914
|
-
child.kill("SIGTERM");
|
|
133915
|
-
} catch {
|
|
133916
|
-
}
|
|
133917
|
-
const t2 = setTimeout(() => {
|
|
133918
|
-
try {
|
|
133919
|
-
child.kill("SIGKILL");
|
|
133920
|
-
} catch {
|
|
133921
|
-
}
|
|
133922
|
-
}, 2e3);
|
|
133923
|
-
t2.unref?.();
|
|
133924
|
-
child.once("exit", () => clearTimeout(t2));
|
|
133925
|
-
}
|
|
133926
|
-
function ensureHook() {
|
|
133927
|
-
if (hooked)
|
|
133928
|
-
return;
|
|
133929
|
-
hooked = true;
|
|
133930
|
-
const killAll = () => {
|
|
133931
|
-
for (const child of live) {
|
|
133932
|
-
try {
|
|
133933
|
-
child.kill("SIGKILL");
|
|
133934
|
-
} catch {
|
|
133935
|
-
}
|
|
133936
|
-
}
|
|
133937
|
-
live.clear();
|
|
133938
|
-
};
|
|
133939
|
-
process.once("exit", killAll);
|
|
133940
|
-
process.once("SIGINT", killAll);
|
|
133941
|
-
process.once("SIGTERM", killAll);
|
|
133942
|
-
}
|
|
133943
|
-
function trackChild(child) {
|
|
133944
|
-
ensureHook();
|
|
133945
|
-
live.add(child);
|
|
133946
|
-
child.once("exit", () => live.delete(child));
|
|
133947
|
-
return () => new Promise((resolve12) => {
|
|
133948
|
-
live.delete(child);
|
|
133949
|
-
if (child.exitCode != null || child.signalCode != null)
|
|
133950
|
-
return resolve12();
|
|
133951
|
-
child.once("exit", () => resolve12());
|
|
133952
|
-
killChild(child);
|
|
133953
|
-
});
|
|
133954
|
-
}
|
|
133955
|
-
|
|
133956
|
-
// ../plugin-channel-web/dist/cloudflared.js
|
|
133957
134098
|
var TRYCLOUDFLARE_RE = /https:\/\/[a-z0-9-]+\.trycloudflare\.com/i;
|
|
133958
134099
|
var URL_TIMEOUT_MS = 3e4;
|
|
133959
|
-
function parseTrycloudflareUrl(chunk) {
|
|
133960
|
-
return TRYCLOUDFLARE_RE.exec(chunk)?.[0] ?? null;
|
|
133961
|
-
}
|
|
133962
134100
|
var cloudflaredTunnel = defineTunnelProvider({
|
|
133963
134101
|
name: "cloudflared",
|
|
133964
|
-
isAvailable: () =>
|
|
133965
|
-
|
|
133966
|
-
|
|
133967
|
-
|
|
133968
|
-
|
|
133969
|
-
|
|
133970
|
-
|
|
133971
|
-
const untrack = trackChild(child);
|
|
133972
|
-
let settled = false;
|
|
133973
|
-
const timer = setTimeout(() => {
|
|
133974
|
-
if (settled)
|
|
133975
|
-
return;
|
|
133976
|
-
settled = true;
|
|
133977
|
-
void untrack();
|
|
133978
|
-
reject(new Error("cloudflared: timed out waiting for the tunnel URL"));
|
|
133979
|
-
}, URL_TIMEOUT_MS);
|
|
133980
|
-
timer.unref?.();
|
|
133981
|
-
const onData = (buf) => {
|
|
133982
|
-
if (settled)
|
|
133983
|
-
return;
|
|
133984
|
-
const url2 = parseTrycloudflareUrl(buf.toString("utf8"));
|
|
133985
|
-
if (!url2)
|
|
133986
|
-
return;
|
|
133987
|
-
settled = true;
|
|
133988
|
-
clearTimeout(timer);
|
|
133989
|
-
resolve12({ url: url2, close: untrack });
|
|
133990
|
-
};
|
|
133991
|
-
child.stderr?.on("data", onData);
|
|
133992
|
-
child.stdout?.on("data", onData);
|
|
133993
|
-
child.on("error", (err) => {
|
|
133994
|
-
if (settled)
|
|
133995
|
-
return;
|
|
133996
|
-
settled = true;
|
|
133997
|
-
clearTimeout(timer);
|
|
133998
|
-
void untrack();
|
|
133999
|
-
reject(err);
|
|
134000
|
-
});
|
|
134001
|
-
child.on("exit", (code) => {
|
|
134002
|
-
if (settled)
|
|
134003
|
-
return;
|
|
134004
|
-
settled = true;
|
|
134005
|
-
clearTimeout(timer);
|
|
134006
|
-
reject(new Error(`cloudflared exited (code ${code}) before emitting a URL`));
|
|
134007
|
-
});
|
|
134102
|
+
isAvailable: () => isCliTunnelAvailable("cloudflared"),
|
|
134103
|
+
open: ({ port, host }) => spawnCliTunnel({
|
|
134104
|
+
cmd: "cloudflared",
|
|
134105
|
+
args: ["tunnel", "--no-autoupdate", "--url", `http://${host}:${port}`],
|
|
134106
|
+
urlRegex: TRYCLOUDFLARE_RE,
|
|
134107
|
+
timeoutMs: URL_TIMEOUT_MS,
|
|
134108
|
+
name: "cloudflared"
|
|
134008
134109
|
})
|
|
134009
134110
|
});
|
|
134010
134111
|
var NGROK_URL_RE = /https:\/\/[a-z0-9-]+\.ngrok(?:-free)?\.(?:app|io|dev)/i;
|
|
134011
134112
|
var URL_TIMEOUT_MS2 = 3e4;
|
|
134012
|
-
function parseNgrokUrl(chunk) {
|
|
134013
|
-
return NGROK_URL_RE.exec(chunk)?.[0] ?? null;
|
|
134014
|
-
}
|
|
134015
134113
|
var ngrokTunnel = defineTunnelProvider({
|
|
134016
134114
|
name: "ngrok",
|
|
134017
|
-
isAvailable: () =>
|
|
134018
|
-
|
|
134019
|
-
|
|
134020
|
-
|
|
134021
|
-
|
|
134022
|
-
|
|
134023
|
-
|
|
134024
|
-
const untrack = trackChild(child);
|
|
134025
|
-
let settled = false;
|
|
134026
|
-
const timer = setTimeout(() => {
|
|
134027
|
-
if (settled)
|
|
134028
|
-
return;
|
|
134029
|
-
settled = true;
|
|
134030
|
-
void untrack();
|
|
134031
|
-
reject(new Error("ngrok: timed out waiting for the tunnel URL"));
|
|
134032
|
-
}, URL_TIMEOUT_MS2);
|
|
134033
|
-
timer.unref?.();
|
|
134034
|
-
const onData = (buf) => {
|
|
134035
|
-
if (settled)
|
|
134036
|
-
return;
|
|
134037
|
-
const url2 = parseNgrokUrl(buf.toString("utf8"));
|
|
134038
|
-
if (!url2)
|
|
134039
|
-
return;
|
|
134040
|
-
settled = true;
|
|
134041
|
-
clearTimeout(timer);
|
|
134042
|
-
resolve12({ url: url2, close: untrack });
|
|
134043
|
-
};
|
|
134044
|
-
child.stdout?.on("data", onData);
|
|
134045
|
-
child.stderr?.on("data", onData);
|
|
134046
|
-
child.on("error", (err) => {
|
|
134047
|
-
if (settled)
|
|
134048
|
-
return;
|
|
134049
|
-
settled = true;
|
|
134050
|
-
clearTimeout(timer);
|
|
134051
|
-
void untrack();
|
|
134052
|
-
reject(err);
|
|
134053
|
-
});
|
|
134054
|
-
child.on("exit", (code) => {
|
|
134055
|
-
if (settled)
|
|
134056
|
-
return;
|
|
134057
|
-
settled = true;
|
|
134058
|
-
clearTimeout(timer);
|
|
134059
|
-
reject(new Error(`ngrok exited (code ${code}) before emitting a URL`));
|
|
134060
|
-
});
|
|
134115
|
+
isAvailable: () => isCliTunnelAvailable("ngrok"),
|
|
134116
|
+
open: ({ port }) => spawnCliTunnel({
|
|
134117
|
+
cmd: "ngrok",
|
|
134118
|
+
args: ["http", String(port), "--log", "stdout", "--log-format", "json"],
|
|
134119
|
+
urlRegex: NGROK_URL_RE,
|
|
134120
|
+
timeoutMs: URL_TIMEOUT_MS2,
|
|
134121
|
+
name: "ngrok"
|
|
134061
134122
|
})
|
|
134062
134123
|
});
|
|
134063
134124
|
var webSettingsSchema = z$1.object({ tunnel: z$1.string().optional() });
|
|
@@ -134310,6 +134371,9 @@ async function createWebSocketTransportServer(opts) {
|
|
|
134310
134371
|
for (const client of wss.clients)
|
|
134311
134372
|
client.terminate();
|
|
134312
134373
|
},
|
|
134374
|
+
clientCount() {
|
|
134375
|
+
return connections;
|
|
134376
|
+
},
|
|
134313
134377
|
close() {
|
|
134314
134378
|
return new Promise((resolve12) => {
|
|
134315
134379
|
for (const client of wss.clients)
|
|
@@ -134640,7 +134704,8 @@ function isRunnerUp(socketPath = runnerSocketPath()) {
|
|
|
134640
134704
|
|
|
134641
134705
|
// ../runner/dist/server.js
|
|
134642
134706
|
init_dist();
|
|
134643
|
-
var RUNNER_PROTOCOL_VERSION =
|
|
134707
|
+
var RUNNER_PROTOCOL_VERSION = 5;
|
|
134708
|
+
var MIN_COMPATIBLE_PROTOCOL_VERSION = 1;
|
|
134644
134709
|
var RunnerMethod = {
|
|
134645
134710
|
/** client->server: handshake; returns the initial info snapshot. */
|
|
134646
134711
|
Attach: "attach",
|
|
@@ -134684,6 +134749,18 @@ var RunnerMethod = {
|
|
|
134684
134749
|
WorkflowSetEnabled: "workflow.setEnabled",
|
|
134685
134750
|
/** client->server: run a workflow now. */
|
|
134686
134751
|
WorkflowRun: "workflow.run",
|
|
134752
|
+
/** client->server: validate a draft workflow YAML (builder). */
|
|
134753
|
+
WorkflowValidateDraft: "workflow.validateDraft",
|
|
134754
|
+
/** client->server: persist a workflow from full YAML (builder). */
|
|
134755
|
+
WorkflowSave: "workflow.save",
|
|
134756
|
+
/** client->server: fetch one saved workflow as canonical YAML (builder). */
|
|
134757
|
+
WorkflowGetRun: "workflow.getRun",
|
|
134758
|
+
/**
|
|
134759
|
+
* client->server: answer a paused workflow's `awaitInput` question and resume
|
|
134760
|
+
* the run (human-in-the-loop). v5 — the client gates this on the server's
|
|
134761
|
+
* reported version so an older runner returns an actionable error.
|
|
134762
|
+
*/
|
|
134763
|
+
WorkflowResume: "workflow.resume",
|
|
134687
134764
|
/** server->client: ask this client to decide a tool-call permission. */
|
|
134688
134765
|
PermissionCheck: "permission.check",
|
|
134689
134766
|
/** server->client: ask this client to confirm an approval checkpoint. */
|
|
@@ -134760,6 +134837,18 @@ var workflowSetEnabledParamsSchema = z.object({
|
|
|
134760
134837
|
enabled: z.boolean()
|
|
134761
134838
|
});
|
|
134762
134839
|
var workflowRunParamsSchema = z.object({ name: z.string() });
|
|
134840
|
+
var workflowValidateDraftParamsSchema = z.object({
|
|
134841
|
+
yaml: z.string().min(1).max(1e6)
|
|
134842
|
+
});
|
|
134843
|
+
var workflowSaveParamsSchema = z.object({
|
|
134844
|
+
yaml: z.string().min(1).max(1e6),
|
|
134845
|
+
previousName: z.string().min(1).max(120).optional()
|
|
134846
|
+
});
|
|
134847
|
+
var workflowGetRunParamsSchema = z.object({ name: z.string().min(1).max(120) });
|
|
134848
|
+
var workflowResumeParamsSchema = z.object({
|
|
134849
|
+
runId: z.string().min(1).max(120),
|
|
134850
|
+
reply: z.string().min(1).max(1e5)
|
|
134851
|
+
});
|
|
134763
134852
|
|
|
134764
134853
|
// ../runner/dist/server.js
|
|
134765
134854
|
var RunnerServer = class {
|
|
@@ -134836,6 +134925,10 @@ var RunnerServer = class {
|
|
|
134836
134925
|
peer.handle(RunnerMethod.WorkflowList, () => this.handleWorkflowList());
|
|
134837
134926
|
peer.handle(RunnerMethod.WorkflowSetEnabled, (raw) => this.handleWorkflowSetEnabled(raw));
|
|
134838
134927
|
peer.handle(RunnerMethod.WorkflowRun, (raw) => this.handleWorkflowRun(raw));
|
|
134928
|
+
peer.handle(RunnerMethod.WorkflowValidateDraft, (raw) => this.handleWorkflowValidateDraft(raw));
|
|
134929
|
+
peer.handle(RunnerMethod.WorkflowSave, (raw) => this.handleWorkflowSave(raw));
|
|
134930
|
+
peer.handle(RunnerMethod.WorkflowGetRun, (raw) => this.handleWorkflowGetRun(raw));
|
|
134931
|
+
peer.handle(RunnerMethod.WorkflowResume, (raw) => this.handleWorkflowResume(raw));
|
|
134839
134932
|
peer.onClose(() => this.onDisconnect(client));
|
|
134840
134933
|
}
|
|
134841
134934
|
onDisconnect(client) {
|
|
@@ -134847,7 +134940,7 @@ var RunnerServer = class {
|
|
|
134847
134940
|
// --- request handlers ----------------------------------------------------
|
|
134848
134941
|
handleAttach(client, raw) {
|
|
134849
134942
|
const params = attachParamsSchema.parse(raw);
|
|
134850
|
-
if (params.protocolVersion
|
|
134943
|
+
if (params.protocolVersion < MIN_COMPATIBLE_PROTOCOL_VERSION) {
|
|
134851
134944
|
throw new Error(`runner protocol mismatch: server v${RUNNER_PROTOCOL_VERSION}, client v${params.protocolVersion}`);
|
|
134852
134945
|
}
|
|
134853
134946
|
client.role = params.role;
|
|
@@ -135066,6 +135159,40 @@ var RunnerServer = class {
|
|
|
135066
135159
|
throw new Error("workflows plugin not loaded");
|
|
135067
135160
|
return view.run(params.name);
|
|
135068
135161
|
}
|
|
135162
|
+
// --- Workflows builder (validate / save / getRun) ------------------------
|
|
135163
|
+
// Optional on the view (older hosts / pre-builder plugins lack them), so
|
|
135164
|
+
// feature-check and throw a clear error rather than calling undefined.
|
|
135165
|
+
async handleWorkflowValidateDraft(raw) {
|
|
135166
|
+
const params = workflowValidateDraftParamsSchema.parse(raw);
|
|
135167
|
+
const view = this.session.workflows;
|
|
135168
|
+
if (!view?.validateDraft)
|
|
135169
|
+
throw new Error("workflows builder not supported on this runner");
|
|
135170
|
+
return view.validateDraft(params.yaml);
|
|
135171
|
+
}
|
|
135172
|
+
async handleWorkflowSave(raw) {
|
|
135173
|
+
const params = workflowSaveParamsSchema.parse(raw);
|
|
135174
|
+
const view = this.session.workflows;
|
|
135175
|
+
if (!view?.save)
|
|
135176
|
+
throw new Error("workflows builder not supported on this runner");
|
|
135177
|
+
return view.save(params.yaml, params.previousName);
|
|
135178
|
+
}
|
|
135179
|
+
async handleWorkflowGetRun(raw) {
|
|
135180
|
+
const params = workflowGetRunParamsSchema.parse(raw);
|
|
135181
|
+
const view = this.session.workflows;
|
|
135182
|
+
if (!view?.getRun)
|
|
135183
|
+
throw new Error("workflows builder not supported on this runner");
|
|
135184
|
+
return await view.getRun(params.name) ?? null;
|
|
135185
|
+
}
|
|
135186
|
+
// --- Workflows human-in-the-loop (resume a paused awaitInput run) ---------
|
|
135187
|
+
// v5. Optional on the view (older hosts lack it), so feature-check and throw a
|
|
135188
|
+
// clear error rather than calling undefined.
|
|
135189
|
+
async handleWorkflowResume(raw) {
|
|
135190
|
+
const params = workflowResumeParamsSchema.parse(raw);
|
|
135191
|
+
const view = this.session.workflows;
|
|
135192
|
+
if (!view?.resume)
|
|
135193
|
+
throw new Error("workflow resume not supported on this runner");
|
|
135194
|
+
return view.resume(params.runId, params.reply);
|
|
135195
|
+
}
|
|
135069
135196
|
broadcastInfo() {
|
|
135070
135197
|
this.broadcast(RunnerNotification.InfoChanged, { info: this.session.getInfo() });
|
|
135071
135198
|
}
|
|
@@ -135208,6 +135335,14 @@ var RemoteSession = class {
|
|
|
135208
135335
|
permissionResolver = null;
|
|
135209
135336
|
approvalResolver = null;
|
|
135210
135337
|
info = null;
|
|
135338
|
+
/**
|
|
135339
|
+
* The protocol version the SERVER reported at attach. Defaults to our own
|
|
135340
|
+
* version until the handshake resolves. Version-specific client methods (the
|
|
135341
|
+
* v4 workflow *builder* family) gate on this so a newer client attached to an
|
|
135342
|
+
* older runner degrades with a clear, actionable error instead of a raw
|
|
135343
|
+
* JSON-RPC method-not-found. Null until attached.
|
|
135344
|
+
*/
|
|
135345
|
+
serverProtocolVersion = null;
|
|
135211
135346
|
constructor(transport) {
|
|
135212
135347
|
this.peer = new JsonRpcPeer(transport);
|
|
135213
135348
|
this.peer.on(RunnerNotification.Event, (params) => {
|
|
@@ -135276,6 +135411,28 @@ var RemoteSession = class {
|
|
|
135276
135411
|
sinceSeq
|
|
135277
135412
|
});
|
|
135278
135413
|
this.info = result.info;
|
|
135414
|
+
this.serverProtocolVersion = typeof result.protocolVersion === "number" ? result.protocolVersion : RUNNER_PROTOCOL_VERSION;
|
|
135415
|
+
}
|
|
135416
|
+
/**
|
|
135417
|
+
* The protocol version the attached runner speaks (its own, from the
|
|
135418
|
+
* handshake). Lets a capability-detecting caller (e.g. the desktop's visual
|
|
135419
|
+
* builder, see #146) decide whether a version-gated feature is available on
|
|
135420
|
+
* THIS runner before invoking it. Null until attached.
|
|
135421
|
+
*/
|
|
135422
|
+
get runnerProtocolVersion() {
|
|
135423
|
+
return this.serverProtocolVersion;
|
|
135424
|
+
}
|
|
135425
|
+
/**
|
|
135426
|
+
* Guard a method that only exists on a server at/after `minVersion`. Throws a
|
|
135427
|
+
* clear, actionable error (not a raw JSON-RPC method-not-found) when the
|
|
135428
|
+
* attached runner is older — the desktop case after a JS hot-update outran
|
|
135429
|
+
* its bundled CLI.
|
|
135430
|
+
*/
|
|
135431
|
+
requireServerProtocol(minVersion, feature) {
|
|
135432
|
+
const server = this.serverProtocolVersion;
|
|
135433
|
+
if (server !== null && server < minVersion) {
|
|
135434
|
+
throw new Error(`${feature} is not supported by this runner (runner protocol v${server}, needs v${minVersion}) \u2014 update the moxxy CLI to continue.`);
|
|
135435
|
+
}
|
|
135279
135436
|
}
|
|
135280
135437
|
get id() {
|
|
135281
135438
|
return this.requireInfo().sessionId;
|
|
@@ -135508,7 +135665,40 @@ var RemoteSession = class {
|
|
|
135508
135665
|
enabled
|
|
135509
135666
|
});
|
|
135510
135667
|
},
|
|
135511
|
-
run: (name) => this.peer.request(RunnerMethod.WorkflowRun, { name })
|
|
135668
|
+
run: (name) => this.peer.request(RunnerMethod.WorkflowRun, { name }),
|
|
135669
|
+
// Builder methods (protocol v4): forward to the runner so the desktop's
|
|
135670
|
+
// RemoteSession-backed visual builder can validate/save/load drafts.
|
|
135671
|
+
// Gated on the SERVER's reported version so a v4 client on a v3 runner
|
|
135672
|
+
// (a desktop whose JS hot-update outran its bundled CLI) gets a clear
|
|
135673
|
+
// "update the CLI" error instead of a raw method-not-found.
|
|
135674
|
+
validateDraft: async (yaml) => {
|
|
135675
|
+
this.requireServerProtocol(4, "The workflows builder");
|
|
135676
|
+
return this.peer.request(RunnerMethod.WorkflowValidateDraft, {
|
|
135677
|
+
yaml
|
|
135678
|
+
});
|
|
135679
|
+
},
|
|
135680
|
+
save: async (yaml, previousName) => {
|
|
135681
|
+
this.requireServerProtocol(4, "Saving a workflow from the builder");
|
|
135682
|
+
return this.peer.request(RunnerMethod.WorkflowSave, {
|
|
135683
|
+
yaml,
|
|
135684
|
+
...previousName ? { previousName } : {}
|
|
135685
|
+
});
|
|
135686
|
+
},
|
|
135687
|
+
getRun: async (name) => {
|
|
135688
|
+
this.requireServerProtocol(4, "Loading a workflow into the builder");
|
|
135689
|
+
return this.peer.request(RunnerMethod.WorkflowGetRun, { name });
|
|
135690
|
+
},
|
|
135691
|
+
// Human-in-the-loop resume (protocol v5). Gated on the SERVER's reported
|
|
135692
|
+
// version so a v5 client attached to a v4 runner (a desktop whose JS
|
|
135693
|
+
// hot-update outran its bundled CLI) gets a clear "update the CLI" error
|
|
135694
|
+
// rather than a raw method-not-found.
|
|
135695
|
+
resume: async (runId, reply2) => {
|
|
135696
|
+
this.requireServerProtocol(5, "Resuming a paused workflow");
|
|
135697
|
+
return this.peer.request(RunnerMethod.WorkflowResume, {
|
|
135698
|
+
runId,
|
|
135699
|
+
reply: reply2
|
|
135700
|
+
});
|
|
135701
|
+
}
|
|
135512
135702
|
};
|
|
135513
135703
|
}
|
|
135514
135704
|
};
|
|
@@ -135575,11 +135765,14 @@ async function connectRemoteSession(opts = {}) {
|
|
|
135575
135765
|
throw err;
|
|
135576
135766
|
}
|
|
135577
135767
|
}
|
|
135768
|
+
function isProtocolMismatchError(err) {
|
|
135769
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
135770
|
+
return /protocol mismatch/i.test(msg);
|
|
135771
|
+
}
|
|
135578
135772
|
async function maybeRecoverFromMismatch(err, socketPath, opts) {
|
|
135579
135773
|
if (opts.transport || opts.skipMismatchRecovery)
|
|
135580
135774
|
return;
|
|
135581
|
-
|
|
135582
|
-
if (!/protocol mismatch/i.test(msg))
|
|
135775
|
+
if (!isProtocolMismatchError(err))
|
|
135583
135776
|
return;
|
|
135584
135777
|
try {
|
|
135585
135778
|
await killAndUnlinkRunner(socketPath, [...DEFAULT_RUNNER_PORTS, ...opts.extraPortsToFree ?? []]);
|
|
@@ -135614,11 +135807,11 @@ async function isMoxxyProcess(pid) {
|
|
|
135614
135807
|
return command.length > 0 && /moxxy/i.test(command);
|
|
135615
135808
|
}
|
|
135616
135809
|
async function pidCommand2(pid) {
|
|
135617
|
-
const { spawn:
|
|
135810
|
+
const { spawn: spawn14 } = await import('child_process');
|
|
135618
135811
|
return await new Promise((resolve12) => {
|
|
135619
135812
|
let out = "";
|
|
135620
135813
|
try {
|
|
135621
|
-
const child =
|
|
135814
|
+
const child = spawn14("ps", ["-p", String(pid), "-o", "command="], {
|
|
135622
135815
|
stdio: ["ignore", "pipe", "ignore"]
|
|
135623
135816
|
});
|
|
135624
135817
|
child.stdout.on("data", (b3) => {
|
|
@@ -135656,11 +135849,11 @@ async function pidsListeningOnPort(port) {
|
|
|
135656
135849
|
return await runLsof(["-t", `-iTCP:${port}`, "-sTCP:LISTEN"]);
|
|
135657
135850
|
}
|
|
135658
135851
|
async function runLsof(args) {
|
|
135659
|
-
const { spawn:
|
|
135852
|
+
const { spawn: spawn14 } = await import('child_process');
|
|
135660
135853
|
return await new Promise((resolve12) => {
|
|
135661
135854
|
let out = "";
|
|
135662
135855
|
try {
|
|
135663
|
-
const child =
|
|
135856
|
+
const child = spawn14("lsof", [...args], {
|
|
135664
135857
|
stdio: ["ignore", "pipe", "ignore"]
|
|
135665
135858
|
});
|
|
135666
135859
|
child.stdout.on("data", (b3) => {
|
|
@@ -135684,8 +135877,8 @@ function parsePids(out) {
|
|
|
135684
135877
|
}
|
|
135685
135878
|
async function unlinkSocket(socketPath) {
|
|
135686
135879
|
try {
|
|
135687
|
-
const
|
|
135688
|
-
|
|
135880
|
+
const fs44 = await import('fs');
|
|
135881
|
+
fs44.unlinkSync(socketPath);
|
|
135689
135882
|
} catch {
|
|
135690
135883
|
}
|
|
135691
135884
|
}
|
|
@@ -135704,13 +135897,44 @@ async function connectWithRetry(socketPath, retries) {
|
|
|
135704
135897
|
}
|
|
135705
135898
|
|
|
135706
135899
|
// ../desktop-ipc-contract/dist/index.js
|
|
135707
|
-
var
|
|
135708
|
-
|
|
135709
|
-
|
|
135710
|
-
|
|
135711
|
-
|
|
135712
|
-
"
|
|
135713
|
-
|
|
135900
|
+
var REMOTE_ALLOWED_COMMANDS = /* @__PURE__ */ new Set([
|
|
135901
|
+
// Answer a permission/approval prompt — RESPOND only. Note that
|
|
135902
|
+
// `session.setAutoApprove` (turn the prompt OFF entirely) is deliberately NOT
|
|
135903
|
+
// here: a remote client may answer the desktop user's prompts, never disable
|
|
135904
|
+
// them and run tools unattended.
|
|
135905
|
+
"ask.respond",
|
|
135906
|
+
// Workspace discovery + reconnect (read-only / non-mutating).
|
|
135907
|
+
"connection.snapshotAll",
|
|
135908
|
+
"connection.activeWorkspace",
|
|
135909
|
+
"connection.retry",
|
|
135910
|
+
// The conversation itself.
|
|
135911
|
+
"session.info",
|
|
135912
|
+
"session.runTurn",
|
|
135913
|
+
"session.abortTurn",
|
|
135914
|
+
"session.setMode",
|
|
135915
|
+
"session.newSession",
|
|
135916
|
+
"session.runCommand",
|
|
135917
|
+
// Voice input (capability-probed; transcribe fails coded without a transcriber).
|
|
135918
|
+
"session.hasTranscriber",
|
|
135919
|
+
"session.transcribe",
|
|
135920
|
+
// Per-workspace transcript log (the mobile ChatStoreBridge persists through
|
|
135921
|
+
// these; they're scoped to a workspace's NDJSON log, not host config).
|
|
135922
|
+
"chat.append",
|
|
135923
|
+
"chat.loadSegment",
|
|
135924
|
+
"chat.clearLog",
|
|
135925
|
+
"chat.migrate",
|
|
135926
|
+
// Workflows: READ + run an existing one only. Authoring (`workflows.save`,
|
|
135927
|
+
// `workflows.validateDraft`, `workflows.setEnabled`) is host-only — a paired
|
|
135928
|
+
// phone must not rewrite or re-enable the host's workflows.
|
|
135929
|
+
"workflows.list",
|
|
135930
|
+
"workflows.run",
|
|
135931
|
+
"workflows.getRun",
|
|
135932
|
+
// Answer a paused workflow's awaitInput question. This is RESPOND-only — like
|
|
135933
|
+
// `ask.respond`, the operator answers a question the WORKFLOW asked (the reply
|
|
135934
|
+
// is fed into the paused step and the run continues); it cannot create or
|
|
135935
|
+
// rewrite a workflow. A mobile user answering "ship it" to their own pipeline
|
|
135936
|
+
// is the canonical human-in-the-loop case, so it belongs on the trust surface.
|
|
135937
|
+
"workflows.resume"
|
|
135714
135938
|
]);
|
|
135715
135939
|
var providerName = z.string().regex(/^[a-z][a-z0-9-]{0,63}$/, "invalid provider name");
|
|
135716
135940
|
var httpUrl = z.string().refine((s2) => {
|
|
@@ -135725,6 +135949,9 @@ var skillName = z.string().min(1).max(200).regex(/^[A-Za-z0-9][A-Za-z0-9 ._/-]*$
|
|
|
135725
135949
|
var vaultKeyName = z.string().min(1).max(200).regex(/^[A-Za-z0-9][A-Za-z0-9._/-]*$/, "invalid vault key name").refine((s2) => !s2.includes(".."), 'vault key name may not contain ".."');
|
|
135726
135950
|
var optionalWorkspace = z.string().min(1).max(256).optional();
|
|
135727
135951
|
var MAX_AUDIO_BASE64 = 4e7;
|
|
135952
|
+
var MAX_INLINE_ATTACHMENT_CONTENT = 12e6;
|
|
135953
|
+
var commandName = z.string().min(1).max(64).regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, "invalid command name");
|
|
135954
|
+
var workflowName = z.string().min(1).max(200).refine((s2) => !s2.includes("..") && !s2.includes("/") && !s2.includes("\\"), "invalid workflow name");
|
|
135728
135955
|
var ipcInputSchemas = {
|
|
135729
135956
|
// No-arg, but spawns a child process (npm install) — pin the payload to
|
|
135730
135957
|
// "nothing" so a hostile renderer can't smuggle args across.
|
|
@@ -135769,7 +135996,40 @@ var ipcInputSchemas = {
|
|
|
135769
135996
|
attachments: z.array(z.object({
|
|
135770
135997
|
path: z.string().min(1).max(4096),
|
|
135771
135998
|
name: z.string().min(1).max(1024)
|
|
135772
|
-
})).max(64).optional()
|
|
135999
|
+
})).max(64).optional(),
|
|
136000
|
+
// Inline attachments cross the wire as payload (remote/mobile clients) —
|
|
136001
|
+
// bound both the entry count and per-entry content size.
|
|
136002
|
+
inlineAttachments: z.array(z.object({
|
|
136003
|
+
kind: z.enum(["stdin", "file", "image", "document", "audio"]),
|
|
136004
|
+
content: z.string().max(MAX_INLINE_ATTACHMENT_CONTENT),
|
|
136005
|
+
name: z.string().max(1024).optional(),
|
|
136006
|
+
mediaType: z.string().max(128).optional()
|
|
136007
|
+
})).max(8).optional()
|
|
136008
|
+
}),
|
|
136009
|
+
// Runs an arbitrary registered slash command — the audit flagged this as the
|
|
136010
|
+
// one mutating session command without a schema, so lock the name to a
|
|
136011
|
+
// registry slug and bound the free-text args.
|
|
136012
|
+
"session.runCommand": z.object({
|
|
136013
|
+
workspaceId: optionalWorkspace,
|
|
136014
|
+
name: commandName,
|
|
136015
|
+
args: z.string().max(1e4)
|
|
136016
|
+
}),
|
|
136017
|
+
"workflows.run": z.object({ name: workflowName }),
|
|
136018
|
+
"workflows.setEnabled": z.object({ name: workflowName, enabled: z.boolean() }),
|
|
136019
|
+
// Builder commands. validateDraft/save take full YAML — bound the size so a
|
|
136020
|
+
// hostile renderer can't OOM the host; save writes to disk so it's
|
|
136021
|
+
// filesystem-touching and gets a boundary check like the other writers.
|
|
136022
|
+
"workflows.validateDraft": z.object({ yaml: z.string().min(1).max(1e6) }),
|
|
136023
|
+
"workflows.save": z.object({
|
|
136024
|
+
yaml: z.string().min(1).max(1e6),
|
|
136025
|
+
previousName: workflowName.optional()
|
|
136026
|
+
}),
|
|
136027
|
+
"workflows.getRun": z.object({ name: workflowName }),
|
|
136028
|
+
// Human-in-the-loop resume: bound the run id + the operator reply (the reply
|
|
136029
|
+
// is forwarded into the paused step's child agent, so cap it to avoid OOM).
|
|
136030
|
+
"workflows.resume": z.object({
|
|
136031
|
+
runId: z.string().min(1).max(120),
|
|
136032
|
+
reply: z.string().min(1).max(1e5)
|
|
135773
136033
|
}),
|
|
135774
136034
|
// Security-sensitive: this bypasses the approval sheet, so validate it at
|
|
135775
136035
|
// the boundary like the other dangerous commands.
|
|
@@ -135795,8 +136055,14 @@ var ipcInputSchemas = {
|
|
|
135795
136055
|
onboardingComplete: z.boolean().optional(),
|
|
135796
136056
|
clerkUserId: z.string().max(256).nullable().optional(),
|
|
135797
136057
|
clerkDisplayName: z.string().max(256).nullable().optional(),
|
|
135798
|
-
signedInAt: z.number().nullable().optional()
|
|
136058
|
+
signedInAt: z.number().nullable().optional(),
|
|
136059
|
+
mobileGatewayEnabled: z.boolean().optional()
|
|
135799
136060
|
}).strict(),
|
|
136061
|
+
// Mobile-gateway control. Both no-arg variants pin the payload to "nothing"
|
|
136062
|
+
// so a hostile caller can't smuggle args; setEnabled is a strict boolean.
|
|
136063
|
+
"mobileGateway.status": z.undefined(),
|
|
136064
|
+
"mobileGateway.rotateToken": z.undefined(),
|
|
136065
|
+
"mobileGateway.setEnabled": z.object({ enabled: z.boolean() }).strict(),
|
|
135800
136066
|
"chat.append": z.object({
|
|
135801
136067
|
workspaceId: z.string().min(1).max(256),
|
|
135802
136068
|
events: z.array(z.unknown()).max(1e4)
|
|
@@ -135877,6 +136143,11 @@ async function dispatch(channel, args, fn) {
|
|
|
135877
136143
|
var WebSocketCommandBus = class {
|
|
135878
136144
|
methods = /* @__PURE__ */ new Map();
|
|
135879
136145
|
peers = /* @__PURE__ */ new Set();
|
|
136146
|
+
/** Deny-by-default allow-list (null ⇒ no filter; see the constructor). */
|
|
136147
|
+
allowedCommands;
|
|
136148
|
+
constructor(opts = {}) {
|
|
136149
|
+
this.allowedCommands = opts.allowedCommands === void 0 ? REMOTE_ALLOWED_COMMANDS : opts.allowedCommands;
|
|
136150
|
+
}
|
|
135880
136151
|
handle(channel, fn) {
|
|
135881
136152
|
this.methods.set(channel, fn);
|
|
135882
136153
|
}
|
|
@@ -135889,7 +136160,7 @@ var WebSocketCommandBus = class {
|
|
|
135889
136160
|
const peer = new JsonRpcPeer(transport);
|
|
135890
136161
|
for (const [channel, fn] of this.methods) {
|
|
135891
136162
|
peer.handle(channel, async (params) => {
|
|
135892
|
-
if (
|
|
136163
|
+
if (this.allowedCommands && !this.allowedCommands.has(channel)) {
|
|
135893
136164
|
const message = `command "${channel}" is not available over a remote transport`;
|
|
135894
136165
|
throw new RpcError(message, { code: "runner-error", message });
|
|
135895
136166
|
}
|
|
@@ -135983,7 +136254,74 @@ var MobileSessionHost = class {
|
|
|
135983
136254
|
this.bus.handle("session.setAutoApprove", async ({ enabled }) => {
|
|
135984
136255
|
this.autoApprove = enabled;
|
|
135985
136256
|
});
|
|
135986
|
-
this.bus.handle("session.
|
|
136257
|
+
this.bus.handle("session.setMode", async ({ mode }) => {
|
|
136258
|
+
this.session.modes.setActive(mode);
|
|
136259
|
+
this.bus.broadcast("connection.changed", { workspaceId: ws, phase: this.snapshot().phase });
|
|
136260
|
+
});
|
|
136261
|
+
this.bus.handle("session.newSession", async () => {
|
|
136262
|
+
for (const controller of this.turns.values())
|
|
136263
|
+
controller.abort();
|
|
136264
|
+
if (this.session.reset)
|
|
136265
|
+
await this.session.reset();
|
|
136266
|
+
else
|
|
136267
|
+
this.session.log.clear();
|
|
136268
|
+
});
|
|
136269
|
+
this.bus.handle("session.runCommand", async ({ name, args }) => {
|
|
136270
|
+
const def = this.session.commands.get(name);
|
|
136271
|
+
if (!def)
|
|
136272
|
+
return { kind: "error", message: `unknown command: /${name}` };
|
|
136273
|
+
return await def.handler({
|
|
136274
|
+
channel: "mobile",
|
|
136275
|
+
sessionId: this.session.getInfo().sessionId,
|
|
136276
|
+
args,
|
|
136277
|
+
session: this.session
|
|
136278
|
+
});
|
|
136279
|
+
});
|
|
136280
|
+
this.bus.handle("session.hasTranscriber", async () => this.activeTranscriber() != null);
|
|
136281
|
+
this.bus.handle("session.transcribe", async ({ audioBase64, mimeType }) => {
|
|
136282
|
+
const transcriber = this.activeTranscriber();
|
|
136283
|
+
if (!transcriber) {
|
|
136284
|
+
throw new IpcError("not-supported", "no transcriber is active on this session");
|
|
136285
|
+
}
|
|
136286
|
+
const audio = Buffer.from(audioBase64, "base64");
|
|
136287
|
+
const result = await transcriber.transcribe(audio, mimeType ? { mimeType } : void 0);
|
|
136288
|
+
return result.text;
|
|
136289
|
+
});
|
|
136290
|
+
this.bus.handle("workflows.list", async () => this.session.workflows?.list() ?? []);
|
|
136291
|
+
this.bus.handle("workflows.setEnabled", async ({ name, enabled }) => {
|
|
136292
|
+
if (this.session.workflows)
|
|
136293
|
+
await this.session.workflows.setEnabled(name, enabled);
|
|
136294
|
+
});
|
|
136295
|
+
this.bus.handle("workflows.run", async ({ name }) => {
|
|
136296
|
+
if (!this.session.workflows) {
|
|
136297
|
+
throw new IpcError("not-supported", "workflows plugin not loaded on this session");
|
|
136298
|
+
}
|
|
136299
|
+
return await this.session.workflows.run(name);
|
|
136300
|
+
});
|
|
136301
|
+
this.bus.handle("workflows.validateDraft", async ({ yaml }) => {
|
|
136302
|
+
if (!this.session.workflows?.validateDraft) {
|
|
136303
|
+
throw new IpcError("not-supported", "workflows builder not supported on this session");
|
|
136304
|
+
}
|
|
136305
|
+
return await this.session.workflows.validateDraft(yaml);
|
|
136306
|
+
});
|
|
136307
|
+
this.bus.handle("workflows.save", async ({ yaml }) => {
|
|
136308
|
+
if (!this.session.workflows?.save) {
|
|
136309
|
+
throw new IpcError("not-supported", "workflows builder not supported on this session");
|
|
136310
|
+
}
|
|
136311
|
+
return await this.session.workflows.save(yaml);
|
|
136312
|
+
});
|
|
136313
|
+
this.bus.handle("workflows.getRun", async ({ name }) => {
|
|
136314
|
+
if (!this.session.workflows?.getRun) {
|
|
136315
|
+
throw new IpcError("not-supported", "workflows builder not supported on this session");
|
|
136316
|
+
}
|
|
136317
|
+
return await this.session.workflows.getRun(name);
|
|
136318
|
+
});
|
|
136319
|
+
this.bus.handle("workflows.resume", async ({ runId, reply: reply2 }) => {
|
|
136320
|
+
if (!this.session.workflows?.resume) {
|
|
136321
|
+
throw new IpcError("not-supported", "workflow resume not supported on this session");
|
|
136322
|
+
}
|
|
136323
|
+
return await this.session.workflows.resume(runId, reply2);
|
|
136324
|
+
});
|
|
135987
136325
|
this.bus.handle("ask.respond", async ({ requestId, response }) => {
|
|
135988
136326
|
this.answerAsk(requestId, response);
|
|
135989
136327
|
});
|
|
@@ -136025,6 +136363,15 @@ var MobileSessionHost = class {
|
|
|
136025
136363
|
this.session.setApprovalResolver(null);
|
|
136026
136364
|
}
|
|
136027
136365
|
// ---- internals ----------------------------------------------------------
|
|
136366
|
+
/** Active transcriber, or null. Guarded access — a thin/remote session may
|
|
136367
|
+
* leave the registry view undefined (capability-absent ≠ crash). */
|
|
136368
|
+
activeTranscriber() {
|
|
136369
|
+
try {
|
|
136370
|
+
return this.session.transcribers?.tryGetActive() ?? null;
|
|
136371
|
+
} catch {
|
|
136372
|
+
return null;
|
|
136373
|
+
}
|
|
136374
|
+
}
|
|
136028
136375
|
snapshot() {
|
|
136029
136376
|
const info = this.session.getInfo();
|
|
136030
136377
|
const phase = {
|
|
@@ -136045,7 +136392,8 @@ var MobileSessionHost = class {
|
|
|
136045
136392
|
try {
|
|
136046
136393
|
for await (const _event of this.session.runTurn(args.prompt, {
|
|
136047
136394
|
signal: controller.signal,
|
|
136048
|
-
...args.model ? { model: args.model } : {}
|
|
136395
|
+
...args.model ? { model: args.model } : {},
|
|
136396
|
+
...args.inlineAttachments && args.inlineAttachments.length > 0 ? { attachments: args.inlineAttachments } : {}
|
|
136049
136397
|
})) {
|
|
136050
136398
|
void _event;
|
|
136051
136399
|
}
|
|
@@ -136084,19 +136432,6 @@ function resolveMobileToken(configured) {
|
|
|
136084
136432
|
function rotateMobileToken() {
|
|
136085
136433
|
return rotateChannelToken({ fileName: TOKEN_FILE });
|
|
136086
136434
|
}
|
|
136087
|
-
function normalizeTunnelChoice(raw) {
|
|
136088
|
-
const v3 = (process.env.MOXXY_MOBILE_TUNNEL ?? raw ?? "localhost").trim().toLowerCase();
|
|
136089
|
-
if (v3 === "cloudflared" || v3 === "ngrok")
|
|
136090
|
-
return v3;
|
|
136091
|
-
return "localhost";
|
|
136092
|
-
}
|
|
136093
|
-
function tunnelProviderFor(choice) {
|
|
136094
|
-
if (choice === "cloudflared")
|
|
136095
|
-
return cloudflaredTunnel;
|
|
136096
|
-
if (choice === "ngrok")
|
|
136097
|
-
return ngrokTunnel;
|
|
136098
|
-
return null;
|
|
136099
|
-
}
|
|
136100
136435
|
function resolveBindHost(configured) {
|
|
136101
136436
|
const v3 = (process.env.MOXXY_MOBILE_HOST ?? configured ?? "").trim();
|
|
136102
136437
|
return v3.length > 0 ? v3 : "127.0.0.1";
|
|
@@ -136133,6 +136468,21 @@ function buildConnectUrl(opts) {
|
|
|
136133
136468
|
return `ws://${opts.localHost}:${opts.port}/?t=${t2}`;
|
|
136134
136469
|
}
|
|
136135
136470
|
|
|
136471
|
+
// ../plugin-channel-mobile/dist/tunnel.js
|
|
136472
|
+
function normalizeTunnelChoice(raw) {
|
|
136473
|
+
const v3 = (process.env.MOXXY_MOBILE_TUNNEL ?? raw ?? "localhost").trim().toLowerCase();
|
|
136474
|
+
if (v3 === "cloudflared" || v3 === "ngrok")
|
|
136475
|
+
return v3;
|
|
136476
|
+
return "localhost";
|
|
136477
|
+
}
|
|
136478
|
+
function tunnelProviderFor(choice) {
|
|
136479
|
+
if (choice === "cloudflared")
|
|
136480
|
+
return cloudflaredTunnel;
|
|
136481
|
+
if (choice === "ngrok")
|
|
136482
|
+
return ngrokTunnel;
|
|
136483
|
+
return null;
|
|
136484
|
+
}
|
|
136485
|
+
|
|
136136
136486
|
// ../plugin-channel-mobile/dist/qr.js
|
|
136137
136487
|
var import_qrcode = __toESM(require_lib3());
|
|
136138
136488
|
async function printConnectInfo(url2, token, hint) {
|
|
@@ -136196,7 +136546,7 @@ var MobileChannel = class {
|
|
|
136196
136546
|
return this.token;
|
|
136197
136547
|
}
|
|
136198
136548
|
async start(startOpts) {
|
|
136199
|
-
const bus = new WebSocketCommandBus();
|
|
136549
|
+
const bus = new WebSocketCommandBus({ allowedCommands: null });
|
|
136200
136550
|
const host = new MobileSessionHost(bus, startOpts.session);
|
|
136201
136551
|
this.host = host;
|
|
136202
136552
|
host.register();
|
|
@@ -137691,10 +138041,10 @@ function buildUsageStatsPlugin(opts = {}) {
|
|
|
137691
138041
|
cursor = ctx.log.length;
|
|
137692
138042
|
},
|
|
137693
138043
|
async onShutdown(ctx) {
|
|
137694
|
-
const
|
|
137695
|
-
if (
|
|
138044
|
+
const live = ctx.log.slice(cursor);
|
|
138045
|
+
if (live.length === 0)
|
|
137696
138046
|
return;
|
|
137697
|
-
const delta = summarizeTokensByModel(
|
|
138047
|
+
const delta = summarizeTokensByModel(live);
|
|
137698
138048
|
await mergeUsageStats(delta, opts.statsPath);
|
|
137699
138049
|
}
|
|
137700
138050
|
}
|
|
@@ -138835,11 +139185,11 @@ var ScheduleStore = class {
|
|
|
138835
139185
|
* Used by the workflows integration to mirror a workflow's `on.schedule`
|
|
138836
139186
|
* into the shared poller without a separate timer.
|
|
138837
139187
|
*/
|
|
138838
|
-
async syncWorkflowSchedule(
|
|
139188
|
+
async syncWorkflowSchedule(workflowName2, entry) {
|
|
138839
139189
|
await this.mutate((schedules) => {
|
|
138840
|
-
const filtered = schedules.filter((s2) => !(s2.source === "workflow" && s2.workflowName ===
|
|
139190
|
+
const filtered = schedules.filter((s2) => !(s2.source === "workflow" && s2.workflowName === workflowName2));
|
|
138841
139191
|
if (entry) {
|
|
138842
|
-
filtered.push(scheduleEntrySchema.parse({ ...entry, source: "workflow", workflowName }));
|
|
139192
|
+
filtered.push(scheduleEntrySchema.parse({ ...entry, source: "workflow", workflowName: workflowName2 }));
|
|
138843
139193
|
}
|
|
138844
139194
|
return filtered;
|
|
138845
139195
|
});
|
|
@@ -139282,7 +139632,7 @@ function readHeader(headers, name) {
|
|
|
139282
139632
|
return v3[0] ?? null;
|
|
139283
139633
|
return v3 ?? null;
|
|
139284
139634
|
}
|
|
139285
|
-
function readJsonPath(body,
|
|
139635
|
+
function readJsonPath(body, path61) {
|
|
139286
139636
|
let parsed;
|
|
139287
139637
|
try {
|
|
139288
139638
|
parsed = JSON.parse(body.toString("utf8"));
|
|
@@ -139290,7 +139640,7 @@ function readJsonPath(body, path60) {
|
|
|
139290
139640
|
return null;
|
|
139291
139641
|
}
|
|
139292
139642
|
let cur = parsed;
|
|
139293
|
-
for (const seg of
|
|
139643
|
+
for (const seg of path61.split(".")) {
|
|
139294
139644
|
if (cur === null || cur === void 0 || typeof cur !== "object")
|
|
139295
139645
|
return null;
|
|
139296
139646
|
cur = cur[seg];
|
|
@@ -139905,88 +140255,52 @@ function redactVerification(v3) {
|
|
|
139905
140255
|
}
|
|
139906
140256
|
var CLOUDFLARED_URL_RE = /https:\/\/[A-Za-z0-9.-]+\.trycloudflare\.com/;
|
|
139907
140257
|
var NGROK_URL_RE2 = /https:\/\/[A-Za-z0-9.-]+\.ngrok[a-z.-]*\.app/;
|
|
139908
|
-
|
|
139909
|
-
|
|
139910
|
-
|
|
139911
|
-
|
|
139912
|
-
|
|
140258
|
+
var SPAWN_CONFIG = {
|
|
140259
|
+
cloudflared: {
|
|
140260
|
+
cmd: "cloudflared",
|
|
140261
|
+
urlRegex: CLOUDFLARED_URL_RE,
|
|
140262
|
+
args: (port, host) => ["tunnel", "--no-autoupdate", "--url", `http://${host}:${port}`]
|
|
140263
|
+
},
|
|
140264
|
+
ngrok: {
|
|
140265
|
+
cmd: "ngrok",
|
|
140266
|
+
urlRegex: NGROK_URL_RE2,
|
|
140267
|
+
args: (port) => ["http", String(port), "--log=stdout"]
|
|
140268
|
+
}
|
|
140269
|
+
};
|
|
140270
|
+
function openCliTunnel(kind3, port, host, timeoutMs) {
|
|
140271
|
+
const cfg = SPAWN_CONFIG[kind3];
|
|
140272
|
+
return spawnCliTunnel({
|
|
140273
|
+
cmd: cfg.cmd,
|
|
140274
|
+
args: cfg.args(port, host),
|
|
140275
|
+
urlRegex: cfg.urlRegex,
|
|
140276
|
+
name: kind3,
|
|
140277
|
+
...timeoutMs !== void 0 ? { timeoutMs } : {}
|
|
139913
140278
|
});
|
|
139914
140279
|
}
|
|
140280
|
+
var webhookTunnelProviders = {
|
|
140281
|
+
cloudflared: defineTunnelProvider({
|
|
140282
|
+
name: "cloudflared",
|
|
140283
|
+
isAvailable: () => isCliTunnelAvailable("cloudflared"),
|
|
140284
|
+
open: ({ port, host }) => openCliTunnel("cloudflared", port, host)
|
|
140285
|
+
}),
|
|
140286
|
+
ngrok: defineTunnelProvider({
|
|
140287
|
+
name: "ngrok",
|
|
140288
|
+
isAvailable: () => isCliTunnelAvailable("ngrok"),
|
|
140289
|
+
open: ({ port, host }) => openCliTunnel("ngrok", port, host)
|
|
140290
|
+
})
|
|
140291
|
+
};
|
|
140292
|
+
function isTunnelCliAvailable(kind3) {
|
|
140293
|
+
const provider = webhookTunnelProviders[kind3];
|
|
140294
|
+
return provider.isAvailable ? provider.isAvailable() : Promise.resolve(false);
|
|
140295
|
+
}
|
|
139915
140296
|
async function startTunnel(opts) {
|
|
139916
140297
|
const host = opts.host ?? "127.0.0.1";
|
|
139917
|
-
const
|
|
139918
|
-
const args = opts.kind === "cloudflared" ? ["tunnel", "--no-autoupdate", "--url", target, ...opts.extraArgs ?? []] : ["http", `${opts.port}`, "--log=stdout", ...opts.extraArgs ?? []];
|
|
139919
|
-
const timeoutMs = opts.urlTimeoutMs ?? 3e4;
|
|
139920
|
-
let child;
|
|
139921
|
-
try {
|
|
139922
|
-
child = spawn(opts.kind, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
139923
|
-
} catch (err) {
|
|
139924
|
-
throw new Error(`failed to spawn ${opts.kind} \u2014 is it installed? (${err instanceof Error ? err.message : String(err)})`);
|
|
139925
|
-
}
|
|
139926
|
-
const urlRe = opts.kind === "cloudflared" ? CLOUDFLARED_URL_RE : NGROK_URL_RE2;
|
|
139927
|
-
const urlPromise = new Promise((resolve12, reject) => {
|
|
139928
|
-
let settled = false;
|
|
139929
|
-
const onChunk = (buf) => {
|
|
139930
|
-
const match = urlRe.exec(buf.toString("utf8"));
|
|
139931
|
-
if (match && !settled) {
|
|
139932
|
-
settled = true;
|
|
139933
|
-
resolve12(match[0]);
|
|
139934
|
-
}
|
|
139935
|
-
};
|
|
139936
|
-
child.stdout?.on("data", onChunk);
|
|
139937
|
-
child.stderr?.on("data", onChunk);
|
|
139938
|
-
child.once("error", (err) => {
|
|
139939
|
-
if (!settled) {
|
|
139940
|
-
settled = true;
|
|
139941
|
-
reject(err);
|
|
139942
|
-
}
|
|
139943
|
-
});
|
|
139944
|
-
child.once("exit", (code) => {
|
|
139945
|
-
if (!settled) {
|
|
139946
|
-
settled = true;
|
|
139947
|
-
reject(new Error(`${opts.kind} exited before printing a URL (code=${code ?? "null"})`));
|
|
139948
|
-
}
|
|
139949
|
-
});
|
|
139950
|
-
setTimeout(() => {
|
|
139951
|
-
if (!settled) {
|
|
139952
|
-
settled = true;
|
|
139953
|
-
reject(new Error(`timed out waiting ${timeoutMs}ms for ${opts.kind} URL`));
|
|
139954
|
-
}
|
|
139955
|
-
}, timeoutMs).unref?.();
|
|
139956
|
-
});
|
|
139957
|
-
let url2;
|
|
139958
|
-
try {
|
|
139959
|
-
url2 = await urlPromise;
|
|
139960
|
-
} catch (err) {
|
|
139961
|
-
try {
|
|
139962
|
-
child.kill("SIGTERM");
|
|
139963
|
-
} catch {
|
|
139964
|
-
}
|
|
139965
|
-
throw err;
|
|
139966
|
-
}
|
|
139967
|
-
const pid = child.pid ?? -1;
|
|
140298
|
+
const handle2 = await openCliTunnel(opts.kind, opts.port, host, opts.urlTimeoutMs);
|
|
139968
140299
|
return {
|
|
139969
140300
|
kind: opts.kind,
|
|
139970
|
-
url:
|
|
139971
|
-
pid,
|
|
139972
|
-
stop:
|
|
139973
|
-
if (!child.killed && child.exitCode === null) {
|
|
139974
|
-
child.kill("SIGTERM");
|
|
139975
|
-
try {
|
|
139976
|
-
await Promise.race([
|
|
139977
|
-
once(child, "exit"),
|
|
139978
|
-
new Promise((r2) => setTimeout(r2, 2e3).unref?.())
|
|
139979
|
-
]);
|
|
139980
|
-
} catch {
|
|
139981
|
-
}
|
|
139982
|
-
if (!child.killed && child.exitCode === null) {
|
|
139983
|
-
try {
|
|
139984
|
-
child.kill("SIGKILL");
|
|
139985
|
-
} catch {
|
|
139986
|
-
}
|
|
139987
|
-
}
|
|
139988
|
-
}
|
|
139989
|
-
}
|
|
140301
|
+
url: handle2.url,
|
|
140302
|
+
pid: handle2.pid,
|
|
140303
|
+
stop: () => handle2.close()
|
|
139990
140304
|
};
|
|
139991
140305
|
}
|
|
139992
140306
|
function defaultWebhookSecretsDir() {
|
|
@@ -141926,23 +142240,123 @@ function validateCondition(expr) {
|
|
|
141926
142240
|
}
|
|
141927
142241
|
|
|
141928
142242
|
// ../plugin-workflows/dist/schema.js
|
|
141929
|
-
var ACTION_KEYS = [
|
|
142243
|
+
var ACTION_KEYS = [
|
|
142244
|
+
"skill",
|
|
142245
|
+
"prompt",
|
|
142246
|
+
"tool",
|
|
142247
|
+
"workflow",
|
|
142248
|
+
"bridge",
|
|
142249
|
+
"condition",
|
|
142250
|
+
"switch",
|
|
142251
|
+
"loop"
|
|
142252
|
+
];
|
|
141930
142253
|
var SLUG_RE = /^[a-z0-9][a-z0-9-]*$/i;
|
|
141931
142254
|
var STEP_ID_RE = /^[a-z0-9][a-z0-9_-]*$/i;
|
|
142255
|
+
var loopActionSchema = z.object({
|
|
142256
|
+
body: z.array(z.string().min(1)).min(1),
|
|
142257
|
+
condition: z.string().min(1),
|
|
142258
|
+
maxIterations: z.number().int().min(1).max(50).default(10)
|
|
142259
|
+
});
|
|
141932
142260
|
var stepSchema = z.object({
|
|
141933
142261
|
id: z.string().min(1).max(80).regex(STEP_ID_RE, "step id must be slug-like"),
|
|
141934
142262
|
skill: z.string().min(1).optional(),
|
|
141935
142263
|
prompt: z.string().min(1).optional(),
|
|
141936
142264
|
tool: z.string().min(1).optional(),
|
|
141937
142265
|
workflow: z.string().min(1).optional(),
|
|
142266
|
+
bridge: z.string().min(1).optional(),
|
|
142267
|
+
condition: z.string().min(1).optional(),
|
|
142268
|
+
then: z.array(z.string().min(1)).optional(),
|
|
142269
|
+
else: z.array(z.string().min(1)).optional(),
|
|
142270
|
+
switch: z.string().min(1).optional(),
|
|
142271
|
+
cases: z.record(z.array(z.string().min(1))).optional(),
|
|
142272
|
+
default: z.array(z.string().min(1)).optional(),
|
|
142273
|
+
loop: loopActionSchema.optional(),
|
|
141938
142274
|
input: z.string().optional(),
|
|
141939
142275
|
args: z.record(z.unknown()).optional(),
|
|
141940
142276
|
needs: z.array(z.string().min(1)).default([]),
|
|
141941
142277
|
when: z.string().min(1).optional(),
|
|
141942
142278
|
onError: z.enum(["fail", "continue", "retry"]).default("fail"),
|
|
141943
142279
|
retries: z.number().int().min(0).max(3).default(0),
|
|
141944
|
-
label: z.string().max(60).optional()
|
|
142280
|
+
label: z.string().max(60).optional(),
|
|
142281
|
+
format: z.enum(["json", "plain"]).optional(),
|
|
142282
|
+
awaitInput: z.boolean().optional()
|
|
141945
142283
|
}).superRefine((step, ctx) => {
|
|
142284
|
+
const isLogic = step.bridge != null || step.condition != null || step.switch != null;
|
|
142285
|
+
if (step.awaitInput && (step.tool != null || step.workflow != null || step.loop != null || isLogic)) {
|
|
142286
|
+
ctx.addIssue({
|
|
142287
|
+
code: z.ZodIssueCode.custom,
|
|
142288
|
+
message: `step "${step.id}": awaitInput is only allowed on prompt or skill steps`,
|
|
142289
|
+
path: ["awaitInput"]
|
|
142290
|
+
});
|
|
142291
|
+
}
|
|
142292
|
+
if (step.format === "plain" && step.bridge == null) {
|
|
142293
|
+
ctx.addIssue({
|
|
142294
|
+
code: z.ZodIssueCode.custom,
|
|
142295
|
+
message: `step "${step.id}": format plain is only allowed on bridge steps`,
|
|
142296
|
+
path: ["format"]
|
|
142297
|
+
});
|
|
142298
|
+
}
|
|
142299
|
+
if (step.condition != null) {
|
|
142300
|
+
if (step.then == null) {
|
|
142301
|
+
ctx.addIssue({
|
|
142302
|
+
code: z.ZodIssueCode.custom,
|
|
142303
|
+
message: `step "${step.id}": condition requires then`,
|
|
142304
|
+
path: ["then"]
|
|
142305
|
+
});
|
|
142306
|
+
}
|
|
142307
|
+
if (step.else == null) {
|
|
142308
|
+
ctx.addIssue({
|
|
142309
|
+
code: z.ZodIssueCode.custom,
|
|
142310
|
+
message: `step "${step.id}": condition requires else`,
|
|
142311
|
+
path: ["else"]
|
|
142312
|
+
});
|
|
142313
|
+
}
|
|
142314
|
+
}
|
|
142315
|
+
if (step.switch != null) {
|
|
142316
|
+
const caseKeys = Object.keys(step.cases ?? {});
|
|
142317
|
+
if (caseKeys.length === 0) {
|
|
142318
|
+
ctx.addIssue({
|
|
142319
|
+
code: z.ZodIssueCode.custom,
|
|
142320
|
+
message: `step "${step.id}": switch requires at least one case`,
|
|
142321
|
+
path: ["cases"]
|
|
142322
|
+
});
|
|
142323
|
+
}
|
|
142324
|
+
}
|
|
142325
|
+
if (step.loop != null && (step.then != null || step.else != null || step.cases != null || step.default != null)) {
|
|
142326
|
+
ctx.addIssue({
|
|
142327
|
+
code: z.ZodIssueCode.custom,
|
|
142328
|
+
message: `step "${step.id}": loop cannot be combined with then/else/cases/default`,
|
|
142329
|
+
path: ["loop"]
|
|
142330
|
+
});
|
|
142331
|
+
}
|
|
142332
|
+
if (step.then != null && step.condition == null) {
|
|
142333
|
+
ctx.addIssue({
|
|
142334
|
+
code: z.ZodIssueCode.custom,
|
|
142335
|
+
message: `step "${step.id}": then is only valid with condition`,
|
|
142336
|
+
path: ["then"]
|
|
142337
|
+
});
|
|
142338
|
+
}
|
|
142339
|
+
if (step.else != null && step.condition == null) {
|
|
142340
|
+
ctx.addIssue({
|
|
142341
|
+
code: z.ZodIssueCode.custom,
|
|
142342
|
+
message: `step "${step.id}": else is only valid with condition`,
|
|
142343
|
+
path: ["else"]
|
|
142344
|
+
});
|
|
142345
|
+
}
|
|
142346
|
+
if (step.cases != null && step.switch == null) {
|
|
142347
|
+
ctx.addIssue({
|
|
142348
|
+
code: z.ZodIssueCode.custom,
|
|
142349
|
+
message: `step "${step.id}": cases is only valid with switch`,
|
|
142350
|
+
path: ["cases"]
|
|
142351
|
+
});
|
|
142352
|
+
}
|
|
142353
|
+
if (step.default != null && step.switch == null) {
|
|
142354
|
+
ctx.addIssue({
|
|
142355
|
+
code: z.ZodIssueCode.custom,
|
|
142356
|
+
message: `step "${step.id}": default branch list is only valid with switch`,
|
|
142357
|
+
path: ["default"]
|
|
142358
|
+
});
|
|
142359
|
+
}
|
|
141946
142360
|
const present2 = ACTION_KEYS.filter((k3) => step[k3] != null);
|
|
141947
142361
|
if (present2.length === 0) {
|
|
141948
142362
|
ctx.addIssue({
|
|
@@ -141972,6 +142386,17 @@ var inputSpecSchema = z.object({
|
|
|
141972
142386
|
default: z.unknown().optional(),
|
|
141973
142387
|
description: z.string().optional()
|
|
141974
142388
|
});
|
|
142389
|
+
var uiLayoutSchema = z.object({
|
|
142390
|
+
nodes: z.record(z.object({
|
|
142391
|
+
x: z.number(),
|
|
142392
|
+
y: z.number()
|
|
142393
|
+
})).default({}),
|
|
142394
|
+
viewport: z.object({
|
|
142395
|
+
x: z.number(),
|
|
142396
|
+
y: z.number(),
|
|
142397
|
+
zoom: z.number().positive()
|
|
142398
|
+
}).optional()
|
|
142399
|
+
});
|
|
141975
142400
|
var workflowSchema = z.object({
|
|
141976
142401
|
name: z.string().min(1).max(120).regex(SLUG_RE, "name must be slug-like"),
|
|
141977
142402
|
description: z.string().min(1),
|
|
@@ -141983,6 +142408,9 @@ var workflowSchema = z.object({
|
|
|
141983
142408
|
channel: z.string().optional(),
|
|
141984
142409
|
inbox: z.boolean().default(true)
|
|
141985
142410
|
}).optional(),
|
|
142411
|
+
ui: z.object({
|
|
142412
|
+
layout: uiLayoutSchema.optional()
|
|
142413
|
+
}).optional(),
|
|
141986
142414
|
concurrency: z.number().int().min(1).max(8).default(4),
|
|
141987
142415
|
steps: z.array(stepSchema).min(1).max(40)
|
|
141988
142416
|
}).superRefine((wf, ctx) => {
|
|
@@ -142028,6 +142456,119 @@ var workflowSchema = z.object({
|
|
|
142028
142456
|
});
|
|
142029
142457
|
}
|
|
142030
142458
|
}
|
|
142459
|
+
for (const step of wf.steps) {
|
|
142460
|
+
const branchIds = [];
|
|
142461
|
+
if (step.then)
|
|
142462
|
+
branchIds.push(...step.then);
|
|
142463
|
+
if (step.else)
|
|
142464
|
+
branchIds.push(...step.else);
|
|
142465
|
+
if (step.cases)
|
|
142466
|
+
for (const list of Object.values(step.cases))
|
|
142467
|
+
branchIds.push(...list);
|
|
142468
|
+
if (step.default)
|
|
142469
|
+
branchIds.push(...step.default);
|
|
142470
|
+
for (const ref of branchIds) {
|
|
142471
|
+
if (!ids.has(ref)) {
|
|
142472
|
+
ctx.addIssue({
|
|
142473
|
+
code: z.ZodIssueCode.custom,
|
|
142474
|
+
message: `step "${step.id}" references unknown branch step "${ref}"`,
|
|
142475
|
+
path: ["steps"]
|
|
142476
|
+
});
|
|
142477
|
+
}
|
|
142478
|
+
if (ref === step.id) {
|
|
142479
|
+
ctx.addIssue({
|
|
142480
|
+
code: z.ZodIssueCode.custom,
|
|
142481
|
+
message: `step "${step.id}" cannot reference itself in then/else/cases/default`,
|
|
142482
|
+
path: ["steps"]
|
|
142483
|
+
});
|
|
142484
|
+
}
|
|
142485
|
+
}
|
|
142486
|
+
}
|
|
142487
|
+
for (const step of wf.steps) {
|
|
142488
|
+
if (step.loop == null)
|
|
142489
|
+
continue;
|
|
142490
|
+
for (const ref of step.loop.body) {
|
|
142491
|
+
if (!ids.has(ref)) {
|
|
142492
|
+
ctx.addIssue({
|
|
142493
|
+
code: z.ZodIssueCode.custom,
|
|
142494
|
+
message: `step "${step.id}" loop references unknown body step "${ref}"`,
|
|
142495
|
+
path: ["steps"]
|
|
142496
|
+
});
|
|
142497
|
+
}
|
|
142498
|
+
}
|
|
142499
|
+
}
|
|
142500
|
+
const stepById = new Map(wf.steps.map((s2) => [s2.id, s2]));
|
|
142501
|
+
const bodyOwner = /* @__PURE__ */ new Map();
|
|
142502
|
+
for (const step of wf.steps) {
|
|
142503
|
+
if (step.loop == null)
|
|
142504
|
+
continue;
|
|
142505
|
+
for (const ref of step.loop.body)
|
|
142506
|
+
bodyOwner.set(ref, step.id);
|
|
142507
|
+
}
|
|
142508
|
+
for (const step of wf.steps) {
|
|
142509
|
+
const owner = bodyOwner.get(step.id);
|
|
142510
|
+
if (owner == null)
|
|
142511
|
+
continue;
|
|
142512
|
+
const body = stepById.get(step.id);
|
|
142513
|
+
if (body.condition != null || body.switch != null) {
|
|
142514
|
+
ctx.addIssue({
|
|
142515
|
+
code: z.ZodIssueCode.custom,
|
|
142516
|
+
message: `step "${step.id}" is a loop body of "${owner}" and cannot be a condition/switch step \u2014 branch routing is not honored inside a loop body. Use a bridge step to set vars and drive the loop's own exit condition instead.`,
|
|
142517
|
+
path: ["steps"]
|
|
142518
|
+
});
|
|
142519
|
+
}
|
|
142520
|
+
if (body.awaitInput) {
|
|
142521
|
+
ctx.addIssue({
|
|
142522
|
+
code: z.ZodIssueCode.custom,
|
|
142523
|
+
message: `step "${step.id}" is a loop body of "${owner}" and cannot use awaitInput \u2014 a loop body cannot pause mid-iteration. Ask the operator before/after the loop instead.`,
|
|
142524
|
+
path: ["steps"]
|
|
142525
|
+
});
|
|
142526
|
+
}
|
|
142527
|
+
if (body.when != null) {
|
|
142528
|
+
ctx.addIssue({
|
|
142529
|
+
code: z.ZodIssueCode.custom,
|
|
142530
|
+
message: `step "${step.id}" is a loop body of "${owner}" and cannot have a \`when\` guard \u2014 loop body steps run unconditionally each iteration. Gate the loop via its \`condition\` (exit) instead.`,
|
|
142531
|
+
path: ["steps"]
|
|
142532
|
+
});
|
|
142533
|
+
}
|
|
142534
|
+
for (const dep of body.needs) {
|
|
142535
|
+
if (dep === owner)
|
|
142536
|
+
continue;
|
|
142537
|
+
if (bodyOwner.get(dep) === owner)
|
|
142538
|
+
continue;
|
|
142539
|
+
ctx.addIssue({
|
|
142540
|
+
code: z.ZodIssueCode.custom,
|
|
142541
|
+
message: `step "${step.id}" is a loop body of "${owner}" and may only \`needs\` its loop step ("${owner}") or a sibling body step of the same loop \u2014 "${dep}" is outside the loop and would never settle for it.`,
|
|
142542
|
+
path: ["steps"]
|
|
142543
|
+
});
|
|
142544
|
+
}
|
|
142545
|
+
}
|
|
142546
|
+
for (const step of wf.steps) {
|
|
142547
|
+
if (bodyOwner.has(step.id))
|
|
142548
|
+
continue;
|
|
142549
|
+
if (step.loop != null) {
|
|
142550
|
+
const ownBody = new Set(step.loop.body);
|
|
142551
|
+
for (const dep of step.needs) {
|
|
142552
|
+
if (bodyOwner.has(dep) && !ownBody.has(dep)) {
|
|
142553
|
+
ctx.addIssue({
|
|
142554
|
+
code: z.ZodIssueCode.custom,
|
|
142555
|
+
message: `step "${step.id}" needs "${dep}", which is a loop body of "${bodyOwner.get(dep)}" \u2014 depend on the loop step "${bodyOwner.get(dep)}" instead.`,
|
|
142556
|
+
path: ["steps"]
|
|
142557
|
+
});
|
|
142558
|
+
}
|
|
142559
|
+
}
|
|
142560
|
+
continue;
|
|
142561
|
+
}
|
|
142562
|
+
for (const dep of step.needs) {
|
|
142563
|
+
if (bodyOwner.has(dep)) {
|
|
142564
|
+
ctx.addIssue({
|
|
142565
|
+
code: z.ZodIssueCode.custom,
|
|
142566
|
+
message: `step "${step.id}" needs "${dep}", which is a loop body of "${bodyOwner.get(dep)}" \u2014 depend on the loop step "${bodyOwner.get(dep)}" instead (loop body steps are owned by their loop and never scheduled in the main DAG).`,
|
|
142567
|
+
path: ["steps"]
|
|
142568
|
+
});
|
|
142569
|
+
}
|
|
142570
|
+
}
|
|
142571
|
+
}
|
|
142031
142572
|
});
|
|
142032
142573
|
function findCycle(steps) {
|
|
142033
142574
|
const byId = new Map(steps.map((s2) => [s2.id, s2]));
|
|
@@ -142064,8 +142605,8 @@ function findCycle(steps) {
|
|
|
142064
142605
|
}
|
|
142065
142606
|
function formatIssues(error2) {
|
|
142066
142607
|
return error2.issues.map((iss) => {
|
|
142067
|
-
const
|
|
142068
|
-
return `${
|
|
142608
|
+
const path61 = iss.path.join(".") || "(root)";
|
|
142609
|
+
return `${path61}: ${iss.message}`;
|
|
142069
142610
|
});
|
|
142070
142611
|
}
|
|
142071
142612
|
function validateWorkflow(raw) {
|
|
@@ -142195,9 +142736,18 @@ var WorkflowStore = class {
|
|
|
142195
142736
|
/**
|
|
142196
142737
|
* Replace a workflow with a new definition. In-place rewrite for user/project
|
|
142197
142738
|
* workflows; a user-scope override for builtin/plugin ones.
|
|
142739
|
+
*
|
|
142740
|
+
* `previousName` supports rename from the builder: when the workflow's name
|
|
142741
|
+
* changed, the old user/project file and its registry entry are removed so a
|
|
142742
|
+
* rename doesn't leave an orphaned duplicate file + stale entry behind.
|
|
142198
142743
|
*/
|
|
142199
|
-
async save(workflow) {
|
|
142744
|
+
async save(workflow, previousName) {
|
|
142200
142745
|
await this.ensureLoaded();
|
|
142746
|
+
const renamed = previousName != null && previousName !== workflow.name ? this.byName.get(previousName) : void 0;
|
|
142747
|
+
if (renamed && (renamed.scope === "user" || renamed.scope === "project")) {
|
|
142748
|
+
await promises.rm(renamed.path, { force: true });
|
|
142749
|
+
this.byName.delete(previousName);
|
|
142750
|
+
}
|
|
142201
142751
|
const existing = this.byName.get(workflow.name);
|
|
142202
142752
|
const editable = existing && (existing.scope === "user" || existing.scope === "project");
|
|
142203
142753
|
if (existing && editable) {
|
|
@@ -142206,11 +142756,12 @@ var WorkflowStore = class {
|
|
|
142206
142756
|
this.byName.set(workflow.name, entry2);
|
|
142207
142757
|
return entry2;
|
|
142208
142758
|
}
|
|
142209
|
-
const
|
|
142759
|
+
const scope = renamed?.scope === "project" ? "project" : "user";
|
|
142760
|
+
const dir = scope === "project" ? this.projectDir() : this.userDir();
|
|
142210
142761
|
await promises.mkdir(dir, { recursive: true });
|
|
142211
142762
|
const file = await uniqueFilename2(dir, workflow.name);
|
|
142212
142763
|
await writeFileAtomic(file, serializeWorkflow(workflow));
|
|
142213
|
-
const entry = { workflow, path: file, scope
|
|
142764
|
+
const entry = { workflow, path: file, scope };
|
|
142214
142765
|
this.byName.set(workflow.name, entry);
|
|
142215
142766
|
return entry;
|
|
142216
142767
|
}
|
|
@@ -142257,8 +142808,176 @@ async function exists3(p3) {
|
|
|
142257
142808
|
return false;
|
|
142258
142809
|
}
|
|
142259
142810
|
}
|
|
142811
|
+
|
|
142812
|
+
// ../plugin-workflows/dist/run-store.js
|
|
142813
|
+
init_index_esm();
|
|
142814
|
+
var WorkflowRunStore = class {
|
|
142815
|
+
dir;
|
|
142816
|
+
constructor(dir = moxxyPath("workflow-runs", "active")) {
|
|
142817
|
+
this.dir = dir;
|
|
142818
|
+
}
|
|
142819
|
+
async save(checkpoint) {
|
|
142820
|
+
const runId = ulid();
|
|
142821
|
+
await promises.mkdir(this.dir, { recursive: true });
|
|
142822
|
+
const file = path3.join(this.dir, `${runId}.json`);
|
|
142823
|
+
const payload = { ...checkpoint, runId };
|
|
142824
|
+
const tmp = `${file}.tmp`;
|
|
142825
|
+
await promises.writeFile(tmp, JSON.stringify(payload), "utf8");
|
|
142826
|
+
await promises.rename(tmp, file);
|
|
142827
|
+
return runId;
|
|
142828
|
+
}
|
|
142829
|
+
async load(runId) {
|
|
142830
|
+
const file = path3.join(this.dir, `${runId}.json`);
|
|
142831
|
+
try {
|
|
142832
|
+
const raw = await promises.readFile(file, "utf8");
|
|
142833
|
+
return JSON.parse(raw);
|
|
142834
|
+
} catch {
|
|
142835
|
+
return null;
|
|
142836
|
+
}
|
|
142837
|
+
}
|
|
142838
|
+
async remove(runId) {
|
|
142839
|
+
const file = path3.join(this.dir, `${runId}.json`);
|
|
142840
|
+
try {
|
|
142841
|
+
await promises.unlink(file);
|
|
142842
|
+
} catch {
|
|
142843
|
+
}
|
|
142844
|
+
}
|
|
142845
|
+
/**
|
|
142846
|
+
* Delete checkpoint files older than `maxAgeMs` (by mtime). Paused runs that
|
|
142847
|
+
* are never resumed (the common case while `awaitInput` is gated — see
|
|
142848
|
+
* schema.ts — and in general after a crash) would otherwise accumulate
|
|
142849
|
+
* `<ulid>.json` files under `active/` forever. Returns the count removed.
|
|
142850
|
+
* Best-effort: a missing dir or an unreadable entry is skipped, not thrown.
|
|
142851
|
+
*/
|
|
142852
|
+
async sweepStale(maxAgeMs = DEFAULT_CHECKPOINT_TTL_MS, now = Date.now()) {
|
|
142853
|
+
let removed = 0;
|
|
142854
|
+
let entries;
|
|
142855
|
+
try {
|
|
142856
|
+
entries = await promises.readdir(this.dir);
|
|
142857
|
+
} catch {
|
|
142858
|
+
return 0;
|
|
142859
|
+
}
|
|
142860
|
+
for (const name of entries) {
|
|
142861
|
+
if (!name.endsWith(".json"))
|
|
142862
|
+
continue;
|
|
142863
|
+
const file = path3.join(this.dir, name);
|
|
142864
|
+
try {
|
|
142865
|
+
const st3 = await promises.stat(file);
|
|
142866
|
+
if (now - st3.mtimeMs > maxAgeMs) {
|
|
142867
|
+
await promises.unlink(file);
|
|
142868
|
+
removed += 1;
|
|
142869
|
+
}
|
|
142870
|
+
} catch {
|
|
142871
|
+
}
|
|
142872
|
+
}
|
|
142873
|
+
return removed;
|
|
142874
|
+
}
|
|
142875
|
+
};
|
|
142876
|
+
var DEFAULT_CHECKPOINT_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
142877
|
+
var defaultWorkflowRunStore = new WorkflowRunStore();
|
|
142878
|
+
|
|
142879
|
+
// ../plugin-workflows/dist/logic-response.js
|
|
142880
|
+
var PLAIN_PROMPT_MARKERS = [
|
|
142881
|
+
"odpowiedz wy\u0142\u0105cznie zwyk\u0142ym tekstem",
|
|
142882
|
+
"odpowiedz tylko zwyk\u0142ym tekstem",
|
|
142883
|
+
"without json",
|
|
142884
|
+
"no json",
|
|
142885
|
+
"plain text only"
|
|
142886
|
+
];
|
|
142887
|
+
var LOGIC_SYSTEM_PROMPT = 'You are a workflow logic step. Do not use tools. Reply with exactly one JSON object. Use keys as needed: "vars" (object, data for downstream templates), "branch" (string, routing decision), "text" (optional human-readable summary). No markdown fences or commentary outside the JSON.';
|
|
142888
|
+
function logicSystemPrompt() {
|
|
142889
|
+
return LOGIC_SYSTEM_PROMPT;
|
|
142890
|
+
}
|
|
142891
|
+
function wantsPlainResponse(step) {
|
|
142892
|
+
if (step.format === "plain")
|
|
142893
|
+
return true;
|
|
142894
|
+
if (step.format === "json")
|
|
142895
|
+
return false;
|
|
142896
|
+
const text = (step.bridge ?? step.condition ?? step.switch ?? "").toLowerCase();
|
|
142897
|
+
return PLAIN_PROMPT_MARKERS.some((m3) => text.includes(m3));
|
|
142898
|
+
}
|
|
142899
|
+
function stripJsonFence(raw) {
|
|
142900
|
+
const trimmed = raw.trim();
|
|
142901
|
+
const fence = /^```(?:json)?\s*([\s\S]*?)```$/i.exec(trimmed);
|
|
142902
|
+
return fence ? fence[1].trim() : trimmed;
|
|
142903
|
+
}
|
|
142904
|
+
function parseJsonObject(raw) {
|
|
142905
|
+
const parsed = JSON.parse(stripJsonFence(raw));
|
|
142906
|
+
if (parsed == null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
142907
|
+
throw new Error("logic step response must be a JSON object");
|
|
142908
|
+
}
|
|
142909
|
+
return parsed;
|
|
142910
|
+
}
|
|
142911
|
+
function parseLogicResponse(raw, _step, format) {
|
|
142912
|
+
if (format === "plain") {
|
|
142913
|
+
return { output: raw.trim() };
|
|
142914
|
+
}
|
|
142915
|
+
const obj = parseJsonObject(raw);
|
|
142916
|
+
const vars = obj.vars != null && typeof obj.vars === "object" && !Array.isArray(obj.vars) ? obj.vars : void 0;
|
|
142917
|
+
const branch = typeof obj.branch === "string" ? obj.branch.trim() : void 0;
|
|
142918
|
+
const text = typeof obj.text === "string" ? obj.text : void 0;
|
|
142919
|
+
const output = text ?? JSON.stringify(obj);
|
|
142920
|
+
return { output, ...vars ? { vars } : {}, ...branch ? { branch } : {} };
|
|
142921
|
+
}
|
|
142922
|
+
function resolveBranchForCondition(_step, branch) {
|
|
142923
|
+
if (!branch)
|
|
142924
|
+
return void 0;
|
|
142925
|
+
const b3 = branch.toLowerCase();
|
|
142926
|
+
if (b3 === "then")
|
|
142927
|
+
return "then";
|
|
142928
|
+
if (b3 === "else")
|
|
142929
|
+
return "else";
|
|
142930
|
+
return void 0;
|
|
142931
|
+
}
|
|
142932
|
+
function resolveBranchForSwitch(step, branch) {
|
|
142933
|
+
if (!branch)
|
|
142934
|
+
return void 0;
|
|
142935
|
+
const cases = step.cases ?? {};
|
|
142936
|
+
if (branch in cases)
|
|
142937
|
+
return branch;
|
|
142938
|
+
if (step.default && step.default.length > 0)
|
|
142939
|
+
return "__default__";
|
|
142940
|
+
return void 0;
|
|
142941
|
+
}
|
|
142942
|
+
function stepsToSkipForBranch(step, selected) {
|
|
142943
|
+
if (step.condition != null) {
|
|
142944
|
+
const then = step.then ?? [];
|
|
142945
|
+
const els = step.else ?? [];
|
|
142946
|
+
const active = selected === "then" ? then : els;
|
|
142947
|
+
const all = [...then, ...els];
|
|
142948
|
+
return all.filter((id) => !active.includes(id));
|
|
142949
|
+
}
|
|
142950
|
+
if (step.switch != null) {
|
|
142951
|
+
const cases = step.cases ?? {};
|
|
142952
|
+
const all = /* @__PURE__ */ new Set();
|
|
142953
|
+
for (const ids of Object.values(cases))
|
|
142954
|
+
for (const id of ids)
|
|
142955
|
+
all.add(id);
|
|
142956
|
+
for (const id of step.default ?? [])
|
|
142957
|
+
all.add(id);
|
|
142958
|
+
if (selected === "__default__") {
|
|
142959
|
+
const keep2 = new Set(step.default ?? []);
|
|
142960
|
+
return [...all].filter((id) => !keep2.has(id));
|
|
142961
|
+
}
|
|
142962
|
+
const keep = new Set(cases[selected] ?? []);
|
|
142963
|
+
return [...all].filter((id) => !keep.has(id));
|
|
142964
|
+
}
|
|
142965
|
+
return [];
|
|
142966
|
+
}
|
|
142967
|
+
|
|
142968
|
+
// ../plugin-workflows/dist/executor/dag.js
|
|
142260
142969
|
var DAG_EXECUTOR_NAME = "dag";
|
|
142261
142970
|
var MAX_NESTING_DEPTH = 5;
|
|
142971
|
+
var FINALIZE_REPLY_SUFFIX = "\n\nFinalize now: consolidate the operator's answers into a clear structured response. Include every field the step instructions require. Do not ask further questions.";
|
|
142972
|
+
function collectLoopBodyIds(workflow) {
|
|
142973
|
+
const ids = /* @__PURE__ */ new Set();
|
|
142974
|
+
for (const step of workflow.steps) {
|
|
142975
|
+
if (step.loop)
|
|
142976
|
+
for (const id of step.loop.body)
|
|
142977
|
+
ids.add(id);
|
|
142978
|
+
}
|
|
142979
|
+
return ids;
|
|
142980
|
+
}
|
|
142262
142981
|
function nowFn(deps) {
|
|
142263
142982
|
return deps.now ?? (() => Date.now());
|
|
142264
142983
|
}
|
|
@@ -142274,27 +142993,100 @@ function resolveInputs(workflow, deps) {
|
|
|
142274
142993
|
}
|
|
142275
142994
|
return out;
|
|
142276
142995
|
}
|
|
142277
|
-
function buildScope(
|
|
142996
|
+
function buildScope(ctx, nowIso) {
|
|
142278
142997
|
const steps = {};
|
|
142279
|
-
for (const [id, st3] of states)
|
|
142998
|
+
for (const [id, st3] of ctx.states)
|
|
142280
142999
|
steps[id] = { output: st3.output };
|
|
142281
143000
|
return {
|
|
142282
143001
|
steps,
|
|
142283
|
-
inputs,
|
|
142284
|
-
|
|
143002
|
+
inputs: ctx.inputs,
|
|
143003
|
+
vars: ctx.vars,
|
|
143004
|
+
...ctx.deps.trigger != null ? { trigger: ctx.deps.trigger } : {},
|
|
142285
143005
|
now: nowIso
|
|
142286
143006
|
};
|
|
142287
143007
|
}
|
|
142288
|
-
|
|
142289
|
-
|
|
142290
|
-
|
|
143008
|
+
var UNSAFE_VAR_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
143009
|
+
function mergeVars(ctx, vars) {
|
|
143010
|
+
if (!vars)
|
|
143011
|
+
return;
|
|
143012
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
143013
|
+
if (UNSAFE_VAR_KEYS.has(key)) {
|
|
143014
|
+
ctx.deps.logger?.warn?.("workflow vars: dropping prototype-pollution key", { key });
|
|
143015
|
+
continue;
|
|
143016
|
+
}
|
|
143017
|
+
Object.defineProperty(ctx.vars, key, {
|
|
143018
|
+
value,
|
|
143019
|
+
writable: true,
|
|
143020
|
+
enumerable: true,
|
|
143021
|
+
configurable: true
|
|
143022
|
+
});
|
|
143023
|
+
}
|
|
143024
|
+
}
|
|
143025
|
+
async function applyBranchSkips(ctx, gate, selected) {
|
|
143026
|
+
for (const id of stepsToSkipForBranch(gate, selected)) {
|
|
143027
|
+
const st3 = ctx.states.get(id);
|
|
143028
|
+
if (!st3 || st3.status !== "pending")
|
|
143029
|
+
continue;
|
|
143030
|
+
st3.status = "skipped";
|
|
143031
|
+
st3.startedAt = st3.endedAt = ctx.now();
|
|
143032
|
+
await ctx.deps.emit?.("workflow_step_skipped", { id, reason: `branch:${gate.id}` });
|
|
143033
|
+
}
|
|
143034
|
+
}
|
|
143035
|
+
function serializeStates(states) {
|
|
143036
|
+
const out = {};
|
|
143037
|
+
for (const [id, st3] of states) {
|
|
143038
|
+
out[id] = {
|
|
143039
|
+
status: st3.status === "pending" ? "pending" : st3.status,
|
|
143040
|
+
output: st3.output,
|
|
143041
|
+
...st3.error ? { error: st3.error } : {},
|
|
143042
|
+
startedAt: st3.startedAt,
|
|
143043
|
+
endedAt: st3.endedAt
|
|
143044
|
+
};
|
|
143045
|
+
}
|
|
143046
|
+
return out;
|
|
143047
|
+
}
|
|
143048
|
+
function restoreStates(raw) {
|
|
142291
143049
|
const states = /* @__PURE__ */ new Map();
|
|
142292
|
-
for (const
|
|
142293
|
-
states.set(
|
|
143050
|
+
for (const [id, st3] of Object.entries(raw)) {
|
|
143051
|
+
states.set(id, {
|
|
143052
|
+
status: st3.status,
|
|
143053
|
+
output: st3.output,
|
|
143054
|
+
...st3.error ? { error: st3.error } : {},
|
|
143055
|
+
startedAt: st3.startedAt,
|
|
143056
|
+
endedAt: st3.endedAt
|
|
143057
|
+
});
|
|
142294
143058
|
}
|
|
143059
|
+
return states;
|
|
143060
|
+
}
|
|
143061
|
+
function buildStepResults(workflow, states) {
|
|
143062
|
+
return workflow.steps.map((step) => {
|
|
143063
|
+
const st3 = states.get(step.id);
|
|
143064
|
+
const status = st3.status === "pending" ? "skipped" : st3.status;
|
|
143065
|
+
return {
|
|
143066
|
+
id: step.id,
|
|
143067
|
+
status,
|
|
143068
|
+
output: st3.output,
|
|
143069
|
+
...st3.error ? { error: st3.error } : {},
|
|
143070
|
+
startedAt: st3.startedAt,
|
|
143071
|
+
endedAt: st3.endedAt
|
|
143072
|
+
};
|
|
143073
|
+
});
|
|
143074
|
+
}
|
|
143075
|
+
function buildRunResult(ctx, status, ok, extra) {
|
|
143076
|
+
const output = status === "completed" ? sinkOutput(ctx.workflow, ctx.states) : "";
|
|
143077
|
+
return {
|
|
143078
|
+
ok,
|
|
143079
|
+
status,
|
|
143080
|
+
steps: buildStepResults(ctx.workflow, ctx.states),
|
|
143081
|
+
output,
|
|
143082
|
+
...extra
|
|
143083
|
+
};
|
|
143084
|
+
}
|
|
143085
|
+
async function runExecutorLoop(ctx) {
|
|
143086
|
+
const { workflow, deps } = ctx;
|
|
142295
143087
|
await deps.emit?.("workflow_started", { name: workflow.name, steps: workflow.steps.length });
|
|
142296
143088
|
const settled = (id) => {
|
|
142297
|
-
const s2 = states.get(id)?.status;
|
|
143089
|
+
const s2 = ctx.states.get(id)?.status;
|
|
142298
143090
|
return s2 === "completed" || s2 === "skipped" || s2 === "failed";
|
|
142299
143091
|
};
|
|
142300
143092
|
let aborted = false;
|
|
@@ -142308,21 +143100,23 @@ async function runExecutor(workflow, deps) {
|
|
|
142308
143100
|
while (skippedSomething) {
|
|
142309
143101
|
skippedSomething = false;
|
|
142310
143102
|
for (const step of workflow.steps) {
|
|
142311
|
-
|
|
143103
|
+
if (ctx.loopBodyIds.has(step.id))
|
|
143104
|
+
continue;
|
|
143105
|
+
const st3 = ctx.states.get(step.id);
|
|
142312
143106
|
if (st3.status !== "pending")
|
|
142313
143107
|
continue;
|
|
142314
143108
|
if (!step.needs.every(settled))
|
|
142315
143109
|
continue;
|
|
142316
143110
|
if (step.when == null)
|
|
142317
143111
|
continue;
|
|
142318
|
-
const scope2 = buildScope(
|
|
143112
|
+
const scope2 = buildScope(ctx, new Date(ctx.now()).toISOString());
|
|
142319
143113
|
let keep;
|
|
142320
143114
|
try {
|
|
142321
143115
|
keep = evalCondition(step.when, scope2);
|
|
142322
143116
|
} catch (err) {
|
|
142323
143117
|
st3.status = "failed";
|
|
142324
143118
|
st3.error = `when: ${err instanceof Error ? err.message : String(err)}`;
|
|
142325
|
-
st3.startedAt = st3.endedAt = now();
|
|
143119
|
+
st3.startedAt = st3.endedAt = ctx.now();
|
|
142326
143120
|
await deps.emit?.("workflow_step_failed", { id: step.id, error: st3.error });
|
|
142327
143121
|
if (step.onError !== "continue") {
|
|
142328
143122
|
aborted = true;
|
|
@@ -142333,7 +143127,7 @@ async function runExecutor(workflow, deps) {
|
|
|
142333
143127
|
}
|
|
142334
143128
|
if (!keep) {
|
|
142335
143129
|
st3.status = "skipped";
|
|
142336
|
-
st3.startedAt = st3.endedAt = now();
|
|
143130
|
+
st3.startedAt = st3.endedAt = ctx.now();
|
|
142337
143131
|
await deps.emit?.("workflow_step_skipped", { id: step.id });
|
|
142338
143132
|
skippedSomething = true;
|
|
142339
143133
|
}
|
|
@@ -142344,11 +143138,13 @@ async function runExecutor(workflow, deps) {
|
|
|
142344
143138
|
if (aborted)
|
|
142345
143139
|
break;
|
|
142346
143140
|
const ready = workflow.steps.filter((step) => {
|
|
142347
|
-
|
|
143141
|
+
if (ctx.loopBodyIds.has(step.id))
|
|
143142
|
+
return false;
|
|
143143
|
+
const st3 = ctx.states.get(step.id);
|
|
142348
143144
|
return st3.status === "pending" && step.needs.every(settled);
|
|
142349
143145
|
});
|
|
142350
143146
|
if (ready.length === 0) {
|
|
142351
|
-
const anyPending = [...states.values()].some((s2) => s2.status === "pending");
|
|
143147
|
+
const anyPending = [...ctx.states.values()].some((s2) => s2.status === "pending");
|
|
142352
143148
|
if (anyPending) {
|
|
142353
143149
|
abortReason = "workflow stalled \u2014 no runnable steps (check needs/when)";
|
|
142354
143150
|
aborted = true;
|
|
@@ -142356,19 +143152,62 @@ async function runExecutor(workflow, deps) {
|
|
|
142356
143152
|
break;
|
|
142357
143153
|
}
|
|
142358
143154
|
const wave = ready.slice(0, Math.max(1, workflow.concurrency));
|
|
142359
|
-
const scope = buildScope(
|
|
142360
|
-
|
|
142361
|
-
const st3 = states.get(step.id);
|
|
142362
|
-
st3.startedAt = now();
|
|
143155
|
+
const scope = buildScope(ctx, new Date(ctx.now()).toISOString());
|
|
143156
|
+
for (const step of wave) {
|
|
143157
|
+
const st3 = ctx.states.get(step.id);
|
|
143158
|
+
st3.startedAt = ctx.now();
|
|
142363
143159
|
await deps.emit?.("workflow_step_started", {
|
|
142364
143160
|
id: step.id,
|
|
142365
143161
|
label: step.label ?? step.id
|
|
142366
143162
|
});
|
|
142367
|
-
const outcome = await runStep(step, scope,
|
|
142368
|
-
st3.endedAt = now();
|
|
143163
|
+
const outcome = await runStep(step, scope, ctx);
|
|
143164
|
+
st3.endedAt = ctx.now();
|
|
143165
|
+
if (outcome.paused) {
|
|
143166
|
+
st3.status = "awaiting_input";
|
|
143167
|
+
st3.output = outcome.output;
|
|
143168
|
+
await deps.emit?.("workflow_step_awaiting_input", {
|
|
143169
|
+
id: step.id,
|
|
143170
|
+
label: step.label ?? step.id,
|
|
143171
|
+
preview: outcome.output.slice(0, 280),
|
|
143172
|
+
childSessionId: outcome.interactionAgentId
|
|
143173
|
+
});
|
|
143174
|
+
const store = deps.runStore ?? defaultWorkflowRunStore;
|
|
143175
|
+
const runId = await store.save({
|
|
143176
|
+
workflow,
|
|
143177
|
+
trigger: deps.trigger ?? "manual",
|
|
143178
|
+
inputs: ctx.inputs,
|
|
143179
|
+
states: serializeStates(ctx.states),
|
|
143180
|
+
// Persist vars set by logic steps that ran before this pause so a
|
|
143181
|
+
// resume restores them (otherwise downstream `{{ vars.x }}` is lost).
|
|
143182
|
+
vars: ctx.vars,
|
|
143183
|
+
pendingStepId: step.id,
|
|
143184
|
+
interactionAgentId: outcome.interactionAgentId,
|
|
143185
|
+
startedAt: ctx.now()
|
|
143186
|
+
});
|
|
143187
|
+
await deps.emit?.("workflow_paused", {
|
|
143188
|
+
runId,
|
|
143189
|
+
stepId: step.id,
|
|
143190
|
+
childSessionId: outcome.interactionAgentId,
|
|
143191
|
+
// Carry the human-facing question so the operator UI is self-contained
|
|
143192
|
+
// (no separate event correlation needed): the workflow name, the step
|
|
143193
|
+
// label, and the prompt/question the paused step asked.
|
|
143194
|
+
workflow: workflow.name,
|
|
143195
|
+
label: step.label ?? step.id,
|
|
143196
|
+
prompt: outcome.output.slice(0, 2e3)
|
|
143197
|
+
});
|
|
143198
|
+
return buildRunResult(ctx, "paused", true, {
|
|
143199
|
+
runId,
|
|
143200
|
+
pendingStepId: step.id,
|
|
143201
|
+
...outcome.interactionAgentId ? { interactionAgentId: outcome.interactionAgentId } : {}
|
|
143202
|
+
});
|
|
143203
|
+
}
|
|
142369
143204
|
if (outcome.ok) {
|
|
142370
143205
|
st3.status = "completed";
|
|
142371
143206
|
st3.output = outcome.output;
|
|
143207
|
+
mergeVars(ctx, outcome.vars);
|
|
143208
|
+
if (outcome.branchRoute != null) {
|
|
143209
|
+
await applyBranchSkips(ctx, step, outcome.branchRoute);
|
|
143210
|
+
}
|
|
142372
143211
|
await deps.emit?.("workflow_step_completed", {
|
|
142373
143212
|
id: step.id,
|
|
142374
143213
|
preview: outcome.output.slice(0, 280)
|
|
@@ -142382,32 +143221,106 @@ async function runExecutor(workflow, deps) {
|
|
|
142382
143221
|
abortReason = `step "${step.id}" failed: ${outcome.error}`;
|
|
142383
143222
|
}
|
|
142384
143223
|
}
|
|
142385
|
-
}
|
|
143224
|
+
}
|
|
142386
143225
|
}
|
|
142387
|
-
const stepResults = workflow.steps.map((step) => {
|
|
142388
|
-
const st3 = states.get(step.id);
|
|
142389
|
-
return {
|
|
142390
|
-
id: step.id,
|
|
142391
|
-
status: st3.status === "pending" ? "skipped" : st3.status,
|
|
142392
|
-
output: st3.output,
|
|
142393
|
-
...st3.error ? { error: st3.error } : {},
|
|
142394
|
-
startedAt: st3.startedAt,
|
|
142395
|
-
endedAt: st3.endedAt
|
|
142396
|
-
};
|
|
142397
|
-
});
|
|
142398
143226
|
const ok = !aborted;
|
|
142399
|
-
const output = sinkOutput(workflow, states);
|
|
143227
|
+
const output = sinkOutput(workflow, ctx.states);
|
|
142400
143228
|
if (ok) {
|
|
142401
143229
|
await deps.emit?.("workflow_completed", { name: workflow.name, output: output.slice(0, 280) });
|
|
142402
|
-
|
|
142403
|
-
await deps.emit?.("workflow_failed", { name: workflow.name, error: abortReason });
|
|
143230
|
+
return buildRunResult(ctx, "completed", true, { output });
|
|
142404
143231
|
}
|
|
142405
|
-
|
|
142406
|
-
|
|
142407
|
-
steps: stepResults,
|
|
143232
|
+
await deps.emit?.("workflow_failed", { name: workflow.name, error: abortReason });
|
|
143233
|
+
return buildRunResult(ctx, "failed", false, {
|
|
142408
143234
|
output,
|
|
142409
|
-
|
|
143235
|
+
error: abortReason ?? "workflow failed"
|
|
143236
|
+
});
|
|
143237
|
+
}
|
|
143238
|
+
async function runExecutor(workflow, deps) {
|
|
143239
|
+
const ctx = {
|
|
143240
|
+
workflow,
|
|
143241
|
+
deps,
|
|
143242
|
+
inputs: resolveInputs(workflow, deps),
|
|
143243
|
+
vars: {},
|
|
143244
|
+
states: /* @__PURE__ */ new Map(),
|
|
143245
|
+
now: nowFn(deps),
|
|
143246
|
+
loopBodyIds: collectLoopBodyIds(workflow)
|
|
142410
143247
|
};
|
|
143248
|
+
for (const step of workflow.steps) {
|
|
143249
|
+
ctx.states.set(step.id, { status: "pending", output: "", startedAt: 0, endedAt: 0 });
|
|
143250
|
+
}
|
|
143251
|
+
return runExecutorLoop(ctx);
|
|
143252
|
+
}
|
|
143253
|
+
async function resumeWorkflowRun(runId, userMessage, deps, store = defaultWorkflowRunStore) {
|
|
143254
|
+
const checkpoint = await store.load(runId);
|
|
143255
|
+
if (!checkpoint) {
|
|
143256
|
+
return {
|
|
143257
|
+
ok: false,
|
|
143258
|
+
status: "failed",
|
|
143259
|
+
steps: [],
|
|
143260
|
+
output: "",
|
|
143261
|
+
error: `no paused workflow run "${runId}"`
|
|
143262
|
+
};
|
|
143263
|
+
}
|
|
143264
|
+
const depsWithStore = { ...deps, runStore: store };
|
|
143265
|
+
const step = checkpoint.workflow.steps.find((s2) => s2.id === checkpoint.pendingStepId);
|
|
143266
|
+
if (!step) {
|
|
143267
|
+
return {
|
|
143268
|
+
ok: false,
|
|
143269
|
+
status: "failed",
|
|
143270
|
+
steps: buildStepResults(checkpoint.workflow, restoreStates(checkpoint.states)),
|
|
143271
|
+
output: "",
|
|
143272
|
+
error: `paused step "${checkpoint.pendingStepId}" not found`
|
|
143273
|
+
};
|
|
143274
|
+
}
|
|
143275
|
+
const restoredVars = {};
|
|
143276
|
+
const ctx = {
|
|
143277
|
+
workflow: checkpoint.workflow,
|
|
143278
|
+
deps: depsWithStore,
|
|
143279
|
+
inputs: checkpoint.inputs,
|
|
143280
|
+
vars: restoredVars,
|
|
143281
|
+
states: restoreStates(checkpoint.states),
|
|
143282
|
+
now: nowFn(deps),
|
|
143283
|
+
loopBodyIds: collectLoopBodyIds(checkpoint.workflow)
|
|
143284
|
+
};
|
|
143285
|
+
mergeVars(ctx, checkpoint.vars);
|
|
143286
|
+
const st3 = ctx.states.get(step.id);
|
|
143287
|
+
await deps.emit?.("workflow_resumed", { runId, stepId: step.id });
|
|
143288
|
+
if (typeof deps.spawner.continue !== "function") {
|
|
143289
|
+
st3.status = "failed";
|
|
143290
|
+
st3.error = "subagent spawner does not support resume (continue)";
|
|
143291
|
+
st3.endedAt = ctx.now();
|
|
143292
|
+
await deps.emit?.("workflow_step_failed", { id: step.id, error: st3.error });
|
|
143293
|
+
await store.remove(runId);
|
|
143294
|
+
return buildRunResult(ctx, "failed", false, { error: st3.error });
|
|
143295
|
+
}
|
|
143296
|
+
const finalizePrompt = `Operator reply:
|
|
143297
|
+
${userMessage.trim()}${FINALIZE_REPLY_SUFFIX}`;
|
|
143298
|
+
try {
|
|
143299
|
+
const child = await deps.spawner.continue({
|
|
143300
|
+
childSessionId: checkpoint.interactionAgentId,
|
|
143301
|
+
prompt: finalizePrompt,
|
|
143302
|
+
label: step.label ?? step.id
|
|
143303
|
+
});
|
|
143304
|
+
if (child.error)
|
|
143305
|
+
throw new Error(child.error.message);
|
|
143306
|
+
st3.status = "completed";
|
|
143307
|
+
st3.output = child.text;
|
|
143308
|
+
st3.endedAt = ctx.now();
|
|
143309
|
+
await deps.emit?.("workflow_step_completed", {
|
|
143310
|
+
id: step.id,
|
|
143311
|
+
preview: child.text.slice(0, 280)
|
|
143312
|
+
});
|
|
143313
|
+
} catch (err) {
|
|
143314
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
143315
|
+
st3.status = "failed";
|
|
143316
|
+
st3.error = message;
|
|
143317
|
+
st3.endedAt = ctx.now();
|
|
143318
|
+
await deps.emit?.("workflow_step_failed", { id: step.id, error: message });
|
|
143319
|
+
await store.remove(runId);
|
|
143320
|
+
return buildRunResult(ctx, "failed", false, { error: message });
|
|
143321
|
+
}
|
|
143322
|
+
await store.remove(runId);
|
|
143323
|
+
return runExecutorLoop(ctx);
|
|
142411
143324
|
}
|
|
142412
143325
|
function sinkOutput(workflow, states) {
|
|
142413
143326
|
const needed = /* @__PURE__ */ new Set();
|
|
@@ -142421,18 +143334,17 @@ function sinkOutput(workflow, states) {
|
|
|
142421
143334
|
const lastCompleted = [...states.values()].filter((s2) => s2.status === "completed").pop();
|
|
142422
143335
|
return lastCompleted?.output ?? "";
|
|
142423
143336
|
}
|
|
142424
|
-
async function runStep(step, scope,
|
|
143337
|
+
async function runStep(step, scope, ctx) {
|
|
142425
143338
|
const attempts = 1 + Math.max(0, step.retries);
|
|
142426
143339
|
let lastError = "";
|
|
142427
143340
|
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
142428
|
-
if (deps.signal.aborted)
|
|
143341
|
+
if (ctx.deps.signal.aborted)
|
|
142429
143342
|
return { ok: false, output: "", error: "aborted" };
|
|
142430
143343
|
try {
|
|
142431
|
-
|
|
142432
|
-
return { ok: true, output };
|
|
143344
|
+
return await runStepOnce(step, scope, ctx);
|
|
142433
143345
|
} catch (err) {
|
|
142434
143346
|
lastError = err instanceof Error ? err.message : String(err);
|
|
142435
|
-
deps.logger?.warn?.("workflow step attempt failed", {
|
|
143347
|
+
ctx.deps.logger?.warn?.("workflow step attempt failed", {
|
|
142436
143348
|
step: step.id,
|
|
142437
143349
|
attempt: attempt + 1,
|
|
142438
143350
|
error: lastError
|
|
@@ -142441,39 +143353,237 @@ async function runStep(step, scope, deps) {
|
|
|
142441
143353
|
}
|
|
142442
143354
|
return { ok: false, output: "", error: lastError };
|
|
142443
143355
|
}
|
|
142444
|
-
async function runStepOnce(step, scope,
|
|
143356
|
+
async function runStepOnce(step, scope, ctx) {
|
|
143357
|
+
const { deps } = ctx;
|
|
142445
143358
|
const opts = deps.logger ? { logger: deps.logger } : {};
|
|
143359
|
+
if (step.loop != null) {
|
|
143360
|
+
return runLoopStep(step, ctx, opts);
|
|
143361
|
+
}
|
|
143362
|
+
if (step.bridge != null || step.condition != null || step.switch != null) {
|
|
143363
|
+
return runLogicStep(step, scope, ctx, opts);
|
|
143364
|
+
}
|
|
142446
143365
|
if (step.tool) {
|
|
142447
143366
|
const args = renderArgs(step.args ?? {}, scope, opts);
|
|
142448
143367
|
const result = await deps.tools.execute(step.tool, args, deps.signal);
|
|
142449
|
-
|
|
143368
|
+
const output = typeof result === "string" ? result : JSON.stringify(result ?? "");
|
|
143369
|
+
return { ok: true, output };
|
|
142450
143370
|
}
|
|
142451
143371
|
if (step.workflow) {
|
|
142452
|
-
|
|
142453
|
-
|
|
142454
|
-
|
|
142455
|
-
|
|
142456
|
-
|
|
142457
|
-
|
|
142458
|
-
|
|
142459
|
-
|
|
142460
|
-
|
|
142461
|
-
|
|
142462
|
-
|
|
142463
|
-
|
|
142464
|
-
|
|
142465
|
-
|
|
142466
|
-
if (!result.ok)
|
|
142467
|
-
throw new Error(result.error ?? `nested workflow "${step.workflow}" failed`);
|
|
142468
|
-
return result.output;
|
|
142469
|
-
}
|
|
142470
|
-
const spec = buildSubagentSpec(step, scope, deps, opts);
|
|
143372
|
+
return runNestedWorkflow(step, scope, ctx, opts);
|
|
143373
|
+
}
|
|
143374
|
+
const spec = buildSubagentSpecWithDeps(step, scope, deps, opts);
|
|
143375
|
+
if (step.awaitInput) {
|
|
143376
|
+
const child2 = await deps.spawner.spawn({ ...spec, retainSession: true });
|
|
143377
|
+
if (child2.error)
|
|
143378
|
+
throw new Error(child2.error.message);
|
|
143379
|
+
return {
|
|
143380
|
+
ok: false,
|
|
143381
|
+
output: child2.text,
|
|
143382
|
+
paused: true,
|
|
143383
|
+
interactionAgentId: String(child2.childSessionId)
|
|
143384
|
+
};
|
|
143385
|
+
}
|
|
142471
143386
|
const child = await deps.spawner.spawn(spec);
|
|
142472
143387
|
if (child.error)
|
|
142473
143388
|
throw new Error(child.error.message);
|
|
142474
|
-
return child.text;
|
|
143389
|
+
return { ok: true, output: child.text };
|
|
143390
|
+
}
|
|
143391
|
+
async function runNestedWorkflow(step, scope, ctx, opts) {
|
|
143392
|
+
const { deps } = ctx;
|
|
143393
|
+
const nested = deps.lookup.workflow(step.workflow);
|
|
143394
|
+
if (!nested)
|
|
143395
|
+
throw new Error(`nested workflow "${step.workflow}" not found`);
|
|
143396
|
+
const depth = (deps.depth ?? 0) + 1;
|
|
143397
|
+
if (depth > MAX_NESTING_DEPTH) {
|
|
143398
|
+
throw new Error(`nested workflow depth exceeded ${MAX_NESTING_DEPTH}`);
|
|
143399
|
+
}
|
|
143400
|
+
const nestedInputs = renderArgs(step.args ?? {}, scope, opts);
|
|
143401
|
+
const result = await runExecutor(nested, {
|
|
143402
|
+
...deps,
|
|
143403
|
+
inputs: nestedInputs,
|
|
143404
|
+
depth,
|
|
143405
|
+
trigger: `workflow:${step.workflow}`
|
|
143406
|
+
});
|
|
143407
|
+
if (result.status === "paused") {
|
|
143408
|
+
return {
|
|
143409
|
+
ok: false,
|
|
143410
|
+
output: result.output,
|
|
143411
|
+
paused: true,
|
|
143412
|
+
...result.interactionAgentId ? { interactionAgentId: result.interactionAgentId } : {}
|
|
143413
|
+
};
|
|
143414
|
+
}
|
|
143415
|
+
if (!result.ok)
|
|
143416
|
+
throw new Error(result.error ?? `nested workflow "${step.workflow}" failed`);
|
|
143417
|
+
return { ok: true, output: result.output };
|
|
143418
|
+
}
|
|
143419
|
+
function buildUpstreamBlock(step, scope) {
|
|
143420
|
+
if (step.needs.length === 0)
|
|
143421
|
+
return "";
|
|
143422
|
+
const parts = step.needs.map((id) => `### ${id}
|
|
143423
|
+
${scope.steps?.[id]?.output ?? ""}`);
|
|
143424
|
+
return `
|
|
143425
|
+
|
|
143426
|
+
## Upstream
|
|
143427
|
+
${parts.join("\n\n")}`;
|
|
143428
|
+
}
|
|
143429
|
+
async function runLogicStep(step, scope, ctx, opts) {
|
|
143430
|
+
const instruction = step.bridge ?? step.condition ?? step.switch ?? "";
|
|
143431
|
+
const format = wantsPlainResponse(step) ? "plain" : "json";
|
|
143432
|
+
if ((step.condition != null || step.switch != null) && format === "plain") {
|
|
143433
|
+
return { ok: false, output: "", error: "condition/switch steps require JSON responses" };
|
|
143434
|
+
}
|
|
143435
|
+
const userPrompt = renderTemplate(instruction, scope, opts) + buildUpstreamBlock(step, scope);
|
|
143436
|
+
const spec = {
|
|
143437
|
+
prompt: userPrompt,
|
|
143438
|
+
...format === "json" ? { systemPrompt: logicSystemPrompt() } : {},
|
|
143439
|
+
label: step.label ?? step.id,
|
|
143440
|
+
allowedTools: []
|
|
143441
|
+
};
|
|
143442
|
+
const child = await ctx.deps.spawner.spawn(spec);
|
|
143443
|
+
if (child.error)
|
|
143444
|
+
return { ok: false, output: "", error: child.error.message };
|
|
143445
|
+
try {
|
|
143446
|
+
const parsed = parseLogicResponse(child.text, step, format);
|
|
143447
|
+
let branchRoute;
|
|
143448
|
+
if (step.condition != null) {
|
|
143449
|
+
const route = resolveBranchForCondition(step, parsed.branch);
|
|
143450
|
+
if (!route) {
|
|
143451
|
+
return {
|
|
143452
|
+
ok: false,
|
|
143453
|
+
output: child.text,
|
|
143454
|
+
error: `condition step "${step.id}": expected branch "then" or "else", got ${JSON.stringify(parsed.branch)}`
|
|
143455
|
+
};
|
|
143456
|
+
}
|
|
143457
|
+
branchRoute = route;
|
|
143458
|
+
}
|
|
143459
|
+
if (step.switch != null) {
|
|
143460
|
+
const route = resolveBranchForSwitch(step, parsed.branch);
|
|
143461
|
+
if (!route) {
|
|
143462
|
+
return {
|
|
143463
|
+
ok: false,
|
|
143464
|
+
output: child.text,
|
|
143465
|
+
error: `switch step "${step.id}": unknown branch ${JSON.stringify(parsed.branch)}`
|
|
143466
|
+
};
|
|
143467
|
+
}
|
|
143468
|
+
branchRoute = route;
|
|
143469
|
+
}
|
|
143470
|
+
return {
|
|
143471
|
+
ok: true,
|
|
143472
|
+
output: parsed.output,
|
|
143473
|
+
...parsed.vars ? { vars: parsed.vars } : {},
|
|
143474
|
+
...branchRoute != null ? { branchRoute } : {}
|
|
143475
|
+
};
|
|
143476
|
+
} catch (err) {
|
|
143477
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
143478
|
+
return { ok: false, output: child.text, error: message };
|
|
143479
|
+
}
|
|
143480
|
+
}
|
|
143481
|
+
async function runLoopStep(step, ctx, opts) {
|
|
143482
|
+
const loop = step.loop;
|
|
143483
|
+
const max = loop.maxIterations;
|
|
143484
|
+
const bodySteps = loop.body.map((id) => ctx.workflow.steps.find((s2) => s2.id === id)).filter((s2) => s2 != null);
|
|
143485
|
+
let iteration = 0;
|
|
143486
|
+
let lastBodyOutput = "";
|
|
143487
|
+
for (; iteration < max; iteration++) {
|
|
143488
|
+
await ctx.deps.emit?.("workflow_step_started", {
|
|
143489
|
+
id: step.id,
|
|
143490
|
+
label: `${step.label ?? step.id} (iteration ${iteration + 1})`
|
|
143491
|
+
});
|
|
143492
|
+
for (const body of bodySteps) {
|
|
143493
|
+
const bst = ctx.states.get(body.id);
|
|
143494
|
+
bst.status = "pending";
|
|
143495
|
+
bst.output = "";
|
|
143496
|
+
delete bst.error;
|
|
143497
|
+
}
|
|
143498
|
+
for (const body of bodySteps) {
|
|
143499
|
+
if (ctx.deps.signal.aborted)
|
|
143500
|
+
return { ok: false, output: lastBodyOutput, error: "aborted" };
|
|
143501
|
+
const bodyScope = buildScope(ctx, new Date(ctx.now()).toISOString());
|
|
143502
|
+
const bst = ctx.states.get(body.id);
|
|
143503
|
+
bst.startedAt = ctx.now();
|
|
143504
|
+
const outcome = await runStep(body, bodyScope, ctx);
|
|
143505
|
+
bst.endedAt = ctx.now();
|
|
143506
|
+
if (outcome.paused) {
|
|
143507
|
+
return {
|
|
143508
|
+
ok: false,
|
|
143509
|
+
output: lastBodyOutput,
|
|
143510
|
+
error: `loop "${step.id}": body step "${body.id}" cannot pause for input`
|
|
143511
|
+
};
|
|
143512
|
+
}
|
|
143513
|
+
if (outcome.ok) {
|
|
143514
|
+
bst.status = "completed";
|
|
143515
|
+
bst.output = outcome.output;
|
|
143516
|
+
lastBodyOutput = outcome.output;
|
|
143517
|
+
mergeVars(ctx, outcome.vars);
|
|
143518
|
+
} else {
|
|
143519
|
+
bst.status = "failed";
|
|
143520
|
+
bst.error = outcome.error;
|
|
143521
|
+
if (body.onError !== "continue") {
|
|
143522
|
+
ctx.deps.logger?.warn?.("workflow loop broke on body error", {
|
|
143523
|
+
step: step.id,
|
|
143524
|
+
body: body.id,
|
|
143525
|
+
error: outcome.error
|
|
143526
|
+
});
|
|
143527
|
+
return {
|
|
143528
|
+
ok: true,
|
|
143529
|
+
output: `loop "${step.id}" broke on error in body step "${body.id}" after ${iteration + 1} iteration(s): ${outcome.error}` + (lastBodyOutput ? `
|
|
143530
|
+
|
|
143531
|
+
${lastBodyOutput}` : "")
|
|
143532
|
+
};
|
|
143533
|
+
}
|
|
143534
|
+
}
|
|
143535
|
+
}
|
|
143536
|
+
const decision = await evaluateLoopCondition(step, loop.condition, ctx, opts);
|
|
143537
|
+
if (!decision.ok) {
|
|
143538
|
+
return { ok: false, output: lastBodyOutput, error: decision.error };
|
|
143539
|
+
}
|
|
143540
|
+
if (decision.route === "then") {
|
|
143541
|
+
return {
|
|
143542
|
+
ok: true,
|
|
143543
|
+
output: `loop "${step.id}" stopped after ${iteration + 1} iteration(s).
|
|
143544
|
+
|
|
143545
|
+
${lastBodyOutput}`.trim()
|
|
143546
|
+
};
|
|
143547
|
+
}
|
|
143548
|
+
}
|
|
143549
|
+
ctx.deps.logger?.warn?.("workflow loop hit max iterations", { step: step.id, maxIterations: max });
|
|
143550
|
+
return {
|
|
143551
|
+
ok: true,
|
|
143552
|
+
output: `loop "${step.id}" reached max iterations (${max}); stopping.` + (lastBodyOutput ? `
|
|
143553
|
+
|
|
143554
|
+
${lastBodyOutput}` : "")
|
|
143555
|
+
};
|
|
142475
143556
|
}
|
|
142476
|
-
function
|
|
143557
|
+
async function evaluateLoopCondition(step, condition, ctx, opts) {
|
|
143558
|
+
const scope = buildScope(ctx, new Date(ctx.now()).toISOString());
|
|
143559
|
+
const userPrompt = renderTemplate(condition, scope, opts) + `
|
|
143560
|
+
|
|
143561
|
+
This is the loop's EXIT condition. Evaluate whether it is now met. Reply with {"branch":"then"} if the condition IS met (stop the loop and continue to the next step), or {"branch":"else"} if it is NOT yet met (run another iteration).`;
|
|
143562
|
+
const spec = {
|
|
143563
|
+
prompt: userPrompt,
|
|
143564
|
+
systemPrompt: logicSystemPrompt(),
|
|
143565
|
+
label: `${step.label ?? step.id} (condition)`,
|
|
143566
|
+
allowedTools: []
|
|
143567
|
+
};
|
|
143568
|
+
const child = await ctx.deps.spawner.spawn(spec);
|
|
143569
|
+
if (child.error)
|
|
143570
|
+
return { ok: false, error: child.error.message };
|
|
143571
|
+
try {
|
|
143572
|
+
const parsed = parseLogicResponse(child.text, step, "json");
|
|
143573
|
+
const route = resolveBranchForCondition(step, parsed.branch);
|
|
143574
|
+
if (!route) {
|
|
143575
|
+
return {
|
|
143576
|
+
ok: false,
|
|
143577
|
+
error: `loop "${step.id}" condition: expected branch "then" or "else", got ${JSON.stringify(parsed.branch)}`
|
|
143578
|
+
};
|
|
143579
|
+
}
|
|
143580
|
+
mergeVars(ctx, parsed.vars);
|
|
143581
|
+
return { ok: true, route };
|
|
143582
|
+
} catch (err) {
|
|
143583
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
143584
|
+
}
|
|
143585
|
+
}
|
|
143586
|
+
function buildSubagentSpecWithDeps(step, scope, deps, opts) {
|
|
142477
143587
|
const label3 = step.label ?? step.id;
|
|
142478
143588
|
const renderedInput = step.input ? renderTemplate(step.input, scope, opts) : "";
|
|
142479
143589
|
if (step.skill) {
|
|
@@ -142536,33 +143646,192 @@ async function writeRunRecord(workflow, result, startedAt, executorName, deps, d
|
|
|
142536
143646
|
}
|
|
142537
143647
|
|
|
142538
143648
|
// ../plugin-workflows/dist/draft.js
|
|
143649
|
+
var DEFAULT_MAX_TOKENS = 4096;
|
|
142539
143650
|
function buildSystemPrompt(opts) {
|
|
142540
|
-
const skills = opts.availableSkills
|
|
142541
|
-
const tools = opts.availableTools
|
|
142542
|
-
return `You are a workflow author for the "moxxy" agent. Output ONLY a YAML document (optionally inside a \`\`\`yaml fence) \u2014 no prose.
|
|
143651
|
+
const skills = formatCatalog(opts.availableSkills, "(none registered \u2014 use `prompt` steps with clear instructions)");
|
|
143652
|
+
const tools = formatCatalog(opts.availableTools, "(none \u2014 use `delivery: { channel: inbox }` for notifications)");
|
|
143653
|
+
return `You are a workflow author for the "moxxy" agent. Output ONLY a YAML document (optionally inside a \`\`\`yaml fence) \u2014 no prose before or after.
|
|
142543
143654
|
|
|
142544
143655
|
A workflow is a DAG of steps. Schema:
|
|
142545
143656
|
- name: kebab-case slug (lowercase letters/numbers/hyphens, starts with a letter)
|
|
142546
|
-
- description: one sentence
|
|
143657
|
+
- description: one clear sentence matching the user's goal (never "A simple Moxxy workflow.")
|
|
143658
|
+
- enabled: true
|
|
142547
143659
|
- on (optional triggers): { schedule: { cron: "m h dom mon dow", timeZone? }, afterWorkflow?, fileChanged?, webhook? }
|
|
142548
|
-
- inputs (optional): { <name>: { default: <value>, description
|
|
143660
|
+
- inputs (optional): { <name>: { default: <value>, description: "..." } } \u2014 use for values the operator supplies at run time (e.g. recipient email, image brief)
|
|
142549
143661
|
- delivery (optional): { channel?: "inbox", inbox?: true }
|
|
142550
143662
|
- steps: array of steps, each with:
|
|
142551
143663
|
- id: slug, unique
|
|
142552
|
-
-
|
|
142553
|
-
-
|
|
143664
|
+
- label: short human title (match the user's language when possible)
|
|
143665
|
+
- EXACTLY ONE action: skill | prompt | tool | workflow | bridge | condition | switch | loop
|
|
143666
|
+
- bridge: instruction \u2014 logic step; agent returns JSON with vars (extract/transform data); optional format: plain
|
|
143667
|
+
- condition: instruction + then: [step ids] + else: [step ids] \u2014 agent returns JSON branch then|else
|
|
143668
|
+
- switch: instruction + cases: { <caseId>: [step ids], ... } + optional default: [step ids] \u2014 agent returns JSON branch matching a case id
|
|
143669
|
+
- loop: { body: [step ids], condition: "<prompt>", maxIterations: 1..50 } \u2014 repeats body in order each iteration. \`condition\` is the loop's EXIT/GOAL condition: after each iteration the agent returns JSON branch then (condition met \u2192 STOP, continue to the next step) | else (not yet met \u2192 run body again). A body step error BREAKS the loop to the next step (use onError: continue on a body step to swallow its error and keep iterating). Always stops at maxIterations (default 10). Body step ids must be real steps; do NOT combine loop with then/else/cases/default.
|
|
143670
|
+
- input: templated instruction for skill steps
|
|
143671
|
+
- prompt: templated instruction for prompt steps (multiline allowed with |)
|
|
142554
143672
|
- args: templated args object for tool/workflow steps
|
|
142555
|
-
- needs: [ <upstream step ids> ] (defines the DAG; omit for sources)
|
|
142556
|
-
- when (optional):
|
|
143673
|
+
- needs: [ <upstream step ids> ] (defines the DAG; omit only for true sources)
|
|
143674
|
+
- when (optional, legacy): simple guards only \u2014 '{{ steps.x.output }} is not empty'. Do NOT use when for semantic decisions (use condition/switch).
|
|
142557
143675
|
- onError (optional): fail | continue | retry ; retries (optional, 0-3)
|
|
142558
143676
|
|
|
142559
|
-
|
|
143677
|
+
Operator data \u2014 two ways: declare a value the operator can supply UP FRONT as an \`inputs\` field (filled in before Run). To PAUSE mid-run and ask a question whose answer depends on earlier steps, set \`awaitInput: true\` on a prompt or skill step: the workflow pauses, surfaces the step's prompt to the operator, and resumes with their reply once they answer. Prefer \`inputs\` for known-up-front values; use \`awaitInput\` only for genuinely mid-run questions.
|
|
143678
|
+
|
|
143679
|
+
Templating: {{ steps.<id>.output }}, {{ inputs.<name> }}, {{ vars.<name> }}, {{ trigger }}, {{ now }}.
|
|
143680
|
+
|
|
143681
|
+
Logic steps: default response is one JSON object (vars, branch, optional text). Describe semantics in the instruction; do not repeat JSON syntax unless needed.
|
|
143682
|
+
|
|
143683
|
+
Ordering: steps whose \`needs\` are all satisfied run in parallel \u2014 chain with \`needs\` for sequential pipelines. A loop's body steps run only inside the loop (each iteration), so give them \`needs: [<loop step id>]\` and never schedule them elsewhere. A loop body step runs unconditionally each iteration: do NOT put \`when\` on it, do NOT make it a condition/switch step, and only \`needs\` its loop step or a sibling body step of the same loop. No NON-loop step may \`needs\` a loop body step \u2014 depend on the loop step instead.
|
|
142560
143684
|
|
|
142561
|
-
|
|
143685
|
+
Authoring rules:
|
|
143686
|
+
1. Decompose the intent into concrete steps. Multi-phase requests (collect \u2192 act \u2192 summarize \u2192 deliver) need at least 4 steps with a linear or fan-in \`needs\` chain.
|
|
143687
|
+
2. Values the operator must supply (search topic, recipient email, brief): declare each as an \`inputs\` field with a clear \`description\` (and a \`default\` when sensible). The operator fills them in before Run; reference them downstream via \`{{ inputs.<name> }}\`.
|
|
143688
|
+
3. To ask the operator a mid-run question whose answer depends on earlier steps, set \`awaitInput: true\` on a prompt or skill step \u2014 the run pauses, shows that step's prompt to the operator, and continues with their reply (referenced downstream via \`{{ steps.<id>.output }}\`). awaitInput is ONLY valid on prompt/skill steps (never tool/logic/loop or a loop body). Prefer \`inputs\` for values known before Run.
|
|
143689
|
+
4. Research + report + email intents: typical chain \u2014 \`web-research\` skill (over \`{{ inputs.topic }}\`) \u2192 \`write_report\` \u2192 \`send_email\` tool (to \`{{ inputs.recipient }}\`). Put \`topic\` and \`recipient\` in \`inputs\`.
|
|
143690
|
+
5. Use ONLY skill/tool names from the catalogs below \u2014 never placeholders like "<< skill-name >>", "TBD", or empty skill/tool fields.
|
|
143691
|
+
6. Prefer a listed skill when its description fits; otherwise use a detailed \`prompt\` step.
|
|
143692
|
+
7. For email/notify: use a listed mail/MCP tool if available; else \`delivery: { channel: inbox }\`.
|
|
143693
|
+
8. For image generation: use a listed image/generation tool if available; else a \`prompt\` step that describes producing the image artifact in text.
|
|
143694
|
+
9. Later steps must read prior results via \`{{ steps.<id>.output }}\`, extracted fields via \`{{ vars.<name> }}\`, and operator data via \`{{ inputs.<name> }}\` \u2014 never invent example emails or briefs in prompts.
|
|
143695
|
+
10. Between incompatible steps insert \`bridge\` to extract fields into vars (e.g. an email address from text). Use \`condition\` for if/else routing, \`switch\` for multi-way (e.g. value > 100 \u2192 pies, < 0 \u2192 kot, else nieokreslony).
|
|
143696
|
+
11. Use \`loop\` for "keep refining until good enough" / "retry up to N times" / "iterate while X holds" intents \u2014 set a sane maxIterations so it always terminates. Prefer bridge + vars over passing raw output to tools.
|
|
142562
143697
|
|
|
142563
|
-
Available skills:
|
|
142564
|
-
|
|
142565
|
-
|
|
143698
|
+
Available skills (name \u2014 description):
|
|
143699
|
+
${skills}
|
|
143700
|
+
|
|
143701
|
+
Available tools (name \u2014 description):
|
|
143702
|
+
${tools}
|
|
143703
|
+
|
|
143704
|
+
Example shape for internet research \u2192 report \u2192 email (operator data via inputs):
|
|
143705
|
+
\`\`\`yaml
|
|
143706
|
+
name: internet-research-report-email
|
|
143707
|
+
description: Research a topic, write a report, and email it to the recipient.
|
|
143708
|
+
enabled: true
|
|
143709
|
+
inputs:
|
|
143710
|
+
topic:
|
|
143711
|
+
description: Temat/zakres wyszukiwania w internecie.
|
|
143712
|
+
recipient:
|
|
143713
|
+
description: Adres e-mail odbiorcy raportu.
|
|
143714
|
+
steps:
|
|
143715
|
+
- id: search_web
|
|
143716
|
+
label: Wyszukaj w internecie
|
|
143717
|
+
skill: web-research
|
|
143718
|
+
input: |
|
|
143719
|
+
Przeprowad\u017A research na temat:
|
|
143720
|
+
{{ inputs.topic }}
|
|
143721
|
+
- id: write_report
|
|
143722
|
+
needs: [search_web]
|
|
143723
|
+
label: Przygotuj raport
|
|
143724
|
+
prompt: |
|
|
143725
|
+
Napisz raport po polsku z wynik\xF3w researchu.
|
|
143726
|
+
Temat: {{ inputs.topic }}
|
|
143727
|
+
Research: {{ steps.search_web.output }}
|
|
143728
|
+
- id: send_email
|
|
143729
|
+
needs: [write_report]
|
|
143730
|
+
label: Wy\u015Blij e-mail
|
|
143731
|
+
tool: gmail_send
|
|
143732
|
+
args:
|
|
143733
|
+
to: ["{{ inputs.recipient }}"]
|
|
143734
|
+
subject: "Raport z researchu"
|
|
143735
|
+
body: "{{ steps.write_report.output }}"
|
|
143736
|
+
\`\`\`
|
|
143737
|
+
|
|
143738
|
+
Example shape for image brief \u2192 generate \u2192 report \u2192 email (operator data via inputs):
|
|
143739
|
+
\`\`\`yaml
|
|
143740
|
+
name: image-report-email
|
|
143741
|
+
description: Generate an image from a brief, write a report, and email it.
|
|
143742
|
+
enabled: true
|
|
143743
|
+
inputs:
|
|
143744
|
+
brief:
|
|
143745
|
+
description: What image to generate (subject, style, format, mood, colors).
|
|
143746
|
+
recipient:
|
|
143747
|
+
description: Recipient email for the report.
|
|
143748
|
+
steps:
|
|
143749
|
+
- id: generate_image
|
|
143750
|
+
label: Generate image
|
|
143751
|
+
prompt: |
|
|
143752
|
+
Generate the image from this brief:
|
|
143753
|
+
{{ inputs.brief }}
|
|
143754
|
+
Return the artifact path or id and short generation notes.
|
|
143755
|
+
- id: write_report
|
|
143756
|
+
needs: [generate_image]
|
|
143757
|
+
label: Write report
|
|
143758
|
+
prompt: |
|
|
143759
|
+
Write a concise report in the operator's language.
|
|
143760
|
+
Brief: {{ inputs.brief }}
|
|
143761
|
+
Generation: {{ steps.generate_image.output }}
|
|
143762
|
+
- id: send_report
|
|
143763
|
+
needs: [write_report]
|
|
143764
|
+
label: Send report
|
|
143765
|
+
tool: gmail_send
|
|
143766
|
+
args:
|
|
143767
|
+
to: ["{{ inputs.recipient }}"]
|
|
143768
|
+
subject: "Image workflow report"
|
|
143769
|
+
body: "{{ steps.write_report.output }}"
|
|
143770
|
+
\`\`\`
|
|
143771
|
+
|
|
143772
|
+
Example shape for an iterative refine-until-good loop:
|
|
143773
|
+
\`\`\`yaml
|
|
143774
|
+
name: refine-draft
|
|
143775
|
+
description: Draft a paragraph, then refine it until it is good enough or 5 tries are used.
|
|
143776
|
+
enabled: true
|
|
143777
|
+
inputs:
|
|
143778
|
+
topic:
|
|
143779
|
+
default: "release notes"
|
|
143780
|
+
steps:
|
|
143781
|
+
- id: first_draft
|
|
143782
|
+
label: First draft
|
|
143783
|
+
prompt: |
|
|
143784
|
+
Write a first draft about {{ inputs.topic }}.
|
|
143785
|
+
- id: refine
|
|
143786
|
+
needs: [first_draft]
|
|
143787
|
+
label: Refine loop
|
|
143788
|
+
loop:
|
|
143789
|
+
# condition is the EXIT/GOAL condition \u2014 describe the goal that ENDS the
|
|
143790
|
+
# loop. Met (then) \u2192 stop and continue to the next step; not met (else) \u2192
|
|
143791
|
+
# run the body again. A body step error breaks the loop to the next step.
|
|
143792
|
+
body: [improve]
|
|
143793
|
+
condition: |
|
|
143794
|
+
Is the latest draft in {{ vars.draft }} good enough \u2014 clear, accurate, and well-structured?
|
|
143795
|
+
If yes, the goal is reached and the loop stops; if not, keep refining.
|
|
143796
|
+
maxIterations: 5
|
|
143797
|
+
- id: improve
|
|
143798
|
+
needs: [refine]
|
|
143799
|
+
label: Improve draft
|
|
143800
|
+
bridge: |
|
|
143801
|
+
Improve the current draft (start from {{ steps.first_draft.output }} or {{ vars.draft }}).
|
|
143802
|
+
Return JSON with vars.draft set to the improved text.
|
|
143803
|
+
\`\`\`
|
|
143804
|
+
|
|
143805
|
+
Example shape for a mid-run question (awaitInput pause \u2192 operator reply \u2192 continue):
|
|
143806
|
+
\`\`\`yaml
|
|
143807
|
+
name: draft-with-approval
|
|
143808
|
+
description: Draft an announcement, ask the operator to approve or tweak it, then publish.
|
|
143809
|
+
enabled: true
|
|
143810
|
+
steps:
|
|
143811
|
+
- id: draft
|
|
143812
|
+
label: Draft announcement
|
|
143813
|
+
prompt: |
|
|
143814
|
+
Write a short product announcement.
|
|
143815
|
+
- id: approve
|
|
143816
|
+
needs: [draft]
|
|
143817
|
+
label: Approve or tweak
|
|
143818
|
+
awaitInput: true
|
|
143819
|
+
prompt: |
|
|
143820
|
+
Here is the draft announcement:
|
|
143821
|
+
{{ steps.draft.output }}
|
|
143822
|
+
Reply with "ship it" to approve, or describe any changes you want.
|
|
143823
|
+
- id: publish
|
|
143824
|
+
needs: [approve]
|
|
143825
|
+
label: Publish
|
|
143826
|
+
prompt: |
|
|
143827
|
+
Apply the operator's decision ({{ steps.approve.output }}) and produce the final announcement.
|
|
143828
|
+
\`\`\`
|
|
143829
|
+
(Replace skill/tool names with ones from the catalog when drafting.)`;
|
|
143830
|
+
}
|
|
143831
|
+
function formatCatalog(entries, emptyLabel) {
|
|
143832
|
+
if (!entries?.length)
|
|
143833
|
+
return emptyLabel;
|
|
143834
|
+
return entries.map((entry) => `- ${entry.name}${entry.description ? ` \u2014 ${entry.description}` : ""}`).join("\n");
|
|
142566
143835
|
}
|
|
142567
143836
|
async function draftWorkflow(provider, model, intent, signal, opts = {}) {
|
|
142568
143837
|
let accumulated = "";
|
|
@@ -142570,7 +143839,7 @@ async function draftWorkflow(provider, model, intent, signal, opts = {}) {
|
|
|
142570
143839
|
model,
|
|
142571
143840
|
system: buildSystemPrompt(opts),
|
|
142572
143841
|
messages: [{ role: "user", content: [{ type: "text", text: `Build a workflow for: ${intent}` }] }],
|
|
142573
|
-
maxTokens: opts.maxTokens ??
|
|
143842
|
+
maxTokens: opts.maxTokens ?? DEFAULT_MAX_TOKENS,
|
|
142574
143843
|
signal
|
|
142575
143844
|
})) {
|
|
142576
143845
|
if (event.type === "text_delta")
|
|
@@ -142652,7 +143921,8 @@ function createTool(deps) {
|
|
|
142652
143921
|
const model = deps.draftModel ?? provider.models[0]?.id ?? "claude-sonnet-4-6";
|
|
142653
143922
|
const drafted = await draftWorkflow(provider, model, intent, ctx.signal, {
|
|
142654
143923
|
...deps.listSkills ? { availableSkills: deps.listSkills() } : {},
|
|
142655
|
-
...deps.listTools ? { availableTools: deps.listTools() } : {}
|
|
143924
|
+
...deps.listTools ? { availableTools: deps.listTools() } : {},
|
|
143925
|
+
maxTokens: 4096
|
|
142656
143926
|
});
|
|
142657
143927
|
if (!drafted.parse.ok || !drafted.parse.workflow) {
|
|
142658
143928
|
throw new MoxxyError({
|
|
@@ -143148,9 +144418,17 @@ function buildWorkflowsIntegration(args) {
|
|
|
143148
144418
|
const warnedCycles = /* @__PURE__ */ new Set();
|
|
143149
144419
|
async function runNow(input) {
|
|
143150
144420
|
const entry = await store.get(input.name);
|
|
143151
|
-
if (!entry)
|
|
144421
|
+
if (!entry) {
|
|
144422
|
+
return { ok: false, status: "failed", steps: [], output: "", error: `no workflow named "${input.name}"` };
|
|
144423
|
+
}
|
|
143152
144424
|
if (inFlight.has(input.name)) {
|
|
143153
|
-
return {
|
|
144425
|
+
return {
|
|
144426
|
+
ok: false,
|
|
144427
|
+
status: "failed",
|
|
144428
|
+
steps: [],
|
|
144429
|
+
output: "",
|
|
144430
|
+
error: `workflow "${input.name}" is already running`
|
|
144431
|
+
};
|
|
143154
144432
|
}
|
|
143155
144433
|
inFlight.add(input.name);
|
|
143156
144434
|
try {
|
|
@@ -143189,12 +144467,62 @@ function buildWorkflowsIntegration(args) {
|
|
|
143189
144467
|
},
|
|
143190
144468
|
{ executor: session.workflowExecutors.getActive() }
|
|
143191
144469
|
);
|
|
144470
|
+
if (result.status === "paused") {
|
|
144471
|
+
logger?.warn?.("workflows: run paused awaiting operator input; not delivering to inbox", {
|
|
144472
|
+
workflow: input.name,
|
|
144473
|
+
runId: result.runId
|
|
144474
|
+
});
|
|
144475
|
+
return result;
|
|
144476
|
+
}
|
|
143192
144477
|
await deliverToInbox(entry.workflow, result, logger);
|
|
143193
144478
|
return result;
|
|
143194
144479
|
} finally {
|
|
143195
144480
|
inFlight.delete(input.name);
|
|
143196
144481
|
}
|
|
143197
144482
|
}
|
|
144483
|
+
async function resumeNow(runId, reply2) {
|
|
144484
|
+
const checkpoint = await defaultWorkflowRunStore.load(runId);
|
|
144485
|
+
const turnId = session.startTurn().turnId;
|
|
144486
|
+
const spawner = createSubagentSpawner({
|
|
144487
|
+
parentSession: session,
|
|
144488
|
+
parentTurnId: turnId,
|
|
144489
|
+
parentSignal: session.signal,
|
|
144490
|
+
parentModel: activeModel(session)
|
|
144491
|
+
});
|
|
144492
|
+
const result = await resumeWorkflowRun(
|
|
144493
|
+
runId,
|
|
144494
|
+
reply2,
|
|
144495
|
+
{
|
|
144496
|
+
spawner,
|
|
144497
|
+
tools: session.tools,
|
|
144498
|
+
lookup: {
|
|
144499
|
+
skill: (n2) => session.skills.byName(n2),
|
|
144500
|
+
workflow: (n2) => store.lookup(n2)
|
|
144501
|
+
},
|
|
144502
|
+
signal: session.signal,
|
|
144503
|
+
now: () => Date.now(),
|
|
144504
|
+
emit: (subtype, payload) => void session.log.append({
|
|
144505
|
+
type: "plugin_event",
|
|
144506
|
+
sessionId: session.id,
|
|
144507
|
+
turnId,
|
|
144508
|
+
source: "plugin",
|
|
144509
|
+
pluginId: PLUGIN_ID3,
|
|
144510
|
+
subtype,
|
|
144511
|
+
payload
|
|
144512
|
+
}),
|
|
144513
|
+
...logger ? { logger } : {}
|
|
144514
|
+
},
|
|
144515
|
+
defaultWorkflowRunStore
|
|
144516
|
+
);
|
|
144517
|
+
if (result.status === "paused") {
|
|
144518
|
+
logger?.warn?.("workflows: run paused again awaiting operator input; not delivering to inbox", {
|
|
144519
|
+
runId: result.runId
|
|
144520
|
+
});
|
|
144521
|
+
return result;
|
|
144522
|
+
}
|
|
144523
|
+
if (checkpoint?.workflow) await deliverToInbox(checkpoint.workflow, result, logger);
|
|
144524
|
+
return result;
|
|
144525
|
+
}
|
|
143198
144526
|
const view = {
|
|
143199
144527
|
list: async () => (await store.list()).map((w4) => ({
|
|
143200
144528
|
name: w4.workflow.name,
|
|
@@ -143214,7 +144542,47 @@ function buildWorkflowsIntegration(args) {
|
|
|
143214
144542
|
ok: r2.ok,
|
|
143215
144543
|
output: r2.output,
|
|
143216
144544
|
...r2.error ? { error: r2.error } : {},
|
|
143217
|
-
steps: r2.steps.map((s2) => ({ id: s2.id, status: s2.status, ...s2.error ? { error: s2.error } : {} }))
|
|
144545
|
+
steps: r2.steps.map((s2) => ({ id: s2.id, status: s2.status, ...s2.error ? { error: s2.error } : {} })),
|
|
144546
|
+
status: r2.status,
|
|
144547
|
+
...r2.runId ? { runId: r2.runId } : {}
|
|
144548
|
+
};
|
|
144549
|
+
},
|
|
144550
|
+
// Builder-facing additions (phase 2 GUI): validate a draft YAML, persist a
|
|
144551
|
+
// workflow, and fetch one as canonical YAML. Keep them on the same store so
|
|
144552
|
+
// the modal and the builder share one source of truth.
|
|
144553
|
+
validateDraft: async (yaml) => {
|
|
144554
|
+
const r2 = parseWorkflowYaml(yaml);
|
|
144555
|
+
return { ok: r2.ok, errors: r2.errors };
|
|
144556
|
+
},
|
|
144557
|
+
save: async (yaml, previousName) => {
|
|
144558
|
+
const parsed = parseWorkflowYaml(yaml);
|
|
144559
|
+
if (!parsed.ok || !parsed.workflow) {
|
|
144560
|
+
throw new Error(`invalid workflow YAML \u2014 ${parsed.errors.join("; ")}`);
|
|
144561
|
+
}
|
|
144562
|
+
const saved = await store.save(parsed.workflow, previousName);
|
|
144563
|
+
await syncSchedules();
|
|
144564
|
+
return { name: saved.workflow.name, scope: saved.scope, path: saved.path };
|
|
144565
|
+
},
|
|
144566
|
+
getRun: async (name) => {
|
|
144567
|
+
const entry = await store.get(name);
|
|
144568
|
+
if (!entry) return null;
|
|
144569
|
+
return {
|
|
144570
|
+
name: entry.workflow.name,
|
|
144571
|
+
scope: entry.scope,
|
|
144572
|
+
path: entry.path,
|
|
144573
|
+
yaml: serializeWorkflow(entry.workflow)
|
|
144574
|
+
};
|
|
144575
|
+
},
|
|
144576
|
+
// Human-in-the-loop: answer a paused run's awaitInput question and resume.
|
|
144577
|
+
resume: async (runId, reply2) => {
|
|
144578
|
+
const r2 = await resumeNow(runId, reply2);
|
|
144579
|
+
return {
|
|
144580
|
+
ok: r2.ok,
|
|
144581
|
+
output: r2.output,
|
|
144582
|
+
...r2.error ? { error: r2.error } : {},
|
|
144583
|
+
steps: r2.steps.map((s2) => ({ id: s2.id, status: s2.status, ...s2.error ? { error: s2.error } : {} })),
|
|
144584
|
+
status: r2.status,
|
|
144585
|
+
...r2.runId ? { runId: r2.runId } : {}
|
|
143218
144586
|
};
|
|
143219
144587
|
}
|
|
143220
144588
|
};
|
|
@@ -143312,8 +144680,11 @@ function buildWorkflowsIntegration(args) {
|
|
|
143312
144680
|
appendEvent: (e3) => session.log.append(e3),
|
|
143313
144681
|
...logger ? { logger } : {},
|
|
143314
144682
|
provider: () => safeActiveProvider(session),
|
|
143315
|
-
listSkills: () => session.skills.list().map((s2) =>
|
|
143316
|
-
|
|
144683
|
+
listSkills: () => session.skills.list().map((s2) => ({
|
|
144684
|
+
name: s2.frontmatter.name,
|
|
144685
|
+
description: s2.frontmatter.description ?? ""
|
|
144686
|
+
})),
|
|
144687
|
+
listTools: () => session.tools.list().map((t2) => ({ name: t2.name, description: t2.description ?? "" })),
|
|
143317
144688
|
onChanged: syncSchedules,
|
|
143318
144689
|
runNow,
|
|
143319
144690
|
userDir: defaultUserWorkflowsDir(),
|
|
@@ -143321,6 +144692,13 @@ function buildWorkflowsIntegration(args) {
|
|
|
143321
144692
|
session.workflows = view;
|
|
143322
144693
|
await syncSchedules();
|
|
143323
144694
|
await startFileWatchers();
|
|
144695
|
+
void defaultWorkflowRunStore.sweepStale().then((n2) => {
|
|
144696
|
+
if (n2 > 0) logger?.info?.("workflows: swept stale paused-run checkpoints", { count: n2 });
|
|
144697
|
+
}).catch(
|
|
144698
|
+
(err) => logger?.warn?.("workflows: checkpoint sweep failed", {
|
|
144699
|
+
err: err instanceof Error ? err.message : String(err)
|
|
144700
|
+
})
|
|
144701
|
+
);
|
|
143324
144702
|
}
|
|
143325
144703
|
});
|
|
143326
144704
|
return {
|
|
@@ -148864,9 +150242,9 @@ ${HELP12}`);
|
|
|
148864
150242
|
function formatCapabilities(caps) {
|
|
148865
150243
|
if (!caps) return "";
|
|
148866
150244
|
const bits = [];
|
|
148867
|
-
const
|
|
148868
|
-
if (
|
|
148869
|
-
if (
|
|
150245
|
+
const fs44 = caps.fs;
|
|
150246
|
+
if (fs44?.read?.length) bits.push(`fs:read(${fs44.read.length})`);
|
|
150247
|
+
if (fs44?.write?.length) bits.push(`fs:write(${fs44.write.length})`);
|
|
148870
150248
|
const net3 = caps.net;
|
|
148871
150249
|
if (net3?.mode) bits.push(`net:${net3.mode}`);
|
|
148872
150250
|
const env3 = caps.env;
|