@orion-agents/orion-code 0.1.2 → 0.1.4
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/README.md +96 -3
- package/README.zh-CN.md +109 -4
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +168 -54
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/types.d.ts +3 -1
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/commands/types.js.map +1 -1
- package/dist/framework/query.d.ts +3 -0
- package/dist/framework/query.d.ts.map +1 -1
- package/dist/framework/query.js +1 -0
- package/dist/framework/query.js.map +1 -1
- package/dist/framework/tool-scheduler.d.ts +61 -1
- package/dist/framework/tool-scheduler.d.ts.map +1 -1
- package/dist/framework/tool-scheduler.js +165 -47
- package/dist/framework/tool-scheduler.js.map +1 -1
- package/dist/framework/tool.d.ts +9 -0
- package/dist/framework/tool.d.ts.map +1 -1
- package/dist/framework/tool.js +2 -0
- package/dist/framework/tool.js.map +1 -1
- package/dist/ink-ui/screens/ReplScreen.d.ts +2 -1
- package/dist/ink-ui/screens/ReplScreen.d.ts.map +1 -1
- package/dist/ink-ui/screens/ReplScreen.js +65 -0
- package/dist/ink-ui/screens/ReplScreen.js.map +1 -1
- package/dist/memory/embeddings.d.ts.map +1 -1
- package/dist/memory/embeddings.js +3 -2
- package/dist/memory/embeddings.js.map +1 -1
- package/dist/memory/semantic-search.d.ts.map +1 -1
- package/dist/memory/semantic-search.js +2 -1
- package/dist/memory/semantic-search.js.map +1 -1
- package/dist/memory/vector-store.d.ts.map +1 -1
- package/dist/memory/vector-store.js +7 -3
- package/dist/memory/vector-store.js.map +1 -1
- package/dist/migration/migrate.d.ts.map +1 -1
- package/dist/migration/migrate.js +7 -11
- package/dist/migration/migrate.js.map +1 -1
- package/dist/print-ui/launch.d.ts +2 -1
- package/dist/print-ui/launch.d.ts.map +1 -1
- package/dist/print-ui/launch.js +7 -0
- package/dist/print-ui/launch.js.map +1 -1
- package/dist/runtime/agent-runtime-controller.d.ts +1 -0
- package/dist/runtime/agent-runtime-controller.d.ts.map +1 -1
- package/dist/runtime/agent-runtime-controller.js +24 -3
- package/dist/runtime/agent-runtime-controller.js.map +1 -1
- package/dist/runtime/agent-runtime-protocol.d.ts +16 -1
- package/dist/runtime/agent-runtime-protocol.d.ts.map +1 -1
- package/dist/runtime/agent-runtime-protocol.js +12 -0
- package/dist/runtime/agent-runtime-protocol.js.map +1 -1
- package/dist/runtime/chat-controller.d.ts +6 -0
- package/dist/runtime/chat-controller.d.ts.map +1 -1
- package/dist/runtime/chat-controller.js +65 -2
- package/dist/runtime/chat-controller.js.map +1 -1
- package/dist/runtime/goals/tools.d.ts.map +1 -1
- package/dist/runtime/goals/tools.js +14 -14
- package/dist/runtime/goals/tools.js.map +1 -1
- package/dist/runtime/goals/types.d.ts +6 -0
- package/dist/runtime/goals/types.d.ts.map +1 -1
- package/dist/runtime/goals/types.js.map +1 -1
- package/dist/runtime/model-coordinator.d.ts.map +1 -1
- package/dist/runtime/model-coordinator.js.map +1 -1
- package/dist/runtime/subagents/child-executor-guard.d.ts.map +1 -1
- package/dist/runtime/subagents/child-executor-guard.js +4 -0
- package/dist/runtime/subagents/child-executor-guard.js.map +1 -1
- package/dist/runtime/subagents/index.d.ts +10 -3
- package/dist/runtime/subagents/index.d.ts.map +1 -1
- package/dist/runtime/subagents/index.js +24 -1
- package/dist/runtime/subagents/index.js.map +1 -1
- package/dist/runtime/subagents/provider-gate.d.ts.map +1 -1
- package/dist/runtime/subagents/provider-gate.js +0 -1
- package/dist/runtime/subagents/provider-gate.js.map +1 -1
- package/dist/runtime/subagents/research-artifact.d.ts +94 -0
- package/dist/runtime/subagents/research-artifact.d.ts.map +1 -0
- package/dist/runtime/subagents/research-artifact.js +164 -0
- package/dist/runtime/subagents/research-artifact.js.map +1 -0
- package/dist/runtime/subagents/research-citation.d.ts +66 -0
- package/dist/runtime/subagents/research-citation.d.ts.map +1 -0
- package/dist/runtime/subagents/research-citation.js +185 -0
- package/dist/runtime/subagents/research-citation.js.map +1 -0
- package/dist/runtime/subagents/research-contract.d.ts +69 -0
- package/dist/runtime/subagents/research-contract.d.ts.map +1 -0
- package/dist/runtime/subagents/research-contract.js +232 -0
- package/dist/runtime/subagents/research-contract.js.map +1 -0
- package/dist/runtime/subagents/research-quality.d.ts +47 -0
- package/dist/runtime/subagents/research-quality.d.ts.map +1 -0
- package/dist/runtime/subagents/research-quality.js +125 -0
- package/dist/runtime/subagents/research-quality.js.map +1 -0
- package/dist/runtime/subagents/research-renderer.d.ts +79 -0
- package/dist/runtime/subagents/research-renderer.d.ts.map +1 -0
- package/dist/runtime/subagents/research-renderer.js +154 -0
- package/dist/runtime/subagents/research-renderer.js.map +1 -0
- package/dist/runtime/subagents/research-types.d.ts +105 -0
- package/dist/runtime/subagents/research-types.d.ts.map +1 -0
- package/dist/runtime/subagents/research-types.js +16 -0
- package/dist/runtime/subagents/research-types.js.map +1 -0
- package/dist/runtime/subagents/runtime-integration.d.ts +1 -1
- package/dist/runtime/subagents/runtime-integration.d.ts.map +1 -1
- package/dist/runtime/subagents/runtime-integration.js.map +1 -1
- package/dist/runtime/subagents/supervisor.d.ts +1 -1
- package/dist/runtime/subagents/supervisor.d.ts.map +1 -1
- package/dist/runtime/subagents/supervisor.js +1 -1
- package/dist/runtime/subagents/supervisor.js.map +1 -1
- package/dist/runtime/subagents/web-research-adapter.d.ts +83 -0
- package/dist/runtime/subagents/web-research-adapter.d.ts.map +1 -0
- package/dist/runtime/subagents/web-research-adapter.js +262 -0
- package/dist/runtime/subagents/web-research-adapter.js.map +1 -0
- package/dist/runtime/turn-controller.d.ts.map +1 -1
- package/dist/runtime/turn-controller.js +3 -1
- package/dist/runtime/turn-controller.js.map +1 -1
- package/dist/runtime/ui-events.d.ts +21 -0
- package/dist/runtime/ui-events.d.ts.map +1 -1
- package/dist/runtime/ui-events.js.map +1 -1
- package/dist/services/auth/auth.d.ts.map +1 -1
- package/dist/services/auth/auth.js +17 -4
- package/dist/services/auth/auth.js.map +1 -1
- package/dist/services/concurrent-sessions.d.ts.map +1 -1
- package/dist/services/concurrent-sessions.js +33 -17
- package/dist/services/concurrent-sessions.js.map +1 -1
- package/dist/services/config-dir.d.ts.map +1 -1
- package/dist/services/config-dir.js +19 -5
- package/dist/services/config-dir.js.map +1 -1
- package/dist/services/config.d.ts.map +1 -1
- package/dist/services/config.js +2 -1
- package/dist/services/config.js.map +1 -1
- package/dist/services/global-config.d.ts +31 -0
- package/dist/services/global-config.d.ts.map +1 -1
- package/dist/services/global-config.js.map +1 -1
- package/dist/services/goal-storage.d.ts.map +1 -1
- package/dist/services/goal-storage.js +22 -8
- package/dist/services/goal-storage.js.map +1 -1
- package/dist/services/llm.d.ts +17 -0
- package/dist/services/llm.d.ts.map +1 -1
- package/dist/services/llm.js +88 -31
- package/dist/services/llm.js.map +1 -1
- package/dist/services/model-catalog.d.ts +2 -0
- package/dist/services/model-catalog.d.ts.map +1 -1
- package/dist/services/model-catalog.js +25 -15
- package/dist/services/model-catalog.js.map +1 -1
- package/dist/services/model-context.d.ts.map +1 -1
- package/dist/services/model-context.js +36 -0
- package/dist/services/model-context.js.map +1 -1
- package/dist/services/model-registry.d.ts.map +1 -1
- package/dist/services/model-registry.js +32 -0
- package/dist/services/model-registry.js.map +1 -1
- package/dist/services/provider-resilience/coordinator.d.ts +1 -1
- package/dist/services/provider-resilience/coordinator.d.ts.map +1 -1
- package/dist/services/provider-resilience/coordinator.js +4 -4
- package/dist/services/provider-resilience/coordinator.js.map +1 -1
- package/dist/services/provider-resilience/error-classifier.js +20 -8
- package/dist/services/provider-resilience/error-classifier.js.map +1 -1
- package/dist/services/provider-resilience/stream-recovery.d.ts +1 -1
- package/dist/services/provider-resilience/stream-recovery.d.ts.map +1 -1
- package/dist/services/provider-resilience/stream-recovery.js +1 -1
- package/dist/services/provider-resilience/stream-recovery.js.map +1 -1
- package/dist/services/session-storage.d.ts.map +1 -1
- package/dist/services/session-storage.js +45 -14
- package/dist/services/session-storage.js.map +1 -1
- package/dist/services/storage-maintenance.d.ts.map +1 -1
- package/dist/services/storage-maintenance.js +44 -9
- package/dist/services/storage-maintenance.js.map +1 -1
- package/dist/services/task-manager.d.ts +3 -3
- package/dist/services/task-manager.d.ts.map +1 -1
- package/dist/services/tool-allowlist.d.ts +100 -0
- package/dist/services/tool-allowlist.d.ts.map +1 -0
- package/dist/services/tool-allowlist.js +250 -0
- package/dist/services/tool-allowlist.js.map +1 -0
- package/dist/services/web-search-adapters.d.ts.map +1 -1
- package/dist/services/web-search-adapters.js +48 -18
- package/dist/services/web-search-adapters.js.map +1 -1
- package/dist/services/web-search-mcp.d.ts.map +1 -1
- package/dist/services/web-search-mcp.js +27 -11
- package/dist/services/web-search-mcp.js.map +1 -1
- package/dist/services/yaml-config.d.ts.map +1 -1
- package/dist/services/yaml-config.js +2 -1
- package/dist/services/yaml-config.js.map +1 -1
- package/dist/skills/loader.d.ts.map +1 -1
- package/dist/skills/loader.js +3 -2
- package/dist/skills/loader.js.map +1 -1
- package/dist/terminal-ui/launch.d.ts +22 -2
- package/dist/terminal-ui/launch.d.ts.map +1 -1
- package/dist/terminal-ui/launch.js +150 -1
- package/dist/terminal-ui/launch.js.map +1 -1
- package/dist/terminal-ui/raw-editor.js.map +1 -1
- package/dist/tools/bash_security.d.ts +50 -18
- package/dist/tools/bash_security.d.ts.map +1 -1
- package/dist/tools/bash_security.js +394 -61
- package/dist/tools/bash_security.js.map +1 -1
- package/dist/tools/git.d.ts +4 -0
- package/dist/tools/git.d.ts.map +1 -1
- package/dist/tools/git.js +310 -3
- package/dist/tools/git.js.map +1 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +87 -25
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/mcp.d.ts +8 -2
- package/dist/tools/mcp.d.ts.map +1 -1
- package/dist/tools/mcp.js +44 -23
- package/dist/tools/mcp.js.map +1 -1
- package/dist/tools/sandbox.d.ts +139 -0
- package/dist/tools/sandbox.d.ts.map +1 -0
- package/dist/tools/sandbox.js +485 -0
- package/dist/tools/sandbox.js.map +1 -0
- package/dist/tools/web.d.ts.map +1 -1
- package/dist/tools/web.js +113 -42
- package/dist/tools/web.js.map +1 -1
- package/dist/tui-core/frame.js.map +1 -1
- package/dist/tui-ui/launch.d.ts.map +1 -1
- package/dist/tui-ui/launch.js +46 -8
- package/dist/tui-ui/launch.js.map +1 -1
- package/dist/tui-ui/layout.d.ts.map +1 -1
- package/dist/tui-ui/layout.js +62 -0
- package/dist/tui-ui/layout.js.map +1 -1
- package/dist/tui-ui/runner.d.ts +6 -0
- package/dist/tui-ui/runner.d.ts.map +1 -1
- package/dist/tui-ui/runner.js +81 -1
- package/dist/tui-ui/runner.js.map +1 -1
- package/dist/tui-ui/state.d.ts +19 -1
- package/dist/tui-ui/state.d.ts.map +1 -1
- package/dist/tui-ui/state.js +35 -7
- package/dist/tui-ui/state.js.map +1 -1
- package/dist/tui-ui/terminal-image.d.ts +3 -13
- package/dist/tui-ui/terminal-image.d.ts.map +1 -1
- package/dist/tui-ui/terminal-image.js +5 -160
- package/dist/tui-ui/terminal-image.js.map +1 -1
- package/dist/utils/debug-log.d.ts +52 -0
- package/dist/utils/debug-log.d.ts.map +1 -0
- package/dist/utils/debug-log.js +91 -0
- package/dist/utils/debug-log.js.map +1 -0
- package/dist/utils/errors.d.ts +25 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +47 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/mask.d.ts +28 -0
- package/dist/utils/mask.d.ts.map +1 -0
- package/dist/utils/mask.js +54 -0
- package/dist/utils/mask.js.map +1 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **Goal-driven coding agent for the terminal.**
|
|
4
4
|
>
|
|
5
|
-
> v0.1.
|
|
5
|
+
> v0.1.4 — Goal continuity, model config & shell sandbox POC
|
|
6
6
|
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](https://nodejs.org)
|
|
@@ -35,8 +35,8 @@ Orion Code is a terminal-based coding agent. It wraps LLM APIs in a harness of s
|
|
|
35
35
|
### Install & Run
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
-
# Install the v0.1.
|
|
39
|
-
npm install -g @orion-agents/orion-code@0.1.
|
|
38
|
+
# Install the v0.1.4 release:
|
|
39
|
+
npm install -g @orion-agents/orion-code@0.1.4
|
|
40
40
|
|
|
41
41
|
# Or run from a checked-out source tree:
|
|
42
42
|
npm ci
|
|
@@ -73,6 +73,10 @@ orion -p "review the current git diff"
|
|
|
73
73
|
echo "summarize this project" | orion --print
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
+
> **Pre-release note.** `0.1.4` is the in-development line on the `v0.1.4` branch and is
|
|
77
|
+
> not on npm yet — `0.1.3` is the current published release. Until `v0.1.4` is tagged and
|
|
78
|
+
> published, install from a source checkout. This note is removed at release.
|
|
79
|
+
|
|
76
80
|
### TUI startup banner
|
|
77
81
|
|
|
78
82
|
The default TUI displays a portable sky-blue pixel banner: a compact landscape
|
|
@@ -147,6 +151,78 @@ Configuration: `~/.orion-code/orion.json` | Priority: `CLI flags > config > env
|
|
|
147
151
|
The renderer is a runtime choice rather than a persisted setting: `orion` starts
|
|
148
152
|
the TUI, while `--ui terminal` selects the technical renderer.
|
|
149
153
|
|
|
154
|
+
### Project tool rules (`allowedTools`)
|
|
155
|
+
|
|
156
|
+
Per-project permission rules live under `projects["<absolute path>"].allowedTools`.
|
|
157
|
+
They are scoped to a single repository and are evaluated on top of each tool's own
|
|
158
|
+
policy — they can tighten the gate, never loosen it.
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"projects": {
|
|
163
|
+
"/Users/me/work/api": {
|
|
164
|
+
"allowedTools": [
|
|
165
|
+
"exec_command(git status*)",
|
|
166
|
+
"exec_command(npm test*)",
|
|
167
|
+
"ask:exec_command(git push*)",
|
|
168
|
+
"deny:read_file(*.env)"
|
|
169
|
+
]
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
- Grammar: `[allow|ask|deny:]tool[(subject glob)]`; `*` matches any run of characters,
|
|
176
|
+
`?` a single one, and `*` as the tool name matches every tool.
|
|
177
|
+
- The subject is the call's `command` / `file_path` / `path` / `url` / `pattern` / `query`
|
|
178
|
+
argument, whichever comes first.
|
|
179
|
+
- Conflicts resolve most-restrictive-first (`deny` > `ask` > `allow`), independent of order.
|
|
180
|
+
- `allow` only skips an interactive confirmation. It never overrides a tool's own `deny`,
|
|
181
|
+
never escapes plan mode, and never auto-approves a destructive invocation.
|
|
182
|
+
- Malformed entries are ignored and listed by `/config` rather than silently applied.
|
|
183
|
+
|
|
184
|
+
### Shell execution sandbox (`sandbox`)
|
|
185
|
+
|
|
186
|
+
`exec_command` can run inside an OS-level sandbox. This is a **security POC**: the
|
|
187
|
+
backend is probed at runtime and a configured-but-unusable sandbox **fails closed**
|
|
188
|
+
(refuses to run) rather than silently degrading to an unsandboxed execution.
|
|
189
|
+
|
|
190
|
+
```json
|
|
191
|
+
{
|
|
192
|
+
"sandbox": {
|
|
193
|
+
"profile": "none",
|
|
194
|
+
"backend": "auto",
|
|
195
|
+
"allowNetwork": false,
|
|
196
|
+
"writableRoots": [],
|
|
197
|
+
"image": "alpine:latest"
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
- **Ownership** — `sandbox` lives in the global config (`~/.orion-code/orion.json`)
|
|
203
|
+
and can be overridden per project under `projects["<path>"].sandbox`. Project
|
|
204
|
+
keys win individually; absent keys inherit the global value.
|
|
205
|
+
- **`profile`** — `none` (default, no isolation, identical to the legacy `sh -c`),
|
|
206
|
+
`read-only` (no writes anywhere, no network), or `workspace-write` (writes
|
|
207
|
+
confined to the workspace + temp dirs, network still blocked unless
|
|
208
|
+
`allowNetwork: true`). An unknown value (e.g. written by a newer Orion) is a
|
|
209
|
+
hard failure, never a downgrade to `none`.
|
|
210
|
+
- **`backend`** — `auto` (default, picks the first usable backend), `seatbelt`
|
|
211
|
+
(macOS `sandbox-exec`), `bubblewrap` (Linux `bwrap`), or `docker`. Each backend
|
|
212
|
+
is validated with a real execution probe; `which`-based guessing is never used.
|
|
213
|
+
- **`image`** — required only for `docker`; names the container image to run in.
|
|
214
|
+
- **`writableRoots`** — extra host roots the `workspace-write` profile may write
|
|
215
|
+
to (in addition to the cwd and temp). Non-string / empty entries are dropped.
|
|
216
|
+
- **Migration / rollback** — adding the `sandbox` key is backward compatible: the
|
|
217
|
+
default `profile: "none"` reproduces the previous behaviour exactly. Removing the
|
|
218
|
+
key (or reverting to a pre-sandbox version) is a safe rollback; older Orion
|
|
219
|
+
simply ignores the unknown field. No secrets are stored, so no redaction is
|
|
220
|
+
required.
|
|
221
|
+
- **Known limitations** — `seatbelt` cannot be nested inside another sandbox (e.g.
|
|
222
|
+
when Orion itself runs inside an app sandbox); `docker` runs the command in a
|
|
223
|
+
separate process tree and only constrains what is bind-mounted (the image rootfs
|
|
224
|
+
is made read-only via `--read-only`); none of the backends constrain CPU/memory.
|
|
225
|
+
|
|
150
226
|
## Interactive Commands
|
|
151
227
|
|
|
152
228
|
| Command | Description |
|
|
@@ -204,6 +280,23 @@ See the [v0.1.2 release notes](https://github.com/orion-agents/orion-code/blob/m
|
|
|
204
280
|
[Goal evidence and recovery guide](https://github.com/orion-agents/orion-code/blob/main/docs/goals/goal-evidence-and-recovery.md),
|
|
205
281
|
and [execution plan](https://github.com/orion-agents/orion-code/blob/main/docs/plan/v0.1.2-execution-plan.md).
|
|
206
282
|
|
|
283
|
+
## Research-to-Evidence (v0.1.4, experimental)
|
|
284
|
+
|
|
285
|
+
> **Status: experimental.** Turns the read-only `research` subagent output into a **traceable, recoverable** research→evidence loop.
|
|
286
|
+
|
|
287
|
+
Hard guarantees (any violation is a No-Go; never published):
|
|
288
|
+
|
|
289
|
+
- **Only specialized WebSearch / WebFetch** — no generic MCP, no write/exec grant.
|
|
290
|
+
- **SSRF / DNS-rebind / redirect / body-size / timeout** re-use the existing guards: a lexical SSRF pre-check at selection, and the full per-hop guard set delegated to the real WebFetch tool.
|
|
291
|
+
- A **claim must bind a source** to reach `observed`; a claim with no independent verification stays `partial`/`unmet` and is never counted as verified/complete.
|
|
292
|
+
- A **security-gate failure becomes `blocked`/`failed` with a structured reason** — never faked as a hit; provider fallback only swaps the provider, never downgrades a source status or writes a failure as a success.
|
|
293
|
+
- Research evidence (web) and execution-verification evidence (file / test / build / file facts) are **kept distinct**; a web summary cannot stand in for execution verification.
|
|
294
|
+
- Packet + source metadata are saved **atomically with a CAS token**; project / session / Goal scope isolation; resume only derives state and never replays external side effects; old schema versions fail closed.
|
|
295
|
+
|
|
296
|
+
Modules: `src/runtime/subagents/{research-types,research-contract,research-citation,web-research-adapter,research-renderer,research-artifact,research-quality}.ts`.
|
|
297
|
+
|
|
298
|
+
> Real-terminal (PTY) and external-state evidence are marked `not_run` in CI; local tests are not treated as release completion.
|
|
299
|
+
|
|
207
300
|
## Development
|
|
208
301
|
|
|
209
302
|
```bash
|
package/README.zh-CN.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> **Orion Code — 通用 Agent 驾驭框架**
|
|
4
4
|
> 一个 CLI 驱动的编码 Agent,具备安全边界、工具编排、记忆系统和上下文管理。
|
|
5
5
|
>
|
|
6
|
-
> v0.1.
|
|
6
|
+
> v0.1.4 — Goal 连续性、模型配置与命令沙箱 POC
|
|
7
7
|
|
|
8
8
|
[](LICENSE)
|
|
9
9
|
[](https://nodejs.org)
|
|
@@ -104,16 +104,19 @@ npm start -- --print "review the current git diff"
|
|
|
104
104
|
|
|
105
105
|
### 全局安装
|
|
106
106
|
|
|
107
|
-
固定安装 v0.1.
|
|
107
|
+
固定安装 v0.1.4:
|
|
108
108
|
|
|
109
109
|
```bash
|
|
110
|
-
npm install -g @orion-agents/orion-code@0.1.
|
|
110
|
+
npm install -g @orion-agents/orion-code@0.1.4
|
|
111
111
|
# 任意目录运行
|
|
112
112
|
orion
|
|
113
113
|
```
|
|
114
114
|
|
|
115
115
|
也可以在源码工作树中使用 `npm ci && npm run build && npm start`。
|
|
116
116
|
|
|
117
|
+
> **预发布说明**:`0.1.4` 是 `v0.1.4` 分支上的开发版本,尚未发布到 npm——当前已发布版本
|
|
118
|
+
> 仍是 `0.1.3`。在 `v0.1.4` 打 tag 并发布之前,请从源码工作树安装。该说明将在发版时移除。
|
|
119
|
+
|
|
117
120
|
公众体验、交互优化和新增工作流优先落在 TUI。`terminal-ui` 不作为与
|
|
118
121
|
TUI 并行发展的公众产品;Ink 只保留迁移期兼容,不再增加产品能力。
|
|
119
122
|
|
|
@@ -173,6 +176,69 @@ v0.1.2 只覆盖单 Session、单 Active Goal,不承诺多 Goal 调度或无
|
|
|
173
176
|
CLI 参数 > ~/.orion-code/orion.json > 环境变量 > 内部默认
|
|
174
177
|
```
|
|
175
178
|
|
|
179
|
+
### 项目级工具规则(`allowedTools`)
|
|
180
|
+
|
|
181
|
+
权限规则写在 `projects["<项目绝对路径>"].allowedTools`,只作用于该仓库。规则叠加在
|
|
182
|
+
工具自身的权限策略之上:**只能收紧,不能放宽**。
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"projects": {
|
|
187
|
+
"/Users/me/work/api": {
|
|
188
|
+
"allowedTools": [
|
|
189
|
+
"exec_command(git status*)",
|
|
190
|
+
"exec_command(npm test*)",
|
|
191
|
+
"ask:exec_command(git push*)",
|
|
192
|
+
"deny:read_file(*.env)"
|
|
193
|
+
]
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
- 语法:`[allow|ask|deny:]工具名[(参数通配)]`;`*` 匹配任意字符串,`?` 匹配单个字符,
|
|
200
|
+
工具名写 `*` 表示匹配所有工具。
|
|
201
|
+
- 参数通配匹配的是调用参数中的 `command` / `file_path` / `path` / `url` / `pattern` /
|
|
202
|
+
`query`(按此顺序取第一个非空字符串)。
|
|
203
|
+
- 冲突时按“最严格优先”解析:`deny` > `ask` > `allow`,与书写顺序无关。
|
|
204
|
+
- `allow` 仅用于免去交互确认,**不会**覆盖工具自身的 `deny`、**不会**突破 plan 模式的
|
|
205
|
+
只读约束,也**不会**自动放行破坏性调用。
|
|
206
|
+
- 无法解析的条目会被忽略而不是静默放行,可通过 `/config` 查看解析结果与非法条目。
|
|
207
|
+
|
|
208
|
+
### 命令执行沙箱(`sandbox`)
|
|
209
|
+
|
|
210
|
+
`exec_command` 可在操作系统级沙箱内执行。这是**安全 POC**:后端在运行
|
|
211
|
+
时实测探测,已配置但不可用的沙箱会**fail closed**(拒绝执行),而不会静默降级为
|
|
212
|
+
无沙箱执行。
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{
|
|
216
|
+
"sandbox": {
|
|
217
|
+
"profile": "none",
|
|
218
|
+
"backend": "auto",
|
|
219
|
+
"allowNetwork": false,
|
|
220
|
+
"writableRoots": [],
|
|
221
|
+
"image": "alpine:latest"
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
- **归属** — `sandbox` 位于全局配置(`~/.orion-code/orion.json`),并可在项目级
|
|
227
|
+
`projects["<项目绝对路径>"].sandbox` 覆盖。项目级按 key 单独覆盖,缺省 key 继承全局。
|
|
228
|
+
- **`profile`** — `none`(默认,不隔离,等价于旧版 `sh -c`)、`read-only`(任何位置不可写、无网络)、
|
|
229
|
+
`workspace-write`(写权限限定在工作区与临时目录,除非 `allowNetwork: true` 否则仍禁网)。
|
|
230
|
+
未知取值(如新版 Orion 写入的更严格值)一律硬失败,绝不降级为 `none`。
|
|
231
|
+
- **`backend`** — `auto`(默认,自动选首个可用后端)、`seatbelt`(macOS `sandbox-exec`)、
|
|
232
|
+
`bubblewrap`(Linux `bwrap`)或 `docker`。每个后端都用真实执行探针校验,从不靠 `which` 推断。
|
|
233
|
+
- **`image`** — 仅 `docker` 需要,指定运行所用的容器镜像。
|
|
234
|
+
- **`writableRoots`** — `workspace-write` 可写入的额外宿主根目录(除工作区与临时目录外)。
|
|
235
|
+
非字符串 / 空项会被丢弃。
|
|
236
|
+
- **迁移 / 回滚** — 新增 `sandbox` 完全向后兼容:默认 `profile: "none"` 与旧行为完全一致。
|
|
237
|
+
删除该 key(或回退到沙箱前的版本)是安全回滚;旧版 Orion 会忽略该未知字段。不涉及任何敏感信息,无需脱敏。
|
|
238
|
+
- **已知限制** — `seatbelt` 不能嵌套在另一沙箱内(例如 Orion 自身运行在应用沙箱中时);
|
|
239
|
+
`docker` 在独立进程树中运行命令,只约束被 bind-mount 的部分(镜像根文件系统已通过 `--read-only` 设为只读);
|
|
240
|
+
各后端均不限制 CPU / 内存。
|
|
241
|
+
|
|
176
242
|
### 环境变量
|
|
177
243
|
|
|
178
244
|
| 变量 | 默认值 | 说明 |
|
|
@@ -399,7 +465,24 @@ orion-code/
|
|
|
399
465
|
|
|
400
466
|
## 版本历史
|
|
401
467
|
|
|
402
|
-
### v0.1.
|
|
468
|
+
### v0.1.4(开发中,未发布)
|
|
469
|
+
|
|
470
|
+
- 版本元数据对齐:`package.json` / `package-lock.json` 升至 `0.1.4`,`orion --version`、
|
|
471
|
+
出站 `User-Agent` 与崩溃/遥测上报不再误报 `0.1.3`;
|
|
472
|
+
- 类型安全推进:外部边界(LLM provider、MCP wire、工具返回)由 `any` 收窄为 `unknown` +
|
|
473
|
+
类型守卫,顺带修复被 `any` 掩盖的真实缺陷;
|
|
474
|
+
- 可靠性:持久化与鉴权路径不再静默吞掉异常,ESLint 启用 `no-empty` 门禁。
|
|
475
|
+
|
|
476
|
+
### v0.1.3(最新已发布版本)
|
|
477
|
+
|
|
478
|
+
- `/model` 与 `/models` 拆分:`/model` 只显示当前模型信息,`/models` 承接交互式切换;
|
|
479
|
+
- `modelRegistry` 成为模型展示与切换的唯一事实源,静态 catalog 退为 legacy fallback;
|
|
480
|
+
- 内置 catalog 补全(火山方舟 / xf-yun / deepseek 等),未配置上下文时正确回退;
|
|
481
|
+
- 命令沙箱 POC、只读 Git 工具与工具 allowlist 的安全基线。
|
|
482
|
+
|
|
483
|
+
> 完整变更与交付状态(已发布 / 已合并 / 候选)以 `CHANGELOG.md` 为准。
|
|
484
|
+
|
|
485
|
+
### v0.1.2(已发布)
|
|
403
486
|
|
|
404
487
|
- 单 Session、单 Active Goal 的 typed continuation;
|
|
405
488
|
- restart/resume 后安全暂停,必须显式恢复;
|
|
@@ -419,6 +502,25 @@ orion-code/
|
|
|
419
502
|
|
|
420
503
|
---
|
|
421
504
|
|
|
505
|
+
## Research-to-Evidence(v0.1.4,实验性)
|
|
506
|
+
|
|
507
|
+
> **状态标记:experimental(实验性)。** 把只读 `research` 子 agent 的结果转化为**可追踪、可恢复**的研究→证据闭环。
|
|
508
|
+
|
|
509
|
+
核心保证(违反任一即 No-Go,绝不发布):
|
|
510
|
+
|
|
511
|
+
- **只接专用 WebSearch / WebFetch**,不暴露通用 MCP、不授予 write/exec。
|
|
512
|
+
- **SSRF / DNS 重解析 / 重定向 / 响应大小 / 超时** 全部走既有守卫:选择期做 lexical SSRF 预检,逐跳防护委托给真实 WebFetch 工具。
|
|
513
|
+
- **claim 必须有 source 绑定**才能进入 `observed`;无独立验证的 claim 永远停在 `partial`/`unmet`,绝不被算作已验证/完成。
|
|
514
|
+
- **安全闸门失败 → `blocked`/`failed` + 结构化原因**,绝不伪装成命中;provider fallback 只换 provider,不降级 source status,也不把失败写成成功。
|
|
515
|
+
- 研究证据(web)与执行验证证据(file / 测试 / 构建 / 文件事实)**明确区分**,web 摘要不能替代执行验证。
|
|
516
|
+
- 包与源元数据**原子 CAS 保存**,project / session / Goal 作用域隔离;恢复只推导状态、不重放外部副作用;旧 schema 版本 fail-closed。
|
|
517
|
+
|
|
518
|
+
模块:`src/runtime/subagents/{research-types,research-contract,research-citation,web-research-adapter,research-renderer,research-artifact,research-quality}.ts`。
|
|
519
|
+
|
|
520
|
+
> 真实终端(PTY)与外部状态证据在 CI 中标记为 `not_run`;本地测试不视为发布完成。
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
422
524
|
## 开发
|
|
423
525
|
|
|
424
526
|
```bash
|
|
@@ -439,6 +541,9 @@ npm run lint
|
|
|
439
541
|
|
|
440
542
|
# 格式化
|
|
441
543
|
npm run format
|
|
544
|
+
|
|
545
|
+
# 发布前只读检查(不会 tag / push / publish)
|
|
546
|
+
npm run release:check
|
|
442
547
|
```
|
|
443
548
|
|
|
444
549
|
---
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,aAAa,EAEnB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,aAAa,EAEnB,MAAM,SAAS,CAAC;AA4UjB,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,eAAe,GAAG,SAAS,GAAG,MAAM,CAErF;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE,CASrE;AA+nDD,iBAAe,UAAU,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAqVpF;AAyyDD,wBAAgB,WAAW,IAAI,YAAY,EAAE,CAE5C;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC,YAAY,CAAC,GAAG,YAAY,EAAE,CAQ1F;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAElE;AAED,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C;AAED,OAAO,EAAE,UAAU,IAAI,WAAW,EAAE,CAAC"}
|
package/dist/commands/index.js
CHANGED
|
@@ -21,6 +21,7 @@ const ui_view_model_1 = require("../runtime/ui-view-model");
|
|
|
21
21
|
const task_manager_1 = require("../services/task-manager");
|
|
22
22
|
const agent_runner_1 = require("../services/agent-runner");
|
|
23
23
|
const config_1 = require("../services/config");
|
|
24
|
+
const tool_allowlist_1 = require("../services/tool-allowlist");
|
|
24
25
|
const box_1 = require("../ui/box");
|
|
25
26
|
const stream_markdown_1 = require("../ui/stream-markdown");
|
|
26
27
|
const progress_1 = require("../ui/progress");
|
|
@@ -40,7 +41,9 @@ const prompt_context_1 = require("../services/prompt-context");
|
|
|
40
41
|
const doctor_1 = require("../services/doctor");
|
|
41
42
|
const model_context_1 = require("../services/model-context");
|
|
42
43
|
const token_estimate_1 = require("../utils/token-estimate");
|
|
44
|
+
const mask_1 = require("../utils/mask");
|
|
43
45
|
const model_catalog_1 = require("../services/model-catalog");
|
|
46
|
+
const model_registry_1 = require("../services/model-registry");
|
|
44
47
|
const workspace_diff_1 = require("../services/workspace-diff");
|
|
45
48
|
const commit_plan_1 = require("../services/commit-plan");
|
|
46
49
|
const tool_artifacts_1 = require("../core/tool-artifacts");
|
|
@@ -107,8 +110,42 @@ function formatRendererStatus(ctx) {
|
|
|
107
110
|
: DIM('custom');
|
|
108
111
|
return `${BRAND(snapshot.renderer.name)} ${status} ${DIM(snapshot.renderer.capabilityLabels.join(', '))}`;
|
|
109
112
|
}
|
|
110
|
-
function
|
|
111
|
-
|
|
113
|
+
function getProfileByModelId(registry, modelId) {
|
|
114
|
+
if (!registry)
|
|
115
|
+
return undefined;
|
|
116
|
+
const normalized = modelId.trim();
|
|
117
|
+
if (!normalized)
|
|
118
|
+
return undefined;
|
|
119
|
+
if (registry.profiles.has(normalized))
|
|
120
|
+
return registry.profiles.get(normalized);
|
|
121
|
+
for (const profile of registry.profiles.values()) {
|
|
122
|
+
if (modelId === profile.model)
|
|
123
|
+
return profile;
|
|
124
|
+
}
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
function resolveModelFromRegistry(config, selector) {
|
|
128
|
+
if (!config.modelRegistry)
|
|
129
|
+
return undefined;
|
|
130
|
+
const trimmed = selector.trim();
|
|
131
|
+
if (!trimmed)
|
|
132
|
+
return undefined;
|
|
133
|
+
return (0, model_registry_1.lookupProfile)(config.modelRegistry, trimmed) ?? undefined;
|
|
134
|
+
}
|
|
135
|
+
function listConfiguredModelCatalogEntries(registry) {
|
|
136
|
+
if (!registry)
|
|
137
|
+
return [];
|
|
138
|
+
return registry.enabledProfiles.map(profile => {
|
|
139
|
+
const provider = registry.providers.get(profile.provider);
|
|
140
|
+
return {
|
|
141
|
+
name: profile.id,
|
|
142
|
+
alias: profile.aliases?.[0],
|
|
143
|
+
provider: provider?.displayName ?? profile.provider,
|
|
144
|
+
contextWindow: profile.resolvedContextWindow,
|
|
145
|
+
maxOutputTokens: profile.resolvedMaxOutputTokens,
|
|
146
|
+
source: `${profile.contextSource}/${profile.outputSource}`,
|
|
147
|
+
};
|
|
148
|
+
});
|
|
112
149
|
}
|
|
113
150
|
function formatLoopBudgetSource(stats) {
|
|
114
151
|
const source = stats.loopBudgetSource ?? 'unknown';
|
|
@@ -1319,19 +1356,35 @@ function showConfig(ctx) {
|
|
|
1319
1356
|
console.log();
|
|
1320
1357
|
console.log(HEADER('Configuration'));
|
|
1321
1358
|
console.log(DIM('─'.repeat(40)));
|
|
1359
|
+
const allowlist = (0, tool_allowlist_1.resolveProjectToolAllowlist)(ctx.cwd);
|
|
1360
|
+
const allowlistSummary = allowlist.rules.length === 0 && allowlist.invalid.length === 0
|
|
1361
|
+
? '(none)'
|
|
1362
|
+
: `${allowlist.rules.length} rule(s)` +
|
|
1363
|
+
(allowlist.invalid.length > 0 ? `, ${allowlist.invalid.length} invalid (ignored)` : '');
|
|
1322
1364
|
const summary = {
|
|
1323
1365
|
name: ctx.config.name,
|
|
1324
1366
|
model: ctx.config.model,
|
|
1325
1367
|
apiBaseUrl: ctx.config.apiBaseUrl || '(default OpenAI)',
|
|
1326
|
-
apiKey:
|
|
1368
|
+
apiKey: (0, mask_1.maskSecret)(ctx.config.apiKey),
|
|
1327
1369
|
mode: ctx.config.mode,
|
|
1328
1370
|
logLevel: ctx.config.logLevel,
|
|
1329
1371
|
toolConfirmation: ctx.config.toolConfirmation,
|
|
1372
|
+
allowedTools: allowlistSummary,
|
|
1330
1373
|
};
|
|
1331
1374
|
const llmSummary = ctx.llm?.getConfigSummary() ?? {};
|
|
1332
1375
|
for (const [key, val] of Object.entries(summary)) {
|
|
1333
1376
|
console.log(` ${ACCENT(key.padEnd(16))} ${DIM(val)}`);
|
|
1334
1377
|
}
|
|
1378
|
+
if (allowlist.rules.length > 0 || allowlist.invalid.length > 0) {
|
|
1379
|
+
console.log();
|
|
1380
|
+
console.log(HEADER(' Project allowedTools:'));
|
|
1381
|
+
for (const rule of allowlist.rules) {
|
|
1382
|
+
console.log(` ${ACCENT(rule.effect.padEnd(6))} ${DIM(rule.tool)}${DIM(rule.pattern ? `(${rule.pattern})` : '')}`);
|
|
1383
|
+
}
|
|
1384
|
+
for (const entry of allowlist.invalid) {
|
|
1385
|
+
console.log(` ${WARN('invalid')} ${DIM(entry)}`);
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1335
1388
|
console.log();
|
|
1336
1389
|
console.log(HEADER(' LLM Settings:'));
|
|
1337
1390
|
for (const [key, val] of Object.entries(llmSummary)) {
|
|
@@ -1346,14 +1399,29 @@ function handleModel(ctx, args) {
|
|
|
1346
1399
|
if (!args || trimmedArgs === '?' || trimmedArgs === 'info') {
|
|
1347
1400
|
console.log();
|
|
1348
1401
|
if (ctx.llm) {
|
|
1349
|
-
const currentModel = ctx.llm.getModel();
|
|
1402
|
+
const currentModel = ctx.store.getSnapshot().currentModel || ctx.llm.getModel();
|
|
1403
|
+
const profile = getProfileByModelId(ctx.config.modelRegistry, currentModel);
|
|
1350
1404
|
const aliasEntry = (0, model_catalog_1.getModelCatalogEntry)(currentModel);
|
|
1351
|
-
const contextInfo =
|
|
1405
|
+
const contextInfo = profile
|
|
1406
|
+
? {
|
|
1407
|
+
id: profile.model,
|
|
1408
|
+
label: profile.displayName || profile.id,
|
|
1409
|
+
contextWindow: profile.resolvedContextWindow,
|
|
1410
|
+
maxOutputTokens: profile.resolvedMaxOutputTokens,
|
|
1411
|
+
source: 'config',
|
|
1412
|
+
matchedId: profile.model,
|
|
1413
|
+
}
|
|
1414
|
+
: (0, model_context_1.resolveModelContext)(currentModel);
|
|
1352
1415
|
const compactStats = getCommandAutoCompact(ctx, currentModel).getStats();
|
|
1353
1416
|
console.log(HEADER('Current Model'));
|
|
1354
1417
|
console.log(DIM('─'.repeat(40)));
|
|
1355
1418
|
console.log(` Model ${BRAND(currentModel)}`);
|
|
1356
|
-
if (
|
|
1419
|
+
if (profile) {
|
|
1420
|
+
console.log(` Alias ${ACCENT(profile.aliases?.[0] ? `(${profile.aliases[0]})` : 'none')}`);
|
|
1421
|
+
const provider = ctx.config.modelRegistry?.providers.get(profile.provider);
|
|
1422
|
+
console.log(` Provider ${DIM(provider?.displayName || profile.provider)}`);
|
|
1423
|
+
}
|
|
1424
|
+
else if (aliasEntry) {
|
|
1357
1425
|
console.log(` Alias ${ACCENT(aliasEntry.alias)}`);
|
|
1358
1426
|
console.log(` Provider ${DIM(aliasEntry.provider)}`);
|
|
1359
1427
|
}
|
|
@@ -1370,49 +1438,12 @@ function handleModel(ctx, args) {
|
|
|
1370
1438
|
console.log();
|
|
1371
1439
|
return { success: true };
|
|
1372
1440
|
}
|
|
1373
|
-
//
|
|
1374
|
-
if (trimmedArgs === 'list' || trimmedArgs === 'ls') {
|
|
1375
|
-
console.log();
|
|
1376
|
-
console.log(HEADER('Available Models'));
|
|
1377
|
-
console.log(DIM('─'.repeat(40)));
|
|
1378
|
-
const currentModel = ctx.llm?.getModel() || '';
|
|
1379
|
-
const modelPicker = (0, ui_view_model_1.createModelPickerState)({
|
|
1380
|
-
currentModel,
|
|
1381
|
-
models: (0, model_catalog_1.listModelCatalogEntries)().map(model => {
|
|
1382
|
-
const contextInfo = (0, model_context_1.resolveModelContext)(model.name);
|
|
1383
|
-
return {
|
|
1384
|
-
...model,
|
|
1385
|
-
contextWindow: contextInfo.contextWindow,
|
|
1386
|
-
maxOutputTokens: contextInfo.maxOutputTokens,
|
|
1387
|
-
source: contextInfo.source,
|
|
1388
|
-
};
|
|
1389
|
-
}),
|
|
1390
|
-
});
|
|
1391
|
-
for (const item of modelPicker.visibleItems) {
|
|
1392
|
-
const marker = item.isCurrent ? SUCCESS('●') : DIM('○');
|
|
1393
|
-
const alias = item.alias ? `(${item.alias})` : '';
|
|
1394
|
-
const context = `${formatTokenCount(item.contextWindow ?? 0)} ctx`;
|
|
1395
|
-
const current = item.isCurrent ? BRAND('(current)') : '';
|
|
1396
|
-
console.log(` ${marker} ${ACCENT(item.name)} ${DIM(alias)} ${DIM(context)} ${current}`);
|
|
1397
|
-
console.log(` ${DIM(item.provider ?? 'unknown')}`);
|
|
1398
|
-
}
|
|
1441
|
+
// /model list|ls|help 已移除,统一由 /models 承接(交互式选择切换)
|
|
1442
|
+
if (trimmedArgs === 'list' || trimmedArgs === 'ls' || trimmedArgs === 'help') {
|
|
1399
1443
|
console.log();
|
|
1400
|
-
console.log(
|
|
1401
|
-
console.log();
|
|
1402
|
-
|
|
1403
|
-
}
|
|
1404
|
-
// 显示帮助
|
|
1405
|
-
if (trimmedArgs === 'help') {
|
|
1406
|
-
console.log();
|
|
1407
|
-
console.log(HEADER('/model Command Help'));
|
|
1408
|
-
console.log(DIM('─'.repeat(40)));
|
|
1409
|
-
console.log();
|
|
1410
|
-
console.log(` ${ACCENT('/model')} Show current model`);
|
|
1411
|
-
console.log(` ${ACCENT('/model list')} Show available models`);
|
|
1412
|
-
console.log(` ${ACCENT('/model <name>')} Switch to specific model`);
|
|
1413
|
-
console.log(` ${ACCENT('/model <alias>')} Switch using alias (opus, sonnet, haiku)`);
|
|
1414
|
-
console.log();
|
|
1415
|
-
console.log(DIM(`Aliases: ${formatModelAliasHelp()}`));
|
|
1444
|
+
console.log(WARN(`/model ${trimmedArgs} was removed.`));
|
|
1445
|
+
console.log(DIM('Use /models to switch models interactively,'));
|
|
1446
|
+
console.log(DIM('or /model <name|alias> to switch directly, e.g. /model sonnet'));
|
|
1416
1447
|
console.log();
|
|
1417
1448
|
return { success: true };
|
|
1418
1449
|
}
|
|
@@ -1423,16 +1454,75 @@ function handleModel(ctx, args) {
|
|
|
1423
1454
|
return { success: false };
|
|
1424
1455
|
}
|
|
1425
1456
|
// 解析别名
|
|
1426
|
-
const
|
|
1457
|
+
const registryProfile = resolveModelFromRegistry(ctx.config, args);
|
|
1458
|
+
const resolvedModel = registryProfile ? registryProfile.model : (0, model_catalog_1.resolveModelAlias)(args);
|
|
1459
|
+
const resolvedProfileId = registryProfile ? registryProfile.id : resolvedModel;
|
|
1427
1460
|
ctx.llm.setModel(resolvedModel);
|
|
1428
1461
|
getCommandAutoCompact(ctx, resolvedModel);
|
|
1429
|
-
ctx.store.setState({ currentModel:
|
|
1430
|
-
console.log(SUCCESS(`✔ Model changed to ${BRAND(
|
|
1431
|
-
const contextInfo =
|
|
1462
|
+
ctx.store.setState({ currentModel: resolvedProfileId });
|
|
1463
|
+
console.log(SUCCESS(`✔ Model changed to ${BRAND(resolvedProfileId)}`));
|
|
1464
|
+
const contextInfo = registryProfile
|
|
1465
|
+
? {
|
|
1466
|
+
contextWindow: registryProfile.resolvedContextWindow,
|
|
1467
|
+
maxOutputTokens: registryProfile.resolvedMaxOutputTokens,
|
|
1468
|
+
source: 'resolved',
|
|
1469
|
+
}
|
|
1470
|
+
: (0, model_context_1.resolveModelContext)(resolvedModel);
|
|
1432
1471
|
console.log(DIM(` Context window ${formatTokenCount(contextInfo.contextWindow)} tokens (${contextInfo.source})`));
|
|
1433
1472
|
console.log();
|
|
1434
1473
|
return { success: true };
|
|
1435
1474
|
}
|
|
1475
|
+
/**
|
|
1476
|
+
* /models — 交互式选择切换模型。
|
|
1477
|
+
* 交互式渲染器返回结构化 modelPicker 请求(渲染器弹出选择层,选中即 /model <id>);
|
|
1478
|
+
* 非交互式渲染器直接打印候选列表并提示 /model <name|alias>。
|
|
1479
|
+
*/
|
|
1480
|
+
function handleModels(ctx, _args) {
|
|
1481
|
+
console.log();
|
|
1482
|
+
const currentModel = ctx.store.getSnapshot().currentModel || ctx.llm?.getModel() || '';
|
|
1483
|
+
const configuredModels = listConfiguredModelCatalogEntries(ctx.config.modelRegistry);
|
|
1484
|
+
const candidates = configuredModels.length > 0
|
|
1485
|
+
? configuredModels
|
|
1486
|
+
: (0, model_catalog_1.listModelCatalogEntries)().map(model => {
|
|
1487
|
+
const contextInfo = (0, model_context_1.resolveModelContext)(model.name);
|
|
1488
|
+
return {
|
|
1489
|
+
name: model.name,
|
|
1490
|
+
alias: model.alias,
|
|
1491
|
+
provider: model.provider,
|
|
1492
|
+
contextWindow: contextInfo.contextWindow,
|
|
1493
|
+
maxOutputTokens: contextInfo.maxOutputTokens,
|
|
1494
|
+
source: contextInfo.source,
|
|
1495
|
+
};
|
|
1496
|
+
});
|
|
1497
|
+
const ui = commandUICapabilities(ctx);
|
|
1498
|
+
if (ui.structuredPickers) {
|
|
1499
|
+
return {
|
|
1500
|
+
success: true,
|
|
1501
|
+
modelPicker: {
|
|
1502
|
+
models: candidates,
|
|
1503
|
+
currentModel,
|
|
1504
|
+
title: 'Switch Model',
|
|
1505
|
+
maxVisibleItems: 12,
|
|
1506
|
+
},
|
|
1507
|
+
};
|
|
1508
|
+
}
|
|
1509
|
+
// 非交互式渲染器:打印候选列表
|
|
1510
|
+
console.log(HEADER('Available Models'));
|
|
1511
|
+
console.log(DIM('─'.repeat(40)));
|
|
1512
|
+
const modelPicker = (0, ui_view_model_1.createModelPickerState)({ currentModel, models: candidates });
|
|
1513
|
+
for (const item of modelPicker.visibleItems) {
|
|
1514
|
+
const marker = item.isCurrent ? SUCCESS('●') : DIM('○');
|
|
1515
|
+
const alias = item.alias ? `(${item.alias})` : '';
|
|
1516
|
+
const context = `${formatTokenCount(item.contextWindow ?? 0)} ctx`;
|
|
1517
|
+
const current = item.isCurrent ? BRAND('(current)') : '';
|
|
1518
|
+
console.log(` ${marker} ${ACCENT(item.name)} ${DIM(alias)} ${DIM(context)} ${current}`);
|
|
1519
|
+
console.log(` ${DIM(item.provider ?? 'unknown')}`);
|
|
1520
|
+
}
|
|
1521
|
+
console.log();
|
|
1522
|
+
console.log(DIM('Use /model <name|alias> to switch, e.g. /model sonnet'));
|
|
1523
|
+
console.log();
|
|
1524
|
+
return { success: true };
|
|
1525
|
+
}
|
|
1436
1526
|
function normalizePermissionMode(raw) {
|
|
1437
1527
|
const value = raw.trim().toLowerCase();
|
|
1438
1528
|
if (!value)
|
|
@@ -1733,6 +1823,7 @@ async function handleChat(ctx, input) {
|
|
|
1733
1823
|
costTracker: snapshot.costTracker,
|
|
1734
1824
|
permissionMode: snapshot.permissionMode,
|
|
1735
1825
|
toolConfirmation: ctx.config.toolConfirmation,
|
|
1826
|
+
toolAllowlist: (0, tool_allowlist_1.resolveProjectToolAllowlist)(ctx.cwd).evaluator,
|
|
1736
1827
|
toolContext: {
|
|
1737
1828
|
cwd: ctx.cwd,
|
|
1738
1829
|
config: {
|
|
@@ -3184,7 +3275,7 @@ const COMMANDS = [
|
|
|
3184
3275
|
{
|
|
3185
3276
|
name: 'model',
|
|
3186
3277
|
description: 'Show or change the current model',
|
|
3187
|
-
argumentHint: '[model|
|
|
3278
|
+
argumentHint: '[model|info]',
|
|
3188
3279
|
category: 'model',
|
|
3189
3280
|
priority: 10,
|
|
3190
3281
|
type: 'builtin',
|
|
@@ -3192,9 +3283,20 @@ const COMMANDS = [
|
|
|
3192
3283
|
risk: 'state-write',
|
|
3193
3284
|
execute: (ctx, args) => handleModel(ctx, args),
|
|
3194
3285
|
},
|
|
3286
|
+
{
|
|
3287
|
+
name: 'models',
|
|
3288
|
+
description: 'Switch the current model interactively',
|
|
3289
|
+
argumentHint: '',
|
|
3290
|
+
category: 'model',
|
|
3291
|
+
priority: 10,
|
|
3292
|
+
type: 'builtin',
|
|
3293
|
+
execution: 'builtin',
|
|
3294
|
+
risk: 'state-write',
|
|
3295
|
+
execute: (ctx, args) => handleModels(ctx, args),
|
|
3296
|
+
},
|
|
3195
3297
|
{
|
|
3196
3298
|
name: 'mode',
|
|
3197
|
-
aliases: ['
|
|
3299
|
+
aliases: ['perm'],
|
|
3198
3300
|
description: 'Show or change tool permission mode',
|
|
3199
3301
|
argumentHint: '[default|accept-edits|plan|auto|next]',
|
|
3200
3302
|
category: 'model',
|
|
@@ -3263,6 +3365,18 @@ const COMMANDS = [
|
|
|
3263
3365
|
rendererScope: ['tui'],
|
|
3264
3366
|
execute: () => ({ success: true }),
|
|
3265
3367
|
},
|
|
3368
|
+
{
|
|
3369
|
+
name: 'permissions',
|
|
3370
|
+
description: 'Set the tool confirmation policy (TUI). No argument opens a picker; with an argument applies immediately.',
|
|
3371
|
+
argumentHint: '[allow|ask|deny]',
|
|
3372
|
+
category: 'system',
|
|
3373
|
+
priority: 33,
|
|
3374
|
+
type: 'builtin',
|
|
3375
|
+
execution: 'renderer-local',
|
|
3376
|
+
risk: 'state-write',
|
|
3377
|
+
rendererScope: ['tui'],
|
|
3378
|
+
execute: () => ({ success: true }),
|
|
3379
|
+
},
|
|
3266
3380
|
{
|
|
3267
3381
|
name: 'redraw',
|
|
3268
3382
|
description: 'Redraw the TUI-owned live region',
|