ningzhi-agent-cli 0.0.1

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.
Files changed (84) hide show
  1. package/CLAUDE.md +197 -0
  2. package/README.md +35 -0
  3. package/dist/agent/agent.d.ts +24 -0
  4. package/dist/agent/agent.js +432 -0
  5. package/dist/agent/cli.d.ts +1 -0
  6. package/dist/agent/cli.js +209 -0
  7. package/dist/agent/colors.d.ts +19 -0
  8. package/dist/agent/colors.js +92 -0
  9. package/dist/agent/commands.d.ts +7 -0
  10. package/dist/agent/commands.js +73 -0
  11. package/dist/agent/config.d.ts +38 -0
  12. package/dist/agent/config.js +119 -0
  13. package/dist/agent/context.d.ts +17 -0
  14. package/dist/agent/context.js +146 -0
  15. package/dist/agent/db.d.ts +25 -0
  16. package/dist/agent/db.js +185 -0
  17. package/dist/agent/hooks/engine.d.ts +27 -0
  18. package/dist/agent/hooks/engine.js +122 -0
  19. package/dist/agent/hooks/index.d.ts +1 -0
  20. package/dist/agent/hooks/index.js +11 -0
  21. package/dist/agent/mcp/client.d.ts +31 -0
  22. package/dist/agent/mcp/client.js +138 -0
  23. package/dist/agent/mcp/index.d.ts +4 -0
  24. package/dist/agent/mcp/index.js +27 -0
  25. package/dist/agent/mcp/wrapper.d.ts +7 -0
  26. package/dist/agent/mcp/wrapper.js +26 -0
  27. package/dist/agent/model.d.ts +5 -0
  28. package/dist/agent/model.js +35 -0
  29. package/dist/agent/permission/dangerous-path.json +115 -0
  30. package/dist/agent/permission/exec.d.ts +14 -0
  31. package/dist/agent/permission/exec.js +35 -0
  32. package/dist/agent/permission/is-dangerous-path.d.ts +8 -0
  33. package/dist/agent/permission/is-dangerous-path.js +96 -0
  34. package/dist/agent/permission/is-safe-domains.d.ts +1 -0
  35. package/dist/agent/permission/is-safe-domains.js +145 -0
  36. package/dist/agent/permission/network.d.ts +8 -0
  37. package/dist/agent/permission/network.js +14 -0
  38. package/dist/agent/permission/read.d.ts +9 -0
  39. package/dist/agent/permission/read.js +17 -0
  40. package/dist/agent/permission/util.d.ts +11 -0
  41. package/dist/agent/permission/util.js +347 -0
  42. package/dist/agent/permission/write.d.ts +11 -0
  43. package/dist/agent/permission/write.js +21 -0
  44. package/dist/agent/prompt.d.ts +1 -0
  45. package/dist/agent/prompt.js +52 -0
  46. package/dist/agent/skills/oppose/SKILL.md +100 -0
  47. package/dist/agent/skills/planner/SKILL.md +90 -0
  48. package/dist/agent/skills.d.ts +8 -0
  49. package/dist/agent/skills.js +103 -0
  50. package/dist/agent/tools/agent_tool.d.ts +3 -0
  51. package/dist/agent/tools/agent_tool.js +44 -0
  52. package/dist/agent/tools/exec_tool.d.ts +3 -0
  53. package/dist/agent/tools/exec_tool.js +33 -0
  54. package/dist/agent/tools/load_skill_tool.d.ts +3 -0
  55. package/dist/agent/tools/load_skill_tool.js +16 -0
  56. package/dist/agent/tools/memory_create_tool.d.ts +6 -0
  57. package/dist/agent/tools/memory_create_tool.js +39 -0
  58. package/dist/agent/tools/memory_delete_tool.d.ts +3 -0
  59. package/dist/agent/tools/memory_delete_tool.js +28 -0
  60. package/dist/agent/tools/memory_retrieve_tool.d.ts +4 -0
  61. package/dist/agent/tools/memory_retrieve_tool.js +26 -0
  62. package/dist/agent/tools/profile_update_tool.d.ts +3 -0
  63. package/dist/agent/tools/profile_update_tool.js +51 -0
  64. package/dist/agent/tools/read_file_tool.d.ts +3 -0
  65. package/dist/agent/tools/read_file_tool.js +16 -0
  66. package/dist/agent/tools/run_js_tool.d.ts +3 -0
  67. package/dist/agent/tools/run_js_tool.js +47 -0
  68. package/dist/agent/tools/run_py_tool.d.ts +3 -0
  69. package/dist/agent/tools/run_py_tool.js +37 -0
  70. package/dist/agent/tools/web_fetch_tool.d.ts +3 -0
  71. package/dist/agent/tools/web_fetch_tool.js +28 -0
  72. package/dist/agent/tools/web_search_tool.d.ts +3 -0
  73. package/dist/agent/tools/web_search_tool.js +38 -0
  74. package/dist/agent/tools/write_file_tool.d.ts +4 -0
  75. package/dist/agent/tools/write_file_tool.js +15 -0
  76. package/dist/agent/tools.d.ts +14 -0
  77. package/dist/agent/tools.js +218 -0
  78. package/dist/agent/utils.d.ts +11 -0
  79. package/dist/agent/utils.js +43 -0
  80. package/dist/index.d.ts +2 -0
  81. package/dist/index.js +81 -0
  82. package/dist/install.d.ts +1 -0
  83. package/dist/install.js +150 -0
  84. package/package.json +56 -0
@@ -0,0 +1,115 @@
1
+ {
2
+ "macos": [
3
+ "~/.ssh",
4
+ "~/.gnupg",
5
+ "~/.aws",
6
+ "~/.azure",
7
+ "~/.config/gcloud",
8
+ "~/.kube",
9
+ "~/.docker",
10
+ "~/.netrc",
11
+ "~/Library/Keychains",
12
+ "~/Library/Application Support/Google/Chrome",
13
+ "~/Library/Application Support/Chromium",
14
+ "~/Library/Application Support/Firefox",
15
+ "~/Library/Application Support/Slack",
16
+ "~/Library/Application Support/Discord",
17
+ "~/Library/Application Support/Telegram",
18
+ "~/Library/Application Support/Signal",
19
+ "~/.zshrc",
20
+ "~/.bashrc",
21
+ "~/.bash_profile",
22
+ "~/.profile",
23
+ "~/.env",
24
+ "~/.env.*",
25
+ "~/.gitconfig",
26
+ "~/.git-credentials",
27
+ "~/.npmrc",
28
+ "~/.pnpmrc",
29
+ "~/.yarnrc",
30
+ "~/.pypirc",
31
+ "~/.m2",
32
+ "~/.gradle",
33
+ "~/.terraform",
34
+ "~/.config/gh",
35
+ "~/.config/gitlab",
36
+ "~/.circleci",
37
+ "~/.vercel",
38
+ "~/.netlify",
39
+ "~/Library/Containers",
40
+ "/private",
41
+ "/etc",
42
+ "/var"
43
+ ],
44
+ "linux": [
45
+ "~/.ssh",
46
+ "~/.gnupg",
47
+ "~/.pki",
48
+ "~/.aws",
49
+ "~/.azure",
50
+ "~/.config/gcloud",
51
+ "~/.kube",
52
+ "~/.docker",
53
+ "~/.netrc",
54
+ "~/.local/share/keyrings",
55
+ "~/.config/google-chrome",
56
+ "~/.config/chromium",
57
+ "~/.mozilla/firefox",
58
+ "~/.config/Slack",
59
+ "~/.config/discord",
60
+ "~/.local/share/TelegramDesktop",
61
+ "~/.zshrc",
62
+ "~/.bashrc",
63
+ "~/.bash_profile",
64
+ "~/.profile",
65
+ "~/.env",
66
+ "~/.env.*",
67
+ "~/.gitconfig",
68
+ "~/.git-credentials",
69
+ "~/.npmrc",
70
+ "~/.pnpmrc",
71
+ "~/.yarnrc",
72
+ "~/.pypirc",
73
+ "~/.m2",
74
+ "~/.gradle",
75
+ "~/.terraform",
76
+ "~/.config/gh",
77
+ "~/.config/gitlab",
78
+ "~/.circleci",
79
+ "~/.vercel",
80
+ "~/.netlify",
81
+ "/etc/shadow",
82
+ "/etc/sudoers",
83
+ "/proc",
84
+ "/sys",
85
+ "/var/lib",
86
+ "/root"
87
+ ],
88
+ "windows": [
89
+ "%USERPROFILE%\\.ssh",
90
+ "%USERPROFILE%\\.gnupg",
91
+ "%USERPROFILE%\\.aws",
92
+ "%USERPROFILE%\\.azure",
93
+ "%USERPROFILE%\\.kube",
94
+ "%USERPROFILE%\\.docker",
95
+ "%LOCALAPPDATA%\\Google\\Chrome\\User Data",
96
+ "%LOCALAPPDATA%\\Chromium\\User Data",
97
+ "%APPDATA%\\Mozilla\\Firefox",
98
+ "%APPDATA%\\Slack",
99
+ "%APPDATA%\\Discord",
100
+ "%APPDATA%\\Telegram Desktop",
101
+ "%USERPROFILE%\\.gitconfig",
102
+ "%USERPROFILE%\\.git-credentials",
103
+ "%USERPROFILE%\\.npmrc",
104
+ "%USERPROFILE%\\.npmrc",
105
+ "%USERPROFILE%\\.yarnrc",
106
+ "%USERPROFILE%\\.m2",
107
+ "%USERPROFILE%\\.gradle",
108
+ "%APPDATA%",
109
+ "%LOCALAPPDATA%",
110
+ "C:\\Windows\\System32",
111
+ "C:\\Windows\\System32\\config\\SAM",
112
+ "C:\\Windows\\System32\\config\\SECURITY",
113
+ "C:\\Windows\\System32\\config\\SYSTEM"
114
+ ]
115
+ }
@@ -0,0 +1,14 @@
1
+ type checkExecPermissionReturnType = {
2
+ action: "allow";
3
+ } | {
4
+ action: "block";
5
+ reason: string;
6
+ } | {
7
+ action: "confirm";
8
+ };
9
+ interface IToolCall {
10
+ name: string;
11
+ args: Record<string, any>;
12
+ }
13
+ export declare function checkExecPermission(toolCall: IToolCall): checkExecPermissionReturnType;
14
+ export {};
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkExecPermission = checkExecPermission;
4
+ const util_1 = require("./util");
5
+ function checkExecPermission(toolCall) {
6
+ const command = toolCall.args?.command;
7
+ if (typeof command !== "string") {
8
+ return { action: "confirm" };
9
+ }
10
+ if ((0, util_1.isSafeCommand)(command)) {
11
+ return { action: "allow" };
12
+ }
13
+ // 检查命令是否包含切换目录操作
14
+ if ((0, util_1.isChangingDirectory)(command)) {
15
+ return {
16
+ action: "block",
17
+ reason: `命令包含切换目录操作,为防止目录逃逸,禁止执行。如有需要请手动操作。`,
18
+ };
19
+ }
20
+ const scriptCheck = (0, util_1.isScriptExecution)(command);
21
+ if (scriptCheck.blocked) {
22
+ return {
23
+ action: "block",
24
+ reason: scriptCheck.reason,
25
+ };
26
+ }
27
+ const dangerCheck = (0, util_1.isDangerousOperation)(command);
28
+ if (dangerCheck.blocked) {
29
+ return {
30
+ action: "block",
31
+ reason: dangerCheck.reason,
32
+ };
33
+ }
34
+ return { action: "confirm" };
35
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * 判断给定路径是否属于系统危险路径(如系统目录、用户家目录根等)。
3
+ * 根据当前操作系统从 dangerous-path.json 中加载对应危险路径列表,
4
+ * 支持通配符匹配与子路径匹配。
5
+ * @param filepath 待检测的路径
6
+ * @returns 若命中任一危险路径规则则返回 true,否则返回 false
7
+ */
8
+ export declare function isDangerousPath(filepath: string): boolean;
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.isDangerousPath = isDangerousPath;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const node_os_1 = __importDefault(require("node:os"));
9
+ const dangerous_path_json_1 = __importDefault(require("./dangerous-path.json"));
10
+ /**
11
+ * 展开路径中的特殊变量与符号,返回规范化后的绝对路径。
12
+ * 支持:`~`、`%USERPROFILE%`、`%APPDATA%`、`%LOCALAPPDATA%` 以及相对路径。
13
+ * @param filepath 待展开的路径字符串
14
+ * @returns 规范化后的绝对路径
15
+ */
16
+ function expandPath(filepath) {
17
+ let expanded = filepath;
18
+ // 处理 Unix 风格的 home 目录简写 `~` 或 `~/xxx`
19
+ if (expanded.startsWith("~")) {
20
+ expanded = node_path_1.default.join(node_os_1.default.homedir(), expanded.slice(1));
21
+ }
22
+ // 展开 Windows 环境变量占位符(不区分大小写)
23
+ expanded = expanded.replace(/%USERPROFILE%/gi, node_os_1.default.homedir());
24
+ // 展开 Windows 环境变量占位符(不区分大小写)
25
+ // 若未指定,使用默认值(用户 home 目录下的 AppData 目录)
26
+ expanded = expanded.replace(/%APPDATA%/gi, process.env.APPDATA || node_path_1.default.join(node_os_1.default.homedir(), "AppData", "Roaming"));
27
+ // 展开 Windows 环境变量占位符(不区分大小写)
28
+ // 若未指定,使用默认值(用户 home 目录下的 AppData 目录下的 Local 目录)
29
+ expanded = expanded.replace(/%LOCALAPPDATA%/gi, process.env.LOCALAPPDATA || node_path_1.default.join(node_os_1.default.homedir(), "AppData", "Local"));
30
+ // 若展开后仍为相对路径,则以当前工作目录为基准转为绝对路径
31
+ if (!node_path_1.default.isAbsolute(expanded)) {
32
+ expanded = node_path_1.default.resolve(expanded);
33
+ }
34
+ // 规范化路径(消除 `..`、`.`、重复分隔符等), 例如:
35
+ // 将 `\\` 转换为 `/`
36
+ // 将 `./` 转换为 `/`
37
+ // 将 `/./` 转换为 `/`
38
+ expanded = node_path_1.default.normalize(expanded);
39
+ // 返回规范化后的路径
40
+ return expanded;
41
+ }
42
+ /**
43
+ * 将含通配符 `*` 的 glob 模式转换为正则表达式。
44
+ * `*` 匹配除路径分隔符外的任意字符序列。
45
+ * @param pattern glob 模式字符串
46
+ * @returns 用于匹配路径的正则表达式
47
+ */
48
+ function globToRegex(pattern) {
49
+ // 先转义正则元字符,再将 `*` 转为 `[^\\/]*`
50
+ const escaped = pattern
51
+ .replace(/[.+^${}()|[\]\\]/g, "\\$&")
52
+ .replace(/\*/g, "[^\\\\/]*");
53
+ // 匹配 pattern 本身或其下的任意子路径
54
+ return new RegExp(`^${escaped}(?:[\\\\/].*)?$`);
55
+ }
56
+ /**
57
+ * 判断给定路径是否属于系统危险路径(如系统目录、用户家目录根等)。
58
+ * 根据当前操作系统从 dangerous-path.json 中加载对应危险路径列表,
59
+ * 支持通配符匹配与子路径匹配。
60
+ * @param filepath 待检测的路径
61
+ * @returns 若命中任一危险路径规则则返回 true,否则返回 false
62
+ */
63
+ function isDangerousPath(filepath) {
64
+ // 识别当前操作系统,映射为 JSON 中的平台键
65
+ const platform = process.platform === "win32"
66
+ ? "windows"
67
+ : process.platform === "darwin"
68
+ ? "macos"
69
+ : "linux";
70
+ const dangerousList = dangerous_path_json_1.default[platform];
71
+ // 先对用户输入路径做展开与规范化,确保后续比较基准一致
72
+ const expandedInput = expandPath(filepath);
73
+ // 遍历危险路径列表,检查是否命中任何规则
74
+ // 若命中则返回 true,否则返回 false
75
+ for (const dangerous of dangerousList) {
76
+ const expandedDangerous = expandPath(dangerous);
77
+ // 检查是否命中通配符规则
78
+ if (dangerous.includes("*")) {
79
+ // 含通配符的规则:使用正则进行匹配
80
+ const regex = globToRegex(expandedDangerous);
81
+ if (regex.test(expandedInput))
82
+ return true;
83
+ }
84
+ else {
85
+ // 精确规则:路径完全相同,或是其子路径(以 dangerous + 分隔符 开头)
86
+ if (expandedInput === expandedDangerous)
87
+ return true;
88
+ // 检查是否命中子路径规则
89
+ // 若以 dangerous + 分隔符 开头,返回 true, path.sep 为分隔符
90
+ if (expandedInput.startsWith(expandedDangerous + node_path_1.default.sep))
91
+ return true;
92
+ }
93
+ }
94
+ // 若未命中任何规则,返回 false
95
+ return false;
96
+ }
@@ -0,0 +1 @@
1
+ export declare function isSafeDomain(url: string): boolean;
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isSafeDomain = isSafeDomain;
4
+ // 中国的程序员、或软件公司、互联网公司的员工 最常用的100个域名
5
+ const commonDomainsCNForDevelopers = [
6
+ // 搜索 / AI
7
+ "google.com",
8
+ "baidu.com",
9
+ "bing.com",
10
+ "openai.com",
11
+ "claude.ai",
12
+ "anthropic.com",
13
+ "perplexity.ai",
14
+ "kimi.moonshot.cn",
15
+ "doubao.com",
16
+ "deepseek.com",
17
+ // 代码托管 / 开发平台
18
+ "github.com",
19
+ "gitlab.com",
20
+ "gitee.com",
21
+ "bitbucket.org",
22
+ // 技术社区
23
+ "stackoverflow.com",
24
+ "v2ex.com",
25
+ "zhihu.com",
26
+ "juejin.cn",
27
+ "csdn.net",
28
+ "oschina.net",
29
+ "segmentfault.com",
30
+ "infoq.cn",
31
+ "51cto.com",
32
+ "cnblogs.com",
33
+ "linux.do",
34
+ "reddit.com",
35
+ "medium.com",
36
+ "dev.to",
37
+ "hackernoon.com",
38
+ // 文档 / API / 开源
39
+ "npmjs.com",
40
+ "nodejs.org",
41
+ "python.org",
42
+ "pypi.org",
43
+ "rust-lang.org",
44
+ "golang.org",
45
+ "docker.com",
46
+ "kubernetes.io",
47
+ "mozilla.org",
48
+ "developer.mozilla.org",
49
+ "w3.org",
50
+ "react.dev",
51
+ "nextjs.org",
52
+ "vuejs.org",
53
+ "nuxt.com",
54
+ "tailwindcss.com",
55
+ "vercel.com",
56
+ "supabase.com",
57
+ "cloudflare.com",
58
+ // 云服务 / DevOps
59
+ "aliyun.com",
60
+ "tencent.com",
61
+ "huaweicloud.com",
62
+ "aws.amazon.com",
63
+ "azure.com",
64
+ "googleapis.com",
65
+ "firebase.google.com",
66
+ "netlify.com",
67
+ "railway.app",
68
+ "render.com",
69
+ // CI/CD / 工程工具
70
+ "jenkins.io",
71
+ "sonarqube.org",
72
+ "sentry.io",
73
+ "postman.com",
74
+ "swagger.io",
75
+ "openapi.org",
76
+ // 数据库 / 中间件
77
+ "mysql.com",
78
+ "postgresql.org",
79
+ "redis.io",
80
+ "mongodb.com",
81
+ "sqlite.org",
82
+ "apache.org",
83
+ "elastic.co",
84
+ "rabbitmq.com",
85
+ "kafka.apache.org",
86
+ // 办公 / 协作
87
+ "feishu.cn",
88
+ "dingtalk.com",
89
+ "yuque.com",
90
+ "notion.so",
91
+ "atlassian.com",
92
+ "jira.com",
93
+ "confluence.com",
94
+ "slack.com",
95
+ "trello.com",
96
+ // 下载 / 软件
97
+ "jetbrains.com",
98
+ "visualstudio.com",
99
+ "microsoft.com",
100
+ "apple.com",
101
+ "homebrew.sh",
102
+ "iterm2.com",
103
+ // 中国互联网公司
104
+ "qq.com",
105
+ "wechat.com",
106
+ "weibo.com",
107
+ "bilibili.com",
108
+ "douyin.com",
109
+ "xiaohongshu.com",
110
+ "taobao.com",
111
+ "tmall.com",
112
+ "jd.com",
113
+ "aliyun.com",
114
+ // 学习 / 视频
115
+ "youtube.com",
116
+ "coursera.org",
117
+ "udemy.com",
118
+ "leetcode.com",
119
+ "nowcoder.com",
120
+ "geeksforgeeks.org",
121
+ // AI / Agent / 自动化
122
+ "langchain.com",
123
+ "langgraph.dev",
124
+ "huggingface.co",
125
+ "replicate.com",
126
+ "ollama.com",
127
+ "openrouter.ai",
128
+ "tavily.com",
129
+ "smith.langchain.com",
130
+ ];
131
+ // 检查域名是否安全安全
132
+ function isSafeDomain(url) {
133
+ let hostname;
134
+ try {
135
+ hostname = new URL(url).hostname.toLowerCase();
136
+ }
137
+ catch {
138
+ return false;
139
+ }
140
+ // 检查域名是否在安全域名列表中
141
+ return commonDomainsCNForDevelopers.some((domain) => {
142
+ const d = domain.toLowerCase();
143
+ return hostname === d || hostname.endsWith("." + d);
144
+ });
145
+ }
@@ -0,0 +1,8 @@
1
+ export declare function checkNetworkPermission(toolCall: {
2
+ name: string;
3
+ args: Record<string, any>;
4
+ }): {
5
+ action: "allow";
6
+ } | {
7
+ action: "confirm";
8
+ };
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkNetworkPermission = checkNetworkPermission;
4
+ const is_safe_domains_1 = require("./is-safe-domains");
5
+ function checkNetworkPermission(toolCall) {
6
+ const url = toolCall.args?.url;
7
+ if (typeof url !== "string") {
8
+ return { action: "allow" };
9
+ }
10
+ if ((0, is_safe_domains_1.isSafeDomain)(url)) {
11
+ return { action: "allow" };
12
+ }
13
+ return { action: "confirm" };
14
+ }
@@ -0,0 +1,9 @@
1
+ export declare function checkReadPermission(toolCall: {
2
+ name: string;
3
+ args: Record<string, any>;
4
+ }): {
5
+ action: "allow";
6
+ } | {
7
+ action: "block";
8
+ reason: string;
9
+ };
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkReadPermission = checkReadPermission;
4
+ const is_dangerous_path_1 = require("./is-dangerous-path");
5
+ function checkReadPermission(toolCall) {
6
+ const filepath = toolCall.args?.filepath;
7
+ if (filepath == null) {
8
+ return { action: "allow" };
9
+ }
10
+ if ((0, is_dangerous_path_1.isDangerousPath)(filepath)) {
11
+ return {
12
+ action: "block",
13
+ reason: `路径 "${filepath}" 是系统敏感目录,为保护系统安全,禁止访问。如有需要请手动操作。`,
14
+ };
15
+ }
16
+ return { action: "allow" };
17
+ }
@@ -0,0 +1,11 @@
1
+ export declare function isInProjectDir(filepath: string): boolean;
2
+ export declare function isChangingDirectory(command: string): boolean;
3
+ export declare function isScriptExecution(command: string): {
4
+ blocked: boolean;
5
+ reason?: string;
6
+ };
7
+ export declare function isSafeCommand(command: string): boolean;
8
+ export declare function isDangerousOperation(command: string): {
9
+ blocked: boolean;
10
+ reason?: string;
11
+ };