@kernlang/agon 0.1.5 → 0.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 (32) hide show
  1. package/dist/{chunk-4NTH3EAR.js → chunk-3PDYVGRS.js} +77 -22
  2. package/dist/chunk-3PDYVGRS.js.map +1 -0
  3. package/dist/{chunk-GPYWJO2Q.js → chunk-6IF2AV4Y.js} +8 -7
  4. package/dist/{chunk-GPYWJO2Q.js.map → chunk-6IF2AV4Y.js.map} +1 -1
  5. package/dist/{chunk-73ETZFDH.js → chunk-7WZ2O5WZ.js} +4 -4
  6. package/dist/{chunk-DGTU4UWQ.js → chunk-NBV37VMW.js} +2 -2
  7. package/dist/{chunk-46WNYE4R.js → chunk-PUNBDLQO.js} +31 -31
  8. package/dist/chunk-PUNBDLQO.js.map +1 -0
  9. package/dist/{chunk-HAJIKZGU.js → chunk-TMNHJOKU.js} +408 -68
  10. package/dist/chunk-TMNHJOKU.js.map +1 -0
  11. package/dist/{chunk-SOUF7XTW.js → chunk-XWHC6VAH.js} +3 -2
  12. package/dist/chunk-XWHC6VAH.js.map +1 -0
  13. package/dist/{dispatch-XHLJ44TF.js → dispatch-S3CR5HKX.js} +2 -2
  14. package/dist/engines/codex.json +3 -0
  15. package/dist/{forge-ZI7NE73F.js → forge-GUOEJ5DJ.js} +6 -6
  16. package/dist/index.js +28 -24
  17. package/dist/index.js.map +1 -1
  18. package/dist/{plan-mode-KIXDKD63.js → plan-mode-35BONR7S.js} +6 -6
  19. package/dist/{src-4A5FVACG.js → src-3NWTITZM.js} +9 -3
  20. package/dist/{update-DLPMYTF3.js → update-H3LE4ZSI.js} +5 -5
  21. package/package.json +3 -2
  22. package/dist/chunk-46WNYE4R.js.map +0 -1
  23. package/dist/chunk-4NTH3EAR.js.map +0 -1
  24. package/dist/chunk-HAJIKZGU.js.map +0 -1
  25. package/dist/chunk-SOUF7XTW.js.map +0 -1
  26. /package/dist/{chunk-73ETZFDH.js.map → chunk-7WZ2O5WZ.js.map} +0 -0
  27. /package/dist/{chunk-DGTU4UWQ.js.map → chunk-NBV37VMW.js.map} +0 -0
  28. /package/dist/{dispatch-XHLJ44TF.js.map → dispatch-S3CR5HKX.js.map} +0 -0
  29. /package/dist/{forge-ZI7NE73F.js.map → forge-GUOEJ5DJ.js.map} +0 -0
  30. /package/dist/{plan-mode-KIXDKD63.js.map → plan-mode-35BONR7S.js.map} +0 -0
  31. /package/dist/{src-4A5FVACG.js.map → src-3NWTITZM.js.map} +0 -0
  32. /package/dist/{update-DLPMYTF3.js.map → update-H3LE4ZSI.js.map} +0 -0
@@ -4,7 +4,7 @@ import {
4
4
  cleanEngineOutput,
5
5
  icons,
6
6
  parseMarkdownBlocks
7
- } from "./chunk-DGTU4UWQ.js";
7
+ } from "./chunk-NBV37VMW.js";
8
8
  import {
9
9
  AGON_MODE_NAMES,
10
10
  CORPUS_PATH,
@@ -109,7 +109,7 @@ import {
109
109
  worktreeCreate,
110
110
  worktreeDiff,
111
111
  worktreeRemoveBestEffort
112
- } from "./chunk-HAJIKZGU.js";
112
+ } from "./chunk-TMNHJOKU.js";
113
113
 
114
114
  // ../forge/src/generated/forge.ts
115
115
  import { randomUUID as randomUUID2 } from "crypto";
@@ -6690,7 +6690,7 @@ function filterDefaultOrchestrationEngines(engineIds) {
6690
6690
 
6691
6691
  // src/generated/cesar/brain.ts
6692
6692
  import { join as join14 } from "path";
6693
- import { mkdirSync as mkdirSync13, appendFileSync as appendFileSync2, existsSync as existsSync12, readFileSync as readFileSync13, unlinkSync, readdirSync, writeFileSync as writeFileSync11 } from "fs";
6693
+ import { mkdirSync as mkdirSync13, appendFileSync as appendFileSync2, existsSync as existsSync13, readFileSync as readFileSync13, unlinkSync, readdirSync, writeFileSync as writeFileSync11 } from "fs";
6694
6694
 
6695
6695
  // src/generated/cesar/confidence.ts
6696
6696
  var CONFIDENCE_TIERS = { direct: 96, quickNero: 93, nero: 88, brainstorm: 72, advisor: 72 };
@@ -6758,11 +6758,12 @@ function parseSuggestion(response) {
6758
6758
  }
6759
6759
 
6760
6760
  // src/generated/cesar/session.ts
6761
- import { readFileSync as readFileSync12, statSync as statSync4 } from "fs";
6761
+ import { readFileSync as readFileSync12, statSync as statSync4, existsSync as existsSync12 } from "fs";
6762
6762
  import { isAbsolute as isAbsolute2, resolve as resolve3, dirname as dirname5 } from "path";
6763
6763
  import { join as join12 } from "path";
6764
6764
  import { mkdirSync as mkdirSync11 } from "fs";
6765
- import { fileURLToPath } from "url";
6765
+ import { fileURLToPath, pathToFileURL } from "url";
6766
+ import { createRequire } from "module";
6766
6767
 
6767
6768
  // src/generated/cesar/tools.ts
6768
6769
  function createCesarToolRegistry(engineId) {
@@ -8122,6 +8123,29 @@ function isUserDirectedQuestion(lastLine) {
8122
8123
  const isForkChoice = /\bor\b[^?]{0,160}\?\s*$/i.test(last);
8123
8124
  return userAddressed || isForkChoice;
8124
8125
  }
8126
+ function findTrailingUserQuestion(text) {
8127
+ const lines = String(text ?? "").split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
8128
+ const TAIL = 6;
8129
+ const start = Math.max(0, lines.length - TAIL);
8130
+ for (let i = lines.length - 1; i >= start; i--) {
8131
+ if (isUserDirectedQuestion(lines[i])) return lines[i];
8132
+ }
8133
+ return null;
8134
+ }
8135
+ function detectAwaitingUserInput(text) {
8136
+ const body = String(text ?? "");
8137
+ if (findTrailingUserQuestion(body)) return true;
8138
+ const tail = body.split(/\r?\n/).map((l) => l.trim().replace(/^(?:[-*>•]\s+|\d+[.)]\s+)/, "")).filter(Boolean).slice(-3);
8139
+ if (tail.length === 0) return false;
8140
+ const HOLDING_RE = /^holding\b(?:\s*$|\s*[.,;:!?…—–-]|\s+for\b|\s+until\b|\s+off\b)/i;
8141
+ const AWAITING_RE = /\b(?:awaiting\s+(?:(?:your|user|the\s+user'?s?|explicit\s+user|my)\s+(?:approval|greenlight|sign[-\s]?off|go[-\s]?ahead|confirmation|input|decision|response|reply|call|word|ok)|(?:approval|greenlight|sign[-\s]?off|go[-\s]?ahead|a\s+decision))|waiting\s+(?:on|for)\s+(?:you\s+to\s+(?:approve|confirm|decide|respond|reply)|your\s+(?:approval|greenlight|sign[-\s]?off|go[-\s]?ahead|input|confirmation|decision|response|reply|ok)|approval|greenlight|sign[-\s]?off|confirmation)|hold(?:ing)?\s+(?:for|until|off)|need(?:s|ing)?\s+(?:your|explicit\s+user|user)\s+(?:approval|greenlight|go[-\s]?ahead|sign[-\s]?off|input|confirmation|ok|decision)|your\s+(?:greenlight|go[-\s]?ahead|sign[-\s]?off)\s+(?:to|before)|need\s+(?:a\s+|the\s+)?greenlight|explicit\s+(?:user\s+)?approval|stand(?:ing)?\s+by\s+(?:for|until))\b/i;
8142
+ for (const line of tail) {
8143
+ const head = line.slice(0, 300);
8144
+ if (HOLDING_RE.test(head)) return true;
8145
+ if (AWAITING_RE.test(head)) return true;
8146
+ }
8147
+ return false;
8148
+ }
8125
8149
  function detectNarratedToolStall(text) {
8126
8150
  const body = String(text ?? "").trim();
8127
8151
  if (!body) {
@@ -9114,7 +9138,7 @@ ${cleaned}`;
9114
9138
  }
9115
9139
  }
9116
9140
  if (name === "ExitPlanMode") {
9117
- const { handleExitPlanMode } = await import("./plan-mode-KIXDKD63.js");
9141
+ const { handleExitPlanMode } = await import("./plan-mode-35BONR7S.js");
9118
9142
  return "[DELEGATION_BREAK] " + handleExitPlanMode(String(args.reason ?? ""), ctx.cesar?.planDispatch ?? null, ctx);
9119
9143
  }
9120
9144
  if (name === "ProposePlan") {
@@ -9137,7 +9161,7 @@ ${cleaned}`;
9137
9161
  }
9138
9162
  }
9139
9163
  }
9140
- const { handleProposePlan } = await import("./plan-mode-KIXDKD63.js");
9164
+ const { handleProposePlan } = await import("./plan-mode-35BONR7S.js");
9141
9165
  const dispatch = ctx.cesar.planDispatch;
9142
9166
  if (!dispatch) {
9143
9167
  return "[PLAN_ERROR] Internal plan display dispatch unavailable. Retry the plan request so Agon can render the approval panel.";
@@ -9472,6 +9496,25 @@ function mcpConfigFingerprint(config) {
9472
9496
  const discoveryFp = mcpDiscoveryFingerprint(resolveWorkingDir());
9473
9497
  return `${enabled}:${configPath}:${mtime}:${discoveryFp}`;
9474
9498
  }
9499
+ function resolveAgonMcpServerPath(fromUrl) {
9500
+ const raw = fromUrl ?? import.meta.url;
9501
+ const url = raw.startsWith("file:") ? raw : pathToFileURL(raw).href;
9502
+ try {
9503
+ const req = createRequire(url);
9504
+ const resolved = req.resolve("@kernlang/agon-mcp");
9505
+ if (existsSync12(resolved)) return resolved;
9506
+ } catch {
9507
+ }
9508
+ let dir = dirname5(fileURLToPath(url));
9509
+ for (let i = 0; i < 12; i++) {
9510
+ const cand = join12(dir, "packages", "mcp", "dist", "index.js");
9511
+ if (existsSync12(cand)) return cand;
9512
+ const parent = dirname5(dir);
9513
+ if (parent === dir) break;
9514
+ dir = parent;
9515
+ }
9516
+ return join12(dirname5(fileURLToPath(url)), "../../../../mcp/dist/index.js");
9517
+ }
9475
9518
  function resolveCesarBackend(ctx, engineId) {
9476
9519
  const config = ctx.config;
9477
9520
  const cesarEngineId = engineId ?? config.cesarEngine ?? config.forgeFixedStarter ?? "claude";
@@ -9574,20 +9617,30 @@ async function ensureCesarSession(ctx) {
9574
9617
  mcpServers = mcpServers ? [...mcpServers, ...sessionMcpWired] : sessionMcpWired;
9575
9618
  }
9576
9619
  const isCompanion = !!binaryPath && (engine.companion?.protocol === "jsonrpc" || engine.companion?.protocol === "acp" || engine.companion?.protocol === "stream-json" || engine.id === "claude" || engine.binary === "claude");
9620
+ const printOptOut = process.env.AGON_CLAUDE_PRINT;
9621
+ const usingPrint = printOptOut === "1" || printOptOut === "true";
9622
+ const isClaudePtyBrain = !!binaryPath && (engine.id === "claude" || engine.binary === "claude") && !usingPrint;
9623
+ let answerChannelPath;
9577
9624
  if (isCompanion) {
9578
9625
  ensureAgonHome();
9579
9626
  const signalDir = join12(getAgonHome(), "signals");
9580
9627
  mkdirSync11(signalDir, { recursive: true });
9581
9628
  const sessionSignalId = `cesar-${Date.now()}`;
9582
- const mcpServerPath = join12(dirname5(fileURLToPath(import.meta.url)), "../../../../mcp/dist/index.js");
9629
+ const mcpServerPath = resolveAgonMcpServerPath();
9630
+ if (!existsSync12(mcpServerPath)) {
9631
+ console.error(`[agon] cesar: agon-orchestration MCP server not found at ${mcpServerPath} \u2014 orchestration tools (Forge/Tribunal/AgonBash/DeliverAnswer) will be UNAVAILABLE and Cesar will fall back to slow scraping.`);
9632
+ }
9633
+ const mcpEnv = { AGON_SIGNAL_DIR: signalDir, AGON_SESSION_ID: sessionSignalId };
9634
+ if (isClaudePtyBrain) mcpEnv.AGON_ANSWER_CHANNEL = "1";
9583
9635
  const agonMcpServer = {
9584
9636
  name: "agon-orchestration",
9585
9637
  command: "node",
9586
9638
  args: [mcpServerPath],
9587
- env: { AGON_SIGNAL_DIR: signalDir, AGON_SESSION_ID: sessionSignalId }
9639
+ env: mcpEnv
9588
9640
  };
9589
9641
  mcpServers = mcpServers ? [...mcpServers, agonMcpServer] : [agonMcpServer];
9590
9642
  ctx.cesar.mcpSignalPath = join12(signalDir, `${sessionSignalId}.json`);
9643
+ if (isClaudePtyBrain) answerChannelPath = join12(signalDir, `${sessionSignalId}-answer.json`);
9591
9644
  }
9592
9645
  const systemPrompt = buildCesarSystemPrompt(ctx);
9593
9646
  const toolRegistry = createCesarToolRegistry(cesarEngineId);
@@ -9599,6 +9652,9 @@ async function ensureCesarSession(ctx) {
9599
9652
  fullPrompt += "\n\nYou have tools available via function calling. Call them directly \u2014 do NOT describe them in XML or narrate what you would call. Just call the function.";
9600
9653
  } else if (isCompanion) {
9601
9654
  fullPrompt += "\n\nYou have tools available via the agon-orchestration MCP server:\n- Orchestration: Tribunal, Brainstorm, Campfire, Forge, Pipeline, Review, Agent, Delegate, QuickNero, ReportConfidence, ProposePlan, ExitPlanMode\n- Write operations: AgonBash (shell commands), AgonEdit (file edits), AgonWrite (file creation)\n\nCall them as MCP tools \u2014 NEVER via your native Bash/Edit/Write. Your native write tools are disabled. Use AgonBash for ALL shell commands (git, npm, etc.), AgonEdit for file edits, AgonWrite for new files. The user will be asked to approve write operations. After calling any orchestration tool except Delegate, QuickNero, and ReportConfidence: STOP and wait.";
9655
+ if (isClaudePtyBrain) {
9656
+ fullPrompt += '\n\nIMPORTANT \u2014 DELIVERING YOUR REPLY: You are running under a PTY answer-channel. DeliverAnswer is REQUIRED and is the FASTEST way to reply \u2014 calling it returns your answer to the user INSTANTLY. To show the user your response you MUST call the DeliverAnswer tool with your complete reply (markdown) in the `text` argument, then STOP. Plain printed/streamed text is only a draft preview, may not reach the user, AND is SLOWER (Agon then has to wait for the terminal to go idle before it can read anything). NEVER "respond directly", skip the tool, or avoid "tool round-trips" to save time \u2014 skipping DeliverAnswer makes the turn SLOWER and risks losing your reply entirely. Even a one-word answer goes through DeliverAnswer. Call it exactly once at the end of every turn \u2014 EXCEPT on turns where you STOP for an orchestration tool (Forge/Tribunal/Brainstorm/Campfire/Pipeline/Review/Agent/Delegate), ProposePlan, or ExitPlanMode (those already end your turn and Agon handles the rest). Always call ReportConfidence first as usual.';
9657
+ }
9602
9658
  } else {
9603
9659
  const toolPrompt = buildToolSystemPrompt(toolRegistry);
9604
9660
  fullPrompt += "\n\nTOOLS: XML format below. Never ask permission \u2014 just call. Never describe changes when you can execute.\n\n" + toolPrompt;
@@ -9615,7 +9671,8 @@ async function ensureCesarSession(ctx) {
9615
9671
  mcpServers,
9616
9672
  sessionContinuity: config.sessionContinuity === true,
9617
9673
  onToolCall: buildOnToolCall(ctx, toolRegistry, config),
9618
- onApproval: buildOnApproval(ctx, cesarEngineId)
9674
+ onApproval: buildOnApproval(ctx, cesarEngineId),
9675
+ answerChannelPath
9619
9676
  };
9620
9677
  const session = createPersistentSession(sessionConfig);
9621
9678
  await session.start();
@@ -10151,7 +10208,7 @@ ${enrichedInput}`;
10151
10208
  const signalDir = ctx.cesar.mcpSignalPath ? join14(ctx.cesar.mcpSignalPath, "..") : null;
10152
10209
  const processMcpSideChannel = () => {
10153
10210
  try {
10154
- if (!signalDir || !existsSync12(signalDir)) return;
10211
+ if (!signalDir || !existsSync13(signalDir)) return;
10155
10212
  const completions = readdirSync(signalDir).filter((f) => f.includes("-tool-") && f.endsWith(".json"));
10156
10213
  for (const f of completions) {
10157
10214
  const donePath = join14(signalDir, f);
@@ -10190,7 +10247,7 @@ ${enrichedInput}`;
10190
10247
  continue;
10191
10248
  }
10192
10249
  const respPath = reqPath.replace(".json", "-response.json");
10193
- if (existsSync12(respPath)) continue;
10250
+ if (existsSync13(respPath)) continue;
10194
10251
  const cfg = loadConfig();
10195
10252
  const allowed = cfg.allowedCommands ?? [];
10196
10253
  const cmdBase = (req.args?.command ?? "").toString().trim().split(/\s+/)[0];
@@ -10607,7 +10664,7 @@ ${enrichedInput}`;
10607
10664
  if (!ctx.cesar.pendingDelegation && ctx.cesar.mcpSignalPath) {
10608
10665
  try {
10609
10666
  const signalPath = ctx.cesar.mcpSignalPath;
10610
- if (existsSync12(signalPath)) {
10667
+ if (existsSync13(signalPath)) {
10611
10668
  const signals = JSON.parse(readFileSync13(signalPath, "utf-8"));
10612
10669
  unlinkSync(signalPath);
10613
10670
  for (const signal of Array.isArray(signals) ? signals : [signals]) {
@@ -10662,7 +10719,7 @@ ${enrichedInput}`;
10662
10719
  });
10663
10720
  continue;
10664
10721
  }
10665
- const { handleProposePlan } = await import("./plan-mode-KIXDKD63.js");
10722
+ const { handleProposePlan } = await import("./plan-mode-35BONR7S.js");
10666
10723
  const planDispatch = ctx.cesar.planDispatch ?? dispatch;
10667
10724
  if (planDispatch) {
10668
10725
  try {
@@ -10675,7 +10732,7 @@ ${enrichedInput}`;
10675
10732
  }
10676
10733
  } else if (signal.tool === "ExitPlanMode") {
10677
10734
  recordToolUse("ExitPlanMode", "mcp", JSON.stringify(signal.args ?? {}), "done");
10678
- const { handleExitPlanMode } = await import("./plan-mode-KIXDKD63.js");
10735
+ const { handleExitPlanMode } = await import("./plan-mode-35BONR7S.js");
10679
10736
  const planDispatch = ctx.cesar.planDispatch ?? dispatch;
10680
10737
  try {
10681
10738
  const exitResult = handleExitPlanMode(String(signal.args?.reason ?? ""), planDispatch, ctx);
@@ -10891,7 +10948,7 @@ ${enrichedInput}`;
10891
10948
  output: "A Cesar plan is already active; nested plans are blocked. Resume or cancel the current plan before proposing another."
10892
10949
  });
10893
10950
  } else {
10894
- const { handleProposePlan } = await import("./plan-mode-KIXDKD63.js");
10951
+ const { handleProposePlan } = await import("./plan-mode-35BONR7S.js");
10895
10952
  const planDispatch = ctx.cesar.planDispatch ?? dispatch;
10896
10953
  const plan = await handleProposePlan(ppArgs, planDispatch, ctx);
10897
10954
  if (ctx.setActivePlan) ctx.setActivePlan(plan);
@@ -10915,7 +10972,7 @@ ${enrichedInput}`;
10915
10972
  const epArgs = ctx.cesar._exitPlanModeArgs;
10916
10973
  delete ctx.cesar._exitPlanModeArgs;
10917
10974
  try {
10918
- const { handleExitPlanMode } = await import("./plan-mode-KIXDKD63.js");
10975
+ const { handleExitPlanMode } = await import("./plan-mode-35BONR7S.js");
10919
10976
  const planDispatch = ctx.cesar.planDispatch ?? dispatch;
10920
10977
  const exitResult = handleExitPlanMode(String(epArgs?.reason ?? ""), planDispatch, ctx);
10921
10978
  dispatch({ type: "tool-call", engineId: cesarEngineId, tool: "ExitPlanMode", input: JSON.stringify(epArgs ?? {}), status: "done", output: exitResult });
@@ -11198,9 +11255,7 @@ ${cleanFinalAnswer}` : cleanFinalAnswer;
11198
11255
  const _AUTO_CONT_READONLY_DONE_RE = /\b(?:tests? passed|all (?:tests|checks) pass|no matches found|no issues found|no errors|all clean|nothing to (?:do|fix|change)|already (?:correct|fixed|in place|done))\b/i;
11199
11256
  const _detectTurnState = (resp, baselineToolCount) => {
11200
11257
  const wroteSinceBaseline = _toolsUsed.slice(baselineToolCount).some((t) => _AUTO_CONT_WRITE_TOOLS.has(t));
11201
- const lines = resp.split("\n").map((l) => l.trim()).filter(Boolean);
11202
- const last = lines[lines.length - 1] ?? "";
11203
- if (isUserDirectedQuestion(last)) return "asks-user";
11258
+ if (findTrailingUserQuestion(resp)) return "asks-user";
11204
11259
  if (wroteSinceBaseline && !_AUTO_CONT_CONTINUE_RE.test(resp)) return "done";
11205
11260
  const effectSummary = /(?:created|modified|deleted|updated|added|removed|fixed|implemented|renamed)\b[^.]{0,80}(?:\b(?:and|,)\b[^.]{0,80}\b(?:created|modified|deleted|updated|added|removed|fixed|implemented|renamed)\b)/i.test(resp);
11206
11261
  if (effectSummary) return "done";
@@ -11544,7 +11599,7 @@ ${cleanFinalAnswer}` : cleanFinalAnswer;
11544
11599
  if (followUp.trim()) dispatch({ type: "engine-block", engineId: cesarEngineId, color, content: followUp.trim() });
11545
11600
  }
11546
11601
  }
11547
- return { mode: usedQuickNero ? "self-nero" : "self", delegated: false, responded: true, decisionReason: usedQuickNero ? "self-challenge" : "self-executed", ...buildToolTelemetry() };
11602
+ return { mode: usedQuickNero ? "self-nero" : "self", delegated: false, responded: true, decisionReason: usedQuickNero ? "self-challenge" : "self-executed", awaitingUserInput: detectAwaitingUserInput(response), ...buildToolTelemetry() };
11548
11603
  } else {
11549
11604
  dispatch({ type: "spinner-stop" });
11550
11605
  }
@@ -11660,4 +11715,4 @@ export {
11660
11715
  ensureCesarSession,
11661
11716
  handleCesarBrain
11662
11717
  };
11663
- //# sourceMappingURL=chunk-4NTH3EAR.js.map
11718
+ //# sourceMappingURL=chunk-3PDYVGRS.js.map