jinzd-ai-cli 0.4.87 → 0.4.88
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/{batch-FNHSLCMV.js → batch-7XCYSPJU.js} +2 -2
- package/dist/{chunk-3DGNN4RM.js → chunk-L3MBIO36.js} +129 -3
- package/dist/{chunk-AQX3GYRD.js → chunk-P6EQZKKG.js} +1 -1
- package/dist/{chunk-Y75YPB5F.js → chunk-QT2KNL3V.js} +19 -1
- package/dist/{chunk-TFLBQRQM.js → chunk-V3NMERIB.js} +1 -1
- package/dist/{chunk-BAOIXQHD.js → chunk-VGXNE37B.js} +1 -1
- package/dist/{chunk-SP6RFAKW.js → chunk-YDHIU24C.js} +2 -2
- package/dist/electron-server.js +141 -3
- package/dist/{hub-HEC4GYKR.js → hub-IR4INXSU.js} +1 -1
- package/dist/index.js +101 -10
- package/dist/{run-tests-7PTRRO4D.js → run-tests-FQHDUYOG.js} +2 -2
- package/dist/{run-tests-P7GIZ6UH.js → run-tests-JVWIGY7P.js} +1 -1
- package/dist/{server-GJRBVTTQ.js → server-HTVVWKFN.js} +3 -3
- package/dist/{server-TRTN3RVO.js → server-UWKRV5DK.js} +6 -6
- package/dist/{task-orchestrator-36SFPCP7.js → task-orchestrator-6MI6LD7T.js} +3 -3
- package/package.json +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ConfigManager
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-QT2KNL3V.js";
|
|
5
5
|
import "./chunk-2ZD3YTVM.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-VGXNE37B.js";
|
|
7
7
|
|
|
8
8
|
// src/cli/batch.ts
|
|
9
9
|
import Anthropic from "@anthropic-ai/sdk";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
schemaToJsonSchema,
|
|
4
4
|
truncateForPersist
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-YDHIU24C.js";
|
|
6
6
|
import {
|
|
7
7
|
AuthError,
|
|
8
8
|
ProviderError,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
MCP_PROTOCOL_VERSION,
|
|
19
19
|
MCP_TOOL_PREFIX,
|
|
20
20
|
VERSION
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-VGXNE37B.js";
|
|
22
22
|
|
|
23
23
|
// src/providers/claude.ts
|
|
24
24
|
import Anthropic from "@anthropic-ai/sdk";
|
|
@@ -2655,6 +2655,108 @@ var Session = class _Session {
|
|
|
2655
2655
|
}
|
|
2656
2656
|
};
|
|
2657
2657
|
|
|
2658
|
+
// src/security/redactor.ts
|
|
2659
|
+
var DEFAULT_PATTERNS = [
|
|
2660
|
+
// password: xxx / password = xxx / password="xxx"
|
|
2661
|
+
// Covers YAML / JSON / shell-ish / env-file forms.
|
|
2662
|
+
{ kind: "password", regex: /\b(password|passwd|pwd)\s*[:=]\s*["']?([^\s"',;{}]{4,200})["']?/gi },
|
|
2663
|
+
// PGPASSWORD=xxx (explicit bash env-var form, separate rule because no quotes usually)
|
|
2664
|
+
{ kind: "pgpassword-env", regex: /\b(PGPASSWORD)=([^\s"']{4,200})/g },
|
|
2665
|
+
// JDBC/PG/MySQL/Mongo connection strings with inline credentials
|
|
2666
|
+
// postgresql://user:pass@host/db → redact pass
|
|
2667
|
+
{ kind: "db-uri-password", regex: /(\b(?:postgres(?:ql)?|mysql|mongodb(?:\+srv)?|redis|amqp|mssql):\/\/[^:\s]+:)([^@\s]+)(@)/gi },
|
|
2668
|
+
// Anthropic API keys
|
|
2669
|
+
{ kind: "anthropic-key", regex: /(sk-ant-[a-zA-Z0-9_-]{90,})/g },
|
|
2670
|
+
// OpenAI / generic sk- keys — requires length ≥32 to avoid eating short identifiers
|
|
2671
|
+
{ kind: "openai-key", regex: /(sk-(?:proj-)?[a-zA-Z0-9_-]{32,})/g },
|
|
2672
|
+
// GitHub personal access tokens
|
|
2673
|
+
{ kind: "github-pat", regex: /\b(ghp_[a-zA-Z0-9]{36})\b/g },
|
|
2674
|
+
{ kind: "github-oauth", regex: /\b(gho_[a-zA-Z0-9]{36})\b/g },
|
|
2675
|
+
{ kind: "github-install", regex: /\b(ghs_[a-zA-Z0-9]{36})\b/g },
|
|
2676
|
+
// Slack tokens
|
|
2677
|
+
{ kind: "slack-bot", regex: /\b(xoxb-\d+-\d+-[a-zA-Z0-9]+)\b/g },
|
|
2678
|
+
{ kind: "slack-user", regex: /\b(xoxp-\d+-\d+-\d+-[a-zA-Z0-9]+)\b/g },
|
|
2679
|
+
// AWS access key IDs (AKIA...) and secret access keys are context-dependent;
|
|
2680
|
+
// we only catch the ID because secret key alone is indistinguishable from random base64.
|
|
2681
|
+
{ kind: "aws-access-key-id", regex: /\b(AKIA[0-9A-Z]{16})\b/g },
|
|
2682
|
+
// Google API keys
|
|
2683
|
+
{ kind: "google-api-key", regex: /\b(AIza[0-9A-Za-z_-]{35})\b/g },
|
|
2684
|
+
// Generic "api_key": "..." / "apiKey": "..." / api-key=xxx
|
|
2685
|
+
{ kind: "api-key", regex: /\b(api[_-]?key)\s*[:=]\s*["']?([a-zA-Z0-9_\-.]{16,200})["']?/gi },
|
|
2686
|
+
// Generic token: xxx (only when value looks token-shaped; avoids eating human prose)
|
|
2687
|
+
{ kind: "token", regex: /\b(token|access[_-]?token|bearer[_-]?token)\s*[:=]\s*["']?([a-zA-Z0-9_\-.]{20,300})["']?/gi },
|
|
2688
|
+
// Bearer <token> in Authorization headers
|
|
2689
|
+
{ kind: "bearer", regex: /\b(Authorization:\s*Bearer\s+)([a-zA-Z0-9_\-.=]{20,500})/g },
|
|
2690
|
+
// Private key PEM blocks — catch the header+footer together
|
|
2691
|
+
{ kind: "private-key", regex: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g }
|
|
2692
|
+
];
|
|
2693
|
+
function render(placeholder, kind) {
|
|
2694
|
+
return placeholder.replace("{kind}", kind);
|
|
2695
|
+
}
|
|
2696
|
+
function redactString(input, options) {
|
|
2697
|
+
if (!options.enabled || !input) return { redacted: input, hits: [] };
|
|
2698
|
+
const placeholder = options.placeholder ?? "[REDACTED:{kind}]";
|
|
2699
|
+
const patterns = [
|
|
2700
|
+
...options.patterns ?? DEFAULT_PATTERNS,
|
|
2701
|
+
...(options.customRegexes ?? []).flatMap((src, i) => {
|
|
2702
|
+
try {
|
|
2703
|
+
const flags = src.match(/^\/.*\/([gimsuy]*)$/)?.[1] ?? "";
|
|
2704
|
+
const body = src.replace(/^\/(.*)\/[gimsuy]*$/, "$1");
|
|
2705
|
+
const regex = new RegExp(body, flags.includes("g") ? flags : flags + "g");
|
|
2706
|
+
return [{ kind: `custom-${i}`, regex }];
|
|
2707
|
+
} catch {
|
|
2708
|
+
return [];
|
|
2709
|
+
}
|
|
2710
|
+
})
|
|
2711
|
+
];
|
|
2712
|
+
let redacted = input;
|
|
2713
|
+
const hits = [];
|
|
2714
|
+
for (const { kind, regex } of patterns) {
|
|
2715
|
+
const rx = new RegExp(regex.source, regex.flags);
|
|
2716
|
+
redacted = redacted.replace(rx, (...args) => {
|
|
2717
|
+
const match = args[0];
|
|
2718
|
+
const probe = new RegExp(rx.source).exec(match);
|
|
2719
|
+
const captureCount = probe ? probe.length - 1 : 0;
|
|
2720
|
+
const g1 = captureCount >= 1 ? args[1] : void 0;
|
|
2721
|
+
const g2 = captureCount >= 2 ? args[2] : void 0;
|
|
2722
|
+
const offset = args[1 + captureCount];
|
|
2723
|
+
if (captureCount >= 2 && typeof g2 === "string") {
|
|
2724
|
+
hits.push({ kind, start: offset + (g1?.length ?? 0), length: g2.length, secret: g2 });
|
|
2725
|
+
return `${g1}${render(placeholder, kind)}`;
|
|
2726
|
+
}
|
|
2727
|
+
hits.push({ kind, start: offset, length: match.length, secret: g1 ?? match });
|
|
2728
|
+
return render(placeholder, kind);
|
|
2729
|
+
});
|
|
2730
|
+
}
|
|
2731
|
+
return { redacted, hits };
|
|
2732
|
+
}
|
|
2733
|
+
function redactJson(value, options) {
|
|
2734
|
+
if (!options.enabled) return { value, hits: [] };
|
|
2735
|
+
const allHits = [];
|
|
2736
|
+
function walk(v) {
|
|
2737
|
+
if (typeof v === "string") {
|
|
2738
|
+
const r = redactString(v, options);
|
|
2739
|
+
allHits.push(...r.hits);
|
|
2740
|
+
return r.redacted;
|
|
2741
|
+
}
|
|
2742
|
+
if (Array.isArray(v)) return v.map(walk);
|
|
2743
|
+
if (v && typeof v === "object") {
|
|
2744
|
+
const out = {};
|
|
2745
|
+
for (const [k, vv] of Object.entries(v)) {
|
|
2746
|
+
out[k] = walk(vv);
|
|
2747
|
+
}
|
|
2748
|
+
return out;
|
|
2749
|
+
}
|
|
2750
|
+
return v;
|
|
2751
|
+
}
|
|
2752
|
+
const redacted = walk(value);
|
|
2753
|
+
return { value: redacted, hits: allHits };
|
|
2754
|
+
}
|
|
2755
|
+
function scanString(input, options) {
|
|
2756
|
+
const { hits } = redactString(input, { ...options, enabled: true });
|
|
2757
|
+
return hits;
|
|
2758
|
+
}
|
|
2759
|
+
|
|
2658
2760
|
// src/session/session-manager.ts
|
|
2659
2761
|
function safeDate(value) {
|
|
2660
2762
|
const d = new Date(value);
|
|
@@ -2668,9 +2770,27 @@ function extractJsonField(header, field) {
|
|
|
2668
2770
|
var SessionManager = class {
|
|
2669
2771
|
_current = null;
|
|
2670
2772
|
historyDir;
|
|
2773
|
+
config;
|
|
2774
|
+
/** Last save's redaction hit count — exposed for /security status reporting */
|
|
2775
|
+
lastRedactionHits = 0;
|
|
2671
2776
|
constructor(config) {
|
|
2777
|
+
this.config = config;
|
|
2672
2778
|
this.historyDir = config.getHistoryDir();
|
|
2673
2779
|
}
|
|
2780
|
+
/**
|
|
2781
|
+
* Build redaction options from config. Returns `{ enabled: false }` when
|
|
2782
|
+
* `security.redactOnSave` is off or `security.mode` is 'off'.
|
|
2783
|
+
*/
|
|
2784
|
+
redactOptionsForSave() {
|
|
2785
|
+
const security = this.config.get("security");
|
|
2786
|
+
if (!security || !security.redactOnSave || security.mode === "off") {
|
|
2787
|
+
return { enabled: false };
|
|
2788
|
+
}
|
|
2789
|
+
return {
|
|
2790
|
+
enabled: true,
|
|
2791
|
+
customRegexes: security.customPatterns ?? []
|
|
2792
|
+
};
|
|
2793
|
+
}
|
|
2674
2794
|
get current() {
|
|
2675
2795
|
return this._current;
|
|
2676
2796
|
}
|
|
@@ -2696,8 +2816,12 @@ var SessionManager = class {
|
|
|
2696
2816
|
if (!this._current) return;
|
|
2697
2817
|
mkdirSync(this.historyDir, { recursive: true });
|
|
2698
2818
|
const filePath = join(this.historyDir, `${this._current.id}.json`);
|
|
2819
|
+
const raw = this._current.toJSON();
|
|
2820
|
+
const opts = this.redactOptionsForSave();
|
|
2821
|
+
const { value: payload, hits } = redactJson(raw, opts);
|
|
2822
|
+
this.lastRedactionHits = hits.length;
|
|
2699
2823
|
const tmpPath = filePath + ".tmp";
|
|
2700
|
-
writeFileSync(tmpPath, JSON.stringify(
|
|
2824
|
+
writeFileSync(tmpPath, JSON.stringify(payload, null, 2), "utf-8");
|
|
2701
2825
|
renameSync(tmpPath, filePath);
|
|
2702
2826
|
}
|
|
2703
2827
|
loadSession(id) {
|
|
@@ -3975,6 +4099,8 @@ export {
|
|
|
3975
4099
|
buildPhantomCorrectionMessage,
|
|
3976
4100
|
ProviderRegistry,
|
|
3977
4101
|
getContentText,
|
|
4102
|
+
DEFAULT_PATTERNS,
|
|
4103
|
+
scanString,
|
|
3978
4104
|
SessionManager,
|
|
3979
4105
|
getGitRoot,
|
|
3980
4106
|
getGitContext,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
CONFIG_FILE_NAME,
|
|
9
9
|
HISTORY_DIR_NAME,
|
|
10
10
|
PLUGINS_DIR_NAME
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-VGXNE37B.js";
|
|
12
12
|
|
|
13
13
|
// src/config/config-manager.ts
|
|
14
14
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
@@ -179,6 +179,24 @@ var ConfigSchema = z.object({
|
|
|
179
179
|
// 必须确认插件来源可信后,再设为 true 启用。
|
|
180
180
|
// 可通过 /config 命令或直接编辑 ~/.aicli/config.json 开启。
|
|
181
181
|
allowPlugins: z.boolean().default(false),
|
|
182
|
+
// 敏感信息脱敏(v0.4.88+,2026-04 凭据泄漏事件后引入)
|
|
183
|
+
// 会话保存到磁盘 / 发送给 Provider 前,自动将 API key、密码、PEM 私钥等
|
|
184
|
+
// 按正则替换为 [REDACTED:kind] 占位符。模式定义在 src/security/redactor.ts。
|
|
185
|
+
//
|
|
186
|
+
// redactOnSave 默认 true:保存到 ~/.aicli/history/*.json 时脱敏(推荐开启)
|
|
187
|
+
// redactOnSend 默认 false:发送到 Provider 时脱敏(激进,可能影响工具结果)
|
|
188
|
+
// mode:
|
|
189
|
+
// 'default' — 使用内置 13 条模式(推荐)
|
|
190
|
+
// 'strict' — 同 default,但阈值更低(更激进,可能误报)
|
|
191
|
+
// 'off' — 禁用所有模式(等同 redactOnSave=false)
|
|
192
|
+
// customPatterns — 用户补充正则字符串(支持 /pattern/flags 形式),
|
|
193
|
+
// 无效正则会静默跳过,不会中断保存。
|
|
194
|
+
security: z.object({
|
|
195
|
+
redactOnSave: z.boolean().default(true),
|
|
196
|
+
redactOnSend: z.boolean().default(false),
|
|
197
|
+
mode: z.enum(["default", "strict", "off"]).default("default"),
|
|
198
|
+
customPatterns: z.array(z.string()).default([])
|
|
199
|
+
}).default({}),
|
|
182
200
|
// 智能模型路由(v0.4.68+)
|
|
183
201
|
// 按用户每轮输入的内容/标签/长度动态选择模型,在同一 provider 内切换,
|
|
184
202
|
// 例:短问题走 haiku(省钱),planning 走 opus(质量)。
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
} from "./chunk-6VRJGH25.js";
|
|
20
20
|
import {
|
|
21
21
|
runTestsTool
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-V3NMERIB.js";
|
|
23
23
|
import {
|
|
24
24
|
CONFIG_DIR_NAME,
|
|
25
25
|
DEFAULT_MAX_TOOL_OUTPUT_CHARS_CAP,
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
SUBAGENT_ALLOWED_TOOLS,
|
|
28
28
|
SUBAGENT_DEFAULT_MAX_ROUNDS,
|
|
29
29
|
SUBAGENT_MAX_ROUNDS_LIMIT
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-VGXNE37B.js";
|
|
31
31
|
|
|
32
32
|
// src/tools/types.ts
|
|
33
33
|
function isFileWriteTool(name) {
|
package/dist/electron-server.js
CHANGED
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
VERSION,
|
|
37
37
|
buildUserIdentityPrompt,
|
|
38
38
|
runTestsTool
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-P6EQZKKG.js";
|
|
40
40
|
import {
|
|
41
41
|
hasSemanticIndex,
|
|
42
42
|
semanticSearch
|
|
@@ -223,6 +223,24 @@ var ConfigSchema = z.object({
|
|
|
223
223
|
// 必须确认插件来源可信后,再设为 true 启用。
|
|
224
224
|
// 可通过 /config 命令或直接编辑 ~/.aicli/config.json 开启。
|
|
225
225
|
allowPlugins: z.boolean().default(false),
|
|
226
|
+
// 敏感信息脱敏(v0.4.88+,2026-04 凭据泄漏事件后引入)
|
|
227
|
+
// 会话保存到磁盘 / 发送给 Provider 前,自动将 API key、密码、PEM 私钥等
|
|
228
|
+
// 按正则替换为 [REDACTED:kind] 占位符。模式定义在 src/security/redactor.ts。
|
|
229
|
+
//
|
|
230
|
+
// redactOnSave 默认 true:保存到 ~/.aicli/history/*.json 时脱敏(推荐开启)
|
|
231
|
+
// redactOnSend 默认 false:发送到 Provider 时脱敏(激进,可能影响工具结果)
|
|
232
|
+
// mode:
|
|
233
|
+
// 'default' — 使用内置 13 条模式(推荐)
|
|
234
|
+
// 'strict' — 同 default,但阈值更低(更激进,可能误报)
|
|
235
|
+
// 'off' — 禁用所有模式(等同 redactOnSave=false)
|
|
236
|
+
// customPatterns — 用户补充正则字符串(支持 /pattern/flags 形式),
|
|
237
|
+
// 无效正则会静默跳过,不会中断保存。
|
|
238
|
+
security: z.object({
|
|
239
|
+
redactOnSave: z.boolean().default(true),
|
|
240
|
+
redactOnSend: z.boolean().default(false),
|
|
241
|
+
mode: z.enum(["default", "strict", "off"]).default("default"),
|
|
242
|
+
customPatterns: z.array(z.string()).default([])
|
|
243
|
+
}).default({}),
|
|
226
244
|
// 智能模型路由(v0.4.68+)
|
|
227
245
|
// 按用户每轮输入的内容/标签/长度动态选择模型,在同一 provider 内切换,
|
|
228
246
|
// 例:短问题走 haiku(省钱),planning 走 opus(质量)。
|
|
@@ -3036,6 +3054,104 @@ var Session = class _Session {
|
|
|
3036
3054
|
}
|
|
3037
3055
|
};
|
|
3038
3056
|
|
|
3057
|
+
// src/security/redactor.ts
|
|
3058
|
+
var DEFAULT_PATTERNS = [
|
|
3059
|
+
// password: xxx / password = xxx / password="xxx"
|
|
3060
|
+
// Covers YAML / JSON / shell-ish / env-file forms.
|
|
3061
|
+
{ kind: "password", regex: /\b(password|passwd|pwd)\s*[:=]\s*["']?([^\s"',;{}]{4,200})["']?/gi },
|
|
3062
|
+
// PGPASSWORD=xxx (explicit bash env-var form, separate rule because no quotes usually)
|
|
3063
|
+
{ kind: "pgpassword-env", regex: /\b(PGPASSWORD)=([^\s"']{4,200})/g },
|
|
3064
|
+
// JDBC/PG/MySQL/Mongo connection strings with inline credentials
|
|
3065
|
+
// postgresql://user:pass@host/db → redact pass
|
|
3066
|
+
{ kind: "db-uri-password", regex: /(\b(?:postgres(?:ql)?|mysql|mongodb(?:\+srv)?|redis|amqp|mssql):\/\/[^:\s]+:)([^@\s]+)(@)/gi },
|
|
3067
|
+
// Anthropic API keys
|
|
3068
|
+
{ kind: "anthropic-key", regex: /(sk-ant-[a-zA-Z0-9_-]{90,})/g },
|
|
3069
|
+
// OpenAI / generic sk- keys — requires length ≥32 to avoid eating short identifiers
|
|
3070
|
+
{ kind: "openai-key", regex: /(sk-(?:proj-)?[a-zA-Z0-9_-]{32,})/g },
|
|
3071
|
+
// GitHub personal access tokens
|
|
3072
|
+
{ kind: "github-pat", regex: /\b(ghp_[a-zA-Z0-9]{36})\b/g },
|
|
3073
|
+
{ kind: "github-oauth", regex: /\b(gho_[a-zA-Z0-9]{36})\b/g },
|
|
3074
|
+
{ kind: "github-install", regex: /\b(ghs_[a-zA-Z0-9]{36})\b/g },
|
|
3075
|
+
// Slack tokens
|
|
3076
|
+
{ kind: "slack-bot", regex: /\b(xoxb-\d+-\d+-[a-zA-Z0-9]+)\b/g },
|
|
3077
|
+
{ kind: "slack-user", regex: /\b(xoxp-\d+-\d+-\d+-[a-zA-Z0-9]+)\b/g },
|
|
3078
|
+
// AWS access key IDs (AKIA...) and secret access keys are context-dependent;
|
|
3079
|
+
// we only catch the ID because secret key alone is indistinguishable from random base64.
|
|
3080
|
+
{ kind: "aws-access-key-id", regex: /\b(AKIA[0-9A-Z]{16})\b/g },
|
|
3081
|
+
// Google API keys
|
|
3082
|
+
{ kind: "google-api-key", regex: /\b(AIza[0-9A-Za-z_-]{35})\b/g },
|
|
3083
|
+
// Generic "api_key": "..." / "apiKey": "..." / api-key=xxx
|
|
3084
|
+
{ kind: "api-key", regex: /\b(api[_-]?key)\s*[:=]\s*["']?([a-zA-Z0-9_\-.]{16,200})["']?/gi },
|
|
3085
|
+
// Generic token: xxx (only when value looks token-shaped; avoids eating human prose)
|
|
3086
|
+
{ kind: "token", regex: /\b(token|access[_-]?token|bearer[_-]?token)\s*[:=]\s*["']?([a-zA-Z0-9_\-.]{20,300})["']?/gi },
|
|
3087
|
+
// Bearer <token> in Authorization headers
|
|
3088
|
+
{ kind: "bearer", regex: /\b(Authorization:\s*Bearer\s+)([a-zA-Z0-9_\-.=]{20,500})/g },
|
|
3089
|
+
// Private key PEM blocks — catch the header+footer together
|
|
3090
|
+
{ kind: "private-key", regex: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g }
|
|
3091
|
+
];
|
|
3092
|
+
function render(placeholder, kind) {
|
|
3093
|
+
return placeholder.replace("{kind}", kind);
|
|
3094
|
+
}
|
|
3095
|
+
function redactString(input, options) {
|
|
3096
|
+
if (!options.enabled || !input) return { redacted: input, hits: [] };
|
|
3097
|
+
const placeholder = options.placeholder ?? "[REDACTED:{kind}]";
|
|
3098
|
+
const patterns = [
|
|
3099
|
+
...options.patterns ?? DEFAULT_PATTERNS,
|
|
3100
|
+
...(options.customRegexes ?? []).flatMap((src, i) => {
|
|
3101
|
+
try {
|
|
3102
|
+
const flags = src.match(/^\/.*\/([gimsuy]*)$/)?.[1] ?? "";
|
|
3103
|
+
const body = src.replace(/^\/(.*)\/[gimsuy]*$/, "$1");
|
|
3104
|
+
const regex = new RegExp(body, flags.includes("g") ? flags : flags + "g");
|
|
3105
|
+
return [{ kind: `custom-${i}`, regex }];
|
|
3106
|
+
} catch {
|
|
3107
|
+
return [];
|
|
3108
|
+
}
|
|
3109
|
+
})
|
|
3110
|
+
];
|
|
3111
|
+
let redacted = input;
|
|
3112
|
+
const hits = [];
|
|
3113
|
+
for (const { kind, regex } of patterns) {
|
|
3114
|
+
const rx = new RegExp(regex.source, regex.flags);
|
|
3115
|
+
redacted = redacted.replace(rx, (...args) => {
|
|
3116
|
+
const match = args[0];
|
|
3117
|
+
const probe = new RegExp(rx.source).exec(match);
|
|
3118
|
+
const captureCount = probe ? probe.length - 1 : 0;
|
|
3119
|
+
const g1 = captureCount >= 1 ? args[1] : void 0;
|
|
3120
|
+
const g2 = captureCount >= 2 ? args[2] : void 0;
|
|
3121
|
+
const offset = args[1 + captureCount];
|
|
3122
|
+
if (captureCount >= 2 && typeof g2 === "string") {
|
|
3123
|
+
hits.push({ kind, start: offset + (g1?.length ?? 0), length: g2.length, secret: g2 });
|
|
3124
|
+
return `${g1}${render(placeholder, kind)}`;
|
|
3125
|
+
}
|
|
3126
|
+
hits.push({ kind, start: offset, length: match.length, secret: g1 ?? match });
|
|
3127
|
+
return render(placeholder, kind);
|
|
3128
|
+
});
|
|
3129
|
+
}
|
|
3130
|
+
return { redacted, hits };
|
|
3131
|
+
}
|
|
3132
|
+
function redactJson(value, options) {
|
|
3133
|
+
if (!options.enabled) return { value, hits: [] };
|
|
3134
|
+
const allHits = [];
|
|
3135
|
+
function walk(v) {
|
|
3136
|
+
if (typeof v === "string") {
|
|
3137
|
+
const r = redactString(v, options);
|
|
3138
|
+
allHits.push(...r.hits);
|
|
3139
|
+
return r.redacted;
|
|
3140
|
+
}
|
|
3141
|
+
if (Array.isArray(v)) return v.map(walk);
|
|
3142
|
+
if (v && typeof v === "object") {
|
|
3143
|
+
const out = {};
|
|
3144
|
+
for (const [k, vv] of Object.entries(v)) {
|
|
3145
|
+
out[k] = walk(vv);
|
|
3146
|
+
}
|
|
3147
|
+
return out;
|
|
3148
|
+
}
|
|
3149
|
+
return v;
|
|
3150
|
+
}
|
|
3151
|
+
const redacted = walk(value);
|
|
3152
|
+
return { value: redacted, hits: allHits };
|
|
3153
|
+
}
|
|
3154
|
+
|
|
3039
3155
|
// src/session/session-manager.ts
|
|
3040
3156
|
function safeDate(value) {
|
|
3041
3157
|
const d = new Date(value);
|
|
@@ -3049,9 +3165,27 @@ function extractJsonField(header, field) {
|
|
|
3049
3165
|
var SessionManager = class {
|
|
3050
3166
|
_current = null;
|
|
3051
3167
|
historyDir;
|
|
3168
|
+
config;
|
|
3169
|
+
/** Last save's redaction hit count — exposed for /security status reporting */
|
|
3170
|
+
lastRedactionHits = 0;
|
|
3052
3171
|
constructor(config) {
|
|
3172
|
+
this.config = config;
|
|
3053
3173
|
this.historyDir = config.getHistoryDir();
|
|
3054
3174
|
}
|
|
3175
|
+
/**
|
|
3176
|
+
* Build redaction options from config. Returns `{ enabled: false }` when
|
|
3177
|
+
* `security.redactOnSave` is off or `security.mode` is 'off'.
|
|
3178
|
+
*/
|
|
3179
|
+
redactOptionsForSave() {
|
|
3180
|
+
const security = this.config.get("security");
|
|
3181
|
+
if (!security || !security.redactOnSave || security.mode === "off") {
|
|
3182
|
+
return { enabled: false };
|
|
3183
|
+
}
|
|
3184
|
+
return {
|
|
3185
|
+
enabled: true,
|
|
3186
|
+
customRegexes: security.customPatterns ?? []
|
|
3187
|
+
};
|
|
3188
|
+
}
|
|
3055
3189
|
get current() {
|
|
3056
3190
|
return this._current;
|
|
3057
3191
|
}
|
|
@@ -3077,8 +3211,12 @@ var SessionManager = class {
|
|
|
3077
3211
|
if (!this._current) return;
|
|
3078
3212
|
mkdirSync2(this.historyDir, { recursive: true });
|
|
3079
3213
|
const filePath = join2(this.historyDir, `${this._current.id}.json`);
|
|
3214
|
+
const raw = this._current.toJSON();
|
|
3215
|
+
const opts = this.redactOptionsForSave();
|
|
3216
|
+
const { value: payload, hits } = redactJson(raw, opts);
|
|
3217
|
+
this.lastRedactionHits = hits.length;
|
|
3080
3218
|
const tmpPath = filePath + ".tmp";
|
|
3081
|
-
writeFileSync2(tmpPath, JSON.stringify(
|
|
3219
|
+
writeFileSync2(tmpPath, JSON.stringify(payload, null, 2), "utf-8");
|
|
3082
3220
|
renameSync(tmpPath, filePath);
|
|
3083
3221
|
}
|
|
3084
3222
|
loadSession(id) {
|
|
@@ -11108,7 +11246,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
11108
11246
|
case "test": {
|
|
11109
11247
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
11110
11248
|
try {
|
|
11111
|
-
const { executeTests } = await import("./run-tests-
|
|
11249
|
+
const { executeTests } = await import("./run-tests-JVWIGY7P.js");
|
|
11112
11250
|
const argStr = args.join(" ").trim();
|
|
11113
11251
|
let testArgs = {};
|
|
11114
11252
|
if (argStr) {
|
|
@@ -385,7 +385,7 @@ ${content}`);
|
|
|
385
385
|
}
|
|
386
386
|
}
|
|
387
387
|
async function runTaskMode(config, providers, configManager, topic) {
|
|
388
|
-
const { TaskOrchestrator } = await import("./task-orchestrator-
|
|
388
|
+
const { TaskOrchestrator } = await import("./task-orchestrator-6MI6LD7T.js");
|
|
389
389
|
const orchestrator = new TaskOrchestrator(config, providers, configManager);
|
|
390
390
|
let interrupted = false;
|
|
391
391
|
const onSigint = () => {
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
DEFAULT_PATTERNS,
|
|
3
4
|
HALLUCINATION_CORRECTION_MESSAGE,
|
|
4
5
|
McpManager,
|
|
5
6
|
ProviderRegistry,
|
|
@@ -28,12 +29,13 @@ import {
|
|
|
28
29
|
persistToolRound,
|
|
29
30
|
rebuildExtraMessages,
|
|
30
31
|
saveDevState,
|
|
32
|
+
scanString,
|
|
31
33
|
sessionHasMeaningfulContent,
|
|
32
34
|
setupProxy
|
|
33
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-L3MBIO36.js";
|
|
34
36
|
import {
|
|
35
37
|
ConfigManager
|
|
36
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-QT2KNL3V.js";
|
|
37
39
|
import {
|
|
38
40
|
ToolExecutor,
|
|
39
41
|
ToolRegistry,
|
|
@@ -49,7 +51,7 @@ import {
|
|
|
49
51
|
spawnAgentContext,
|
|
50
52
|
theme,
|
|
51
53
|
undoStack
|
|
52
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-YDHIU24C.js";
|
|
53
55
|
import "./chunk-2ZD3YTVM.js";
|
|
54
56
|
import {
|
|
55
57
|
fileCheckpoints
|
|
@@ -58,7 +60,7 @@ import "./chunk-NHNWUBXB.js";
|
|
|
58
60
|
import "./chunk-CQQQFNND.js";
|
|
59
61
|
import "./chunk-6VRJGH25.js";
|
|
60
62
|
import "./chunk-PFYAAX2S.js";
|
|
61
|
-
import "./chunk-
|
|
63
|
+
import "./chunk-V3NMERIB.js";
|
|
62
64
|
import {
|
|
63
65
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
64
66
|
AUTHOR,
|
|
@@ -80,7 +82,7 @@ import {
|
|
|
80
82
|
SKILLS_DIR_NAME,
|
|
81
83
|
VERSION,
|
|
82
84
|
buildUserIdentityPrompt
|
|
83
|
-
} from "./chunk-
|
|
85
|
+
} from "./chunk-VGXNE37B.js";
|
|
84
86
|
|
|
85
87
|
// src/index.ts
|
|
86
88
|
import { program } from "commander";
|
|
@@ -980,6 +982,7 @@ function createDefaultCommands() {
|
|
|
980
982
|
" /fork [checkpoint] - Fork session from checkpoint or current position",
|
|
981
983
|
" /branch [list|new|switch|delete|rename|diff|cherry-pick] - Manage conversation branches (fork tree, cross-branch picks)",
|
|
982
984
|
" /index [status|rebuild|clear|semantic-rebuild|semantic-clear] - Symbol + semantic index (find_symbol / search_code)",
|
|
985
|
+
" /security [status|scan|on|off] - Sensitive-data redaction status & session scan",
|
|
983
986
|
" /yolo [on|off] - Toggle session auto-approve (skip confirmations)",
|
|
984
987
|
" /exit - Exit"
|
|
985
988
|
] : [];
|
|
@@ -2592,7 +2595,7 @@ ${hint}` : "")
|
|
|
2592
2595
|
usage: "/test [command|filter]",
|
|
2593
2596
|
async execute(args, ctx) {
|
|
2594
2597
|
try {
|
|
2595
|
-
const { executeTests } = await import("./run-tests-
|
|
2598
|
+
const { executeTests } = await import("./run-tests-FQHDUYOG.js");
|
|
2596
2599
|
const argStr = args.join(" ").trim();
|
|
2597
2600
|
let testArgs = {};
|
|
2598
2601
|
if (argStr) {
|
|
@@ -3031,6 +3034,94 @@ Summary: ${fileMap.size} file(s) \u2014 ${newFiles} new, ${modifiedFiles} modifi
|
|
|
3031
3034
|
}
|
|
3032
3035
|
}
|
|
3033
3036
|
},
|
|
3037
|
+
{
|
|
3038
|
+
name: "security",
|
|
3039
|
+
description: "Sensitive-data redaction \u2014 status, scan sessions, toggle on/off",
|
|
3040
|
+
usage: "/security [status|scan [--all]|on|off]",
|
|
3041
|
+
async execute(args, ctx) {
|
|
3042
|
+
const sub = (args[0] || "status").toLowerCase();
|
|
3043
|
+
const security = ctx.config.get("security") ?? {
|
|
3044
|
+
redactOnSave: true,
|
|
3045
|
+
redactOnSend: false,
|
|
3046
|
+
mode: "default",
|
|
3047
|
+
customPatterns: []
|
|
3048
|
+
};
|
|
3049
|
+
if (sub === "status") {
|
|
3050
|
+
console.log(theme.heading(" \u{1F6E1} Security / Redaction"));
|
|
3051
|
+
console.log(` redactOnSave : ${security.redactOnSave ? theme.success("on") : theme.warning("off")}`);
|
|
3052
|
+
console.log(` redactOnSend : ${security.redactOnSend ? theme.success("on") : theme.dim("off")}`);
|
|
3053
|
+
console.log(` mode : ${security.mode}`);
|
|
3054
|
+
console.log(` patterns : ${DEFAULT_PATTERNS.length} built-in + ${security.customPatterns?.length ?? 0} custom`);
|
|
3055
|
+
console.log(` last save : ${ctx.sessions.lastRedactionHits} hit(s) redacted`);
|
|
3056
|
+
console.log();
|
|
3057
|
+
console.log(theme.dim(" /security scan \u2014 scan current session for leaks"));
|
|
3058
|
+
console.log(theme.dim(" /security scan --all \u2014 scan all saved sessions"));
|
|
3059
|
+
console.log(theme.dim(" /security on|off \u2014 toggle redactOnSave"));
|
|
3060
|
+
console.log();
|
|
3061
|
+
return;
|
|
3062
|
+
}
|
|
3063
|
+
if (sub === "on" || sub === "off") {
|
|
3064
|
+
ctx.config.set("security", { ...security, redactOnSave: sub === "on" });
|
|
3065
|
+
console.log(theme.success(` \u2713 redactOnSave = ${sub}`));
|
|
3066
|
+
console.log();
|
|
3067
|
+
return;
|
|
3068
|
+
}
|
|
3069
|
+
if (sub === "scan") {
|
|
3070
|
+
const scanAll = args.includes("--all");
|
|
3071
|
+
const opts = { customRegexes: security.customPatterns ?? [] };
|
|
3072
|
+
let totalHits = 0;
|
|
3073
|
+
let filesWithHits = 0;
|
|
3074
|
+
if (scanAll) {
|
|
3075
|
+
const metas = ctx.sessions.listSessions();
|
|
3076
|
+
console.log(theme.info(` Scanning ${metas.length} session(s)\u2026`));
|
|
3077
|
+
const { readFileSync: readFileSync5 } = await import("fs");
|
|
3078
|
+
const { join: join6 } = await import("path");
|
|
3079
|
+
const historyDir = ctx.config.getHistoryDir();
|
|
3080
|
+
for (const m of metas) {
|
|
3081
|
+
try {
|
|
3082
|
+
const content = readFileSync5(join6(historyDir, `${m.id}.json`), "utf-8");
|
|
3083
|
+
const hits2 = scanString(content, opts);
|
|
3084
|
+
if (hits2.length) {
|
|
3085
|
+
filesWithHits++;
|
|
3086
|
+
totalHits += hits2.length;
|
|
3087
|
+
const kinds = [...new Set(hits2.map((h) => h.kind))].join(", ");
|
|
3088
|
+
console.log(` ${theme.warning("\u26A0")} ${m.id.slice(0, 8)}\u2026 ${theme.dim(m.title || "")} \u2014 ${hits2.length} hit(s) [${kinds}]`);
|
|
3089
|
+
}
|
|
3090
|
+
} catch {
|
|
3091
|
+
}
|
|
3092
|
+
}
|
|
3093
|
+
console.log();
|
|
3094
|
+
console.log(
|
|
3095
|
+
totalHits === 0 ? theme.success(` \u2713 No secrets found in ${metas.length} session(s).`) : theme.warning(` Found ${totalHits} hit(s) across ${filesWithHits} session(s). Re-save them with redactOnSave=on to sanitize.`)
|
|
3096
|
+
);
|
|
3097
|
+
console.log();
|
|
3098
|
+
return;
|
|
3099
|
+
}
|
|
3100
|
+
const current = ctx.sessions.current;
|
|
3101
|
+
if (!current) {
|
|
3102
|
+
console.log(theme.warning(" No active session to scan."));
|
|
3103
|
+
console.log();
|
|
3104
|
+
return;
|
|
3105
|
+
}
|
|
3106
|
+
const json = JSON.stringify(current.toJSON());
|
|
3107
|
+
const hits = scanString(json, opts);
|
|
3108
|
+
if (hits.length === 0) {
|
|
3109
|
+
console.log(theme.success(" \u2713 Current session: no secrets detected."));
|
|
3110
|
+
} else {
|
|
3111
|
+
const byKind = /* @__PURE__ */ new Map();
|
|
3112
|
+
for (const h of hits) byKind.set(h.kind, (byKind.get(h.kind) ?? 0) + 1);
|
|
3113
|
+
console.log(theme.warning(` \u26A0 Current session: ${hits.length} hit(s)`));
|
|
3114
|
+
for (const [k, n] of byKind) console.log(` \u2022 ${k}: ${n}`);
|
|
3115
|
+
console.log(theme.dim(" (save the session to replace them with placeholders)"));
|
|
3116
|
+
}
|
|
3117
|
+
console.log();
|
|
3118
|
+
return;
|
|
3119
|
+
}
|
|
3120
|
+
console.log(theme.error(` Unknown subcommand: ${sub}`));
|
|
3121
|
+
console.log(theme.dim(" Usage: /security [status|scan [--all]|on|off]"));
|
|
3122
|
+
console.log();
|
|
3123
|
+
}
|
|
3124
|
+
},
|
|
3034
3125
|
{
|
|
3035
3126
|
name: "yolo",
|
|
3036
3127
|
description: "Toggle session auto-approve (skip all confirmations)",
|
|
@@ -6485,7 +6576,7 @@ program.command("web").description("Start Web UI server with browser-based chat
|
|
|
6485
6576
|
console.error("Error: Invalid port number. Must be between 1 and 65535.");
|
|
6486
6577
|
process.exit(1);
|
|
6487
6578
|
}
|
|
6488
|
-
const { startWebServer } = await import("./server-
|
|
6579
|
+
const { startWebServer } = await import("./server-UWKRV5DK.js");
|
|
6489
6580
|
await startWebServer({ port, host: options.host });
|
|
6490
6581
|
});
|
|
6491
6582
|
program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | migrate <name>)").action(async (action, username) => {
|
|
@@ -6608,7 +6699,7 @@ program.command("sessions").description("List recent conversation sessions").act
|
|
|
6608
6699
|
});
|
|
6609
6700
|
program.command("batch <action> [arg] [arg2]").description("Anthropic Message Batches: submit | list | status <id> | results <id> [out] | cancel <id>").option("--dry-run", "Parse and validate input without submitting (submit only)").action(async (action, arg, arg2, options) => {
|
|
6610
6701
|
try {
|
|
6611
|
-
const batch = await import("./batch-
|
|
6702
|
+
const batch = await import("./batch-7XCYSPJU.js");
|
|
6612
6703
|
switch (action) {
|
|
6613
6704
|
case "submit":
|
|
6614
6705
|
if (!arg) {
|
|
@@ -6651,7 +6742,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
|
|
|
6651
6742
|
}
|
|
6652
6743
|
});
|
|
6653
6744
|
program.command("mcp-serve").description("Start an MCP server over STDIO, exposing aicli's built-in tools to Claude Desktop / Cursor / other MCP clients").option("--allow-destructive", "Allow bash / run_interactive / task_create (always destructive in MCP mode)").option("--allow-outside-cwd", "Allow tool path arguments to escape the sandbox root \u2014 disabled by default").option("--tools <list>", "Comma-separated whitelist of tools to expose (default: all eligible tools)").option("--cwd <path>", "Working directory AND sandbox root (default: current directory)").action(async (options) => {
|
|
6654
|
-
const { startMcpServer } = await import("./server-
|
|
6745
|
+
const { startMcpServer } = await import("./server-HTVVWKFN.js");
|
|
6655
6746
|
await startMcpServer({
|
|
6656
6747
|
allowDestructive: !!options.allowDestructive,
|
|
6657
6748
|
allowOutsideCwd: !!options.allowOutsideCwd,
|
|
@@ -6778,7 +6869,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
|
|
|
6778
6869
|
}),
|
|
6779
6870
|
config.get("customProviders")
|
|
6780
6871
|
);
|
|
6781
|
-
const { startHub } = await import("./hub-
|
|
6872
|
+
const { startHub } = await import("./hub-IR4INXSU.js");
|
|
6782
6873
|
await startHub(
|
|
6783
6874
|
{
|
|
6784
6875
|
topic: topic ?? "",
|
|
@@ -3,17 +3,17 @@ import {
|
|
|
3
3
|
ToolRegistry,
|
|
4
4
|
getDangerLevel,
|
|
5
5
|
schemaToJsonSchema
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-YDHIU24C.js";
|
|
7
7
|
import "./chunk-2ZD3YTVM.js";
|
|
8
8
|
import "./chunk-4BKXL7SM.js";
|
|
9
9
|
import "./chunk-NHNWUBXB.js";
|
|
10
10
|
import "./chunk-CQQQFNND.js";
|
|
11
11
|
import "./chunk-6VRJGH25.js";
|
|
12
12
|
import "./chunk-PFYAAX2S.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-V3NMERIB.js";
|
|
14
14
|
import {
|
|
15
15
|
VERSION
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-VGXNE37B.js";
|
|
17
17
|
|
|
18
18
|
// src/mcp/server.ts
|
|
19
19
|
import { createInterface } from "readline";
|
|
@@ -20,10 +20,10 @@ import {
|
|
|
20
20
|
persistToolRound,
|
|
21
21
|
rebuildExtraMessages,
|
|
22
22
|
setupProxy
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-L3MBIO36.js";
|
|
24
24
|
import {
|
|
25
25
|
ConfigManager
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-QT2KNL3V.js";
|
|
27
27
|
import {
|
|
28
28
|
ToolExecutor,
|
|
29
29
|
ToolRegistry,
|
|
@@ -41,14 +41,14 @@ import {
|
|
|
41
41
|
spawnAgentContext,
|
|
42
42
|
truncateOutput,
|
|
43
43
|
undoStack
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-YDHIU24C.js";
|
|
45
45
|
import "./chunk-2ZD3YTVM.js";
|
|
46
46
|
import "./chunk-4BKXL7SM.js";
|
|
47
47
|
import "./chunk-NHNWUBXB.js";
|
|
48
48
|
import "./chunk-CQQQFNND.js";
|
|
49
49
|
import "./chunk-6VRJGH25.js";
|
|
50
50
|
import "./chunk-PFYAAX2S.js";
|
|
51
|
-
import "./chunk-
|
|
51
|
+
import "./chunk-V3NMERIB.js";
|
|
52
52
|
import {
|
|
53
53
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
54
54
|
AUTHOR,
|
|
@@ -67,7 +67,7 @@ import {
|
|
|
67
67
|
SKILLS_DIR_NAME,
|
|
68
68
|
VERSION,
|
|
69
69
|
buildUserIdentityPrompt
|
|
70
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-VGXNE37B.js";
|
|
71
71
|
import {
|
|
72
72
|
AuthManager
|
|
73
73
|
} from "./chunk-BYNY5JPB.js";
|
|
@@ -2229,7 +2229,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
2229
2229
|
case "test": {
|
|
2230
2230
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
2231
2231
|
try {
|
|
2232
|
-
const { executeTests } = await import("./run-tests-
|
|
2232
|
+
const { executeTests } = await import("./run-tests-FQHDUYOG.js");
|
|
2233
2233
|
const argStr = args.join(" ").trim();
|
|
2234
2234
|
let testArgs = {};
|
|
2235
2235
|
if (argStr) {
|
|
@@ -4,17 +4,17 @@ import {
|
|
|
4
4
|
getDangerLevel,
|
|
5
5
|
googleSearchContext,
|
|
6
6
|
truncateOutput
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-YDHIU24C.js";
|
|
8
8
|
import "./chunk-2ZD3YTVM.js";
|
|
9
9
|
import "./chunk-4BKXL7SM.js";
|
|
10
10
|
import "./chunk-NHNWUBXB.js";
|
|
11
11
|
import "./chunk-CQQQFNND.js";
|
|
12
12
|
import "./chunk-6VRJGH25.js";
|
|
13
13
|
import "./chunk-PFYAAX2S.js";
|
|
14
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-V3NMERIB.js";
|
|
15
15
|
import {
|
|
16
16
|
SUBAGENT_ALLOWED_TOOLS
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-VGXNE37B.js";
|
|
18
18
|
|
|
19
19
|
// src/hub/task-orchestrator.ts
|
|
20
20
|
import { createInterface } from "readline";
|