@armadra/agent 0.7.5 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/CHANGELOG.zh-CN.md +34 -0
- package/dist/agent/session-classifier.d.ts +2 -0
- package/dist/agent/session-classifier.js +24 -3
- package/dist/agent/session-extensions.d.ts +1 -0
- package/dist/agent/session-extensions.js +3 -0
- package/dist/agent/session-subagent.js +9 -2
- package/dist/agent/subagent-background.d.ts +5 -1
- package/dist/agent/subagent-background.js +13 -1
- package/dist/agent/subagent-fork.d.ts +10 -5
- package/dist/agent/subagent-fork.js +22 -6
- package/dist/agent/subagent-registry.d.ts +1 -1
- package/dist/agent/subagent-registry.js +1 -1
- package/dist/agents/catalog.d.ts +1 -0
- package/dist/ai/apis/chatgpt-backend.d.ts +3 -1
- package/dist/ai/apis/chatgpt-backend.js +10 -1
- package/dist/ai/apis/max-tokens.d.ts +4 -0
- package/dist/ai/apis/max-tokens.js +12 -1
- package/dist/ai/providers/enrich.d.ts +6 -2
- package/dist/ai/providers/enrich.js +13 -2
- package/dist/ai/providers/max-tokens-cache.d.ts +22 -0
- package/dist/ai/providers/max-tokens-cache.js +95 -0
- package/dist/ai/providers/registry.js +3 -3
- package/dist/bundle/ama.cjs +1250 -375
- package/dist/checkpoints/shadow-git.d.ts +5 -1
- package/dist/checkpoints/shadow-git.js +11 -2
- package/dist/cli/compose-providers.d.ts +1 -0
- package/dist/cli/compose-providers.js +3 -0
- package/dist/cli/compose-store.d.ts +6 -2
- package/dist/cli/compose-store.js +8 -4
- package/dist/cli/compose.js +2 -2
- package/dist/config/json-schema.js +1 -0
- package/dist/config/key-docs.js +1 -0
- package/dist/config/schema-w5.js +2 -0
- package/dist/config/settings-registry.js +1 -0
- package/dist/config/types-w5.d.ts +5 -0
- package/dist/drivers/acp/driver.d.ts +22 -1
- package/dist/drivers/acp/driver.js +59 -5
- package/dist/drivers/agents.js +3 -0
- package/dist/drivers/catalog.d.ts +2 -0
- package/dist/drivers/catalog.js +94 -4
- package/dist/drivers/native/claude-normalize.d.ts +8 -0
- package/dist/drivers/native/claude-normalize.js +27 -0
- package/dist/drivers/native/claude-stream.js +16 -1
- package/dist/drivers/native/codex-app-server.js +4 -2
- package/dist/drivers/native/oneshot.js +12 -2
- package/dist/drivers/native/pi-gate.d.ts +19 -0
- package/dist/drivers/native/pi-gate.js +39 -0
- package/dist/drivers/native/pi-rpc.d.ts +29 -0
- package/dist/drivers/native/pi-rpc.js +483 -0
- package/dist/drivers/runner.js +1 -0
- package/dist/drivers/types.d.ts +1 -1
- package/dist/i18n/catalog.d.ts +5 -0
- package/dist/i18n/messages/auth.d.ts +2 -0
- package/dist/i18n/messages/auth.js +2 -0
- package/dist/i18n/messages/config-keys.d.ts +2 -0
- package/dist/i18n/messages/config-keys.js +2 -0
- package/dist/i18n/messages/config.d.ts +2 -0
- package/dist/i18n/messages/drivers.d.ts +4 -0
- package/dist/i18n/messages/drivers.js +4 -0
- package/dist/i18n/messages/interactive.d.ts +2 -0
- package/dist/i18n/messages/interactive.js +2 -0
- package/dist/i18n/messages/session.js +2 -2
- package/dist/modes/interactive/agent-ui.js +7 -0
- package/dist/session/manager.d.ts +3 -1
- package/dist/session/manager.js +5 -0
- package/dist/session/offload.d.ts +10 -2
- package/dist/session/offload.js +27 -4
- package/dist/tools/background-jobs.d.ts +4 -4
- package/dist/tools/background-jobs.js +4 -4
- package/dist/tools/bash.d.ts +2 -1
- package/dist/tools/bash.js +4 -3
- package/dist/tools/task-ctl.js +2 -1
- package/dist/tools/task.d.ts +9 -0
- package/dist/tools/task.js +27 -1
- package/docs/agents.md +70 -14
- package/docs/en/permissions.md +1 -1
- package/docs/en/providers.md +11 -10
- package/docs/en/sessions.md +2 -1
- package/docs/permissions.md +1 -1
- package/docs/providers.md +16 -11
- package/docs/session-format.md +2 -1
- package/docs/sessions.md +2 -1
- package/package.json +1 -1
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `max_tokens` 上限的跨进程缓存:`<dataDir>/models/max-tokens-caps.json`(#152)。
|
|
3
|
+
*
|
|
4
|
+
* 被动修正(apis/max-tokens.ts)学到的 `provider/model` 上限原本只在进程内,重启后每个模型的首个请求仍被
|
|
5
|
+
* 400 拒一次。这里把它写进数据目录:组装注册表时载回进程内的表(进程内已有的键优先),学到新上限就把文件里
|
|
6
|
+
* 未过期的条目加上这一条原子写回(临时文件 + 改名;并发进程后写者赢,丢的一条下次再学)。条目 30 天过期,
|
|
7
|
+
* 过期后重新探测(中转放宽上限时不会一直压低输出);删掉文件即重测。只存模型引用、上限与时间,没有凭据。
|
|
8
|
+
*/
|
|
9
|
+
import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
10
|
+
import { dirname, join } from "node:path";
|
|
11
|
+
import { maxTokensCaps, onMaxTokensCap } from "../apis/max-tokens.js";
|
|
12
|
+
export const MAX_TOKENS_CACHE_VERSION = 1;
|
|
13
|
+
/** 条目有效期:30 天。 */
|
|
14
|
+
export const MAX_TOKENS_CACHE_TTL_MS = 30 * 24 * 60 * 60 * 1000;
|
|
15
|
+
/** 缓存文件位置。 */
|
|
16
|
+
export function maxTokensCachePath(dataDir) {
|
|
17
|
+
return join(dataDir, "models", "max-tokens-caps.json");
|
|
18
|
+
}
|
|
19
|
+
/** 读文件里未过期的条目;不存在、坏 JSON、版本不符或形状不对的条目一律忽略。 */
|
|
20
|
+
function readEntries(dataDir, now) {
|
|
21
|
+
const out = new Map();
|
|
22
|
+
let parsed;
|
|
23
|
+
try {
|
|
24
|
+
parsed = JSON.parse(readFileSync(maxTokensCachePath(dataDir), "utf8"));
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
if (typeof parsed !== "object" || parsed === null)
|
|
30
|
+
return out;
|
|
31
|
+
const file = parsed;
|
|
32
|
+
if (file.version !== MAX_TOKENS_CACHE_VERSION)
|
|
33
|
+
return out;
|
|
34
|
+
if (typeof file.caps !== "object" || file.caps === null)
|
|
35
|
+
return out;
|
|
36
|
+
for (const [key, value] of Object.entries(file.caps)) {
|
|
37
|
+
if (typeof value !== "object" || value === null)
|
|
38
|
+
continue;
|
|
39
|
+
const { cap, learnedAt } = value;
|
|
40
|
+
if (typeof cap !== "number" || !Number.isInteger(cap) || cap < 1)
|
|
41
|
+
continue;
|
|
42
|
+
if (typeof learnedAt !== "number" || !Number.isFinite(learnedAt))
|
|
43
|
+
continue;
|
|
44
|
+
if (now - learnedAt > MAX_TOKENS_CACHE_TTL_MS)
|
|
45
|
+
continue;
|
|
46
|
+
out.set(key, { cap, learnedAt });
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
/** 载入未过期的上限到进程内的表(已有的键不覆盖);返回载入条数。 */
|
|
51
|
+
export function loadMaxTokensCaps(dataDir, now = Date.now) {
|
|
52
|
+
let loaded = 0;
|
|
53
|
+
for (const [key, entry] of readEntries(dataDir, now())) {
|
|
54
|
+
if (maxTokensCaps.has(key))
|
|
55
|
+
continue;
|
|
56
|
+
maxTokensCaps.set(key, entry.cap);
|
|
57
|
+
loaded++;
|
|
58
|
+
}
|
|
59
|
+
return loaded;
|
|
60
|
+
}
|
|
61
|
+
/** 把一条新上限并入文件(顺带清掉过期条目);写失败不抛(缓存只是省一次 400)。 */
|
|
62
|
+
export function recordMaxTokensCap(dataDir, key, cap, now = Date.now) {
|
|
63
|
+
const at = now();
|
|
64
|
+
const entries = readEntries(dataDir, at);
|
|
65
|
+
entries.set(key, { cap, learnedAt: at });
|
|
66
|
+
const path = maxTokensCachePath(dataDir);
|
|
67
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
68
|
+
try {
|
|
69
|
+
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
70
|
+
const caps = Object.fromEntries([...entries].sort(([a], [b]) => (a < b ? -1 : 1)));
|
|
71
|
+
writeFileSync(tmp, `${JSON.stringify({ version: MAX_TOKENS_CACHE_VERSION, caps }, null, 2)}\n`);
|
|
72
|
+
renameSync(tmp, path);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// 只读数据目录等:本进程内的表仍有效
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const attached = new Map();
|
|
79
|
+
/**
|
|
80
|
+
* 载入并订阅:之后学到的上限写回该数据目录。按 `dataDir` 幂等(同一进程重复组装注册表不重复订阅);
|
|
81
|
+
* 返回取消函数(取消后可重新 attach)。
|
|
82
|
+
*/
|
|
83
|
+
export function attachMaxTokensCache(dataDir, now = Date.now) {
|
|
84
|
+
const existing = attached.get(dataDir);
|
|
85
|
+
if (existing !== undefined)
|
|
86
|
+
return existing;
|
|
87
|
+
loadMaxTokensCaps(dataDir, now);
|
|
88
|
+
const unsubscribe = onMaxTokensCap((key, cap) => recordMaxTokensCap(dataDir, key, cap, now));
|
|
89
|
+
const detach = () => {
|
|
90
|
+
unsubscribe();
|
|
91
|
+
attached.delete(dataDir);
|
|
92
|
+
};
|
|
93
|
+
attached.set(dataDir, detach);
|
|
94
|
+
return detach;
|
|
95
|
+
}
|
|
@@ -256,9 +256,9 @@ export class ProviderRegistry {
|
|
|
256
256
|
const channelsOf = (wanted, modelId) => modelChannels(wanted, provider.channels ?? [], provider.defaultChannel ?? "", (name) => this.warn(`model "${id}/${modelId}" channel "${name}" not found; ignored`));
|
|
257
257
|
for (const entry of config.models ?? []) {
|
|
258
258
|
// 模型级 api(第三波 §2.3):同一中转下不同模型走不同协议;缺省沿用供应商(或渠道)的。
|
|
259
|
-
const { entry: filled, metadata } = enrichEntry(entry, this.modelsDev);
|
|
260
|
-
|
|
261
|
-
this.warn(
|
|
259
|
+
const { entry: filled, metadata } = enrichEntry(entry, this.modelsDev, id);
|
|
260
|
+
for (const warning of metadata.warnings ?? [])
|
|
261
|
+
this.warn(warning);
|
|
262
262
|
const model = withCustomDefaults(filled, id, entry.api ?? provider.api);
|
|
263
263
|
// 内置供应商上没写 channels 的模型:定渠道时挂全部渠道(settleBuiltinChannels)
|
|
264
264
|
if (provider.channels !== undefined && (entry.channels !== undefined || !provider.builtin))
|