@livx.cc/agentx 0.99.63 → 0.99.65
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/{Agent-DbqXQy5q.d.ts → Agent-BpCqDWFG.d.ts} +13 -2
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +167 -134
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +8 -6
- package/dist/index.js +162 -128
- package/dist/index.js.map +1 -1
- package/dist/{mcp-CSLRyvEp.d.ts → mcp-DGd2If0Z.d.ts} +1 -1
- package/dist/mcp.client.d.ts +2 -2
- package/dist/{tools-HsbxgqjF.d.ts → tools-DV4SkkQs.d.ts} +6 -0
- package/dist/tools.shell.d.ts +1 -1
- package/dist/tools.shell.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { a as AgentOptions, H as Hooks, n as RunResult, A as Agent } from './Agent-
|
|
2
|
-
export { C as ChatFragment, b as Classification, c as Classifier, d as CompactResult, D as DEFAULT_MUTATING, e as Decision, M as ModelRouter, f as ModelRouterOptions, P as PermissionOptions,
|
|
1
|
+
import { a as AgentOptions, H as Hooks, n as RunResult, A as Agent, g as PermissionPolicy } from './Agent-BpCqDWFG.js';
|
|
2
|
+
export { C as ChatFragment, b as Classification, c as Classifier, d as CompactResult, D as DEFAULT_MUTATING, e as Decision, M as ModelRouter, f as ModelRouterOptions, P as PermissionOptions, h as PermissionRule, i as PreToolUseDecision, R as ReasoningEffort, j as RecordingHooks, k as RecordingLifecycle, l as RouteDecision, m as RouterState, T as Tier, o as ToolUse, p as ToolUseMeta, q as claudeCodeDisallowedTools, r as composeHooks, s as estimateTokens, t as jevAvailable, u as jevClassifier, v as pickTier, w as planMode, x as reasoningToChatFragment } from './Agent-BpCqDWFG.js';
|
|
3
3
|
export { MODEL_ALIASES, ModelSwitch, ResolveModelSwitchOpts, 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';
|
|
6
6
|
import { BodDB } from '@bod.ee/db';
|
|
7
|
-
import { A as AgentTool, C as ChatLike, a as ChatOptions, b as ChatResponse, r as ToolCall, H as HostBridge, U as UserQuestion, o as MessageContent } from './tools-
|
|
8
|
-
export { c as ContentPart, d as HostEvent, I as IMAGE_ELIDE_STUB, e as IMAGE_REF_SCHEME, f as ImageRef, J as JobCtx, g as JobHandle, h as JobInfo, i as JobKind, j as JobNotice, k as JobRegistry, l as JobRegistryOptions, n as JobTrackOptions, M as Message, m as RegistryJobStatus, R as Role, S as SandboxJobRegistry, p as StreamChunk, T as TodoItem, q as Tool, s as ToolContext, t as bashTool, u as clearImageRefs, v as contentBytes, w as contentText, x as defaultTools, y as editTool, z as elideImages, B as elideInlineImages, D as elideStaleImages, E as exitSessionTool, F as expandImagesForSend, G as formatJobNotice, K as imagePart, L as imageRefPart, N as imageRefResult, O as makeContext, P as makeJobTools, Q as messageHasImage, V as messageHasImageRef, W as messageHasInlineImage, X as mintImageRef, Y as parseImageRef, Z as readTool, _ as remintImageRefs, $ as sendBytes, a0 as sendBytesPer, a1 as toWireTools, a2 as todoWriteTool, a3 as toolImageRef, a4 as toolRegistry, a5 as toolsByName } from './tools-
|
|
7
|
+
import { A as AgentTool, C as ChatLike, a as ChatOptions, b as ChatResponse, r as ToolCall, H as HostBridge, U as UserQuestion, o as MessageContent } from './tools-DV4SkkQs.js';
|
|
8
|
+
export { c as ContentPart, d as HostEvent, I as IMAGE_ELIDE_STUB, e as IMAGE_REF_SCHEME, f as ImageRef, J as JobCtx, g as JobHandle, h as JobInfo, i as JobKind, j as JobNotice, k as JobRegistry, l as JobRegistryOptions, n as JobTrackOptions, M as Message, m as RegistryJobStatus, R as Role, S as SandboxJobRegistry, p as StreamChunk, T as TodoItem, q as Tool, s as ToolContext, t as bashTool, u as clearImageRefs, v as contentBytes, w as contentText, x as defaultTools, y as editTool, z as elideImages, B as elideInlineImages, D as elideStaleImages, E as exitSessionTool, F as expandImagesForSend, G as formatJobNotice, K as imagePart, L as imageRefPart, N as imageRefResult, O as makeContext, P as makeJobTools, Q as messageHasImage, V as messageHasImageRef, W as messageHasInlineImage, X as mintImageRef, Y as parseImageRef, Z as readTool, _ as remintImageRefs, $ as sendBytes, a0 as sendBytesPer, a1 as toWireTools, a2 as todoWriteTool, a3 as toolImageRef, a4 as toolRegistry, a5 as toolsByName } from './tools-DV4SkkQs.js';
|
|
9
9
|
import { ShellJobRegistry } from './tools.shell.js';
|
|
10
10
|
import { SpokenSplitter } from '@bod.ee/voice';
|
|
11
11
|
export { AudioSink, AudioSource, AuthProvider, CartesiaTTS, CartesiaTTSOptions, STT_SAMPLE_RATE, SonioxSTT, SonioxSTTOptions, SttLike, TTS_SAMPLE_RATE, TtsLike, VoiceEngine, VoiceEngineOptions, VoiceState, resolveAuth } from '@bod.ee/voice';
|
|
12
|
-
export { M as McpCall, a as McpImage, b as McpRoute, c as McpRouteResolver, d as McpToolResult, e as McpToolSearchOptions, f as McpToolSpec, g as MountedMcpLike, h as buildMcpCatalog, m as makeLazyMcpToolSearch, i as makeMcpToolSearch, j as makeMcpToolSearchFromMounted, k as mcpToolToAgentTool, l as mcpToolsToAgentTools } from './mcp-
|
|
12
|
+
export { M as McpCall, a as McpImage, b as McpRoute, c as McpRouteResolver, d as McpToolResult, e as McpToolSearchOptions, f as McpToolSpec, g as MountedMcpLike, h as buildMcpCatalog, m as makeLazyMcpToolSearch, i as makeMcpToolSearch, j as makeMcpToolSearchFromMounted, k as mcpToolToAgentTool, l as mcpToolsToAgentTools } from './mcp-DGd2If0Z.js';
|
|
13
13
|
import * as libx_js_src_modules_log from 'libx.js/src/modules/log';
|
|
14
14
|
export { log } from 'libx.js/src/modules/log';
|
|
15
15
|
|
|
@@ -1417,6 +1417,8 @@ interface TaskToolOptions {
|
|
|
1417
1417
|
maxParallel?: number;
|
|
1418
1418
|
/** Parent hooks — `onSubagentStop` fires with each child's summary when it finishes. */
|
|
1419
1419
|
hooks?: Hooks;
|
|
1420
|
+
/** Parent permission policy — its DENY rules are inherited by every child (they must hold across delegation). */
|
|
1421
|
+
permissions?: PermissionPolicy;
|
|
1420
1422
|
/**
|
|
1421
1423
|
* Wall-clock ceiling for ONE child run, in ms (default `SUBAGENT_MAX_DURATION_MS`). `maxSteps` alone is
|
|
1422
1424
|
* not a bound: 25 steps x a 600s Shell is ~250 minutes, far past any transport deadline wrapping the
|
|
@@ -1491,4 +1493,4 @@ declare function exitWorktree(): {
|
|
|
1491
1493
|
reason?: string;
|
|
1492
1494
|
} | null;
|
|
1493
1495
|
|
|
1494
|
-
export { Agent, type AgentDef, AgentOptions, AgentTool, type AskOptions, type Attempt, BodDbFilesystem, ChatLike, ChatOptions, ChatResponse, type CommandInfo, ConsoleHostBridge, DEFAULT_DENY, DEFAULT_MAX_DEPTH, DEFAULT_SKIP_DIRS, DuplexAgent, DuplexAgentOptions, type DuplexTaskStatus, FakeAIClient, type FileScanOptions, Hooks, HostBridge, JailOptions, JailedFilesystem, type LessonOptions, LessonOptionsDefaults, type LoadMemoryOpts, MEMORY_PROMPT, MessageContent, type Mount, MountFilesystem, NodeDiskFilesystem, OverlayFilesystem, type ReflectOptions, RunResult, SCRATCH_DIR, type ScheduledJob, type ScheduledJobSnapshot, Scheduler, type SchedulerOptions, Scratch, type ScratchOptions, ScriptedHostBridge, type SiblingResolver, type SkillInfo, type TaskRecord, type TaskToolOptions, ToolCall, type ToolSpec, type Trigger, type TriggerCron, type TriggerInterval, type TriggerOneOff, UserQuestion, VOICE_MEMORY_PROMPT, VOICE_SYSTEM_PROMPT, type WebFetchOptions, type WebSearchOptions, type WorkerTier, type WorktreeInfo, type WorktreeSession, applyEditsTool, askUserQuestionTool, checkpointTool, checkpointTools, cleanupWorktree, compileSynthesizedTool, cronMatches, decodeDdgUrl, diskAgentOptions, enterWorktree, exitWorktree, expandCommand, expandEntry, expandTemplate, findGitRoot, forComponent, fullAgentOptions, getOrCreateWorktree, getWorktreeSession, globTool, grepTool, htmlToText, idfWeights, lessonCapture, loadAgents, loadCommands, loadInstructions, loadMemory, loadSkills, makeAskTool, makeGlobTool, makeGrepTool, makeScheduleTools, makeTaskBatchTool, makeTaskTool, makeWebFetchTool, makeWebSearchAnthropicTool, makeWebSearchTool, mkdirp, multiEditTool, nextCronAfter, parseCron, parseDdgHtml, raceAttempts, reflectOnRun, relevanceScore, repoIndex, repoMapTool, rollbackTool, sandboxAgentOptions, scanCommands, scanSkills, slugify, tokenize, toolCall, topByRelevance, validateToolCode, validateWorktreeSlug, webFetchTool, webSearchAnthropicTool, webSearchTool, worktreeBranchName, writeFact, writeTool };
|
|
1496
|
+
export { Agent, type AgentDef, AgentOptions, AgentTool, type AskOptions, type Attempt, BodDbFilesystem, ChatLike, ChatOptions, ChatResponse, type CommandInfo, ConsoleHostBridge, DEFAULT_DENY, DEFAULT_MAX_DEPTH, DEFAULT_SKIP_DIRS, DuplexAgent, DuplexAgentOptions, type DuplexTaskStatus, FakeAIClient, type FileScanOptions, Hooks, HostBridge, JailOptions, JailedFilesystem, type LessonOptions, LessonOptionsDefaults, type LoadMemoryOpts, MEMORY_PROMPT, MessageContent, type Mount, MountFilesystem, NodeDiskFilesystem, OverlayFilesystem, PermissionPolicy, type ReflectOptions, RunResult, SCRATCH_DIR, type ScheduledJob, type ScheduledJobSnapshot, Scheduler, type SchedulerOptions, Scratch, type ScratchOptions, ScriptedHostBridge, type SiblingResolver, type SkillInfo, type TaskRecord, type TaskToolOptions, ToolCall, type ToolSpec, type Trigger, type TriggerCron, type TriggerInterval, type TriggerOneOff, UserQuestion, VOICE_MEMORY_PROMPT, VOICE_SYSTEM_PROMPT, type WebFetchOptions, type WebSearchOptions, type WorkerTier, type WorktreeInfo, type WorktreeSession, applyEditsTool, askUserQuestionTool, checkpointTool, checkpointTools, cleanupWorktree, compileSynthesizedTool, cronMatches, decodeDdgUrl, diskAgentOptions, enterWorktree, exitWorktree, expandCommand, expandEntry, expandTemplate, findGitRoot, forComponent, fullAgentOptions, getOrCreateWorktree, getWorktreeSession, globTool, grepTool, htmlToText, idfWeights, lessonCapture, loadAgents, loadCommands, loadInstructions, loadMemory, loadSkills, makeAskTool, makeGlobTool, makeGrepTool, makeScheduleTools, makeTaskBatchTool, makeTaskTool, makeWebFetchTool, makeWebSearchAnthropicTool, makeWebSearchTool, mkdirp, multiEditTool, nextCronAfter, parseCron, parseDdgHtml, raceAttempts, reflectOnRun, relevanceScore, repoIndex, repoMapTool, rollbackTool, sandboxAgentOptions, scanCommands, scanSkills, slugify, tokenize, toolCall, topByRelevance, validateToolCode, validateWorktreeSlug, webFetchTool, webSearchAnthropicTool, webSearchTool, worktreeBranchName, writeFact, writeTool };
|
package/dist/index.js
CHANGED
|
@@ -3422,6 +3422,149 @@ function resolveModelSwitch(opts) {
|
|
|
3422
3422
|
};
|
|
3423
3423
|
}
|
|
3424
3424
|
|
|
3425
|
+
// src/permissions.ts
|
|
3426
|
+
init_tools_structured();
|
|
3427
|
+
function commandMatches(glob, cmd) {
|
|
3428
|
+
const pattern = glob.split("*").map((s) => s.replace(/[.+?^${}()|[\]\\]/g, "\\$&")).join(".*");
|
|
3429
|
+
return new RegExp("^" + pattern + "$").test(cmd);
|
|
3430
|
+
}
|
|
3431
|
+
function toolMatches(rule, name) {
|
|
3432
|
+
return rule.includes("*") ? commandMatches(rule, name) : rule === name;
|
|
3433
|
+
}
|
|
3434
|
+
var PermissionOptions = class {
|
|
3435
|
+
rules = [];
|
|
3436
|
+
/** decision when no rule matches. */
|
|
3437
|
+
default = "allow";
|
|
3438
|
+
/** host channel for `ask` (confirm). If absent, `ask` is treated as `deny` (fail-closed). */
|
|
3439
|
+
host;
|
|
3440
|
+
};
|
|
3441
|
+
var PermissionPolicy = class {
|
|
3442
|
+
options;
|
|
3443
|
+
constructor(options) {
|
|
3444
|
+
this.options = { ...new PermissionOptions(), ...options };
|
|
3445
|
+
}
|
|
3446
|
+
/** Resolve the decision for a tool call (first matching rule, else default). */
|
|
3447
|
+
decide(call) {
|
|
3448
|
+
const names = call.name === "McpCall" && typeof call.args?.name === "string" ? [call.name, call.args.name] : [call.name];
|
|
3449
|
+
for (const r of this.options.rules) {
|
|
3450
|
+
if (r.tool && !names.some((n) => toolMatches(r.tool, n))) continue;
|
|
3451
|
+
if (r.pathGlob) {
|
|
3452
|
+
const path = typeof call.args?.path === "string" ? call.args.path : null;
|
|
3453
|
+
const cmd = typeof call.args?.command === "string" ? call.args.command : null;
|
|
3454
|
+
if (path != null) {
|
|
3455
|
+
if (!globToRegExp(r.pathGlob).test(path.startsWith("/") ? path : `/${path}`)) continue;
|
|
3456
|
+
} else if (cmd != null) {
|
|
3457
|
+
if (!commandMatches(r.pathGlob, cmd)) continue;
|
|
3458
|
+
} else continue;
|
|
3459
|
+
}
|
|
3460
|
+
return r.decision;
|
|
3461
|
+
}
|
|
3462
|
+
return this.options.default;
|
|
3463
|
+
}
|
|
3464
|
+
/** The policy's `deny` rules as rule strings (`Tool` / `Tool(glob)`) — for delegated runtimes that run
|
|
3465
|
+
* their OWN tools (claude-code/cursor) and never pass through {@link hooks}. */
|
|
3466
|
+
denyRules(explicitOnly = false) {
|
|
3467
|
+
return this.options.rules.filter((r) => r.decision === "deny" && (!explicitOnly || r.explicit)).map((r) => `${r.tool ?? "*"}${r.pathGlob ? `(${r.pathGlob})` : ""}`);
|
|
3468
|
+
}
|
|
3469
|
+
/** A preToolUse hook enforcing this policy (deny/ask → block; allow → proceed). */
|
|
3470
|
+
hooks() {
|
|
3471
|
+
return {
|
|
3472
|
+
preToolUse: async (call) => {
|
|
3473
|
+
const d = this.decide(call);
|
|
3474
|
+
if (d === "allow") return;
|
|
3475
|
+
if (d === "deny") return { block: true, reason: `denied by permission policy (${call.name})` };
|
|
3476
|
+
if (this.options.ask) {
|
|
3477
|
+
const r = await this.options.ask(call);
|
|
3478
|
+
const decision = r?.decision ?? "deny";
|
|
3479
|
+
const rememberTool2 = call.name === "McpCall" && typeof call.args?.name === "string" ? call.args.name : call.name;
|
|
3480
|
+
if (r?.remember) this.options.rules.unshift({ tool: rememberTool2, decision });
|
|
3481
|
+
return decision === "allow" ? void 0 : { block: true, reason: `not approved (${call.name})` };
|
|
3482
|
+
}
|
|
3483
|
+
const ok = await this.options.host?.confirm?.(`Allow ${call.name}${call.args?.path ? " on " + call.args.path : ""}?`);
|
|
3484
|
+
return ok ? void 0 : { block: true, reason: `not approved (${call.name})` };
|
|
3485
|
+
}
|
|
3486
|
+
};
|
|
3487
|
+
}
|
|
3488
|
+
};
|
|
3489
|
+
var CC_TOOL_ALIAS = { Shell: "Bash", bash: "Bash" };
|
|
3490
|
+
function claudeCodeDisallowedTools(policy) {
|
|
3491
|
+
const out = /* @__PURE__ */ new Set();
|
|
3492
|
+
for (const rule of policy?.denyRules() ?? []) {
|
|
3493
|
+
const m = /^([^(]+)(\(.*\))?$/.exec(rule);
|
|
3494
|
+
if (m[1] === "*") throw new Error("permission policy denies every tool (`*`) \u2014 claude-code cannot express that; refusing to run.");
|
|
3495
|
+
out.add((CC_TOOL_ALIAS[m[1]] ?? m[1]) + (m[2] ?? ""));
|
|
3496
|
+
}
|
|
3497
|
+
return [...out];
|
|
3498
|
+
}
|
|
3499
|
+
var DEFAULT_MUTATING = ["Write", "Edit", "MultiEdit", "deleteFile", "bash"];
|
|
3500
|
+
function planMode(opts) {
|
|
3501
|
+
const mutating = new Set(opts?.mutating ?? DEFAULT_MUTATING);
|
|
3502
|
+
let approved = false;
|
|
3503
|
+
const tool = {
|
|
3504
|
+
name: "ExitPlanMode",
|
|
3505
|
+
description: "Call when your plan is ready and you want to start making changes. Provide the `plan`. Until this is approved, edits/writes are blocked.",
|
|
3506
|
+
parameters: { type: "object", required: ["plan"], properties: { plan: { type: "string", description: "the concrete steps you will take" } } },
|
|
3507
|
+
async run({ plan }, _ctx) {
|
|
3508
|
+
if (opts?.host?.confirm) {
|
|
3509
|
+
const confirm = opts.host.confirm(`Approve this plan?
|
|
3510
|
+
|
|
3511
|
+
${String(plan ?? "")}`);
|
|
3512
|
+
const ok = await (_ctx?.parkHuman ? _ctx.parkHuman(confirm) : confirm);
|
|
3513
|
+
if (!ok) return "Plan not approved. Revise it and call ExitPlanMode again.";
|
|
3514
|
+
}
|
|
3515
|
+
approved = true;
|
|
3516
|
+
return "Plan approved \u2014 you may now make changes.";
|
|
3517
|
+
}
|
|
3518
|
+
};
|
|
3519
|
+
const hooks = {
|
|
3520
|
+
preToolUse: (call) => !approved && mutating.has(call.name) ? { block: true, reason: "plan mode: present a plan and call ExitPlanMode (approved) before editing." } : void 0
|
|
3521
|
+
};
|
|
3522
|
+
return { hooks, tool };
|
|
3523
|
+
}
|
|
3524
|
+
function composeHooks(...list) {
|
|
3525
|
+
const hooks = list.filter(Boolean);
|
|
3526
|
+
return {
|
|
3527
|
+
async preToolUse(call, meta) {
|
|
3528
|
+
for (const h of hooks) {
|
|
3529
|
+
const d = await h.preToolUse?.(call, meta);
|
|
3530
|
+
if (d?.block) return d;
|
|
3531
|
+
}
|
|
3532
|
+
},
|
|
3533
|
+
async postToolUse(call, result, meta) {
|
|
3534
|
+
for (const h of hooks) await h.postToolUse?.(call, result, meta);
|
|
3535
|
+
},
|
|
3536
|
+
onToolOutput(call, chunk, meta) {
|
|
3537
|
+
for (const h of hooks) h.onToolOutput?.(call, chunk, meta);
|
|
3538
|
+
},
|
|
3539
|
+
onStop(text) {
|
|
3540
|
+
for (const h of hooks) h.onStop?.(text);
|
|
3541
|
+
},
|
|
3542
|
+
// lifecycle: concatenate session-start context; chain prompt-submit transforms; fan out pre-compact.
|
|
3543
|
+
async onSessionStart() {
|
|
3544
|
+
let ctx = "";
|
|
3545
|
+
for (const h of hooks) {
|
|
3546
|
+
const r = await h.onSessionStart?.();
|
|
3547
|
+
if (r) ctx += (ctx ? "\n\n" : "") + r;
|
|
3548
|
+
}
|
|
3549
|
+
return ctx || void 0;
|
|
3550
|
+
},
|
|
3551
|
+
async onUserPromptSubmit(text) {
|
|
3552
|
+
let t = text;
|
|
3553
|
+
for (const h of hooks) {
|
|
3554
|
+
const r = await h.onUserPromptSubmit?.(t);
|
|
3555
|
+
if (typeof r === "string") t = r;
|
|
3556
|
+
}
|
|
3557
|
+
return t;
|
|
3558
|
+
},
|
|
3559
|
+
async onPreCompact(messages) {
|
|
3560
|
+
for (const h of hooks) await h.onPreCompact?.(messages);
|
|
3561
|
+
},
|
|
3562
|
+
async onSubagentStop(summary, info) {
|
|
3563
|
+
for (const h of hooks) await h.onSubagentStop?.(summary, info);
|
|
3564
|
+
}
|
|
3565
|
+
};
|
|
3566
|
+
}
|
|
3567
|
+
|
|
3425
3568
|
// src/subagent.ts
|
|
3426
3569
|
init_OverlayFilesystem();
|
|
3427
3570
|
|
|
@@ -3729,6 +3872,8 @@ function childOptionsFor(opts, fs, depth, maxDepth, agentType, model, root) {
|
|
|
3729
3872
|
}
|
|
3730
3873
|
const po = opts.providerOptionsFor?.(childModel);
|
|
3731
3874
|
if (po) childOpts.providerOptions = po;
|
|
3875
|
+
const deny = opts.permissions?.options.rules.filter((r) => r.decision === "deny") ?? [];
|
|
3876
|
+
if (deny.length) childOpts.permissions = new PermissionPolicy({ rules: deny, default: "allow" });
|
|
3732
3877
|
if (opts.hooks?.preToolUse) childOpts.hooks = { preToolUse: opts.hooks.preToolUse.bind(opts.hooks) };
|
|
3733
3878
|
return childOpts;
|
|
3734
3879
|
}
|
|
@@ -3948,133 +4093,6 @@ async function loadAgents(fs, dir) {
|
|
|
3948
4093
|
|
|
3949
4094
|
// src/Agent.ts
|
|
3950
4095
|
init_OverlayFilesystem();
|
|
3951
|
-
|
|
3952
|
-
// src/permissions.ts
|
|
3953
|
-
init_tools_structured();
|
|
3954
|
-
function commandMatches(glob, cmd) {
|
|
3955
|
-
const pattern = glob.split("*").map((s) => s.replace(/[.+?^${}()|[\]\\]/g, "\\$&")).join(".*");
|
|
3956
|
-
return new RegExp("^" + pattern + "$").test(cmd);
|
|
3957
|
-
}
|
|
3958
|
-
var PermissionOptions = class {
|
|
3959
|
-
rules = [];
|
|
3960
|
-
/** decision when no rule matches. */
|
|
3961
|
-
default = "allow";
|
|
3962
|
-
/** host channel for `ask` (confirm). If absent, `ask` is treated as `deny` (fail-closed). */
|
|
3963
|
-
host;
|
|
3964
|
-
};
|
|
3965
|
-
var PermissionPolicy = class {
|
|
3966
|
-
options;
|
|
3967
|
-
constructor(options) {
|
|
3968
|
-
this.options = { ...new PermissionOptions(), ...options };
|
|
3969
|
-
}
|
|
3970
|
-
/** Resolve the decision for a tool call (first matching rule, else default). */
|
|
3971
|
-
decide(call) {
|
|
3972
|
-
const names = call.name === "McpCall" && typeof call.args?.name === "string" ? [call.name, call.args.name] : [call.name];
|
|
3973
|
-
for (const r of this.options.rules) {
|
|
3974
|
-
if (r.tool && !names.includes(r.tool)) continue;
|
|
3975
|
-
if (r.pathGlob) {
|
|
3976
|
-
const path = typeof call.args?.path === "string" ? call.args.path : null;
|
|
3977
|
-
const cmd = typeof call.args?.command === "string" ? call.args.command : null;
|
|
3978
|
-
if (path != null) {
|
|
3979
|
-
if (!globToRegExp(r.pathGlob).test(path.startsWith("/") ? path : `/${path}`)) continue;
|
|
3980
|
-
} else if (cmd != null) {
|
|
3981
|
-
if (!commandMatches(r.pathGlob, cmd)) continue;
|
|
3982
|
-
} else continue;
|
|
3983
|
-
}
|
|
3984
|
-
return r.decision;
|
|
3985
|
-
}
|
|
3986
|
-
return this.options.default;
|
|
3987
|
-
}
|
|
3988
|
-
/** A preToolUse hook enforcing this policy (deny/ask → block; allow → proceed). */
|
|
3989
|
-
hooks() {
|
|
3990
|
-
return {
|
|
3991
|
-
preToolUse: async (call) => {
|
|
3992
|
-
const d = this.decide(call);
|
|
3993
|
-
if (d === "allow") return;
|
|
3994
|
-
if (d === "deny") return { block: true, reason: `denied by permission policy (${call.name})` };
|
|
3995
|
-
if (this.options.ask) {
|
|
3996
|
-
const r = await this.options.ask(call);
|
|
3997
|
-
const decision = r?.decision ?? "deny";
|
|
3998
|
-
const rememberTool2 = call.name === "McpCall" && typeof call.args?.name === "string" ? call.args.name : call.name;
|
|
3999
|
-
if (r?.remember) this.options.rules.unshift({ tool: rememberTool2, decision });
|
|
4000
|
-
return decision === "allow" ? void 0 : { block: true, reason: `not approved (${call.name})` };
|
|
4001
|
-
}
|
|
4002
|
-
const ok = await this.options.host?.confirm?.(`Allow ${call.name}${call.args?.path ? " on " + call.args.path : ""}?`);
|
|
4003
|
-
return ok ? void 0 : { block: true, reason: `not approved (${call.name})` };
|
|
4004
|
-
}
|
|
4005
|
-
};
|
|
4006
|
-
}
|
|
4007
|
-
};
|
|
4008
|
-
var DEFAULT_MUTATING = ["Write", "Edit", "MultiEdit", "deleteFile", "bash"];
|
|
4009
|
-
function planMode(opts) {
|
|
4010
|
-
const mutating = new Set(opts?.mutating ?? DEFAULT_MUTATING);
|
|
4011
|
-
let approved = false;
|
|
4012
|
-
const tool = {
|
|
4013
|
-
name: "ExitPlanMode",
|
|
4014
|
-
description: "Call when your plan is ready and you want to start making changes. Provide the `plan`. Until this is approved, edits/writes are blocked.",
|
|
4015
|
-
parameters: { type: "object", required: ["plan"], properties: { plan: { type: "string", description: "the concrete steps you will take" } } },
|
|
4016
|
-
async run({ plan }, _ctx) {
|
|
4017
|
-
if (opts?.host?.confirm) {
|
|
4018
|
-
const confirm = opts.host.confirm(`Approve this plan?
|
|
4019
|
-
|
|
4020
|
-
${String(plan ?? "")}`);
|
|
4021
|
-
const ok = await (_ctx?.parkHuman ? _ctx.parkHuman(confirm) : confirm);
|
|
4022
|
-
if (!ok) return "Plan not approved. Revise it and call ExitPlanMode again.";
|
|
4023
|
-
}
|
|
4024
|
-
approved = true;
|
|
4025
|
-
return "Plan approved \u2014 you may now make changes.";
|
|
4026
|
-
}
|
|
4027
|
-
};
|
|
4028
|
-
const hooks = {
|
|
4029
|
-
preToolUse: (call) => !approved && mutating.has(call.name) ? { block: true, reason: "plan mode: present a plan and call ExitPlanMode (approved) before editing." } : void 0
|
|
4030
|
-
};
|
|
4031
|
-
return { hooks, tool };
|
|
4032
|
-
}
|
|
4033
|
-
function composeHooks(...list) {
|
|
4034
|
-
const hooks = list.filter(Boolean);
|
|
4035
|
-
return {
|
|
4036
|
-
async preToolUse(call, meta) {
|
|
4037
|
-
for (const h of hooks) {
|
|
4038
|
-
const d = await h.preToolUse?.(call, meta);
|
|
4039
|
-
if (d?.block) return d;
|
|
4040
|
-
}
|
|
4041
|
-
},
|
|
4042
|
-
async postToolUse(call, result, meta) {
|
|
4043
|
-
for (const h of hooks) await h.postToolUse?.(call, result, meta);
|
|
4044
|
-
},
|
|
4045
|
-
onToolOutput(call, chunk, meta) {
|
|
4046
|
-
for (const h of hooks) h.onToolOutput?.(call, chunk, meta);
|
|
4047
|
-
},
|
|
4048
|
-
onStop(text) {
|
|
4049
|
-
for (const h of hooks) h.onStop?.(text);
|
|
4050
|
-
},
|
|
4051
|
-
// lifecycle: concatenate session-start context; chain prompt-submit transforms; fan out pre-compact.
|
|
4052
|
-
async onSessionStart() {
|
|
4053
|
-
let ctx = "";
|
|
4054
|
-
for (const h of hooks) {
|
|
4055
|
-
const r = await h.onSessionStart?.();
|
|
4056
|
-
if (r) ctx += (ctx ? "\n\n" : "") + r;
|
|
4057
|
-
}
|
|
4058
|
-
return ctx || void 0;
|
|
4059
|
-
},
|
|
4060
|
-
async onUserPromptSubmit(text) {
|
|
4061
|
-
let t = text;
|
|
4062
|
-
for (const h of hooks) {
|
|
4063
|
-
const r = await h.onUserPromptSubmit?.(t);
|
|
4064
|
-
if (typeof r === "string") t = r;
|
|
4065
|
-
}
|
|
4066
|
-
return t;
|
|
4067
|
-
},
|
|
4068
|
-
async onPreCompact(messages) {
|
|
4069
|
-
for (const h of hooks) await h.onPreCompact?.(messages);
|
|
4070
|
-
},
|
|
4071
|
-
async onSubagentStop(summary, info) {
|
|
4072
|
-
for (const h of hooks) await h.onSubagentStop?.(summary, info);
|
|
4073
|
-
}
|
|
4074
|
-
};
|
|
4075
|
-
}
|
|
4076
|
-
|
|
4077
|
-
// src/Agent.ts
|
|
4078
4096
|
init_logging();
|
|
4079
4097
|
|
|
4080
4098
|
// src/lint.ts
|
|
@@ -4594,6 +4612,8 @@ var Agent = class _Agent {
|
|
|
4594
4612
|
agents,
|
|
4595
4613
|
hooks: o.hooks,
|
|
4596
4614
|
traceDir: o.traceDir,
|
|
4615
|
+
permissions: o.permissions,
|
|
4616
|
+
// a child obeys the parent's allow/deny rules (else Task is a one-call bypass)
|
|
4597
4617
|
tools: [...o.tools, ...this.injectedTools],
|
|
4598
4618
|
systemPrompt: o.systemPrompt,
|
|
4599
4619
|
providerOptionsFor: o.providerOptionsFor ?? ((m) => modelProvider(m) === modelProvider(o.model) ? o.providerOptions : void 0)
|
|
@@ -4766,6 +4786,14 @@ var Agent = class _Agent {
|
|
|
4766
4786
|
}
|
|
4767
4787
|
} : void 0;
|
|
4768
4788
|
const claudeSteerPo = o.model.startsWith("claude-code/") ? { steer: () => this.drainPendingSteers() } : void 0;
|
|
4789
|
+
const denyTools = o.model.startsWith("claude-code/") ? claudeCodeDisallowedTools(o.permissions) : [];
|
|
4790
|
+
if (denyTools.length) {
|
|
4791
|
+
const prior = o.providerOptions?.disallowedTools ?? [];
|
|
4792
|
+
claudeSteerPo.disallowedTools = [.../* @__PURE__ */ new Set([...prior, ...denyTools])];
|
|
4793
|
+
}
|
|
4794
|
+
const cursorDeny = o.model.startsWith("cursor/") ? o.permissions?.denyRules(true) ?? [] : [];
|
|
4795
|
+
if (cursorDeny.length)
|
|
4796
|
+
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.`);
|
|
4769
4797
|
const reasonOpts = {
|
|
4770
4798
|
...frag,
|
|
4771
4799
|
...o.promptCache ? { promptCache: true } : {},
|
|
@@ -4882,6 +4910,9 @@ var Agent = class _Agent {
|
|
|
4882
4910
|
this.transcript.push({
|
|
4883
4911
|
role: "assistant",
|
|
4884
4912
|
content: res.content ?? "",
|
|
4913
|
+
// Record the model the adapter actually ran: aliases (`claude-code/opus`) resolve to a concrete
|
|
4914
|
+
// id (e.g. `claude-opus-5-5`); fall back to the requested model if the adapter didn't report one.
|
|
4915
|
+
model: res.model ?? o.model,
|
|
4885
4916
|
...toolCalls.length ? { tool_calls: toolCalls } : {},
|
|
4886
4917
|
...res.reasoningContent && passesBackReasoning(o.model) ? { reasoning_content: res.reasoningContent } : {}
|
|
4887
4918
|
});
|
|
@@ -5044,7 +5075,9 @@ var Agent = class _Agent {
|
|
|
5044
5075
|
let sawTool = false;
|
|
5045
5076
|
let trailing = "";
|
|
5046
5077
|
let reasoning = "";
|
|
5078
|
+
let resolvedModel;
|
|
5047
5079
|
for await (const chunk of stream) {
|
|
5080
|
+
if (chunk.model) resolvedModel = chunk.model;
|
|
5048
5081
|
poke?.();
|
|
5049
5082
|
if (this.options.signal?.aborted) break;
|
|
5050
5083
|
if (chunk.reasoningContent) {
|
|
@@ -5093,7 +5126,7 @@ var Agent = class _Agent {
|
|
|
5093
5126
|
}
|
|
5094
5127
|
const delegatedTools = delegatedOrder.map((k) => delegated.get(k));
|
|
5095
5128
|
const endedWithoutClosing = sawTool && (!trailing.trim() || endsOnAnnouncedAction(trailing));
|
|
5096
|
-
return { content, ...reasoning ? { reasoningContent: reasoning } : {}, ...finishReason ? { finishReason } : {}, ...toolCalls ? { toolCalls } : {}, ...usage ? { usage } : {}, ...delegatedTools.length ? { delegatedTools } : {}, ...endedWithoutClosing ? { endedWithoutClosing: true } : {} };
|
|
5129
|
+
return { content, ...resolvedModel ? { model: resolvedModel } : {}, ...reasoning ? { reasoningContent: reasoning } : {}, ...finishReason ? { finishReason } : {}, ...toolCalls ? { toolCalls } : {}, ...usage ? { usage } : {}, ...delegatedTools.length ? { delegatedTools } : {}, ...endedWithoutClosing ? { endedWithoutClosing: true } : {} };
|
|
5097
5130
|
}
|
|
5098
5131
|
/**
|
|
5099
5132
|
* FABRICATED TOOL USE — the failure no call-reactive layer can see, because there IS no call.
|
|
@@ -11008,6 +11041,7 @@ export {
|
|
|
11008
11041
|
buildMcpCatalog,
|
|
11009
11042
|
checkpointTool,
|
|
11010
11043
|
checkpointTools,
|
|
11044
|
+
claudeCodeDisallowedTools,
|
|
11011
11045
|
cleanupWorktree,
|
|
11012
11046
|
clearImageRefs,
|
|
11013
11047
|
compileSynthesizedTool,
|