@moxxy/cli 0.9.0 → 0.10.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/dist/bin.js +225 -11
- 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, 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,
|
|
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, migrateModeName, bearerGuard, tokenFromWsProtocolHeader, skillFrontmatterSchema, asSkillId, getInstallHint, moxxyHome, defineTranscriber, summarizeTokensByModel, 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';
|
|
@@ -1376,6 +1376,13 @@ var init_providers = __esm({
|
|
|
1376
1376
|
defs = /* @__PURE__ */ new Map();
|
|
1377
1377
|
instances = /* @__PURE__ */ new Map();
|
|
1378
1378
|
active = null;
|
|
1379
|
+
/**
|
|
1380
|
+
* Names the user disabled. Kept name-based (not def-based) so it can be
|
|
1381
|
+
* seeded from preferences BEFORE the plugins register their defs — boot
|
|
1382
|
+
* order doesn't matter. A disabled provider stays registered/listable but
|
|
1383
|
+
* can't be activated.
|
|
1384
|
+
*/
|
|
1385
|
+
disabled = /* @__PURE__ */ new Set();
|
|
1379
1386
|
/**
|
|
1380
1387
|
* Register a provider def. Throws on duplicate — use `replace()` for
|
|
1381
1388
|
* explicit overwrite. Matches the semantics of `tools` and `channels`.
|
|
@@ -1404,10 +1411,32 @@ var init_providers = __esm({
|
|
|
1404
1411
|
list() {
|
|
1405
1412
|
return [...this.defs.values()];
|
|
1406
1413
|
}
|
|
1414
|
+
/**
|
|
1415
|
+
* Enable/disable a provider by name. Disabling the ACTIVE provider is
|
|
1416
|
+
* refused — switch first, then disable — so a session never ends up with an
|
|
1417
|
+
* active-but-disabled provider. Unknown names are accepted (the set seeds
|
|
1418
|
+
* from preferences before plugins register), except when disabling via a
|
|
1419
|
+
* live toggle is meaningless because the provider is active.
|
|
1420
|
+
*/
|
|
1421
|
+
setEnabled(name, enabled) {
|
|
1422
|
+
if (!enabled && this.active === name) {
|
|
1423
|
+
throw new Error(`Cannot disable the active provider "${name}" \u2014 switch providers first.`);
|
|
1424
|
+
}
|
|
1425
|
+
if (enabled)
|
|
1426
|
+
this.disabled.delete(name);
|
|
1427
|
+
else
|
|
1428
|
+
this.disabled.add(name);
|
|
1429
|
+
}
|
|
1430
|
+
isEnabled(name) {
|
|
1431
|
+
return !this.disabled.has(name);
|
|
1432
|
+
}
|
|
1407
1433
|
setActive(name, config) {
|
|
1408
1434
|
const def = this.defs.get(name);
|
|
1409
1435
|
if (!def)
|
|
1410
1436
|
throw new Error(`Provider not registered: ${name}`);
|
|
1437
|
+
if (this.disabled.has(name)) {
|
|
1438
|
+
throw new Error(`Provider "${name}" is disabled \u2014 enable it first.`);
|
|
1439
|
+
}
|
|
1411
1440
|
let instance = this.instances.get(name);
|
|
1412
1441
|
if (!instance) {
|
|
1413
1442
|
instance = def.createClient(config ?? {});
|
|
@@ -3081,6 +3110,7 @@ var init_session = __esm({
|
|
|
3081
3110
|
readyProviders;
|
|
3082
3111
|
credentialResolver;
|
|
3083
3112
|
mcpAdmin;
|
|
3113
|
+
providerAdmin;
|
|
3084
3114
|
workflows;
|
|
3085
3115
|
pluginsAdmin;
|
|
3086
3116
|
dispatcher;
|
|
@@ -3262,7 +3292,8 @@ var init_session = __esm({
|
|
|
3262
3292
|
// are the ones the desktop's "Fetch live" affordance targets;
|
|
3263
3293
|
// they advertise this via the provider-admin factory by
|
|
3264
3294
|
// setting `supportsLiveModelDiscovery: true` on their def.
|
|
3265
|
-
supportsLiveModelDiscovery: p3.supportsLiveModelDiscovery === true
|
|
3295
|
+
supportsLiveModelDiscovery: p3.supportsLiveModelDiscovery === true,
|
|
3296
|
+
enabled: this.providers.isEnabled(p3.name)
|
|
3266
3297
|
})),
|
|
3267
3298
|
activeMode,
|
|
3268
3299
|
activeModeBadge,
|
|
@@ -127441,6 +127472,15 @@ function noteTemperatureUnsupported() {
|
|
|
127441
127472
|
console.debug("[openai-codex] ProviderRequest.temperature is not supported by the Codex Responses backend (gpt-5 reasoning models reject sampling params); ignoring it.");
|
|
127442
127473
|
}
|
|
127443
127474
|
}
|
|
127475
|
+
var maxTokensNoteShown = false;
|
|
127476
|
+
function noteMaxTokensUnsupported() {
|
|
127477
|
+
if (maxTokensNoteShown)
|
|
127478
|
+
return;
|
|
127479
|
+
maxTokensNoteShown = true;
|
|
127480
|
+
if (process.env.MOXXY_DEBUG) {
|
|
127481
|
+
console.debug("[openai-codex] ProviderRequest.maxTokens is not supported by the Codex Responses backend (400 Unsupported parameter: max_output_tokens); ignoring it.");
|
|
127482
|
+
}
|
|
127483
|
+
}
|
|
127444
127484
|
function toResponsesBody(req, opts = {}) {
|
|
127445
127485
|
const instructions = extractSystemText(req.messages, req.system) || DEFAULT_INSTRUCTIONS;
|
|
127446
127486
|
const body = {
|
|
@@ -127458,7 +127498,7 @@ function toResponsesBody(req, opts = {}) {
|
|
|
127458
127498
|
if (opts.sessionHint)
|
|
127459
127499
|
body.prompt_cache_key = opts.sessionHint;
|
|
127460
127500
|
if (req.maxTokens !== void 0)
|
|
127461
|
-
|
|
127501
|
+
noteMaxTokensUnsupported();
|
|
127462
127502
|
if (req.temperature !== void 0)
|
|
127463
127503
|
noteTemperatureUnsupported();
|
|
127464
127504
|
return body;
|
|
@@ -134757,7 +134797,7 @@ function isRunnerUp(socketPath = runnerSocketPath()) {
|
|
|
134757
134797
|
|
|
134758
134798
|
// ../runner/dist/server.js
|
|
134759
134799
|
init_dist();
|
|
134760
|
-
var RUNNER_PROTOCOL_VERSION =
|
|
134800
|
+
var RUNNER_PROTOCOL_VERSION = 7;
|
|
134761
134801
|
var MIN_COMPATIBLE_PROTOCOL_VERSION = 1;
|
|
134762
134802
|
var RunnerMethod = {
|
|
134763
134803
|
/** client->server: handshake; returns the initial info snapshot. */
|
|
@@ -134782,6 +134822,12 @@ var RunnerMethod = {
|
|
|
134782
134822
|
ModeSetActive: "mode.setActive",
|
|
134783
134823
|
/** client->server: switch the active provider (server resolves credentials). */
|
|
134784
134824
|
ProviderSetActive: "provider.setActive",
|
|
134825
|
+
/** client->server: enable/disable a provider (v7; persists to preferences). */
|
|
134826
|
+
ProviderSetEnabled: "provider.setEnabled",
|
|
134827
|
+
/** client->server: re-probe every provider's credentials → readyProviders (v7). */
|
|
134828
|
+
ProviderRefreshReady: "provider.refreshReady",
|
|
134829
|
+
/** client->server: patch a stored (runtime-registered) provider's config (v7). */
|
|
134830
|
+
ProviderConfigure: "provider.configure",
|
|
134785
134831
|
/** client->server: persist an allow-always permission rule. */
|
|
134786
134832
|
PermissionAddAllow: "permission.addAllow",
|
|
134787
134833
|
/** client->server: run a registered slash command on the runner. */
|
|
@@ -134877,6 +134923,19 @@ var providerSetActiveParamsSchema = z.object({
|
|
|
134877
134923
|
name: z.string(),
|
|
134878
134924
|
config: z.record(z.unknown()).optional()
|
|
134879
134925
|
});
|
|
134926
|
+
var providerSetEnabledParamsSchema = z.object({
|
|
134927
|
+
name: z.string().min(1),
|
|
134928
|
+
enabled: z.boolean()
|
|
134929
|
+
});
|
|
134930
|
+
var providerConfigureParamsSchema = z.object({
|
|
134931
|
+
name: z.string().min(1),
|
|
134932
|
+
patch: z.object({
|
|
134933
|
+
baseURL: z.string().url().optional(),
|
|
134934
|
+
defaultModel: z.string().min(1).optional(),
|
|
134935
|
+
envVar: z.string().regex(/^[A-Z][A-Z0-9_]*$/).optional(),
|
|
134936
|
+
models: z.array(z.object({ id: z.string().min(1), contextWindow: z.number() }).passthrough()).min(1).optional()
|
|
134937
|
+
})
|
|
134938
|
+
});
|
|
134880
134939
|
var permissionAddAllowParamsSchema = z.object({
|
|
134881
134940
|
name: z.string(),
|
|
134882
134941
|
reason: z.string().optional()
|
|
@@ -134983,6 +135042,9 @@ var RunnerServer = class {
|
|
|
134983
135042
|
peer.handle(RunnerMethod.SetResolver, (raw) => this.handleSetResolver(client, raw));
|
|
134984
135043
|
peer.handle(RunnerMethod.ModeSetActive, (raw) => this.handleModeSetActive(raw));
|
|
134985
135044
|
peer.handle(RunnerMethod.ProviderSetActive, (raw) => this.handleProviderSetActive(raw));
|
|
135045
|
+
peer.handle(RunnerMethod.ProviderSetEnabled, (raw) => this.handleProviderSetEnabled(raw));
|
|
135046
|
+
peer.handle(RunnerMethod.ProviderRefreshReady, () => this.handleProviderRefreshReady());
|
|
135047
|
+
peer.handle(RunnerMethod.ProviderConfigure, (raw) => this.handleProviderConfigure(raw));
|
|
134986
135048
|
peer.handle(RunnerMethod.PermissionAddAllow, (raw) => this.handlePermissionAddAllow(raw));
|
|
134987
135049
|
peer.handle(RunnerMethod.CommandRun, (raw) => this.handleCommandRun(raw));
|
|
134988
135050
|
peer.handle(RunnerMethod.Transcribe, (raw) => this.handleTranscribe(raw));
|
|
@@ -135058,6 +135120,7 @@ var RunnerServer = class {
|
|
|
135058
135120
|
turnId,
|
|
135059
135121
|
...error2 ? { error: error2 } : {}
|
|
135060
135122
|
});
|
|
135123
|
+
this.broadcastInfo();
|
|
135061
135124
|
}
|
|
135062
135125
|
});
|
|
135063
135126
|
return { turnId };
|
|
@@ -135122,6 +135185,54 @@ var RunnerServer = class {
|
|
|
135122
135185
|
this.broadcastInfo();
|
|
135123
135186
|
return {};
|
|
135124
135187
|
}
|
|
135188
|
+
async handleProviderSetEnabled(raw) {
|
|
135189
|
+
const { name, enabled } = providerSetEnabledParamsSchema.parse(raw);
|
|
135190
|
+
if (!this.session.providers.list().some((p3) => p3.name === name)) {
|
|
135191
|
+
throw new Error(`Provider not registered: ${name}`);
|
|
135192
|
+
}
|
|
135193
|
+
this.session.providers.setEnabled(name, enabled);
|
|
135194
|
+
void (async () => {
|
|
135195
|
+
const prefs = await loadPreferences();
|
|
135196
|
+
const current = new Set(prefs.disabledProviders ?? []);
|
|
135197
|
+
if (enabled)
|
|
135198
|
+
current.delete(name);
|
|
135199
|
+
else
|
|
135200
|
+
current.add(name);
|
|
135201
|
+
await savePreferences({ disabledProviders: [...current] });
|
|
135202
|
+
})();
|
|
135203
|
+
this.broadcastInfo();
|
|
135204
|
+
return {};
|
|
135205
|
+
}
|
|
135206
|
+
async handleProviderRefreshReady() {
|
|
135207
|
+
const resolver2 = this.session.credentialResolver;
|
|
135208
|
+
if (resolver2) {
|
|
135209
|
+
const ready = /* @__PURE__ */ new Set();
|
|
135210
|
+
const active = this.session.providers.getActiveName();
|
|
135211
|
+
if (active)
|
|
135212
|
+
ready.add(active);
|
|
135213
|
+
for (const p3 of this.session.providers.list()) {
|
|
135214
|
+
if (ready.has(p3.name))
|
|
135215
|
+
continue;
|
|
135216
|
+
try {
|
|
135217
|
+
await resolver2(p3.name);
|
|
135218
|
+
ready.add(p3.name);
|
|
135219
|
+
} catch {
|
|
135220
|
+
}
|
|
135221
|
+
}
|
|
135222
|
+
this.session.readyProviders = ready;
|
|
135223
|
+
}
|
|
135224
|
+
this.broadcastInfo();
|
|
135225
|
+
return {};
|
|
135226
|
+
}
|
|
135227
|
+
async handleProviderConfigure(raw) {
|
|
135228
|
+
const { name, patch } = providerConfigureParamsSchema.parse(raw);
|
|
135229
|
+
const admin = this.session.providerAdmin;
|
|
135230
|
+
if (!admin)
|
|
135231
|
+
throw new Error("provider admin not supported on this runner");
|
|
135232
|
+
await admin.configure(name, patch);
|
|
135233
|
+
this.broadcastInfo();
|
|
135234
|
+
return {};
|
|
135235
|
+
}
|
|
135125
135236
|
async handlePermissionAddAllow(raw) {
|
|
135126
135237
|
const { name, reason } = permissionAddAllowParamsSchema.parse(raw);
|
|
135127
135238
|
await this.session.permissions.addAllow({ name, ...reason ? { reason } : {} });
|
|
@@ -135397,6 +135508,7 @@ var RemoteSession = class {
|
|
|
135397
135508
|
requirements;
|
|
135398
135509
|
permissions;
|
|
135399
135510
|
mcpAdmin;
|
|
135511
|
+
providerAdmin;
|
|
135400
135512
|
workflows;
|
|
135401
135513
|
/**
|
|
135402
135514
|
* Turns that completed before their `runTurn` stream was registered. A fast
|
|
@@ -135410,6 +135522,8 @@ var RemoteSession = class {
|
|
|
135410
135522
|
permissionResolver = null;
|
|
135411
135523
|
approvalResolver = null;
|
|
135412
135524
|
info = null;
|
|
135525
|
+
/** Subscribers to `info.changed` pushes (see {@link onInfoChanged}). */
|
|
135526
|
+
infoListeners = /* @__PURE__ */ new Set();
|
|
135413
135527
|
/**
|
|
135414
135528
|
* The protocol version the SERVER reported at attach. Defaults to our own
|
|
135415
135529
|
* version until the handshake resolves. Version-specific client methods (the
|
|
@@ -135435,6 +135549,12 @@ var RemoteSession = class {
|
|
|
135435
135549
|
});
|
|
135436
135550
|
this.peer.on(RunnerNotification.InfoChanged, (params) => {
|
|
135437
135551
|
this.info = params.info;
|
|
135552
|
+
for (const fn of this.infoListeners) {
|
|
135553
|
+
try {
|
|
135554
|
+
fn(this.info);
|
|
135555
|
+
} catch {
|
|
135556
|
+
}
|
|
135557
|
+
}
|
|
135438
135558
|
});
|
|
135439
135559
|
this.peer.on(RunnerNotification.ReplayStart, (params) => {
|
|
135440
135560
|
const { fromSeq } = params;
|
|
@@ -135472,6 +135592,7 @@ var RemoteSession = class {
|
|
|
135472
135592
|
this.requirements = { check: () => ({ ready: false, issues: [] }) };
|
|
135473
135593
|
this.permissions = this.makePermissionsView();
|
|
135474
135594
|
this.mcpAdmin = this.makeMcpAdminView();
|
|
135595
|
+
this.providerAdmin = this.makeProviderAdminView();
|
|
135475
135596
|
this.workflows = this.makeWorkflowsView();
|
|
135476
135597
|
}
|
|
135477
135598
|
/**
|
|
@@ -135537,6 +135658,16 @@ var RemoteSession = class {
|
|
|
135537
135658
|
getInfo() {
|
|
135538
135659
|
return this.requireInfo();
|
|
135539
135660
|
}
|
|
135661
|
+
/**
|
|
135662
|
+
* Subscribe to runner `info.changed` pushes (registry snapshot changes —
|
|
135663
|
+
* provider/mode/MCP/workflow mutations, including ones made by tools inside
|
|
135664
|
+
* a turn). Fires after the local `getInfo()` mirror has been updated, so a
|
|
135665
|
+
* listener can re-read it synchronously. Returns an unsubscribe fn.
|
|
135666
|
+
*/
|
|
135667
|
+
onInfoChanged(fn) {
|
|
135668
|
+
this.infoListeners.add(fn);
|
|
135669
|
+
return () => this.infoListeners.delete(fn);
|
|
135670
|
+
}
|
|
135540
135671
|
async *runTurn(prompt, opts = {}) {
|
|
135541
135672
|
const result = await this.peer.request(RunnerMethod.RunTurn, {
|
|
135542
135673
|
prompt,
|
|
@@ -135740,6 +135871,27 @@ var RemoteSession = class {
|
|
|
135740
135871
|
detach: (name) => this.peer.request(RunnerMethod.McpDetach, { name })
|
|
135741
135872
|
};
|
|
135742
135873
|
}
|
|
135874
|
+
// Provider management (protocol v7): backs the desktop's interactive
|
|
135875
|
+
// Settings → Providers tab. Gated on the SERVER's reported version so a v7
|
|
135876
|
+
// client attached to an older runner (a desktop whose JS hot-update outran
|
|
135877
|
+
// its bundled CLI) gets a clear "update the CLI" error instead of a raw
|
|
135878
|
+
// method-not-found.
|
|
135879
|
+
makeProviderAdminView() {
|
|
135880
|
+
return {
|
|
135881
|
+
setEnabled: async (name, enabled) => {
|
|
135882
|
+
this.requireServerProtocol(7, "Enabling/disabling a provider");
|
|
135883
|
+
await this.peer.request(RunnerMethod.ProviderSetEnabled, { name, enabled });
|
|
135884
|
+
},
|
|
135885
|
+
refreshReady: async () => {
|
|
135886
|
+
this.requireServerProtocol(7, "Re-probing provider credentials");
|
|
135887
|
+
await this.peer.request(RunnerMethod.ProviderRefreshReady, {});
|
|
135888
|
+
},
|
|
135889
|
+
configure: async (name, patch) => {
|
|
135890
|
+
this.requireServerProtocol(7, "Configuring a provider");
|
|
135891
|
+
await this.peer.request(RunnerMethod.ProviderConfigure, { name, patch });
|
|
135892
|
+
}
|
|
135893
|
+
};
|
|
135894
|
+
}
|
|
135743
135895
|
makeWorkflowsView() {
|
|
135744
135896
|
return {
|
|
135745
135897
|
list: () => this.peer.request(RunnerMethod.WorkflowList),
|
|
@@ -138037,6 +138189,51 @@ var testProviderInput = z$1.object({
|
|
|
138037
138189
|
baseURL: z$1.string().url().describe("Vendor API base URL to probe, e.g. https://api.deepseek.com."),
|
|
138038
138190
|
keyName: z$1.string().regex(/^[A-Z][A-Z0-9_]*$/).describe("NAME of the vault secret holding the API key (e.g. DEEPSEEK_API_KEY). The key is resolved from the vault inside the tool \u2014 never ask the user for the plaintext key and never pass one as a tool argument. Have them store it first: /vault set <NAME> <key>.")
|
|
138039
138191
|
});
|
|
138192
|
+
function buildProviderAdminPluginWithApi(opts) {
|
|
138193
|
+
const { providerRegistry, configPath } = opts;
|
|
138194
|
+
const api = {
|
|
138195
|
+
configure: async (name, patch) => {
|
|
138196
|
+
const cfg = await readProvidersConfig(configPath);
|
|
138197
|
+
const entry = cfg.providers.find((p3) => p3.name === name);
|
|
138198
|
+
if (!entry) {
|
|
138199
|
+
throw new MoxxyError({
|
|
138200
|
+
code: "CONFIG_INVALID",
|
|
138201
|
+
message: `provider-admin: no stored provider named "${name}" \u2014 only runtime-registered (providers.json) providers are configurable; built-ins are code.`
|
|
138202
|
+
});
|
|
138203
|
+
}
|
|
138204
|
+
const next = {
|
|
138205
|
+
...entry,
|
|
138206
|
+
...patch.baseURL ? { baseURL: patch.baseURL } : {},
|
|
138207
|
+
...patch.defaultModel ? { defaultModel: patch.defaultModel } : {},
|
|
138208
|
+
...patch.envVar ? { envVar: patch.envVar } : {},
|
|
138209
|
+
...patch.models && patch.models.length > 0 ? { models: patch.models } : {}
|
|
138210
|
+
};
|
|
138211
|
+
if (!next.models.some((m3) => m3.id === next.defaultModel)) {
|
|
138212
|
+
throw new MoxxyError({
|
|
138213
|
+
code: "CONFIG_INVALID",
|
|
138214
|
+
message: `provider-admin: defaultModel "${next.defaultModel}" is not in the models list (${next.models.map((m3) => m3.id).join(", ")}).`
|
|
138215
|
+
});
|
|
138216
|
+
}
|
|
138217
|
+
const def = buildProviderDef(next);
|
|
138218
|
+
const hadDef = providerRegistry.list().some((p3) => p3.name === name);
|
|
138219
|
+
if (hadDef)
|
|
138220
|
+
providerRegistry.replace(def);
|
|
138221
|
+
else
|
|
138222
|
+
providerRegistry.register(def);
|
|
138223
|
+
try {
|
|
138224
|
+
await upsertStoredProvider(next, configPath);
|
|
138225
|
+
} catch (err) {
|
|
138226
|
+
const prev = buildProviderDef(entry);
|
|
138227
|
+
if (hadDef)
|
|
138228
|
+
providerRegistry.replace(prev);
|
|
138229
|
+
else
|
|
138230
|
+
providerRegistry.unregister(name);
|
|
138231
|
+
throw err;
|
|
138232
|
+
}
|
|
138233
|
+
}
|
|
138234
|
+
};
|
|
138235
|
+
return { plugin: buildProviderAdminPlugin(opts), api };
|
|
138236
|
+
}
|
|
138040
138237
|
function buildProviderAdminPlugin(opts) {
|
|
138041
138238
|
const { providerRegistry, configPath } = opts;
|
|
138042
138239
|
return definePlugin({
|
|
@@ -144027,20 +144224,25 @@ function formatCatalog(entries, emptyLabel) {
|
|
|
144027
144224
|
}
|
|
144028
144225
|
async function draftWorkflow(provider, model, intent, signal, opts = {}) {
|
|
144029
144226
|
let accumulated = "";
|
|
144227
|
+
let truncated = false;
|
|
144228
|
+
const ceiling = provider.models.find((m3) => m3.id === model)?.maxOutputTokens;
|
|
144229
|
+
const budget = Math.min(opts.maxTokens ?? DEFAULT_MAX_TOKENS, ceiling ?? Number.POSITIVE_INFINITY);
|
|
144030
144230
|
for await (const event of provider.stream({
|
|
144031
144231
|
model,
|
|
144032
144232
|
system: buildSystemPrompt(opts),
|
|
144033
144233
|
messages: [{ role: "user", content: [{ type: "text", text: `Build a workflow for: ${intent}` }] }],
|
|
144034
|
-
maxTokens:
|
|
144234
|
+
maxTokens: budget,
|
|
144035
144235
|
signal
|
|
144036
144236
|
})) {
|
|
144037
144237
|
if (event.type === "text_delta")
|
|
144038
144238
|
accumulated += event.delta;
|
|
144239
|
+
if (event.type === "message_end")
|
|
144240
|
+
truncated = event.stopReason === "max_tokens";
|
|
144039
144241
|
if (event.type === "error")
|
|
144040
144242
|
throw new Error(`workflow_create: provider error: ${event.message}`);
|
|
144041
144243
|
}
|
|
144042
144244
|
const raw = extractYamlBlock(accumulated);
|
|
144043
|
-
return { raw, parse: parseWorkflowYaml(raw) };
|
|
144245
|
+
return { raw, parse: parseWorkflowYaml(raw), truncated };
|
|
144044
144246
|
}
|
|
144045
144247
|
function extractYamlBlock(s2) {
|
|
144046
144248
|
const fence = /```(?:ya?ml)?\n([\s\S]*?)```/.exec(s2);
|
|
@@ -144119,7 +144321,7 @@ function createTool(deps) {
|
|
|
144119
144321
|
if (!drafted.parse.ok || !drafted.parse.workflow) {
|
|
144120
144322
|
throw new MoxxyError({
|
|
144121
144323
|
code: "TOOL_ERROR",
|
|
144122
|
-
message: `workflow_create: the model did not produce a valid workflow (${drafted.parse.errors.join("; ")}). Try a more specific intent.`
|
|
144324
|
+
message: drafted.truncated ? "workflow_create: the draft hit the output-token limit before the YAML was complete. Try a simpler intent, or split the workflow into smaller ones." : `workflow_create: the model did not produce a valid workflow (${drafted.parse.errors.join("; ")}). Try a more specific intent.`
|
|
144123
144325
|
});
|
|
144124
144326
|
}
|
|
144125
144327
|
const created = await deps.store.create(drafted.parse.workflow, scope);
|
|
@@ -145292,10 +145494,11 @@ function buildBuiltinsCore(args) {
|
|
|
145292
145494
|
// ~/.moxxy/providers.json; the plugin's onInit re-registers them on
|
|
145293
145495
|
// every boot. Pairs with the `add-provider` skill which walks the
|
|
145294
145496
|
// model through gathering baseURL + models + key.
|
|
145295
|
-
{
|
|
145296
|
-
|
|
145297
|
-
|
|
145298
|
-
|
|
145497
|
+
(() => {
|
|
145498
|
+
const { plugin: plugin4, api } = buildProviderAdminPluginWithApi({ providerRegistry: session.providers });
|
|
145499
|
+
session.providerAdmin = api;
|
|
145500
|
+
return { name: "@moxxy/plugin-provider-admin", plugin: plugin4 };
|
|
145501
|
+
})(),
|
|
145299
145502
|
// Admin tools (mcp_add_server, mcp_list_servers, mcp_remove_server,
|
|
145300
145503
|
// mcp_test_server) plus the boot-time lazy attach. Passing the
|
|
145301
145504
|
// session's live tool registry enables both hot-attach for runtime
|
|
@@ -145794,6 +145997,10 @@ async function activateProvider(args) {
|
|
|
145794
145997
|
} else {
|
|
145795
145998
|
for (let i2 = 0; i2 < candidates.length; i2++) {
|
|
145796
145999
|
const candidate = candidates[i2];
|
|
146000
|
+
if (!session.providers.isEnabled(candidate)) {
|
|
146001
|
+
logger.warn("skipping disabled provider", { provider: candidate });
|
|
146002
|
+
continue;
|
|
146003
|
+
}
|
|
145797
146004
|
const interactive = i2 === 0 && !skipKeyPrompt && process.stdin.isTTY === true;
|
|
145798
146005
|
try {
|
|
145799
146006
|
const resolved = await resolveProviderCredentials(candidate, vault, {
|
|
@@ -146002,6 +146209,13 @@ async function setupSessionWithConfig(opts) {
|
|
|
146002
146209
|
});
|
|
146003
146210
|
await selectEmbedder(session, rawConfig.embeddings, logger);
|
|
146004
146211
|
for (const iso2 of session.isolators.list()) security.registry.register(iso2);
|
|
146212
|
+
try {
|
|
146213
|
+
const bootPrefs = await loadPreferences();
|
|
146214
|
+
for (const name of bootPrefs.disabledProviders ?? []) {
|
|
146215
|
+
session.providers.setEnabled(name, false);
|
|
146216
|
+
}
|
|
146217
|
+
} catch {
|
|
146218
|
+
}
|
|
146005
146219
|
const { credentialResolver } = await activateProvider({
|
|
146006
146220
|
session,
|
|
146007
146221
|
config,
|