topchester-ai 0.19.0 → 0.20.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/cli.mjs CHANGED
@@ -2212,7 +2212,7 @@ function killChild(pid, detached, signal) {
2212
2212
  const inspectCommandTool = defineTool({
2213
2213
  name: "inspect_command",
2214
2214
  description: "Run a narrowly validated read-only command for repository orientation.",
2215
- prompt: "inspect_command: run a safe read-only discovery command inside the workspace for quick orientation; prefer read_file, list_files, grep, and find_file for exact file tasks, and do not use it for builds, tests, installs, network, shell scripts, or edits. To use it, reply with only JSON: {\"tool\":\"inspect_command\",\"args\":{\"command\":\"pwd && rg --files docs/plans | head -20\",\"workdir\":\".\",\"timeout_ms\":10000}}",
2215
+ prompt: "inspect_command: run a safe read-only discovery command inside the workspace for quick repo orientation; prefer read_file, list_files, grep, and find_file for exact file tasks, and do not use it for builds, tests, installs, network, shell scripts, edits, or user-requested specific commands such as node --version, which node, or pnpm --version. To use it, reply with only JSON: {\"tool\":\"inspect_command\",\"args\":{\"command\":\"pwd && rg --files docs/plans | head -20\",\"workdir\":\".\",\"timeout_ms\":10000}}",
2216
2216
  argsSchema: inspectCommandArgsSchema,
2217
2217
  execute: (context, args) => inspectWorkspaceCommand(context.workspaceRoot, args, { pathEnv: context.pathEnv })
2218
2218
  });
@@ -3259,8 +3259,8 @@ const runCommandArgsSchema = z.object({
3259
3259
  });
3260
3260
  const runCommandTool = defineTool({
3261
3261
  name: "run_command",
3262
- description: "Run a strictly policy-approved project command inside the workspace.",
3263
- prompt: "run_command: run a project command only when strict policy allows it; prefer run_validator for tests, lint, typecheck, build, check, format-check, and smoke. To use it, reply with only JSON: {\"tool\":\"run_command\",\"args\":{\"command\":\"node scripts/check-fixtures.mjs\",\"workdir\":\".\",\"timeout_ms\":30000}}",
3262
+ description: "Run a policy-gated command inside the workspace.",
3263
+ prompt: "run_command: run a user-requested command when no more specific tool fits; it is the general policy-gated command runner, and runtime policy decides whether the command is allowed, rejected, or needs approval. Prefer run_validator for tests, lint, typecheck, build, check, format-check, and smoke. To use it, reply with only JSON: {\"tool\":\"run_command\",\"args\":{\"command\":\"node --version\",\"workdir\":\".\",\"timeout_ms\":30000}}",
3264
3264
  argsSchema: runCommandArgsSchema,
3265
3265
  requiresExclusiveWorkspace: true,
3266
3266
  execute: async (context, args) => runWorkspaceCommand(context.workspaceRoot, args, context.config?.tools?.commands, context.runCommandApprovals?.allowExactCommands, context.pathEnv, context.abortSignal)
@@ -4457,11 +4457,14 @@ const hookEventNames = [
4457
4457
  "UserPromptSubmit",
4458
4458
  "PreToolUse",
4459
4459
  "PostToolUse",
4460
+ "PermissionRequest",
4460
4461
  "PreCompact",
4461
4462
  "Stop"
4462
4463
  ];
4463
4464
  const hookEventAliasMap = {
4464
4465
  TaskStart: "SessionStart",
4466
+ TaskAcknowledge: "UserPromptSubmit",
4467
+ UserActionRequired: "PermissionRequest",
4465
4468
  TaskComplete: "Stop"
4466
4469
  };
4467
4470
  const hookTimeoutMsSchema = z.number().int().positive().max(6e5);
@@ -4478,11 +4481,14 @@ const canonicalHooksConfigSchema = z.object({
4478
4481
  UserPromptSubmit: z.array(hookHandlerSchema).optional(),
4479
4482
  PreToolUse: z.array(hookHandlerSchema).optional(),
4480
4483
  PostToolUse: z.array(hookHandlerSchema).optional(),
4484
+ PermissionRequest: z.array(hookHandlerSchema).optional(),
4481
4485
  PreCompact: z.array(hookHandlerSchema).optional(),
4482
4486
  Stop: z.array(hookHandlerSchema).optional()
4483
4487
  }).strict();
4484
4488
  const rawHooksConfigSchema = canonicalHooksConfigSchema.extend({
4485
4489
  TaskStart: z.array(hookHandlerSchema).optional(),
4490
+ TaskAcknowledge: z.array(hookHandlerSchema).optional(),
4491
+ UserActionRequired: z.array(hookHandlerSchema).optional(),
4486
4492
  TaskComplete: z.array(hookHandlerSchema).optional()
4487
4493
  }).strict();
4488
4494
  const topchesterConfigSchema = z.object({
@@ -9219,14 +9225,24 @@ function getChatSystemPrompt(options = {}) {
9219
9225
  ...canUseTool("list_files") && canUseTool("grep") && canUseTool("find_file") && canUseTool("read_file") ? ["- Use list_files, grep, find_file, and read_file for exact file listing, search, lookup, and reading tasks."] : [],
9220
9226
  ...canUseTool("git_status") && canUseTool("git_diff") && canUseTool("git_log") ? ["- Use git_status, git_diff, and git_log for Git state, diffs, and history. Prefer these over inspect_command for Git workflow inspection."] : [],
9221
9227
  ...canUseTool("git_add") && canUseTool("git_commit") ? ["- Use git_add and git_commit only when the user explicitly asks to stage or commit. Never stage unrelated files, never stage '.', and never commit unless staged paths exactly match the user's request."] : [],
9222
- ...canUseTool("inspect_command") ? ["- Use inspect_command only for quick read-only repo orientation when a short familiar command chain is clearer than several dedicated tool calls.", "- inspect_command is not a shell. Unsafe commands, shell expansion, scripts, installs, builds, tests, network access, and file mutation are not available through it."] : [],
9228
+ ...canUseTool("inspect_command") ? [
9229
+ "- Use inspect_command only for quick read-only repo orientation when the user did not ask to run a specific command and a short familiar command chain is clearer than several dedicated tool calls.",
9230
+ "- inspect_command is not a shell. Unsafe commands, shell expansion, scripts, installs, builds, tests, network access, and file mutation are not available through it.",
9231
+ canUseTool("run_command") ? "- Do not use inspect_command when the user asks to run a specific command such as node --version, which node, or pnpm --version; use run_command or run_validator instead." : ""
9232
+ ].filter(Boolean) : [],
9223
9233
  ...canUseTool("run_validator") ? [
9224
9234
  "- After code edits, use run_validator when there is a relevant test, lint, typecheck, build, check, format-check, or smoke command that can prove the change.",
9225
9235
  "- Failed run_validator exits are evidence. Read stdout and stderr, fix the issue when it is in scope, and rerun the narrowest useful validator.",
9226
9236
  canUseTool("run_command") ? "- If run_validator is rejected because the command is not a strict validator shape but the user still needs command output, retry with run_command when project policy allows it." : "",
9227
9237
  "- Do not use inspect_command for tests, builds, lint, typecheck, format checks, or smoke checks. Use run_validator for verification."
9228
9238
  ].filter(Boolean) : [],
9229
- ...canUseTool("run_command") ? ["- Use run_command only for commands allowed by project command policy. Prefer dedicated read, edit, Git, and validator tools when they fit.", "- Do not use run_command for installs, deploys, network commands, destructive commands, interactive commands, file reads, file writes, Git inspection, or validation when run_validator can do it."] : [],
9239
+ ...canUseTool("run_command") ? [
9240
+ "- When the user explicitly asks to run a command or asks for command output, use run_command unless a more specific tool is clearly the right fit.",
9241
+ "- run_command is the general policy-gated command runner. Do not avoid it because a command might be disallowed; call run_command and let command policy return the allowed, rejected, or approval result.",
9242
+ "- Prefer dedicated tools for file reads, file writes, edits, Git inspection, and searches.",
9243
+ "- Use run_command only for commands allowed by project command policy. Prefer dedicated read, edit, Git, and validator tools when they fit.",
9244
+ "- Do not use run_command for installs, deploys, network commands, destructive commands, interactive commands, file reads, file writes, Git inspection, or validation when run_validator can do it."
9245
+ ] : [],
9230
9246
  ...canUseTool("edit_file") && canUseTool("read_file") ? ["- Use read_file before editing a file so your edit is based on current file content and hash metadata."] : [],
9231
9247
  ...canUseTool("read_file") && (canUseTool("edit_file") || canUseTool("write_file")) ? ["- When passing expected_current_hash to edit_file or write_file, use the current pre-edit/pre-write hash from the latest read_file result for that exact file. Never invent it and never use a predicted after-edit or after-write hash."] : [],
9232
9248
  ...canUseTool("edit_file") ? ["- Use edit_file for targeted edits to existing files. Make multiple disjoint edits for the same file in one call when possible."] : [],
@@ -10190,7 +10206,8 @@ var TopchesterAgentRuntime = class TopchesterAgentRuntime {
10190
10206
  }
10191
10207
  if (preHook.blocked) toolResult = createToolErrorResult(executableToolCall.tool, preHook.blocked.message);
10192
10208
  else {
10193
- const approval = await this.resolveRunCommandApproval(executableToolCall, options);
10209
+ const approval = await this.resolveRunCommandApproval(executableToolCall, toolCall.id, options, session, abortSignal);
10210
+ for (const event of approval.events) yield event;
10194
10211
  if (approval.cancelled) toolResult = createToolErrorResult(executableToolCall.tool, approval.reason);
10195
10212
  else {
10196
10213
  const toolEventQueue = createRuntimeEventQueue();
@@ -10303,16 +10320,18 @@ var TopchesterAgentRuntime = class TopchesterAgentRuntime {
10303
10320
  const hookContext = formatHookContextsForPrompt(event, contexts);
10304
10321
  return hookContext ? `${prompt}\n\n${hookContext}` : prompt;
10305
10322
  }
10306
- async resolveRunCommandApproval(call, options) {
10323
+ async resolveRunCommandApproval(call, toolCallId, options, session, abortSignal) {
10307
10324
  const approvedCommands = [...this.approvedRunCommands];
10308
10325
  if (call.tool !== "run_command") return {
10309
10326
  cancelled: false,
10310
- approvedCommands
10327
+ approvedCommands,
10328
+ events: []
10311
10329
  };
10312
10330
  const parsed = runCommandArgsSchema.safeParse(call.args);
10313
10331
  if (!parsed.success) return {
10314
10332
  cancelled: false,
10315
- approvedCommands
10333
+ approvedCommands,
10334
+ events: []
10316
10335
  };
10317
10336
  const decision = await validateRunCommandPolicy(parsed.data, {
10318
10337
  workspaceRoot: this.context.workspaceRoot,
@@ -10321,13 +10340,31 @@ var TopchesterAgentRuntime = class TopchesterAgentRuntime {
10321
10340
  });
10322
10341
  if (decision.allowed) return {
10323
10342
  cancelled: false,
10324
- approvedCommands
10343
+ approvedCommands,
10344
+ events: []
10325
10345
  };
10326
10346
  if (!isRunCommandApprovalEligible(decision.reason) || !options.requestRunCommandApproval) return {
10327
10347
  cancelled: false,
10328
- approvedCommands
10348
+ approvedCommands,
10349
+ events: []
10329
10350
  };
10330
10351
  const command = decision.commands[0] ?? parsed.data.command.trim();
10352
+ const actionRequiredHook = await this.runHookEvent("PermissionRequest", this.createToolHookPayload("PermissionRequest", call, toolCallId, session, {
10353
+ notification_type: "permission_prompt",
10354
+ permission_mode: "",
10355
+ command,
10356
+ workdir: parsed.data.workdir,
10357
+ reason: decision.reason
10358
+ }), {
10359
+ toolName: call.tool,
10360
+ abortSignal
10361
+ });
10362
+ const events = this.hookResultToEvents(actionRequiredHook);
10363
+ if (actionRequiredHook.blocked || actionRequiredHook.stopped) return {
10364
+ cancelled: true,
10365
+ reason: (actionRequiredHook.blocked ?? actionRequiredHook.stopped).message,
10366
+ events
10367
+ };
10331
10368
  const approval = await options.requestRunCommandApproval({
10332
10369
  command,
10333
10370
  workdir: parsed.data.workdir,
@@ -10335,18 +10372,21 @@ var TopchesterAgentRuntime = class TopchesterAgentRuntime {
10335
10372
  });
10336
10373
  if (approval === "cancel") return {
10337
10374
  cancelled: true,
10338
- reason: `run_command cancelled by user for '${command}'.`
10375
+ reason: `run_command cancelled by user for '${command}'.`,
10376
+ events
10339
10377
  };
10340
10378
  if (approval === "allow_session" || approval === "allow_repo") {
10341
10379
  this.approvedRunCommands.add(command);
10342
10380
  return {
10343
10381
  cancelled: false,
10344
- approvedCommands: [...this.approvedRunCommands]
10382
+ approvedCommands: [...this.approvedRunCommands],
10383
+ events
10345
10384
  };
10346
10385
  }
10347
10386
  return {
10348
10387
  cancelled: false,
10349
- approvedCommands: [...approvedCommands, command]
10388
+ approvedCommands: [...approvedCommands, command],
10389
+ events
10350
10390
  };
10351
10391
  }
10352
10392
  /**