@moxxy/cli 0.13.1 → 0.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +154 -93
- package/dist/bin.js.map +1 -1
- package/package.json +2 -2
package/dist/bin.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { z as z$1, createMutex, defineTunnelProvider,
|
|
3
|
+
import { z as z$1, createMutex, defineTunnelProvider, definePlugin, defineProvider, defineTool, MoxxyError, asTurnId, defineMode, asPluginId, defineCommand, defineChannel, defineWorkflowExecutor, toFriendlyError, estimateTextTokens, classifyHttpStatus, createStuckLoopDetector, runCompactionIfNeeded, runElisionIfNeeded, collectProviderStream, usageEventFields, isContextOverflowError, emitRequestsAndDetectStuck, executeToolUses, buildSystemPromptWithSkills, projectMessages, defineCompactor, defineCacheStrategy, denyByDefaultResolver, createAllowListResolver, zodToJsonSchema, fileDiffSummary, runSingleShotTurn, defineSurface, runManualCompaction, isFileDiffDisplay, renderFrontmatter, defineEmbedder, migrateModeName, skillFrontmatterSchema, asSkillId, getInstallHint, parseFrontmatterFile, createDeferredPermissionResolver, encodeLoginPrompt, defineTranscriber, summarizeTokensByModel, countNodes, moxxyPackageSchema, classifyNetworkError, addModelTotals, createJsonFileStore, ISOLATION_RANK, MOXXY_PCM16_24KHZ_MIME, fileDiffVerb, parseFrontmatter, createCallbackResolver, autoAllowResolver, asSessionId, asToolCallId, defineViewRenderer, DEFAULT_VIEW_TAGS, assertNever, isSafeViewUrl, evaluateToolRule, summarizeSessionTokensFromEvents, toDiffRows, diffGutterNo, computeElisionState, toolResultStubbed, toolResultStub, toolResultBytes, conversationalStubbed, conversationalStub, asEventId } from '@moxxy/sdk';
|
|
4
4
|
import * as fs32 from 'fs';
|
|
5
|
-
import fs32__default, { existsSync, promises, ReadStream, mkdirSync, statSync, readdirSync, writeFileSync, readFileSync,
|
|
5
|
+
import fs32__default, { existsSync, promises, ReadStream, mkdirSync, statSync, readdirSync, writeFileSync, readFileSync, unlinkSync, chmodSync, watch, createReadStream } from 'fs';
|
|
6
6
|
import * as path3 from 'path';
|
|
7
7
|
import path3__default, { join, dirname, basename } from 'path';
|
|
8
|
+
import { isCliTunnelAvailable, writeFileAtomic, spawnCliTunnel, moxxyPath, moxxyHome, bearerTokenMatches, resolveChannelToken, rotateChannelToken, readRequestBody, MOXXY_WS_SUBPROTOCOL, bearerGuard, tokenFromWsProtocolHeader, writeFileAtomicSync } from '@moxxy/sdk/server';
|
|
8
9
|
import { z } from 'zod';
|
|
9
10
|
import * as os5 from 'os';
|
|
10
11
|
import os5__default, { homedir, tmpdir, userInfo } from 'os';
|
|
@@ -85505,12 +85506,9 @@ function handleCollabEvent(e3, ref, root) {
|
|
|
85505
85506
|
root.push(block2);
|
|
85506
85507
|
return;
|
|
85507
85508
|
}
|
|
85508
|
-
|
|
85509
|
-
if (!block)
|
|
85510
|
-
|
|
85511
|
-
ref.current = block;
|
|
85512
|
-
root.push(block);
|
|
85513
|
-
}
|
|
85509
|
+
const block = ref.current;
|
|
85510
|
+
if (!block)
|
|
85511
|
+
return;
|
|
85514
85512
|
switch (e3.subtype) {
|
|
85515
85513
|
case "collab_fallback_sequential":
|
|
85516
85514
|
block.fallbackReason = String(p3.reason ?? "");
|
|
@@ -87762,7 +87760,7 @@ function useVoiceInput(opts) {
|
|
|
87762
87760
|
const pcm = await recording.stop();
|
|
87763
87761
|
const transcriber = resolveCodexTranscriber(session);
|
|
87764
87762
|
const result = await transcriber.transcribe(pcm, {
|
|
87765
|
-
mimeType:
|
|
87763
|
+
mimeType: MOXXY_PCM16_24KHZ_MIME
|
|
87766
87764
|
});
|
|
87767
87765
|
const text = result.text.trim();
|
|
87768
87766
|
if (!text) {
|
|
@@ -87869,13 +87867,12 @@ function formatVoiceError(err) {
|
|
|
87869
87867
|
return `voice: ${message}`;
|
|
87870
87868
|
return `voice: ${message || "failed"}`;
|
|
87871
87869
|
}
|
|
87872
|
-
var import_react51, CODEX_TRANSCRIBER_NAME
|
|
87870
|
+
var import_react51, CODEX_TRANSCRIBER_NAME;
|
|
87873
87871
|
var init_use_voice_input = __esm({
|
|
87874
87872
|
"../plugin-cli/dist/session/use-voice-input.js"() {
|
|
87875
87873
|
import_react51 = __toESM(require_react());
|
|
87876
87874
|
init_voice_input();
|
|
87877
87875
|
CODEX_TRANSCRIBER_NAME = "openai-codex-transcribe";
|
|
87878
|
-
MOXXY_PCM16_24KHZ_MIME2 = "audio/x-moxxy-pcm16-24khz";
|
|
87879
87876
|
}
|
|
87880
87877
|
});
|
|
87881
87878
|
|
|
@@ -88165,13 +88162,17 @@ function startCollab(deps, arg) {
|
|
|
88165
88162
|
deps.submitPrompt(objective);
|
|
88166
88163
|
}
|
|
88167
88164
|
function openModePicker(deps, arg = "") {
|
|
88168
|
-
const modes = deps.session.modes.list();
|
|
88165
|
+
const modes = deps.session.modes.list().filter((m3) => !COLLAB_HIDDEN_MODES.has(m3.name));
|
|
88169
88166
|
if (modes.length === 0) {
|
|
88170
88167
|
deps.setSystemNotice("no modes registered");
|
|
88171
88168
|
return;
|
|
88172
88169
|
}
|
|
88173
88170
|
const target = arg.trim().toLowerCase();
|
|
88174
88171
|
if (target) {
|
|
88172
|
+
if (COLLAB_HIDDEN_MODES.has(target)) {
|
|
88173
|
+
deps.setSystemNotice("Use /collab <goal> to run a collaborative team (only one runs at a time).");
|
|
88174
|
+
return;
|
|
88175
|
+
}
|
|
88175
88176
|
const match = modes.find((m3) => m3.name.toLowerCase() === target);
|
|
88176
88177
|
if (match) {
|
|
88177
88178
|
try {
|
|
@@ -88197,7 +88198,7 @@ function openModePicker(deps, arg = "") {
|
|
|
88197
88198
|
function truncate5(s2, n2) {
|
|
88198
88199
|
return s2.length <= n2 ? s2 : s2.slice(0, n2 - 1) + "\u2026";
|
|
88199
88200
|
}
|
|
88200
|
-
var PLUGIN_KIND_TAB, OTHER_TAB, PLUGIN_TAB_ORDER;
|
|
88201
|
+
var PLUGIN_KIND_TAB, OTHER_TAB, PLUGIN_TAB_ORDER, COLLAB_HIDDEN_MODES;
|
|
88201
88202
|
var init_run_slash = __esm({
|
|
88202
88203
|
async "../plugin-cli/dist/session/run-slash.js"() {
|
|
88203
88204
|
init_dist();
|
|
@@ -88212,6 +88213,11 @@ var init_run_slash = __esm({
|
|
|
88212
88213
|
};
|
|
88213
88214
|
OTHER_TAB = { id: "others", label: "Others" };
|
|
88214
88215
|
PLUGIN_TAB_ORDER = ["providers", "modes", "channels", "tools", "others"];
|
|
88216
|
+
COLLAB_HIDDEN_MODES = /* @__PURE__ */ new Set([
|
|
88217
|
+
"collaborative",
|
|
88218
|
+
"collab-architect",
|
|
88219
|
+
"collab-peer"
|
|
88220
|
+
]);
|
|
88215
88221
|
}
|
|
88216
88222
|
});
|
|
88217
88223
|
|
|
@@ -133481,9 +133487,6 @@ var localPlugin = definePlugin({
|
|
|
133481
133487
|
version: "0.0.0",
|
|
133482
133488
|
providers: [localProviderDef]
|
|
133483
133489
|
});
|
|
133484
|
-
|
|
133485
|
-
// ../plugin-stt-whisper/dist/audio.js
|
|
133486
|
-
var MOXXY_PCM16_24KHZ_MIME = "audio/x-moxxy-pcm16-24khz";
|
|
133487
133490
|
var WHISPER_FILENAME_BY_MIME = {
|
|
133488
133491
|
"audio/ogg": "audio.ogg",
|
|
133489
133492
|
"audio/opus": "audio.opus",
|
|
@@ -139079,6 +139082,57 @@ async function integrate(input) {
|
|
|
139079
139082
|
}
|
|
139080
139083
|
return { merged, conflicts, resolvedByOwnership, stagingBranch: branchName, promoted };
|
|
139081
139084
|
}
|
|
139085
|
+
var COLLAB_LOCK_PATH = join(homedir(), ".moxxy", "collab", "active.lock");
|
|
139086
|
+
function collabLockPath() {
|
|
139087
|
+
return process.env.MOXXY_COLLAB_LOCK || COLLAB_LOCK_PATH;
|
|
139088
|
+
}
|
|
139089
|
+
function readRaw() {
|
|
139090
|
+
try {
|
|
139091
|
+
return JSON.parse(readFileSync(collabLockPath(), "utf8"));
|
|
139092
|
+
} catch {
|
|
139093
|
+
return null;
|
|
139094
|
+
}
|
|
139095
|
+
}
|
|
139096
|
+
function isAlive(pid) {
|
|
139097
|
+
try {
|
|
139098
|
+
process.kill(pid, 0);
|
|
139099
|
+
return true;
|
|
139100
|
+
} catch (err) {
|
|
139101
|
+
return err.code === "EPERM";
|
|
139102
|
+
}
|
|
139103
|
+
}
|
|
139104
|
+
function readActiveCollab() {
|
|
139105
|
+
const info = readRaw();
|
|
139106
|
+
if (!info)
|
|
139107
|
+
return null;
|
|
139108
|
+
if (!isAlive(info.pid)) {
|
|
139109
|
+
try {
|
|
139110
|
+
unlinkSync(collabLockPath());
|
|
139111
|
+
} catch {
|
|
139112
|
+
}
|
|
139113
|
+
return null;
|
|
139114
|
+
}
|
|
139115
|
+
return info;
|
|
139116
|
+
}
|
|
139117
|
+
function tryAcquireCollabLock(args) {
|
|
139118
|
+
mkdirSync(dirname(collabLockPath()), { recursive: true });
|
|
139119
|
+
const existing = readActiveCollab();
|
|
139120
|
+
if (existing && existing.sessionId !== args.sessionId) {
|
|
139121
|
+
return { ok: false, holder: existing };
|
|
139122
|
+
}
|
|
139123
|
+
const info = { pid: process.pid, ...args };
|
|
139124
|
+
writeFileSync(collabLockPath(), JSON.stringify(info));
|
|
139125
|
+
return { ok: true };
|
|
139126
|
+
}
|
|
139127
|
+
function releaseCollabLock(sessionId) {
|
|
139128
|
+
const info = readRaw();
|
|
139129
|
+
if (info && info.sessionId === sessionId) {
|
|
139130
|
+
try {
|
|
139131
|
+
unlinkSync(collabLockPath());
|
|
139132
|
+
} catch {
|
|
139133
|
+
}
|
|
139134
|
+
}
|
|
139135
|
+
}
|
|
139082
139136
|
|
|
139083
139137
|
// ../mode-collaborative/dist/collab-loop.js
|
|
139084
139138
|
var POLL_MS = 500;
|
|
@@ -139097,47 +139151,56 @@ async function* runCollaborative(ctx, deps) {
|
|
|
139097
139151
|
yield await ctx.emit(assistant(ctx, "Collaborative mode needs a task to work on."));
|
|
139098
139152
|
return;
|
|
139099
139153
|
}
|
|
139100
|
-
const
|
|
139101
|
-
|
|
139102
|
-
|
|
139103
|
-
|
|
139104
|
-
|
|
139105
|
-
yield await ctx.emit(plugin4(ctx, "collab_fallback_sequential", {
|
|
139106
|
-
reason: !gitInstalled2 ? "git is not installed \u2014 running agents sequentially in your workspace" : !gitRepo ? "this folder is not a git repository \u2014 running agents sequentially in your workspace" : "sequential mode selected"
|
|
139107
|
-
}));
|
|
139108
|
-
}
|
|
139109
|
-
let baseSha = "";
|
|
139110
|
-
if (parallel) {
|
|
139111
|
-
const base2 = await resolveBase(cwd2);
|
|
139112
|
-
baseSha = base2.baseSha;
|
|
139154
|
+
const lock = tryAcquireCollabLock({ sessionId: String(ctx.sessionId), task, startedAtMs: Date.now() });
|
|
139155
|
+
if (!lock.ok) {
|
|
139156
|
+
yield await ctx.emit(plugin4(ctx, "collab_blocked", { reason: "already-running", holderTask: lock.holder.task }));
|
|
139157
|
+
yield await ctx.emit(assistant(ctx, `A collaboration is already running ("${lock.holder.task}"). Only one runs at a time to save resources \u2014 stop it first, then start again.`));
|
|
139158
|
+
return;
|
|
139113
139159
|
}
|
|
139160
|
+
const runId = collabRunId(String(ctx.sessionId), String(ctx.turnId));
|
|
139114
139161
|
const worktrees = /* @__PURE__ */ new Map();
|
|
139115
|
-
|
|
139116
|
-
|
|
139117
|
-
|
|
139118
|
-
role: "architect",
|
|
139119
|
-
subtask: task
|
|
139120
|
-
};
|
|
139121
|
-
const hub = await createCollaborationHub({
|
|
139122
|
-
socketPath: hubSocketPath(runId),
|
|
139123
|
-
task,
|
|
139124
|
-
roster: [architectEntry],
|
|
139125
|
-
peerReader: peerReaderFor(worktrees, baseSha)
|
|
139126
|
-
});
|
|
139127
|
-
registerActiveHub(String(ctx.sessionId), hub);
|
|
139128
|
-
const unsubscribe = hub.subscribe((e3) => {
|
|
139129
|
-
void ctx.emit(toCollabEvent(ctx, e3));
|
|
139130
|
-
});
|
|
139131
|
-
const supervisorOpts = {
|
|
139132
|
-
runId,
|
|
139133
|
-
hubSocket: hub.socketPath,
|
|
139134
|
-
coordinatorSessionId: String(ctx.sessionId),
|
|
139135
|
-
parentTask: task,
|
|
139136
|
-
...cfg.defaultModel ? { defaultModel: cfg.defaultModel } : {},
|
|
139137
|
-
signal: ctx.signal
|
|
139138
|
-
};
|
|
139139
|
-
const supervisor = (deps.createSupervisor ?? ((o2) => new PeerSupervisor(o2)))(supervisorOpts, hub);
|
|
139162
|
+
let hub = null;
|
|
139163
|
+
let supervisor = null;
|
|
139164
|
+
let unsubscribe = null;
|
|
139140
139165
|
try {
|
|
139166
|
+
mkdirSync(collabRunDir(runId), { recursive: true });
|
|
139167
|
+
const { installed: gitInstalled2, repo: gitRepo } = await detectGit(cwd2);
|
|
139168
|
+
const parallel = cfg.concurrency === "parallel" && gitRepo;
|
|
139169
|
+
if (!parallel) {
|
|
139170
|
+
yield await ctx.emit(plugin4(ctx, "collab_fallback_sequential", {
|
|
139171
|
+
reason: !gitInstalled2 ? "git is not installed \u2014 running agents sequentially in your workspace" : !gitRepo ? "this folder is not a git repository \u2014 running agents sequentially in your workspace" : "sequential mode selected"
|
|
139172
|
+
}));
|
|
139173
|
+
}
|
|
139174
|
+
let baseSha = "";
|
|
139175
|
+
if (parallel) {
|
|
139176
|
+
const base2 = await resolveBase(cwd2, { snapshotDirty: true });
|
|
139177
|
+
baseSha = base2.baseSha;
|
|
139178
|
+
}
|
|
139179
|
+
const architectEntry = {
|
|
139180
|
+
id: ARCHITECT_AGENT_ID,
|
|
139181
|
+
name: "Architect",
|
|
139182
|
+
role: "architect",
|
|
139183
|
+
subtask: task
|
|
139184
|
+
};
|
|
139185
|
+
hub = await createCollaborationHub({
|
|
139186
|
+
socketPath: hubSocketPath(runId),
|
|
139187
|
+
task,
|
|
139188
|
+
roster: [architectEntry],
|
|
139189
|
+
peerReader: peerReaderFor(worktrees, baseSha)
|
|
139190
|
+
});
|
|
139191
|
+
registerActiveHub(String(ctx.sessionId), hub);
|
|
139192
|
+
unsubscribe = hub.subscribe((e3) => {
|
|
139193
|
+
void ctx.emit(toCollabEvent(ctx, e3));
|
|
139194
|
+
});
|
|
139195
|
+
const supervisorOpts = {
|
|
139196
|
+
runId,
|
|
139197
|
+
hubSocket: hub.socketPath,
|
|
139198
|
+
coordinatorSessionId: String(ctx.sessionId),
|
|
139199
|
+
parentTask: task,
|
|
139200
|
+
...cfg.defaultModel ? { defaultModel: cfg.defaultModel } : {},
|
|
139201
|
+
signal: ctx.signal
|
|
139202
|
+
};
|
|
139203
|
+
supervisor = (deps.createSupervisor ?? ((o2) => new PeerSupervisor(o2)))(supervisorOpts, hub);
|
|
139141
139204
|
yield await ctx.emit(plugin4(ctx, "collab_started", { task, parallel, gitInstalled: gitInstalled2, gitRepo }));
|
|
139142
139205
|
supervisor.spawn({ entry: architectEntry, cwd: cwd2, mode: COLLAB_ARCHITECT_MODE_NAME });
|
|
139143
139206
|
yield await ctx.emit(plugin4(ctx, "collab_agent_spawned", { id: ARCHITECT_AGENT_ID, role: "architect" }));
|
|
@@ -139235,10 +139298,14 @@ ${summaryBlock}${mergeNote ? `
|
|
|
139235
139298
|
${mergeNote}` : ""}`));
|
|
139236
139299
|
yield await ctx.emit(plugin4(ctx, "collab_completed", { done: doneIds, total: roster.length }));
|
|
139237
139300
|
} finally {
|
|
139238
|
-
|
|
139239
|
-
|
|
139301
|
+
if (supervisor)
|
|
139302
|
+
await supervisor.shutdownAll("collaboration complete");
|
|
139303
|
+
if (unsubscribe)
|
|
139304
|
+
unsubscribe();
|
|
139240
139305
|
unregisterActiveHub(String(ctx.sessionId));
|
|
139241
|
-
|
|
139306
|
+
if (hub)
|
|
139307
|
+
await hub.close();
|
|
139308
|
+
releaseCollabLock(String(ctx.sessionId));
|
|
139242
139309
|
}
|
|
139243
139310
|
}
|
|
139244
139311
|
function lastUserPromptText(ctx) {
|
|
@@ -144062,6 +144129,7 @@ var optionalWorkspace = z.string().min(1).max(256).optional();
|
|
|
144062
144129
|
var MAX_AUDIO_BASE64 = 4e7;
|
|
144063
144130
|
var MAX_INLINE_ATTACHMENT_CONTENT = 12e6;
|
|
144064
144131
|
var commandName = z.string().min(1).max(64).regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, "invalid command name");
|
|
144132
|
+
var appId = z.string().min(1).max(64).regex(/^[a-z][a-z0-9-]*$/, "invalid app id");
|
|
144065
144133
|
var workflowName = z.string().min(1).max(200).refine((s2) => !s2.includes("..") && !s2.includes("/") && !s2.includes("\\"), "invalid workflow name");
|
|
144066
144134
|
var ipcInputSchemas = {
|
|
144067
144135
|
// No-arg, but spawns a child process (npm install) — pin the payload to
|
|
@@ -144171,6 +144239,20 @@ var ipcInputSchemas = {
|
|
|
144171
144239
|
"settings.writeSkill": z.object({ name: skillName, body: z.string().max(1e6) }),
|
|
144172
144240
|
"settings.readSkill": z.object({ name: skillName }),
|
|
144173
144241
|
"settings.deleteSkill": z.object({ name: skillName }),
|
|
144242
|
+
// Desktop apps: appId keys the per-app install dir + a network download, so
|
|
144243
|
+
// pin it to a non-traversing slug. (pickDocument is no-arg → see below.)
|
|
144244
|
+
"apps.status": z.object({ appId }),
|
|
144245
|
+
"apps.install": z.object({ appId }),
|
|
144246
|
+
"apps.uninstall": z.object({ appId }),
|
|
144247
|
+
// Anonymizer: parseDocument reads a file (bound the path), saveRedacted writes
|
|
144248
|
+
// one (bound name + cap content so a renderer can't OOM main). pickDocument
|
|
144249
|
+
// takes nothing — pin it to "nothing" so no args can be smuggled across.
|
|
144250
|
+
"anonymizer.pickDocument": z.undefined(),
|
|
144251
|
+
"anonymizer.parseDocument": z.object({ path: z.string().min(1).max(4096) }),
|
|
144252
|
+
"anonymizer.saveRedacted": z.object({
|
|
144253
|
+
suggestedName: z.string().min(1).max(255),
|
|
144254
|
+
content: z.string().max(2e7)
|
|
144255
|
+
}),
|
|
144174
144256
|
"desks.create": z.object({ name: z.string().min(1).max(200), cwd: z.string().min(1).max(4096) }),
|
|
144175
144257
|
// Mirror desks.create's name bounds — rename writes the name into the desks
|
|
144176
144258
|
// JSON, so an unbounded string would let a renderer bloat the state file.
|
|
@@ -146562,37 +146644,25 @@ async function compactSession(session) {
|
|
|
146562
146644
|
if (events.length === 0) {
|
|
146563
146645
|
return { kind: "text", text: "nothing to compact: event log is empty" };
|
|
146564
146646
|
}
|
|
146565
|
-
const providerCtxWindow = resolveActiveContextWindow(s2);
|
|
146566
146647
|
const provider = safe(() => s2.providers?.getActive()) ?? void 0;
|
|
146567
146648
|
const model = provider?.models[0]?.id;
|
|
146649
|
+
const contextWindow = provider?.models[0]?.contextWindow;
|
|
146568
146650
|
try {
|
|
146569
|
-
const result = await
|
|
146570
|
-
|
|
146571
|
-
|
|
146572
|
-
|
|
146573
|
-
estimatedTokens: estimateContextTokens$1(s2.log.asReader ? s2.log.asReader() : s2.log),
|
|
146574
|
-
reserveForOutput: 0
|
|
146575
|
-
},
|
|
146576
|
-
signal: s2.signal ?? new AbortController().signal,
|
|
146651
|
+
const result = await runManualCompaction({
|
|
146652
|
+
compactor,
|
|
146653
|
+
log: s2.log,
|
|
146654
|
+
signal: s2.signal,
|
|
146577
146655
|
...provider ? { provider } : {},
|
|
146578
|
-
...model ? { model } : {}
|
|
146656
|
+
...model !== void 0 ? { model } : {},
|
|
146657
|
+
...contextWindow !== void 0 ? { contextWindow } : {},
|
|
146658
|
+
...s2.id !== void 0 ? { sessionId: s2.id } : {}
|
|
146579
146659
|
});
|
|
146580
|
-
if (result.
|
|
146660
|
+
if (!result.compacted) {
|
|
146581
146661
|
return { kind: "text", text: "nothing to compact yet" };
|
|
146582
146662
|
}
|
|
146583
|
-
const lastEvent = events[events.length - 1];
|
|
146584
|
-
const emittable = {
|
|
146585
|
-
sessionId: s2.id ?? lastEvent?.sessionId,
|
|
146586
|
-
turnId: lastEvent?.turnId,
|
|
146587
|
-
source: "compactor",
|
|
146588
|
-
...result
|
|
146589
|
-
};
|
|
146590
|
-
await s2.log.append(emittable);
|
|
146591
|
-
const [fromSeq, toSeq] = result.replacedRange;
|
|
146592
|
-
const compactedEvents = events.filter((e3) => e3.seq >= fromSeq && e3.seq <= toSeq).length;
|
|
146593
146663
|
return {
|
|
146594
146664
|
kind: "text",
|
|
146595
|
-
text: `context compacted: ${formatCount2(
|
|
146665
|
+
text: `context compacted: ${formatCount2(result.eventsCompacted)} ${plural2(result.eventsCompacted, "event")}, ~${formatTokenCount2(result.tokensSaved)} tokens saved`
|
|
146596
146666
|
};
|
|
146597
146667
|
} catch (err) {
|
|
146598
146668
|
return {
|
|
@@ -146601,17 +146671,6 @@ async function compactSession(session) {
|
|
|
146601
146671
|
};
|
|
146602
146672
|
}
|
|
146603
146673
|
}
|
|
146604
|
-
function resolveActiveContextWindow(s2) {
|
|
146605
|
-
try {
|
|
146606
|
-
const provider = s2.providers?.getActive();
|
|
146607
|
-
if (!provider)
|
|
146608
|
-
return Number.MAX_SAFE_INTEGER;
|
|
146609
|
-
const window2 = provider.models[0]?.contextWindow;
|
|
146610
|
-
return window2 && window2 > 0 ? window2 : Number.MAX_SAFE_INTEGER;
|
|
146611
|
-
} catch {
|
|
146612
|
-
return Number.MAX_SAFE_INTEGER;
|
|
146613
|
-
}
|
|
146614
|
-
}
|
|
146615
146674
|
function formatCount2(value) {
|
|
146616
146675
|
return new Intl.NumberFormat("en-US").format(value);
|
|
146617
146676
|
}
|
|
@@ -147610,6 +147669,8 @@ var stepSchema = z.object({
|
|
|
147610
147669
|
needs: z.array(z.string().min(1)).default([]),
|
|
147611
147670
|
when: z.string().min(1).optional(),
|
|
147612
147671
|
onError: z.enum(["fail", "continue", "retry"]).default("fail"),
|
|
147672
|
+
// `retries` only takes effect when `onError: 'retry'`; with 'fail'/'continue'
|
|
147673
|
+
// the step runs exactly one attempt (see runStep in executor/steps.ts).
|
|
147613
147674
|
retries: z.number().int().min(0).max(3).default(0),
|
|
147614
147675
|
label: z.string().max(60).optional(),
|
|
147615
147676
|
format: z.enum(["json", "plain"]).optional(),
|
|
@@ -148519,7 +148580,7 @@ function buildRunResult(ctx, status, ok, extra) {
|
|
|
148519
148580
|
};
|
|
148520
148581
|
}
|
|
148521
148582
|
async function runStep(step, scope, ctx) {
|
|
148522
|
-
const attempts = 1 + Math.max(0, step.retries);
|
|
148583
|
+
const attempts = step.onError === "retry" ? 1 + Math.max(0, step.retries) : 1;
|
|
148523
148584
|
let lastError = "";
|
|
148524
148585
|
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
148525
148586
|
if (ctx.deps.signal.aborted)
|
|
@@ -149040,7 +149101,7 @@ ${userMessage.trim()}${FINALIZE_REPLY_SUFFIX}`;
|
|
|
149040
149101
|
var DAG_EXECUTOR_NAME = "dag";
|
|
149041
149102
|
var dagExecutor = defineWorkflowExecutor({
|
|
149042
149103
|
name: DAG_EXECUTOR_NAME,
|
|
149043
|
-
description: "DAG runner: steps with settled dependencies are scheduled in waves of up to `concurrency` ready steps, then executed sequentially within each wave (no overlap
|
|
149104
|
+
description: "DAG runner: steps with settled dependencies are scheduled in waves of up to `concurrency` ready steps, then executed sequentially within each wave (no overlap \u2014 `concurrency` caps the batch size drained per pass, not wall-clock latency).",
|
|
149044
149105
|
run: runExecutor
|
|
149045
149106
|
});
|
|
149046
149107
|
|
|
@@ -149107,7 +149168,7 @@ A workflow is a DAG of steps. Schema:
|
|
|
149107
149168
|
- args: templated args object for tool/workflow steps
|
|
149108
149169
|
- needs: [ <upstream step ids> ] (defines the DAG; omit only for true sources)
|
|
149109
149170
|
- when (optional, legacy): simple guards only \u2014 '{{ steps.x.output }} is not empty'. Do NOT use when for semantic decisions (use condition/switch).
|
|
149110
|
-
- onError (optional): fail | continue | retry ; retries (optional, 0-3)
|
|
149171
|
+
- onError (optional): fail | continue | retry ; retries (optional, 0-3 \u2014 only applies when onError is retry; fail/continue always run exactly one attempt)
|
|
149111
149172
|
|
|
149112
149173
|
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.
|
|
149113
149174
|
|