jinzd-ai-cli 0.4.291 → 0.4.293
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-3ADC4W3L.js → batch-3H2X3QHW.js} +2 -2
- package/dist/{chunk-EL3IUHQO.js → chunk-653JBZ6J.js} +1 -1
- package/dist/{chunk-3VV7EXLZ.js → chunk-7XSG2TIU.js} +1 -1
- package/dist/{chunk-T635CMLK.js → chunk-BDXS27DX.js} +1 -1
- package/dist/{chunk-TBR45SMC.js → chunk-C7DVLUZE.js} +1 -1
- package/dist/{chunk-6F3LPG3H.js → chunk-EU4IPUNW.js} +8 -8
- package/dist/{chunk-UVXYEQSL.js → chunk-IZJRDI5E.js} +1 -1
- package/dist/{chunk-OJYAUCYL.js → chunk-OP2GIZFU.js} +1 -1
- package/dist/{chunk-I3XKGEWJ.js → chunk-PL6EEP5B.js} +1 -1
- package/dist/{chunk-S7CZWIOW.js → chunk-QJ4QJUU3.js} +1 -1
- package/dist/{chunk-7R7DN5XE.js → chunk-QKZUWT3S.js} +15 -2
- package/dist/{chunk-6HBNRJVC.js → chunk-S2GDHXBI.js} +4 -4
- package/dist/{chunk-5DRJ3GDE.js → chunk-T56RAP6E.js} +4 -4
- package/dist/{chunk-CWQCAJQC.js → chunk-XFZTFEZZ.js} +5 -5
- package/dist/{chunk-VWNLJ4GL.js → chunk-XHCJJFYO.js} +1 -1
- package/dist/{chunk-TEXT4DAT.js → chunk-Y56UGZPX.js} +68 -68
- package/dist/{ci-K5LN4JKT.js → ci-BYYYDYYC.js} +6 -6
- package/dist/{ci-format-RCB5TGFB.js → ci-format-NXFB37WR.js} +2 -2
- package/dist/{constants-DFQ54TBO.js → constants-MCPEC2GB.js} +1 -1
- package/dist/{constants-VYHOOORA.js → constants-VHZTK4PO.js} +1 -1
- package/dist/{doctor-cli-XOELATBK.js → doctor-cli-4F7DBT5A.js} +6 -6
- package/dist/electron-server.js +24 -11
- package/dist/{hub-33WQ7VWX.js → hub-Y545G6KJ.js} +1 -1
- package/dist/index.js +54 -28
- package/dist/{persistent-memory-DXWLXKAR.js → persistent-memory-V5ZDLPNB.js} +2 -2
- package/dist/{persistent-memory-GJUEX7YU.js → persistent-memory-XTP7BD5C.js} +2 -2
- package/dist/{pr-DQH4NILB.js → pr-4OGJOG2P.js} +6 -6
- package/dist/{run-tests-TBGKOHMH.js → run-tests-5LNNPOSH.js} +2 -2
- package/dist/{run-tests-YA5SSTLH.js → run-tests-XQO4UZFN.js} +2 -2
- package/dist/{server-WNZM63CG.js → server-KXPO46PT.js} +6 -6
- package/dist/{server-SCCVV3AS.js → server-QAFBIQIU.js} +15 -15
- package/dist/{task-orchestrator-W27ZK4MO.js → task-orchestrator-V3F6JQQV.js} +6 -6
- package/dist/{usage-7NFO6LEY.js → usage-MHLWUUWZ.js} +2 -2
- package/package.json +1 -1
package/dist/electron-server.js
CHANGED
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
touchMemoryReferences,
|
|
51
51
|
updateMemoryApproval,
|
|
52
52
|
updateMemoryEntry
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-7XSG2TIU.js";
|
|
54
54
|
import {
|
|
55
55
|
DEFAULT_PATTERNS,
|
|
56
56
|
redactJson,
|
|
@@ -66,7 +66,7 @@ import {
|
|
|
66
66
|
} from "./chunk-CGLYJRFA.js";
|
|
67
67
|
import {
|
|
68
68
|
runTestsTool
|
|
69
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-653JBZ6J.js";
|
|
70
70
|
import {
|
|
71
71
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
72
72
|
APP_NAME,
|
|
@@ -100,7 +100,7 @@ import {
|
|
|
100
100
|
SUBAGENT_MAX_ROUNDS_LIMIT,
|
|
101
101
|
VERSION,
|
|
102
102
|
buildUserIdentityPrompt
|
|
103
|
-
} from "./chunk-
|
|
103
|
+
} from "./chunk-C7DVLUZE.js";
|
|
104
104
|
|
|
105
105
|
// src/web/server.ts
|
|
106
106
|
import express from "express";
|
|
@@ -3612,7 +3612,9 @@ var OpenAICompatibleProvider = class extends BaseProvider {
|
|
|
3612
3612
|
});
|
|
3613
3613
|
let thinkingStarted = false;
|
|
3614
3614
|
let reasoningAccumulator = "";
|
|
3615
|
+
let pendingUsage;
|
|
3615
3616
|
for await (const chunk of stream) {
|
|
3617
|
+
if (chunk.usage) pendingUsage = toUsage(chunk.usage);
|
|
3616
3618
|
const choice = chunk.choices[0];
|
|
3617
3619
|
const done = choice?.finish_reason != null;
|
|
3618
3620
|
if (!choice && chunk.usage) {
|
|
@@ -3640,7 +3642,14 @@ var OpenAICompatibleProvider = class extends BaseProvider {
|
|
|
3640
3642
|
yield { delta: "</think>", done: false };
|
|
3641
3643
|
}
|
|
3642
3644
|
if (done) {
|
|
3643
|
-
yield {
|
|
3645
|
+
yield {
|
|
3646
|
+
delta,
|
|
3647
|
+
done,
|
|
3648
|
+
// usage 与 finish_reason 同条时(智谱),必须在这里带出去——否则流就结束了,
|
|
3649
|
+
// 再也没有第二次机会。
|
|
3650
|
+
...pendingUsage ? { usage: pendingUsage } : {},
|
|
3651
|
+
...reasoningAccumulator ? { reasoningContent: reasoningAccumulator } : {}
|
|
3652
|
+
};
|
|
3644
3653
|
} else {
|
|
3645
3654
|
yield { delta, done };
|
|
3646
3655
|
}
|
|
@@ -3795,8 +3804,10 @@ var OpenAICompatibleProvider = class extends BaseProvider {
|
|
|
3795
3804
|
let reasoningAccumulator = "";
|
|
3796
3805
|
let lastFinishReason;
|
|
3797
3806
|
let doneEmitted = false;
|
|
3807
|
+
let pendingUsage;
|
|
3798
3808
|
for await (const chunk of stream) {
|
|
3799
3809
|
const choice = chunk.choices[0];
|
|
3810
|
+
if (chunk.usage) pendingUsage = toUsage(chunk.usage);
|
|
3800
3811
|
if (choice?.finish_reason) lastFinishReason = choice.finish_reason;
|
|
3801
3812
|
if (!choice && chunk.usage) {
|
|
3802
3813
|
if (thinkingStarted) {
|
|
@@ -3877,6 +3888,8 @@ var OpenAICompatibleProvider = class extends BaseProvider {
|
|
|
3877
3888
|
}
|
|
3878
3889
|
yield {
|
|
3879
3890
|
type: "done",
|
|
3891
|
+
// usage 与 finish_reason 同条时(智谱),只有这里带得出去——流已经结束了,没有第二次机会。
|
|
3892
|
+
...pendingUsage ? { usage: pendingUsage } : {},
|
|
3880
3893
|
...reasoningAccumulator ? { reasoningContent: reasoningAccumulator } : {},
|
|
3881
3894
|
...lastFinishReason && lastFinishReason !== "stop" ? { finishReason: lastFinishReason } : {}
|
|
3882
3895
|
};
|
|
@@ -16908,7 +16921,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
|
|
|
16908
16921
|
Cost: ${formatCost(cost)}` : "";
|
|
16909
16922
|
let memoryLine = "";
|
|
16910
16923
|
try {
|
|
16911
|
-
const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-
|
|
16924
|
+
const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-V5ZDLPNB.js");
|
|
16912
16925
|
const pending = countPendingMemories2(ctx.config.getConfigDir());
|
|
16913
16926
|
if (pending > 0) memoryLine = `
|
|
16914
16927
|
Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
|
|
@@ -17891,7 +17904,7 @@ async function handleTest(args, ctx) {
|
|
|
17891
17904
|
const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
|
|
17892
17905
|
testArgs = isCommand ? { command: argStr } : { filter: argStr };
|
|
17893
17906
|
}
|
|
17894
|
-
const runTests = ctx.runTests ?? (await import("./run-tests-
|
|
17907
|
+
const runTests = ctx.runTests ?? (await import("./run-tests-XQO4UZFN.js")).executeTests;
|
|
17895
17908
|
const report = await runTests(testArgs);
|
|
17896
17909
|
ctx.send({ type: "info", message: report });
|
|
17897
17910
|
} catch (err) {
|
|
@@ -18281,7 +18294,7 @@ async function handleMemory(args, ctx) {
|
|
|
18281
18294
|
}
|
|
18282
18295
|
if (intent.kind === "status") {
|
|
18283
18296
|
const { getChatIndexStatus: getChatIndexStatus2 } = await import("./chat-index-DGUOUUQW.js");
|
|
18284
|
-
const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-
|
|
18297
|
+
const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-V5ZDLPNB.js");
|
|
18285
18298
|
const memories = listMemoryEntries2(configDir, { includeExpired: true, includeRejected: true });
|
|
18286
18299
|
const injected = formatMemoryForPrompt2(configDir, process.cwd(), ctx.config.get("memory")?.maxChars);
|
|
18287
18300
|
const view = buildMemoryStatusView({
|
|
@@ -18304,7 +18317,7 @@ async function handleMemory(args, ctx) {
|
|
|
18304
18317
|
return;
|
|
18305
18318
|
}
|
|
18306
18319
|
if (intent.kind === "recall") {
|
|
18307
|
-
const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-
|
|
18320
|
+
const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-V5ZDLPNB.js");
|
|
18308
18321
|
const { searchChatMemory: searchChatMemory2 } = await import("./chat-index-DGUOUUQW.js");
|
|
18309
18322
|
const persistentHits = searchPersistentMemories2(configDir, intent.query, process.cwd(), 3);
|
|
18310
18323
|
if (persistentHits.length > 0) {
|
|
@@ -18425,7 +18438,7 @@ async function handleMemory(args, ctx) {
|
|
|
18425
18438
|
ctx.handleMemoryManage(intent.action, args[1], intent.action === "expire" ? args[2] : void 0);
|
|
18426
18439
|
} else if (intent.kind === "export") {
|
|
18427
18440
|
if (args[1] === "md") {
|
|
18428
|
-
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-
|
|
18441
|
+
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-V5ZDLPNB.js");
|
|
18429
18442
|
ctx.send({
|
|
18430
18443
|
type: "export_data",
|
|
18431
18444
|
format: "md",
|
|
@@ -19430,7 +19443,7 @@ No tools match "${filter}".
|
|
|
19430
19443
|
const { join: join29 } = await import("path");
|
|
19431
19444
|
const { existsSync: existsSync33 } = await import("fs");
|
|
19432
19445
|
const { getGitRoot: getGitRoot2 } = await import("./git-context-VNCA2GU7.js");
|
|
19433
|
-
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-
|
|
19446
|
+
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-VHZTK4PO.js");
|
|
19434
19447
|
const { approveProject, hashMcpFile } = await import("./project-trust-MUG325AW.js");
|
|
19435
19448
|
const cwd = process.cwd();
|
|
19436
19449
|
const projectRoot = getGitRoot2(cwd) ?? cwd;
|
|
@@ -20345,7 +20358,7 @@ function createReviewCommands() {
|
|
|
20345
20358
|
usage: "/test [command|filter]",
|
|
20346
20359
|
async execute(args, ctx) {
|
|
20347
20360
|
try {
|
|
20348
|
-
const { executeTests } = await import("./run-tests-
|
|
20361
|
+
const { executeTests } = await import("./run-tests-XQO4UZFN.js");
|
|
20349
20362
|
const argStr = args.join(" ").trim();
|
|
20350
20363
|
let testArgs = {};
|
|
20351
20364
|
if (argStr) {
|
|
@@ -158,7 +158,7 @@ ${content}`);
|
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
async function runTaskMode(config, providers, configManager, topic) {
|
|
161
|
-
const { TaskOrchestrator } = await import("./task-orchestrator-
|
|
161
|
+
const { TaskOrchestrator } = await import("./task-orchestrator-V3F6JQQV.js");
|
|
162
162
|
const orchestrator = new TaskOrchestrator(config, providers, configManager);
|
|
163
163
|
let interrupted = false;
|
|
164
164
|
const onSigint = () => {
|
package/dist/index.js
CHANGED
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
setupProxy,
|
|
25
25
|
snapshotFile,
|
|
26
26
|
stripRoutingTags
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-EU4IPUNW.js";
|
|
28
28
|
import {
|
|
29
29
|
CostTracker,
|
|
30
30
|
getPricing,
|
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
setMaxOutputCap,
|
|
50
50
|
spawnAgentContext,
|
|
51
51
|
undoStack
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-XFZTFEZZ.js";
|
|
53
53
|
import "./chunk-HLWUDRBO.js";
|
|
54
54
|
import {
|
|
55
55
|
NO_THINKING,
|
|
@@ -62,7 +62,7 @@ import {
|
|
|
62
62
|
countPendingMemories,
|
|
63
63
|
detectStaleLegacyMarkdownEdit,
|
|
64
64
|
formatMemoryForPrompt
|
|
65
|
-
} from "./chunk-
|
|
65
|
+
} from "./chunk-BDXS27DX.js";
|
|
66
66
|
import "./chunk-4DEMGCK4.js";
|
|
67
67
|
import "./chunk-UUSRWSSX.js";
|
|
68
68
|
import "./chunk-CKH4KQ4E.js";
|
|
@@ -83,22 +83,22 @@ import {
|
|
|
83
83
|
import {
|
|
84
84
|
loadContextFiles,
|
|
85
85
|
writeCrashLog
|
|
86
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-T56RAP6E.js";
|
|
87
87
|
import {
|
|
88
88
|
getActivePluginAssets,
|
|
89
89
|
getPendingHookTrust,
|
|
90
90
|
installFlushOnExit,
|
|
91
91
|
mergePluginHooks,
|
|
92
92
|
runLifecycleHooks
|
|
93
|
-
} from "./chunk-
|
|
93
|
+
} from "./chunk-XHCJJFYO.js";
|
|
94
94
|
import "./chunk-RS7SKYTS.js";
|
|
95
95
|
import {
|
|
96
96
|
ProviderRegistry,
|
|
97
97
|
listBuiltInProviderMetadata
|
|
98
|
-
} from "./chunk-
|
|
98
|
+
} from "./chunk-QKZUWT3S.js";
|
|
99
99
|
import {
|
|
100
100
|
ConfigManager
|
|
101
|
-
} from "./chunk-
|
|
101
|
+
} from "./chunk-IZJRDI5E.js";
|
|
102
102
|
import {
|
|
103
103
|
CONTENT_ONLY_STREAM_REMINDER,
|
|
104
104
|
TEE_FINAL_USER_NUDGE,
|
|
@@ -116,7 +116,7 @@ import {
|
|
|
116
116
|
runAgentLoop,
|
|
117
117
|
stripToolCallReminder,
|
|
118
118
|
teeStreamErrorSummary
|
|
119
|
-
} from "./chunk-
|
|
119
|
+
} from "./chunk-Y56UGZPX.js";
|
|
120
120
|
import {
|
|
121
121
|
AuthError,
|
|
122
122
|
ProviderError,
|
|
@@ -132,7 +132,7 @@ import {
|
|
|
132
132
|
} from "./chunk-IW3Q7AE5.js";
|
|
133
133
|
import "./chunk-XNFIYS7G.js";
|
|
134
134
|
import "./chunk-4BKXL7SM.js";
|
|
135
|
-
import "./chunk-
|
|
135
|
+
import "./chunk-OP2GIZFU.js";
|
|
136
136
|
import {
|
|
137
137
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
138
138
|
AUTHOR,
|
|
@@ -149,7 +149,7 @@ import {
|
|
|
149
149
|
SKILLS_DIR_NAME,
|
|
150
150
|
VERSION,
|
|
151
151
|
buildUserIdentityPrompt
|
|
152
|
-
} from "./chunk-
|
|
152
|
+
} from "./chunk-PL6EEP5B.js";
|
|
153
153
|
|
|
154
154
|
// src/index.ts
|
|
155
155
|
import { program } from "commander";
|
|
@@ -3930,7 +3930,7 @@ process.on("unhandledRejection", (reason) => {
|
|
|
3930
3930
|
});
|
|
3931
3931
|
var builtInProviderIds = listBuiltInProviderMetadata().map(({ id }) => id).join("/");
|
|
3932
3932
|
program.name("aicli").description("Cross-platform REPL-style AI CLI with multi-provider support").version(VERSION);
|
|
3933
|
-
program.option("--provider <name>", `AI provider to use (${builtInProviderIds}, or any custom provider)`).option("-m, --model <name>", "Model to use").option("-p, --prompt <text>", "Headless mode: send a single prompt and exit (reads stdin as context if piped)").option("--system <prompt>", "System prompt override (headless mode)").option("--json", "Output result as JSON object (headless mode only)").option("--output-format <format>", "Output format: text (default) | streaming-json (NDJSON per-chunk, headless only)").option("--no-stream", "Disable streaming output").option("--allowed-tools <tools>", "Comma-separated whitelist of tools (e.g. bash,read_file)").option("--blocked-tools <tools>", "Comma-separated blacklist of tools (e.g. bash,write_file)").option("--resume <id>", "Resume a previous session by ID (prefix match supported)").option("--max-tool-rounds <n>", "Max agentic tool-call rounds per conversation (default: 200)").option("--think <mode>", "Thinking for this run: off | on | low | high | max (default: follow config)").action(async (options) => {
|
|
3933
|
+
program.option("--provider <name>", `AI provider to use (${builtInProviderIds}, or any custom provider)`).option("-m, --model <name>", "Model to use").option("-p, --prompt <text>", "Headless mode: send a single prompt and exit (reads stdin as context if piped)").option("--system <prompt>", "System prompt override (headless mode)").option("--json", "Output result as JSON object (headless mode only)").option("--output-format <format>", "Output format: text (default) | streaming-json (NDJSON per-chunk, headless only)").option("--include-thinking", "Keep inline <think> blocks in headless output (default: stripped)").option("--no-stream", "Disable streaming output").option("--allowed-tools <tools>", "Comma-separated whitelist of tools (e.g. bash,read_file)").option("--blocked-tools <tools>", "Comma-separated blacklist of tools (e.g. bash,write_file)").option("--resume <id>", "Resume a previous session by ID (prefix match supported)").option("--max-tool-rounds <n>", "Max agentic tool-call rounds per conversation (default: 200)").option("--think <mode>", "Thinking for this run: off | on | low | high | max (default: follow config)").action(async (options) => {
|
|
3934
3934
|
if (options.prompt !== void 0) {
|
|
3935
3935
|
await runHeadless(options);
|
|
3936
3936
|
} else {
|
|
@@ -3992,7 +3992,7 @@ program.command("web").description("Start Web UI server with browser-based chat
|
|
|
3992
3992
|
console.error("Error: Invalid port number. Must be between 1 and 65535.");
|
|
3993
3993
|
process.exit(1);
|
|
3994
3994
|
}
|
|
3995
|
-
const { startWebServer } = await import("./server-
|
|
3995
|
+
const { startWebServer } = await import("./server-QAFBIQIU.js");
|
|
3996
3996
|
await startWebServer({ port, host: options.host });
|
|
3997
3997
|
});
|
|
3998
3998
|
program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | logout-all <name> | migrate <name>)").action(async (action, username) => {
|
|
@@ -4159,11 +4159,11 @@ program.command("sessions").description("List recent conversation sessions").opt
|
|
|
4159
4159
|
console.log(footer + "\n");
|
|
4160
4160
|
});
|
|
4161
4161
|
program.command("usage").description("Show token + cost usage grouped by provider/model (cross-session)").option("--days <n>", "Only the last N days (inclusive of today)").option("--month <ym>", "Only a specific month, format YYYY-MM (e.g. 2026-06)").option("--json", "Output as JSON (for scripting)").action(async (options) => {
|
|
4162
|
-
const { runUsageCli } = await import("./usage-
|
|
4162
|
+
const { runUsageCli } = await import("./usage-MHLWUUWZ.js");
|
|
4163
4163
|
await runUsageCli(options);
|
|
4164
4164
|
});
|
|
4165
4165
|
program.command("doctor").description("Health check: API keys, config, MCP, recent crashes, tool usage, disk usage").option("--json", "Output as JSON (for scripting)").option("--reset-stats", "Reset accumulated tool usage statistics").action(async (options) => {
|
|
4166
|
-
const { runDoctorCli } = await import("./doctor-cli-
|
|
4166
|
+
const { runDoctorCli } = await import("./doctor-cli-4F7DBT5A.js");
|
|
4167
4167
|
const argv = process.argv.slice(2);
|
|
4168
4168
|
await runDoctorCli({
|
|
4169
4169
|
json: !!options.json || argv.includes("--json"),
|
|
@@ -4172,7 +4172,7 @@ program.command("doctor").description("Health check: API keys, config, MCP, rece
|
|
|
4172
4172
|
});
|
|
4173
4173
|
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) => {
|
|
4174
4174
|
try {
|
|
4175
|
-
const batch = await import("./batch-
|
|
4175
|
+
const batch = await import("./batch-3H2X3QHW.js");
|
|
4176
4176
|
switch (action) {
|
|
4177
4177
|
case "submit":
|
|
4178
4178
|
if (!arg) {
|
|
@@ -4215,7 +4215,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
|
|
|
4215
4215
|
}
|
|
4216
4216
|
});
|
|
4217
4217
|
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) => {
|
|
4218
|
-
const { startMcpServer } = await import("./server-
|
|
4218
|
+
const { startMcpServer } = await import("./server-KXPO46PT.js");
|
|
4219
4219
|
await startMcpServer({
|
|
4220
4220
|
allowDestructive: !!options.allowDestructive,
|
|
4221
4221
|
allowOutsideCwd: !!options.allowOutsideCwd,
|
|
@@ -4228,7 +4228,7 @@ program.command("pr <action> [target]").description("PR review helpers: review |
|
|
|
4228
4228
|
console.error(`Unknown pr action: ${action}. Use review | security-review | summarize.`);
|
|
4229
4229
|
process.exit(1);
|
|
4230
4230
|
}
|
|
4231
|
-
const { runPrCli } = await import("./pr-
|
|
4231
|
+
const { runPrCli } = await import("./pr-4OGJOG2P.js");
|
|
4232
4232
|
const result = await runPrCli({
|
|
4233
4233
|
action,
|
|
4234
4234
|
target,
|
|
@@ -4248,8 +4248,8 @@ program.command("pr <action> [target]").description("PR review helpers: review |
|
|
|
4248
4248
|
process.exit(result.exitCode);
|
|
4249
4249
|
});
|
|
4250
4250
|
program.command("ci").description("Headless PR review (code + security) \u2014 reads git/gh diff, optionally posts to PR. Designed for GitHub Actions.").option("--pr <num>", "PR number or URL; diff fetched via gh pr diff <value>", (v) => /^#?\d+$/.test(v) ? parseInt(v.replace(/^#/, ""), 10) : v).option("--base <ref>", "Base ref for git diff <ref>...HEAD (ignored when --pr set)").option("--post", "Post review as a PR comment (requires gh CLI + GH_TOKEN, needs --pr)").option("--no-update", "Always create a new comment instead of updating the previous aicli review").option("--skip-code", "Skip the code review section").option("--skip-security", "Skip the security review section").option("--detailed", "Use the detailed code-review prompt").option("--max-diff <n>", "Max diff chars sent to the model (default 30000)", (v) => parseInt(v, 10)).option("--provider <id>", "Override provider (default: config.defaultProvider)").option("--model <id>", "Override model").option("--dry-run", "Print result to stdout instead of posting (overrides --post)").option("--json", "Output a structured JSON report").option("--markdown", "Output Markdown report (default)").option("--sarif", "Output SARIF 2.1.0 for code scanning artifacts").option("--fail-on-security-high", "Fail when the security review contains HIGH/CRITICAL findings (default)").option("--no-fail-on-security-high", "Do not fail on security HIGH/CRITICAL findings").option("--fail-on-test-failure", "Fail when the report mentions test failures (default)").option("--no-fail-on-test-failure", "Do not fail on test failure findings").option("--fail-on-lint-failure", "Fail when the report mentions lint/typecheck failures (default)").option("--no-fail-on-lint-failure", "Do not fail on lint/typecheck failure findings").action(async (options) => {
|
|
4251
|
-
const { runCi } = await import("./ci-
|
|
4252
|
-
const { formatCiResult } = await import("./ci-format-
|
|
4251
|
+
const { runCi } = await import("./ci-BYYYDYYC.js");
|
|
4252
|
+
const { formatCiResult } = await import("./ci-format-NXFB37WR.js");
|
|
4253
4253
|
const formats = [options.json, options.markdown, options.sarif].filter(Boolean).length;
|
|
4254
4254
|
if (formats > 1) {
|
|
4255
4255
|
console.error("Choose only one output format: --json, --markdown, or --sarif.");
|
|
@@ -4324,6 +4324,7 @@ program.command("help").description("Show a comprehensive guide to all aicli fea
|
|
|
4324
4324
|
` ${Y}--system <prompt>${R} Override system prompt`,
|
|
4325
4325
|
` ${Y}--json${R} Output as JSON`,
|
|
4326
4326
|
` ${Y}--output-format <fmt>${R} text | streaming-json (NDJSON)`,
|
|
4327
|
+
` ${Y}--include-thinking${R} Keep <think> blocks (default: stripped)`,
|
|
4327
4328
|
` ${D}echo "code" | aicli -p "explain" \u2190 pipe stdin as context${R}`,
|
|
4328
4329
|
"",
|
|
4329
4330
|
`${B}${C} \u25A0 WEB UI OPTIONS${R}`,
|
|
@@ -4407,7 +4408,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
|
|
|
4407
4408
|
config.get("customProviders"),
|
|
4408
4409
|
config.getConfigDir()
|
|
4409
4410
|
);
|
|
4410
|
-
const { startHub } = await import("./hub-
|
|
4411
|
+
const { startHub } = await import("./hub-Y545G6KJ.js");
|
|
4411
4412
|
await startHub(
|
|
4412
4413
|
{
|
|
4413
4414
|
topic: topic ?? "",
|
|
@@ -4536,6 +4537,18 @@ ${loaded.mergedContent}` : void 0
|
|
|
4536
4537
|
}
|
|
4537
4538
|
const isStreamingJson = options.outputFormat === "streaming-json";
|
|
4538
4539
|
const useStream = options.stream !== false && !options.json && !isStreamingJson;
|
|
4540
|
+
const costTracker = new CostTracker(config.getConfigDir());
|
|
4541
|
+
const recordUsage = (u) => {
|
|
4542
|
+
if (!u) return;
|
|
4543
|
+
if (u.inputTokens === 0 && u.outputTokens === 0) return;
|
|
4544
|
+
costTracker.addCost(providerId, model, u);
|
|
4545
|
+
};
|
|
4546
|
+
const keepThinking = options.includeThinking === true;
|
|
4547
|
+
const stripThinking = (text) => {
|
|
4548
|
+
if (keepThinking) return text;
|
|
4549
|
+
const f = new ThinkTagFilter();
|
|
4550
|
+
return f.push(text) + f.flush();
|
|
4551
|
+
};
|
|
4539
4552
|
try {
|
|
4540
4553
|
if (isStreamingJson) {
|
|
4541
4554
|
const stream = provider.chatStream({
|
|
@@ -4550,16 +4563,20 @@ ${loaded.mergedContent}` : void 0
|
|
|
4550
4563
|
});
|
|
4551
4564
|
let fullContent = "";
|
|
4552
4565
|
let finalUsage;
|
|
4566
|
+
const jsonFilter = new ThinkTagFilter();
|
|
4567
|
+
const emitDelta = (text) => {
|
|
4568
|
+
if (!text) return;
|
|
4569
|
+
fullContent += text;
|
|
4570
|
+
process.stdout.write(JSON.stringify({ type: "delta", text }) + "\n");
|
|
4571
|
+
};
|
|
4553
4572
|
for await (const chunk of stream) {
|
|
4554
4573
|
if (chunk.done) {
|
|
4555
4574
|
finalUsage = chunk.usage;
|
|
4556
4575
|
break;
|
|
4557
4576
|
}
|
|
4558
|
-
if (chunk.delta)
|
|
4559
|
-
fullContent += chunk.delta;
|
|
4560
|
-
process.stdout.write(JSON.stringify({ type: "delta", text: chunk.delta }) + "\n");
|
|
4561
|
-
}
|
|
4577
|
+
if (chunk.delta) emitDelta(keepThinking ? chunk.delta : jsonFilter.push(chunk.delta));
|
|
4562
4578
|
}
|
|
4579
|
+
if (!keepThinking) emitDelta(jsonFilter.flush());
|
|
4563
4580
|
const doneOut = {
|
|
4564
4581
|
type: "done",
|
|
4565
4582
|
content: fullContent,
|
|
@@ -4567,6 +4584,7 @@ ${loaded.mergedContent}` : void 0
|
|
|
4567
4584
|
model
|
|
4568
4585
|
};
|
|
4569
4586
|
if (finalUsage) doneOut["usage"] = finalUsage;
|
|
4587
|
+
recordUsage(finalUsage);
|
|
4570
4588
|
process.stdout.write(JSON.stringify(doneOut) + "\n");
|
|
4571
4589
|
} else if (options.json) {
|
|
4572
4590
|
const response = await provider.chat({
|
|
@@ -4580,11 +4598,12 @@ ${loaded.mergedContent}` : void 0
|
|
|
4580
4598
|
...thinkingParams
|
|
4581
4599
|
});
|
|
4582
4600
|
const out = {
|
|
4583
|
-
content: response.content,
|
|
4601
|
+
content: stripThinking(response.content),
|
|
4584
4602
|
provider: providerId,
|
|
4585
4603
|
model: response.model ?? model,
|
|
4586
4604
|
usage: response.usage ?? null
|
|
4587
4605
|
};
|
|
4606
|
+
recordUsage(response.usage);
|
|
4588
4607
|
process.stdout.write(JSON.stringify(out, null, 2) + "\n");
|
|
4589
4608
|
} else if (useStream) {
|
|
4590
4609
|
const stream = provider.chatStream({
|
|
@@ -4597,10 +4616,14 @@ ${loaded.mergedContent}` : void 0
|
|
|
4597
4616
|
timeout,
|
|
4598
4617
|
...thinkingParams
|
|
4599
4618
|
});
|
|
4619
|
+
const textFilter = new ThinkTagFilter();
|
|
4620
|
+
let streamUsage;
|
|
4600
4621
|
for await (const chunk of stream) {
|
|
4601
|
-
if (chunk.
|
|
4602
|
-
if (chunk.delta) process.stdout.write(chunk.delta);
|
|
4622
|
+
if (chunk.usage) streamUsage = chunk.usage;
|
|
4623
|
+
if (chunk.delta) process.stdout.write(keepThinking ? chunk.delta : textFilter.push(chunk.delta));
|
|
4603
4624
|
}
|
|
4625
|
+
if (!keepThinking) process.stdout.write(textFilter.flush());
|
|
4626
|
+
recordUsage(streamUsage);
|
|
4604
4627
|
process.stdout.write("\n");
|
|
4605
4628
|
} else {
|
|
4606
4629
|
const response = await provider.chat({
|
|
@@ -4613,10 +4636,13 @@ ${loaded.mergedContent}` : void 0
|
|
|
4613
4636
|
timeout,
|
|
4614
4637
|
...thinkingParams
|
|
4615
4638
|
});
|
|
4616
|
-
|
|
4639
|
+
recordUsage(response.usage);
|
|
4640
|
+
process.stdout.write(stripThinking(response.content) + "\n");
|
|
4617
4641
|
}
|
|
4642
|
+
costTracker.flush();
|
|
4618
4643
|
process.exit(0);
|
|
4619
4644
|
} catch (err) {
|
|
4645
|
+
costTracker.flush();
|
|
4620
4646
|
const msg = err instanceof Error ? err.message : String(err);
|
|
4621
4647
|
process.stderr.write(`Error: ${msg}
|
|
4622
4648
|
`);
|
|
@@ -27,11 +27,11 @@ import {
|
|
|
27
27
|
touchMemoryReferences,
|
|
28
28
|
updateMemoryApproval,
|
|
29
29
|
updateMemoryEntry
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-7XSG2TIU.js";
|
|
31
31
|
import "./chunk-FSC6KEWU.js";
|
|
32
32
|
import "./chunk-6BUTA5VW.js";
|
|
33
33
|
import "./chunk-CGLYJRFA.js";
|
|
34
|
-
import "./chunk-
|
|
34
|
+
import "./chunk-C7DVLUZE.js";
|
|
35
35
|
export {
|
|
36
36
|
addMemoryEntry,
|
|
37
37
|
backupMemoryStore,
|
|
@@ -28,11 +28,11 @@ import {
|
|
|
28
28
|
touchMemoryReferences,
|
|
29
29
|
updateMemoryApproval,
|
|
30
30
|
updateMemoryEntry
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-BDXS27DX.js";
|
|
32
32
|
import "./chunk-3FEZSLGI.js";
|
|
33
33
|
import "./chunk-HOSJZMQS.js";
|
|
34
34
|
import "./chunk-IW3Q7AE5.js";
|
|
35
|
-
import "./chunk-
|
|
35
|
+
import "./chunk-PL6EEP5B.js";
|
|
36
36
|
export {
|
|
37
37
|
addMemoryEntry,
|
|
38
38
|
backupMemoryStore,
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import {
|
|
3
3
|
countSeverity,
|
|
4
4
|
runCi
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-S2GDHXBI.js";
|
|
6
|
+
import "./chunk-QJ4QJUU3.js";
|
|
7
7
|
import {
|
|
8
8
|
buildReviewPrompt,
|
|
9
9
|
buildSecurityReviewPrompt,
|
|
@@ -14,16 +14,16 @@ import {
|
|
|
14
14
|
} from "./chunk-6YZEZFX5.js";
|
|
15
15
|
import {
|
|
16
16
|
ProviderRegistry
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-QKZUWT3S.js";
|
|
18
18
|
import {
|
|
19
19
|
ConfigManager
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-
|
|
20
|
+
} from "./chunk-IZJRDI5E.js";
|
|
21
|
+
import "./chunk-Y56UGZPX.js";
|
|
22
22
|
import "./chunk-TU3L3PW7.js";
|
|
23
23
|
import "./chunk-IW3Q7AE5.js";
|
|
24
24
|
import {
|
|
25
25
|
VERSION
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-PL6EEP5B.js";
|
|
27
27
|
|
|
28
28
|
// src/cli/pr.ts
|
|
29
29
|
import { execFileSync } from "child_process";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ToolRegistry
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-XFZTFEZZ.js";
|
|
5
5
|
import "./chunk-GHWZVPUV.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-BDXS27DX.js";
|
|
7
7
|
import "./chunk-4DEMGCK4.js";
|
|
8
8
|
import "./chunk-UUSRWSSX.js";
|
|
9
9
|
import "./chunk-CKH4KQ4E.js";
|
|
@@ -14,20 +14,20 @@ import "./chunk-NYNSYLFY.js";
|
|
|
14
14
|
import "./chunk-3FEZSLGI.js";
|
|
15
15
|
import {
|
|
16
16
|
runTool
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-XHCJJFYO.js";
|
|
18
18
|
import "./chunk-RS7SKYTS.js";
|
|
19
19
|
import {
|
|
20
20
|
getDangerLevel,
|
|
21
21
|
schemaToJsonSchema
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-Y56UGZPX.js";
|
|
23
23
|
import "./chunk-TU3L3PW7.js";
|
|
24
24
|
import "./chunk-HOSJZMQS.js";
|
|
25
25
|
import "./chunk-IW3Q7AE5.js";
|
|
26
26
|
import "./chunk-4BKXL7SM.js";
|
|
27
|
-
import "./chunk-
|
|
27
|
+
import "./chunk-OP2GIZFU.js";
|
|
28
28
|
import {
|
|
29
29
|
VERSION
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-PL6EEP5B.js";
|
|
31
31
|
|
|
32
32
|
// src/mcp/server.ts
|
|
33
33
|
import { createInterface } from "readline";
|
|
@@ -81,7 +81,7 @@ import {
|
|
|
81
81
|
skillHistoryNote,
|
|
82
82
|
snapshotFile,
|
|
83
83
|
stripRoutingTags
|
|
84
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-EU4IPUNW.js";
|
|
85
85
|
import {
|
|
86
86
|
CNY_PER_USD,
|
|
87
87
|
CostTracker,
|
|
@@ -126,7 +126,7 @@ import {
|
|
|
126
126
|
spawnAgentContext,
|
|
127
127
|
truncateOutput,
|
|
128
128
|
undoStack
|
|
129
|
-
} from "./chunk-
|
|
129
|
+
} from "./chunk-XFZTFEZZ.js";
|
|
130
130
|
import {
|
|
131
131
|
buildReviewPrompt,
|
|
132
132
|
buildSecurityReviewPrompt
|
|
@@ -153,7 +153,7 @@ import {
|
|
|
153
153
|
restoreMemoryEntries,
|
|
154
154
|
updateMemoryApproval,
|
|
155
155
|
updateMemoryEntry
|
|
156
|
-
} from "./chunk-
|
|
156
|
+
} from "./chunk-BDXS27DX.js";
|
|
157
157
|
import "./chunk-4DEMGCK4.js";
|
|
158
158
|
import "./chunk-UUSRWSSX.js";
|
|
159
159
|
import "./chunk-CKH4KQ4E.js";
|
|
@@ -172,7 +172,7 @@ import {
|
|
|
172
172
|
buildDoctorReport,
|
|
173
173
|
formatDoctorReport,
|
|
174
174
|
loadContextFiles
|
|
175
|
-
} from "./chunk-
|
|
175
|
+
} from "./chunk-T56RAP6E.js";
|
|
176
176
|
import {
|
|
177
177
|
describePlugin,
|
|
178
178
|
getActivePluginAssets,
|
|
@@ -187,14 +187,14 @@ import {
|
|
|
187
187
|
runTool,
|
|
188
188
|
setPluginEnabled,
|
|
189
189
|
trustPlugin
|
|
190
|
-
} from "./chunk-
|
|
190
|
+
} from "./chunk-XHCJJFYO.js";
|
|
191
191
|
import "./chunk-RS7SKYTS.js";
|
|
192
192
|
import {
|
|
193
193
|
ProviderRegistry
|
|
194
|
-
} from "./chunk-
|
|
194
|
+
} from "./chunk-QKZUWT3S.js";
|
|
195
195
|
import {
|
|
196
196
|
ConfigManager
|
|
197
|
-
} from "./chunk-
|
|
197
|
+
} from "./chunk-IZJRDI5E.js";
|
|
198
198
|
import {
|
|
199
199
|
CONTENT_ONLY_STREAM_REMINDER,
|
|
200
200
|
TEE_FINAL_USER_NUDGE,
|
|
@@ -210,7 +210,7 @@ import {
|
|
|
210
210
|
runAgentLoop,
|
|
211
211
|
stripToolCallReminder,
|
|
212
212
|
teeStreamErrorSummary
|
|
213
|
-
} from "./chunk-
|
|
213
|
+
} from "./chunk-Y56UGZPX.js";
|
|
214
214
|
import "./chunk-TU3L3PW7.js";
|
|
215
215
|
import {
|
|
216
216
|
formatGitContextForPrompt,
|
|
@@ -225,7 +225,7 @@ import {
|
|
|
225
225
|
maskConfigSecrets
|
|
226
226
|
} from "./chunk-XNFIYS7G.js";
|
|
227
227
|
import "./chunk-4BKXL7SM.js";
|
|
228
|
-
import "./chunk-
|
|
228
|
+
import "./chunk-OP2GIZFU.js";
|
|
229
229
|
import {
|
|
230
230
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
231
231
|
AUTHOR,
|
|
@@ -241,7 +241,7 @@ import {
|
|
|
241
241
|
SKILLS_DIR_NAME,
|
|
242
242
|
VERSION,
|
|
243
243
|
buildUserIdentityPrompt
|
|
244
|
-
} from "./chunk-
|
|
244
|
+
} from "./chunk-PL6EEP5B.js";
|
|
245
245
|
|
|
246
246
|
// src/web/server.ts
|
|
247
247
|
import express from "express";
|
|
@@ -930,7 +930,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
|
|
|
930
930
|
Cost: ${formatCost(cost)}` : "";
|
|
931
931
|
let memoryLine = "";
|
|
932
932
|
try {
|
|
933
|
-
const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-
|
|
933
|
+
const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-XTP7BD5C.js");
|
|
934
934
|
const pending = countPendingMemories2(ctx.config.getConfigDir());
|
|
935
935
|
if (pending > 0) memoryLine = `
|
|
936
936
|
Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
|
|
@@ -1854,7 +1854,7 @@ async function handleTest(args, ctx) {
|
|
|
1854
1854
|
const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
|
|
1855
1855
|
testArgs = isCommand ? { command: argStr } : { filter: argStr };
|
|
1856
1856
|
}
|
|
1857
|
-
const runTests = ctx.runTests ?? (await import("./run-tests-
|
|
1857
|
+
const runTests = ctx.runTests ?? (await import("./run-tests-5LNNPOSH.js")).executeTests;
|
|
1858
1858
|
const report = await runTests(testArgs);
|
|
1859
1859
|
ctx.send({ type: "info", message: report });
|
|
1860
1860
|
} catch (err) {
|
|
@@ -2129,7 +2129,7 @@ async function handleMemory(args, ctx) {
|
|
|
2129
2129
|
}
|
|
2130
2130
|
if (intent.kind === "status") {
|
|
2131
2131
|
const { getChatIndexStatus } = await import("./chat-index-2D5GK2DB.js");
|
|
2132
|
-
const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-
|
|
2132
|
+
const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-XTP7BD5C.js");
|
|
2133
2133
|
const memories = listMemoryEntries2(configDir, { includeExpired: true, includeRejected: true });
|
|
2134
2134
|
const injected = formatMemoryForPrompt2(configDir, process.cwd(), ctx.config.get("memory")?.maxChars);
|
|
2135
2135
|
const view = buildMemoryStatusView({
|
|
@@ -2152,7 +2152,7 @@ async function handleMemory(args, ctx) {
|
|
|
2152
2152
|
return;
|
|
2153
2153
|
}
|
|
2154
2154
|
if (intent.kind === "recall") {
|
|
2155
|
-
const { searchPersistentMemories, touchMemoryReferences } = await import("./persistent-memory-
|
|
2155
|
+
const { searchPersistentMemories, touchMemoryReferences } = await import("./persistent-memory-XTP7BD5C.js");
|
|
2156
2156
|
const { searchChatMemory } = await import("./chat-index-2D5GK2DB.js");
|
|
2157
2157
|
const persistentHits = searchPersistentMemories(configDir, intent.query, process.cwd(), 3);
|
|
2158
2158
|
if (persistentHits.length > 0) {
|
|
@@ -2273,7 +2273,7 @@ async function handleMemory(args, ctx) {
|
|
|
2273
2273
|
ctx.handleMemoryManage(intent.action, args[1], intent.action === "expire" ? args[2] : void 0);
|
|
2274
2274
|
} else if (intent.kind === "export") {
|
|
2275
2275
|
if (args[1] === "md") {
|
|
2276
|
-
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-
|
|
2276
|
+
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-XTP7BD5C.js");
|
|
2277
2277
|
ctx.send({
|
|
2278
2278
|
type: "export_data",
|
|
2279
2279
|
format: "md",
|