@wrongstack/cli 0.298.0 → 0.298.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.
@@ -39,11 +39,11 @@ import {
39
39
  } from "./chunk-XTIXVJXP.js";
40
40
  import {
41
41
  setupPlugins
42
- } from "./chunk-QUNHS6O3.js";
42
+ } from "./chunk-4U3DMA2Y.js";
43
43
  import {
44
44
  PLUGIN_AUDIT_ENTRIES,
45
45
  runPluginManagementCommand
46
- } from "./chunk-XWEGWYDU.js";
46
+ } from "./chunk-PEKUKUCH.js";
47
47
  import {
48
48
  configureSimpleUiRuntimeContext,
49
49
  detectProjectFacts,
@@ -80,11 +80,11 @@ import {
80
80
  runClaudeOAuthLogin,
81
81
  runCopilotOAuthLogin,
82
82
  validateFamily
83
- } from "./chunk-I2BM6FK6.js";
83
+ } from "./chunk-L5CE52XW.js";
84
84
  import {
85
85
  LOCAL_LLM_PRESETS,
86
86
  parseSpawnFlags
87
- } from "./chunk-JBSQ7ONN.js";
87
+ } from "./chunk-ZNZJ34RF.js";
88
88
  import {
89
89
  buildPickableProviders
90
90
  } from "./chunk-66T43Q4Y.js";
@@ -381,6 +381,187 @@ function createAuthPanelHost(deps) {
381
381
  return true;
382
382
  });
383
383
  },
384
+ editModelDetails(providerId, modelId, io) {
385
+ return runFlow(async () => {
386
+ const providers = await loadProviders();
387
+ const cfg = providers[providerId];
388
+ if (!cfg) {
389
+ io.onLog(`\u2717 Provider "${providerId}" no longer in config.`);
390
+ return false;
391
+ }
392
+ const catalogModel = await deps.modelsRegistry.getModel(
393
+ cfg.type && cfg.type !== providerId ? cfg.type : providerId,
394
+ modelId
395
+ ).catch(() => void 0);
396
+ const existing = cfg.customModels?.[modelId];
397
+ const currentMd = existing?.modelsDev ?? {};
398
+ io.onLog(
399
+ catalogModel ? `Catalog reference: ctx=${catalogModel.capabilities.maxContext ?? "?"}, out=${catalogModel.capabilities.maxOutput ?? "?"}` : `(no catalog entry for ${modelId})`
400
+ );
401
+ const name = (await io.prompt(
402
+ `Name (current: ${currentMd["name"] ?? modelId})`,
403
+ { secret: false }
404
+ )).trim();
405
+ const ctxRaw = (await io.prompt(
406
+ `Context window (current: ${currentMd.limit?.["context"] ?? "?"}, catalog: ${catalogModel?.capabilities.maxContext ?? "?"})`,
407
+ { secret: false }
408
+ )).trim();
409
+ const outRaw = (await io.prompt(
410
+ `Max output (current: ${existing?.maxOutput ?? currentMd.limit?.["output"] ?? "?"}, catalog: ${catalogModel?.capabilities.maxOutput ?? "?"})`,
411
+ { secret: false }
412
+ )).trim();
413
+ const costInRaw = (await io.prompt(
414
+ `Cost input $/1M (current: ${currentMd.cost?.["input"] ?? "?"}, catalog: ${catalogModel?.cost?.input ?? "?"})`,
415
+ { secret: false }
416
+ )).trim();
417
+ const costOutRaw = (await io.prompt(
418
+ `Cost output $/1M (current: ${currentMd.cost?.["output"] ?? "?"}, catalog: ${catalogModel?.cost?.output ?? "?"})`,
419
+ { secret: false }
420
+ )).trim();
421
+ const modelsDev = {};
422
+ if (name) modelsDev["name"] = name;
423
+ const limit = {};
424
+ if (ctxRaw) {
425
+ const n = Number(ctxRaw);
426
+ if (!Number.isNaN(n) && n >= 0) limit["context"] = n;
427
+ }
428
+ if (outRaw) {
429
+ const n = Number(outRaw);
430
+ if (!Number.isNaN(n) && n >= 0) limit["output"] = n;
431
+ }
432
+ if (Object.keys(limit).length > 0) modelsDev["limit"] = limit;
433
+ const cost = {};
434
+ if (costInRaw) {
435
+ const n = Number(costInRaw);
436
+ if (!Number.isNaN(n) && n >= 0) cost["input"] = n;
437
+ }
438
+ if (costOutRaw) {
439
+ const n = Number(costOutRaw);
440
+ if (!Number.isNaN(n) && n >= 0) cost["output"] = n;
441
+ }
442
+ if (Object.keys(cost).length > 0) modelsDev["cost"] = cost;
443
+ if (Object.keys(modelsDev).length === 0) {
444
+ io.onLog("(no changes \u2014 nothing entered)");
445
+ return true;
446
+ }
447
+ const err = await mutate((all) => {
448
+ const p = all[providerId];
449
+ if (!p) return `Provider "${providerId}" no longer in config.`;
450
+ if (!p.customModels) p.customModels = {};
451
+ const existingEntry = p.customModels[modelId] ?? {};
452
+ p.customModels[modelId] = {
453
+ ...existingEntry,
454
+ modelsDev: {
455
+ ...existingEntry.modelsDev ?? {},
456
+ ...modelsDev,
457
+ // Deep-merge limit/cost so partial overrides don't wipe sub-fields
458
+ ...limit || existingEntry.modelsDev ? {
459
+ limit: {
460
+ ...existingEntry.modelsDev?.["limit"] ?? {},
461
+ ...limit
462
+ }
463
+ } : {},
464
+ ...cost || existingEntry.modelsDev?.["cost"] ? {
465
+ cost: {
466
+ ...existingEntry.modelsDev?.["cost"] ?? {},
467
+ ...cost
468
+ }
469
+ } : {}
470
+ }
471
+ };
472
+ return null;
473
+ });
474
+ if (err) {
475
+ io.onLog(`\u2717 ${err}`);
476
+ return false;
477
+ }
478
+ io.onLog(`\u2713 ${modelId} updated`);
479
+ return true;
480
+ });
481
+ },
482
+ addModel(providerId, io, opts) {
483
+ return runFlow(async () => {
484
+ const providers = await loadProviders();
485
+ const cfg = providers[providerId];
486
+ if (!cfg) {
487
+ io.onLog(`\u2713 Provider "${providerId}" no longer in config.`);
488
+ return false;
489
+ }
490
+ const modelId = (await io.prompt("Model id", { secret: false })).trim();
491
+ if (!modelId) {
492
+ io.onLog("\u2717 Model id is required.");
493
+ return false;
494
+ }
495
+ if (opts?.fromCatalog) {
496
+ const catalogModel = await deps.modelsRegistry.getModel(
497
+ cfg.type && cfg.type !== providerId ? cfg.type : providerId,
498
+ modelId
499
+ ).catch(() => void 0);
500
+ if (catalogModel) {
501
+ io.onLog(
502
+ `Found in catalog: ctx=${catalogModel.capabilities.maxContext}, out=${catalogModel.capabilities.maxOutput}`
503
+ );
504
+ } else {
505
+ io.onLog(`(not found in catalog \u2014 entering as custom)`);
506
+ }
507
+ }
508
+ const err = await mutate((all) => {
509
+ const p = all[providerId];
510
+ if (!p) return `Provider "${providerId}" no longer in config.`;
511
+ if (!p.models) p.models = [];
512
+ if (!p.models.includes(modelId)) p.models.push(modelId);
513
+ return null;
514
+ });
515
+ if (err) {
516
+ io.onLog(`\u2717 ${err}`);
517
+ return false;
518
+ }
519
+ io.onLog(`\u2713 Added model "${modelId}" to ${providerId}`);
520
+ return true;
521
+ });
522
+ },
523
+ removeModel(providerId, modelId) {
524
+ return (async () => {
525
+ const err = await mutate((all) => {
526
+ const p = all[providerId];
527
+ if (!p) return `Provider "${providerId}" no longer in config.`;
528
+ if (p.models) {
529
+ p.models = p.models.filter((m) => m !== modelId);
530
+ if (p.models.length === 0) delete p.models;
531
+ }
532
+ if (p.customModels && modelId in p.customModels) {
533
+ delete p.customModels[modelId];
534
+ if (Object.keys(p.customModels).length === 0) delete p.customModels;
535
+ }
536
+ return null;
537
+ });
538
+ return err;
539
+ })();
540
+ },
541
+ resetModelToCatalog(providerId, modelId) {
542
+ return (async () => {
543
+ const providers = await loadProviders();
544
+ const cfg = providers[providerId];
545
+ if (!cfg) return `Provider "${providerId}" no longer in config.`;
546
+ const catalogModel = await deps.modelsRegistry.getModel(
547
+ cfg.type && cfg.type !== providerId ? cfg.type : providerId,
548
+ modelId
549
+ ).catch(() => void 0);
550
+ if (!catalogModel) {
551
+ return `Model "${modelId}" not found in catalog \u2014 cannot reset.`;
552
+ }
553
+ const err = await mutate((all) => {
554
+ const p = all[providerId];
555
+ if (!p) return `Provider "${providerId}" no longer in config.`;
556
+ if (p.customModels && modelId in p.customModels) {
557
+ delete p.customModels[modelId];
558
+ if (Object.keys(p.customModels).length === 0) delete p.customModels;
559
+ }
560
+ return null;
561
+ });
562
+ return err;
563
+ })();
564
+ },
384
565
  addCatalogProvider(catalogId, io) {
385
566
  return runFlow(async () => {
386
567
  const catalog = await deps.modelsRegistry.listProviders();
@@ -2842,7 +3023,7 @@ import {
2842
3023
  } from "@wrongstack/acp";
2843
3024
  import { ToolValidationError } from "@wrongstack/core/types";
2844
3025
  function buildAcpSubagentRunner(subagentId) {
2845
- let cmd = ACP_AGENT_COMMANDS[subagentId];
3026
+ let cmd = Object.prototype.hasOwnProperty.call(ACP_AGENT_COMMANDS, subagentId) ? ACP_AGENT_COMMANDS[subagentId] : void 0;
2846
3027
  if (!cmd) {
2847
3028
  const desc = findAgentDescriptor(subagentId);
2848
3029
  if (desc) {
@@ -3182,6 +3363,75 @@ import { DefaultTokenCounter } from "@wrongstack/core/infrastructure";
3182
3363
  import { EventBus } from "@wrongstack/core/kernel";
3183
3364
  import { AutoApprovePermissionPolicy } from "@wrongstack/core/security";
3184
3365
 
3366
+ // src/fleet/host-context.ts
3367
+ import { TOKENS as TOKENS2 } from "@wrongstack/core/kernel";
3368
+ import { getSageRetrieval } from "@wrongstack/sage";
3369
+ async function resolveHostSubagentSkillContent(deps, roster, subCfg) {
3370
+ const rosterSkillNames = subCfg.role ? roster[subCfg.role]?.skillNames : void 0;
3371
+ const skillNames = [...new Set(subCfg.skillNames ?? rosterSkillNames ?? [])];
3372
+ const directContent = subCfg.skillContent?.trim();
3373
+ if (skillNames.length === 0 || !deps.skillLoader) return directContent ?? "";
3374
+ const resolved = [];
3375
+ let usedChars = 0;
3376
+ const maxChars = 16e3;
3377
+ const maxCharsPerSkill = 4e3;
3378
+ for (const skillName of skillNames) {
3379
+ try {
3380
+ const manifest = await deps.skillLoader.find(skillName);
3381
+ if (!manifest) continue;
3382
+ const body = (await deps.skillLoader.readSaveBody(skillName)).trim();
3383
+ if (!body) continue;
3384
+ const entry = `## Skill: ${skillName}
3385
+
3386
+ ${body.slice(0, maxCharsPerSkill)}`;
3387
+ if (usedChars + entry.length > maxChars) {
3388
+ console.warn(
3389
+ `[MultiAgentHost] resolveSubagentSkillContent: budget (${maxChars}) exhausted after ${resolved.length} skill(s); dropping "${skillName}" and remaining skills`
3390
+ );
3391
+ break;
3392
+ }
3393
+ resolved.push(entry);
3394
+ usedChars += entry.length;
3395
+ } catch {
3396
+ }
3397
+ }
3398
+ const sections = [
3399
+ directContent,
3400
+ resolved.length > 0 ? `# Role-prioritized skills
3401
+
3402
+ Apply these skills first for this assignment.
3403
+
3404
+ ${resolved.join("\n\n---\n\n")}` : void 0
3405
+ ].filter((section) => Boolean(section));
3406
+ return sections.join("\n\n");
3407
+ }
3408
+ async function retrieveHostSubagentMemory(deps, getLeaderMode, subCfg, taskContext) {
3409
+ const memoryPort = deps.container.safeResolve(TOKENS2.MemoryStore);
3410
+ const memory = memoryPort ? getSageRetrieval(memoryPort) : void 0;
3411
+ if (!memory?.retrieveForAudience) return [];
3412
+ const contextualTaskType = typeof taskContext?.["taskType"] === "string" ? taskContext["taskType"] : void 0;
3413
+ try {
3414
+ const taskType = subCfg.memoryContext?.taskType ?? contextualTaskType;
3415
+ const mode = subCfg.memoryContext?.mode ?? getLeaderMode?.();
3416
+ const matches = await memory.retrieveForAudience(
3417
+ {
3418
+ ...subCfg.role !== void 0 ? { role: subCfg.role } : {},
3419
+ ...taskType !== void 0 ? { taskType } : {},
3420
+ ...mode !== void 0 ? { mode } : {}
3421
+ },
3422
+ 20
3423
+ );
3424
+ await memory.recordInjection?.(
3425
+ matches.map((item) => item.id),
3426
+ "subagent_audience",
3427
+ deps.session.id
3428
+ );
3429
+ return matches.map((item) => item.text);
3430
+ } catch {
3431
+ return [];
3432
+ }
3433
+ }
3434
+
3185
3435
  // src/fleet/host-event-bridge.ts
3186
3436
  import * as path4 from "node:path";
3187
3437
  var BRIDGE_TEXT_CAP = 360;
@@ -3352,106 +3602,6 @@ function installSubagentEventBridge(opts) {
3352
3602
  };
3353
3603
  }
3354
3604
 
3355
- // src/fleet/host-session-writer.ts
3356
- function createParentSubagentSessionWriter(parentSession) {
3357
- return {
3358
- id: parentSession.id,
3359
- transcriptPath: parentSession.transcriptPath,
3360
- get pendingToolUses() {
3361
- return [];
3362
- },
3363
- append: (event) => parentSession.append({ ...event }),
3364
- appendBatch: (events) => parentSession.appendBatch(events.map((event) => ({ ...event }))),
3365
- flush: () => parentSession.flush(),
3366
- close: async () => {
3367
- },
3368
- recordFileChange: () => {
3369
- },
3370
- recordSideEffect: () => {
3371
- },
3372
- writeCheckpoint: async () => {
3373
- },
3374
- writeFileSnapshot: async () => {
3375
- },
3376
- truncateToCheckpoint: async () => 0,
3377
- clearSession: async () => {
3378
- },
3379
- writeInFlightMarker: async () => {
3380
- },
3381
- clearInFlightMarker: async () => {
3382
- }
3383
- };
3384
- }
3385
-
3386
- // src/fleet/host-context.ts
3387
- import { TOKENS as TOKENS2 } from "@wrongstack/core/kernel";
3388
- import { getSageRetrieval } from "@wrongstack/sage";
3389
- async function resolveHostSubagentSkillContent(deps, roster, subCfg) {
3390
- const rosterSkillNames = subCfg.role ? roster[subCfg.role]?.skillNames : void 0;
3391
- const skillNames = [...new Set(subCfg.skillNames ?? rosterSkillNames ?? [])];
3392
- const directContent = subCfg.skillContent?.trim();
3393
- if (skillNames.length === 0 || !deps.skillLoader) return directContent ?? "";
3394
- const resolved = [];
3395
- let usedChars = 0;
3396
- const maxChars = 16e3;
3397
- const maxCharsPerSkill = 4e3;
3398
- for (const skillName of skillNames) {
3399
- try {
3400
- const manifest = await deps.skillLoader.find(skillName);
3401
- if (!manifest) continue;
3402
- const body = (await deps.skillLoader.readSaveBody(skillName)).trim();
3403
- if (!body) continue;
3404
- const entry = `## Skill: ${skillName}
3405
-
3406
- ${body.slice(0, maxCharsPerSkill)}`;
3407
- if (usedChars + entry.length > maxChars) {
3408
- console.warn(
3409
- `[MultiAgentHost] resolveSubagentSkillContent: budget (${maxChars}) exhausted after ${resolved.length} skill(s); dropping "${skillName}" and remaining skills`
3410
- );
3411
- break;
3412
- }
3413
- resolved.push(entry);
3414
- usedChars += entry.length;
3415
- } catch {
3416
- }
3417
- }
3418
- const sections = [
3419
- directContent,
3420
- resolved.length > 0 ? `# Role-prioritized skills
3421
-
3422
- Apply these skills first for this assignment.
3423
-
3424
- ${resolved.join("\n\n---\n\n")}` : void 0
3425
- ].filter((section) => Boolean(section));
3426
- return sections.join("\n\n");
3427
- }
3428
- async function retrieveHostSubagentMemory(deps, getLeaderMode, subCfg, taskContext) {
3429
- const memoryPort = deps.container.safeResolve(TOKENS2.MemoryStore);
3430
- const memory = memoryPort ? getSageRetrieval(memoryPort) : void 0;
3431
- if (!memory?.retrieveForAudience) return [];
3432
- const contextualTaskType = typeof taskContext?.["taskType"] === "string" ? taskContext["taskType"] : void 0;
3433
- try {
3434
- const taskType = subCfg.memoryContext?.taskType ?? contextualTaskType;
3435
- const mode = subCfg.memoryContext?.mode ?? getLeaderMode?.();
3436
- const matches = await memory.retrieveForAudience(
3437
- {
3438
- ...subCfg.role !== void 0 ? { role: subCfg.role } : {},
3439
- ...taskType !== void 0 ? { taskType } : {},
3440
- ...mode !== void 0 ? { mode } : {}
3441
- },
3442
- 20
3443
- );
3444
- await memory.recordInjection?.(
3445
- matches.map((item) => item.id),
3446
- "subagent_audience",
3447
- deps.session.id
3448
- );
3449
- return matches.map((item) => item.text);
3450
- } catch {
3451
- return [];
3452
- }
3453
- }
3454
-
3455
3605
  // src/fleet/host-provider.ts
3456
3606
  import { makeProviderFromConfig, withCatalogCapabilities } from "@wrongstack/providers";
3457
3607
  async function buildHostSubagentProvider(deps, config, overrideId, model) {
@@ -3532,6 +3682,37 @@ function resolveHostSubagentModelSelection(liveConfig, effectiveCfg, matrixTarge
3532
3682
  };
3533
3683
  }
3534
3684
 
3685
+ // src/fleet/host-session-writer.ts
3686
+ function createParentSubagentSessionWriter(parentSession) {
3687
+ return {
3688
+ id: parentSession.id,
3689
+ transcriptPath: parentSession.transcriptPath,
3690
+ get pendingToolUses() {
3691
+ return [];
3692
+ },
3693
+ append: (event) => parentSession.append({ ...event }),
3694
+ appendBatch: (events) => parentSession.appendBatch(events.map((event) => ({ ...event }))),
3695
+ flush: () => parentSession.flush(),
3696
+ close: async () => {
3697
+ },
3698
+ recordFileChange: () => {
3699
+ },
3700
+ recordSideEffect: () => {
3701
+ },
3702
+ writeCheckpoint: async () => {
3703
+ },
3704
+ writeFileSnapshot: async () => {
3705
+ },
3706
+ truncateToCheckpoint: async () => 0,
3707
+ clearSession: async () => {
3708
+ },
3709
+ writeInFlightMarker: async () => {
3710
+ },
3711
+ clearInFlightMarker: async () => {
3712
+ }
3713
+ };
3714
+ }
3715
+
3535
3716
  // src/fleet/host-subagent-factory.ts
3536
3717
  function createHostSubagentFactory(config, host) {
3537
3718
  return async (subCfg, task) => {
@@ -3544,7 +3725,14 @@ function createHostSubagentFactory(config, host) {
3544
3725
  const effectiveCfg = projectCfg ? applyProjectAgentConfig(subCfg, projectCfg, {
3545
3726
  protectSystemRole: isSystemRole
3546
3727
  }) : subCfg;
3547
- const matrixTarget = effectiveCfg.model ? void 0 : resolveSubagentModelTarget(liveConfig, effectiveCfg.role);
3728
+ const matrixTarget = effectiveCfg.model ? void 0 : resolveSubagentModelTarget(liveConfig, effectiveCfg.role, {
3729
+ // Thread the shared tracker so the resolved matrix target skips
3730
+ // (provider, model) pairs currently in the waiting room. Without
3731
+ // this, the subagent factory would seed its own primary from a
3732
+ // doomed model the leader just 429-stricken, and the fallback
3733
+ // extension would have to spend a turn rotating away.
3734
+ ...host.opts.statusTracker ? { statusTracker: host.opts.statusTracker } : {}
3735
+ });
3548
3736
  const modelSelection = resolveHostSubagentModelSelection(
3549
3737
  liveConfig,
3550
3738
  effectiveCfg,
@@ -3573,8 +3761,7 @@ function createHostSubagentFactory(config, host) {
3573
3761
  providerError = err;
3574
3762
  }
3575
3763
  }
3576
- if (!provider)
3577
- throw providerError ?? new Error("No permitted provider/model could be built.");
3764
+ if (!provider) throw providerError ?? new Error("No permitted provider/model could be built.");
3578
3765
  let subReasoningConfig = await resolveHostSubagentReasoningConfig(
3579
3766
  host.deps,
3580
3767
  effProvider,
@@ -13094,7 +13281,7 @@ function buildDoctorCommand(opts) {
13094
13281
  ].join("\n");
13095
13282
  async function loadPluginSchemas() {
13096
13283
  try {
13097
- const { BUILTIN_PLUGIN_FACTORIES } = await import("./plugins-4LJ5IUBI.js");
13284
+ const { BUILTIN_PLUGIN_FACTORIES } = await import("./plugins-ETY6W3DC.js");
13098
13285
  const settled = await Promise.allSettled(BUILTIN_PLUGIN_FACTORIES.map((f) => f()));
13099
13286
  const loaded = [];
13100
13287
  for (const s of settled) {
@@ -29806,7 +29993,7 @@ async function runInteractive(cliCtx) {
29806
29993
  onEvent: evOn
29807
29994
  });
29808
29995
  const savedProviderCfg = config.providers?.[config.provider];
29809
- const { execute } = await import("./execution-INOV5P7N.js");
29996
+ const { execute } = await import("./execution-BY556FCF.js");
29810
29997
  const stopHeapWatchdog = startSharedHeapWatchdog({
29811
29998
  collectStats: () => {
29812
29999
  const hqQueue = hqPublisherRef.current?.getQueueStats();
@@ -30038,4 +30225,4 @@ export {
30038
30225
  CLI_VERSION,
30039
30226
  runInteractive
30040
30227
  };
30041
- //# sourceMappingURL=cli-main-TJEU4OUY.js.map
30228
+ //# sourceMappingURL=cli-main-ZDZMCVLM.js.map