@armadra/agent 0.2.1 → 0.4.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/CHANGELOG.md +99 -0
- package/README.md +142 -49
- package/dist/agent/retry.d.ts +1 -1
- package/dist/agent/retry.js +2 -1
- package/dist/agent/session-cache.js +6 -3
- package/dist/agent/session-classifier.d.ts +18 -0
- package/dist/agent/session-classifier.js +103 -0
- package/dist/agent/session-core.d.ts +13 -0
- package/dist/agent/session-state.js +2 -1
- package/dist/agent/session-sync.js +9 -2
- package/dist/agent/session-tools.js +24 -3
- package/dist/agent/session.d.ts +3 -0
- package/dist/agent/session.js +20 -10
- package/dist/agent/tool-runner.js +15 -2
- package/dist/agent/types.d.ts +9 -1
- package/dist/ai/apis/anthropic-messages.js +3 -2
- package/dist/ai/apis/google-generative-ai.js +3 -2
- package/dist/ai/apis/openai-completions.js +3 -2
- package/dist/ai/apis/openai-responses.js +5 -3
- package/dist/ai/cache/fingerprint.d.ts +1 -1
- package/dist/ai/cache/fingerprint.js +1 -1
- package/dist/ai/cache/reporting.js +2 -1
- package/dist/ai/http.d.ts +28 -6
- package/dist/ai/http.js +41 -8
- package/dist/ai/providers/channels.d.ts +51 -0
- package/dist/ai/providers/channels.js +96 -0
- package/dist/ai/providers/enrich.d.ts +34 -0
- package/dist/ai/providers/enrich.js +86 -0
- package/dist/ai/providers/models-dev-cache.d.ts +53 -0
- package/dist/ai/providers/models-dev-cache.js +147 -0
- package/dist/ai/providers/models-dev.d.ts +99 -0
- package/dist/ai/providers/models-dev.js +315 -0
- package/dist/ai/providers/registry.d.ts +42 -4
- package/dist/ai/providers/registry.js +195 -34
- package/dist/ai/providers/suggest.d.ts +18 -0
- package/dist/ai/providers/suggest.js +72 -0
- package/dist/ai/sse.d.ts +6 -2
- package/dist/ai/sse.js +22 -2
- package/dist/ai/types.d.ts +30 -3
- package/dist/bundle/ama.cjs +17893 -10698
- package/dist/cli/args.d.ts +23 -5
- package/dist/cli/args.js +113 -13
- package/dist/cli/bootstrap.js +28 -3
- package/dist/cli/codemode-notice.d.ts +20 -0
- package/dist/cli/codemode-notice.js +55 -0
- package/dist/cli/compose-providers.js +3 -0
- package/dist/cli/compose-session.d.ts +8 -0
- package/dist/cli/compose-session.js +32 -1
- package/dist/cli/compose-store.d.ts +1 -1
- package/dist/cli/compose-store.js +3 -1
- package/dist/cli/compose.d.ts +17 -5
- package/dist/cli/compose.js +53 -19
- package/dist/cli/default-model.d.ts +38 -1
- package/dist/cli/default-model.js +96 -9
- package/dist/cli/deps.d.ts +38 -0
- package/dist/cli/exit-codes.d.ts +2 -0
- package/dist/cli/exit-codes.js +3 -0
- package/dist/cli/fake-visibility.d.ts +13 -0
- package/dist/cli/fake-visibility.js +26 -0
- package/dist/cli/from-prompt.d.ts +18 -0
- package/dist/cli/from-prompt.js +49 -0
- package/dist/cli/main.d.ts +10 -2
- package/dist/cli/main.js +88 -2
- package/dist/cli/proxy.d.ts +51 -0
- package/dist/cli/proxy.js +135 -0
- package/dist/cli/startup-screen.d.ts +29 -0
- package/dist/cli/startup-screen.js +47 -0
- package/dist/cli/startup-steps.d.ts +1 -1
- package/dist/cli/startup-steps.js +20 -13
- package/dist/cli/subcommands/config.d.ts +29 -4
- package/dist/cli/subcommands/config.js +188 -25
- package/dist/cli/subcommands/context.js +5 -1
- package/dist/cli/subcommands/doctor.js +12 -1
- package/dist/cli/subcommands/init.d.ts +6 -0
- package/dist/cli/subcommands/init.js +23 -0
- package/dist/cli/subcommands/model-meta.d.ts +16 -0
- package/dist/cli/subcommands/model-meta.js +54 -0
- package/dist/cli/subcommands/models-cache-probe.js +1 -1
- package/dist/cli/subcommands/models-discover.d.ts +18 -6
- package/dist/cli/subcommands/models-discover.js +87 -52
- package/dist/cli/subcommands/models.js +26 -18
- package/dist/cli/subcommands/probe-runner.d.ts +96 -0
- package/dist/cli/subcommands/probe-runner.js +264 -0
- package/dist/cli/subcommands/providers-list.d.ts +8 -0
- package/dist/cli/subcommands/providers-list.js +97 -0
- package/dist/cli/subcommands/providers-plan.d.ts +79 -0
- package/dist/cli/subcommands/providers-plan.js +215 -0
- package/dist/cli/subcommands/providers-probe.d.ts +34 -0
- package/dist/cli/subcommands/providers-probe.js +87 -0
- package/dist/cli/subcommands/providers.d.ts +28 -0
- package/dist/cli/subcommands/providers.js +436 -0
- package/dist/cli/subcommands/sessions-export.d.ts +10 -0
- package/dist/cli/subcommands/sessions-export.js +59 -0
- package/dist/cli/subcommands/sessions-search.d.ts +13 -0
- package/dist/cli/subcommands/sessions-search.js +103 -0
- package/dist/cli/subcommands/sessions.d.ts +3 -2
- package/dist/cli/subcommands/sessions.js +22 -1
- package/dist/cli/subcommands/stats.d.ts +17 -0
- package/dist/cli/subcommands/stats.js +198 -0
- package/dist/cli/system-prompt-arg.d.ts +11 -0
- package/dist/cli/system-prompt-arg.js +34 -0
- package/dist/codemode/modes.d.ts +4 -11
- package/dist/codemode/modes.js +5 -27
- package/dist/codemode/tool.d.ts +18 -14
- package/dist/codemode/tool.js +71 -28
- package/dist/config/init.d.ts +34 -0
- package/dist/config/init.js +99 -0
- package/dist/config/json-schema.d.ts +15 -0
- package/dist/config/json-schema.js +215 -0
- package/dist/config/key-docs.d.ts +22 -0
- package/dist/config/key-docs.js +105 -0
- package/dist/config/merge.d.ts +9 -8
- package/dist/config/merge.js +22 -7
- package/dist/config/schema.d.ts +1 -1
- package/dist/config/schema.js +97 -15
- package/dist/config/types.d.ts +57 -11
- package/dist/config/types.js +19 -1
- package/dist/modes/commands-core.js +6 -5
- package/dist/modes/image-input.d.ts +27 -0
- package/dist/modes/image-input.js +78 -0
- package/dist/modes/interactive/approval-dialog.d.ts +21 -5
- package/dist/modes/interactive/approval-dialog.js +106 -27
- package/dist/modes/interactive/commands.d.ts +11 -2
- package/dist/modes/interactive/commands.js +58 -19
- package/dist/modes/interactive/interactive-mode.d.ts +2 -1
- package/dist/modes/interactive/interactive-mode.js +70 -82
- package/dist/modes/interactive/key-dispatch.d.ts +3 -1
- package/dist/modes/interactive/key-dispatch.js +5 -6
- package/dist/modes/interactive/line/line-mode.d.ts +1 -0
- package/dist/modes/interactive/line/line-mode.js +9 -5
- package/dist/modes/interactive/line/line-render.d.ts +4 -0
- package/dist/modes/interactive/line/line-render.js +28 -6
- package/dist/modes/interactive/message-view.d.ts +48 -9
- package/dist/modes/interactive/message-view.js +238 -44
- package/dist/modes/interactive/panels.d.ts +18 -0
- package/dist/modes/interactive/panels.js +143 -0
- package/dist/modes/interactive/pickers.d.ts +23 -2
- package/dist/modes/interactive/pickers.js +48 -15
- package/dist/modes/interactive/run-indicator.d.ts +51 -0
- package/dist/modes/interactive/run-indicator.js +189 -0
- package/dist/modes/interactive/startup-header.d.ts +40 -0
- package/dist/modes/interactive/startup-header.js +169 -0
- package/dist/modes/interactive/startup-ui.d.ts +7 -2
- package/dist/modes/interactive/startup-ui.js +41 -11
- package/dist/modes/interactive/status-bar.d.ts +18 -15
- package/dist/modes/interactive/status-bar.js +98 -56
- package/dist/modes/interactive/tool-summary.d.ts +46 -0
- package/dist/modes/interactive/tool-summary.js +218 -0
- package/dist/modes/interactive/tool-view.d.ts +48 -15
- package/dist/modes/interactive/tool-view.js +203 -145
- package/dist/modes/print/print-mode.d.ts +33 -4
- package/dist/modes/print/print-mode.js +128 -8
- package/dist/modes/rpc/commands.js +12 -2
- package/dist/permissions/auto-safe.d.ts +60 -0
- package/dist/permissions/auto-safe.js +529 -0
- package/dist/permissions/classifier.d.ts +64 -0
- package/dist/permissions/classifier.js +184 -0
- package/dist/permissions/dangerous.d.ts +5 -0
- package/dist/permissions/dangerous.js +1 -1
- package/dist/permissions/modes.d.ts +30 -0
- package/dist/permissions/modes.js +78 -0
- package/dist/permissions/pipeline.d.ts +31 -4
- package/dist/permissions/pipeline.js +196 -6
- package/dist/permissions/protected.d.ts +19 -0
- package/dist/permissions/protected.js +74 -0
- package/dist/permissions/rules.js +3 -0
- package/dist/permissions/types.d.ts +50 -3
- package/dist/permissions/types.js +3 -0
- package/dist/rpc.d.ts +2 -0
- package/dist/sdk.d.ts +9 -3
- package/dist/sdk.js +10 -2
- package/dist/session/export.d.ts +32 -0
- package/dist/session/export.js +187 -0
- package/dist/session/projection.js +5 -1
- package/dist/session/redact.d.ts +15 -0
- package/dist/session/redact.js +55 -0
- package/dist/session/reuse.d.ts +33 -0
- package/dist/session/reuse.js +86 -0
- package/dist/session/scan.d.ts +34 -0
- package/dist/session/scan.js +140 -0
- package/dist/session/search.d.ts +52 -0
- package/dist/session/search.js +211 -0
- package/dist/session/stats-aggregate.d.ts +63 -0
- package/dist/session/stats-aggregate.js +163 -0
- package/dist/session/stats-index.d.ts +26 -0
- package/dist/session/stats-index.js +91 -0
- package/dist/session/stats-scan.d.ts +54 -0
- package/dist/session/stats-scan.js +236 -0
- package/dist/session/types.d.ts +2 -0
- package/dist/tools/image-file.d.ts +31 -0
- package/dist/tools/image-file.js +114 -0
- package/dist/tools/presets.d.ts +35 -8
- package/dist/tools/presets.js +56 -17
- package/dist/tools/read.d.ts +4 -8
- package/dist/tools/read.js +15 -64
- package/dist/tui/component.d.ts +8 -2
- package/dist/tui/component.js +3 -1
- package/dist/tui/components/box.d.ts +6 -1
- package/dist/tui/components/box.js +16 -6
- package/dist/tui/components/card.d.ts +23 -0
- package/dist/tui/components/card.js +37 -0
- package/dist/tui/components/editor-history.d.ts +6 -0
- package/dist/tui/components/editor-history.js +45 -0
- package/dist/tui/components/editor-paste.d.ts +1 -1
- package/dist/tui/components/editor-paste.js +4 -4
- package/dist/tui/components/editor.d.ts +11 -5
- package/dist/tui/components/editor.js +52 -58
- package/dist/tui/components/key-value.d.ts +3 -0
- package/dist/tui/components/key-value.js +16 -6
- package/dist/tui/components/loader.d.ts +37 -7
- package/dist/tui/components/loader.js +84 -21
- package/dist/tui/components/markdown.d.ts +5 -1
- package/dist/tui/components/markdown.js +45 -21
- package/dist/tui/components/meter.d.ts +3 -3
- package/dist/tui/components/meter.js +13 -11
- package/dist/tui/components/select-list.d.ts +23 -1
- package/dist/tui/components/select-list.js +76 -13
- package/dist/tui/glyphs.d.ts +68 -0
- package/dist/tui/glyphs.js +114 -0
- package/dist/tui/theme.d.ts +30 -6
- package/dist/tui/theme.js +103 -17
- package/dist/tui.d.ts +4 -2
- package/dist/tui.js +3 -1
- package/docs/codemode.md +23 -9
- package/docs/hooks.md +10 -10
- package/docs/permissions.md +148 -0
- package/docs/providers.md +241 -3
- package/docs/rpc.md +38 -38
- package/docs/session-format.md +3 -2
- package/docs/sessions.md +134 -0
- package/docs/tui.md +140 -61
- package/package.json +3 -1
package/dist/cli/args.d.ts
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
* 手写参数解析(设计 §11.1 第 2 步、§12.10、§13)。[B5]
|
|
3
3
|
*
|
|
4
4
|
* - 支持 `--opt value` 与 `--opt=value`;`--` 之后全部作为提示文本;可重复的参数累加。
|
|
5
|
-
* -
|
|
5
|
+
* - 位置参数 `-`:`-p` 一直等 stdin 到 EOF(有提示参数时也不设首字节超时)。
|
|
6
|
+
* - 子命令只在第一个参数是 `auth / sessions / models / providers / doctor / config / init` 时识别,
|
|
7
|
+
* 其余参数原样交给子命令。
|
|
6
8
|
* - 互斥:`-p` 与 `--mode rpc`;`--continue` / `--resume` / `--session-id` / `--fork` 两两互斥;
|
|
7
9
|
* `--trust` 与 `--no-trust`;`--api-key` 需要 `--model`;`--output-format` 需要 `-p`。
|
|
8
10
|
* - `--resume [id]`:下一个参数形如会话 id(无空白、不以 `-` 开头)才被当作 id;
|
|
@@ -11,9 +13,9 @@
|
|
|
11
13
|
*/
|
|
12
14
|
import { AmaError } from "../errors.js";
|
|
13
15
|
import type { ModelThinkingLevel } from "../ai/types.js";
|
|
14
|
-
import type
|
|
15
|
-
import type
|
|
16
|
-
export declare const SUBCOMMANDS: readonly ["auth", "sessions", "models", "doctor", "config"];
|
|
16
|
+
import { type PermissionMode } from "../permissions/types.js";
|
|
17
|
+
import { type CodemodeMode, type ToolsPreset } from "../config/types.js";
|
|
18
|
+
export declare const SUBCOMMANDS: readonly ["auth", "sessions", "models", "providers", "doctor", "config", "init", "stats"];
|
|
17
19
|
export type SubcommandName = (typeof SUBCOMMANDS)[number];
|
|
18
20
|
export type OutputFormat = "text" | "json" | "stream-json";
|
|
19
21
|
export type QuietStartup = "normal" | "header" | "silent";
|
|
@@ -54,6 +56,22 @@ export interface ParsedArgs {
|
|
|
54
56
|
toolsPreset?: ToolsPreset;
|
|
55
57
|
/** `--codemode`:覆盖 config `codemode.mode`。 */
|
|
56
58
|
codemode?: CodemodeMode;
|
|
59
|
+
/** `--no-session`:会话只在内存里,不写会话文件。 */
|
|
60
|
+
noSession: boolean;
|
|
61
|
+
/** `--system-prompt <文本|@文件>`:缺省追加进系统提示的 rules 节。 */
|
|
62
|
+
systemPrompt?: string;
|
|
63
|
+
/** `--system-prompt-mode`:append(缺省)| replace(替换开头的 preamble)。 */
|
|
64
|
+
systemPromptMode?: "append" | "replace";
|
|
65
|
+
/** `--max-turns N`(只用于 -p):一次运行最多 N 轮(模型请求 + 工具执行算一轮)。 */
|
|
66
|
+
maxTurns?: number;
|
|
67
|
+
/** 位置参数 `-`(只用于 -p):一直等 stdin 到 EOF,不设首字节超时。 */
|
|
68
|
+
stdin: boolean;
|
|
69
|
+
/** `--no-stdin`(只用于 -p):不读 stdin。 */
|
|
70
|
+
noStdin: boolean;
|
|
71
|
+
/** `--image <文件>`(可重复,只用于 -p):随首条提示发送的图片。 */
|
|
72
|
+
images: string[];
|
|
73
|
+
/** `--from <会话 id>[#编号]`:用旧会话的一条用户消息作为提示(cli/from-prompt.ts)。 */
|
|
74
|
+
from?: string;
|
|
57
75
|
/** 位置参数拼成的提示(空格连接)。 */
|
|
58
76
|
prompt?: string;
|
|
59
77
|
/** 原始位置参数。 */
|
|
@@ -70,7 +88,7 @@ export type ParseResult = {
|
|
|
70
88
|
export declare class UsageError extends AmaError {
|
|
71
89
|
constructor(message: string);
|
|
72
90
|
}
|
|
73
|
-
export declare const HELP_TEXT = "\u7528\u6CD5\uFF1Aama [\u9009\u9879] [\u63D0\u793A]\n ama <\u5B50\u547D\u4EE4> \u2026\n\n\u6A21\u5F0F\n \uFF08\u7F3A\u7701\uFF09 \u7EC8\u7AEF\u754C\u9762\uFF1Bstdin / stdout \u975E TTY \u6216 TERM=dumb \u65F6\u81EA\u52A8\u964D\u7EA7\u4E3A\u884C\u5F0F\n --no-tui \u884C\u5F0F\u754C\u9762\uFF08readline + \u62EC\u53F7\u7C98\u8D34\uFF09\n -p, --print \u975E\u4EA4\u4E92\uFF1A\u6267\u884C\u63D0\u793A\u540E\u9000\u51FA\
|
|
91
|
+
export declare const HELP_TEXT = "\u7528\u6CD5\uFF1Aama [\u9009\u9879] [\u63D0\u793A]\n ama <\u5B50\u547D\u4EE4> \u2026\n\n\u6A21\u5F0F\n \uFF08\u7F3A\u7701\uFF09 \u7EC8\u7AEF\u754C\u9762\uFF1Bstdin / stdout \u975E TTY \u6216 TERM=dumb \u65F6\u81EA\u52A8\u964D\u7EA7\u4E3A\u884C\u5F0F\n --no-tui \u884C\u5F0F\u754C\u9762\uFF08readline + \u62EC\u53F7\u7C98\u8D34\uFF09\n -p, --print \u975E\u4EA4\u4E92\uFF1A\u6267\u884C\u63D0\u793A\u540E\u9000\u51FA\u3002\u63D0\u793A = \u53C2\u6570 + stdin \u7BA1\u9053\u5185\u5BB9\uFF1B\u6709\u63D0\u793A\u53C2\u6570\u65F6\n \u53EA\u7B49\u7BA1\u9053\u9996\u5B57\u8282 2 s\uFF08AMA_STDIN_WAIT_MS\uFF09\uFF0C\u6CA1\u6536\u5230\u5C31\u5FFD\u7565\u5E76\u63D0\u793A\uFF1B\n \u672B\u5C3E\u52A0 - \u5219\u4E00\u76F4\u7B49\u5230 EOF\uFF08\u5982 npm test | ama -p \u627E\u539F\u56E0 -\uFF09\n --no-stdin -p \u4E0D\u8BFB stdin\uFF08\u7236\u8FDB\u7A0B\u7559\u7740\u7BA1\u9053\u3001\u53C8\u4E0D\u60F3\u7B49 2 s \u65F6\uFF09\n --output-format <\u683C\u5F0F> -p \u7684\u8F93\u51FA\uFF1Atext\uFF08\u7F3A\u7701\uFF09| json | stream-json\n --max-turns <N> -p \u6700\u591A\u8DD1 N \u8F6E\uFF08\u4E00\u6B21\u6A21\u578B\u8BF7\u6C42\u52A0\u5176\u5DE5\u5177\u6267\u884C\u7B97\u4E00\u8F6E\uFF09\uFF1B\u5230\u8FBE\u4E0A\u9650\u4ECD\u6709\n \u672A\u5B8C\u6210\u7684\u5DE5\u5177\u8C03\u7528\u65F6\u63D0\u524D\u7ED3\u675F\uFF0C\u9000\u51FA\u7801 1\n --image <\u6587\u4EF6> -p \u968F\u63D0\u793A\u53D1\u9001\u56FE\u7247\uFF08\u53EF\u91CD\u590D\uFF1Bpng / jpg / gif / webp\uFF0C\u5355\u5F20 \u2264 5 MB\uFF09\uFF1B\n \u4EA4\u4E92\u754C\u9762\u91CC\u5199 @\u56FE\u7247\u8DEF\u5F84 \u6216\u7C98\u8D34\u56FE\u7247\u8DEF\u5F84\n --mode rpc stdio JSONL \u534F\u8BAE\uFF08\u4F9B\u5D4C\u5165\uFF09\n --tui-mode <\u6A21\u5F0F> \u663E\u793A\u6A21\u5F0F\uFF0C\u7B2C\u4E00\u671F\u53EA\u6709 regular\uFF08\u4E3B\u5C4F\uFF09\n --quiet-startup <\u6863> \u542F\u52A8\u753B\u9762\uFF1Anormal | header | silent\n\n\u6A21\u578B\n --model <provider/id> \u6A21\u578B\uFF08\u53EF\u914D\u5408 --provider \u53EA\u5199 id\uFF1B@\u6E20\u9053 \u6307\u5B9A\u6E20\u9053\uFF0C\u5982 packy/kimi-k2.5@messages\uFF09\n --provider <id> \u4F9B\u5E94\u5546\uFF08\u5FC5\u987B\u540C\u65F6\u7ED9 --model\uFF09\n --api-key <key> \u53EA\u7528\u4E8E\u672C\u6B21\u542F\u52A8\u7684 key\uFF08\u9700\u8981 --model\uFF1B\u4F18\u5148\u7528 ama auth set\uFF09\n --thinking <\u7EA7\u522B> off | minimal | low | medium | high | xhigh\n\n\u4F1A\u8BDD\n -c, --continue \u7EE7\u7EED\u672C\u76EE\u5F55\u6700\u8FD1\u7684\u4F1A\u8BDD\n -r, --resume [id] \u6062\u590D\u4F1A\u8BDD\uFF08\u4EA4\u4E92\u6A21\u5F0F\u65E0 id \u65F6\u5F39\u9009\u62E9\u5668\uFF09\n --session-id <id> \u4F7F\u7528\u6307\u5B9A id \u7684\u4F1A\u8BDD\uFF08\u4E0D\u5B58\u5728\u5219\u65B0\u5EFA\uFF09\n --fork <id> \u4ECE\u6307\u5B9A\u4F1A\u8BDD\u5206\u53C9\u51FA\u65B0\u4F1A\u8BDD\n --session-dir <\u76EE\u5F55> \u4F1A\u8BDD\u76EE\u5F55\uFF08\u7F3A\u7701 ~/.local/share/ama/sessions\uFF09\n --no-session \u4F1A\u8BDD\u53EA\u5728\u5185\u5B58\u91CC\uFF0C\u4E0D\u5199\u4F1A\u8BDD\u6587\u4EF6\uFF08\u4E4B\u540E\u65E0\u6CD5 --resume\uFF09\n --from <id>[#\u7F16\u53F7] \u7528\u65E7\u4F1A\u8BDD\u7684\u4E00\u6761\u7528\u6237\u6D88\u606F\u4F5C\u63D0\u793A\uFF08\u7F3A\u7701\u6700\u540E\u4E00\u6761\uFF1B-p \u65F6\u8FDE\u56FE\u7247\u4E00\u8D77\uFF1B\n \u7F16\u53F7\u89C1 ama sessions show\uFF09\n\n\u6743\u9650\u4E0E\u4FE1\u4EFB\n --permission-mode <\u6A21\u5F0F> default | auto-edit | plan | auto | full-auto | allowlist\n \uFF08auto \u7531 ama \u5224\u65AD\u6BCF\u4E00\u6B65\uFF1Ballowlist \u53EA\u653E\u884C allow \u89C4\u5219\u547D\u4E2D\u7684\uFF0C\u9002\u5408 CI\uFF09\n --allow <\u89C4\u5219> \u8FFD\u52A0\u5141\u8BB8\u89C4\u5219\uFF0C\u53EF\u91CD\u590D\uFF08\u5982 \"bash(git status*)\"\uFF09\n --deny <\u89C4\u5219> \u8FFD\u52A0\u62D2\u7EDD\u89C4\u5219\uFF0C\u53EF\u91CD\u590D\uFF08\u5982 \"write(**/.env*)\"\uFF09\n --trust / --no-trust \u4FE1\u4EFB / \u4E0D\u4FE1\u4EFB\u5F53\u524D\u9879\u76EE\uFF08\u9879\u76EE\u7EA7 Hook\u3001Skill\u3001\u63D0\u793A\u6A21\u677F\uFF09\n\n\u8D44\u6E90\n --system-prompt <\u6587\u672C|@\u6587\u4EF6> \u8FFD\u52A0\u7CFB\u7EDF\u63D0\u793A\uFF1A\u7F3A\u7701\u4F5C\u4E3A\u6700\u540E\u4E00\u6761\u89C4\u5219\u8FFD\u52A0\uFF08\u5DE5\u5177\u8868\u7B49\u524D\u7F00\u4E0D\u53D8\uFF0C\u5229\u4E8E\u7F13\u5B58\uFF09\n --system-prompt-mode <\u65B9\u5F0F> append\uFF08\u7F3A\u7701\uFF09| replace\uFF08\u66FF\u6362\u5F00\u5934\u7684\u89D2\u8272\u8BF4\u660E\uFF0C\u5DE5\u5177\u4E0E\u9879\u76EE\u4E0A\u4E0B\u6587\u4FDD\u7559\uFF09\n --profile <\u6587\u4EF6> \u5BBF\u4E3B profile.json\uFF08\u5B57\u6BB5\u7B49\u4EF7\u4E8E\u5BF9\u5E94\u53C2\u6570\uFF0C\u547D\u4EE4\u884C\u4F18\u5148\uFF09\n --host <\u6A21\u5757> \u5BBF\u4E3B\u9002\u914D\u5668\u6A21\u5757\uFF08CJS / ESM\uFF09\n --instructions <\u6587\u4EF6> \u8FFD\u52A0\u6307\u4EE4\u6587\u4EF6\uFF0C\u53EF\u91CD\u590D\n --skill-dir <\u76EE\u5F55> \u8FFD\u52A0 Skill \u76EE\u5F55\uFF0C\u53EF\u91CD\u590D\n --auth-file <\u6587\u4EF6> auth.json \u4F4D\u7F6E\uFF08\u7F3A\u7701 ~/.config/ama/auth.json\uFF09\n --tools <a,b,\u2026> \u53EA\u542F\u7528\u8FD9\u4E9B\u5DE5\u5177\n --exclude-tools <a,b,\u2026> \u7981\u7528\u8FD9\u4E9B\u5DE5\u5177\n --tools-preset <\u540D> \u5DE5\u5177\u9884\u8BBE\uFF1Adefault\uFF08\u7F3A\u7701\uFF09| minimal | codemode-only | coordinator\n \uFF08codemode \u662F codemode-only \u7684\u65E7\u540D\uFF0C\u4ECD\u53EF\u7528\uFF09\n --codemode <\u6A21\u5F0F> codemode \u8C03\u7528\u65B9\u5F0F\uFF1Aoff | on | only\uFF08\u7F3A\u7701\u968F\u9884\u8BBE\uFF09\n\n\u5B50\u547D\u4EE4\n ama auth set <provider> \u4ECE stdin \u8BFB\u53D6 key \u5199\u5165 auth.json\uFF080600\uFF09\n ama auth list \u5217\u51FA\u5DF2\u4FDD\u5B58 key \u7684\u4F9B\u5E94\u5546\uFF08\u4E0D\u663E\u793A key\uFF09\n ama auth remove <provider> \u5220\u9664\u5DF2\u4FDD\u5B58\u7684 key\n ama sessions list|show|prune \u4F1A\u8BDD\u7BA1\u7406\n ama sessions search <\u5173\u952E\u8BCD|/\u6B63\u5219/> [--all] [--role user|assistant|tool] [--since 7d] [--limit N]\n \u8DE8\u4F1A\u8BDD\u5168\u6587\u68C0\u7D22\n ama sessions export <id> [--format md|json|jsonl] [--output <\u6587\u4EF6>] [--branch leaf|all]\n \u5BFC\u51FA\u4F1A\u8BDD\uFF08\u5DF2\u8131\u654F\uFF09\n ama models list [--provider <id>] \u5217\u51FA\u6A21\u578B\uFF08\u542B\u6765\u6E90\u4E0E key \u72B6\u6001\uFF09\n ama models check <provider/id> \u53D1\u4E00\u6B21\u6700\u5C0F\u8BF7\u6C42\u68C0\u67E5\u53EF\u7528\u6027\n ama models discover <provider> [--probe] [--write] [--limit N]\n \u4ECE\u4E2D\u8F6C /v1/models \u5217\u51FA\u6A21\u578B\uFF0C\u63A2\u6D4B\u534F\u8BAE\u5E76\u5199\u5165\u914D\u7F6E\n ama models refresh-catalog \u5F3A\u5236\u5237\u65B0 models.dev \u6A21\u578B\u5143\u6570\u636E\u7F13\u5B58\n ama providers add <id> --base-url <url> [--key-env VAR] [--probe] [--channel n=api@url] [--yes]\n \u4E00\u952E\u63A5\u5165\uFF1A\u5217\u6A21\u578B\u3001\u8865 models.dev \u5143\u6570\u636E\u3001\u63A2\u6D4B\u6E20\u9053\u3001\u5199\u5165\u914D\u7F6E\n ama providers list|channels <id>|remove <id>|refresh <id>\n \u4F9B\u5E94\u5546 \u2192 \u6E20\u9053 \u2192 \u6A21\u578B\uFF1B\u5220\u9664\uFF1B\u91CD\u62C9\u6A21\u578B\u5217\u8868\n ama models cache-probe <provider/id> [--tokens N] [--gap-ms MS] [--yes] [--json]\n \u5224\u65AD\u7AEF\u70B9\u662F\u5426\u62A5\u544A\u7F13\u5B58\u547D\u4E2D\n ama doctor \u914D\u7F6E\u5C42\u7EA7\u3001\u4FE1\u4EFB\u3001key \u6765\u6E90\u3001Hook\u3001\u7EC8\u7AEF\u80FD\u529B\n ama config show [--json] \u751F\u6548\u914D\u7F6E\u4E0E\u6BCF\u9879\u6765\u6E90\u3001\u5C06\u4F7F\u7528\u7684\u6A21\u578B\n ama config path \u914D\u7F6E\u76EE\u5F55\u3001\u6570\u636E\u76EE\u5F55\u4E0E\u5404\u6587\u4EF6\u8DEF\u5F84\n ama config edit \u7528 $VISUAL / $EDITOR \u6253\u5F00 config.json\n ama init [--force] \u5EFA\u914D\u7F6E\u76EE\u5F55\uFF080700\uFF09\u4E0E config.json\u3001config.schema.json\uFF1B\u5DF2\u6709\u7684\u4E0D\u8986\u76D6\n ama stats [--since 7d] [--by day|week|month|provider|channel|model|project] [--all] [--json]\n \u8DE8\u4F1A\u8BDD\u7EDF\u8BA1\uFF1A\u8BF7\u6C42\u3001token\u3001\u7F13\u5B58\u547D\u4E2D\u7387\u3001\u8D39\u7528\u3001\u5DE5\u5177\u8C03\u7528\n\n\u5176\u5B83\n -h, --help \u8F93\u51FA\u672C\u5E2E\u52A9\n -v, --version \u8F93\u51FA\u7248\u672C\n\n\u9000\u51FA\u7801\uFF1A0 \u6B63\u5E38 \u00B7 1 \u8FD0\u884C\u671F\u9519\u8BEF \u00B7 2 \u7528\u6CD5\u9519\u8BEF \u00B7 3 \u914D\u7F6E\u9519\u8BEF \u00B7 4 \u65E0\u53EF\u7528\u6A21\u578B\u6216 key \u00B7\n 5 \u4F1A\u8BDD\u9519\u8BEF \u00B7 6 \u5BBF\u4E3B / Hook \u542F\u52A8\u5931\u8D25 \u00B7 7 -p \u6709\u5DE5\u5177\u8C03\u7528\u88AB\u62D2\uFF08\u65E0\u4EBA\u5BA1\u6279\uFF1B\u7528\n --permission-mode auto-edit|auto \u6216 --allow \u653E\u884C\uFF09\u00B7 78 \u5BBF\u4E3B API \u7248\u672C\u4E0D\u5339\u914D \u00B7\n 130 SIGINT \u00B7 143 SIGTERM\n";
|
|
74
92
|
export declare function emptyArgs(): ParsedArgs;
|
|
75
93
|
/** 解析 argv(不含 node 与脚本路径);用法错误抛 UsageError(退出码 2)。 */
|
|
76
94
|
export declare function parseArgs(argv: readonly string[]): ParseResult;
|
package/dist/cli/args.js
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
* 手写参数解析(设计 §11.1 第 2 步、§12.10、§13)。[B5]
|
|
3
3
|
*
|
|
4
4
|
* - 支持 `--opt value` 与 `--opt=value`;`--` 之后全部作为提示文本;可重复的参数累加。
|
|
5
|
-
* -
|
|
5
|
+
* - 位置参数 `-`:`-p` 一直等 stdin 到 EOF(有提示参数时也不设首字节超时)。
|
|
6
|
+
* - 子命令只在第一个参数是 `auth / sessions / models / providers / doctor / config / init` 时识别,
|
|
7
|
+
* 其余参数原样交给子命令。
|
|
6
8
|
* - 互斥:`-p` 与 `--mode rpc`;`--continue` / `--resume` / `--session-id` / `--fork` 两两互斥;
|
|
7
9
|
* `--trust` 与 `--no-trust`;`--api-key` 需要 `--model`;`--output-format` 需要 `-p`。
|
|
8
10
|
* - `--resume [id]`:下一个参数形如会话 id(无空白、不以 `-` 开头)才被当作 id;
|
|
@@ -10,15 +12,26 @@
|
|
|
10
12
|
* - `--provider` 不带 `--model` 不在这里报错,由 bootstrap 第 11 步报(退出码 2)。
|
|
11
13
|
*/
|
|
12
14
|
import { AmaError } from "../errors.js";
|
|
15
|
+
import { PERMISSION_MODES_STRICT_FIRST } from "../permissions/types.js";
|
|
16
|
+
import { canonicalPreset } from "../config/types.js";
|
|
13
17
|
import { CODEMODE_MODES } from "../config/types.js";
|
|
14
|
-
export const SUBCOMMANDS = [
|
|
18
|
+
export const SUBCOMMANDS = [
|
|
19
|
+
"auth",
|
|
20
|
+
"sessions",
|
|
21
|
+
"models",
|
|
22
|
+
"providers",
|
|
23
|
+
"doctor",
|
|
24
|
+
"config",
|
|
25
|
+
"init",
|
|
26
|
+
"stats",
|
|
27
|
+
];
|
|
15
28
|
export class UsageError extends AmaError {
|
|
16
29
|
constructor(message) {
|
|
17
30
|
super("invalid_arguments", message, { exitCode: 2 });
|
|
18
31
|
this.name = "UsageError";
|
|
19
32
|
}
|
|
20
33
|
}
|
|
21
|
-
const PERMISSION_MODES =
|
|
34
|
+
const PERMISSION_MODES = PERMISSION_MODES_STRICT_FIRST;
|
|
22
35
|
const THINKING_LEVELS = [
|
|
23
36
|
"off",
|
|
24
37
|
"minimal",
|
|
@@ -29,8 +42,8 @@ const THINKING_LEVELS = [
|
|
|
29
42
|
];
|
|
30
43
|
const OUTPUT_FORMATS = ["text", "json", "stream-json"];
|
|
31
44
|
const QUIET_LEVELS = ["normal", "header", "silent"];
|
|
32
|
-
/** 帮助与报错按常用顺序列出(校验集合同
|
|
33
|
-
const PRESET_CHOICES = ["default", "minimal", "codemode", "coordinator"];
|
|
45
|
+
/** 帮助与报错按常用顺序列出(校验集合同 TOOLS_PRESET_INPUTS;`codemode` 是 `codemode-only` 的别名)。 */
|
|
46
|
+
const PRESET_CHOICES = ["default", "minimal", "codemode-only", "coordinator", "codemode"];
|
|
34
47
|
const SESSION_ID_LIKE = /^[A-Za-z0-9][A-Za-z0-9._:-]*$/;
|
|
35
48
|
export const HELP_TEXT = `用法:ama [选项] [提示]
|
|
36
49
|
ama <子命令> …
|
|
@@ -38,14 +51,21 @@ export const HELP_TEXT = `用法:ama [选项] [提示]
|
|
|
38
51
|
模式
|
|
39
52
|
(缺省) 终端界面;stdin / stdout 非 TTY 或 TERM=dumb 时自动降级为行式
|
|
40
53
|
--no-tui 行式界面(readline + 括号粘贴)
|
|
41
|
-
-p, --print
|
|
54
|
+
-p, --print 非交互:执行提示后退出。提示 = 参数 + stdin 管道内容;有提示参数时
|
|
55
|
+
只等管道首字节 2 s(AMA_STDIN_WAIT_MS),没收到就忽略并提示;
|
|
56
|
+
末尾加 - 则一直等到 EOF(如 npm test | ama -p 找原因 -)
|
|
57
|
+
--no-stdin -p 不读 stdin(父进程留着管道、又不想等 2 s 时)
|
|
42
58
|
--output-format <格式> -p 的输出:text(缺省)| json | stream-json
|
|
59
|
+
--max-turns <N> -p 最多跑 N 轮(一次模型请求加其工具执行算一轮);到达上限仍有
|
|
60
|
+
未完成的工具调用时提前结束,退出码 1
|
|
61
|
+
--image <文件> -p 随提示发送图片(可重复;png / jpg / gif / webp,单张 ≤ 5 MB);
|
|
62
|
+
交互界面里写 @图片路径 或粘贴图片路径
|
|
43
63
|
--mode rpc stdio JSONL 协议(供嵌入)
|
|
44
64
|
--tui-mode <模式> 显示模式,第一期只有 regular(主屏)
|
|
45
65
|
--quiet-startup <档> 启动画面:normal | header | silent
|
|
46
66
|
|
|
47
67
|
模型
|
|
48
|
-
--model <provider/id> 模型(可配合 --provider 只写 id)
|
|
68
|
+
--model <provider/id> 模型(可配合 --provider 只写 id;@渠道 指定渠道,如 packy/kimi-k2.5@messages)
|
|
49
69
|
--provider <id> 供应商(必须同时给 --model)
|
|
50
70
|
--api-key <key> 只用于本次启动的 key(需要 --model;优先用 ama auth set)
|
|
51
71
|
--thinking <级别> off | minimal | low | medium | high | xhigh
|
|
@@ -56,14 +76,20 @@ export const HELP_TEXT = `用法:ama [选项] [提示]
|
|
|
56
76
|
--session-id <id> 使用指定 id 的会话(不存在则新建)
|
|
57
77
|
--fork <id> 从指定会话分叉出新会话
|
|
58
78
|
--session-dir <目录> 会话目录(缺省 ~/.local/share/ama/sessions)
|
|
79
|
+
--no-session 会话只在内存里,不写会话文件(之后无法 --resume)
|
|
80
|
+
--from <id>[#编号] 用旧会话的一条用户消息作提示(缺省最后一条;-p 时连图片一起;
|
|
81
|
+
编号见 ama sessions show)
|
|
59
82
|
|
|
60
83
|
权限与信任
|
|
61
|
-
--permission-mode <模式>
|
|
84
|
+
--permission-mode <模式> default | auto-edit | plan | auto | full-auto | allowlist
|
|
85
|
+
(auto 由 ama 判断每一步;allowlist 只放行 allow 规则命中的,适合 CI)
|
|
62
86
|
--allow <规则> 追加允许规则,可重复(如 "bash(git status*)")
|
|
63
87
|
--deny <规则> 追加拒绝规则,可重复(如 "write(**/.env*)")
|
|
64
88
|
--trust / --no-trust 信任 / 不信任当前项目(项目级 Hook、Skill、提示模板)
|
|
65
89
|
|
|
66
90
|
资源
|
|
91
|
+
--system-prompt <文本|@文件> 追加系统提示:缺省作为最后一条规则追加(工具表等前缀不变,利于缓存)
|
|
92
|
+
--system-prompt-mode <方式> append(缺省)| replace(替换开头的角色说明,工具与项目上下文保留)
|
|
67
93
|
--profile <文件> 宿主 profile.json(字段等价于对应参数,命令行优先)
|
|
68
94
|
--host <模块> 宿主适配器模块(CJS / ESM)
|
|
69
95
|
--instructions <文件> 追加指令文件,可重复
|
|
@@ -71,29 +97,46 @@ export const HELP_TEXT = `用法:ama [选项] [提示]
|
|
|
71
97
|
--auth-file <文件> auth.json 位置(缺省 ~/.config/ama/auth.json)
|
|
72
98
|
--tools <a,b,…> 只启用这些工具
|
|
73
99
|
--exclude-tools <a,b,…> 禁用这些工具
|
|
74
|
-
--tools-preset <名> 工具预设:default(缺省)| minimal | codemode | coordinator
|
|
75
|
-
|
|
100
|
+
--tools-preset <名> 工具预设:default(缺省)| minimal | codemode-only | coordinator
|
|
101
|
+
(codemode 是 codemode-only 的旧名,仍可用)
|
|
102
|
+
--codemode <模式> codemode 调用方式:off | on | only(缺省随预设)
|
|
76
103
|
|
|
77
104
|
子命令
|
|
78
105
|
ama auth set <provider> 从 stdin 读取 key 写入 auth.json(0600)
|
|
79
106
|
ama auth list 列出已保存 key 的供应商(不显示 key)
|
|
80
107
|
ama auth remove <provider> 删除已保存的 key
|
|
81
108
|
ama sessions list|show|prune 会话管理
|
|
109
|
+
ama sessions search <关键词|/正则/> [--all] [--role user|assistant|tool] [--since 7d] [--limit N]
|
|
110
|
+
跨会话全文检索
|
|
111
|
+
ama sessions export <id> [--format md|json|jsonl] [--output <文件>] [--branch leaf|all]
|
|
112
|
+
导出会话(已脱敏)
|
|
82
113
|
ama models list [--provider <id>] 列出模型(含来源与 key 状态)
|
|
83
114
|
ama models check <provider/id> 发一次最小请求检查可用性
|
|
84
115
|
ama models discover <provider> [--probe] [--write] [--limit N]
|
|
85
116
|
从中转 /v1/models 列出模型,探测协议并写入配置
|
|
117
|
+
ama models refresh-catalog 强制刷新 models.dev 模型元数据缓存
|
|
118
|
+
ama providers add <id> --base-url <url> [--key-env VAR] [--probe] [--channel n=api@url] [--yes]
|
|
119
|
+
一键接入:列模型、补 models.dev 元数据、探测渠道、写入配置
|
|
120
|
+
ama providers list|channels <id>|remove <id>|refresh <id>
|
|
121
|
+
供应商 → 渠道 → 模型;删除;重拉模型列表
|
|
86
122
|
ama models cache-probe <provider/id> [--tokens N] [--gap-ms MS] [--yes] [--json]
|
|
87
123
|
判断端点是否报告缓存命中
|
|
88
124
|
ama doctor 配置层级、信任、key 来源、Hook、终端能力
|
|
89
125
|
ama config show [--json] 生效配置与每项来源、将使用的模型
|
|
126
|
+
ama config path 配置目录、数据目录与各文件路径
|
|
127
|
+
ama config edit 用 $VISUAL / $EDITOR 打开 config.json
|
|
128
|
+
ama init [--force] 建配置目录(0700)与 config.json、config.schema.json;已有的不覆盖
|
|
129
|
+
ama stats [--since 7d] [--by day|week|month|provider|channel|model|project] [--all] [--json]
|
|
130
|
+
跨会话统计:请求、token、缓存命中率、费用、工具调用
|
|
90
131
|
|
|
91
132
|
其它
|
|
92
133
|
-h, --help 输出本帮助
|
|
93
134
|
-v, --version 输出版本
|
|
94
135
|
|
|
95
136
|
退出码:0 正常 · 1 运行期错误 · 2 用法错误 · 3 配置错误 · 4 无可用模型或 key ·
|
|
96
|
-
5 会话错误 · 6 宿主 / Hook 启动失败 ·
|
|
137
|
+
5 会话错误 · 6 宿主 / Hook 启动失败 · 7 -p 有工具调用被拒(无人审批;用
|
|
138
|
+
--permission-mode auto-edit|auto 或 --allow 放行)· 78 宿主 API 版本不匹配 ·
|
|
139
|
+
130 SIGINT · 143 SIGTERM
|
|
97
140
|
`;
|
|
98
141
|
const VALUE_OPTIONS = new Set([
|
|
99
142
|
"profile",
|
|
@@ -119,6 +162,11 @@ const VALUE_OPTIONS = new Set([
|
|
|
119
162
|
"exclude-tools",
|
|
120
163
|
"tools-preset",
|
|
121
164
|
"codemode",
|
|
165
|
+
"image",
|
|
166
|
+
"max-turns",
|
|
167
|
+
"system-prompt",
|
|
168
|
+
"system-prompt-mode",
|
|
169
|
+
"from",
|
|
122
170
|
]);
|
|
123
171
|
const FLAG_ALIASES = {
|
|
124
172
|
"-h": "help",
|
|
@@ -146,10 +194,14 @@ export function emptyArgs() {
|
|
|
146
194
|
skillDirs: [],
|
|
147
195
|
allow: [],
|
|
148
196
|
deny: [],
|
|
197
|
+
images: [],
|
|
149
198
|
continue: false,
|
|
150
199
|
resume: false,
|
|
151
200
|
print: false,
|
|
152
201
|
noTui: false,
|
|
202
|
+
noSession: false,
|
|
203
|
+
stdin: false,
|
|
204
|
+
noStdin: false,
|
|
153
205
|
positionals: [],
|
|
154
206
|
};
|
|
155
207
|
}
|
|
@@ -223,11 +275,30 @@ function applyValue(args, option, value) {
|
|
|
223
275
|
args.excludeTools = [...(args.excludeTools ?? []), ...list(value)];
|
|
224
276
|
break;
|
|
225
277
|
case "tools-preset":
|
|
226
|
-
args.toolsPreset = choice(option, value, PRESET_CHOICES);
|
|
278
|
+
args.toolsPreset = canonicalPreset(choice(option, value, PRESET_CHOICES));
|
|
227
279
|
break;
|
|
228
280
|
case "codemode":
|
|
229
281
|
args.codemode = choice(option, value, CODEMODE_MODES);
|
|
230
282
|
break;
|
|
283
|
+
case "image":
|
|
284
|
+
args.images.push(value);
|
|
285
|
+
break;
|
|
286
|
+
case "system-prompt":
|
|
287
|
+
args.systemPrompt = value;
|
|
288
|
+
break;
|
|
289
|
+
case "system-prompt-mode":
|
|
290
|
+
args.systemPromptMode = choice(option, value, ["append", "replace"]);
|
|
291
|
+
break;
|
|
292
|
+
case "max-turns": {
|
|
293
|
+
const turns = Number(value);
|
|
294
|
+
if (!Number.isInteger(turns) || turns < 1)
|
|
295
|
+
throw new UsageError(`--max-turns 应为正整数(收到 ${value})`);
|
|
296
|
+
args.maxTurns = turns;
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
case "from":
|
|
300
|
+
args.from = value;
|
|
301
|
+
break;
|
|
231
302
|
}
|
|
232
303
|
}
|
|
233
304
|
function applyFlag(args, name) {
|
|
@@ -247,6 +318,12 @@ function applyFlag(args, name) {
|
|
|
247
318
|
case "no-tui":
|
|
248
319
|
args.noTui = true;
|
|
249
320
|
return true;
|
|
321
|
+
case "no-session":
|
|
322
|
+
args.noSession = true;
|
|
323
|
+
return true;
|
|
324
|
+
case "no-stdin":
|
|
325
|
+
args.noStdin = true;
|
|
326
|
+
return true;
|
|
250
327
|
case "trust":
|
|
251
328
|
case "no-trust": {
|
|
252
329
|
const value = name === "trust";
|
|
@@ -271,12 +348,31 @@ function validate(args) {
|
|
|
271
348
|
].filter((f) => f !== undefined);
|
|
272
349
|
if (sessionFlags.length > 1)
|
|
273
350
|
throw new UsageError(`${sessionFlags.join(" 与 ")} 不能同时使用`);
|
|
351
|
+
if (args.noSession && sessionFlags.length > 0) {
|
|
352
|
+
throw new UsageError(`--no-session 与 ${sessionFlags[0]} 不能同时使用`);
|
|
353
|
+
}
|
|
274
354
|
if (args.apiKey !== undefined && args.model === undefined) {
|
|
275
355
|
throw new UsageError("--api-key 需要同时给出 --model");
|
|
276
356
|
}
|
|
277
357
|
if (args.outputFormat !== undefined && !args.print) {
|
|
278
358
|
throw new UsageError("--output-format 只用于 -p / --print");
|
|
279
359
|
}
|
|
360
|
+
if (args.systemPromptMode !== undefined && args.systemPrompt === undefined) {
|
|
361
|
+
throw new UsageError("--system-prompt-mode 需要同时给出 --system-prompt");
|
|
362
|
+
}
|
|
363
|
+
if (args.maxTurns !== undefined && !args.print) {
|
|
364
|
+
throw new UsageError("--max-turns 只用于 -p / --print");
|
|
365
|
+
}
|
|
366
|
+
if (args.noStdin && !args.print)
|
|
367
|
+
throw new UsageError("--no-stdin 只用于 -p / --print");
|
|
368
|
+
if (args.noStdin && args.stdin)
|
|
369
|
+
throw new UsageError("--no-stdin 与位置参数 - 不能同时使用");
|
|
370
|
+
if (args.stdin && !args.print) {
|
|
371
|
+
throw new UsageError("位置参数 - (从 stdin 读提示)只用于 -p / --print");
|
|
372
|
+
}
|
|
373
|
+
if (args.images.length > 0 && !args.print) {
|
|
374
|
+
throw new UsageError("--image 只用于 -p / --print(交互界面里写 @图片路径)");
|
|
375
|
+
}
|
|
280
376
|
}
|
|
281
377
|
/** 解析 argv(不含 node 与脚本路径);用法错误抛 UsageError(退出码 2)。 */
|
|
282
378
|
export function parseArgs(argv) {
|
|
@@ -291,7 +387,11 @@ export function parseArgs(argv) {
|
|
|
291
387
|
args.positionals.push(...argv.slice(i + 1));
|
|
292
388
|
break;
|
|
293
389
|
}
|
|
294
|
-
if (
|
|
390
|
+
if (token === "-") {
|
|
391
|
+
args.stdin = true;
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
if (!token.startsWith("-")) {
|
|
295
395
|
args.positionals.push(token);
|
|
296
396
|
continue;
|
|
297
397
|
}
|
package/dist/cli/bootstrap.js
CHANGED
|
@@ -20,8 +20,10 @@ import { HookDispatcher } from "../hooks/dispatcher.js";
|
|
|
20
20
|
import { AgentEventBus, createHostApi } from "../host/api-impl.js";
|
|
21
21
|
import { activateHost, disposeHost } from "../host/loader.js";
|
|
22
22
|
import { HELP_TEXT, parseArgs, UsageError } from "./args.js";
|
|
23
|
+
import { applyFromOption } from "./from-prompt.js";
|
|
23
24
|
import { ExitCode } from "./exit-codes.js";
|
|
24
25
|
import { applyProfile, applyToolFilters, decideMode, defaultSendUser, instructionSources, resolveModel, sessionRequestOf, sourceOf, step, thinkingOf, toStartupError, } from "./startup-steps.js";
|
|
26
|
+
import { resolveSystemPromptArg } from "./system-prompt-arg.js";
|
|
25
27
|
/** §11.1 第 3–14 步。 */
|
|
26
28
|
export async function bootstrap(argsIn, deps, io) {
|
|
27
29
|
const warnings = [];
|
|
@@ -143,6 +145,7 @@ export async function bootstrap(argsIn, deps, io) {
|
|
|
143
145
|
? resolve(io.cwd, args.authFile)
|
|
144
146
|
: defaultAuthFilePath(paths.configDir),
|
|
145
147
|
authEnv: profile?.authEnv ?? true,
|
|
148
|
+
dataDir: paths.dataDir,
|
|
146
149
|
...(args.apiKey !== undefined && args.model !== undefined
|
|
147
150
|
? {
|
|
148
151
|
cliApiKey: {
|
|
@@ -153,10 +156,15 @@ export async function bootstrap(argsIn, deps, io) {
|
|
|
153
156
|
}
|
|
154
157
|
: {}),
|
|
155
158
|
}));
|
|
156
|
-
const { model, provider } = await step(ExitCode.NoModel, "模型", () => resolveModel(args, providers, sessionManager, config.defaultModel, deps, interactive));
|
|
159
|
+
const { model, provider } = await step(ExitCode.NoModel, "模型", () => resolveModel(args, providers, sessionManager, config.defaultModel, deps, interactive, io.env));
|
|
157
160
|
const thinkingLevel = thinkingOf(args, sessionManager, config.thinkingLevel);
|
|
158
161
|
// 12. 工具注册表
|
|
159
|
-
const tools = await step(ExitCode.RuntimeError, "工具", () => deps.tools.create({
|
|
162
|
+
const tools = await step(ExitCode.RuntimeError, "工具", () => deps.tools.create({
|
|
163
|
+
config,
|
|
164
|
+
cwd: sessionCwd,
|
|
165
|
+
mode,
|
|
166
|
+
paths: { configDir: paths.configDir, dataDir: paths.dataDir },
|
|
167
|
+
}));
|
|
160
168
|
for (const name of config.tools?.disabled ?? []) {
|
|
161
169
|
if (tools.get(name) === undefined)
|
|
162
170
|
warn(`config tools.disabled:未知工具 ${name},已忽略`);
|
|
@@ -199,12 +207,14 @@ export async function bootstrap(argsIn, deps, io) {
|
|
|
199
207
|
// 14. 组装 AgentSession、session_start、SessionStart Hook
|
|
200
208
|
const unattended = mode === "print";
|
|
201
209
|
const builtinDeny = config.permission?.builtinDeny;
|
|
210
|
+
const autoSafeCommands = config.permission?.autoSafeCommands;
|
|
202
211
|
const permission = await step(ExitCode.Config, "权限", () => deps.permissions.create({
|
|
203
212
|
mode: config.permission?.mode ?? "default",
|
|
204
213
|
rules: merged.ruleSpecs,
|
|
205
214
|
unattended,
|
|
206
215
|
cwd: sessionCwd,
|
|
207
216
|
...(builtinDeny !== undefined ? { builtinDeny } : {}),
|
|
217
|
+
...(autoSafeCommands !== undefined ? { autoSafeCommands } : {}),
|
|
208
218
|
}));
|
|
209
219
|
const hooks = new HookDispatcher({
|
|
210
220
|
hooks: hookConfig.hooks,
|
|
@@ -259,6 +269,16 @@ export async function bootstrap(argsIn, deps, io) {
|
|
|
259
269
|
unattended,
|
|
260
270
|
warn,
|
|
261
271
|
};
|
|
272
|
+
const overrides = {};
|
|
273
|
+
if (args.maxTurns !== undefined)
|
|
274
|
+
overrides.maxTurns = args.maxTurns;
|
|
275
|
+
if (args.noSession)
|
|
276
|
+
overrides.noSession = true;
|
|
277
|
+
const systemPrompt = await step(ExitCode.Config, "--system-prompt", () => resolveSystemPromptArg(args.systemPrompt, args.systemPromptMode, io.cwd));
|
|
278
|
+
if (systemPrompt !== undefined)
|
|
279
|
+
overrides.systemPrompt = systemPrompt;
|
|
280
|
+
if (Object.keys(overrides).length > 0)
|
|
281
|
+
assembly.overrides = overrides;
|
|
262
282
|
session = await step(ExitCode.RuntimeError, "会话组装", () => deps.session.create(assembly));
|
|
263
283
|
const active = session;
|
|
264
284
|
let disposed;
|
|
@@ -358,11 +378,15 @@ export async function runCli(argv, deps, io) {
|
|
|
358
378
|
return reportError(error, io);
|
|
359
379
|
}
|
|
360
380
|
const restore = runtime.mode === "print" || runtime.mode === "rpc" ? takeOverStdout() : () => undefined;
|
|
381
|
+
let cleanupFrom = () => undefined;
|
|
361
382
|
try {
|
|
362
383
|
if (runtime.mode !== "interactive")
|
|
363
384
|
for (const w of runtime.warnings)
|
|
364
385
|
io.stderr(`ama: 警告:${w}\n`);
|
|
365
|
-
|
|
386
|
+
// [W4-D] --from:旧会话的一条用户消息作提示(-p 时连图片,临时文件在 finally 删除)。
|
|
387
|
+
const from = applyFromOption(args, runtime, io);
|
|
388
|
+
cleanupFrom = from.cleanup;
|
|
389
|
+
const context = from.context;
|
|
366
390
|
const runner = deps.modes[runtime.mode];
|
|
367
391
|
if (runner === undefined)
|
|
368
392
|
throw new AmaError("not_implemented", `模式 ${runtime.mode} 尚未装配`, { exitCode: 1 });
|
|
@@ -382,6 +406,7 @@ export async function runCli(argv, deps, io) {
|
|
|
382
406
|
}
|
|
383
407
|
finally {
|
|
384
408
|
await runtime.dispose("exit").catch(() => undefined);
|
|
409
|
+
cleanupFrom();
|
|
385
410
|
restore();
|
|
386
411
|
}
|
|
387
412
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* codemode 缺省关闭的一次性提示(设计 §5.5「默认开放」):`default` 预设跟随预设时只在沙箱 strict
|
|
3
|
+
* (Node ≥ 25)开 codemode;Node 22 / 24 下缺省关闭,启动时提示一次怎么显式开启。
|
|
4
|
+
*
|
|
5
|
+
* - 只在「跟随预设」且预设是 `default`、运行时不是 strict 时提示;显式写了 `codemode.mode`(含 off)
|
|
6
|
+
* 不提示;
|
|
7
|
+
* - 每个配置目录只提示一次:已提示过的配置目录记在 `<数据目录>/notices.json`;读写失败不影响启动
|
|
8
|
+
* (至多多提示一次)。
|
|
9
|
+
*/
|
|
10
|
+
import type { SandboxCapability } from "../codemode/capability.js";
|
|
11
|
+
import type { AmaConfig } from "../config/types.js";
|
|
12
|
+
export declare const NOTICES_FILE = "notices.json";
|
|
13
|
+
export declare function codemodeNoticeText(capability: Pick<SandboxCapability, "nodeMajor">): string;
|
|
14
|
+
/** 需要提示时返回文案并记下(之后同一配置目录不再提示);不需要时 undefined。 */
|
|
15
|
+
export declare function takeCodemodeNotice(input: {
|
|
16
|
+
config: Pick<AmaConfig, "tools" | "codemode">;
|
|
17
|
+
capability: Pick<SandboxCapability, "strict" | "nodeMajor">;
|
|
18
|
+
configDir: string;
|
|
19
|
+
dataDir: string;
|
|
20
|
+
}): string | undefined;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* codemode 缺省关闭的一次性提示(设计 §5.5「默认开放」):`default` 预设跟随预设时只在沙箱 strict
|
|
3
|
+
* (Node ≥ 25)开 codemode;Node 22 / 24 下缺省关闭,启动时提示一次怎么显式开启。
|
|
4
|
+
*
|
|
5
|
+
* - 只在「跟随预设」且预设是 `default`、运行时不是 strict 时提示;显式写了 `codemode.mode`(含 off)
|
|
6
|
+
* 不提示;
|
|
7
|
+
* - 每个配置目录只提示一次:已提示过的配置目录记在 `<数据目录>/notices.json`;读写失败不影响启动
|
|
8
|
+
* (至多多提示一次)。
|
|
9
|
+
*/
|
|
10
|
+
import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { resolveCodemodeMode } from "../tools/presets.js";
|
|
13
|
+
export const NOTICES_FILE = "notices.json";
|
|
14
|
+
const KEY = "codemodeNonStrictDefault";
|
|
15
|
+
function readNotices(path) {
|
|
16
|
+
try {
|
|
17
|
+
const value = JSON.parse(readFileSync(path, "utf8"));
|
|
18
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
19
|
+
const shown = value[KEY];
|
|
20
|
+
return {
|
|
21
|
+
version: 1,
|
|
22
|
+
...(Array.isArray(shown) ? { [KEY]: shown.filter((s) => typeof s === "string") } : {}),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// 不存在或损坏:按没提示过处理
|
|
28
|
+
}
|
|
29
|
+
return { version: 1 };
|
|
30
|
+
}
|
|
31
|
+
export function codemodeNoticeText(capability) {
|
|
32
|
+
return (`Node ${capability.nodeMajor} < 25:codemode 沙箱的网络未隔离,codemode 缺省关闭;` +
|
|
33
|
+
"用 `--codemode on` 或 config 的 codemode.mode 开启(每个配置目录只提示一次)");
|
|
34
|
+
}
|
|
35
|
+
/** 需要提示时返回文案并记下(之后同一配置目录不再提示);不需要时 undefined。 */
|
|
36
|
+
export function takeCodemodeNotice(input) {
|
|
37
|
+
const resolved = resolveCodemodeMode(input.config, input.capability.strict);
|
|
38
|
+
if (resolved.source !== "preset" || resolved.preset !== "default" || input.capability.strict)
|
|
39
|
+
return undefined;
|
|
40
|
+
const path = join(input.dataDir, NOTICES_FILE);
|
|
41
|
+
const notices = readNotices(path);
|
|
42
|
+
const shown = notices[KEY] ?? [];
|
|
43
|
+
if (shown.includes(input.configDir))
|
|
44
|
+
return undefined;
|
|
45
|
+
try {
|
|
46
|
+
mkdirSync(input.dataDir, { recursive: true });
|
|
47
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
48
|
+
writeFileSync(tmp, `${JSON.stringify({ ...notices, [KEY]: [...shown, input.configDir] })}\n`);
|
|
49
|
+
renameSync(tmp, path);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// 写不进去也照常提示
|
|
53
|
+
}
|
|
54
|
+
return codemodeNoticeText(input.capability);
|
|
55
|
+
}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* - 零配置(设计 §10.0):没有 `defaultModel`、也没有任何需要 key 的供应商配了 key 时,探测本地
|
|
11
11
|
* ollama / lmstudio(短超时),把枚举到的模型加进注册表,供 `pickDefaultModel` 选用。
|
|
12
12
|
*/
|
|
13
|
+
import { loadModelsDevIndex } from "../ai/providers/models-dev-cache.js";
|
|
13
14
|
import { ProviderRegistry, discoverLocalModels } from "../ai/providers/registry.js";
|
|
14
15
|
export const LOCAL_PROBE_TIMEOUT_MS = 300;
|
|
15
16
|
export const NO_LOCAL_PROBE_ENV = "AMA_NO_LOCAL_PROBE";
|
|
@@ -45,6 +46,7 @@ export function withExtraProviders(config, providers) {
|
|
|
45
46
|
}
|
|
46
47
|
export async function buildProviderRegistry(input, options = {}) {
|
|
47
48
|
const config = withExtraProviders(input.config, options.providers);
|
|
49
|
+
const dataDir = input.dataDir;
|
|
48
50
|
const make = (cliApiKey) => new ProviderRegistry({
|
|
49
51
|
config,
|
|
50
52
|
apis: options.apis,
|
|
@@ -57,6 +59,7 @@ export async function buildProviderRegistry(input, options = {}) {
|
|
|
57
59
|
env: options.env,
|
|
58
60
|
},
|
|
59
61
|
onWarning: options.warn,
|
|
62
|
+
...(dataDir !== undefined ? { modelsDev: () => loadModelsDevIndex(dataDir) } : {}),
|
|
60
63
|
});
|
|
61
64
|
let registry = make();
|
|
62
65
|
const cli = input.cliApiKey;
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* - 会话切换:`switchSession()` 复用同一份装配材料建新会话,`assembly.onSessionReplaced(next)`
|
|
16
16
|
* 让宿主访问、Hook 公共字段与退出 dispose 跟随新会话。
|
|
17
17
|
*/
|
|
18
|
+
import type { ProviderRegistryApi } from "../ai/types.js";
|
|
18
19
|
import { AgentSessionImpl } from "../agent/session.js";
|
|
19
20
|
import type { AgentSession, CacheSettings, SessionEvent } from "../agent/types.js";
|
|
20
21
|
import { type AmaConfig } from "../config/types.js";
|
|
@@ -32,6 +33,8 @@ export interface ComposeState {
|
|
|
32
33
|
warnings: string[];
|
|
33
34
|
/** 当前会话(工具工厂的 `session()`)。 */
|
|
34
35
|
session: AgentSession | undefined;
|
|
36
|
+
/** 第 11 步建好的供应商注册表(read 工具判断当前模型收不收图片)。 */
|
|
37
|
+
providers?: ProviderRegistryApi;
|
|
35
38
|
}
|
|
36
39
|
export declare function emptyComposeState(): ComposeState;
|
|
37
40
|
export type LogFn = (level: "debug" | "info" | "warn" | "error", message: string) => void;
|
|
@@ -44,6 +47,11 @@ export interface SessionComposeOptions {
|
|
|
44
47
|
export declare function stderrLog(env?: NodeJS.ProcessEnv): LogFn;
|
|
45
48
|
/** config `cache` 段 + 环境变量 → 会话缓存设置;非法的环境变量值忽略并 warning。 */
|
|
46
49
|
export declare function cacheSettingsFrom(config: Pick<AmaConfig, "cache">, env?: NodeJS.ProcessEnv, warn?: (message: string) => void): Partial<CacheSettings>;
|
|
50
|
+
/**
|
|
51
|
+
* 模型请求的空闲超时:`AMA_IDLE_TIMEOUT_MS` > config `request.idleTimeoutMs`;都没有 → undefined
|
|
52
|
+
* (协议层取缺省 300 000)。0 关闭;非法的环境变量值忽略并 warning。
|
|
53
|
+
*/
|
|
54
|
+
export declare function idleTimeoutFrom(config: Pick<AmaConfig, "request">, env?: NodeJS.ProcessEnv, warn?: (message: string) => void): number | undefined;
|
|
47
55
|
/** §1.4:SessionEvent → AgentEvents。 */
|
|
48
56
|
export declare function bridgeEvent(event: SessionEvent, bus: AgentEventBus): void;
|
|
49
57
|
/** 第 14 步:组装主会话。 */
|
|
@@ -83,6 +83,11 @@ function contextFiles(record) {
|
|
|
83
83
|
}
|
|
84
84
|
function systemInput(record, active) {
|
|
85
85
|
const system = { contextFiles: contextFiles(record) };
|
|
86
|
+
const override = record.assembly.overrides?.systemPrompt;
|
|
87
|
+
if (override?.mode === "replace")
|
|
88
|
+
system.preamble = override.text;
|
|
89
|
+
else if (override !== undefined)
|
|
90
|
+
system.extraRules = [override.text];
|
|
86
91
|
const index = formatSkillIndex(record.state.skills, {
|
|
87
92
|
hasSkillTool: false,
|
|
88
93
|
hasReadTool: active.includes("read"),
|
|
@@ -145,6 +150,20 @@ export function cacheSettingsFrom(config, env = process.env, warn = () => undefi
|
|
|
145
150
|
}
|
|
146
151
|
return settings;
|
|
147
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* 模型请求的空闲超时:`AMA_IDLE_TIMEOUT_MS` > config `request.idleTimeoutMs`;都没有 → undefined
|
|
155
|
+
* (协议层取缺省 300 000)。0 关闭;非法的环境变量值忽略并 warning。
|
|
156
|
+
*/
|
|
157
|
+
export function idleTimeoutFrom(config, env = process.env, warn = () => undefined) {
|
|
158
|
+
const raw = env["AMA_IDLE_TIMEOUT_MS"];
|
|
159
|
+
if (raw !== undefined && raw.trim() !== "") {
|
|
160
|
+
const value = Number(raw);
|
|
161
|
+
if (Number.isFinite(value) && value >= 0)
|
|
162
|
+
return value;
|
|
163
|
+
warn(`AMA_IDLE_TIMEOUT_MS=${raw} 无效(应为不小于 0 的毫秒数),已忽略`);
|
|
164
|
+
}
|
|
165
|
+
return config.request?.idleTimeoutMs;
|
|
166
|
+
}
|
|
148
167
|
/** §1.4:SessionEvent → AgentEvents。 */
|
|
149
168
|
export function bridgeEvent(event, bus) {
|
|
150
169
|
switch (event.type) {
|
|
@@ -242,6 +261,15 @@ function buildSession(record, manager, model, thinkingLevel) {
|
|
|
242
261
|
cache: cacheSettingsFrom(config, process.env, (message) => record.log("warn", message)),
|
|
243
262
|
warmingDecider: () => assembly.host.warmingDecider?.(),
|
|
244
263
|
};
|
|
264
|
+
const maxTurns = assembly.overrides?.maxTurns;
|
|
265
|
+
if (maxTurns !== undefined)
|
|
266
|
+
options.maxTurns = maxTurns;
|
|
267
|
+
const idle = idleTimeoutFrom(config, process.env, (message) => record.log("warn", message));
|
|
268
|
+
if (idle !== undefined)
|
|
269
|
+
options.idleTimeoutMs = idle;
|
|
270
|
+
const autoModel = config.permission?.autoModel;
|
|
271
|
+
if (autoModel !== undefined)
|
|
272
|
+
options.permissionClassifier = { model: autoModel };
|
|
245
273
|
const maxChars = config.tools?.maxToolResultChars;
|
|
246
274
|
if (maxChars !== undefined)
|
|
247
275
|
options.maxToolResultChars = maxChars;
|
|
@@ -329,7 +357,10 @@ export async function switchSession(target, request) {
|
|
|
329
357
|
let source;
|
|
330
358
|
switch (request.kind) {
|
|
331
359
|
case "new":
|
|
332
|
-
manager =
|
|
360
|
+
manager =
|
|
361
|
+
assembly.overrides?.noSession === true
|
|
362
|
+
? SessionManager.inMemory(old.cwd)
|
|
363
|
+
: SessionManager.create(sessionDirForCwd(sessionDir, old.cwd), old.cwd);
|
|
333
364
|
source = "new";
|
|
334
365
|
break;
|
|
335
366
|
case "open":
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* 组装根:会话存储(实施计划 §1.1 `sessions.*`)。[B6]
|
|
3
3
|
*
|
|
4
4
|
* 会话根目录 `sessionDir` 下按 cwd 分子目录(`sessionDirForCwd`)。
|
|
5
|
-
* - `new` → 延迟落盘新建;`continue` → 本目录最近一条(没有则新建);
|
|
5
|
+
* - `new` → 延迟落盘新建;`memory`(`--no-session`)→ 内存会话,从不落盘;`continue` → 本目录最近一条(没有则新建);
|
|
6
6
|
* - `resume{id}` / `fork{id}`:先在本目录、再在全部子目录里按 id 或唯一前缀找文件;找不到 →
|
|
7
7
|
* `session_not_found`,前缀不唯一 → `invalid_arguments` 并列出候选;
|
|
8
8
|
* - `session-id{id}`:找到则打开,否则以该 id 新建;
|