@skillfm/local 2.7.3 → 2.7.5
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/dist/checkup/daily-push.d.ts +29 -0
- package/dist/checkup/daily-push.d.ts.map +1 -0
- package/dist/checkup/daily-push.js +86 -0
- package/dist/checkup/daily-push.js.map +1 -0
- package/dist/checkup/dimension-1-usage.d.ts +22 -0
- package/dist/checkup/dimension-1-usage.d.ts.map +1 -0
- package/dist/checkup/dimension-1-usage.js +115 -0
- package/dist/checkup/dimension-1-usage.js.map +1 -0
- package/dist/checkup/dimension-3-files.d.ts +36 -0
- package/dist/checkup/dimension-3-files.d.ts.map +1 -0
- package/dist/checkup/dimension-3-files.js +276 -0
- package/dist/checkup/dimension-3-files.js.map +1 -0
- package/dist/checkup/dimension-4-context.d.ts +18 -0
- package/dist/checkup/dimension-4-context.d.ts.map +1 -0
- package/dist/checkup/dimension-4-context.js +177 -0
- package/dist/checkup/dimension-4-context.js.map +1 -0
- package/dist/checkup/index.d.ts +11 -0
- package/dist/checkup/index.d.ts.map +1 -0
- package/dist/checkup/index.js +10 -0
- package/dist/checkup/index.js.map +1 -0
- package/dist/checkup/report.d.ts +26 -0
- package/dist/checkup/report.d.ts.map +1 -0
- package/dist/checkup/report.js +173 -0
- package/dist/checkup/report.js.map +1 -0
- package/dist/checkup/score.d.ts +27 -0
- package/dist/checkup/score.d.ts.map +1 -0
- package/dist/checkup/score.js +101 -0
- package/dist/checkup/score.js.map +1 -0
- package/dist/checkup/types.d.ts +64 -0
- package/dist/checkup/types.d.ts.map +1 -0
- package/dist/checkup/types.js +5 -0
- package/dist/checkup/types.js.map +1 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +27 -0
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/tools/checkup.d.ts +21 -0
- package/dist/mcp/tools/checkup.d.ts.map +1 -0
- package/dist/mcp/tools/checkup.js +35 -0
- package/dist/mcp/tools/checkup.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +6 -0
- package/dist/mcp/tools/index.d.ts.map +1 -1
- package/dist/mcp/tools/index.js +47 -0
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/setup-gateway.d.ts +16 -0
- package/dist/mcp/tools/setup-gateway.d.ts.map +1 -0
- package/dist/mcp/tools/setup-gateway.js +79 -0
- package/dist/mcp/tools/setup-gateway.js.map +1 -0
- package/dist/mcp/tools/show-my-usage.d.ts +26 -0
- package/dist/mcp/tools/show-my-usage.d.ts.map +1 -0
- package/dist/mcp/tools/show-my-usage.js +68 -0
- package/dist/mcp/tools/show-my-usage.js.map +1 -0
- package/dist/reconciliation/engine.d.ts +30 -0
- package/dist/reconciliation/engine.d.ts.map +1 -0
- package/dist/reconciliation/engine.js +62 -0
- package/dist/reconciliation/engine.js.map +1 -0
- package/dist/reconciliation/index.d.ts +8 -0
- package/dist/reconciliation/index.d.ts.map +1 -0
- package/dist/reconciliation/index.js +8 -0
- package/dist/reconciliation/index.js.map +1 -0
- package/dist/reconciliation/l1-reconciler.d.ts +29 -0
- package/dist/reconciliation/l1-reconciler.d.ts.map +1 -0
- package/dist/reconciliation/l1-reconciler.js +144 -0
- package/dist/reconciliation/l1-reconciler.js.map +1 -0
- package/dist/reconciliation/l2-reconciler.d.ts +21 -0
- package/dist/reconciliation/l2-reconciler.d.ts.map +1 -0
- package/dist/reconciliation/l2-reconciler.js +241 -0
- package/dist/reconciliation/l2-reconciler.js.map +1 -0
- package/dist/reconciliation/types.d.ts +49 -0
- package/dist/reconciliation/types.d.ts.map +1 -0
- package/dist/reconciliation/types.js +9 -0
- package/dist/reconciliation/types.js.map +1 -0
- package/dist/save-token/e1-router.d.ts +7 -0
- package/dist/save-token/e1-router.d.ts.map +1 -0
- package/dist/save-token/e1-router.js +112 -0
- package/dist/save-token/e1-router.js.map +1 -0
- package/dist/save-token/e2-cache.d.ts +7 -0
- package/dist/save-token/e2-cache.d.ts.map +1 -0
- package/dist/save-token/e2-cache.js +128 -0
- package/dist/save-token/e2-cache.js.map +1 -0
- package/dist/save-token/e3-batch.d.ts +7 -0
- package/dist/save-token/e3-batch.d.ts.map +1 -0
- package/dist/save-token/e3-batch.js +80 -0
- package/dist/save-token/e3-batch.js.map +1 -0
- package/dist/save-token/gateway-setup.d.ts +27 -0
- package/dist/save-token/gateway-setup.d.ts.map +1 -0
- package/dist/save-token/gateway-setup.js +200 -0
- package/dist/save-token/gateway-setup.js.map +1 -0
- package/dist/save-token/index.d.ts +13 -0
- package/dist/save-token/index.d.ts.map +1 -0
- package/dist/save-token/index.js +23 -0
- package/dist/save-token/index.js.map +1 -0
- package/dist/save-token/types.d.ts +46 -0
- package/dist/save-token/types.d.ts.map +1 -0
- package/dist/save-token/types.js +5 -0
- package/dist/save-token/types.js.map +1 -0
- package/dist/usage-local/index.d.ts +34 -0
- package/dist/usage-local/index.d.ts.map +1 -0
- package/dist/usage-local/index.js +33 -0
- package/dist/usage-local/index.js.map +1 -0
- package/dist/usage-local/model-pricing.d.ts +42 -0
- package/dist/usage-local/model-pricing.d.ts.map +1 -0
- package/dist/usage-local/model-pricing.js +253 -0
- package/dist/usage-local/model-pricing.js.map +1 -0
- package/dist/usage-local/openclaw-watcher.d.ts +35 -0
- package/dist/usage-local/openclaw-watcher.d.ts.map +1 -0
- package/dist/usage-local/openclaw-watcher.js +190 -0
- package/dist/usage-local/openclaw-watcher.js.map +1 -0
- package/dist/usage-local/plan.d.ts +58 -0
- package/dist/usage-local/plan.d.ts.map +1 -0
- package/dist/usage-local/plan.js +84 -0
- package/dist/usage-local/plan.js.map +1 -0
- package/dist/usage-local/store.d.ts +50 -0
- package/dist/usage-local/store.d.ts.map +1 -0
- package/dist/usage-local/store.js +201 -0
- package/dist/usage-local/store.js.map +1 -0
- package/dist/usage-local/types.d.ts +94 -0
- package/dist/usage-local/types.d.ts.map +1 -0
- package/dist/usage-local/types.js +6 -0
- package/dist/usage-local/types.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// sdk/skillfm-local/src/save-token/e1-router.ts
|
|
2
|
+
//
|
|
3
|
+
// E1 Free 智能 Model Router — cascading 启发式 (PRD §6.2 Phase 1).
|
|
4
|
+
// 扫 trajectory 找 expensive model 调用, 推荐切 cheaper 同档.
|
|
5
|
+
//
|
|
6
|
+
// MVP: 只做规则启发式 (基于价目表 + model family 映射).
|
|
7
|
+
// Pro 升级 (2.7.5): 通过 gateway hook 真自动 cascade + brain LLM 评 quality.
|
|
8
|
+
import { getModelPrice, USD_TO_CNY } from '../usage-local/model-pricing.js';
|
|
9
|
+
import { timeWindow } from '../usage-local/store.js';
|
|
10
|
+
/**
|
|
11
|
+
* Model family 映射: expensive → cheaper 同档替代
|
|
12
|
+
* 仅在质量"通常"够 (90%+) 的场景下推荐. 用户决定切不切.
|
|
13
|
+
*/
|
|
14
|
+
const CASCADE_MAP = [
|
|
15
|
+
{
|
|
16
|
+
expensive_pattern: /claude.*opus/i,
|
|
17
|
+
cheaper: { provider: 'anthropic', model_id: 'claude-sonnet-4-6' },
|
|
18
|
+
description: 'Opus 级任务很多 Sonnet 4.6 能干 (95%+ 质量)',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
expensive_pattern: /claude.*sonnet/i,
|
|
22
|
+
cheaper: { provider: 'anthropic', model_id: 'claude-haiku-4-5' },
|
|
23
|
+
description: '日常 Sonnet 调用 80% 任务 Haiku 4.5 同质量, 价格 1/4',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
expensive_pattern: /(gpt-4o|gpt-4-turbo)$/i,
|
|
27
|
+
cheaper: { provider: 'openai', model_id: 'gpt-4o-mini' },
|
|
28
|
+
description: 'GPT-4o 很多任务 4o-mini 同质量, 价格 1/17',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
expensive_pattern: /^o1$/i,
|
|
32
|
+
cheaper: { provider: 'openai', model_id: 'o1-mini' },
|
|
33
|
+
description: 'o1 reasoning 任务 o1-mini 同等推理能力, 价格 1/5',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
expensive_pattern: /minimax-m2\.7/i,
|
|
37
|
+
cheaper: { provider: 'minimax-cn', model_id: 'MiniMax-M2.5' },
|
|
38
|
+
description: 'M2.7 → M2.5 价格 1/2.5, 大部分 routine 任务质量同档',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
expensive_pattern: /deepseek-v4-pro/i,
|
|
42
|
+
cheaper: { provider: 'deepseek', model_id: 'deepseek-v4-flash' },
|
|
43
|
+
description: 'V4 Pro → V4 Flash 价格 1/5',
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
/**
|
|
47
|
+
* 扫描 + 返建议
|
|
48
|
+
*/
|
|
49
|
+
export async function scanE1Router(store, opts) {
|
|
50
|
+
const window = opts.start && opts.end
|
|
51
|
+
? { start: opts.start, end: opts.end }
|
|
52
|
+
: timeWindow('week'); // 默认近 7 天
|
|
53
|
+
const records = store.query(window);
|
|
54
|
+
if (records.length === 0)
|
|
55
|
+
return [];
|
|
56
|
+
// 按 (provider, model) 聚合
|
|
57
|
+
const byModel = new Map();
|
|
58
|
+
for (const r of records) {
|
|
59
|
+
const key = `${r.provider}/${r.model_id}`;
|
|
60
|
+
const cur = byModel.get(key) ?? { count: 0, tokens_in: 0, tokens_out: 0, cost_usd: 0 };
|
|
61
|
+
cur.count += 1;
|
|
62
|
+
cur.tokens_in += r.input_tokens;
|
|
63
|
+
cur.tokens_out += r.output_tokens;
|
|
64
|
+
cur.cost_usd += r.estimated_cost_usd;
|
|
65
|
+
byModel.set(key, cur);
|
|
66
|
+
}
|
|
67
|
+
const suggestions = [];
|
|
68
|
+
for (const [key, agg] of byModel) {
|
|
69
|
+
if (agg.cost_usd < 0.5)
|
|
70
|
+
continue; // 低于 ¥3.65 不值得 surface
|
|
71
|
+
for (const rule of CASCADE_MAP) {
|
|
72
|
+
if (rule.expensive_pattern.test(key)) {
|
|
73
|
+
// 算切 cheaper 后估省
|
|
74
|
+
const cheaperPrice = getModelPrice(rule.cheaper.provider, rule.cheaper.model_id);
|
|
75
|
+
const newCost = (agg.tokens_in / 1_000_000) * cheaperPrice.input_per_1m
|
|
76
|
+
+ (agg.tokens_out / 1_000_000) * cheaperPrice.output_per_1m;
|
|
77
|
+
const savings_usd = agg.cost_usd - newCost;
|
|
78
|
+
if (savings_usd <= 0)
|
|
79
|
+
continue;
|
|
80
|
+
const savings_pct = (savings_usd / agg.cost_usd) * 100;
|
|
81
|
+
// 月度估算 (从 7 天 → 30 天 × 4.3 比例)
|
|
82
|
+
const monthly_savings_usd = savings_usd * (30 / 7);
|
|
83
|
+
const monthly_savings_tokens = (agg.tokens_in + agg.tokens_out) * (30 / 7);
|
|
84
|
+
const fix_method = opts.is_pro ? 'pro_auto' : 'free_manual';
|
|
85
|
+
suggestions.push({
|
|
86
|
+
engine: 'E1_router',
|
|
87
|
+
headline: `${agg.count} 次 ${key} 调用可切 ${rule.cheaper.provider}/${rule.cheaper.model_id} (${rule.description.slice(0, 50)}...)`,
|
|
88
|
+
estimated_savings_pct: Math.round(savings_pct),
|
|
89
|
+
estimated_savings_tokens: Math.round(monthly_savings_tokens),
|
|
90
|
+
estimated_savings_cny: Math.round(monthly_savings_usd * USD_TO_CNY * 100) / 100,
|
|
91
|
+
fix_method,
|
|
92
|
+
fix_instructions: opts.is_pro
|
|
93
|
+
? undefined
|
|
94
|
+
: `在你 IDE 中, 把 model 设置改成 ${rule.cheaper.provider}/${rule.cheaper.model_id}; 或手动针对 routine 任务用 cheaper model`,
|
|
95
|
+
pro_unlock_label: opts.is_pro
|
|
96
|
+
? undefined
|
|
97
|
+
: `Pro 升级后 SkillFM gateway 自动 cascade routing — 估月省 ¥${Math.round(monthly_savings_usd * USD_TO_CNY)}`,
|
|
98
|
+
details: {
|
|
99
|
+
from_model: key,
|
|
100
|
+
to_model: `${rule.cheaper.provider}/${rule.cheaper.model_id}`,
|
|
101
|
+
calls_in_window: agg.count,
|
|
102
|
+
cost_usd_window: agg.cost_usd,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
break; // 一个 expensive model 只推一个 cheaper 候选
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// 按估省排序, 大头先 surface
|
|
110
|
+
return suggestions.sort((a, b) => b.estimated_savings_cny - a.estimated_savings_cny);
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=e1-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e1-router.js","sourceRoot":"","sources":["../../src/save-token/e1-router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { LocalUsageStore } from '../usage-local/store.js';
|
|
2
|
+
import type { SaveTokenSuggestion, SaveTokenScanOptions } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* 扫描 + 返建议
|
|
5
|
+
*/
|
|
6
|
+
export declare function scanE2Cache(store: LocalUsageStore, opts: SaveTokenScanOptions): Promise<SaveTokenSuggestion[]>;
|
|
7
|
+
//# sourceMappingURL=e2-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2-cache.d.ts","sourceRoot":"","sources":["../../src/save-token/e2-cache.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAI/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAO5E;;GAEG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,mBAAmB,EAAE,CAAC,CA0FhC"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// sdk/skillfm-local/src/save-token/e2-cache.ts
|
|
2
|
+
//
|
|
3
|
+
// E2 Prompt Caching 自动启用 (PRD §6.3) — Free 即得真省钱.
|
|
4
|
+
//
|
|
5
|
+
// Free: 扫 trajectory 找 system prompt 重复率高 / 长 prompt → surface "启 cache 估省 ¥X"
|
|
6
|
+
// 给 cache_control 代码片段让用户手动加
|
|
7
|
+
// Pro: gateway hook auto inject cache_control breakpoint (2.7.5+)
|
|
8
|
+
//
|
|
9
|
+
// 真证据 (PRD §6.3):
|
|
10
|
+
// OpenAI 50% off cached tokens (auto, 1024+ token)
|
|
11
|
+
// Anthropic 90% off cache reads ($0.30/M vs $3.00/M, 显式 ephemeral)
|
|
12
|
+
// 真案例 1 个开发者 $720 → $72/月 = 90% off
|
|
13
|
+
import { getModelPrice, USD_TO_CNY } from '../usage-local/model-pricing.js';
|
|
14
|
+
import { timeWindow } from '../usage-local/store.js';
|
|
15
|
+
/**
|
|
16
|
+
* 哪些 provider 真支持 prompt cache
|
|
17
|
+
*/
|
|
18
|
+
const CACHE_SUPPORTED_PROVIDERS = new Set(['anthropic', 'openai', 'deepseek']);
|
|
19
|
+
/**
|
|
20
|
+
* 扫描 + 返建议
|
|
21
|
+
*/
|
|
22
|
+
export async function scanE2Cache(store, opts) {
|
|
23
|
+
const window = opts.start && opts.end
|
|
24
|
+
? { start: opts.start, end: opts.end }
|
|
25
|
+
: timeWindow('week');
|
|
26
|
+
const records = store.query(window);
|
|
27
|
+
if (records.length === 0)
|
|
28
|
+
return [];
|
|
29
|
+
// 按 (provider, model) 聚合 cache 利用率
|
|
30
|
+
const byModel = new Map();
|
|
31
|
+
for (const r of records) {
|
|
32
|
+
const key = `${r.provider}/${r.model_id}`;
|
|
33
|
+
const cur = byModel.get(key) ?? {
|
|
34
|
+
count: 0, input_tokens: 0, cache_read_tokens: 0, cache_write_tokens: 0, cost_usd: 0,
|
|
35
|
+
};
|
|
36
|
+
cur.count += 1;
|
|
37
|
+
cur.input_tokens += r.input_tokens;
|
|
38
|
+
cur.cache_read_tokens += r.cache_read_tokens;
|
|
39
|
+
cur.cache_write_tokens += r.cache_write_tokens;
|
|
40
|
+
cur.cost_usd += r.estimated_cost_usd;
|
|
41
|
+
byModel.set(key, cur);
|
|
42
|
+
}
|
|
43
|
+
const suggestions = [];
|
|
44
|
+
for (const [key, agg] of byModel) {
|
|
45
|
+
const [provider] = key.split('/');
|
|
46
|
+
if (!CACHE_SUPPORTED_PROVIDERS.has(provider))
|
|
47
|
+
continue;
|
|
48
|
+
if (agg.cost_usd < 0.5)
|
|
49
|
+
continue;
|
|
50
|
+
if (agg.count < 5)
|
|
51
|
+
continue; // 5+ 次调用才有 cache 意义
|
|
52
|
+
const totalInput = agg.input_tokens + agg.cache_read_tokens;
|
|
53
|
+
if (totalInput < 5000)
|
|
54
|
+
continue; // 累计 input 太少不值得 cache
|
|
55
|
+
const cache_hit_rate = totalInput > 0 ? agg.cache_read_tokens / totalInput : 0;
|
|
56
|
+
// 如果 cache hit rate < 30% + 平均 input > 1024 tokens (cache 阈值) → 推荐启
|
|
57
|
+
const avg_input = agg.input_tokens / agg.count;
|
|
58
|
+
if (cache_hit_rate >= 0.3)
|
|
59
|
+
continue; // 已经在用 cache, skip
|
|
60
|
+
if (avg_input < 1024 && provider === 'openai')
|
|
61
|
+
continue; // OpenAI auto cache 阈值
|
|
62
|
+
if (avg_input < 200)
|
|
63
|
+
continue; // 太短不值得显式 cache
|
|
64
|
+
// 估算启 cache 后省多少
|
|
65
|
+
// 假设 cache hit rate 提到 70% (合理水平)
|
|
66
|
+
const targetCacheRate = 0.7;
|
|
67
|
+
const newCacheRead = totalInput * targetCacheRate;
|
|
68
|
+
const newRawInput = totalInput * (1 - targetCacheRate);
|
|
69
|
+
const price = getModelPrice(provider, key.split('/').slice(1).join('/'));
|
|
70
|
+
const oldCost = (agg.input_tokens / 1_000_000) * price.input_per_1m
|
|
71
|
+
+ (agg.cache_read_tokens / 1_000_000) * price.cache_read_per_1m;
|
|
72
|
+
const newCost = (newRawInput / 1_000_000) * price.input_per_1m
|
|
73
|
+
+ (newCacheRead / 1_000_000) * price.cache_read_per_1m
|
|
74
|
+
+ (totalInput * 0.1 / 1_000_000) * price.cache_write_per_1m; // 估 cache write 是 input 10%
|
|
75
|
+
const savings_usd = oldCost - newCost;
|
|
76
|
+
if (savings_usd <= 0)
|
|
77
|
+
continue;
|
|
78
|
+
const savings_pct = (savings_usd / oldCost) * 100;
|
|
79
|
+
const monthly_savings_usd = savings_usd * (30 / 7);
|
|
80
|
+
const fix_method = opts.is_pro ? 'pro_auto' : 'free_manual';
|
|
81
|
+
suggestions.push({
|
|
82
|
+
engine: 'E2_cache',
|
|
83
|
+
headline: `${key} ${agg.count} 次调用 cache 命中率 ${(cache_hit_rate * 100).toFixed(0)}% — 启 cache 可省 ${Math.round(savings_pct)}% input cost`,
|
|
84
|
+
estimated_savings_pct: Math.round(savings_pct),
|
|
85
|
+
estimated_savings_tokens: Math.round(totalInput * (30 / 7) * targetCacheRate),
|
|
86
|
+
estimated_savings_cny: Math.round(monthly_savings_usd * USD_TO_CNY * 100) / 100,
|
|
87
|
+
fix_method,
|
|
88
|
+
fix_instructions: opts.is_pro ? undefined : buildCacheInstructions(provider),
|
|
89
|
+
pro_unlock_label: opts.is_pro
|
|
90
|
+
? undefined
|
|
91
|
+
: `Pro 升级后 SkillFM gateway auto inject cache_control — 估月省 ¥${Math.round(monthly_savings_usd * USD_TO_CNY)}`,
|
|
92
|
+
details: {
|
|
93
|
+
model: key,
|
|
94
|
+
avg_input_tokens: Math.round(avg_input),
|
|
95
|
+
current_cache_hit_rate: cache_hit_rate,
|
|
96
|
+
target_cache_hit_rate: targetCacheRate,
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return suggestions.sort((a, b) => b.estimated_savings_cny - a.estimated_savings_cny);
|
|
101
|
+
}
|
|
102
|
+
function buildCacheInstructions(provider) {
|
|
103
|
+
switch (provider) {
|
|
104
|
+
case 'anthropic':
|
|
105
|
+
return [
|
|
106
|
+
'在 system prompt 里加 cache_control breakpoint:',
|
|
107
|
+
'```',
|
|
108
|
+
'{role: "system", content: [{',
|
|
109
|
+
' type: "text",',
|
|
110
|
+
' text: "你的长 system prompt...",',
|
|
111
|
+
' cache_control: {type: "ephemeral"}', // ephemeral 5 min cache
|
|
112
|
+
'}]}',
|
|
113
|
+
'```',
|
|
114
|
+
'价: cache write +25%, cache read 90% off (vs 普通 input)',
|
|
115
|
+
].join('\n');
|
|
116
|
+
case 'openai':
|
|
117
|
+
return [
|
|
118
|
+
'OpenAI 自动 cache (1024+ token) — 无需 code 改, 但要保证 prompt 前缀稳定:',
|
|
119
|
+
'- 不要每次 inject 时间戳 / 随机 ID 在 prompt 顶',
|
|
120
|
+
'- 把 system + few-shot 例子放最前 (这样 prefix 稳定 → 自动 cache hit)',
|
|
121
|
+
].join('\n');
|
|
122
|
+
case 'deepseek':
|
|
123
|
+
return 'DeepSeek 类似 OpenAI 自动 prefix cache, 保证 prompt 前缀稳定即可';
|
|
124
|
+
default:
|
|
125
|
+
return '该 provider 暂不支持 prompt cache';
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=e2-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2-cache.js","sourceRoot":"","sources":["../../src/save-token/e2-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { LocalUsageStore } from '../usage-local/store.js';
|
|
2
|
+
import type { SaveTokenSuggestion, SaveTokenScanOptions } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* 检测 batch 候选: 深夜调用 (00:00-06:00) 或 短时间内 5+ 调用 (批量类)
|
|
5
|
+
*/
|
|
6
|
+
export declare function scanE3Batch(store: LocalUsageStore, opts: SaveTokenScanOptions): Promise<SaveTokenSuggestion[]>;
|
|
7
|
+
//# sourceMappingURL=e3-batch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e3-batch.d.ts","sourceRoot":"","sources":["../../src/save-token/e3-batch.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAI/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAO5E;;GAEG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,mBAAmB,EAAE,CAAC,CA+DhC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// sdk/skillfm-local/src/save-token/e3-batch.ts
|
|
2
|
+
//
|
|
3
|
+
// E3 Batch API 推荐 (PRD §6.4) — 50% 即得 (异步任务).
|
|
4
|
+
//
|
|
5
|
+
// Free: 找 latency-tolerant task (深夜跑 / 批量同类 / 长完成时间) → 提示走 batch
|
|
6
|
+
// Pro: gateway 自动 dispatch batch (2.7.5+)
|
|
7
|
+
//
|
|
8
|
+
// 真证据:
|
|
9
|
+
// OpenAI Batch API 50% off all models, 24h window
|
|
10
|
+
// Anthropic Message Batches 同 50%
|
|
11
|
+
// Stack: cache + batch = 75-95% off
|
|
12
|
+
import { USD_TO_CNY } from '../usage-local/model-pricing.js';
|
|
13
|
+
import { timeWindow } from '../usage-local/store.js';
|
|
14
|
+
/**
|
|
15
|
+
* Batch API 真支持 provider
|
|
16
|
+
*/
|
|
17
|
+
const BATCH_SUPPORTED_PROVIDERS = new Set(['openai', 'anthropic']);
|
|
18
|
+
/**
|
|
19
|
+
* 检测 batch 候选: 深夜调用 (00:00-06:00) 或 短时间内 5+ 调用 (批量类)
|
|
20
|
+
*/
|
|
21
|
+
export async function scanE3Batch(store, opts) {
|
|
22
|
+
const window = opts.start && opts.end
|
|
23
|
+
? { start: opts.start, end: opts.end }
|
|
24
|
+
: timeWindow('week');
|
|
25
|
+
const records = store.query(window);
|
|
26
|
+
if (records.length === 0)
|
|
27
|
+
return [];
|
|
28
|
+
// 找深夜调用 (00:00-06:00 in Asia/Shanghai)
|
|
29
|
+
const nightRecords = records.filter((r) => {
|
|
30
|
+
if (!BATCH_SUPPORTED_PROVIDERS.has(r.provider.toLowerCase()))
|
|
31
|
+
return false;
|
|
32
|
+
const d = new Date(r.timestamp);
|
|
33
|
+
// 转 Asia/Shanghai 小时 (UTC+8)
|
|
34
|
+
const shanghaiHour = (d.getUTCHours() + 8) % 24;
|
|
35
|
+
return shanghaiHour < 6 || shanghaiHour >= 23;
|
|
36
|
+
});
|
|
37
|
+
if (nightRecords.length === 0)
|
|
38
|
+
return [];
|
|
39
|
+
// 算这些 record 总成本 + 估省 50%
|
|
40
|
+
let total_cost_usd = 0;
|
|
41
|
+
let total_tokens = 0;
|
|
42
|
+
const providerCount = new Map();
|
|
43
|
+
for (const r of nightRecords) {
|
|
44
|
+
total_cost_usd += r.estimated_cost_usd;
|
|
45
|
+
total_tokens += r.input_tokens + r.output_tokens;
|
|
46
|
+
providerCount.set(r.provider, (providerCount.get(r.provider) ?? 0) + 1);
|
|
47
|
+
}
|
|
48
|
+
if (total_cost_usd < 0.5)
|
|
49
|
+
return []; // 太少不值得
|
|
50
|
+
const savings_usd = total_cost_usd * 0.5;
|
|
51
|
+
const monthly_savings_usd = savings_usd * (30 / 7);
|
|
52
|
+
const monthly_savings_tokens = total_tokens * (30 / 7);
|
|
53
|
+
const providerList = Array.from(providerCount.entries())
|
|
54
|
+
.map(([p, c]) => `${p} ${c} 次`)
|
|
55
|
+
.join(', ');
|
|
56
|
+
const fix_method = opts.is_pro ? 'pro_auto' : 'free_manual';
|
|
57
|
+
return [{
|
|
58
|
+
engine: 'E3_batch',
|
|
59
|
+
headline: `深夜调用 ${nightRecords.length} 次 (${providerList}, ¥${(total_cost_usd * USD_TO_CNY).toFixed(2)}) — 走 batch API 50% off`,
|
|
60
|
+
estimated_savings_pct: 50,
|
|
61
|
+
estimated_savings_tokens: Math.round(monthly_savings_tokens),
|
|
62
|
+
estimated_savings_cny: Math.round(monthly_savings_usd * USD_TO_CNY * 100) / 100,
|
|
63
|
+
fix_method,
|
|
64
|
+
fix_instructions: opts.is_pro ? undefined : [
|
|
65
|
+
'深夜任务 (你不在等结果) 改走 Batch API 即 50% off:',
|
|
66
|
+
'- OpenAI: POST /v1/batches + 上传 JSONL, 24h 内返结果 (50% off)',
|
|
67
|
+
'- Anthropic: POST /v1/messages/batches 同上',
|
|
68
|
+
'在你的 agent / script 里, 把这类异步任务排队上传, 而非实时调用',
|
|
69
|
+
].join('\n'),
|
|
70
|
+
pro_unlock_label: opts.is_pro
|
|
71
|
+
? undefined
|
|
72
|
+
: `Pro 升级后 SkillFM gateway 自动 dispatch latency-tolerant task 到 Batch API — 估月省 ¥${Math.round(monthly_savings_usd * USD_TO_CNY)}`,
|
|
73
|
+
details: {
|
|
74
|
+
night_call_count: nightRecords.length,
|
|
75
|
+
provider_breakdown: Object.fromEntries(providerCount),
|
|
76
|
+
total_cost_usd_window: total_cost_usd,
|
|
77
|
+
},
|
|
78
|
+
}];
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=e3-batch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e3-batch.js","sourceRoot":"","sources":["../../src/save-token/e3-batch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { GatewayDetection } from './types.js';
|
|
2
|
+
export declare const SKILLFM_GATEWAY_BASE_URL: string;
|
|
3
|
+
/**
|
|
4
|
+
* 检测各 IDE 的配置 + 当前 BASE_URL
|
|
5
|
+
*/
|
|
6
|
+
export declare function detectIDEs(): Promise<GatewayDetection[]>;
|
|
7
|
+
/**
|
|
8
|
+
* 配置一个 IDE 的 gateway BASE_URL (写 config + 提供 revert 命令)
|
|
9
|
+
*
|
|
10
|
+
* 真改: 在每个 config 加 ANTHROPIC_BASE_URL / OPENAI_API_BASE 指向 SkillFM gateway
|
|
11
|
+
* 透明: 改之前 backup 原 config 到 ~/.skillfm/gateway-backup/<ts>/
|
|
12
|
+
*/
|
|
13
|
+
export interface SetupResult {
|
|
14
|
+
ide: string;
|
|
15
|
+
applied: boolean;
|
|
16
|
+
config_path?: string;
|
|
17
|
+
backup_path?: string;
|
|
18
|
+
revert_command?: string;
|
|
19
|
+
error?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function setupClaudeCodeGateway(): Promise<SetupResult>;
|
|
22
|
+
export declare function setupShellEnvGateway(): Promise<SetupResult>;
|
|
23
|
+
/**
|
|
24
|
+
* 一键配 — 所有检测到的 IDE
|
|
25
|
+
*/
|
|
26
|
+
export declare function setupAllDetectedGateways(): Promise<SetupResult[]>;
|
|
27
|
+
//# sourceMappingURL=gateway-setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway-setup.d.ts","sourceRoot":"","sources":["../../src/save-token/gateway-setup.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,gBAAgB,EAAsB,MAAM,YAAY,CAAC;AAEvE,eAAO,MAAM,wBAAwB,QAAuE,CAAC;AAE7G;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAsB9D;AAyFD;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,WAAW,CAAC,CAiCnE;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,WAAW,CAAC,CAoCjE;AAED;;GAEG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAcvE"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// sdk/skillfm-local/src/save-token/gateway-setup.ts
|
|
2
|
+
//
|
|
3
|
+
// LLM Gateway Onboarding 一键配置 (PRD V1.3 §3.4 + 决策 #8).
|
|
4
|
+
// Eric 拍板: Day 0 一次问授权, Pro 升级 0 摩擦.
|
|
5
|
+
//
|
|
6
|
+
// 真核心:
|
|
7
|
+
// 1. detectIDEs() — 看 PATH / 已知配置目录, 检测用户用啥 IDE
|
|
8
|
+
// 2. setupGateway() — 改 IDE config 把 ANTHROPIC_BASE_URL / OPENAI_API_BASE 指向 SkillFM gateway
|
|
9
|
+
// 3. revertGateway() — 1 行 unset 命令让用户随时回滚
|
|
10
|
+
//
|
|
11
|
+
// 透明性: 改任何文件前 surface 给用户 + 提供 revert 命令.
|
|
12
|
+
// MVP: gateway 端 URL 用 placeholder (https://gateway.skillfm.ai), 真 gateway 服务 2.7.5 上线.
|
|
13
|
+
import * as fs from 'node:fs';
|
|
14
|
+
import * as path from 'node:path';
|
|
15
|
+
import { homedir } from 'node:os';
|
|
16
|
+
export const SKILLFM_GATEWAY_BASE_URL = process.env.SKILLFM_GATEWAY_BASE_URL ?? 'https://gateway.skillfm.ai';
|
|
17
|
+
/**
|
|
18
|
+
* 检测各 IDE 的配置 + 当前 BASE_URL
|
|
19
|
+
*/
|
|
20
|
+
export async function detectIDEs() {
|
|
21
|
+
const out = [];
|
|
22
|
+
// Claude Code: ~/.claude/settings.json
|
|
23
|
+
out.push(await detectClaudeCode());
|
|
24
|
+
// Cursor: ~/Library/Application Support/Cursor/User/settings.json (Mac)
|
|
25
|
+
out.push(await detectCursor());
|
|
26
|
+
// Codex: ~/.codex/config.json
|
|
27
|
+
out.push(await detectCodex());
|
|
28
|
+
// Aider: env CHECK
|
|
29
|
+
out.push(await detectAider());
|
|
30
|
+
// Continue: ~/.continue/config.json
|
|
31
|
+
out.push(await detectContinue());
|
|
32
|
+
// Shell env (zsh / bash)
|
|
33
|
+
out.push(await detectShellEnv());
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
async function detectClaudeCode() {
|
|
37
|
+
const settingsPath = path.join(homedir(), '.claude', 'settings.json');
|
|
38
|
+
const exists = fs.existsSync(settingsPath);
|
|
39
|
+
let current_base_url;
|
|
40
|
+
let setup_status = 'not_configured';
|
|
41
|
+
if (exists) {
|
|
42
|
+
try {
|
|
43
|
+
const content = await fs.promises.readFile(settingsPath, 'utf-8');
|
|
44
|
+
const settings = JSON.parse(content);
|
|
45
|
+
current_base_url = settings.env?.ANTHROPIC_BASE_URL;
|
|
46
|
+
setup_status = current_base_url?.includes('skillfm') ? 'configured' : 'not_configured';
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
setup_status = 'unknown';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
ide: 'claude-code',
|
|
54
|
+
detected: exists,
|
|
55
|
+
config_path: exists ? settingsPath : undefined,
|
|
56
|
+
current_base_url,
|
|
57
|
+
setup_status,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
async function detectCursor() {
|
|
61
|
+
const cursorDir = path.join(homedir(), 'Library', 'Application Support', 'Cursor');
|
|
62
|
+
const detected = fs.existsSync(cursorDir);
|
|
63
|
+
return {
|
|
64
|
+
ide: 'cursor',
|
|
65
|
+
detected,
|
|
66
|
+
config_path: detected ? path.join(cursorDir, 'User', 'settings.json') : undefined,
|
|
67
|
+
setup_status: detected ? 'not_configured' : 'unknown',
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
async function detectCodex() {
|
|
71
|
+
const cfgPath = path.join(homedir(), '.codex', 'config.json');
|
|
72
|
+
const exists = fs.existsSync(cfgPath);
|
|
73
|
+
return {
|
|
74
|
+
ide: 'codex',
|
|
75
|
+
detected: exists,
|
|
76
|
+
config_path: exists ? cfgPath : undefined,
|
|
77
|
+
setup_status: exists ? 'not_configured' : 'unknown',
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
async function detectAider() {
|
|
81
|
+
// Aider 用 env 配, 没固定 config 文件
|
|
82
|
+
return {
|
|
83
|
+
ide: 'aider',
|
|
84
|
+
detected: false, // 简化: MVP 不主动检测 aider, 用户手动配
|
|
85
|
+
setup_status: 'unknown',
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
async function detectContinue() {
|
|
89
|
+
const cfgPath = path.join(homedir(), '.continue', 'config.json');
|
|
90
|
+
const exists = fs.existsSync(cfgPath);
|
|
91
|
+
return {
|
|
92
|
+
ide: 'continue',
|
|
93
|
+
detected: exists,
|
|
94
|
+
config_path: exists ? cfgPath : undefined,
|
|
95
|
+
setup_status: exists ? 'not_configured' : 'unknown',
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
async function detectShellEnv() {
|
|
99
|
+
const current_anthropic = process.env.ANTHROPIC_BASE_URL;
|
|
100
|
+
const current_openai = process.env.OPENAI_API_BASE;
|
|
101
|
+
const isConfigured = !!(current_anthropic?.includes('skillfm') || current_openai?.includes('skillfm'));
|
|
102
|
+
// 检测 shell rc
|
|
103
|
+
const zshrc = path.join(homedir(), '.zshrc');
|
|
104
|
+
const bashrc = path.join(homedir(), '.bashrc');
|
|
105
|
+
const cfgPath = fs.existsSync(zshrc) ? zshrc : fs.existsSync(bashrc) ? bashrc : undefined;
|
|
106
|
+
return {
|
|
107
|
+
ide: 'shell-env',
|
|
108
|
+
detected: !!cfgPath,
|
|
109
|
+
config_path: cfgPath,
|
|
110
|
+
current_base_url: current_anthropic ?? current_openai,
|
|
111
|
+
setup_status: isConfigured ? 'configured' : 'not_configured',
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
export async function setupClaudeCodeGateway() {
|
|
115
|
+
const settingsPath = path.join(homedir(), '.claude', 'settings.json');
|
|
116
|
+
const ide = 'claude-code';
|
|
117
|
+
if (!fs.existsSync(settingsPath)) {
|
|
118
|
+
// Claude Code 不存在 → skip
|
|
119
|
+
return { ide, applied: false, error: 'Claude Code not detected' };
|
|
120
|
+
}
|
|
121
|
+
// backup
|
|
122
|
+
const backupDir = path.join(homedir(), '.skillfm', 'gateway-backup', new Date().toISOString().replace(/[:.]/g, '-'));
|
|
123
|
+
await fs.promises.mkdir(backupDir, { recursive: true, mode: 0o700 });
|
|
124
|
+
const backupPath = path.join(backupDir, 'claude-settings.json');
|
|
125
|
+
await fs.promises.copyFile(settingsPath, backupPath);
|
|
126
|
+
// 改 config
|
|
127
|
+
try {
|
|
128
|
+
const content = await fs.promises.readFile(settingsPath, 'utf-8');
|
|
129
|
+
const settings = JSON.parse(content);
|
|
130
|
+
settings.env = settings.env ?? {};
|
|
131
|
+
settings.env.ANTHROPIC_BASE_URL = SKILLFM_GATEWAY_BASE_URL;
|
|
132
|
+
await fs.promises.writeFile(settingsPath, JSON.stringify(settings, null, 2), 'utf-8');
|
|
133
|
+
return {
|
|
134
|
+
ide,
|
|
135
|
+
applied: true,
|
|
136
|
+
config_path: settingsPath,
|
|
137
|
+
backup_path: backupPath,
|
|
138
|
+
revert_command: `cp "${backupPath}" "${settingsPath}"`,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
catch (e) {
|
|
142
|
+
return { ide, applied: false, error: e.message };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
export async function setupShellEnvGateway() {
|
|
146
|
+
const ide = 'shell-env';
|
|
147
|
+
const zshrc = path.join(homedir(), '.zshrc');
|
|
148
|
+
const bashrc = path.join(homedir(), '.bashrc');
|
|
149
|
+
const rcPath = fs.existsSync(zshrc) ? zshrc : fs.existsSync(bashrc) ? bashrc : null;
|
|
150
|
+
if (!rcPath) {
|
|
151
|
+
return { ide, applied: false, error: 'No shell rc found' };
|
|
152
|
+
}
|
|
153
|
+
const backupDir = path.join(homedir(), '.skillfm', 'gateway-backup', new Date().toISOString().replace(/[:.]/g, '-'));
|
|
154
|
+
await fs.promises.mkdir(backupDir, { recursive: true, mode: 0o700 });
|
|
155
|
+
const backupPath = path.join(backupDir, path.basename(rcPath));
|
|
156
|
+
await fs.promises.copyFile(rcPath, backupPath);
|
|
157
|
+
const block = [
|
|
158
|
+
'',
|
|
159
|
+
'# === SkillFM Gateway (added by skillfm_setup_gateway) ===',
|
|
160
|
+
`export ANTHROPIC_BASE_URL="${SKILLFM_GATEWAY_BASE_URL}/anthropic"`,
|
|
161
|
+
`export OPENAI_API_BASE="${SKILLFM_GATEWAY_BASE_URL}/openai"`,
|
|
162
|
+
'# === SkillFM Gateway end ===',
|
|
163
|
+
'',
|
|
164
|
+
].join('\n');
|
|
165
|
+
try {
|
|
166
|
+
await fs.promises.appendFile(rcPath, block, 'utf-8');
|
|
167
|
+
return {
|
|
168
|
+
ide,
|
|
169
|
+
applied: true,
|
|
170
|
+
config_path: rcPath,
|
|
171
|
+
backup_path: backupPath,
|
|
172
|
+
revert_command: `cp "${backupPath}" "${rcPath}" && source "${rcPath}"`,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
catch (e) {
|
|
176
|
+
return { ide, applied: false, error: e.message };
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* 一键配 — 所有检测到的 IDE
|
|
181
|
+
*/
|
|
182
|
+
export async function setupAllDetectedGateways() {
|
|
183
|
+
const detections = await detectIDEs();
|
|
184
|
+
const results = [];
|
|
185
|
+
for (const d of detections) {
|
|
186
|
+
if (!d.detected)
|
|
187
|
+
continue;
|
|
188
|
+
if (d.setup_status === 'configured') {
|
|
189
|
+
results.push({ ide: d.ide, applied: false, error: 'already configured' });
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
if (d.ide === 'claude-code')
|
|
193
|
+
results.push(await setupClaudeCodeGateway());
|
|
194
|
+
else if (d.ide === 'shell-env')
|
|
195
|
+
results.push(await setupShellEnvGateway());
|
|
196
|
+
// Cursor / Codex / Aider / Continue: MVP 仅 surface 提示用户手动配 (UI 复杂)
|
|
197
|
+
}
|
|
198
|
+
return results;
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=gateway-setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway-setup.js","sourceRoot":"","sources":["../../src/save-token/gateway-setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type { EngineId, FixMethod, SaveTokenSuggestion, SaveTokenScanOptions, GatewaySetupStatus, GatewayDetection, } from './types.js';
|
|
2
|
+
export { scanE1Router } from './e1-router.js';
|
|
3
|
+
export { scanE2Cache } from './e2-cache.js';
|
|
4
|
+
export { scanE3Batch } from './e3-batch.js';
|
|
5
|
+
export { detectIDEs, setupClaudeCodeGateway, setupShellEnvGateway, setupAllDetectedGateways, SKILLFM_GATEWAY_BASE_URL, } from './gateway-setup.js';
|
|
6
|
+
export type { SetupResult } from './gateway-setup.js';
|
|
7
|
+
import type { LocalUsageStore } from '../usage-local/store.js';
|
|
8
|
+
import type { SaveTokenSuggestion, SaveTokenScanOptions } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* 跑全 engine 扫描 (E1+E2+E3 并行) — 主入口用
|
|
11
|
+
*/
|
|
12
|
+
export declare function scanAllEngines(store: LocalUsageStore, opts: SaveTokenScanOptions): Promise<SaveTokenSuggestion[]>;
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/save-token/index.ts"],"names":[],"mappings":"AAKA,YAAY,EACV,QAAQ,EACR,SAAS,EACT,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EACL,UAAU,EACV,sBAAsB,EACtB,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAK5E;;GAEG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAOhC"}
|