kimiflare 0.9.2 → 0.10.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/index.js +214 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -489,21 +489,209 @@ function nextMode(m) {
|
|
|
489
489
|
function isBlockedInPlanMode(toolName) {
|
|
490
490
|
return MUTATING_TOOLS.has(toolName);
|
|
491
491
|
}
|
|
492
|
+
function tokenizeCommand(command) {
|
|
493
|
+
const tokens = [];
|
|
494
|
+
let current = "";
|
|
495
|
+
let inQuote = null;
|
|
496
|
+
for (const ch of command) {
|
|
497
|
+
if (inQuote) {
|
|
498
|
+
if (ch === inQuote) {
|
|
499
|
+
inQuote = null;
|
|
500
|
+
} else {
|
|
501
|
+
current += ch;
|
|
502
|
+
}
|
|
503
|
+
} else if (ch === '"' || ch === "'") {
|
|
504
|
+
inQuote = ch;
|
|
505
|
+
} else if (/\s/.test(ch)) {
|
|
506
|
+
if (current) {
|
|
507
|
+
tokens.push(current);
|
|
508
|
+
current = "";
|
|
509
|
+
}
|
|
510
|
+
} else {
|
|
511
|
+
current += ch;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
if (current) tokens.push(current);
|
|
515
|
+
return tokens;
|
|
516
|
+
}
|
|
517
|
+
function isReadOnlyBash(command) {
|
|
518
|
+
const trimmed = command.trim();
|
|
519
|
+
if (!trimmed) return false;
|
|
520
|
+
if (DANGEROUS_PATTERNS.test(trimmed)) return false;
|
|
521
|
+
const tokens = tokenizeCommand(trimmed);
|
|
522
|
+
if (tokens.length === 0) return false;
|
|
523
|
+
const first = tokens[0];
|
|
524
|
+
let cmdIndex = 0;
|
|
525
|
+
if (first === "cd" && tokens.length >= 3 && tokens[1] && tokens[2] === "&&") {
|
|
526
|
+
cmdIndex = 3;
|
|
527
|
+
}
|
|
528
|
+
const cmd = tokens[cmdIndex];
|
|
529
|
+
if (!cmd) return false;
|
|
530
|
+
const args = tokens.slice(cmdIndex + 1);
|
|
531
|
+
if (cmd === "git") {
|
|
532
|
+
const sub = args[0] ?? "";
|
|
533
|
+
const allowed = GIT_READONLY_SUBCOMMANDS[sub];
|
|
534
|
+
if (allowed === void 0) return false;
|
|
535
|
+
if (allowed === true) return true;
|
|
536
|
+
switch (sub) {
|
|
537
|
+
case "branch":
|
|
538
|
+
return !args.some((a) => /^-[dDmMcC]/.test(a));
|
|
539
|
+
case "stash":
|
|
540
|
+
return args[1] === "list";
|
|
541
|
+
case "remote":
|
|
542
|
+
return args[1] === "-v" || args[1] === "--verbose" || args.length === 1;
|
|
543
|
+
case "tag":
|
|
544
|
+
return args[1] === "-l" || args[1] === "--list" || args.length === 1;
|
|
545
|
+
case "config":
|
|
546
|
+
return args[1] === "--list" || args[1]?.startsWith("--get") === true || args.length === 1;
|
|
547
|
+
default:
|
|
548
|
+
return false;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
const argCheck = COMMANDS_NEEDING_ARG_CHECK[cmd];
|
|
552
|
+
if (argCheck) {
|
|
553
|
+
return argCheck(args);
|
|
554
|
+
}
|
|
555
|
+
return READONLY_COMMANDS.has(cmd);
|
|
556
|
+
}
|
|
492
557
|
function systemPromptForMode(m) {
|
|
493
558
|
if (m === "plan") {
|
|
494
|
-
return "\n\nPLAN MODE is active. The user wants you to investigate and produce a plan WITHOUT making any changes. Do not call write, edit, or bash.
|
|
559
|
+
return "\n\nPLAN MODE is active. The user wants you to investigate and produce a plan WITHOUT making any changes. Do not call write, edit, or mutating bash commands. You may use read-only bash commands (e.g., git log, git diff, ls, cat) along with read/glob/grep/web-fetch. At the end, present a concise plan (bullets, files to change, approach). The user will review and then exit plan mode to execute.";
|
|
495
560
|
}
|
|
496
561
|
if (m === "auto") {
|
|
497
562
|
return "\n\nAUTO MODE is active. The user has opted into autonomous execution \u2014 every tool call will be auto-approved. Work efficiently, but do not take irreversible destructive actions (rm -rf, git push --force, dropping tables, etc.) without pausing to describe them in chat first. Prefer smaller reversible steps.";
|
|
498
563
|
}
|
|
499
564
|
return "";
|
|
500
565
|
}
|
|
501
|
-
var MODES, MUTATING_TOOLS;
|
|
566
|
+
var MODES, MUTATING_TOOLS, DANGEROUS_PATTERNS, GIT_READONLY_SUBCOMMANDS, READONLY_COMMANDS, COMMANDS_NEEDING_ARG_CHECK;
|
|
502
567
|
var init_mode = __esm({
|
|
503
568
|
"src/mode.ts"() {
|
|
504
569
|
"use strict";
|
|
505
570
|
MODES = ["edit", "plan", "auto"];
|
|
506
571
|
MUTATING_TOOLS = /* @__PURE__ */ new Set(["write", "edit", "bash"]);
|
|
572
|
+
DANGEROUS_PATTERNS = /[<>|;&`$]|\$\(|\$\{|&&|\|\||\b&\s*$/;
|
|
573
|
+
GIT_READONLY_SUBCOMMANDS = {
|
|
574
|
+
log: true,
|
|
575
|
+
diff: true,
|
|
576
|
+
status: true,
|
|
577
|
+
show: true,
|
|
578
|
+
blame: true,
|
|
579
|
+
describe: true,
|
|
580
|
+
"rev-parse": true,
|
|
581
|
+
"ls-files": true,
|
|
582
|
+
reflog: true,
|
|
583
|
+
shortlog: true,
|
|
584
|
+
whatchanged: true,
|
|
585
|
+
grep: true,
|
|
586
|
+
branch: false,
|
|
587
|
+
// needs check: block -d/-D/-m/-M/-c/-C
|
|
588
|
+
stash: false,
|
|
589
|
+
// needs check: only allow "list"
|
|
590
|
+
remote: false,
|
|
591
|
+
// needs check: only allow -v
|
|
592
|
+
tag: false,
|
|
593
|
+
// needs check: only allow -l
|
|
594
|
+
config: false
|
|
595
|
+
// needs check: only allow --list/--get
|
|
596
|
+
};
|
|
597
|
+
READONLY_COMMANDS = /* @__PURE__ */ new Set([
|
|
598
|
+
// File system
|
|
599
|
+
"ls",
|
|
600
|
+
"cat",
|
|
601
|
+
"head",
|
|
602
|
+
"tail",
|
|
603
|
+
"pwd",
|
|
604
|
+
"echo",
|
|
605
|
+
"file",
|
|
606
|
+
"stat",
|
|
607
|
+
"readlink",
|
|
608
|
+
"realpath",
|
|
609
|
+
"dirname",
|
|
610
|
+
"basename",
|
|
611
|
+
"wc",
|
|
612
|
+
"sort",
|
|
613
|
+
"uniq",
|
|
614
|
+
"diff",
|
|
615
|
+
"cmp",
|
|
616
|
+
// Search
|
|
617
|
+
"grep",
|
|
618
|
+
"rg",
|
|
619
|
+
"ag",
|
|
620
|
+
"fd",
|
|
621
|
+
// System info
|
|
622
|
+
"ps",
|
|
623
|
+
"df",
|
|
624
|
+
"du",
|
|
625
|
+
"env",
|
|
626
|
+
"printenv",
|
|
627
|
+
"which",
|
|
628
|
+
"whereis",
|
|
629
|
+
"uname",
|
|
630
|
+
"hostname",
|
|
631
|
+
"uptime",
|
|
632
|
+
"free",
|
|
633
|
+
"date",
|
|
634
|
+
"id",
|
|
635
|
+
"whoami",
|
|
636
|
+
"groups",
|
|
637
|
+
// Dev tools (version/info only)
|
|
638
|
+
"node",
|
|
639
|
+
"npx",
|
|
640
|
+
"python3",
|
|
641
|
+
"ruby",
|
|
642
|
+
"perl",
|
|
643
|
+
// Utilities
|
|
644
|
+
"jq",
|
|
645
|
+
"yq",
|
|
646
|
+
"awk",
|
|
647
|
+
"cut",
|
|
648
|
+
"tr",
|
|
649
|
+
"base64",
|
|
650
|
+
"sha256sum",
|
|
651
|
+
"md5sum",
|
|
652
|
+
"shasum",
|
|
653
|
+
"hexdump",
|
|
654
|
+
"xxd",
|
|
655
|
+
"strings",
|
|
656
|
+
"less",
|
|
657
|
+
"more",
|
|
658
|
+
"man",
|
|
659
|
+
"clear",
|
|
660
|
+
"history",
|
|
661
|
+
// Archive inspection
|
|
662
|
+
"zipinfo",
|
|
663
|
+
// Network
|
|
664
|
+
"ping",
|
|
665
|
+
"netstat",
|
|
666
|
+
"ss",
|
|
667
|
+
"lsof"
|
|
668
|
+
]);
|
|
669
|
+
COMMANDS_NEEDING_ARG_CHECK = {
|
|
670
|
+
find: (args) => !args.some((a) => a === "-delete" || a === "-exec"),
|
|
671
|
+
sed: (args) => !args.some((a) => a === "-i" || a.startsWith("-i")),
|
|
672
|
+
tar: (args) => args[0] === "-tf" || args[0] === "--list",
|
|
673
|
+
unzip: (args) => args[0] === "-l",
|
|
674
|
+
curl: (args) => !args.some((a) => a === "-o" || a === "-O" || a === "-d" || a === "--data" || a.startsWith("-X")),
|
|
675
|
+
wget: (args) => !args.some((a) => a === "-O" || a === "--output-document" || a.startsWith("--post")),
|
|
676
|
+
npm: (args) => ["list", "view", "config"].includes(args[0] ?? "") && !(args[0] === "config" && args[1] && !args[1].startsWith("get") && args[1] !== "list"),
|
|
677
|
+
tsc: (args) => args.every(
|
|
678
|
+
(a) => ["--noEmit", "--version", "--showConfig", "--help", "-h", "--init"].includes(a)
|
|
679
|
+
),
|
|
680
|
+
eslint: (args) => args.every(
|
|
681
|
+
(a) => ["--version", "--print-config", "--help", "-h"].includes(a) || !a.startsWith("-")
|
|
682
|
+
),
|
|
683
|
+
prettier: (args) => args.every(
|
|
684
|
+
(a) => ["--version", "--check", "--help", "-h"].includes(a) || !a.startsWith("-")
|
|
685
|
+
),
|
|
686
|
+
jest: (args) => args.every(
|
|
687
|
+
(a) => ["--version", "--listTests", "--showConfig", "--help", "-h"].includes(a) || !a.startsWith("-")
|
|
688
|
+
),
|
|
689
|
+
vitest: (args) => args.every(
|
|
690
|
+
(a) => ["--version", "--help", "-h"].includes(a) || !a.startsWith("-")
|
|
691
|
+
),
|
|
692
|
+
go: (args) => ["version", "env", "list", "mod"].includes(args[0] ?? "") && !(args[0] === "mod" && args[1] && !["graph", "download", "why", "verify"].includes(args[1])),
|
|
693
|
+
cargo: (args) => ["--version", "-V", "check", "test", "metadata"].includes(args[0] ?? "") && !(args[0] === "test" && args.includes("--no-run") === false)
|
|
694
|
+
};
|
|
507
695
|
}
|
|
508
696
|
});
|
|
509
697
|
|
|
@@ -3711,7 +3899,26 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
3711
3899
|
setUsage(u);
|
|
3712
3900
|
},
|
|
3713
3901
|
askPermission: (req) => new Promise((resolve2) => {
|
|
3714
|
-
if (modeRef.current === "auto")
|
|
3902
|
+
if (modeRef.current === "auto") {
|
|
3903
|
+
resolve2("allow");
|
|
3904
|
+
return;
|
|
3905
|
+
}
|
|
3906
|
+
if (modeRef.current === "plan" && isBlockedInPlanMode(req.tool.name)) {
|
|
3907
|
+
if (req.tool.name === "bash" && typeof req.args.command === "string" && isReadOnlyBash(req.args.command)) {
|
|
3908
|
+
resolve2("allow");
|
|
3909
|
+
return;
|
|
3910
|
+
}
|
|
3911
|
+
setEvents((e) => [
|
|
3912
|
+
...e,
|
|
3913
|
+
{
|
|
3914
|
+
kind: "info",
|
|
3915
|
+
key: mkKey(),
|
|
3916
|
+
text: `plan mode blocked ${req.tool.name}; exit plan mode to execute`
|
|
3917
|
+
}
|
|
3918
|
+
]);
|
|
3919
|
+
resolve2("deny");
|
|
3920
|
+
return;
|
|
3921
|
+
}
|
|
3715
3922
|
setPerm({ tool: req.tool, args: req.args, resolve: resolve2 });
|
|
3716
3923
|
})
|
|
3717
3924
|
}
|
|
@@ -4106,6 +4313,10 @@ use: /thinking low | medium | high`
|
|
|
4106
4313
|
return;
|
|
4107
4314
|
}
|
|
4108
4315
|
if (modeRef.current === "plan" && isBlockedInPlanMode(req.tool.name)) {
|
|
4316
|
+
if (req.tool.name === "bash" && typeof req.args.command === "string" && isReadOnlyBash(req.args.command)) {
|
|
4317
|
+
resolve2("allow");
|
|
4318
|
+
return;
|
|
4319
|
+
}
|
|
4109
4320
|
setEvents((e) => [
|
|
4110
4321
|
...e,
|
|
4111
4322
|
{
|