@wrongstack/cli 1.1.4 → 1.1.6

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.
Files changed (103) hide show
  1. package/dist/{acp-MZ5MQBFN.js → acp-CZBSFQB7.js} +6 -5
  2. package/dist/acp-leader/acp-leader-confirm.d.ts +2 -0
  3. package/dist/acp-leader/acp-leader-host-binding.d.ts +1 -0
  4. package/dist/acp-leader/acp-leader-host.d.ts +9 -0
  5. package/dist/acp-leader/acp-leader-picker.d.ts +6 -3
  6. package/dist/acp-leader/acp-leader-provider.d.ts +10 -0
  7. package/dist/acp-leader/acp-leader-skills.d.ts +5 -0
  8. package/dist/acp-leader/acp-leader-stream.d.ts +9 -0
  9. package/dist/{auth-IHQS6AFW.js → auth-2ZG5DBHS.js} +4 -4
  10. package/dist/boot/launch-menu-arrow.d.ts +20 -0
  11. package/dist/boot/launch-menu-types.d.ts +36 -0
  12. package/dist/boot/launch-menu.d.ts +1 -57
  13. package/dist/boot/tui-session-resume-rollback.d.ts +31 -0
  14. package/dist/{boot-auto-thin-7D4OVEWA.js → boot-auto-thin-N2CIGTXE.js} +3 -3
  15. package/dist/{chunk-TZPKOS5G.js → chunk-2XQ6SRKG.js} +2 -2
  16. package/dist/{chunk-3EXRPTAU.js → chunk-5TQ65PXQ.js} +17 -17
  17. package/dist/{chunk-VAQXOZKP.js → chunk-AJM4EFCM.js} +139 -136
  18. package/dist/{chunk-C2BBH4S4.js → chunk-E3MJFAFR.js} +2 -2
  19. package/dist/{chunk-COGI7EQU.js → chunk-EAATL6FL.js} +713 -21
  20. package/dist/{chunk-AWRZWPJ3.js → chunk-FWUIKCCO.js} +152 -123
  21. package/dist/{chunk-TAE3EGBM.js → chunk-H5DCQFUI.js} +5 -5
  22. package/dist/{chunk-BIGSVBPI.js → chunk-KNYIEQAY.js} +64 -61
  23. package/dist/chunk-LYWOV4OX.js +252 -0
  24. package/dist/{chunk-75OLD563.js → chunk-M7PSENGF.js} +3 -1
  25. package/dist/{chunk-I5LJLKA3.js → chunk-MKMM5RIW.js} +12 -5
  26. package/dist/{chunk-ZF4HRR5F.js → chunk-P7MEEUGT.js} +275 -250
  27. package/dist/chunk-PGC44T7N.js +255 -0
  28. package/dist/chunk-QLYPIJ7X.js +258 -0
  29. package/dist/{chunk-JKTJSLUT.js → chunk-QRWXHGLB.js} +242 -18
  30. package/dist/chunk-RN5CFAVQ.js +292 -0
  31. package/dist/{chunk-WDXNBYGD.js → chunk-TDP7CZGE.js} +6 -1
  32. package/dist/{chunk-6VPWQ4TG.js → chunk-UROB7MK5.js} +2 -1
  33. package/dist/{chunk-IJLIAPCW.js → chunk-VPSAKGLK.js} +47 -47
  34. package/dist/{chunk-2LTHDKZX.js → chunk-W7X23HI6.js} +18 -18
  35. package/dist/{chunk-GKGWPFW2.js → chunk-X4DEQLAZ.js} +1 -1
  36. package/dist/{cli-context-E44HQ4ZO.js → cli-context-6KS3HV5R.js} +247 -236
  37. package/dist/{cli-main-OT63I2FX.js → cli-main-NF3YGDME.js} +1779 -1494
  38. package/dist/cli-main-boot.d.ts +1 -1
  39. package/dist/config-doctor-known-keys.d.ts +33 -0
  40. package/dist/config-doctor.d.ts +2 -47
  41. package/dist/config-history-support.d.ts +36 -0
  42. package/dist/config-history.d.ts +1 -1
  43. package/dist/{config-transfer-Y7XJMJRN.js → config-transfer-B4GOZTFC.js} +2 -2
  44. package/dist/{execution-OK34CJKJ.js → execution-RVDUXLNT.js} +6522 -6426
  45. package/dist/execution-tui.d.ts +30 -0
  46. package/dist/fleet/acp-wrongstack-bridge.d.ts +11 -3
  47. package/dist/fleet/host-acp.d.ts +3 -0
  48. package/dist/fleet/wrongforge-client.d.ts +116 -0
  49. package/dist/fleet/wrongforge-gateway.d.ts +20 -0
  50. package/dist/fleet/wrongforge-info.d.ts +32 -0
  51. package/dist/fleet/wrongforge-quota.d.ts +10 -0
  52. package/dist/fleet/wrongforge-runner.d.ts +37 -0
  53. package/dist/fleet/wrongforge-runtime.d.ts +10 -0
  54. package/dist/{hq-JD5AZVMG.js → hq-V2M4IYCI.js} +320 -306
  55. package/dist/hq-server/login-attempt-store.d.ts +2 -0
  56. package/dist/hq-server/sweeps.d.ts +28 -0
  57. package/dist/{hq-server-BI23EPM7.js → hq-server-QM7EIVGJ.js} +3 -3
  58. package/dist/index.js +5 -5
  59. package/dist/mcp-22CFBX4H.js +236 -0
  60. package/dist/mcp-serve.d.ts +0 -63
  61. package/dist/{modeldiag-HDIKG37X.js → modeldiag-5PBB777J.js} +4 -4
  62. package/dist/{per-subcommand-help-4GYSCMLU.js → per-subcommand-help-MQGERD4E.js} +2 -2
  63. package/dist/plugin-llm-command.d.ts +9 -0
  64. package/dist/{plugin-usage-TYF5HY4K.js → plugin-usage-UWKYMNQU.js} +3 -3
  65. package/dist/{plugins-XGAXDLPT.js → plugins-VP7JQH47.js} +4 -4
  66. package/dist/{sdd-runtime-6MFUXWJK.js → sdd-runtime-HIJ4Z5TF.js} +2 -2
  67. package/dist/services/sdd/state.d.ts +2 -0
  68. package/dist/session-event-wiring-types.d.ts +62 -0
  69. package/dist/session-event-wiring.d.ts +2 -52
  70. package/dist/{sessions-config-SJVQXCIE.js → sessions-config-7MK742OW.js} +2 -2
  71. package/dist/short-circuit-flags-276OLPIN.js +11 -0
  72. package/dist/slash-commands/command-context-fleet.d.ts +187 -0
  73. package/dist/slash-commands/command-context-sdd-goal.d.ts +102 -0
  74. package/dist/slash-commands/command-context.d.ts +3 -282
  75. package/dist/slash-commands/project-switch-interactive.d.ts +11 -0
  76. package/dist/slash-commands/setmodel-helpers.d.ts +36 -0
  77. package/dist/subcommands/handlers/hq-token.d.ts +3 -0
  78. package/dist/subcommands/handlers/hq.d.ts +0 -21
  79. package/dist/subcommands/handlers/per-subcommand-help-operations.d.ts +8 -0
  80. package/dist/subcommands/handlers/tools-cli-args.d.ts +57 -0
  81. package/dist/subcommands/handlers/tools-cli.d.ts +5 -0
  82. package/dist/subcommands/handlers/tools-serve.d.ts +4 -0
  83. package/dist/{subcommands-YADUV7IJ.js → subcommands-SKJPUJ7N.js} +2 -2
  84. package/dist/tool-gateway-http.d.ts +30 -0
  85. package/dist/tool-gateway.d.ts +185 -0
  86. package/dist/tools-cli-44MLIUQO.js +509 -0
  87. package/dist/tools-serve-TRCET2M7.js +102 -0
  88. package/dist/{tools-skills-55QVTMSK.js → tools-skills-WDTMCE46.js} +7 -2
  89. package/dist/tuneup-runtime-checks.d.ts +7 -0
  90. package/dist/tuneup-types.d.ts +118 -0
  91. package/dist/tuneup.d.ts +3 -122
  92. package/dist/{typesafe-YBEADNAH.js → typesafe-QLSMFU7J.js} +1 -1
  93. package/dist/{version-help-RBZC5GZZ.js → version-help-X6CC4CFY.js} +2 -2
  94. package/dist/{webui-server-CB64CFDG.js → webui-server-6I6QOECV.js} +44 -6
  95. package/dist/wiring/provider-runtime-setup.d.ts +3 -1
  96. package/dist/wiring/session-runtime.d.ts +1 -1
  97. package/dist/wrongforge-gateway-UOFBK56J.js +92 -0
  98. package/dist/wrongforge-leader/wrongforge-leader-gateway.d.ts +9 -0
  99. package/dist/wrongforge-leader/wrongforge-leader-picker.d.ts +12 -0
  100. package/dist/wrongforge-leader/wrongforge-leader-provider.d.ts +56 -0
  101. package/package.json +1 -1
  102. package/dist/mcp-W7A5HUXV.js +0 -560
  103. package/dist/short-circuit-flags-QEXUS3BY.js +0 -11
@@ -1,9 +1,27 @@
1
1
  import {
2
+ parseWrongForgeInfo,
3
+ reportWrongForgeQuota,
4
+ writeWrongForgeInfoCache,
2
5
  wrongstackBridgeSetup
3
- } from "./chunk-JKTJSLUT.js";
6
+ } from "./chunk-QRWXHGLB.js";
4
7
  import {
5
8
  isRestrictedMode
6
9
  } from "./chunk-3LEIFO5D.js";
10
+ import {
11
+ WRONGFORGE_AGENT_ID,
12
+ WRONGFORGE_READ_SIDE_TOOLS,
13
+ WfAborted,
14
+ WfHttpError,
15
+ cancelTask,
16
+ chooseModel,
17
+ followTask,
18
+ resolveWrongForgeEndpoint,
19
+ safeWfId,
20
+ terminalTaskRecord,
21
+ toProgress,
22
+ wfTokens,
23
+ wrongForgeCall
24
+ } from "./chunk-PGC44T7N.js";
7
25
  import {
8
26
  buildProviderForId,
9
27
  resolveProviderCfgWithProxy
@@ -12,7 +30,7 @@ import {
12
30
  ACP_LEADER_PROVIDER_ID,
13
31
  acpLeaderHost,
14
32
  trackAcpLeader
15
- } from "./chunk-GKGWPFW2.js";
33
+ } from "./chunk-X4DEQLAZ.js";
16
34
 
17
35
  // src/acp-agent-list.ts
18
36
  import { REGISTRY_ID_ALIASES } from "@wrongstack/acp";
@@ -449,6 +467,7 @@ function startAcpTurnReminders(options) {
449
467
 
450
468
  // src/acp-leader/acp-leader-confirm.ts
451
469
  import { confirmObserverCount } from "@wrongstack/core/agent";
470
+ import { DEFAULT_ALWAYS_TRUST_TTL_MS, scopedApprovalPattern } from "@wrongstack/core/security";
452
471
  var ACP_CONFIRM_TIMEOUT_MS = 12e4;
453
472
  async function confirmThroughEvents(req) {
454
473
  if (req.events.listenerCount("tool.confirm_needed") - confirmObserverCount() <= 0) return false;
@@ -489,10 +508,22 @@ async function confirmThroughEvents(req) {
489
508
  });
490
509
  });
491
510
  if (answer === "abort" || answer === "no") return false;
492
- const rule = { tool: req.tool.name, pattern: req.suggestedPattern };
493
511
  try {
494
- if (answer === "deny") await req.permission?.deny(rule);
495
- else if (answer !== "yes") await req.permission?.trust(rule);
512
+ if (answer === "deny") {
513
+ await req.permission?.deny({ tool: req.tool.name, pattern: req.suggestedPattern });
514
+ } else if (answer !== "yes") {
515
+ await req.permission?.trust({
516
+ tool: req.tool.name,
517
+ pattern: scopedApprovalPattern(
518
+ answer,
519
+ req.tool,
520
+ req.input,
521
+ req.context,
522
+ req.suggestedPattern
523
+ ),
524
+ ttlMs: DEFAULT_ALWAYS_TRUST_TTL_MS
525
+ });
526
+ }
496
527
  } catch {
497
528
  }
498
529
  return answer !== "deny";
@@ -538,6 +569,7 @@ function publishLeaderContext(events, sessionId, reading, fallbackMaxContext) {
538
569
 
539
570
  // src/acp-leader/acp-leader-fleet.ts
540
571
  import { randomBytes } from "node:crypto";
572
+ import { toErrorMessage as toErrorMessage2 } from "@wrongstack/core/utils";
541
573
  import { MCPServer, serveHttp } from "@wrongstack/mcp";
542
574
  var FLEET_SERVER_NAME = "wrongstack-fleet";
543
575
  var FLEET_TOOLS = [
@@ -548,7 +580,10 @@ var FLEET_TOOLS = [
548
580
  "roll_up",
549
581
  "fleet_status",
550
582
  "session_note",
551
- "terminate_subagent"
583
+ "terminate_subagent",
584
+ // Not a fleet tool, but it too must run in this process: WrongStack's
585
+ // skills (a /bughunt playbook) reach the agent only through it.
586
+ "skill"
552
587
  ];
553
588
  var MCP_PREFIX = `mcp__${FLEET_SERVER_NAME}__`;
554
589
  function fleetToolName(mcpName) {
@@ -574,7 +609,11 @@ async function startFleetEndpoint(host, run) {
574
609
  if (!offered.has(name)) {
575
610
  return { content: `Tool "${name}" is not offered here`, isError: true };
576
611
  }
577
- return run ? host.runTool(name, args, run) : host.runTool(name, args);
612
+ try {
613
+ return await (run ? host.runTool(name, args, run) : host.runTool(name, args));
614
+ } catch (err) {
615
+ return { content: `Failed to execute ${name}: ${toErrorMessage2(err)}`, isError: true };
616
+ }
578
617
  }
579
618
  }
580
619
  });
@@ -600,7 +639,11 @@ function fleetNote(tools) {
600
639
  ...has("fleet_status") ? ["- fleet_status: what is running and its progress."] : [],
601
640
  ...has("roll_up") ? ["- roll_up: the full result of finished tasks."] : [],
602
641
  ...has("session_note") ? ["- session_note: steer a running worker."] : [],
603
- ...has("terminate_subagent") ? ["- terminate_subagent: stop a worker."] : []
642
+ ...has("terminate_subagent") ? ["- terminate_subagent: stop a worker."] : [],
643
+ ...has("skill") ? [
644
+ "- skill: load one of WrongStack's skills by name (follow nextOffset to the last page);",
645
+ " a task that names WrongStack skills means these."
646
+ ] : []
604
647
  ].join("\n");
605
648
  }
606
649
 
@@ -643,9 +686,28 @@ function writeLeaderSession(stateDir, sessionId, record) {
643
686
  return writing.catch(() => void 0);
644
687
  }
645
688
 
689
+ // src/acp-leader/acp-leader-skills.ts
690
+ import { parseRequiredSkillsMarker } from "@wrongstack/core/skills";
691
+ var MARKERS = /<!--\s*wrongstack:required-skills\s+[\s\S]*?-->/g;
692
+ function externalSkillLoader(offered, prefix) {
693
+ return offered?.includes("skill") ? `${prefix}skill` : void 0;
694
+ }
695
+ function externalSkillDirective(text, loader) {
696
+ const skills = parseRequiredSkillsMarker(text);
697
+ if (!skills) return text;
698
+ const list = skills.join(", ");
699
+ const line = loader ? `[WrongStack] This task's playbook skills: ${list}. They are WrongStack skills: load each with the \`${loader}\` tool, following nextOffset to the last page, before changing code. Where the text below names the \`skill\` tool or a $name, it means that tool and these skills.` : `[WrongStack] This task's playbook skills: ${list}. This route offers no WrongStack skill tool: load them with your own skill tool if you have them, otherwise follow the protocol below without them.`;
700
+ let first = true;
701
+ return text.replace(MARKERS, () => {
702
+ if (!first) return "";
703
+ first = false;
704
+ return line;
705
+ });
706
+ }
707
+
646
708
  // src/acp-leader/acp-leader-stream.ts
647
709
  import { ProviderError } from "@wrongstack/core/types";
648
- import { toErrorMessage as toErrorMessage2 } from "@wrongstack/core/utils";
710
+ import { toErrorMessage as toErrorMessage3 } from "@wrongstack/core/utils";
649
711
  var StreamQueue = class {
650
712
  items = [];
651
713
  wake;
@@ -711,10 +773,7 @@ function clip(text, max) {
711
773
  if (last >= 55296 && last <= 56319) end -= 1;
712
774
  return `${text.slice(0, end)}\u2026`;
713
775
  }
714
- function cardOutput(call) {
715
- const raw = call.rawOutput;
716
- const text = call.output ?? (raw ? typeof raw.output === "string" ? raw.output : JSON.stringify(raw) : void 0);
717
- if (text === void 0) return void 0;
776
+ function cardOutputForText(text) {
718
777
  const output = clip(text, OUTPUT_PREVIEW_CHARS);
719
778
  return {
720
779
  output,
@@ -723,6 +782,12 @@ function cardOutput(call) {
723
782
  outputBytes: Buffer.byteLength(text)
724
783
  };
725
784
  }
785
+ function cardOutput(call) {
786
+ const raw = call.rawOutput;
787
+ const text = call.output ?? (raw ? typeof raw.output === "string" ? raw.output : JSON.stringify(raw) : void 0);
788
+ if (text === void 0) return void 0;
789
+ return cardOutputForText(text);
790
+ }
726
791
  var ToolCardRelay = class {
727
792
  constructor(events, meta) {
728
793
  this.events = events;
@@ -744,7 +809,7 @@ var ToolCardRelay = class {
744
809
  name,
745
810
  id,
746
811
  input: call.rawInput,
747
- provider: "acp",
812
+ provider: this.meta.provider ?? "acp",
748
813
  model: this.meta.model
749
814
  });
750
815
  }
@@ -855,7 +920,7 @@ function agentTurnError(err, agentId, classify) {
855
920
  };
856
921
  }
857
922
  const kind = err?.kind;
858
- const message = `${agentId}: ${toErrorMessage2(err)}`;
923
+ const message = `${agentId}: ${toErrorMessage3(err)}`;
859
924
  if (kind === "stalled") {
860
925
  return {
861
926
  error: new ProviderError(message, 408, false, "acp", { kind: "timeout", cause: err }),
@@ -910,8 +975,11 @@ function parseSideModel(ref) {
910
975
  if (provider === ACP_LEADER_PROVIDER_ID) return void 0;
911
976
  return { provider, model: ref.slice(slash + 1) };
912
977
  }
978
+ function explicitLeaderSideModel(config) {
979
+ return parseSideModel(config.acp?.leader?.sideModel);
980
+ }
913
981
  function leaderSideModel(config) {
914
- return parseSideModel(config.acp?.leader?.sideModel) ?? parseSideModel(config.fallbackBridge) ?? parseSideModel(config.fallbackModels?.[0]);
982
+ return explicitLeaderSideModel(config) ?? parseSideModel(config.fallbackBridge) ?? parseSideModel(config.fallbackModels?.[0]);
915
983
  }
916
984
  function isLeaderTurn(req) {
917
985
  const { sessionId, threadId } = req.cache ?? {};
@@ -1029,7 +1097,10 @@ var AcpLeaderProvider = class {
1029
1097
  }
1030
1098
  /** The turn's prompt; an agent joining a conversation under way gets the turns before it. */
1031
1099
  promptText(leader, req) {
1032
- const latest = latestUserText(req.messages);
1100
+ const latest = externalSkillDirective(
1101
+ latestUserText(req.messages),
1102
+ externalSkillLoader(leader.fleet?.tools, `mcp__${FLEET_SERVER_NAME}__`)
1103
+ );
1033
1104
  const earlier = leader.joined ? void 0 : earlierConversation(req.messages);
1034
1105
  leader.joined = true;
1035
1106
  const prompt = earlier ? `${earlier}
@@ -1105,8 +1176,20 @@ ${withNotes}` : withNotes;
1105
1176
  this.acp ??= await import("@wrongstack/acp");
1106
1177
  return this.acp;
1107
1178
  }
1179
+ dropFleetGrants(sessionId) {
1180
+ for (const grantKey of this.fleetGrants.keys()) {
1181
+ try {
1182
+ const parsed = JSON.parse(grantKey);
1183
+ if (Array.isArray(parsed) && parsed[0] === sessionId) {
1184
+ this.fleetGrants.delete(grantKey);
1185
+ }
1186
+ } catch {
1187
+ }
1188
+ }
1189
+ }
1108
1190
  drop(key, leader) {
1109
1191
  this.sessions.delete(key);
1192
+ this.dropFleetGrants(key);
1110
1193
  void leader.session.close().catch(() => {
1111
1194
  });
1112
1195
  void leader.fleet?.close().catch(() => {
@@ -1176,7 +1259,8 @@ ${withNotes}` : withNotes;
1176
1259
  toolUseId,
1177
1260
  suggestedPattern,
1178
1261
  signal: request.signal,
1179
- permission: host.permission(sessionId)
1262
+ permission: host.permission(sessionId),
1263
+ context: host.context(sessionId)
1180
1264
  });
1181
1265
  }
1182
1266
  async startSession(key, agentId) {
@@ -1280,6 +1364,7 @@ ${fleetNote(fleet.tools)}` : "")
1280
1364
  async closeAll() {
1281
1365
  const all = [...this.sessions.values()];
1282
1366
  this.sessions.clear();
1367
+ this.fleetGrants.clear();
1283
1368
  await Promise.all(
1284
1369
  all.map(
1285
1370
  (p) => p.then((leader) => {
@@ -1302,6 +1387,24 @@ function createAcpLeaderProviderFactory(opts) {
1302
1387
  };
1303
1388
  }
1304
1389
 
1390
+ // src/fleet/wrongforge-runtime.ts
1391
+ var WRONGFORGE_REASONING = {
1392
+ default: "adaptive",
1393
+ disableSupported: true,
1394
+ effortSupported: true,
1395
+ effortLevels: ["none", "minimal", "low", "medium", "high", "xhigh", "max"],
1396
+ preserveThinking: "unsupported"
1397
+ };
1398
+ function wrongForgeRuntime(reasoning, cache, info) {
1399
+ const effort = reasoning?.effort;
1400
+ return {
1401
+ ...reasoning?.enabled === false || effort === "none" ? { effort: "off" } : effort ? {
1402
+ effort: effort === "minimal" ? "low" : (effort === "xhigh" || effort === "max") && !info?.effortLevels?.includes(effort) ? "high" : effort
1403
+ } : {},
1404
+ ...cache?.ttl ? { cache: cache.ttl } : {}
1405
+ };
1406
+ }
1407
+
1305
1408
  // src/wiring/provider.ts
1306
1409
  import { ProviderAuthRegistry, ProviderRegistry } from "@wrongstack/core/registry";
1307
1410
  import { ConfigError } from "@wrongstack/core/types";
@@ -1317,6 +1420,577 @@ import {
1317
1420
  withCatalogCapabilities
1318
1421
  } from "@wrongstack/providers";
1319
1422
  import { registerBuiltinProviderAuthStrategies } from "@wrongstack/providers/oauth";
1423
+
1424
+ // src/wrongforge-leader/wrongforge-leader-provider.ts
1425
+ import { consumeBtwNotes as consumeBtwNotes3 } from "@wrongstack/core/agent";
1426
+ import { ProviderError as ProviderError3 } from "@wrongstack/core/types";
1427
+ import { toErrorMessage as toErrorMessage5 } from "@wrongstack/core/utils";
1428
+
1429
+ // src/wrongforge-leader/wrongforge-leader-gateway.ts
1430
+ import { randomBytes as randomBytes2 } from "node:crypto";
1431
+ import http from "node:http";
1432
+ import {
1433
+ compactToolDefinitionForWire,
1434
+ subjectForToolInput as subjectForToolInput2,
1435
+ toErrorMessage as toErrorMessage4
1436
+ } from "@wrongstack/core/utils";
1437
+ import { timingSafeTokenEqual } from "@wrongstack/primitives";
1438
+ var NOT_OFFERED = /* @__PURE__ */ new Set([
1439
+ "read",
1440
+ "glob",
1441
+ "grep",
1442
+ "fetch",
1443
+ "read_url_content",
1444
+ "tree",
1445
+ "clarify",
1446
+ "tool_use",
1447
+ "tool_script",
1448
+ "tool_search"
1449
+ ]);
1450
+ var MAX_BODY = 4 * 1024 * 1024;
1451
+ async function askUser(host, sessionId, tool, input) {
1452
+ const suggestedPattern = subjectForToolInput2(tool.name, input, tool.subjectKey, tool.subjectFields) ?? tool.name;
1453
+ const toolUseId = `wrongforge-${randomBytes2(6).toString("hex")}`;
1454
+ if (host.confirmAwaiter) {
1455
+ const answer = await host.confirmAwaiter(tool, input, toolUseId, suggestedPattern);
1456
+ return answer !== "no" && answer !== "deny";
1457
+ }
1458
+ if (!host.confirmThroughEvents) return false;
1459
+ return confirmThroughEvents({
1460
+ events: host.events,
1461
+ sessionId,
1462
+ tool,
1463
+ input,
1464
+ toolUseId,
1465
+ suggestedPattern,
1466
+ signal: new AbortController().signal,
1467
+ permission: host.permission(sessionId),
1468
+ context: host.context(sessionId)
1469
+ });
1470
+ }
1471
+ async function startLeaderGateway(host, sessionId) {
1472
+ const tools = (host.listTools?.() ?? []).filter((t) => !NOT_OFFERED.has(t.name));
1473
+ if (tools.length === 0) return void 0;
1474
+ const byName = new Map(tools.map((t) => [t.name, t]));
1475
+ const wireTools = tools.map(
1476
+ (t) => compactToolDefinitionForWire({
1477
+ name: t.name,
1478
+ description: t.description,
1479
+ inputSchema: t.inputSchema ?? { type: "object" }
1480
+ })
1481
+ );
1482
+ const token = randomBytes2(24).toString("hex");
1483
+ const expected = `Bearer ${token}`;
1484
+ const authorized = (req) => timingSafeTokenEqual(req.headers.authorization, expected);
1485
+ const send = (res, status, body) => {
1486
+ const text = JSON.stringify(body);
1487
+ res.writeHead(status, {
1488
+ "content-type": "application/json; charset=utf-8",
1489
+ "content-length": Buffer.byteLength(text)
1490
+ });
1491
+ res.end(text);
1492
+ };
1493
+ const server = http.createServer((req, res) => {
1494
+ if (!authorized(req)) return send(res, 401, { ok: false, error: "unauthorized" });
1495
+ const url = new URL(req.url ?? "/", "http://localhost");
1496
+ if (req.method === "GET" && url.pathname === "/v1/tools") {
1497
+ return send(res, 200, {
1498
+ tools: wireTools.map(({ name: name2, description, inputSchema }) => ({
1499
+ name: name2,
1500
+ description,
1501
+ input_schema: inputSchema
1502
+ }))
1503
+ });
1504
+ }
1505
+ const m = /^\/v1\/tools\/([^/]+)\/call$/.exec(url.pathname);
1506
+ if (req.method !== "POST" || !m) return send(res, 404, { ok: false, error: "not_found" });
1507
+ const name = decodeURIComponent(m[1] ?? "");
1508
+ const tool = byName.get(name);
1509
+ if (!tool) {
1510
+ return send(res, 404, { ok: false, tool: name, error: "not_offered" });
1511
+ }
1512
+ const chunks = [];
1513
+ let size = 0;
1514
+ req.on("data", (c) => {
1515
+ size += c.length;
1516
+ if (size > MAX_BODY) req.destroy();
1517
+ else chunks.push(c);
1518
+ });
1519
+ req.on("end", () => {
1520
+ let input = {};
1521
+ try {
1522
+ const body = JSON.parse(Buffer.concat(chunks).toString("utf8") || "{}");
1523
+ if (body.input && typeof body.input === "object" && !Array.isArray(body.input)) {
1524
+ input = body.input;
1525
+ }
1526
+ } catch {
1527
+ return send(res, 400, { ok: false, tool: name, error: "invalid_json" });
1528
+ }
1529
+ host.runTool(name, input, {
1530
+ sessionId,
1531
+ approve: (t, i) => askUser(host, sessionId, t, i),
1532
+ // The provider draws no card for a `wstack_*` call (its events are
1533
+ // marked external), so the session's card is settled here.
1534
+ announce: true
1535
+ }).then(
1536
+ (r) => send(res, 200, { ok: !r.isError, tool: name, content: r.content }),
1537
+ (err) => send(res, 200, {
1538
+ ok: false,
1539
+ tool: name,
1540
+ error: "tool_failed",
1541
+ message: toErrorMessage4(err)
1542
+ })
1543
+ );
1544
+ });
1545
+ });
1546
+ await new Promise((resolve, reject) => {
1547
+ server.once("error", reject);
1548
+ server.listen(0, "127.0.0.1", () => {
1549
+ server.removeListener("error", reject);
1550
+ resolve();
1551
+ });
1552
+ });
1553
+ server.unref();
1554
+ const port = server.address().port;
1555
+ return {
1556
+ spec: {
1557
+ url: `http://127.0.0.1:${port}`,
1558
+ token,
1559
+ list_path: "/v1/tools",
1560
+ call_path: "/v1/tools/{name}/call",
1561
+ name_prefix: "wstack_"
1562
+ },
1563
+ tools: [...byName.keys()],
1564
+ close: () => new Promise((resolve) => server.close(() => resolve()))
1565
+ };
1566
+ }
1567
+
1568
+ // src/wrongforge-leader/wrongforge-leader-provider.ts
1569
+ var WRONGFORGE_LEADER_PROVIDER_ID = WRONGFORGE_AGENT_ID;
1570
+ var LEADER_MAX_STEPS = 150;
1571
+ var LEADER_TURN_TIMEOUT_MS = 2 * 60 * 6e4;
1572
+ var CAPABILITIES2 = {
1573
+ tools: true,
1574
+ parallelTools: false,
1575
+ vision: false,
1576
+ streaming: true,
1577
+ promptCache: true,
1578
+ systemPrompt: true,
1579
+ jsonMode: false,
1580
+ reasoning: true,
1581
+ // Learned from WrongForge's first task result (its model's window).
1582
+ maxContext: 0,
1583
+ maxOutput: 32e3,
1584
+ cacheControl: "native",
1585
+ topK: false,
1586
+ frequencyPenalty: false,
1587
+ presencePenalty: false,
1588
+ seed: false,
1589
+ structuredOutput: false,
1590
+ logprobs: false,
1591
+ audio: false,
1592
+ multipleCompletions: false,
1593
+ // WrongForge keeps the conversation (its session) and compacts it itself.
1594
+ keepsOwnContext: true
1595
+ };
1596
+ function leaderAppend(routed, tools) {
1597
+ const has = (n) => tools.includes(n);
1598
+ return [
1599
+ "In this task you LEAD a WrongStack session: a human user talks to you through",
1600
+ "WrongStack, and your reply goes to them, not to an orchestrator. Answer them directly,",
1601
+ "ask when something is truly ambiguous, and end a turn when the work or the answer is done.",
1602
+ "The worker-only rules of the WrongStack guide (no human watching, reply = report to a",
1603
+ "leader) do not apply to you; the rest (stay in the workdir, no git history rewrites, no",
1604
+ "commit or push unless asked) does.",
1605
+ ...routed ? [
1606
+ "Your own write/edit/shell tools are off: change files with WrongStack's `wstack_edit` /",
1607
+ "`wstack_write` / `wstack_patch` and run commands with `wstack_bash` (or `wstack_test`,",
1608
+ "`wstack_lint`, `wstack_typecheck`). They run in the user's session, under their rules."
1609
+ ] : [],
1610
+ ...has("delegate") ? [
1611
+ "`wstack_delegate` hands work to WrongStack workers (scope and outOfScope required); the",
1612
+ "result arrives later as a [DELEGATION RESULT] message, so end your turn or keep working."
1613
+ ] : [],
1614
+ ...has("remember") || has("memory_search") ? ["`wstack_memory_search` / `wstack_remember` are the project memory: check it, add to it."] : []
1615
+ ].join(" ");
1616
+ }
1617
+ function flatten(req) {
1618
+ const text = (m) => typeof m.content === "string" ? m.content : m.content.map((b) => "text" in b && typeof b.text === "string" ? b.text : "").filter(Boolean).join("\n");
1619
+ const system = (req.system ?? []).map((b) => b.text).join("\n\n");
1620
+ const turns = req.messages.map((m) => `[${m.role}]
1621
+ ${text(m)}`).join("\n\n");
1622
+ return [
1623
+ system ? `<instructions>
1624
+ ${system}
1625
+ </instructions>` : "",
1626
+ turns,
1627
+ "Reply to the last message, following the instructions above. Use no tools."
1628
+ ].filter(Boolean).join("\n\n");
1629
+ }
1630
+ function providerError(err, id) {
1631
+ if (err instanceof ProviderError3) return err;
1632
+ const make = (message, status, retryable, kind) => new ProviderError3(`WrongForge: ${message}`, status, retryable, id, { kind });
1633
+ if (err instanceof WfAborted) return make("the turn was cancelled", 499, false, "unknown");
1634
+ if (err instanceof WfHttpError) {
1635
+ if (err.status === 401 || err.status === 403 || err.code === "not_signed_in")
1636
+ return make(err.message, 401, false, "auth");
1637
+ if (err.status === 0) return make(err.message, 0, true, "network");
1638
+ if (err.status >= 500) return make(err.message, err.status, true, "server");
1639
+ return make(`${err.code}: ${err.message}`, err.status, false, "invalid_request");
1640
+ }
1641
+ return make(toErrorMessage5(err), 0, false, "unknown");
1642
+ }
1643
+ function taskError(record, id) {
1644
+ const make = (message, status, retryable, kind) => new ProviderError3(`WrongForge: ${message}`, status, retryable, id, { kind });
1645
+ switch (record.status) {
1646
+ case "completed":
1647
+ return void 0;
1648
+ case "cancelled":
1649
+ return make(
1650
+ `the turn was cancelled${record.cancel_reason ? ` (${record.cancel_reason})` : ""}`,
1651
+ 499,
1652
+ false,
1653
+ "unknown"
1654
+ );
1655
+ case "timed_out":
1656
+ return make("the turn hit its timeout", 408, false, "timeout");
1657
+ default: {
1658
+ const code = record.error?.code ?? "internal_error";
1659
+ const message = `${code}: ${record.error?.message ?? "no detail"}`;
1660
+ if (code === "context_overflow") return make(message, 413, false, "context_overflow");
1661
+ if (/rate.?limit|429/i.test(message)) return make(message, 429, true, "rate_limit");
1662
+ if (/quota|usage limit|extra usage/i.test(message))
1663
+ return make(message, 402, false, "quota_exhausted");
1664
+ return make(message, 500, code === "server_restarted", "server");
1665
+ }
1666
+ }
1667
+ }
1668
+ var WrongForgeLeaderProvider = class {
1669
+ constructor(opts) {
1670
+ this.opts = opts;
1671
+ this.id = opts.id ?? WRONGFORGE_LEADER_PROVIDER_ID;
1672
+ trackAcpLeader(this);
1673
+ }
1674
+ opts;
1675
+ id;
1676
+ capabilities = { ...CAPABILITIES2 };
1677
+ sessions = /* @__PURE__ */ new Map();
1678
+ sideProviders = /* @__PURE__ */ new Map();
1679
+ config() {
1680
+ return acpLeaderHost()?.getConfig() ?? this.opts.bootConfig;
1681
+ }
1682
+ client() {
1683
+ const ep = resolveWrongForgeEndpoint();
1684
+ if (!ep) {
1685
+ throw new ProviderError3(
1686
+ "WrongForge: no API key found. Start it once with `npm run serve` (it saves ~/.wrongforge/api-key) or set WRONGFORGE_API_KEY.",
1687
+ 401,
1688
+ false,
1689
+ this.id,
1690
+ { kind: "auth" }
1691
+ );
1692
+ }
1693
+ void reportWrongForgeQuota({
1694
+ endpoint: ep,
1695
+ providerId: this.id,
1696
+ fetchImpl: this.opts.fetchImpl
1697
+ });
1698
+ return wrongForgeCall(ep, this.opts.fetchImpl);
1699
+ }
1700
+ async info(call, signal) {
1701
+ try {
1702
+ const info = parseWrongForgeInfo(await call("GET", "/v1/info", void 0, signal));
1703
+ writeWrongForgeInfoCache(info);
1704
+ return info;
1705
+ } catch {
1706
+ return void 0;
1707
+ }
1708
+ }
1709
+ model(requested, info) {
1710
+ const choice = chooseModel(requested, void 0, info);
1711
+ if (choice.error) {
1712
+ throw new ProviderError3(choice.error, 400, false, this.id, { kind: "invalid_request" });
1713
+ }
1714
+ return choice.id;
1715
+ }
1716
+ /**
1717
+ * A side model for a turn WrongForge does not lead. `explicitOnly` (a side
1718
+ * request through `complete()`) takes only the model the user named in
1719
+ * `acp.leader.sideModel`: WrongForge answers those itself (`oneShot`), and
1720
+ * handing them to `fallbackModels[0]` let that model take over the session.
1721
+ * A worker's turn may still fall back to the fallback chain, since `oneShot`
1722
+ * would leave it without tools.
1723
+ */
1724
+ sideProvider(explicitOnly = false) {
1725
+ const config = this.config();
1726
+ const ref = explicitOnly ? explicitLeaderSideModel(config) : leaderSideModel(config);
1727
+ if (!ref || ref.provider === this.id) return void 0;
1728
+ let provider = this.sideProviders.get(ref.provider);
1729
+ if (!provider) {
1730
+ provider = this.opts.buildProvider(ref.provider, config);
1731
+ if (provider) this.sideProviders.set(ref.provider, provider);
1732
+ }
1733
+ return provider ? { provider, model: ref.model } : void 0;
1734
+ }
1735
+ async complete(req, opts) {
1736
+ const side = this.sideProvider(true);
1737
+ if (side) return side.provider.complete({ ...req, model: side.model }, opts);
1738
+ return this.oneShot(req, opts.signal);
1739
+ }
1740
+ /** WrongForge as a plain model: one step, no tools, its own throwaway session. */
1741
+ async oneShot(req, signal) {
1742
+ const call = this.client();
1743
+ try {
1744
+ const info = await this.info(call, signal);
1745
+ const model = this.model(req.model, info);
1746
+ const host = acpLeaderHost();
1747
+ const { task } = await call(
1748
+ "POST",
1749
+ "/v1/tasks",
1750
+ {
1751
+ prompt: flatten(req),
1752
+ workdir: host?.projectRoot ?? process.cwd(),
1753
+ ...model ? { model } : {},
1754
+ max_steps: 1,
1755
+ builtin_tools: [],
1756
+ ...wrongForgeRuntime(req.reasoning, req.cache, info),
1757
+ wait: true,
1758
+ cancel_on_disconnect: true
1759
+ },
1760
+ signal
1761
+ );
1762
+ const failure = taskError(task, this.id);
1763
+ if (failure) throw failure;
1764
+ const usage = wfTokens(task.result?.usage);
1765
+ return {
1766
+ model: model ?? req.model,
1767
+ content: [{ type: "text", text: task.result?.text ?? "" }],
1768
+ stopReason: "end_turn",
1769
+ usage
1770
+ };
1771
+ } catch (err) {
1772
+ throw providerError(err, this.id);
1773
+ } finally {
1774
+ void reportWrongForgeQuota({ providerId: this.id, fetchImpl: this.opts.fetchImpl });
1775
+ }
1776
+ }
1777
+ async *stream(req, opts) {
1778
+ if (!isLeaderTurn(req)) {
1779
+ const side = this.sideProvider();
1780
+ if (side) {
1781
+ yield* side.provider.stream({ ...req, model: side.model }, opts);
1782
+ return;
1783
+ }
1784
+ const res = await this.complete(req, opts);
1785
+ yield { type: "message_start", model: res.model };
1786
+ const text = res.content.map((b) => "text" in b ? b.text : "").join("");
1787
+ if (text) {
1788
+ yield { type: "content_block_start", kind: "text" };
1789
+ yield { type: "text_delta", text };
1790
+ yield { type: "content_block_stop", index: 0 };
1791
+ }
1792
+ yield { type: "message_stop", stopReason: "end_turn", usage: res.usage };
1793
+ return;
1794
+ }
1795
+ const call = this.client();
1796
+ const host = acpLeaderHost();
1797
+ const key = req.cache?.sessionId ?? "default";
1798
+ const leader = this.sessionFor(key);
1799
+ let info;
1800
+ let model;
1801
+ let gateway;
1802
+ let joinedBefore;
1803
+ try {
1804
+ info = await this.info(call, opts.signal);
1805
+ model = this.model(req.model, info);
1806
+ if (host && !leader.gateway) {
1807
+ leader.gateway = startLeaderGateway(host, key).catch(() => {
1808
+ leader.gateway = void 0;
1809
+ return void 0;
1810
+ });
1811
+ }
1812
+ gateway = await leader.gateway;
1813
+ if (!gateway) {
1814
+ leader.gateway = void 0;
1815
+ }
1816
+ joinedBefore = leader.joined ?? await this.wfSessionExists(call, leader, opts.signal);
1817
+ } catch (err) {
1818
+ throw providerError(err, this.id);
1819
+ }
1820
+ const routed = gateway !== void 0 && (info?.features.includes("builtin_tools") ?? false);
1821
+ const queue = new StreamQueue();
1822
+ const blocks = new TextBlocks(queue);
1823
+ const cards = new ToolCardRelay(host?.events, {
1824
+ sessionId: req.cache?.sessionId,
1825
+ model: model ?? req.model,
1826
+ provider: this.id
1827
+ });
1828
+ yield { type: "message_start", model: model ?? req.model };
1829
+ let taskId;
1830
+ const onAbort = () => {
1831
+ if (taskId) cancelTask(call, taskId, "interrupted in WrongStack");
1832
+ };
1833
+ opts.signal.addEventListener("abort", onAbort, { once: true });
1834
+ const run = (async () => {
1835
+ const { task } = await call(
1836
+ "POST",
1837
+ "/v1/tasks",
1838
+ {
1839
+ prompt: this.promptText(req, joinedBefore, gateway),
1840
+ session_id: leader.wfSessionId,
1841
+ workdir: host?.projectRoot ?? process.cwd(),
1842
+ ...model ? { model } : {},
1843
+ max_steps: LEADER_MAX_STEPS,
1844
+ timeout_ms: LEADER_TURN_TIMEOUT_MS,
1845
+ ...wrongForgeRuntime(req.reasoning, req.cache, info),
1846
+ system_append: leaderAppend(routed, gateway?.tools ?? []),
1847
+ context: { wrongstack: { sessionId: key, role: "leader" } },
1848
+ ...gateway ? { gateway: { ...gateway.spec, optional: !routed } } : {},
1849
+ ...routed ? { builtin_tools: WRONGFORGE_READ_SIDE_TOOLS } : {}
1850
+ },
1851
+ opts.signal
1852
+ );
1853
+ taskId = task.id;
1854
+ leader.joined = true;
1855
+ if (opts.signal.aborted) {
1856
+ cancelTask(call, taskId, "interrupted in WrongStack");
1857
+ throw new WfAborted();
1858
+ }
1859
+ for await (const ev of followTask(call, task.id, opts.signal)) {
1860
+ if (ev.type === "task.heartbeat" || ev.type === "step.finished") {
1861
+ void reportWrongForgeQuota({ providerId: this.id, fetchImpl: this.opts.fetchImpl });
1862
+ }
1863
+ const external = ev.data["external"] === true;
1864
+ for (const p of toProgress(ev)) {
1865
+ if (p.type === "message") blocks.text(p.text);
1866
+ else if (p.type === "tool_call") {
1867
+ blocks.close();
1868
+ if (!external) cards.update(p.toolCall);
1869
+ } else if (p.type === "tool_call_update" && !external) cards.update(p.toolCall);
1870
+ }
1871
+ if (ev.type === "step.finished" && typeof ev.data["context_tokens"] === "number") {
1872
+ this.observeContext(leader, req.cache?.sessionId, {
1873
+ used: ev.data["context_tokens"],
1874
+ size: this.capabilities.maxContext
1875
+ });
1876
+ }
1877
+ }
1878
+ const done = await terminalTaskRecord(call, task.id, opts.signal);
1879
+ blocks.close();
1880
+ const failure = taskError(done, this.id);
1881
+ if (failure) throw failure;
1882
+ const window = done.result?.context_window ?? 0;
1883
+ if (window > 0) this.capabilities.maxContext = window;
1884
+ if (typeof done.result?.context_tokens === "number") {
1885
+ this.observeContext(leader, req.cache?.sessionId, {
1886
+ used: done.result.context_tokens,
1887
+ size: window
1888
+ });
1889
+ }
1890
+ queue.push({
1891
+ type: "message_stop",
1892
+ stopReason: done.result?.finish_reason === "length" ? "max_tokens" : "end_turn",
1893
+ usage: wfTokens(done.result?.usage),
1894
+ ...leader.context ? { agentContext: leader.context } : {}
1895
+ });
1896
+ queue.end();
1897
+ })().catch((err) => {
1898
+ blocks.close();
1899
+ queue.fail(providerError(err, this.id));
1900
+ });
1901
+ try {
1902
+ yield* queue.drain();
1903
+ } finally {
1904
+ opts.signal.removeEventListener("abort", onAbort);
1905
+ await run;
1906
+ void reportWrongForgeQuota({ providerId: this.id, fetchImpl: this.opts.fetchImpl });
1907
+ }
1908
+ }
1909
+ /** The turn's prompt; WrongForge joining a conversation under way gets the turns before it. */
1910
+ promptText(req, joined, gateway) {
1911
+ const latest = externalSkillDirective(
1912
+ latestUserText(req.messages),
1913
+ gateway ? externalSkillLoader(gateway.tools, gateway.spec.name_prefix ?? "") : void 0
1914
+ );
1915
+ const earlier = joined ? void 0 : earlierConversation(req.messages);
1916
+ const prompt = earlier ? `${earlier}
1917
+
1918
+ ${latest}` : latest;
1919
+ const context = acpLeaderHost()?.context(req.cache?.sessionId);
1920
+ const notes = context?.meta ? consumeBtwNotes3(context) : [];
1921
+ return notes.length > 0 ? `${prompt}
1922
+
1923
+ ${acpBtwBlock(notes)}` : prompt;
1924
+ }
1925
+ async wfSessionExists(call, leader, signal) {
1926
+ try {
1927
+ await call(
1928
+ "GET",
1929
+ `/v1/sessions/${encodeURIComponent(leader.wfSessionId)}`,
1930
+ void 0,
1931
+ signal
1932
+ );
1933
+ return true;
1934
+ } catch (err) {
1935
+ if (err instanceof WfHttpError && err.status === 404) return false;
1936
+ throw err;
1937
+ }
1938
+ }
1939
+ sessionFor(key) {
1940
+ let leader = this.sessions.get(key);
1941
+ if (!leader) {
1942
+ leader = { wfSessionId: `wsl-${safeWfId(key)}` };
1943
+ this.sessions.set(key, leader);
1944
+ }
1945
+ return leader;
1946
+ }
1947
+ observeContext(leader, sessionId, reading) {
1948
+ leader.context = { used: reading.used, size: reading.size || this.capabilities.maxContext };
1949
+ publishLeaderContext(
1950
+ acpLeaderHost()?.events,
1951
+ sessionId,
1952
+ leader.context,
1953
+ this.capabilities.maxContext
1954
+ );
1955
+ }
1956
+ /** `/compact` on this route: WrongForge compacts its own session. */
1957
+ async compactOwnContext(opts) {
1958
+ const leader = this.sessions.get(opts.sessionId);
1959
+ if (!leader) return void 0;
1960
+ const call = this.client();
1961
+ try {
1962
+ await call(
1963
+ "POST",
1964
+ `/v1/sessions/${encodeURIComponent(leader.wfSessionId)}/compact`,
1965
+ {},
1966
+ opts.signal
1967
+ );
1968
+ } catch (err) {
1969
+ throw providerError(err, this.id);
1970
+ }
1971
+ leader.context = void 0;
1972
+ return void 0;
1973
+ }
1974
+ /** Close every session gateway (process shutdown). */
1975
+ async closeAll() {
1976
+ const all = [...this.sessions.values()];
1977
+ this.sessions.clear();
1978
+ await Promise.all(all.map((s) => s.gateway?.then((g) => g?.close()).catch(() => void 0)));
1979
+ }
1980
+ };
1981
+ function createWrongForgeLeaderProviderFactory(opts) {
1982
+ return {
1983
+ type: WRONGFORGE_LEADER_PROVIDER_ID,
1984
+ // Routing metadata only: the provider does no wire conversion.
1985
+ family: "openai-compatible",
1986
+ create: (cfg) => new WrongForgeLeaderProvider({
1987
+ ...opts,
1988
+ id: cfg.type || WRONGFORGE_LEADER_PROVIDER_ID
1989
+ })
1990
+ };
1991
+ }
1992
+
1993
+ // src/wiring/provider.ts
1320
1994
  async function setupProvider(params) {
1321
1995
  const { config, modelsRegistry, logger } = params;
1322
1996
  const providerAuthRegistry = new ProviderAuthRegistry();
@@ -1333,7 +2007,16 @@ async function setupProvider(params) {
1333
2007
  }
1334
2008
  const savedProviderCfg = config.providers?.[config.provider];
1335
2009
  const acpLeader = config.provider === ACP_LEADER_PROVIDER_ID;
1336
- let resolvedProvider = acpLeader ? {
2010
+ const wrongForgeLeader = config.provider === WRONGFORGE_LEADER_PROVIDER_ID;
2011
+ let resolvedProvider = wrongForgeLeader ? {
2012
+ id: WRONGFORGE_LEADER_PROVIDER_ID,
2013
+ name: "WrongForge",
2014
+ family: "openai-compatible",
2015
+ apiBase: void 0,
2016
+ envVars: [],
2017
+ models: [{ id: config.model, name: config.model }],
2018
+ npm: void 0
2019
+ } : acpLeader ? {
1337
2020
  id: ACP_LEADER_PROVIDER_ID,
1338
2021
  name: "ACP agent",
1339
2022
  family: "openai-compatible",
@@ -1393,6 +2076,12 @@ async function setupProvider(params) {
1393
2076
  buildProvider: (providerId, live) => buildProviderForId({ config: live, providerRegistry, logger }, providerId)
1394
2077
  })
1395
2078
  );
2079
+ providerRegistry.register(
2080
+ createWrongForgeLeaderProviderFactory({
2081
+ bootConfig: config,
2082
+ buildProvider: (providerId, live) => buildProviderForId({ config: live, providerRegistry, logger }, providerId)
2083
+ })
2084
+ );
1396
2085
  if (config.features.modelsRegistry) {
1397
2086
  try {
1398
2087
  const factories = await buildProviderFactoriesFromRegistry({
@@ -1433,7 +2122,7 @@ Try \`wstack models refresh\` once you have network access.`,
1433
2122
  cause: err
1434
2123
  });
1435
2124
  }
1436
- if (config.features.modelsRegistry && !acpLeader) {
2125
+ if (config.features.modelsRegistry && !acpLeader && !wrongForgeLeader) {
1437
2126
  provider = await withCatalogCapabilities(
1438
2127
  modelsRegistry,
1439
2128
  config.provider,
@@ -1452,7 +2141,10 @@ export {
1452
2141
  wrongstackAcpPermissionPolicy,
1453
2142
  recordAcpRateLimit,
1454
2143
  startAcpTurnReminders,
2144
+ cardOutputForText,
2145
+ WRONGFORGE_REASONING,
2146
+ wrongForgeRuntime,
1455
2147
  setupProvider,
1456
2148
  createGracefulShutdown
1457
2149
  };
1458
- //# sourceMappingURL=chunk-COGI7EQU.js.map
2150
+ //# sourceMappingURL=chunk-EAATL6FL.js.map