@prestyj/cli 5.30.0 → 5.30.2
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 +54 -39
- package/assets/skills/bulletproof/SKILL.md +1 -1
- package/assets/skills/clarify/SKILL.md +1 -1
- package/assets/skills/code-review/SKILL.md +1 -1
- package/assets/skills/compliance-guard/SKILL.md +1 -1
- package/assets/skills/durable/SKILL.md +1 -1
- package/assets/skills/evidence-led-ui/SKILL.md +1 -1
- package/assets/skills/lean/SKILL.md +1 -1
- package/assets/skills/refactoring/SKILL.md +1 -1
- package/assets/skills/root-cause/SKILL.md +1 -1
- package/assets/skills/shared-language/SKILL.md +1 -1
- package/assets/skills/tdd/SKILL.md +1 -1
- package/dist/app-sidecar/app-settings.d.ts +63 -0
- package/dist/app-sidecar/app-settings.js +147 -0
- package/dist/app-sidecar/app-settings.js.map +1 -0
- package/dist/app-sidecar/attachments.d.ts +11 -0
- package/dist/app-sidecar/attachments.js +47 -0
- package/dist/app-sidecar/attachments.js.map +1 -0
- package/dist/app-sidecar/auth-routes.d.ts +3 -0
- package/dist/app-sidecar/auth-routes.js +293 -0
- package/dist/app-sidecar/auth-routes.js.map +1 -0
- package/dist/app-sidecar/autopilot-runner.d.ts +62 -0
- package/dist/app-sidecar/autopilot-runner.js +373 -0
- package/dist/app-sidecar/autopilot-runner.js.map +1 -0
- package/dist/app-sidecar/file-search.d.ts +15 -0
- package/dist/app-sidecar/file-search.js +103 -0
- package/dist/app-sidecar/file-search.js.map +1 -0
- package/dist/app-sidecar/hf-pull-manager.d.ts +20 -0
- package/dist/app-sidecar/hf-pull-manager.js +224 -0
- package/dist/app-sidecar/hf-pull-manager.js.map +1 -0
- package/dist/app-sidecar/history-routes.d.ts +3 -0
- package/dist/app-sidecar/history-routes.js +375 -0
- package/dist/app-sidecar/history-routes.js.map +1 -0
- package/dist/app-sidecar/history.d.ts +67 -0
- package/dist/app-sidecar/history.js +23 -0
- package/dist/app-sidecar/history.js.map +1 -0
- package/dist/app-sidecar/http.d.ts +5 -0
- package/dist/app-sidecar/http.js +27 -0
- package/dist/app-sidecar/http.js.map +1 -0
- package/dist/app-sidecar/integration-routes.d.ts +3 -0
- package/dist/app-sidecar/integration-routes.js +286 -0
- package/dist/app-sidecar/integration-routes.js.map +1 -0
- package/dist/app-sidecar/json-mode.d.ts +10 -0
- package/dist/app-sidecar/json-mode.js +73 -0
- package/dist/app-sidecar/json-mode.js.map +1 -0
- package/dist/app-sidecar/keep-awake.d.ts +4 -0
- package/dist/app-sidecar/keep-awake.js +5 -0
- package/dist/app-sidecar/keep-awake.js.map +1 -0
- package/dist/app-sidecar/mcp-routes.d.ts +3 -0
- package/dist/app-sidecar/mcp-routes.js +185 -0
- package/dist/app-sidecar/mcp-routes.js.map +1 -0
- package/dist/app-sidecar/mcp-rows.d.ts +31 -0
- package/dist/app-sidecar/mcp-rows.js +77 -0
- package/dist/app-sidecar/mcp-rows.js.map +1 -0
- package/dist/app-sidecar/nolan-context.d.ts +20 -0
- package/dist/app-sidecar/nolan-context.js +55 -0
- package/dist/app-sidecar/nolan-context.js.map +1 -0
- package/dist/app-sidecar/progress-manager.d.ts +10 -0
- package/dist/app-sidecar/progress-manager.js +116 -0
- package/dist/app-sidecar/progress-manager.js.map +1 -0
- package/dist/app-sidecar/prompt-routes.d.ts +3 -0
- package/dist/app-sidecar/prompt-routes.js +355 -0
- package/dist/app-sidecar/prompt-routes.js.map +1 -0
- package/dist/app-sidecar/repo-polls.d.ts +18 -0
- package/dist/app-sidecar/repo-polls.js +45 -0
- package/dist/app-sidecar/repo-polls.js.map +1 -0
- package/dist/app-sidecar/route-context.d.ts +147 -0
- package/dist/app-sidecar/route-context.js +2 -0
- package/dist/app-sidecar/route-context.js.map +1 -0
- package/dist/app-sidecar/run-control-routes.d.ts +3 -0
- package/dist/app-sidecar/run-control-routes.js +437 -0
- package/dist/app-sidecar/run-control-routes.js.map +1 -0
- package/dist/app-sidecar/session-routes.d.ts +3 -0
- package/dist/app-sidecar/session-routes.js +115 -0
- package/dist/app-sidecar/session-routes.js.map +1 -0
- package/dist/app-sidecar/session-types.d.ts +39 -0
- package/dist/app-sidecar/session-types.js +5 -0
- package/dist/app-sidecar/session-types.js.map +1 -0
- package/dist/app-sidecar/task-routes.d.ts +3 -0
- package/dist/app-sidecar/task-routes.js +232 -0
- package/dist/app-sidecar/task-routes.js.map +1 -0
- package/dist/app-sidecar/usage.d.ts +19 -0
- package/dist/app-sidecar/usage.js +153 -0
- package/dist/app-sidecar/usage.js.map +1 -0
- package/dist/app-sidecar/workspace-routes.d.ts +3 -0
- package/dist/app-sidecar/workspace-routes.js +374 -0
- package/dist/app-sidecar/workspace-routes.js.map +1 -0
- package/dist/app-sidecar.js +541 -3971
- package/dist/app-sidecar.js.map +1 -1
- package/dist/chat-agents/jiwa.js +2 -0
- package/dist/chat-agents/jiwa.js.map +1 -1
- package/dist/chat-agents/memory.js +2 -0
- package/dist/chat-agents/memory.js.map +1 -1
- package/dist/cli/auth.js +13 -9
- package/dist/cli/auth.js.map +1 -1
- package/dist/cli.js +10 -11
- package/dist/cli.js.map +1 -1
- package/dist/config.js +1 -1
- package/dist/core/acceptance-checks.js +3 -9
- package/dist/core/acceptance-checks.js.map +1 -1
- package/dist/core/agent-session/helpers.d.ts +26 -0
- package/dist/core/agent-session/helpers.js +47 -0
- package/dist/core/agent-session/helpers.js.map +1 -0
- package/dist/core/agent-session/mcp-tools.d.ts +68 -0
- package/dist/core/agent-session/mcp-tools.js +195 -0
- package/dist/core/agent-session/mcp-tools.js.map +1 -0
- package/dist/core/agent-session/run-loop-monitor.d.ts +63 -0
- package/dist/core/agent-session/run-loop-monitor.js +164 -0
- package/dist/core/agent-session/run-loop-monitor.js.map +1 -0
- package/dist/core/agent-session/transcript-markers.d.ts +57 -0
- package/dist/core/agent-session/transcript-markers.js +166 -0
- package/dist/core/agent-session/transcript-markers.js.map +1 -0
- package/dist/core/agent-session/verification-tracker.d.ts +50 -0
- package/dist/core/agent-session/verification-tracker.js +269 -0
- package/dist/core/agent-session/verification-tracker.js.map +1 -0
- package/dist/core/agent-session.d.ts +27 -87
- package/dist/core/agent-session.js +166 -713
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-providers.js +3 -3
- package/dist/core/auth-providers.js.map +1 -1
- package/dist/core/autopilot-cycle.d.ts +8 -2
- package/dist/core/autopilot-cycle.js +22 -3
- package/dist/core/autopilot-cycle.js.map +1 -1
- package/dist/core/bundled-agents.js +6 -6
- package/dist/core/bundled-agents.js.map +1 -1
- package/dist/core/checklist-git.d.ts +19 -0
- package/dist/core/checklist-git.js +54 -0
- package/dist/core/checklist-git.js.map +1 -0
- package/dist/core/checklist-items.d.ts +10 -1
- package/dist/core/checklist-items.js +22 -0
- package/dist/core/checklist-items.js.map +1 -1
- package/dist/core/checklist-prompt.d.ts +14 -3
- package/dist/core/checklist-prompt.js +38 -8
- package/dist/core/checklist-prompt.js.map +1 -1
- package/dist/core/checklist-snapshot.d.ts +5 -1
- package/dist/core/checklist-snapshot.js +20 -3
- package/dist/core/checklist-snapshot.js.map +1 -1
- package/dist/core/checklist-store.d.ts +5 -1
- package/dist/core/checklist-store.js +35 -4
- package/dist/core/checklist-store.js.map +1 -1
- package/dist/core/context-limits.js +1 -1
- package/dist/core/context-limits.js.map +1 -1
- package/dist/core/event-bus.d.ts +1 -1
- package/dist/core/event-bus.js +39 -13
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/extensions/plugin-bundles.js +4 -2
- package/dist/core/extensions/plugin-bundles.js.map +1 -1
- package/dist/core/hashline.d.ts +10 -8
- package/dist/core/hashline.js.map +1 -1
- package/dist/core/mcp/client.js +2 -0
- package/dist/core/mcp/client.js.map +1 -1
- package/dist/core/mcp/loopback.d.ts +2 -2
- package/dist/core/mcp/loopback.js +2 -2
- package/dist/core/mcp/shared-pool.js +4 -3
- package/dist/core/mcp/shared-pool.js.map +1 -1
- package/dist/core/persistent-shell.js +2 -1
- package/dist/core/persistent-shell.js.map +1 -1
- package/dist/core/plan-handoff.d.ts +30 -0
- package/dist/core/plan-handoff.js +10 -0
- package/dist/core/plan-handoff.js.map +1 -0
- package/dist/core/plan-submission-gate.d.ts +28 -0
- package/dist/core/plan-submission-gate.js +27 -0
- package/dist/core/plan-submission-gate.js.map +1 -0
- package/dist/core/process-manager.js +9 -1
- package/dist/core/process-manager.js.map +1 -1
- package/dist/core/project-health-scan.d.ts +109 -0
- package/dist/core/project-health-scan.js +673 -0
- package/dist/core/project-health-scan.js.map +1 -0
- package/dist/core/project-health-score.d.ts +41 -0
- package/dist/core/project-health-score.js +257 -0
- package/dist/core/project-health-score.js.map +1 -0
- package/dist/core/prompt-commands.js +44 -6
- package/dist/core/prompt-commands.js.map +1 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-storage.d.ts +1 -0
- package/dist/core/session-storage.js +1 -1
- package/dist/core/session-storage.js.map +1 -1
- package/dist/core/skills.js +6 -9
- package/dist/core/skills.js.map +1 -1
- package/dist/core/style-packs/index.js +2 -11
- package/dist/core/style-packs/index.js.map +1 -1
- package/dist/core/style-packs/packs.d.ts +3 -12
- package/dist/core/style-packs/packs.js +132 -173
- package/dist/core/style-packs/packs.js.map +1 -1
- package/dist/core/subagent-manager.js +11 -6
- package/dist/core/subagent-manager.js.map +1 -1
- package/dist/core/subagent-receipt.js +3 -4
- package/dist/core/subagent-receipt.js.map +1 -1
- package/dist/core/ui-adoption.js +2 -0
- package/dist/core/ui-adoption.js.map +1 -1
- package/dist/core/ui-registry.js +5 -4
- package/dist/core/ui-registry.js.map +1 -1
- package/dist/core/verification-evidence.d.ts +21 -2
- package/dist/core/verification-evidence.js +283 -8
- package/dist/core/verification-evidence.js.map +1 -1
- package/dist/core/verification-gate.js +4 -2
- package/dist/core/verification-gate.js.map +1 -1
- package/dist/core/verify-commands.js +2 -3
- package/dist/core/verify-commands.js.map +1 -1
- package/dist/modes/agent-home-mode.js +1 -4
- package/dist/modes/agent-home-mode.js.map +1 -1
- package/dist/modes/subagent-worker-mode.js +13 -8
- package/dist/modes/subagent-worker-mode.js.map +1 -1
- package/dist/system-prompt.js +70 -87
- package/dist/system-prompt.js.map +1 -1
- package/dist/tools/ask-user.js +13 -74
- package/dist/tools/ask-user.js.map +1 -1
- package/dist/tools/bash.d.ts +3 -1
- package/dist/tools/bash.js +28 -84
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/checklist.d.ts +7 -14
- package/dist/tools/checklist.js +22 -41
- package/dist/tools/checklist.js.map +1 -1
- package/dist/tools/code-nav.js +7 -29
- package/dist/tools/code-nav.js.map +1 -1
- package/dist/tools/edit.d.ts +4 -9
- package/dist/tools/edit.js +175 -65
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/enter-plan.js +2 -7
- package/dist/tools/enter-plan.js.map +1 -1
- package/dist/tools/exit-plan.js +2 -3
- package/dist/tools/exit-plan.js.map +1 -1
- package/dist/tools/find.js +3 -4
- package/dist/tools/find.js.map +1 -1
- package/dist/tools/grep.js +9 -20
- package/dist/tools/grep.js.map +1 -1
- package/dist/tools/index.js +10 -7
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/ls.js +3 -3
- package/dist/tools/ls.js.map +1 -1
- package/dist/tools/prompt-hints.js +34 -47
- package/dist/tools/prompt-hints.js.map +1 -1
- package/dist/tools/read-only-bash.js +3 -0
- package/dist/tools/read-only-bash.js.map +1 -1
- package/dist/tools/read.js +8 -20
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/search-code.js +4 -12
- package/dist/tools/search-code.js.map +1 -1
- package/dist/tools/skill.js +13 -7
- package/dist/tools/skill.js.map +1 -1
- package/dist/tools/subagent-control.js +7 -22
- package/dist/tools/subagent-control.js.map +1 -1
- package/dist/tools/subagent.js +1 -1
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/task-output.js +4 -15
- package/dist/tools/task-output.js.map +1 -1
- package/dist/tools/task-send.js +5 -17
- package/dist/tools/task-send.js.map +1 -1
- package/dist/tools/task-stop.js +2 -2
- package/dist/tools/task-stop.js.map +1 -1
- package/dist/tools/tool-search.js +2 -7
- package/dist/tools/tool-search.js.map +1 -1
- package/dist/tools/tool-tiers.d.ts +21 -4
- package/dist/tools/tool-tiers.js +44 -17
- package/dist/tools/tool-tiers.js.map +1 -1
- package/dist/tools/web-fetch.js +7 -33
- package/dist/tools/web-fetch.js.map +1 -1
- package/dist/tools/write.js +3 -4
- package/dist/tools/write.js.map +1 -1
- package/dist/ui/App.js +20 -26
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/components/Footer.js +1 -2
- package/dist/ui/components/Footer.js.map +1 -1
- package/dist/ui/components/InputArea.js +0 -2
- package/dist/ui/components/InputArea.js.map +1 -1
- package/dist/ui/components/ToolExecution.js +4 -3
- package/dist/ui/components/ToolExecution.js.map +1 -1
- package/dist/ui/hooks/useAgentLoop.js +7 -6
- package/dist/ui/hooks/useAgentLoop.js.map +1 -1
- package/dist/ui/sessions.js +1 -5
- package/dist/ui/sessions.js.map +1 -1
- package/dist/ui/utils/highlight.d.ts +0 -5
- package/dist/ui/utils/highlight.js +3 -49
- package/dist/ui/utils/highlight.js.map +1 -1
- package/dist/ui/utils/markdown-renderer.d.ts +6 -0
- package/dist/ui/utils/markdown-renderer.js +21 -5
- package/dist/ui/utils/markdown-renderer.js.map +1 -1
- package/dist/utils/process.js +3 -3
- package/dist/utils/process.js.map +1 -1
- package/dist/utils/shared-poll.d.ts +37 -0
- package/dist/utils/shared-poll.js +104 -0
- package/dist/utils/shared-poll.js.map +1 -0
- package/package.json +8 -8
- package/dist/core/api-benchmark.d.ts +0 -63
- package/dist/core/api-benchmark.js +0 -381
- package/dist/core/api-benchmark.js.map +0 -1
- package/dist/core/bash-spawn-benchmark.d.ts +0 -1
- package/dist/core/bash-spawn-benchmark.js +0 -139
- package/dist/core/bash-spawn-benchmark.js.map +0 -1
- package/dist/core/cache-warm-benchmark.d.ts +0 -21
- package/dist/core/cache-warm-benchmark.js +0 -170
- package/dist/core/cache-warm-benchmark.js.map +0 -1
- package/dist/core/fast-apply-benchmark.d.ts +0 -25
- package/dist/core/fast-apply-benchmark.js +0 -284
- package/dist/core/fast-apply-benchmark.js.map +0 -1
- package/dist/core/hashline-edit-benchmark.d.ts +0 -88
- package/dist/core/hashline-edit-benchmark.js +0 -518
- package/dist/core/hashline-edit-benchmark.js.map +0 -1
- package/dist/core/semantic-search-benchmark.d.ts +0 -36
- package/dist/core/semantic-search-benchmark.js +0 -211
- package/dist/core/semantic-search-benchmark.js.map +0 -1
- package/dist/core/speed-benchmark.d.ts +0 -132
- package/dist/core/speed-benchmark.js +0 -410
- package/dist/core/speed-benchmark.js.map +0 -1
- package/dist/ui/activity-phrases.d.ts +0 -10
- package/dist/ui/activity-phrases.js +0 -184
- package/dist/ui/activity-phrases.js.map +0 -1
- package/dist/ui/components/PlanApproval.d.ts +0 -7
- package/dist/ui/components/PlanApproval.js +0 -60
- package/dist/ui/components/PlanApproval.js.map +0 -1
- package/dist/ui/components/PlanBanner.d.ts +0 -5
- package/dist/ui/components/PlanBanner.js +0 -31
- package/dist/ui/components/PlanBanner.js.map +0 -1
- package/dist/ui/components/PlanProgress.d.ts +0 -6
- package/dist/ui/components/PlanProgress.js +0 -30
- package/dist/ui/components/PlanProgress.js.map +0 -1
- package/dist/ui/hooks/useMinDisplayTime.d.ts +0 -10
- package/dist/ui/hooks/useMinDisplayTime.js +0 -34
- package/dist/ui/hooks/useMinDisplayTime.js.map +0 -1
- package/dist/ui/hooks/useSessionManager.d.ts +0 -12
- package/dist/ui/hooks/useSessionManager.js +0 -43
- package/dist/ui/hooks/useSessionManager.js.map +0 -1
- package/dist/ui/hooks/useSlashCommands.d.ts +0 -6
- package/dist/ui/hooks/useSlashCommands.js +0 -11
- package/dist/ui/hooks/useSlashCommands.js.map +0 -1
- package/dist/ui/terminal-history-spacing.d.ts +0 -1
- package/dist/ui/terminal-history-spacing.js +0 -2
- package/dist/ui/terminal-history-spacing.js.map +0 -1
- package/dist/ui/utils/markdown-cache.d.ts +0 -10
- package/dist/ui/utils/markdown-cache.js +0 -58
- package/dist/ui/utils/markdown-cache.js.map +0 -1
- package/dist/ui/utils/token-to-ansi.d.ts +0 -8
- package/dist/ui/utils/token-to-ansi.js +0 -323
- package/dist/ui/utils/token-to-ansi.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|

|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
|
-
<strong>The fast, lean coding agent.
|
|
4
|
+
<strong>The fast, lean coding agent. Twelve providers plus local models. Zero bloat.</strong>
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
<a href="https://github.com/Gahroot"><img src="https://img.shields.io/badge/GitHub-181717?style=for-the-badge&logo=github&logoColor=white" alt="GitHub"></a>
|
|
13
13
|
</p>
|
|
14
14
|
|
|
15
|
-
A coding agent that ships only what the model needs to work — a tiny system prompt,
|
|
15
|
+
A coding agent that ships only what the model needs to work — a tiny system prompt, no bundled MCPs, and a focused tool set. Switch between Anthropic, OpenAI, Gemini, xAI, Moonshot, GLM, MiniMax, Xiaomi, DeepSeek, Sakana, OpenRouter, Hugging Face, and your own local models mid-conversation. Run it on its own, or let [`@prestyj/boss`](../ezboss/README.md) drive a fleet of `ezcoder` workers across many projects from a single chat.
|
|
16
16
|
|
|
17
17
|
Built on [`@prestyj/ai`](../ai/README.md) and [`@prestyj/agent`](../agent/README.md). Part of the [EZCoder Framework](../../README.md) monorepo.
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
-
##
|
|
21
|
+
## Run It
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
24
|
npm i -g @prestyj/cli
|
|
@@ -27,11 +27,11 @@ ezcoder login # Pick provider, authenticate
|
|
|
27
27
|
ezcoder # Start coding
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
OAuth for Anthropic and
|
|
30
|
+
OAuth for Anthropic, OpenAI, and Gemini; OAuth or an API key for xAI and Moonshot (log in once, auto-refresh, no key to leak). API keys for the rest. Up and running in seconds either way. Auth lives in `~/.ezcoder/auth.json` and is shared with `ezboss`.
|
|
31
31
|
|
|
32
32
|
---
|
|
33
33
|
|
|
34
|
-
##
|
|
34
|
+
## The system prompt problem
|
|
35
35
|
|
|
36
36
|
Every token in the system prompt gets processed on **every single turn**. It's not a one-time cost. It's a tax on every request.
|
|
37
37
|
|
|
@@ -51,38 +51,43 @@ EZ Coder sends only what the model needs: how to work, what tools it has, and yo
|
|
|
51
51
|
|
|
52
52
|
---
|
|
53
53
|
|
|
54
|
-
##
|
|
54
|
+
## The MCP problem
|
|
55
55
|
|
|
56
56
|
Same philosophy applies to tools. People collect MCPs like Pokemon. Slack MCP, GitHub MCP, Notion MCP, five different file system MCPs. Every single one injects its tool descriptions into the context. The model now has to figure out which of 40+ tools to use for any given task.
|
|
57
57
|
|
|
58
58
|
This doesn't help. It confuses the agent. More tool descriptions = more noise = worse tool selection. The model spends tokens reasoning about tools it will never call.
|
|
59
59
|
|
|
60
|
-
EZ Coder ships with
|
|
60
|
+
EZ Coder ships with no MCPs by default. Checking work against real-world code is a native tool instead: `steroids` finds production repos similar to yours so the agent can confirm API usage, library idioms, and patterns. It loads only when the agent asks for it, so it costs nothing until it's used. (On GLM, the Z.AI MCP servers that come with your key are connected automatically.)
|
|
61
61
|
|
|
62
|
-
You can still add your own MCPs
|
|
62
|
+
You can still add your own MCPs in `~/.ezcoder/mcp.json` or `.ezcoder/mcp.json`. But start with less. You'll get better results.
|
|
63
63
|
|
|
64
64
|
---
|
|
65
65
|
|
|
66
|
-
##
|
|
66
|
+
## Twelve providers, one agent
|
|
67
67
|
|
|
68
68
|
Switch mid-conversation with `/model`. Not locked to anyone.
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
| **
|
|
74
|
-
| **
|
|
75
|
-
| **
|
|
76
|
-
| **
|
|
77
|
-
| **
|
|
78
|
-
| **
|
|
79
|
-
| **
|
|
80
|
-
| **
|
|
81
|
-
| **
|
|
70
|
+
| Provider | Models | Auth |
|
|
71
|
+
| ----------------- | ------------------------------------------------------------------------------------------- | ---------------- |
|
|
72
|
+
| **Anthropic** | Claude Fable 5.1, Opus 5.5, Sonnet 5.5, Haiku 5.5 | OAuth |
|
|
73
|
+
| **OpenAI** | GPT-6 Astra, GPT-6.1 Sol, GPT-6 Luna | OAuth |
|
|
74
|
+
| **Gemini** | Gemini 3.1 Pro (Preview), 3.8 Flash, 3.7 Flash, 3.5 Flash, 3.5 Flash Lite, 3.1 Flash Lite | OAuth |
|
|
75
|
+
| **xAI (Grok)** | Grok 4.7 | OAuth or API key |
|
|
76
|
+
| **Moonshot** | Kimi K3, K2.8 Preview (Kimi sign-in), K2.7 Code, K2.7 Code HighSpeed | OAuth or API key |
|
|
77
|
+
| **Z.AI (GLM)** | GLM-5.3, GLM-5.3-Flash | API key |
|
|
78
|
+
| **MiniMax** | MiniMax M3 | API key |
|
|
79
|
+
| **Xiaomi (MiMo)** | MiMo-V2.6-Pro, MiMo-V2.6-Flash, MiMo-V2.6-Pro-UltraSpeed | API key |
|
|
80
|
+
| **DeepSeek** | DeepSeek V4 Pro, V4.1 Flash | API key |
|
|
81
|
+
| **Sakana (Fugu)** | Fugu, Fugu Max, Fugu Ultra | API key |
|
|
82
|
+
| **OpenRouter** | Qwen3.8 Max | API key |
|
|
83
|
+
| **Hugging Face** | Kimi K2.7 Code, DeepSeek V4.1 Flash, GPT-OSS 120B (Inference Providers router) | API key |
|
|
84
|
+
| **Local** | Any model on an OpenAI-compatible server: Ollama, LM Studio, llama.cpp, vLLM | None |
|
|
85
|
+
|
|
86
|
+
Every hosted model above except GLM-5.3, DeepSeek V4 Pro, and GPT-OSS 120B accepts images.
|
|
82
87
|
|
|
83
88
|
The same conversation, the same tools, the same project context — only the model changes. Use a strong reasoning model when you need it, swap to a fast cheap one for grunt work, never restart your session.
|
|
84
89
|
|
|
85
|
-
**Attachments.** Drag, paste, or type a path to attach images and video in the chat input. Video is sent natively to models that support it (Gemini 3.x,
|
|
90
|
+
**Attachments.** Drag, paste, or type a path to attach images and video in the chat input. Video is sent natively to models that support it (Gemini 3.x, every Moonshot Kimi model, MiniMax M3, MiMo-V2.6, Qwen3.8 Max); for other models the video is saved to a temp file and the model is told to inspect it with ffmpeg or its own tools.
|
|
86
91
|
|
|
87
92
|
---
|
|
88
93
|
|
|
@@ -118,7 +123,7 @@ Run `ezcoder` directly when you're heads-down on one project. Switch to `ezboss`
|
|
|
118
123
|
|
|
119
124
|
---
|
|
120
125
|
|
|
121
|
-
##
|
|
126
|
+
## Slash commands
|
|
122
127
|
|
|
123
128
|
Everything runs through slash commands inside the session. Not CLI flags.
|
|
124
129
|
|
|
@@ -131,7 +136,8 @@ Everything runs through slash commands inside the session. Not CLI flags.
|
|
|
131
136
|
| `/branch` (`/b`) | Branch the current conversation |
|
|
132
137
|
| `/branches` | List branches of the current session |
|
|
133
138
|
| `/rewind` | Restore files and/or conversation to an earlier checkpoint |
|
|
134
|
-
| `/
|
|
139
|
+
| `/add-dir` | Add another project folder to this workspace |
|
|
140
|
+
| `/remove-dir` | Remove an added project folder from this workspace |
|
|
135
141
|
| `/settings` (`/config`) | Open settings |
|
|
136
142
|
| `/help` (`/h`, `/?`) | Show all commands |
|
|
137
143
|
| `/quit` (`/q`, `/exit`) | Exit |
|
|
@@ -142,28 +148,37 @@ Plus built-in workflows that ship with the binary:
|
|
|
142
148
|
/expand # Compare against current alternatives and report gaps
|
|
143
149
|
/raise-floor # Audit existing features and make them just work
|
|
144
150
|
/bullet-proof # Run a defensive security review
|
|
145
|
-
/init # Generate CLAUDE.md for your project
|
|
151
|
+
/init # Generate or update AGENTS.md / CLAUDE.md for your project
|
|
146
152
|
/setup-commit # Generate a /commit command with quality checks
|
|
153
|
+
/setup-ci # Set up or harden CI for any stack
|
|
147
154
|
/setup-skills # Audit and recommend reusable skills
|
|
155
|
+
/compare # Compare your code against real-world code
|
|
156
|
+
/steroids # Index real repos like this project
|
|
148
157
|
```
|
|
149
158
|
|
|
150
159
|
---
|
|
151
160
|
|
|
152
|
-
##
|
|
161
|
+
## Tools
|
|
153
162
|
|
|
154
|
-
EZ Coder comes with a focused set of tools.
|
|
163
|
+
EZ Coder comes with a focused set of tools. Only six core tools — `read`, `write`, `edit`, `bash`, `grep`, and `skill` — plus `tool_search` send their full schemas on every request. Everything else is listed as a one-line hint and loads the first time the agent needs it, so rarely used tools cost almost nothing.
|
|
155
164
|
|
|
156
165
|
| Tool | What it does |
|
|
157
166
|
| --------------------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
158
|
-
| `bash` | Run shell commands
|
|
167
|
+
| `bash` | Run shell commands, in the foreground or background (`task_output` / `task_send` / `task_stop`) |
|
|
159
168
|
| `read` | Read file contents |
|
|
160
169
|
| `write` | Write files |
|
|
161
170
|
| `edit` | Surgical string replacements |
|
|
162
171
|
| `grep` | Search file contents (regex) |
|
|
163
|
-
| `
|
|
164
|
-
| `
|
|
165
|
-
| `
|
|
172
|
+
| `skill` | Load a skill's instructions |
|
|
173
|
+
| `tool_search` | Load an on-demand tool by capability |
|
|
174
|
+
| `find` / `ls` | Find files by glob pattern / list a directory |
|
|
175
|
+
| `code_search` / `code_nav` | Find code by meaning / jump to exact definitions and callers |
|
|
176
|
+
| `web_fetch` / `web_search` | Fetch a URL / search the web |
|
|
177
|
+
| `steroids` | Find real production repos similar to yours and read how they do it |
|
|
178
|
+
| `source_path` | Locate an installed dependency's source |
|
|
166
179
|
| `screenshot` | Open a URL / dev server in a headless browser and capture a PNG so the agent can see the rendered page |
|
|
180
|
+
| `debug` | Drive the Node debugger |
|
|
181
|
+
| `enter_plan` / `exit_plan` | Plan before editing, then hand the plan back for approval |
|
|
167
182
|
| `subagent` | Run one blocking, isolated child task (backward-compatible) |
|
|
168
183
|
| `spawn_agent` / `wait_agent` | Launch persistent child turns concurrently and collect results |
|
|
169
184
|
| `send_message` / `followup_task` | Steer a running child or reuse an idle child's context |
|
|
@@ -171,7 +186,7 @@ EZ Coder comes with a focused set of tools. Each one is small, well-described, a
|
|
|
171
186
|
|
|
172
187
|
The `screenshot` tool needs the optional `playwright` dependency plus a one-time `npx playwright install chromium`. Without it the tool returns an install hint instead of failing the turn. Captured images render inline in graphics-capable terminals (kitty, Ghostty, WezTerm, iTerm2); other terminals show a text line.
|
|
173
188
|
|
|
174
|
-
|
|
189
|
+
Add your own MCPs in `~/.ezcoder/mcp.json` or `.ezcoder/mcp.json` if you need more — but start lean.
|
|
175
190
|
|
|
176
191
|
### Async subagent lifecycle
|
|
177
192
|
|
|
@@ -185,13 +200,13 @@ Parent cancellation interrupts active children. Session disposal shuts down ever
|
|
|
185
200
|
|
|
186
201
|
---
|
|
187
202
|
|
|
188
|
-
##
|
|
203
|
+
## Custom commands
|
|
189
204
|
|
|
190
205
|
Drop a markdown file in `.ezcoder/commands/` and it becomes a slash command. Your React app gets `/deploy` and `/storybook`. Your API gets `/migrate` and `/seed`. Different projects, different commands.
|
|
191
206
|
|
|
192
207
|
---
|
|
193
208
|
|
|
194
|
-
##
|
|
209
|
+
## Checkpoints & `/rewind`
|
|
195
210
|
|
|
196
211
|
Before every file the agent writes or edits, EZ Coder snapshots the prior on-disk content into a per-session checkpoint (stored under `~/.ezcoder/checkpoints/`, never in your repo). Run `/rewind` to pick an earlier checkpoint and restore **code only**, **conversation only**, or **both**.
|
|
197
212
|
|
|
@@ -199,7 +214,7 @@ Only edits made through ezcoder's `write`/`edit` tools are tracked — changes m
|
|
|
199
214
|
|
|
200
215
|
---
|
|
201
216
|
|
|
202
|
-
##
|
|
217
|
+
## Skills
|
|
203
218
|
|
|
204
219
|
Reusable behaviors across projects. Drop `.md` files in:
|
|
205
220
|
|
|
@@ -226,22 +241,22 @@ Eleven ship built in, and route themselves when the work matches:
|
|
|
226
241
|
|
|
227
242
|
---
|
|
228
243
|
|
|
229
|
-
##
|
|
244
|
+
## Project guidelines
|
|
230
245
|
|
|
231
|
-
Drop
|
|
246
|
+
Drop an `AGENTS.md` or `CLAUDE.md` in your repo root (or any parent directory). EZ Coder picks it up automatically. One file per directory is loaded, first match wins: `AGENTS.override.md` > `AGENTS.md` > `CLAUDE.md` > `.cursorrules` > `CONVENTIONS.md`.
|
|
232
247
|
|
|
233
248
|
Your rules. Your conventions. The agent follows them.
|
|
234
249
|
|
|
235
250
|
---
|
|
236
251
|
|
|
237
|
-
##
|
|
252
|
+
## Community
|
|
238
253
|
|
|
239
254
|
- [Prestyj website](https://prestyj.com) — tutorials and updates
|
|
240
255
|
- [GitHub @Gahroot](https://github.com/Gahroot)
|
|
241
256
|
|
|
242
257
|
---
|
|
243
258
|
|
|
244
|
-
##
|
|
259
|
+
## License
|
|
245
260
|
|
|
246
261
|
MIT
|
|
247
262
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: bulletproof
|
|
3
|
-
description: Use
|
|
3
|
+
description: "Use for attacker-reachable code: auth, tokens, crypto, untrusted input, secrets, tenant data, CI, agent tools. Do NOT use for local scripts without auth or network."
|
|
4
4
|
license: Apache-2.0. Content is defensive engineering guidance, not a security certification or a penetration test. See references/provenance.md.
|
|
5
5
|
compatibility: Works offline from the bundled references, which are a snapshot dated 3 October 2026. Version numbers, CVEs, and incident details decay fast; re-verify date-sensitive claims with web access before stating them as current. Never certifies that software is secure.
|
|
6
6
|
---
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: clarify
|
|
3
|
-
description: Use when requirements
|
|
3
|
+
description: Use when requirements are genuinely unsettled. Do NOT use for routine work.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Clarify
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: code-review
|
|
3
|
-
description: Use when
|
|
3
|
+
description: Use when asked to review a diff, PR or finished work. Do NOT use mid-build.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Code Review
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: compliance-guard
|
|
3
|
-
description: Use when shipping
|
|
3
|
+
description: Use when shipping to real users risks legal exposure (personal data, payments, minors). Do NOT use for local work.
|
|
4
4
|
license: Apache-2.0. Content is engineering guidance, not legal advice. See references/provenance.md.
|
|
5
5
|
compatibility: Static review works offline from the bundled references. Legal status changes constantly; date-sensitive claims must be re-verified with web access before being stated as current. Never certifies compliance.
|
|
6
6
|
---
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: durable
|
|
3
|
-
description: Use when
|
|
3
|
+
description: "Use when data could be lost: migrations, destructive ops, real databases. Do NOT use for query speed."
|
|
4
4
|
license: Data-durability engineering guidance, not a DBA certification. Sources and snapshot date are recorded at the foot of each reference file.
|
|
5
5
|
compatibility: Snapshot dated 3 October 2026. Version behaviours, provider retention defaults and tool flags decay — re-verify with web access before asserting them as current.
|
|
6
6
|
---
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: evidence-led-ui
|
|
3
|
-
description: Use when building or
|
|
3
|
+
description: Use when building or reviewing UI visuals. Do NOT use for behaviour-only changes.
|
|
4
4
|
license: See LICENSES.md
|
|
5
5
|
compatibility: Full review requires filesystem inspection and rendered screenshots (deferred `screenshot` tool); web research and device tooling are optional and unavailable checks must be reported as unverified.
|
|
6
6
|
---
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: lean
|
|
3
|
-
description: Use when speed or resource use matters
|
|
3
|
+
description: Use when speed or resource use matters. Do NOT use for correctness bugs.
|
|
4
4
|
license: Performance engineering guidance, not a benchmark certification. Sources and snapshot date are recorded at the foot of each reference file.
|
|
5
5
|
compatibility: Snapshot dated 3 October 2026. Thresholds, tool names, and defaults decay — re-verify with web access before asserting them as current. Claims sourced to that date carry a SNAPSHOT marker.
|
|
6
6
|
---
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: refactoring
|
|
3
|
-
description: Use for
|
|
3
|
+
description: Use for behaviour-preserving restructuring behind an unchanged contract. Do NOT use for renames, bug fixes or behaviour changes.
|
|
4
4
|
license: Behavior-preservation methodology synthesized from public sources (Fowler's Refactoring catalog, Tidy First?, and community agent skills by bienhoang, wondelai, mattpocock, jeffallan, vasilyu1983), audited 2026-09-12.
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: root-cause
|
|
3
|
-
description: Use when a bug resists the obvious fix
|
|
3
|
+
description: Use when a bug resists the obvious fix or is flaky. Do NOT use when the cause is obvious.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Root-Cause
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: shared-language
|
|
3
|
-
description: Use when
|
|
3
|
+
description: Use when domain terms drift or a decision needs an ADR. Do NOT use for renames.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Shared Language
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tdd
|
|
3
|
-
description: Use when
|
|
3
|
+
description: Use when asked for test-first development. Do NOT use for post-build tests.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# TDD
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Provider, ThinkingLevel } from "@prestyj/ai";
|
|
2
|
+
import type { NolanModelPref } from "../core/nolan-model.js";
|
|
3
|
+
export declare const ALL_PROVIDERS: Provider[];
|
|
4
|
+
/** Per-project model + thinking preferences. Persisted so each window (one
|
|
5
|
+
* project cwd) restores its OWN model across app restarts — instead of every
|
|
6
|
+
* window reading the same single global slot that the last writer clobbered. */
|
|
7
|
+
export interface ProjectModelPrefs {
|
|
8
|
+
provider: Provider;
|
|
9
|
+
model: string;
|
|
10
|
+
thinkingEnabled?: boolean;
|
|
11
|
+
thinkingLevel?: ThinkingLevel;
|
|
12
|
+
}
|
|
13
|
+
export interface AppSettings {
|
|
14
|
+
/** Folder new projects are created inside. Defaults to ~/ez-projects. */
|
|
15
|
+
projectsRoot: string;
|
|
16
|
+
/** Model + thinking prefs keyed by normalized project cwd. A window restores
|
|
17
|
+
* its own entry on boot; absent → global settings.json → provider default. */
|
|
18
|
+
projectModels?: Record<string, ProjectModelPrefs>;
|
|
19
|
+
/** Autopilot (auto-review) on/off keyed by normalized project cwd. Per-window
|
|
20
|
+
* (one window = one cwd); absent/false → off. Restored on boot. */
|
|
21
|
+
autopilot?: Record<string, boolean>;
|
|
22
|
+
/** Nolan model override keyed by normalized project cwd. */
|
|
23
|
+
nolanModels?: Record<string, NolanModelPref>;
|
|
24
|
+
/** Extra folders scanned for projects alongside `projectsRoot`. */
|
|
25
|
+
projectRoots?: string[];
|
|
26
|
+
/** Project paths dismissed from the picker, as normalized cwds. */
|
|
27
|
+
hiddenProjects?: string[];
|
|
28
|
+
}
|
|
29
|
+
export declare function stringArray(value: unknown): string[] | undefined;
|
|
30
|
+
export declare function appSettingsFile(): string;
|
|
31
|
+
export declare function defaultProjectsRoot(): string;
|
|
32
|
+
/** Normalize a project cwd to a stable settings key so trailing slashes /
|
|
33
|
+
* relative segments collapse — the same project always maps to one entry. */
|
|
34
|
+
export declare function projectModelKey(cwd: string): string;
|
|
35
|
+
export declare function loadAppSettings(): Promise<AppSettings>;
|
|
36
|
+
export declare function saveAppSettings(settings: AppSettings): Promise<void>;
|
|
37
|
+
/** Read this project's persisted model/thinking prefs, if any. */
|
|
38
|
+
export declare function loadProjectModelPrefs(cwd: string): Promise<ProjectModelPrefs | undefined>;
|
|
39
|
+
/** Persist this project's model/thinking prefs via read-modify-write so the rest
|
|
40
|
+
* of the settings file (projectsRoot, other projects' entries) is preserved. */
|
|
41
|
+
export declare function saveProjectModelPrefs(cwd: string, prefs: ProjectModelPrefs): Promise<void>;
|
|
42
|
+
/** Read this project's persisted Nolan model override, if any. */
|
|
43
|
+
export declare function loadNolanModelPref(cwd: string): Promise<NolanModelPref | undefined>;
|
|
44
|
+
/** Persist (or with null, clear) this project's Nolan model override via
|
|
45
|
+
* read-modify-write so the rest of the settings file is preserved. */
|
|
46
|
+
export declare function saveNolanModelPref(cwd: string, pref: NolanModelPref | null): Promise<void>;
|
|
47
|
+
/** Read this project's persisted autopilot flag (default off). */
|
|
48
|
+
export declare function loadAutopilot(cwd: string): Promise<boolean>;
|
|
49
|
+
/** Persist this project's autopilot flag via read-modify-write so the rest of
|
|
50
|
+
* the settings file (projectsRoot, model map, other projects) is preserved. */
|
|
51
|
+
export declare function saveAutopilot(cwd: string, enabled: boolean): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Persist the active model selection to ~/.ezcoder/settings.json so it survives app
|
|
54
|
+
* restarts. Mirrors the CLI's handleModelSelect persistence (App.tsx).
|
|
55
|
+
*/
|
|
56
|
+
export declare function persistModelSelection(settingsFile: string, provider: Provider, model: string): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Persist the thinking level to ~/.ezcoder/settings.json so it survives app restarts.
|
|
59
|
+
* Mirrors the CLI's handleToggleThinking persistence (App.tsx).
|
|
60
|
+
*/
|
|
61
|
+
export declare function persistThinkingLevel(settingsFile: string, level: ThinkingLevel | undefined): Promise<void>;
|
|
62
|
+
/** Validate a project folder name: lowercase letters, digits, dashes only. */
|
|
63
|
+
export declare function isValidProjectName(name: string): boolean;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { SettingsManager } from "../core/settings-manager.js";
|
|
5
|
+
import { log } from "../core/logger.js";
|
|
6
|
+
export const ALL_PROVIDERS = [
|
|
7
|
+
// US
|
|
8
|
+
"anthropic",
|
|
9
|
+
"openai",
|
|
10
|
+
"gemini",
|
|
11
|
+
"xai",
|
|
12
|
+
// China
|
|
13
|
+
"moonshot",
|
|
14
|
+
"glm",
|
|
15
|
+
"minimax",
|
|
16
|
+
"xiaomi",
|
|
17
|
+
"deepseek",
|
|
18
|
+
// Open-community gateway, before the provider-agnostic one
|
|
19
|
+
"huggingface",
|
|
20
|
+
// Japan, then provider-agnostic gateway last
|
|
21
|
+
"sakana",
|
|
22
|
+
"openrouter",
|
|
23
|
+
];
|
|
24
|
+
export function stringArray(value) {
|
|
25
|
+
if (!Array.isArray(value))
|
|
26
|
+
return undefined;
|
|
27
|
+
const out = value.filter((v) => typeof v === "string" && v.trim().length > 0);
|
|
28
|
+
return out.length > 0 ? out : undefined;
|
|
29
|
+
}
|
|
30
|
+
export function appSettingsFile() {
|
|
31
|
+
return path.join(os.homedir(), ".ezcoder", "ezcoder-app.json");
|
|
32
|
+
}
|
|
33
|
+
export function defaultProjectsRoot() {
|
|
34
|
+
return path.join(os.homedir(), "ez-projects");
|
|
35
|
+
}
|
|
36
|
+
/** Normalize a project cwd to a stable settings key so trailing slashes /
|
|
37
|
+
* relative segments collapse — the same project always maps to one entry. */
|
|
38
|
+
export function projectModelKey(cwd) {
|
|
39
|
+
return path.resolve(cwd);
|
|
40
|
+
}
|
|
41
|
+
export async function loadAppSettings() {
|
|
42
|
+
try {
|
|
43
|
+
const raw = JSON.parse(await fs.readFile(appSettingsFile(), "utf-8"));
|
|
44
|
+
return {
|
|
45
|
+
projectsRoot: typeof raw.projectsRoot === "string" && raw.projectsRoot.trim()
|
|
46
|
+
? raw.projectsRoot
|
|
47
|
+
: defaultProjectsRoot(),
|
|
48
|
+
// Preserve the per-project map verbatim (validated + written by the
|
|
49
|
+
// model/thinking handlers below).
|
|
50
|
+
projectModels: raw.projectModels && typeof raw.projectModels === "object" ? raw.projectModels : undefined,
|
|
51
|
+
autopilot: raw.autopilot && typeof raw.autopilot === "object" ? raw.autopilot : undefined,
|
|
52
|
+
nolanModels: raw.nolanModels && typeof raw.nolanModels === "object" ? raw.nolanModels : undefined,
|
|
53
|
+
projectRoots: stringArray(raw.projectRoots),
|
|
54
|
+
hiddenProjects: stringArray(raw.hiddenProjects),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return { projectsRoot: defaultProjectsRoot() };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export async function saveAppSettings(settings) {
|
|
62
|
+
await fs.mkdir(path.dirname(appSettingsFile()), { recursive: true });
|
|
63
|
+
await fs.writeFile(appSettingsFile(), JSON.stringify(settings, null, 2), "utf-8");
|
|
64
|
+
}
|
|
65
|
+
/** Read this project's persisted model/thinking prefs, if any. */
|
|
66
|
+
export async function loadProjectModelPrefs(cwd) {
|
|
67
|
+
const s = await loadAppSettings();
|
|
68
|
+
return s.projectModels?.[projectModelKey(cwd)];
|
|
69
|
+
}
|
|
70
|
+
/** Persist this project's model/thinking prefs via read-modify-write so the rest
|
|
71
|
+
* of the settings file (projectsRoot, other projects' entries) is preserved. */
|
|
72
|
+
export async function saveProjectModelPrefs(cwd, prefs) {
|
|
73
|
+
const s = await loadAppSettings();
|
|
74
|
+
const key = projectModelKey(cwd);
|
|
75
|
+
s.projectModels = { ...(s.projectModels ?? {}), [key]: prefs };
|
|
76
|
+
await saveAppSettings(s);
|
|
77
|
+
}
|
|
78
|
+
/** Read this project's persisted Nolan model override, if any. */
|
|
79
|
+
export async function loadNolanModelPref(cwd) {
|
|
80
|
+
const s = await loadAppSettings();
|
|
81
|
+
return s.nolanModels?.[projectModelKey(cwd)];
|
|
82
|
+
}
|
|
83
|
+
/** Persist (or with null, clear) this project's Nolan model override via
|
|
84
|
+
* read-modify-write so the rest of the settings file is preserved. */
|
|
85
|
+
export async function saveNolanModelPref(cwd, pref) {
|
|
86
|
+
const s = await loadAppSettings();
|
|
87
|
+
const key = projectModelKey(cwd);
|
|
88
|
+
const next = { ...(s.nolanModels ?? {}) };
|
|
89
|
+
if (pref)
|
|
90
|
+
next[key] = pref;
|
|
91
|
+
else
|
|
92
|
+
delete next[key];
|
|
93
|
+
s.nolanModels = next;
|
|
94
|
+
await saveAppSettings(s);
|
|
95
|
+
}
|
|
96
|
+
/** Read this project's persisted autopilot flag (default off). */
|
|
97
|
+
export async function loadAutopilot(cwd) {
|
|
98
|
+
const s = await loadAppSettings();
|
|
99
|
+
return s.autopilot?.[projectModelKey(cwd)] ?? false;
|
|
100
|
+
}
|
|
101
|
+
/** Persist this project's autopilot flag via read-modify-write so the rest of
|
|
102
|
+
* the settings file (projectsRoot, model map, other projects) is preserved. */
|
|
103
|
+
export async function saveAutopilot(cwd, enabled) {
|
|
104
|
+
const s = await loadAppSettings();
|
|
105
|
+
const key = projectModelKey(cwd);
|
|
106
|
+
s.autopilot = { ...(s.autopilot ?? {}), [key]: enabled };
|
|
107
|
+
await saveAppSettings(s);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Persist the active model selection to ~/.ezcoder/settings.json so it survives app
|
|
111
|
+
* restarts. Mirrors the CLI's handleModelSelect persistence (App.tsx).
|
|
112
|
+
*/
|
|
113
|
+
export async function persistModelSelection(settingsFile, provider, model) {
|
|
114
|
+
try {
|
|
115
|
+
const sm = new SettingsManager(settingsFile);
|
|
116
|
+
await sm.load();
|
|
117
|
+
await sm.set("defaultProvider", provider);
|
|
118
|
+
await sm.set("defaultModel", model);
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
log("WARN", "app-sidecar", "failed to persist model selection", { err: String(err) });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Persist the thinking level to ~/.ezcoder/settings.json so it survives app restarts.
|
|
126
|
+
* Mirrors the CLI's handleToggleThinking persistence (App.tsx).
|
|
127
|
+
*/
|
|
128
|
+
export async function persistThinkingLevel(settingsFile, level) {
|
|
129
|
+
try {
|
|
130
|
+
const sm = new SettingsManager(settingsFile);
|
|
131
|
+
await sm.load();
|
|
132
|
+
await sm.set("thinkingEnabled", !!level);
|
|
133
|
+
if (level)
|
|
134
|
+
await sm.set("thinkingLevel", level);
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
log("WARN", "app-sidecar", "failed to persist thinking level", { err: String(err) });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/** Validate a project folder name: lowercase letters, digits, dashes only. */
|
|
141
|
+
export function isValidProjectName(name) {
|
|
142
|
+
return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name);
|
|
143
|
+
}
|
|
144
|
+
// ── History reconstruction types ──────────────────────────
|
|
145
|
+
// Mirrors HistoryEntry in ezcoder-app/src/agent.ts — the wire shape the webview
|
|
146
|
+
// receives from GET /history. Fields beyond role/text carry the transcript
|
|
147
|
+
//# sourceMappingURL=app-settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-settings.js","sourceRoot":"","sources":["../../src/app-sidecar/app-settings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface AppAttachment {
|
|
2
|
+
kind: "image" | "video" | "file";
|
|
3
|
+
name: string;
|
|
4
|
+
mediaType: string;
|
|
5
|
+
/** base64 (no data: prefix). */
|
|
6
|
+
data: string;
|
|
7
|
+
}
|
|
8
|
+
export interface PreparedAttachment extends AppAttachment {
|
|
9
|
+
path?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function prepareAttachments(cwd: string, attachments: AppAttachment[]): Promise<PreparedAttachment[]>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { shrinkToFit, validateVisionImage } from "../utils/image.js";
|
|
4
|
+
export async function prepareAttachments(cwd, attachments) {
|
|
5
|
+
const dir = path.join(cwd, ".ezcoder", "uploads");
|
|
6
|
+
await fs.mkdir(dir, { recursive: true }).catch(() => { });
|
|
7
|
+
const out = [];
|
|
8
|
+
for (const a of attachments) {
|
|
9
|
+
// Sanitize the filename and prefix with a short timestamp to avoid clobber.
|
|
10
|
+
const safe = a.name.replace(/[^\w.-]+/g, "_").slice(-80) || "file";
|
|
11
|
+
const fileName = `${Date.now().toString(36)}-${safe}`;
|
|
12
|
+
const filePath = path.join(dir, fileName);
|
|
13
|
+
const buf = Buffer.from(a.data, "base64");
|
|
14
|
+
// Validate and cap image attachments before they become native image content
|
|
15
|
+
// blocks. Anthropic applies a 2000 px per-dimension cap once conversation
|
|
16
|
+
// history contains more than 20 images, so every attachment must be safe for
|
|
17
|
+
// later turns too. Keep the original on disk, but send the resized bytes.
|
|
18
|
+
// Corrupt or unsupported images become plain files so they cannot reject the
|
|
19
|
+
// entire provider request.
|
|
20
|
+
let prepared = { ...a };
|
|
21
|
+
if (a.kind === "image") {
|
|
22
|
+
try {
|
|
23
|
+
const resized = await shrinkToFit(buf, a.mediaType);
|
|
24
|
+
const validatedType = await validateVisionImage(resized.buffer);
|
|
25
|
+
prepared = validatedType
|
|
26
|
+
? {
|
|
27
|
+
...a,
|
|
28
|
+
mediaType: validatedType,
|
|
29
|
+
data: resized.buffer.toString("base64"),
|
|
30
|
+
}
|
|
31
|
+
: { ...a, kind: "file" };
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
prepared = { ...a, kind: "file" };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
await fs.writeFile(filePath, buf);
|
|
39
|
+
out.push({ ...prepared, path: filePath });
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
out.push({ ...prepared });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=attachments.js.map
|