auto-mode 0.10.0 → 0.12.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/classify-edit-D8GC6b91.js +17848 -0
- package/dist/cli.js +320 -10
- package/dist/get-edit-fields-BtAvHIsq.js +20 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/{render-verdict-1xtCI2is.js → render-verdict-FhSKxlO9.js} +804 -602
- package/mods/auto-mode/hooks/register.claude-check.ts +97 -0
- package/mods/auto-mode/hooks/register.ts +36 -2
- package/mods/auto-mode/hooks/types.ts +13 -2
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import { appendFile, mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
2
|
+
import { D as string, E as strictObject, T as number, _ as splitCommandWords, a as resolveSessionScopePath, b as DEFAULT_SCOPE_SOURCES, c as loadCheckoutRemotes, g as splitShellCommand, h as toRepositorySlug, i as resolveStateDir, l as findCheckout, m as loadPolicy, n as parseActionRequest, o as loadSessionScope, p as loadRepositoryContext, r as classifyAction, s as EMPTY_SESSION_SCOPE, t as renderVerdict, x as loadConfig, y as DEFAULT_DENIAL_BUDGET } from "./render-verdict-FhSKxlO9.js";
|
|
3
|
+
import { appendFile, mkdir, open, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
4
|
+
import { dirname, isAbsolute, join, normalize } from "node:path";
|
|
4
5
|
import { homedir } from "node:os";
|
|
5
|
-
import {
|
|
6
|
+
import { spawn } from "node:child_process";
|
|
6
7
|
import { createHash, randomUUID } from "node:crypto";
|
|
7
8
|
import { text } from "node:stream/consumers";
|
|
8
9
|
import { parseArgs } from "node:util";
|
|
10
|
+
import { setTimeout } from "node:timers/promises";
|
|
9
11
|
//#region src/budget/build-retry-key.ts
|
|
10
12
|
const DESCRIPTIVE_FIELDS = { Bash: [
|
|
11
13
|
"description",
|
|
@@ -117,13 +119,6 @@ function formatDenialsLeft(left) {
|
|
|
117
119
|
return "This is the last denial before auto-mode asks the user. Stop now, without finishing the rest of the task, and tell the user what consent you need to continue.";
|
|
118
120
|
}
|
|
119
121
|
//#endregion
|
|
120
|
-
//#region src/state/resolve-state-dir.ts
|
|
121
|
-
function resolveStateDir() {
|
|
122
|
-
const stateHome = process.env["XDG_STATE_HOME"];
|
|
123
|
-
const base = stateHome === void 0 || stateHome === "" ? join(homedir(), ".local", "state") : stateHome;
|
|
124
|
-
return join(base, "auto-mode");
|
|
125
|
-
}
|
|
126
|
-
//#endregion
|
|
127
122
|
//#region src/budget/resolve-denial-state-path.ts
|
|
128
123
|
function resolveDenialStatePath(request) {
|
|
129
124
|
const agentID = request.decisionContext?.agentID ?? "";
|
|
@@ -185,12 +180,303 @@ function toHash(value) {
|
|
|
185
180
|
return createHash("sha256").update(value).digest("hex").slice(0, 16);
|
|
186
181
|
}
|
|
187
182
|
//#endregion
|
|
183
|
+
//#region src/request/parse-scope-record-request.ts
|
|
184
|
+
const recordSchema = strictObject({
|
|
185
|
+
sessionID: string().min(1),
|
|
186
|
+
cwd: string().min(1),
|
|
187
|
+
startedAt: number().int().positive(),
|
|
188
|
+
command: string().min(1),
|
|
189
|
+
resultText: string()
|
|
190
|
+
});
|
|
191
|
+
function parseScopeRecordRequest(body) {
|
|
192
|
+
const parsed = recordSchema.safeParse(body);
|
|
193
|
+
return parsed.success ? parsed.data : null;
|
|
194
|
+
}
|
|
195
|
+
//#endregion
|
|
196
|
+
//#region src/scope/read-pull-request.ts
|
|
197
|
+
const LOOKUP_TIMEOUT_MS = 5e3;
|
|
198
|
+
function readPullRequest(repository, number) {
|
|
199
|
+
const args = [
|
|
200
|
+
"pr",
|
|
201
|
+
"view",
|
|
202
|
+
String(number),
|
|
203
|
+
"--repo",
|
|
204
|
+
repository,
|
|
205
|
+
"--json",
|
|
206
|
+
"headRefName,createdAt"
|
|
207
|
+
];
|
|
208
|
+
return new Promise((resolve) => {
|
|
209
|
+
const child = spawn("gh", [
|
|
210
|
+
...args,
|
|
211
|
+
"--jq",
|
|
212
|
+
"[.headRefName, .createdAt] | @tsv"
|
|
213
|
+
], {
|
|
214
|
+
stdio: [
|
|
215
|
+
"ignore",
|
|
216
|
+
"pipe",
|
|
217
|
+
"ignore"
|
|
218
|
+
],
|
|
219
|
+
timeout: LOOKUP_TIMEOUT_MS
|
|
220
|
+
});
|
|
221
|
+
let output = "";
|
|
222
|
+
child.stdout.setEncoding("utf8");
|
|
223
|
+
child.stdout.on("data", (chunk) => {
|
|
224
|
+
output += chunk;
|
|
225
|
+
});
|
|
226
|
+
child.on("error", () => {
|
|
227
|
+
resolve(null);
|
|
228
|
+
});
|
|
229
|
+
child.on("close", (code) => {
|
|
230
|
+
const [head = "", created = ""] = output.trim().split(" ");
|
|
231
|
+
const createdAt = Date.parse(created);
|
|
232
|
+
resolve(code === 0 && head !== "" && !Number.isNaN(createdAt) ? {
|
|
233
|
+
head,
|
|
234
|
+
createdAt
|
|
235
|
+
} : null);
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
//#endregion
|
|
240
|
+
//#region src/scope/collect-pull-request-addresses.ts
|
|
241
|
+
function collectPullRequestAddresses(text) {
|
|
242
|
+
const addresses = /* @__PURE__ */ new Map();
|
|
243
|
+
for (const match of text.matchAll(PULL_REQUEST_URL)) {
|
|
244
|
+
const repository = toRepositorySlug(`https://${match.groups?.["repository"] ?? ""}`);
|
|
245
|
+
const number = Number(match.groups?.["number"]);
|
|
246
|
+
if (repository !== null) addresses.set(`${repository}#${String(number)}`, {
|
|
247
|
+
repository,
|
|
248
|
+
number
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
return [...addresses.values()];
|
|
252
|
+
}
|
|
253
|
+
const PULL_REQUEST_URL = /https:\/\/(?<repository>[^/\s]+\/[^/\s]+\/[^/\s]+)\/pull\/(?<number>[1-9]\d*)\b/gu;
|
|
254
|
+
//#endregion
|
|
255
|
+
//#region src/scope/collect-scope-events.ts
|
|
256
|
+
function collectScopeEvents(command, cwd, home) {
|
|
257
|
+
const events = [];
|
|
258
|
+
const hasPipe = /(?<!\|)\|(?!\|)/u.test(command);
|
|
259
|
+
let directory = cwd;
|
|
260
|
+
for (const segment of splitShellCommand(command).segments) {
|
|
261
|
+
const [name, ...args] = splitCommandWords(segment.text);
|
|
262
|
+
if (name === "cd") directory = hasPipe ? null : resolvePath(directory, args[0] ?? home, home);
|
|
263
|
+
else if (name === "git" && directory !== null) events.push(...collectGitEvents(args, directory, home));
|
|
264
|
+
else if (name === "gh" && directory !== null && args[0] === "pr" && args[1] === "create") events.push({
|
|
265
|
+
kind: "pull-request",
|
|
266
|
+
directory,
|
|
267
|
+
head: findOptionValue(args, ["--head", "-H"])
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
return events;
|
|
271
|
+
}
|
|
272
|
+
const BRANCH_CREATE_OPTIONS = /* @__PURE__ */ new Set([
|
|
273
|
+
"-b",
|
|
274
|
+
"-B",
|
|
275
|
+
"-c",
|
|
276
|
+
"-C",
|
|
277
|
+
"--create",
|
|
278
|
+
"--force-create"
|
|
279
|
+
]);
|
|
280
|
+
const BRANCH_OTHER_OPTIONS = /^-(?:d|D|m|M|c|C|l|a|r|v|vv|u)$|^--(?:delete|move|copy|list|all|remotes|verbose|show-current|contains|no-contains|merged|no-merged|points-at|format|sort|set-upstream-to|unset-upstream|edit-description)/u;
|
|
281
|
+
function collectGitEvents(args, cwd, home) {
|
|
282
|
+
let directory = cwd;
|
|
283
|
+
let index = 0;
|
|
284
|
+
while (index < args.length && args[index]?.startsWith("-") === true) {
|
|
285
|
+
if (args[index] === "-C") directory = resolvePath(directory, args[index + 1] ?? "", home);
|
|
286
|
+
index += args[index] === "-C" || args[index] === "-c" ? 2 : 1;
|
|
287
|
+
}
|
|
288
|
+
const subcommand = args[index];
|
|
289
|
+
const rest = args.slice(index + 1);
|
|
290
|
+
if (directory === null) return [];
|
|
291
|
+
if (subcommand === "worktree" && rest[0] === "add") {
|
|
292
|
+
const path = findWorktreePath(rest.slice(1));
|
|
293
|
+
const resolved = path === null ? null : resolvePath(directory, path, home);
|
|
294
|
+
return resolved === null ? [] : [{
|
|
295
|
+
kind: "worktree",
|
|
296
|
+
path: resolved
|
|
297
|
+
}];
|
|
298
|
+
}
|
|
299
|
+
if (subcommand === "checkout" || subcommand === "switch") {
|
|
300
|
+
const name = findOptionValue(rest, [...BRANCH_CREATE_OPTIONS]);
|
|
301
|
+
return name === null ? [] : [{
|
|
302
|
+
kind: "branch",
|
|
303
|
+
name,
|
|
304
|
+
directory
|
|
305
|
+
}];
|
|
306
|
+
}
|
|
307
|
+
if (subcommand === "branch" && !rest.some((word) => BRANCH_OTHER_OPTIONS.test(word))) {
|
|
308
|
+
const name = rest.find((word) => !word.startsWith("-"));
|
|
309
|
+
return name === void 0 || isUnresolved(name) ? [] : [{
|
|
310
|
+
kind: "branch",
|
|
311
|
+
name,
|
|
312
|
+
directory
|
|
313
|
+
}];
|
|
314
|
+
}
|
|
315
|
+
return [];
|
|
316
|
+
}
|
|
317
|
+
const WORKTREE_VALUE_OPTIONS = /* @__PURE__ */ new Set([
|
|
318
|
+
"-b",
|
|
319
|
+
"-B",
|
|
320
|
+
"--reason"
|
|
321
|
+
]);
|
|
322
|
+
function findWorktreePath(args) {
|
|
323
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
324
|
+
const word = args[index] ?? "";
|
|
325
|
+
if (WORKTREE_VALUE_OPTIONS.has(word)) index += 1;
|
|
326
|
+
else if (!word.startsWith("-")) return word;
|
|
327
|
+
}
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
330
|
+
function findOptionValue(args, options) {
|
|
331
|
+
const index = args.findIndex((word) => options.includes(word));
|
|
332
|
+
const value = index === -1 ? void 0 : args[index + 1];
|
|
333
|
+
return value === void 0 || isUnresolved(value) ? null : value;
|
|
334
|
+
}
|
|
335
|
+
function isUnresolved(word) {
|
|
336
|
+
return /[$`]/u.test(word);
|
|
337
|
+
}
|
|
338
|
+
function resolvePath(directory, path, home) {
|
|
339
|
+
const expanded = path.replace(/^(?:~|\$HOME|\$\{HOME\})(?=\/|$)/u, home);
|
|
340
|
+
if (isUnresolved(expanded) || expanded.startsWith("~") || expanded === "") return null;
|
|
341
|
+
if (!isAbsolute(expanded) && directory === null) return null;
|
|
342
|
+
const absolute = isAbsolute(expanded) || directory === null ? expanded : join(directory, expanded);
|
|
343
|
+
return normalize(absolute).replace(/(?<=.)\/$/u, "");
|
|
344
|
+
}
|
|
345
|
+
//#endregion
|
|
346
|
+
//#region src/scope/merge-session-scope.ts
|
|
347
|
+
function mergeSessionScope(all) {
|
|
348
|
+
const branches = /* @__PURE__ */ new Map();
|
|
349
|
+
const pullRequests = /* @__PURE__ */ new Map();
|
|
350
|
+
for (const branch of all.flatMap((scope) => scope.branches)) branches.set(`${branch.commonDir}\0${branch.name}`, branch);
|
|
351
|
+
for (const pull of all.flatMap((scope) => scope.pullRequests)) pullRequests.set(`${pull.repository}#${String(pull.number)}`, pull);
|
|
352
|
+
return {
|
|
353
|
+
worktrees: [...new Set(all.flatMap((scope) => scope.worktrees))],
|
|
354
|
+
branches: [...branches.values()],
|
|
355
|
+
pullRequests: [...pullRequests.values()]
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
//#endregion
|
|
359
|
+
//#region src/scope/read-branch-created-at.ts
|
|
360
|
+
async function readBranchCreatedAt(commonDir, branch) {
|
|
361
|
+
if (!/^[\w./-]+$/u.test(branch) || branch.split("/").includes("..")) return null;
|
|
362
|
+
const [first = ""] = (await readFile(join(commonDir, "logs", "refs", "heads", branch), "utf8").catch(() => "")).split("\n");
|
|
363
|
+
const seconds = /^0+ [\da-f]+ .* (?<time>\d+) [+-]\d{4}\t/u.exec(first)?.groups?.["time"];
|
|
364
|
+
return seconds === void 0 ? null : Number(seconds) * 1e3;
|
|
365
|
+
}
|
|
366
|
+
//#endregion
|
|
367
|
+
//#region src/scope/write-session-scope.ts
|
|
368
|
+
async function writeSessionScope(path, added) {
|
|
369
|
+
await mkdir(dirname(path), {
|
|
370
|
+
recursive: true,
|
|
371
|
+
mode: 448
|
|
372
|
+
});
|
|
373
|
+
const lock = `${path}.lock`;
|
|
374
|
+
await claimLock(lock);
|
|
375
|
+
try {
|
|
376
|
+
const merged = mergeSessionScope([await loadSessionScope(path), added]);
|
|
377
|
+
const staged = `${path}.${randomUUID()}.tmp`;
|
|
378
|
+
await writeFile(staged, `${JSON.stringify(merged)}\n`, { mode: 384 });
|
|
379
|
+
await rename(staged, path);
|
|
380
|
+
} finally {
|
|
381
|
+
await rm(lock, { force: true });
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
const STALE_LOCK_MS = 1e4;
|
|
385
|
+
const LOCK_WAIT_MS = 3e3;
|
|
386
|
+
const LOCK_POLL_MS = 10;
|
|
387
|
+
async function claimLock(lock) {
|
|
388
|
+
const deadline = Date.now() + LOCK_WAIT_MS;
|
|
389
|
+
for (;;) {
|
|
390
|
+
try {
|
|
391
|
+
await (await open(lock, "wx", 384)).close();
|
|
392
|
+
return;
|
|
393
|
+
} catch (error) {
|
|
394
|
+
if (!(error instanceof Error && "code" in error && error.code === "EEXIST")) throw error;
|
|
395
|
+
}
|
|
396
|
+
const held = await stat(lock).catch(() => null);
|
|
397
|
+
if (held !== null && Date.now() - held.mtimeMs > STALE_LOCK_MS) await rm(lock, { force: true });
|
|
398
|
+
else if (Date.now() > deadline) throw new Error("session scope lock unavailable");
|
|
399
|
+
else await setTimeout(LOCK_POLL_MS);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
//#endregion
|
|
403
|
+
//#region src/scope/update-session-scope.ts
|
|
404
|
+
const MAX_CALL_AGE_MS = 9e5;
|
|
405
|
+
async function updateSessionScope(request, options) {
|
|
406
|
+
const age = options.now - request.startedAt;
|
|
407
|
+
if (age < -6e4 || age > MAX_CALL_AGE_MS) return EMPTY_SESSION_SCOPE;
|
|
408
|
+
const events = collectScopeEvents(request.command, request.cwd, options.home);
|
|
409
|
+
const scope = mergeSessionScope(await Promise.all(events.map((event) => tryVerifyScopeEvent(event, request, options))));
|
|
410
|
+
if (scope.worktrees.length + scope.branches.length + scope.pullRequests.length > 0) await writeSessionScope(resolveSessionScopePath(options.stateDir, request.sessionID), scope);
|
|
411
|
+
return scope;
|
|
412
|
+
}
|
|
413
|
+
async function tryVerifyScopeEvent(event, request, options) {
|
|
414
|
+
try {
|
|
415
|
+
return await verifyScopeEvent(event, request, options);
|
|
416
|
+
} catch {
|
|
417
|
+
return EMPTY_SESSION_SCOPE;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
const FORGE_CLOCK_SKEW_MS = 6e4;
|
|
421
|
+
const FILE_CLOCK_SLACK_MS = 50;
|
|
422
|
+
async function verifyScopeEvent(event, request, options) {
|
|
423
|
+
if (event.kind === "worktree") {
|
|
424
|
+
const link = await stat(join(event.path, ".git"));
|
|
425
|
+
const checkout = await findCheckout(event.path);
|
|
426
|
+
if (!link.isFile() || link.mtimeMs < request.startedAt - FILE_CLOCK_SLACK_MS || checkout?.worktree !== event.path) return EMPTY_SESSION_SCOPE;
|
|
427
|
+
const branch = (await loadRepositoryContext(event.path))?.branch ?? null;
|
|
428
|
+
if (branch === null) return {
|
|
429
|
+
...EMPTY_SESSION_SCOPE,
|
|
430
|
+
worktrees: [event.path]
|
|
431
|
+
};
|
|
432
|
+
const isNew = await isBranchCreatedSince(checkout.commonDir, branch, request.startedAt);
|
|
433
|
+
return {
|
|
434
|
+
...EMPTY_SESSION_SCOPE,
|
|
435
|
+
worktrees: [event.path],
|
|
436
|
+
branches: isNew ? [{
|
|
437
|
+
name: branch,
|
|
438
|
+
commonDir: checkout.commonDir
|
|
439
|
+
}] : []
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
const checkout = await findCheckout(event.directory);
|
|
443
|
+
if (checkout === null) return EMPTY_SESSION_SCOPE;
|
|
444
|
+
if (event.kind === "branch") return await isBranchCreatedSince(checkout.commonDir, event.name, request.startedAt) ? {
|
|
445
|
+
...EMPTY_SESSION_SCOPE,
|
|
446
|
+
branches: [{
|
|
447
|
+
name: event.name,
|
|
448
|
+
commonDir: checkout.commonDir
|
|
449
|
+
}]
|
|
450
|
+
} : EMPTY_SESSION_SCOPE;
|
|
451
|
+
const remotes = await loadCheckoutRemotes(checkout.commonDir);
|
|
452
|
+
const repositories = new Set(remotes.map((remote) => toRepositorySlug(remote.url)));
|
|
453
|
+
const addresses = collectPullRequestAddresses(request.resultText).filter((address) => repositories.has(address.repository));
|
|
454
|
+
const pulls = await Promise.all(addresses.map(async (address) => {
|
|
455
|
+
const pull = await options.readPullRequest(address.repository, address.number);
|
|
456
|
+
return pull !== null && pull.createdAt >= request.startedAt - FORGE_CLOCK_SKEW_MS ? [{
|
|
457
|
+
...address,
|
|
458
|
+
head: pull.head
|
|
459
|
+
}] : [];
|
|
460
|
+
}));
|
|
461
|
+
return {
|
|
462
|
+
...EMPTY_SESSION_SCOPE,
|
|
463
|
+
pullRequests: pulls.flat()
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
async function isBranchCreatedSince(commonDir, branch, since) {
|
|
467
|
+
const createdAt = await readBranchCreatedAt(commonDir, branch);
|
|
468
|
+
if (createdAt === null || createdAt < Math.floor(since / 1e3) * 1e3) return false;
|
|
469
|
+
const ref = await stat(join(commonDir, "refs", "heads", branch)).catch(() => null);
|
|
470
|
+
return ref !== null && ref.mtimeMs >= since - FILE_CLOCK_SLACK_MS;
|
|
471
|
+
}
|
|
472
|
+
//#endregion
|
|
188
473
|
//#region src/cli.ts
|
|
189
474
|
const USAGE = `auto-mode — a permission classifier for the auto-mode Claude Code mod
|
|
190
475
|
|
|
191
476
|
Usage:
|
|
192
477
|
auto-mode run Read an action request on stdin, write a verdict on stdout
|
|
193
478
|
auto-mode print-prompt Print the system prompt the classifier receives
|
|
479
|
+
auto-mode record Read a finished Bash call on stdin, add what it created to the session's scope
|
|
194
480
|
|
|
195
481
|
Options:
|
|
196
482
|
--classifier <path> Use this framework file instead of the shipped one
|
|
@@ -294,6 +580,29 @@ async function run(explain, localOnly, jevOnly, deadline) {
|
|
|
294
580
|
process.off("SIGINT", stopEvaluation);
|
|
295
581
|
}
|
|
296
582
|
}
|
|
583
|
+
async function runRecord() {
|
|
584
|
+
const raw = await readStdin();
|
|
585
|
+
let body;
|
|
586
|
+
try {
|
|
587
|
+
body = JSON.parse(raw);
|
|
588
|
+
} catch {
|
|
589
|
+
return 0;
|
|
590
|
+
}
|
|
591
|
+
const request = parseScopeRecordRequest(body);
|
|
592
|
+
if (request === null) return 0;
|
|
593
|
+
try {
|
|
594
|
+
const config = await loadConfig();
|
|
595
|
+
if (Object.values(config.scopeSources ?? DEFAULT_SCOPE_SOURCES).some((source) => source.kind === "session")) await updateSessionScope(request, {
|
|
596
|
+
now: Date.now(),
|
|
597
|
+
stateDir: resolveStateDir(),
|
|
598
|
+
home: homedir(),
|
|
599
|
+
readPullRequest
|
|
600
|
+
});
|
|
601
|
+
} catch {
|
|
602
|
+
process.stderr.write("auto-mode: session scope unavailable\n");
|
|
603
|
+
}
|
|
604
|
+
return 0;
|
|
605
|
+
}
|
|
297
606
|
async function tryWriteDenialState(path, state) {
|
|
298
607
|
try {
|
|
299
608
|
await writeDenialState(path, state);
|
|
@@ -339,6 +648,7 @@ async function main(argv) {
|
|
|
339
648
|
process.stderr.write("auto-mode: configuration unreadable; no verdict\n");
|
|
340
649
|
return 0;
|
|
341
650
|
}
|
|
651
|
+
if (command === "record") return runRecord();
|
|
342
652
|
if (command === "print-prompt") {
|
|
343
653
|
const config = await loadConfig();
|
|
344
654
|
printWarnings(config.warnings);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/bypass/get-edit-fields.ts
|
|
2
|
+
const EDIT_FIELDS = {
|
|
3
|
+
Edit: {
|
|
4
|
+
path: "file_path",
|
|
5
|
+
content: "new_string"
|
|
6
|
+
},
|
|
7
|
+
Write: {
|
|
8
|
+
path: "file_path",
|
|
9
|
+
content: "content"
|
|
10
|
+
},
|
|
11
|
+
NotebookEdit: {
|
|
12
|
+
path: "notebook_path",
|
|
13
|
+
content: "new_source"
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
function getEditFields(toolName) {
|
|
17
|
+
return EDIT_FIELDS[toolName] ?? null;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { getEditFields as t };
|
package/dist/index.d.ts
CHANGED
|
@@ -115,7 +115,7 @@ interface DecisionDiagnostics {
|
|
|
115
115
|
}
|
|
116
116
|
//#endregion
|
|
117
117
|
//#region src/classify-action.d.ts
|
|
118
|
-
type DecidingStage = 'local' | 'containment' | 'jev' | 'messages' | 'retry';
|
|
118
|
+
type DecidingStage = 'local' | 'containment' | 'bypass' | 'jev' | 'messages' | 'retry';
|
|
119
119
|
interface ActionOutcome {
|
|
120
120
|
readonly verdict: Verdict | null;
|
|
121
121
|
readonly decidingStage: DecidingStage;
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { C as resolveConfigPath, S as resolveApiKey, d as classifyWithModel, f as parseModelVerdict, m as loadPolicy, n as parseActionRequest, r as classifyAction, t as renderVerdict, u as classifyLocally, v as DEFAULT_CONFIG, w as PRESETS, x as loadConfig } from "./render-verdict-FhSKxlO9.js";
|
|
2
2
|
export { DEFAULT_CONFIG, PRESETS, classifyAction, classifyLocally, classifyWithModel, loadConfig, loadPolicy, parseActionRequest, parseModelVerdict, renderVerdict, resolveApiKey, resolveConfigPath };
|