@miphamai/cli 0.47.0 → 0.49.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/package.json +1 -1
- package/skills/mipham/doc-sync.mipham-skill.md +198 -0
- package/skills/mipham/self-audit.mipham-skill.md +1 -1
- package/skills/standard/web-access/references/cdp-api.md +132 -0
- package/skills/standard/web-access/references/site-patterns/.gitkeep +0 -0
- package/skills/standard/web-access/scripts/cdp-proxy.mjs +756 -0
- package/skills/standard/web-access/scripts/check-deps.mjs +187 -0
- package/skills/standard/web-access/scripts/find-url.mjs +271 -0
- package/skills/standard/web-access/scripts/match-site.mjs +48 -0
- package/skills/standard/web-access.SKILL.md +77 -158
- package/src/agent/agent-context.ts +3 -1
- package/src/agent/sub-agent.ts +31 -28
- package/src/agent/types.ts +0 -1
- package/src/core/engine.ts +1 -1
- package/src/daemon/server.ts +21 -4
- package/src/i18n-core/locales/en-US.json +73 -0
- package/src/i18n-core/locales/zh-CN.json +73 -0
- package/src/shared/package-info.ts +1 -1
- package/src/skills/bundled-skill-assets.ts +19 -0
- package/src/skills/bundled-skills.ts +3 -2
- package/src/skills/skill-assets.ts +37 -0
- package/src/tools/agent/skill.ts +13 -2
- package/src/ui/config-wizard.tsx +77 -47
- package/src/ui/error-boundary.tsx +18 -15
- package/src/ui/goal-progress.tsx +13 -7
- package/src/ui/workflow-progress.tsx +18 -9
|
@@ -1,213 +1,132 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: web-access
|
|
3
|
-
description:
|
|
4
|
-
|
|
3
|
+
description: '联网访问:CDP 驱动用户已登录 Chrome(登录后操作、动态页面、反爬站点、社交媒体、本地书签/历史检索)'
|
|
4
|
+
license: MIT
|
|
5
|
+
github: https://github.com/eze-is/web-access
|
|
6
|
+
version: 2.5.0
|
|
5
7
|
user-invocable: true
|
|
6
8
|
allowed-tools:
|
|
7
9
|
- Bash
|
|
8
10
|
- WebFetch
|
|
9
11
|
- WebSearch
|
|
10
|
-
- ComputerUse
|
|
11
12
|
- Read
|
|
12
13
|
---
|
|
13
14
|
|
|
14
|
-
# Web Access —
|
|
15
|
+
# Web Access — CDP 驱动已登录 Chrome
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
> 来源:eze-is/web-access (MIT),Mipham Code 合并升级。核心能力 = CDP Proxy 直连用户日常 Chrome,天然携带登录态。
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
## 前置检查
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
先确保 CDP 就绪:
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
## Phase 0: Route to the Right Tool (ALWAYS RUN FIRST)
|
|
25
|
-
|
|
26
|
-
```
|
|
27
|
-
User request involves network?
|
|
28
|
-
├── Search engine query (find/discover/look up)?
|
|
29
|
-
│ └── → WebSearch tool
|
|
30
|
-
│ Query best practices: specific + versioned + technical terms
|
|
31
|
-
│
|
|
32
|
-
├── Read a known URL (docs/article/API)?
|
|
33
|
-
│ └── → WebFetch tool
|
|
34
|
-
│ HTTP auto-upgrades to HTTPS, HTML converts to markdown
|
|
35
|
-
│ Cached for 15 minutes — re-fetch only if stale
|
|
36
|
-
│
|
|
37
|
-
├── Login-required site? JavaScript SPA? Form submission?
|
|
38
|
-
│ └── → ComputerUse browser automation
|
|
39
|
-
│ browser_navigate → browser_snapshot → browser_click
|
|
40
|
-
│
|
|
41
|
-
├── Social media (Xiaohongshu, Weibo, Twitter, etc.)?
|
|
42
|
-
│ └── → ComputerUse browser (render JS, handle auth)
|
|
43
|
-
│ OR → WebFetch if public page
|
|
44
|
-
│
|
|
45
|
-
└── API endpoint (REST/GraphQL)?
|
|
46
|
-
└── → WebFetch with prompt for structured extraction
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
## Phase 1: Web Search
|
|
52
|
-
|
|
53
|
-
Use `WebSearch` for discovery queries — finding documentation, news, troubleshooting, comparisons.
|
|
54
|
-
|
|
55
|
-
### Query Construction
|
|
56
|
-
|
|
57
|
-
```
|
|
58
|
-
❌ "React" → too broad
|
|
59
|
-
❌ "React problems" → ambiguous
|
|
60
|
-
✅ "React 19 useEffect double mount fix 2026" → specific + versioned
|
|
61
|
-
✅ "Next.js 14 App Router caching behavior" → targeted
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
### Domain Filtering
|
|
65
|
-
|
|
66
|
-
Use `allowed_domains` for authoritative sources:
|
|
67
|
-
|
|
68
|
-
- `docs.github.com` — GitHub docs
|
|
69
|
-
- `nextjs.org` — Next.js official
|
|
70
|
-
- `developer.mozilla.org` — MDN
|
|
71
|
-
- `nodejs.org` — Node.js official
|
|
72
|
-
|
|
73
|
-
Use `blocked_domains` to exclude noise (e.g., exclude `w3schools.com` when looking for MDN).
|
|
74
|
-
|
|
75
|
-
### Verification
|
|
76
|
-
|
|
77
|
-
- Cross-reference claims across 2+ independent sources
|
|
78
|
-
- Prefer results from current year
|
|
79
|
-
- Authority: official docs > well-known blogs > Stack Overflow > random forums
|
|
80
|
-
|
|
81
|
-
### Source Attribution
|
|
82
|
-
|
|
83
|
-
Always end responses with:
|
|
84
|
-
|
|
85
|
-
```markdown
|
|
86
|
-
Sources:
|
|
87
|
-
|
|
88
|
-
- [Title](URL) — brief note
|
|
23
|
+
```bash
|
|
24
|
+
node ~/.mipham/skills/web-access/scripts/check-deps.mjs
|
|
89
25
|
```
|
|
90
26
|
|
|
91
|
-
|
|
27
|
+
> Mipham Code 环境:`node` 不可用时可用 `bun` 替代(Bun 原生支持 WebSocket 与 node: 内建)。未通过时引导用户:Chrome 地址栏打开 `chrome://inspect/#remote-debugging`,勾选 "Allow remote debugging for this browser instance"。
|
|
92
28
|
|
|
93
|
-
|
|
29
|
+
**必须向用户展示**:部分站点对浏览器自动化检测严格,存在账号封禁风险。已内置防护但无法完全避免,Agent 继续操作即视为接受。
|
|
94
30
|
|
|
95
|
-
|
|
31
|
+
## 工具选择
|
|
96
32
|
|
|
97
|
-
|
|
33
|
+
| 场景 | 工具 |
|
|
34
|
+
| --------------------------------------------- | ----------- |
|
|
35
|
+
| 搜索摘要 / 发现来源 | WebSearch |
|
|
36
|
+
| URL 已知,定向提取 | WebFetch |
|
|
37
|
+
| URL 已知,要原始 HTML(meta/JSON-LD) | Bash + curl |
|
|
38
|
+
| 非公开内容 / 反爬站点(小红书、微信公众号等) | 浏览器 CDP |
|
|
39
|
+
| 需要登录态、交互、自由导航 | 浏览器 CDP |
|
|
98
40
|
|
|
99
|
-
|
|
100
|
-
- Converts HTML to Markdown (headings, links, images, lists, code blocks)
|
|
101
|
-
- Strips scripts, styles, nav, header, footer before conversion
|
|
102
|
-
- Caches results for 15 minutes per URL
|
|
103
|
-
- Detects cross-host redirects and reports them
|
|
104
|
-
- Truncates content at 100K characters
|
|
41
|
+
浏览器 CDP 不要求 URL 已知;WebSearch/WebFetch/curl 均不处理登录态。
|
|
105
42
|
|
|
106
|
-
|
|
43
|
+
## 浏览器 CDP 模式
|
|
107
44
|
|
|
108
|
-
|
|
45
|
+
通过 CDP Proxy 直连用户日常 Chrome,天然携带登录态。**不主动操作用户已有 tab**,所有操作在自己创建的后台 tab 中进行,任务结束关闭自建 tab(保留用户原 tab)。
|
|
109
46
|
|
|
110
|
-
|
|
111
|
-
WebFetch: url="https://docs.example.com", prompt="find the authentication API section"
|
|
112
|
-
```
|
|
47
|
+
Proxy(`scripts/cdp-proxy.mjs`)由 `check-deps.mjs` 自动拉起并常驻。Proxy API(curl 调 `http://localhost:3456/...`):
|
|
113
48
|
|
|
114
|
-
|
|
49
|
+
| 端点 | 用途 |
|
|
50
|
+
| ------------------------------------------ | ------------------------------------------------------------------------ |
|
|
51
|
+
| `GET /targets` | 列出已开 tab |
|
|
52
|
+
| `GET /new?url=` | 新建后台 tab(自动等加载) |
|
|
53
|
+
| `GET /navigate?target=&url=` | 导航(自动等加载) |
|
|
54
|
+
| `GET /back?target=` | 后退 |
|
|
55
|
+
| `GET /info?target=` | 页面标题/URL/状态 |
|
|
56
|
+
| `POST /eval?target=`(body=JS) | 执行任意 JS(读写 DOM、提取、提交) |
|
|
57
|
+
| `POST /click?target=`(body=CSS 选择器) | JS 点击(`el.click()`,覆盖大多数场景) |
|
|
58
|
+
| `POST /clickAt?target=`(body=CSS 选择器) | 真实鼠标点击(`Input.dispatchMouseEvent`,算用户手势,能触发文件对话框) |
|
|
59
|
+
| `POST /setFiles?target=`(body JSON) | 设置 file input 本地文件路径(`DOM.setFileInputFiles`,绕过文件对话框) |
|
|
60
|
+
| `GET /scroll?target=&y=&direction=` | 滚动(`direction=down/up/top/bottom`,触发懒加载) |
|
|
61
|
+
| `GET /screenshot?target=&file=` | 截图 |
|
|
62
|
+
| `GET /close?target=` | 关闭 tab |
|
|
115
63
|
|
|
116
|
-
|
|
117
|
-
- Login-required pages → use ComputerUse browser
|
|
118
|
-
- Large file downloads → use Bash + curl/wget
|
|
119
|
-
- API endpoints returning JSON → WebFetch works, returns raw JSON
|
|
64
|
+
进入浏览器层后,`/eval` 是眼睛、`/click` 是手:先看 DOM 结构再决定下一步,不预先规划所有步骤。
|
|
120
65
|
|
|
121
|
-
|
|
66
|
+
### 登录判断
|
|
122
67
|
|
|
123
|
-
|
|
68
|
+
核心问题只有一个:**目标内容拿到了吗?** 打开页面先尝试获取目标内容;确认「目标内容无法获取」且判断登录能解决时,告知用户在其 Chrome 登录后继续(无需重启任何东西,刷新页面即可)。
|
|
124
69
|
|
|
125
|
-
|
|
70
|
+
### 媒体资源提取
|
|
126
71
|
|
|
127
|
-
|
|
72
|
+
判断内容在图片里时,用 `/eval` 从 DOM 直接拿图片 URL 定向读取,比全页截图精准。`/scroll` 到底部触发懒加载后再提取图片 URL。
|
|
128
73
|
|
|
129
|
-
|
|
130
|
-
| ------------------ | ------------------------------------------- |
|
|
131
|
-
| `browser_navigate` | Go to a URL |
|
|
132
|
-
| `browser_snapshot` | Capture accessibility tree (page structure) |
|
|
133
|
-
| `browser_click` | Click an element by UID |
|
|
134
|
-
| `screenshot` | Capture visible viewport |
|
|
135
|
-
| `launch` | Open a desktop application |
|
|
74
|
+
### 视频内容获取
|
|
136
75
|
|
|
137
|
-
|
|
76
|
+
用户 Chrome 真实渲染,截图可捕获当前视频帧。用 `/eval` 操控 `<video>`(时长、seek、播放/暂停),配合 `/screenshot` 采帧,做离散采样分析。
|
|
138
77
|
|
|
139
|
-
|
|
140
|
-
1. browser_navigate → login page
|
|
141
|
-
2. browser_snapshot → find form fields (UIDs)
|
|
142
|
-
3. Ask user for credentials (NEVER auto-fill)
|
|
143
|
-
4. browser_click → submit
|
|
144
|
-
5. browser_navigate → target page
|
|
145
|
-
6. browser_snapshot → extract content
|
|
146
|
-
```
|
|
78
|
+
## 本地 Chrome 资源
|
|
147
79
|
|
|
148
|
-
|
|
80
|
+
用户指向「本人访问过的页面」或「组织内部系统」时,检索本地书签/历史:
|
|
149
81
|
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
2. Wait 2-3 seconds (JavaScript render)
|
|
153
|
-
3. browser_snapshot → extract rendered content
|
|
82
|
+
```bash
|
|
83
|
+
node ~/.mipham/skills/web-access/scripts/find-url.mjs [关键词...] [--only bookmarks|history] [--limit N] [--since 1d|7h|YYYY-MM-DD] [--sort recent|visits]
|
|
154
84
|
```
|
|
155
85
|
|
|
156
|
-
|
|
86
|
+
## 并行调研:子 Agent 分治
|
|
157
87
|
|
|
158
|
-
|
|
159
|
-
- First launch opens a visible browser window (headless: false)
|
|
88
|
+
多个独立调研目标时,分治给子 Agent 并行执行(共享一个 Chrome、一个 Proxy,各自建 tab、各自 `/close`,无竞态)。子 Agent prompt 写**目标**(「获取/调研/了解」),不写**手段**(避免「搜索xx」锚定到 WebSearch 而错过需 CDP 的反爬站点)。
|
|
160
89
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
## Phase 4: Extraction & Synthesis
|
|
90
|
+
## 信息核实
|
|
164
91
|
|
|
165
|
-
|
|
92
|
+
核实目标是一手来源,非二手报道。搜索引擎是**定位**工具,不可直接**证明**真伪;找到来源后直接访问读原文。
|
|
166
93
|
|
|
167
|
-
|
|
94
|
+
| 信息类型 | 一手来源 |
|
|
95
|
+
| ------------- | -------------- |
|
|
96
|
+
| 政策/法规 | 发布机构官网 |
|
|
97
|
+
| 企业公告 | 公司官方新闻页 |
|
|
98
|
+
| 工具能力/用法 | 官方文档、源码 |
|
|
168
99
|
|
|
169
|
-
|
|
170
|
-
2. Extract key facts, code examples, API signatures
|
|
171
|
-
3. Note the source URL for attribution
|
|
100
|
+
### 交叉验证
|
|
172
101
|
|
|
173
|
-
|
|
102
|
+
- 关键声明须 2+ 独立来源交叉印证。
|
|
103
|
+
- 优先采纳当年/近期资料。
|
|
104
|
+
- 权威层级:官方文档 > 知名博客 > 技术社区 > 随机论坛。
|
|
174
105
|
|
|
175
|
-
|
|
176
|
-
2. Flag contradictions between sources
|
|
177
|
-
3. Note version/deprecation warnings
|
|
106
|
+
### 来源归因
|
|
178
107
|
|
|
179
|
-
|
|
108
|
+
回答结尾附来源列表:
|
|
180
109
|
|
|
181
110
|
```markdown
|
|
182
|
-
## [Topic]
|
|
183
|
-
|
|
184
|
-
[Key finding with source attribution]
|
|
185
|
-
|
|
186
|
-
### Details
|
|
187
|
-
|
|
188
|
-
[Structured content from page]
|
|
189
|
-
|
|
190
111
|
Sources:
|
|
191
112
|
|
|
192
|
-
- [
|
|
113
|
+
- [标题](URL) — 一句话说明
|
|
193
114
|
```
|
|
194
115
|
|
|
195
|
-
|
|
116
|
+
## 站点经验
|
|
196
117
|
|
|
197
|
-
|
|
118
|
+
特定网站经验按域名存 `~/.mipham/skills/web-access/references/site-patterns/<domain>.md`(frontmatter: domain/aliases/updated + 平台特征/有效模式/已知陷阱)。操作前若有匹配经验先读;操作成功后把验证过的新模式写回。
|
|
198
119
|
|
|
199
|
-
|
|
200
|
-
- Respect `robots.txt` and rate limiting
|
|
201
|
-
- Do not scrape PII or sensitive data
|
|
202
|
-
- All URLs validated against SSRF before fetching
|
|
203
|
-
- Only HTTPS for remote requests (HTTP auto-upgraded)
|
|
204
|
-
- Cross-host redirects reported to caller (not silently followed)
|
|
120
|
+
## Security Rules
|
|
205
121
|
|
|
206
|
-
|
|
122
|
+
- 不主动操作用户已有 tab;任务结束关闭自建 tab。
|
|
123
|
+
- 不提交凭据(除非用户显式批准)。
|
|
124
|
+
- 尊重 robots.txt 与速率限制;不抓 PII。
|
|
125
|
+
- proxy 仅绑 127.0.0.1,不暴露外网;端口 3456 无鉴权,依赖本机信任边界,勿在共享/多用户主机运行。
|
|
126
|
+
- ⚠️ proxy 不做 URL SSRF 校验(照搬上游,与 computer-use/Playwright 同类):避免驱动 Chrome 访问本机内部服务/内网地址。
|
|
207
127
|
|
|
208
|
-
##
|
|
128
|
+
## 何时不用本 skill
|
|
209
129
|
|
|
210
|
-
-
|
|
211
|
-
-
|
|
212
|
-
-
|
|
213
|
-
- Downloading large binaries → use Bash + curl
|
|
130
|
+
- 纯逻辑/算法题(推理非研究)。
|
|
131
|
+
- 代码已在上下文里的问题。
|
|
132
|
+
- 大文件下载 → Bash + curl。
|
|
@@ -102,10 +102,12 @@ export function createAgentContext(
|
|
|
102
102
|
contextWindow?: number,
|
|
103
103
|
crsiConfig?: Partial<CrsiConfig>,
|
|
104
104
|
): AgentContextResult {
|
|
105
|
-
// Create isolated context
|
|
105
|
+
// Create isolated context, sized to the resolved model's window when known.
|
|
106
|
+
// Passing contextWindow (not just maxTokens) enables adaptive thresholds.
|
|
106
107
|
const context = new ContextManager({
|
|
107
108
|
maxTokens: contextWindow || 100_000,
|
|
108
109
|
compactionThreshold: 0.85,
|
|
110
|
+
contextWindow,
|
|
109
111
|
})
|
|
110
112
|
|
|
111
113
|
// Build system prompt with optional agent memory
|
package/src/agent/sub-agent.ts
CHANGED
|
@@ -254,7 +254,35 @@ export class SubAgent {
|
|
|
254
254
|
const systemPrompt =
|
|
255
255
|
agentDef?.systemPrompt || options.systemPrompt || TYPE_SYSTEM_PROMPTS[agentType]
|
|
256
256
|
|
|
257
|
-
//
|
|
257
|
+
// Resolve the sub-agent's model first, so its context window is known
|
|
258
|
+
// before the isolated context is created (model-aware sizing).
|
|
259
|
+
const modelToUse = options.modelOverride || agentDef?.model || model
|
|
260
|
+
// 'inherit' means use parent model
|
|
261
|
+
const resolvedModel = modelToUse === 'inherit' ? model : modelToUse
|
|
262
|
+
|
|
263
|
+
// Validate resolved model exists in registry; fall back to parent model with warning
|
|
264
|
+
let finalModel = resolvedModel
|
|
265
|
+
if (resolvedModel !== model) {
|
|
266
|
+
const modelExists = this.registry.findModel(resolvedModel) !== undefined
|
|
267
|
+
if (!modelExists) {
|
|
268
|
+
const warnMsg = `Warning: model "${resolvedModel}" not found in provider registry. Falling back to "${model}".`
|
|
269
|
+
console.warn(warnMsg)
|
|
270
|
+
|
|
271
|
+
// Post warning to message bus for UI display
|
|
272
|
+
const bus = getMessageBus()
|
|
273
|
+
bus.post(
|
|
274
|
+
'system',
|
|
275
|
+
'main',
|
|
276
|
+
`Sub-agent model fallback: ${resolvedModel} → ${model}`,
|
|
277
|
+
warnMsg,
|
|
278
|
+
'warning',
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
finalModel = model
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Create isolated context with tool scoping, sized to the resolved model.
|
|
258
286
|
const resolvedDef: AgentDefinition = agentDef || {
|
|
259
287
|
name: agentType,
|
|
260
288
|
description: '',
|
|
@@ -264,10 +292,11 @@ export class SubAgent {
|
|
|
264
292
|
background: false,
|
|
265
293
|
source: 'builtin',
|
|
266
294
|
}
|
|
295
|
+
const contextWindow = this.registry.findModel(finalModel)?.contextWindow
|
|
267
296
|
const { context, allowedTools } = createAgentContext(
|
|
268
297
|
resolvedDef,
|
|
269
298
|
this.toolRegistry,
|
|
270
|
-
|
|
299
|
+
contextWindow,
|
|
271
300
|
)
|
|
272
301
|
|
|
273
302
|
context.setSystemPrompt(systemPrompt)
|
|
@@ -291,32 +320,6 @@ export class SubAgent {
|
|
|
291
320
|
}))
|
|
292
321
|
: undefined
|
|
293
322
|
|
|
294
|
-
const modelToUse = options.modelOverride || agentDef?.model || model
|
|
295
|
-
// 'inherit' means use parent model
|
|
296
|
-
const resolvedModel = modelToUse === 'inherit' ? model : modelToUse
|
|
297
|
-
|
|
298
|
-
// Validate resolved model exists in registry; fall back to parent model with warning
|
|
299
|
-
let finalModel = resolvedModel
|
|
300
|
-
if (resolvedModel !== model) {
|
|
301
|
-
const modelExists = this.registry.findModel(resolvedModel) !== undefined
|
|
302
|
-
if (!modelExists) {
|
|
303
|
-
const warnMsg = `Warning: model "${resolvedModel}" not found in provider registry. Falling back to "${model}".`
|
|
304
|
-
console.warn(warnMsg)
|
|
305
|
-
|
|
306
|
-
// Post warning to message bus for UI display
|
|
307
|
-
const bus = getMessageBus()
|
|
308
|
-
bus.post(
|
|
309
|
-
'system',
|
|
310
|
-
'main',
|
|
311
|
-
`Sub-agent model fallback: ${resolvedModel} → ${model}`,
|
|
312
|
-
warnMsg,
|
|
313
|
-
'warning',
|
|
314
|
-
)
|
|
315
|
-
|
|
316
|
-
finalModel = model
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
323
|
const chunks: string[] = []
|
|
321
324
|
const MAX_TOOL_TURNS = options.maxTurns || 5
|
|
322
325
|
|
package/src/agent/types.ts
CHANGED
|
@@ -39,7 +39,6 @@ export interface SubAgentOptions {
|
|
|
39
39
|
type?: SubAgentType
|
|
40
40
|
agentDef?: AgentDefinition
|
|
41
41
|
systemPrompt?: string
|
|
42
|
-
maxContextMessages?: number
|
|
43
42
|
allowedTools?: string[]
|
|
44
43
|
modelOverride?: string
|
|
45
44
|
/** Maximum tool-calling turns (default: 5) to prevent infinite loops. */
|
package/src/core/engine.ts
CHANGED
|
@@ -1431,7 +1431,7 @@ export class QueryEngine {
|
|
|
1431
1431
|
const DISABLE_1M = process.env.MIPHAM_DISABLE_1M_CONTEXT === '1'
|
|
1432
1432
|
const maxTokens =
|
|
1433
1433
|
DISABLE_1M && model.contextWindow > 200_000 ? 200_000 : model.contextWindow
|
|
1434
|
-
this.context.updateMaxTokens(maxTokens)
|
|
1434
|
+
this.context.updateMaxTokens(maxTokens, model.contextWindow)
|
|
1435
1435
|
}
|
|
1436
1436
|
}
|
|
1437
1437
|
}
|
package/src/daemon/server.ts
CHANGED
|
@@ -67,6 +67,22 @@ function resolveDaemonPermission(): PermissionMode {
|
|
|
67
67
|
: 'default'
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
const DAEMON_DEFAULT_CONTEXT_WINDOW = 200_000
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Resolve the effective context window (in tokens) for the daemon session's
|
|
74
|
+
* model. Mirrors the CLI's model-aware context sizing so a 1M-context model
|
|
75
|
+
* isn't silently hard-capped at 200K; falls back when the model isn't in the
|
|
76
|
+
* registry.
|
|
77
|
+
*/
|
|
78
|
+
export function resolveContextWindow(
|
|
79
|
+
registry: ProviderRegistry,
|
|
80
|
+
modelId: string,
|
|
81
|
+
fallback = DAEMON_DEFAULT_CONTEXT_WINDOW,
|
|
82
|
+
): number {
|
|
83
|
+
return registry.findModel(modelId)?.contextWindow ?? fallback
|
|
84
|
+
}
|
|
85
|
+
|
|
70
86
|
export function createServer(config: ServerConfig): Server<WsData> {
|
|
71
87
|
const {
|
|
72
88
|
db,
|
|
@@ -120,7 +136,6 @@ export function createServer(config: ServerConfig): Server<WsData> {
|
|
|
120
136
|
const engineCache = new Map<string, QueryEngine>()
|
|
121
137
|
let sharedRegistry: ProviderRegistry | null = null
|
|
122
138
|
let sharedTools: Map<string, ToolDefinition> | null = null
|
|
123
|
-
const DEFAULT_MAX_TOKENS = 200_000
|
|
124
139
|
|
|
125
140
|
function getOrCreateEngine(
|
|
126
141
|
sessionId: string,
|
|
@@ -148,11 +163,13 @@ export function createServer(config: ServerConfig): Server<WsData> {
|
|
|
148
163
|
sharedTools = createToolRegistry()
|
|
149
164
|
}
|
|
150
165
|
|
|
151
|
-
// Create per-session context, restoring previous messages from DB
|
|
166
|
+
// Create per-session context, restoring previous messages from DB.
|
|
167
|
+
// Size it to the active model's context window (1M-capable models get 1M).
|
|
168
|
+
const contextWindow = resolveContextWindow(sharedRegistry!, model)
|
|
152
169
|
const context = new ContextManager({
|
|
153
|
-
maxTokens:
|
|
170
|
+
maxTokens: contextWindow,
|
|
154
171
|
compactionThreshold: 0.9,
|
|
155
|
-
contextWindow
|
|
172
|
+
contextWindow,
|
|
156
173
|
})
|
|
157
174
|
|
|
158
175
|
const dbMessages = db.getMessages(sessionId, 10000)
|
|
@@ -718,6 +718,79 @@
|
|
|
718
718
|
"shift_tab_cycle": "shift+tab",
|
|
719
719
|
"left_for_agents": "ctrl+g agents to manage",
|
|
720
720
|
"mipham_modes": "Mipham"
|
|
721
|
+
},
|
|
722
|
+
"wizard": {
|
|
723
|
+
"header_subtitle": " — Configuration Wizard",
|
|
724
|
+
"welcome_title": "Welcome to Mipham Code!",
|
|
725
|
+
"welcome_intro": "Before you start, you need to configure your AI model connection.",
|
|
726
|
+
"welcome_time": "This wizard takes about 1 minute — please have your API key ready.",
|
|
727
|
+
"welcome_start": "Press Enter to start →",
|
|
728
|
+
"welcome_skip": "Esc to skip",
|
|
729
|
+
"mode_title": "Choose connection method:",
|
|
730
|
+
"mode_cloud": "🌐 Cloud AI models (recommended)",
|
|
731
|
+
"mode_local": "🖥️ Local models (Ollama)",
|
|
732
|
+
"mode_local_hint": " Requires Ollama installed with models downloaded",
|
|
733
|
+
"nav_hint": "↑↓ select · Enter confirm · Esc back",
|
|
734
|
+
"provider_title": "Choose AI model provider:",
|
|
735
|
+
"provider_count": " ({count} models)",
|
|
736
|
+
"model_title": "Choose model ({provider}):",
|
|
737
|
+
"apikey_title": "Paste your API key:",
|
|
738
|
+
"apikey_provider": "Provider: {provider}",
|
|
739
|
+
"apikey_model": "Model: {model}",
|
|
740
|
+
"apikey_placeholder": "Paste API key then press Enter...",
|
|
741
|
+
"apikey_continue": "Enter to continue · Esc to go back to model",
|
|
742
|
+
"ollama_title": "Ollama local model configuration:",
|
|
743
|
+
"ollama_status": "Status: ",
|
|
744
|
+
"ollama_installed": "✅ installed",
|
|
745
|
+
"ollama_not_installed": "❌ not installed",
|
|
746
|
+
"ollama_running": " · running",
|
|
747
|
+
"ollama_not_running": " · not running (run ollama serve)",
|
|
748
|
+
"ollama_detecting": "Detecting Ollama...",
|
|
749
|
+
"ollama_downloaded": "Downloaded models (↑↓ select · Enter confirm):",
|
|
750
|
+
"ollama_source_hot": "Popular",
|
|
751
|
+
"ollama_no_models": "No downloaded models found. Run ollama pull <model> to download one.",
|
|
752
|
+
"ollama_preset_hint": "Below are preset models — switch anytime via /models.",
|
|
753
|
+
"confirm_title": "Confirm configuration:",
|
|
754
|
+
"confirm_connection": "Connection: ",
|
|
755
|
+
"confirm_cloud": "🌐 Cloud",
|
|
756
|
+
"confirm_local": "🖥️ Local",
|
|
757
|
+
"confirm_provider": "Provider: {provider}",
|
|
758
|
+
"confirm_model": "Model: {model}",
|
|
759
|
+
"confirm_apikey": "API key: {masked}",
|
|
760
|
+
"confirm_ollama_model": "Ollama model: {model}",
|
|
761
|
+
"confirm_save_path": "Config will be saved to ~/.mipham/config.yml",
|
|
762
|
+
"confirm_save": "Press Enter to save and launch →",
|
|
763
|
+
"confirm_back": "Esc to go back",
|
|
764
|
+
"done_title": "✅ Configuration complete!",
|
|
765
|
+
"done_launching": "Mipham Code is starting...",
|
|
766
|
+
"error_apikey_required": "Please enter your API key",
|
|
767
|
+
"error_write_failed": "Failed to write config: {err}"
|
|
768
|
+
},
|
|
769
|
+
"goal_progress": {
|
|
770
|
+
"title": "🎯 Goal: {goal}",
|
|
771
|
+
"no_subtasks": " (no subtasks yet)",
|
|
772
|
+
"summary": "═══ {done}/{total} done",
|
|
773
|
+
"in_progress": " · {n} in progress",
|
|
774
|
+
"failed": " · {n} failed",
|
|
775
|
+
"tokens": " · {n} tokens",
|
|
776
|
+
"border_end": " ═══"
|
|
777
|
+
},
|
|
778
|
+
"workflow": {
|
|
779
|
+
"title": "═══ Workflow: {runId} ═══",
|
|
780
|
+
"phase": "Phase: {name}",
|
|
781
|
+
"done_count": " [{done}/{total} done]",
|
|
782
|
+
"footer": "═══ Elapsed: {time} | Agents: {done}/{total}",
|
|
783
|
+
"running": " ({n} running)",
|
|
784
|
+
"failed": " ({n} failed)",
|
|
785
|
+
"cache_hits": " | Cache hits: {n}",
|
|
786
|
+
"done_marker": " | DONE ═══",
|
|
787
|
+
"running_marker": " | Status: running ═══"
|
|
788
|
+
},
|
|
789
|
+
"error_boundary": {
|
|
790
|
+
"title": "⚠️ UI Render Error",
|
|
791
|
+
"unknown": "Unknown rendering error",
|
|
792
|
+
"recovery": "The terminal interface encountered a rendering issue. Auto-recovery in 5 seconds... Press Enter to attempt immediate recovery.",
|
|
793
|
+
"preserved": "Your session data and conversation history are preserved."
|
|
721
794
|
}
|
|
722
795
|
},
|
|
723
796
|
"tools": {
|
|
@@ -718,6 +718,79 @@
|
|
|
718
718
|
"shift_tab_cycle": "Shift+Tab",
|
|
719
719
|
"left_for_agents": "ctrl+g 管理代理",
|
|
720
720
|
"mipham_modes": "Mipham独有"
|
|
721
|
+
},
|
|
722
|
+
"wizard": {
|
|
723
|
+
"header_subtitle": " — 配置向导",
|
|
724
|
+
"welcome_title": "欢迎使用 Mipham Code!",
|
|
725
|
+
"welcome_intro": "在开始之前,需要先配置 AI 模型连接。",
|
|
726
|
+
"welcome_time": "此向导只需 1 分钟,需要您准备好 API Key。",
|
|
727
|
+
"welcome_start": "按 Enter 开始 →",
|
|
728
|
+
"welcome_skip": "Esc 跳过配置",
|
|
729
|
+
"mode_title": "选择模型连接方式:",
|
|
730
|
+
"mode_cloud": "🌐 云端 AI 模型(推荐)",
|
|
731
|
+
"mode_local": "🖥️ 本地模型(Ollama)",
|
|
732
|
+
"mode_local_hint": " 需要提前安装 Ollama 并下载模型",
|
|
733
|
+
"nav_hint": "↑↓ 选择 · Enter 确认 · Esc 返回",
|
|
734
|
+
"provider_title": "选择 AI 模型提供商:",
|
|
735
|
+
"provider_count": " ({count} 个模型)",
|
|
736
|
+
"model_title": "选择模型({provider}):",
|
|
737
|
+
"apikey_title": "粘贴 API Key:",
|
|
738
|
+
"apikey_provider": "提供商:{provider}",
|
|
739
|
+
"apikey_model": "模型:{model}",
|
|
740
|
+
"apikey_placeholder": "粘贴 API Key 后按 Enter...",
|
|
741
|
+
"apikey_continue": "Enter 继续 · Esc 返回选模型",
|
|
742
|
+
"ollama_title": "Ollama 本地模型配置:",
|
|
743
|
+
"ollama_status": "状态:",
|
|
744
|
+
"ollama_installed": "✅ 已安装",
|
|
745
|
+
"ollama_not_installed": "❌ 未安装",
|
|
746
|
+
"ollama_running": " · 运行中",
|
|
747
|
+
"ollama_not_running": " · 未运行(请执行 ollama serve)",
|
|
748
|
+
"ollama_detecting": "正在检测 Ollama...",
|
|
749
|
+
"ollama_downloaded": "已下载模型(↑↓ 选择 · Enter 确认):",
|
|
750
|
+
"ollama_source_hot": "热门",
|
|
751
|
+
"ollama_no_models": "未检测到已下载模型。请先运行 ollama pull <model> 下载模型。",
|
|
752
|
+
"ollama_preset_hint": "以下为预置模型列表,选择后可在对话中通过 /models 切换。",
|
|
753
|
+
"confirm_title": "配置确认:",
|
|
754
|
+
"confirm_connection": "连接方式:",
|
|
755
|
+
"confirm_cloud": "🌐 云端",
|
|
756
|
+
"confirm_local": "🖥️ 本地",
|
|
757
|
+
"confirm_provider": "提供商:{provider}",
|
|
758
|
+
"confirm_model": "模型:{model}",
|
|
759
|
+
"confirm_apikey": "API Key:{masked}",
|
|
760
|
+
"confirm_ollama_model": "Ollama 模型:{model}",
|
|
761
|
+
"confirm_save_path": "配置文件将保存到 ~/.mipham/config.yml",
|
|
762
|
+
"confirm_save": "按 Enter 保存并启动 →",
|
|
763
|
+
"confirm_back": "Esc 返回修改",
|
|
764
|
+
"done_title": "✅ 配置完成!",
|
|
765
|
+
"done_launching": "Mipham Code 正在启动...",
|
|
766
|
+
"error_apikey_required": "请填写 API Key",
|
|
767
|
+
"error_write_failed": "写入配置失败: {err}"
|
|
768
|
+
},
|
|
769
|
+
"goal_progress": {
|
|
770
|
+
"title": "🎯 目标:{goal}",
|
|
771
|
+
"no_subtasks": " (暂无子任务)",
|
|
772
|
+
"summary": "═══ {done}/{total} 完成",
|
|
773
|
+
"in_progress": " · {n} 进行中",
|
|
774
|
+
"failed": " · {n} 失败",
|
|
775
|
+
"tokens": " · {n} tokens",
|
|
776
|
+
"border_end": " ═══"
|
|
777
|
+
},
|
|
778
|
+
"workflow": {
|
|
779
|
+
"title": "═══ 工作流:{runId} ═══",
|
|
780
|
+
"phase": "阶段:{name}",
|
|
781
|
+
"done_count": " [{done}/{total} 完成]",
|
|
782
|
+
"footer": "═══ 耗时:{time} | Agent:{done}/{total}",
|
|
783
|
+
"running": " ({n} 运行中)",
|
|
784
|
+
"failed": " ({n} 失败)",
|
|
785
|
+
"cache_hits": " | 缓存命中:{n}",
|
|
786
|
+
"done_marker": " | 完成 ═══",
|
|
787
|
+
"running_marker": " | 状态:运行中 ═══"
|
|
788
|
+
},
|
|
789
|
+
"error_boundary": {
|
|
790
|
+
"title": "⚠️ UI 渲染错误",
|
|
791
|
+
"unknown": "未知渲染错误",
|
|
792
|
+
"recovery": "终端界面遇到渲染问题,5 秒后自动恢复... 按 Enter 尝试立即恢复。",
|
|
793
|
+
"preserved": "你的会话数据和对话历史已保留。"
|
|
721
794
|
}
|
|
722
795
|
},
|
|
723
796
|
"tools": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
export const PACKAGE_NAME = '@miphamai/cli' as const
|
|
10
10
|
|
|
11
11
|
/** 当前发布版本 */
|
|
12
|
-
export const PACKAGE_VERSION = '0.
|
|
12
|
+
export const PACKAGE_VERSION = '0.49.0' as const
|
|
13
13
|
|
|
14
14
|
/** npm install 全局安装命令 */
|
|
15
15
|
export const NPM_INSTALL_COMMAND = `npm install -g ${PACKAGE_NAME}` as const
|