topchester-ai 0.65.0 → 0.66.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.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as runTopchesterCli } from "./cli-2v1iJ0YF.mjs";
2
+ import { t as runTopchesterCli } from "./cli-BS67FTk8.mjs";
3
3
  //#region src/bin.ts
4
4
  await runTopchesterCli();
5
5
  //#endregion
@@ -21,6 +21,13 @@ import { diffWords } from "diff";
21
21
  import { highlight, supportsLanguage } from "cli-highlight";
22
22
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
23
23
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
24
+ //#region src/agent/benchmark-profile.ts
25
+ const BENCHMARK_PROFILES = ["terminal-bench"];
26
+ function parseBenchmarkProfile(value) {
27
+ if (BENCHMARK_PROFILES.includes(value)) return value;
28
+ throw new Error(`Unsupported benchmark profile '${value}'. Supported profiles: ${BENCHMARK_PROFILES.join(", ")}.`);
29
+ }
30
+ //#endregion
24
31
  //#region src/auth/codex.ts
25
32
  const CODEX_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
26
33
  const CODEX_ISSUER = "https://auth.openai.com";
@@ -638,9 +645,10 @@ async function validateBashPolicy(args, context) {
638
645
  if (!cwd.allowed) return reject(command, cwd.reason, false);
639
646
  const deniedRule = findMatchingBashRule(command, context.permissions?.deny ?? []);
640
647
  if (deniedRule) return reject(command, `bash policy rejected '${command}' because it matches deny rule '${deniedRule}'.`, false);
648
+ const shell = resolveBashShell(context.permissions?.shell);
649
+ if (context.benchmarkProfile === "terminal-bench") return allow(command, cwd.path, realWorkspaceRoot, shell, "benchmark_terminal", "terminal-bench");
641
650
  const destructive = getDestructiveReason(command);
642
651
  if (destructive) return reject(command, `bash policy rejected '${command}' because it looks destructive: ${destructive}.`, false);
643
- const shell = resolveBashShell(context.permissions?.shell);
644
652
  const allowedExactRule = findExactBashRule(command, context.permissions?.allowExact ?? []);
645
653
  if (allowedExactRule) return allow(command, cwd.path, realWorkspaceRoot, shell, "allow_exact", allowedExactRule);
646
654
  const approvedRule = findExactBashRule(command, context.approvedCommands ?? []);
@@ -668,7 +676,7 @@ function getBashApprovalCandidates(command) {
668
676
  };
669
677
  }
670
678
  function allow(command, cwd, workspaceRoot, shell, kind, matchedRule) {
671
- const reason = kind === "allow_exact" ? `bash exact command allowed by '${matchedRule}'` : kind === "allow_prefix" ? `bash command allowed by prefix '${matchedRule}'` : `bash exact command approved by '${matchedRule}'`;
679
+ const reason = kind === "allow_exact" ? `bash exact command allowed by '${matchedRule}'` : kind === "benchmark_terminal" ? `bash command allowed by benchmark profile '${matchedRule}'` : kind === "allow_prefix" ? `bash command allowed by prefix '${matchedRule}'` : `bash exact command approved by '${matchedRule}'`;
672
680
  return {
673
681
  allowed: true,
674
682
  reason,
@@ -758,14 +766,16 @@ const bashTool = defineTool({
758
766
  pathEnv: context.pathEnv,
759
767
  abortSignal: context.abortSignal,
760
768
  permissions: context.config?.tools?.bash,
761
- approvedCommands: context.bashApprovals?.allowExactCommands
769
+ approvedCommands: context.bashApprovals?.allowExactCommands,
770
+ benchmarkProfile: context.benchmarkProfile
762
771
  })
763
772
  });
764
773
  async function runBashCommand(workspaceRoot, args, options = {}) {
765
774
  const decision = await validateBashPolicy(args, {
766
775
  workspaceRoot,
767
776
  permissions: options.permissions,
768
- approvedCommands: options.approvedCommands
777
+ approvedCommands: options.approvedCommands,
778
+ benchmarkProfile: options.benchmarkProfile
769
779
  });
770
780
  if (!decision.allowed) throw new Error(decision.reason);
771
781
  const result = await runProcess({
@@ -1843,7 +1853,7 @@ async function deleteWorkspaceFile(workspaceRoot, path) {
1843
1853
  const finishTaskTool = defineTool({
1844
1854
  name: "finish_task",
1845
1855
  description: "Finish the current task only after the requested work has actually been completed with tools. Do not use this to claim edits, file reads, or validation that did not happen.",
1846
- prompt: "finish_task: complete the task with a brief final response only after tool results prove the work is done. In benchmark or require-finish mode, this is the only valid terminal action; normal assistant messages are progress notes and do not finish the task. For implementation tasks, do not call finish_task until source files were changed by edit_file, write_file, apply_patch, or another mutating tool, unless no code change is truly required. Example: {\"tool\":\"finish_task\",\"args\":{\"final_response\":\"Changed src/foo.ts and ran pnpm test foo.test.ts.\",\"files_changed\":[\"src/foo.ts\"],\"validation\":[\"pnpm test foo.test.ts\"],\"remaining_issues\":[]}}",
1856
+ prompt: "finish_task: complete the task with a brief final response only after tool results prove the work is done. In benchmark or require-finish mode, this is the only valid terminal action; normal assistant messages are progress notes and do not finish the task, and remaining_issues must be empty. For implementation tasks, do not call finish_task until source files were changed by edit_file, write_file, apply_patch, or another mutating tool, unless no code change is truly required. Example: {\"tool\":\"finish_task\",\"args\":{\"final_response\":\"Changed src/foo.ts and ran pnpm test foo.test.ts.\",\"files_changed\":[\"src/foo.ts\"],\"validation\":[\"pnpm test foo.test.ts\"],\"remaining_issues\":[]}}",
1847
1857
  argsSchema: z.object({
1848
1858
  final_response: z.string().describe("Brief final response for the user."),
1849
1859
  files_changed: z.array(z.string()).optional().describe("Workspace-relative files actually changed by successful edit tools."),
@@ -12054,6 +12064,7 @@ async function executeToolCall(workspaceRoot, call, options = {}) {
12054
12064
  subagents: options.subagents,
12055
12065
  projectInstructions: options.projectInstructions,
12056
12066
  currentUserMessage: options.currentUserMessage,
12067
+ benchmarkProfile: options.benchmarkProfile,
12057
12068
  eventSink: options.eventSink,
12058
12069
  abortSignal: options.abortSignal,
12059
12070
  toolCallId: options.toolCallId
@@ -13492,6 +13503,7 @@ var TopchesterAgentRuntime = class TopchesterAgentRuntime {
13492
13503
  subagents,
13493
13504
  projectInstructions: projectInstructionToolState,
13494
13505
  currentUserMessage: message,
13506
+ benchmarkProfile: options.benchmarkProfile,
13495
13507
  abortSignal,
13496
13508
  toolCallId: entry.toolCallId,
13497
13509
  toolCatalog,
@@ -13510,7 +13522,7 @@ var TopchesterAgentRuntime = class TopchesterAgentRuntime {
13510
13522
  const call = taskCalls[index];
13511
13523
  const toolResult = taskResults[index];
13512
13524
  for (const event of createInstructionContextEventsFromToolResult(toolResult, persistedProjectInstructionKeys)) yield event;
13513
- if (isSourceMutationResult(toolResult)) hasSourceMutation = true;
13525
+ if (isSourceMutationResult(toolResult) || isBenchmarkMutationResult(toolResult, options.benchmarkProfile)) hasSourceMutation = true;
13514
13526
  yield agentEvent.toolCall(call, formatToolCallMessage(call, toolResult), getToolCallDisplayDiff(toolResult));
13515
13527
  const postHookRun = this.startPostToolUseHook(call, modelToolCalls[index]?.id, toolResult, session, abortSignal);
13516
13528
  for await (const event of postHookRun.statusEvents) yield event;
@@ -13562,6 +13574,7 @@ var TopchesterAgentRuntime = class TopchesterAgentRuntime {
13562
13574
  subagents,
13563
13575
  projectInstructions: projectInstructionToolState,
13564
13576
  currentUserMessage: message,
13577
+ benchmarkProfile: options.benchmarkProfile,
13565
13578
  abortSignal,
13566
13579
  toolCallId: entry.toolCallId,
13567
13580
  toolCatalog
@@ -13574,7 +13587,7 @@ var TopchesterAgentRuntime = class TopchesterAgentRuntime {
13574
13587
  const call = parallelCalls[index];
13575
13588
  const toolResult = parallelResults[index];
13576
13589
  for (const event of createInstructionContextEventsFromToolResult(toolResult, persistedProjectInstructionKeys)) yield event;
13577
- if (isSourceMutationResult(toolResult)) hasSourceMutation = true;
13590
+ if (isSourceMutationResult(toolResult) || isBenchmarkMutationResult(toolResult, options.benchmarkProfile)) hasSourceMutation = true;
13578
13591
  yield agentEvent.toolCall(call, formatToolCallMessage(call, toolResult), getToolCallDisplayDiff(toolResult));
13579
13592
  const postHookRun = this.startPostToolUseHook(call, modelToolCalls[index]?.id, toolResult, session, abortSignal);
13580
13593
  for await (const event of postHookRun.statusEvents) yield event;
@@ -13639,6 +13652,7 @@ var TopchesterAgentRuntime = class TopchesterAgentRuntime {
13639
13652
  subagents,
13640
13653
  projectInstructions: projectInstructionToolState,
13641
13654
  currentUserMessage: message,
13655
+ benchmarkProfile: options.benchmarkProfile,
13642
13656
  abortSignal,
13643
13657
  toolCallId: toolCall.id,
13644
13658
  toolCatalog,
@@ -13657,11 +13671,12 @@ var TopchesterAgentRuntime = class TopchesterAgentRuntime {
13657
13671
  implementationTask,
13658
13672
  hasSourceMutation,
13659
13673
  hasOpenPlan: planTodoMode === "normal" && hasOpenTaskPlan(this.taskPlan.get()),
13660
- canUseSourceEditTool: canStillUseSourceEditTool(permissions)
13674
+ canUseSourceEditTool: canStillUseSourceEditTool(permissions),
13675
+ requireFinishTask
13661
13676
  });
13662
13677
  if (finishError) toolResult = createToolErrorResult(executableToolCall.tool, finishError);
13663
13678
  }
13664
- if (isSourceMutationResult(toolResult)) hasSourceMutation = true;
13679
+ if (isSourceMutationResult(toolResult) || isBenchmarkMutationResult(toolResult, options.benchmarkProfile)) hasSourceMutation = true;
13665
13680
  yield agentEvent.toolCall(executableToolCall, formatToolCallMessage(executableToolCall, toolResult), getToolCallDisplayDiff(toolResult));
13666
13681
  if (!isToolErrorResult(toolResult) && toolResult.tool === "plan_todo") {
13667
13682
  planTodoUpdates += 1;
@@ -13870,7 +13885,8 @@ var TopchesterAgentRuntime = class TopchesterAgentRuntime {
13870
13885
  const decision = await validateBashPolicy(parsed.data, {
13871
13886
  workspaceRoot: this.context.workspaceRoot,
13872
13887
  permissions: this.context.config.tools?.bash,
13873
- approvedCommands
13888
+ approvedCommands,
13889
+ benchmarkProfile: options.benchmarkProfile
13874
13890
  });
13875
13891
  if (decision.allowed) return {
13876
13892
  cancelled: false,
@@ -14125,6 +14141,10 @@ function isSourceMutationResult(result) {
14125
14141
  if (result.tool === "apply_patch") return result.changedFiles.some(isSourcePath);
14126
14142
  return false;
14127
14143
  }
14144
+ function isBenchmarkMutationResult(result, benchmarkProfile) {
14145
+ if (benchmarkProfile !== "terminal-bench" || isToolErrorResult(result)) return false;
14146
+ return result.tool === "bash" && "workspaceMayHaveChanged" in result && result.workspaceMayHaveChanged === true;
14147
+ }
14128
14148
  function isSourcePath(path) {
14129
14149
  if (!path) return false;
14130
14150
  return !path.startsWith(".agents/") && !path.startsWith(".git/") && !path.startsWith("topchester-kb/");
@@ -14133,6 +14153,7 @@ function validateFinishTaskResult(result, state) {
14133
14153
  if (isToolErrorResult(result) || result.tool !== "finish_task") return;
14134
14154
  if (state.hasOpenPlan) return "finish_task rejected because the visible plan is still open. Close or update plan_todo first.";
14135
14155
  if (state.implementationTask && state.canUseSourceEditTool && !state.hasSourceMutation) return "finish_task rejected because this appears to be an implementation task but no successful source-file edit has occurred. Use edit_file, write_file, or apply_patch first, unless you can prove no code change is required.";
14156
+ if (state.requireFinishTask && result.remainingIssues.length > 0) return "finish_task rejected because benchmark mode cannot finish with known remaining issues. Continue implementing or validating until remaining_issues is empty.";
14136
14157
  }
14137
14158
  function isL1ContextDisabledByEnv() {
14138
14159
  const value = process.env.TOPCHESTER_DISABLE_L1_CONTEXT?.trim().toLowerCase();
@@ -15710,12 +15731,14 @@ async function executeRunCommand(context, options) {
15710
15731
  json: Boolean(options.json),
15711
15732
  outputJson: options.outputJson,
15712
15733
  timeoutMs,
15713
- dangerouslyAutoApprove: Boolean(options.dangerouslyAutoApprove)
15734
+ dangerouslyAutoApprove: Boolean(options.dangerouslyAutoApprove),
15735
+ benchmarkProfile: options.benchmarkProfile
15714
15736
  }, "run started");
15715
15737
  pushJson(jsonEvents, runId, session.sessionId, "run.started", {
15716
15738
  workspaceRoot: runContext.workspaceRoot,
15717
15739
  timeoutMs,
15718
- dangerouslyAutoApprove: Boolean(options.dangerouslyAutoApprove)
15740
+ dangerouslyAutoApprove: Boolean(options.dangerouslyAutoApprove),
15741
+ benchmarkProfile: options.benchmarkProfile
15719
15742
  });
15720
15743
  try {
15721
15744
  if (!options.resume) await persistStartupMessages(session, runContext);
@@ -15772,7 +15795,8 @@ async function executeRunCommand(context, options) {
15772
15795
  });
15773
15796
  for await (const event of runtime.submitMessageStream(conversation, options.prompt, abortController.signal, {
15774
15797
  session,
15775
- userApprovalMode: options.dangerouslyAutoApprove ? "auto_allow" : "interactive"
15798
+ userApprovalMode: options.dangerouslyAutoApprove ? "auto_allow" : "interactive",
15799
+ benchmarkProfile: options.benchmarkProfile
15776
15800
  })) await applyRuntimeEvent({
15777
15801
  event,
15778
15802
  session,
@@ -16228,7 +16252,7 @@ function createTopchesterProgram() {
16228
16252
  process.exitCode = 1;
16229
16253
  }
16230
16254
  });
16231
- program.command("run").description("run one prompt or slash command without opening the TUI").argument("<prompt...>", "prompt text or slash command").option("--model <model>", "override the agent.primary model for this run").option("--timeout <ms>", "timeout for the run in milliseconds", parsePositiveInteger).option("--json", "write JSONL run events to stdout").option("--output-json <path>", "write JSONL run events to a file").option("--dangerously-auto-approve", "auto-approve prompt-gated tool calls for this non-interactive run").action(async (promptParts, options) => {
16255
+ program.command("run").description("run one prompt or slash command without opening the TUI").argument("<prompt...>", "prompt text or slash command").option("--model <model>", "override the agent.primary model for this run").option("--timeout <ms>", "timeout for the run in milliseconds", parsePositiveInteger).option("--json", "write JSONL run events to stdout").option("--output-json <path>", "write JSONL run events to a file").option("--dangerously-auto-approve", "auto-approve prompt-gated tool calls for this non-interactive run").option("--benchmark-profile <profile>", "enable an explicit benchmark runtime profile", parseBenchmarkProfile).action(async (promptParts, options) => {
16232
16256
  const context = createContextFromOptions(program);
16233
16257
  const globalOptions = program.opts();
16234
16258
  try {
@@ -16239,7 +16263,8 @@ function createTopchesterProgram() {
16239
16263
  json: options.json,
16240
16264
  outputJson: options.outputJson,
16241
16265
  resume: globalOptions.resume,
16242
- dangerouslyAutoApprove: options.dangerouslyAutoApprove
16266
+ dangerouslyAutoApprove: options.dangerouslyAutoApprove,
16267
+ benchmarkProfile: options.benchmarkProfile
16243
16268
  });
16244
16269
  } catch (error) {
16245
16270
  console.error(formatStartupError(error));
@@ -16529,4 +16554,4 @@ function formatDryRunSyncStatus(status) {
16529
16554
  //#endregion
16530
16555
  export { runTopchesterCli as t };
16531
16556
 
16532
- //# sourceMappingURL=cli-2v1iJ0YF.mjs.map
16557
+ //# sourceMappingURL=cli-BS67FTk8.mjs.map