@livx.cc/agentx 0.99.127 → 0.99.128

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/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { c as AgentOptions, H as Hooks, x as RunResult, k as Decider, b as Agent, q as PermissionPolicy, G as Gender, L as LineKind, d as ChannelMode, y as SecondChannelOptions, S as SecondChannel } from './secondChannel-CYU9qqwr.js';
2
- export { A as ADVISE_LIMIT, a as AdvisorSetup, C as CC_WRITE_TOOLS, e as ChatFragment, f as ChatUsage, g as Classification, h as Classifier, i as CompactResult, j as ContextFileSpec, D as DEFAULT_MUTATING, l as Decision, M as ModelRouter, m as ModelRouterOptions, P as PLANNER_BLOCKED, n as PLANNER_REFUSAL, o as PLAN_FIRST, p as PermissionOptions, r as PermissionRule, s as PreToolUseDecision, R as ReasoningEffort, t as RecordingHooks, u as RecordingLifecycle, v as RouteDecision, w as RouterState, T as Tier, z as ToolUse, B as ToolUseMeta, W as WRITE_TOOLS, E as advisorFor, F as advisorPrompt, I as ccModeOptions, J as claudeCodeDisallowedTools, K as composeHooks, N as delegatePrompt, O as delegateTools, Q as delegateWorkerFor, U as estimateTokens, V as jevAvailable, X as jevClassifier, Y as loadContextFiles, Z as loadInstructions, _ as makeAdvisor, $ as meterWorkers, a0 as pickTier, a1 as planMode, a2 as plannerBlocks, a3 as reasoningToChatFragment } from './secondChannel-CYU9qqwr.js';
1
+ import { c as AgentOptions, H as Hooks, x as RunResult, k as Decider, b as Agent, q as PermissionPolicy, G as Gender, L as LineKind, d as ChannelMode, y as SecondChannelOptions, S as SecondChannel } from './secondChannel-D-8AGmAT.js';
2
+ export { A as ADVISE_LIMIT, a as AdvisorSetup, C as CC_WRITE_TOOLS, e as ChatFragment, f as ChatUsage, g as Classification, h as Classifier, i as CompactResult, j as ContextFileSpec, D as DEFAULT_MUTATING, l as Decision, M as ModelRouter, m as ModelRouterOptions, P as PLANNER_BLOCKED, n as PLANNER_REFUSAL, o as PLAN_FIRST, p as PermissionOptions, r as PermissionRule, s as PreToolUseDecision, R as ReasoningEffort, t as RecordingHooks, u as RecordingLifecycle, v as RouteDecision, w as RouterState, T as Tier, z as ToolUse, B as ToolUseMeta, W as WRITE_TOOLS, E as advisorFor, F as advisorPrompt, I as ccModeOptions, J as claudeCodeDisallowedTools, K as composeHooks, N as delegatePrompt, O as delegateTools, Q as delegateWorkerFor, U as estimateTokens, V as jevAvailable, X as jevClassifier, Y as loadContextFiles, Z as loadInstructions, _ as makeAdvisor, $ as meterWorkers, a0 as pickTier, a1 as planMode, a2 as plannerBlocks, a3 as reasoningToChatFragment } from './secondChannel-D-8AGmAT.js';
3
3
  export { MODEL_ALIASES, ModelSwitch, ResolveModelSwitchOpts, latestClaude, modelShortLabel, resolveModelAlias, resolveModelSwitch } from './models.js';
4
4
  import { IFilesystem, FileMetadata } from '@livx.cc/wcli/core';
5
5
  export { CommandExecutor, FileMetadata, IFilesystem, IndexedDbFilesystem, MemFilesystem, registerHeadlessCommands } from '@livx.cc/wcli/core';
package/dist/index.js CHANGED
@@ -3901,16 +3901,19 @@ import { join as join3 } from "path";
3901
3901
 
3902
3902
  // src/permissions.ts
3903
3903
  init_tools_structured();
3904
+ import { posix } from "path";
3904
3905
  function commandMatches(glob, cmd) {
3905
3906
  const pattern = glob.split("*").map((s) => s.replace(/[.+?^${}()|[\]\\]/g, "\\$&")).join(".*");
3906
3907
  return new RegExp("^" + pattern + "$").test(cmd);
3907
3908
  }
3909
+ var SHELL_CONTROL = /[;&|`$<>\n\r]/;
3908
3910
  function toolMatches(rule, name) {
3909
3911
  return rule.includes("*") ? commandMatches(rule, name) : rule === name;
3910
3912
  }
3911
3913
  var PermissionOptions = class {
3912
3914
  rules = [];
3913
- /** decision when no rule matches. */
3915
+ /** decision when no rule matches. 'deny' = an allow-list run (`--onlyTools`): only the allow rules run, an allowed
3916
+ * command glob never matches shell control syntax, and claude-code enforces it by a PreToolUse hook (ccHooks). */
3914
3917
  default = "allow";
3915
3918
  /** host channel for `ask` (confirm). If absent, `ask` is treated as `deny` (fail-closed). */
3916
3919
  host;
@@ -3923,15 +3926,17 @@ var PermissionPolicy = class {
3923
3926
  /** Resolve the decision for a tool call (first matching rule, else default). */
3924
3927
  decide(call) {
3925
3928
  const names = call.name === "McpCall" && typeof call.args?.name === "string" ? [call.name, call.args.name] : [call.name];
3929
+ if (CC_TOOL_ALIAS[call.name]) names.push(CC_TOOL_ALIAS[call.name]);
3930
+ const strict = this.options.default === "deny";
3926
3931
  for (const r of this.options.rules) {
3927
3932
  if (r.tool && !names.some((n) => toolMatches(r.tool, n))) continue;
3928
3933
  if (r.pathGlob) {
3929
3934
  const path = typeof call.args?.path === "string" ? call.args.path : null;
3930
3935
  const cmd = typeof call.args?.command === "string" ? call.args.command : null;
3931
3936
  if (path != null) {
3932
- if (!globToRegExp(r.pathGlob).test(path.startsWith("/") ? path : `/${path}`)) continue;
3937
+ if (!globToRegExp(r.pathGlob).test(posix.normalize(path.startsWith("/") ? path : `/${path}`))) continue;
3933
3938
  } else if (cmd != null) {
3934
- if (!commandMatches(r.pathGlob, cmd)) continue;
3939
+ if (!commandMatches(r.pathGlob, cmd) || strict && r.decision === "allow" && SHELL_CONTROL.test(cmd)) continue;
3935
3940
  } else continue;
3936
3941
  }
3937
3942
  return r.decision;
@@ -3943,6 +3948,18 @@ var PermissionPolicy = class {
3943
3948
  denyRules(explicitOnly = false) {
3944
3949
  return this.options.rules.filter((r) => r.decision === "deny" && (!explicitOnly || r.explicit)).map((r) => `${r.tool ?? "*"}${r.pathGlob ? `(${r.pathGlob})` : ""}`);
3945
3950
  }
3951
+ /** An allow-list policy (default 'deny') as Claude Code SDK hooks: claude-code runs its own tools, which never reach
3952
+ * {@link hooks}, and `disallowedTools` can't say "everything else". Every tool call (native and MCP) goes through
3953
+ * decide(); `ask` has no host there → deny. undefined for a default-allow policy (its deny rules travel as disallowedTools). */
3954
+ ccHooks() {
3955
+ if (this.options.default !== "deny") return void 0;
3956
+ const gate = async (input) => {
3957
+ const t = input?.tool_input ?? {}, path = t.file_path ?? t.notebook_path ?? t.path;
3958
+ const d = this.decide({ name: String(input?.tool_name ?? ""), args: { ...t, ...typeof path === "string" ? { path } : {} } });
3959
+ return d === "allow" ? {} : { hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "deny", permissionDecisionReason: `not on this run's tool allow-list (${input?.tool_name})` } };
3960
+ };
3961
+ return { PreToolUse: [{ hooks: [gate] }] };
3962
+ }
3946
3963
  /** A preToolUse hook enforcing this policy (deny/ask → block; allow → proceed). */
3947
3964
  hooks() {
3948
3965
  return {
@@ -5181,6 +5198,11 @@ var Agent = class _Agent {
5181
5198
  }
5182
5199
  const denyTools = [...claudeCodeDisallowedTools(o.permissions), ...mode.disallow];
5183
5200
  if (mode.hooks) po.hooks = mode.hooks;
5201
+ const allowOnly = o.permissions?.ccHooks();
5202
+ if (allowOnly) {
5203
+ const h = po.hooks ?? o.providerOptions?.hooks ?? {};
5204
+ po.hooks = { ...h, PreToolUse: [...h.PreToolUse ?? [], ...allowOnly.PreToolUse] };
5205
+ }
5184
5206
  if (this.modeKind && o.providerOptions?.claudeCodeSession) po.claudeCodeSession = `${o.providerOptions.claudeCodeSession}:${this.modeKind}`;
5185
5207
  if (denyTools.length) {
5186
5208
  const prior = o.providerOptions?.disallowedTools ?? [];
@@ -5538,6 +5560,8 @@ var Agent = class _Agent {
5538
5560
  const claudeSteerPo = this.claudeCodePo();
5539
5561
  if (this.ccServer) this.ccExec = hostExec;
5540
5562
  const cursorDeny = o.model.startsWith("cursor/") ? o.permissions?.denyRules(true) ?? [] : [];
5563
+ if (o.model.startsWith("cursor/") && o.permissions?.options.default === "deny")
5564
+ throw new Error("cursor/* cannot enforce --onlyTools: its native tools bypass it. Refusing to run \u2014 use a claude-code/* or API model.");
5541
5565
  if (cursorDeny.length)
5542
5566
  throw new Error(`cursor/* cannot enforce --disallowedTools (${cursorDeny.join(", ")}): its native tools bypass them. Refusing to run \u2014 use a claude-code/* or API model, or drop --disallowedTools.`);
5543
5567
  const reasonOpts = {