skyloom 1.14.6 → 1.15.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/.github/workflows/ci.yml +2 -2
- package/.github/workflows/publish.yml +74 -0
- package/CONVERSION_PLAN.md +191 -191
- package/README.md +523 -220
- package/config/default.yaml +46 -43
- package/config/models.yaml +928 -155
- package/config/providers.yaml +109 -6
- package/dist/agents/snow.d.ts +2 -0
- package/dist/agents/snow.d.ts.map +1 -1
- package/dist/agents/snow.js +36 -5
- package/dist/agents/snow.js.map +1 -1
- package/dist/cli/loom_chat.d.ts.map +1 -1
- package/dist/cli/loom_chat.js +207 -1
- package/dist/cli/loom_chat.js.map +1 -1
- package/dist/cli/main.js +190 -40
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/tui.d.ts.map +1 -1
- package/dist/cli/tui.js +6 -31
- package/dist/cli/tui.js.map +1 -1
- package/dist/core/agent.d.ts +6 -4
- package/dist/core/agent.d.ts.map +1 -1
- package/dist/core/agent.js +61 -20
- package/dist/core/agent.js.map +1 -1
- package/dist/core/catalog.d.ts.map +1 -1
- package/dist/core/catalog.js +30 -9
- package/dist/core/catalog.js.map +1 -1
- package/dist/core/commands.d.ts +110 -0
- package/dist/core/commands.d.ts.map +1 -0
- package/dist/core/commands.js +633 -0
- package/dist/core/commands.js.map +1 -0
- package/dist/core/concurrency.d.ts +38 -0
- package/dist/core/concurrency.d.ts.map +1 -0
- package/dist/core/concurrency.js +65 -0
- package/dist/core/concurrency.js.map +1 -0
- package/dist/core/factory.js +16 -16
- package/dist/core/file_checkpoint.d.ts +9 -0
- package/dist/core/file_checkpoint.d.ts.map +1 -1
- package/dist/core/file_checkpoint.js +33 -1
- package/dist/core/file_checkpoint.js.map +1 -1
- package/dist/core/llm.d.ts.map +1 -1
- package/dist/core/llm.js +66 -13
- package/dist/core/llm.js.map +1 -1
- package/dist/core/memory.js +51 -51
- package/dist/core/schemas.d.ts +16 -0
- package/dist/core/schemas.d.ts.map +1 -1
- package/dist/core/schemas.js +32 -0
- package/dist/core/schemas.js.map +1 -1
- package/dist/core/security.d.ts.map +1 -1
- package/dist/core/security.js +27 -0
- package/dist/core/security.js.map +1 -1
- package/dist/core/skymd.js +14 -14
- package/dist/core/trace.d.ts +105 -0
- package/dist/core/trace.d.ts.map +1 -0
- package/dist/core/trace.js +213 -0
- package/dist/core/trace.js.map +1 -0
- package/dist/tools/builtin.d.ts +2 -6
- package/dist/tools/builtin.d.ts.map +1 -1
- package/dist/tools/builtin.js +180 -125
- package/dist/tools/builtin.js.map +1 -1
- package/dist/tools/extra.d.ts +13 -0
- package/dist/tools/extra.d.ts.map +1 -0
- package/dist/tools/extra.js +827 -0
- package/dist/tools/extra.js.map +1 -0
- package/dist/tools/guards.d.ts +12 -0
- package/dist/tools/guards.d.ts.map +1 -0
- package/dist/tools/guards.js +143 -0
- package/dist/tools/guards.js.map +1 -0
- package/dist/tools/model_tool.d.ts.map +1 -1
- package/dist/tools/model_tool.js +24 -4
- package/dist/tools/model_tool.js.map +1 -1
- package/dist/web/markdown.d.ts +32 -0
- package/dist/web/markdown.d.ts.map +1 -0
- package/dist/web/markdown.js +202 -0
- package/dist/web/markdown.js.map +1 -0
- package/dist/web/server.d.ts +4 -0
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +14 -582
- package/dist/web/server.js.map +1 -1
- package/dist/web/ui.d.ts +31 -0
- package/dist/web/ui.d.ts.map +1 -0
- package/dist/web/ui.js +1009 -0
- package/dist/web/ui.js.map +1 -0
- package/docs/AESTHETIC_DESIGN.md +152 -152
- package/docs/OPTIMIZATION_PLAN.md +178 -178
- package/package.json +68 -68
- package/src/agents/snow.ts +38 -5
- package/src/cli/commands_md.ts +112 -112
- package/src/cli/input_macros.ts +83 -83
- package/src/cli/loom.ts +1041 -1041
- package/src/cli/loom_chat.ts +772 -603
- package/src/cli/main.ts +853 -723
- package/src/cli/tui.ts +264 -289
- package/src/core/agent/guard.ts +133 -133
- package/src/core/agent/task.ts +100 -100
- package/src/core/agent.ts +1630 -1590
- package/src/core/agent_helpers.ts +500 -500
- package/src/core/bus.ts +221 -221
- package/src/core/cache.ts +153 -153
- package/src/core/catalog.ts +199 -178
- package/src/core/circuit_breaker.ts +119 -119
- package/src/core/commands.ts +704 -0
- package/src/core/concurrency.ts +73 -0
- package/src/core/config.ts +365 -365
- package/src/core/constants.ts +95 -95
- package/src/core/factory.ts +656 -656
- package/src/core/file_checkpoint.ts +163 -136
- package/src/core/hooks.ts +126 -126
- package/src/core/llm.ts +972 -915
- package/src/core/logger.ts +143 -143
- package/src/core/mcp.ts +1001 -1001
- package/src/core/memory.ts +1201 -1201
- package/src/core/middleware.ts +350 -350
- package/src/core/model_config.ts +159 -159
- package/src/core/pipelines.ts +424 -424
- package/src/core/schemas.ts +319 -282
- package/src/core/security.ts +27 -0
- package/src/core/semantic.ts +211 -211
- package/src/core/skill.ts +384 -384
- package/src/core/skymd.ts +143 -143
- package/src/core/theme.ts +65 -65
- package/src/core/tool.ts +457 -457
- package/src/core/trace.ts +236 -0
- package/src/core/verify.ts +71 -71
- package/src/plugins/loader.ts +91 -91
- package/src/skills/loader.ts +75 -75
- package/src/tools/builtin.ts +571 -493
- package/src/tools/computer.ts +279 -279
- package/src/tools/extra.ts +662 -0
- package/src/tools/guards.ts +82 -0
- package/src/tools/model_tool.ts +93 -74
- package/src/tools/todo.ts +76 -76
- package/src/web/markdown.ts +193 -0
- package/src/web/server.ts +117 -693
- package/src/web/ui.ts +949 -0
- package/tests/agent.test.ts +211 -159
- package/tests/agent_helpers.test.ts +48 -48
- package/tests/catalog.test.ts +86 -86
- package/tests/checkpoint_commands.test.ts +124 -124
- package/tests/claude_compat.test.ts +110 -110
- package/tests/commands.test.ts +103 -0
- package/tests/concurrency.test.ts +102 -0
- package/tests/config.test.ts +41 -41
- package/tests/extra_tools.test.ts +212 -0
- package/tests/fence_plugin.test.ts +52 -52
- package/tests/guard.test.ts +75 -75
- package/tests/loom.test.ts +337 -337
- package/tests/memory.test.ts +170 -170
- package/tests/model_config.test.ts +109 -109
- package/tests/skymd.test.ts +146 -146
- package/tests/ssrf.test.ts +38 -38
- package/tests/structured_retry.test.ts +87 -0
- package/tests/task.test.ts +60 -60
- package/tests/todo_toolstats.test.ts +94 -94
- package/tests/trace.test.ts +128 -0
- package/tests/tui.test.ts +67 -67
- package/tests/web.test.ts +169 -0
- package/tsconfig.json +38 -38
package/config/providers.yaml
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
# Provider catalog — API key env vars, base URLs, docs
|
|
2
|
+
# All providers use OpenAI-compatible API format unless noted.
|
|
3
|
+
|
|
4
|
+
# ═══════════════════════════════════════════
|
|
5
|
+
# Major International Providers
|
|
6
|
+
# ═══════════════════════════════════════════
|
|
2
7
|
openai:
|
|
3
8
|
env_var: OPENAI_API_KEY
|
|
4
9
|
base_url: https://api.openai.com/v1
|
|
@@ -9,31 +14,129 @@ anthropic:
|
|
|
9
14
|
base_url: https://api.anthropic.com/v1
|
|
10
15
|
docs_url: https://console.anthropic.com/settings/keys
|
|
11
16
|
|
|
17
|
+
google:
|
|
18
|
+
env_var: GEMINI_API_KEY
|
|
19
|
+
base_url: https://generativelanguage.googleapis.com/v1beta
|
|
20
|
+
docs_url: https://aistudio.google.com/app/apikey
|
|
21
|
+
|
|
12
22
|
deepseek:
|
|
13
23
|
env_var: DEEPSEEK_API_KEY
|
|
14
24
|
base_url: https://api.deepseek.com/v1
|
|
15
25
|
docs_url: https://platform.deepseek.com/api_keys
|
|
16
26
|
|
|
17
|
-
|
|
18
|
-
env_var:
|
|
19
|
-
base_url: https://api.
|
|
27
|
+
xai:
|
|
28
|
+
env_var: XAI_API_KEY
|
|
29
|
+
base_url: https://api.x.ai/v1
|
|
30
|
+
docs_url: https://console.x.ai/
|
|
20
31
|
|
|
21
32
|
mistral:
|
|
22
33
|
env_var: MISTRAL_API_KEY
|
|
23
34
|
base_url: https://api.mistral.ai/v1
|
|
35
|
+
docs_url: https://console.mistral.ai/api-keys/
|
|
36
|
+
|
|
37
|
+
groq:
|
|
38
|
+
env_var: GROQ_API_KEY
|
|
39
|
+
base_url: https://api.groq.com/openai/v1
|
|
40
|
+
docs_url: https://console.groq.com/keys
|
|
24
41
|
|
|
25
42
|
cohere:
|
|
26
43
|
env_var: COHERE_API_KEY
|
|
27
44
|
base_url: https://api.cohere.ai/v1
|
|
45
|
+
docs_url: https://dashboard.cohere.com/api-keys
|
|
46
|
+
|
|
47
|
+
perplexity:
|
|
48
|
+
env_var: PERPLEXITY_API_KEY
|
|
49
|
+
base_url: https://api.perplexity.ai
|
|
50
|
+
docs_url: https://www.perplexity.ai/settings/api
|
|
51
|
+
|
|
52
|
+
fireworks:
|
|
53
|
+
env_var: FIREWORKS_API_KEY
|
|
54
|
+
base_url: https://api.fireworks.ai/inference/v1
|
|
55
|
+
docs_url: https://fireworks.ai/api-keys
|
|
56
|
+
|
|
57
|
+
together:
|
|
58
|
+
env_var: TOGETHER_API_KEY
|
|
59
|
+
base_url: https://api.together.xyz/v1
|
|
60
|
+
docs_url: https://api.together.xyz/settings/api-keys
|
|
28
61
|
|
|
29
62
|
openrouter:
|
|
30
63
|
env_var: OPENROUTER_API_KEY
|
|
31
64
|
base_url: https://openrouter.ai/api/v1
|
|
65
|
+
docs_url: https://openrouter.ai/keys
|
|
32
66
|
|
|
33
|
-
|
|
34
|
-
env_var:
|
|
35
|
-
base_url: https://
|
|
67
|
+
reka:
|
|
68
|
+
env_var: REKA_API_KEY
|
|
69
|
+
base_url: https://api.reka.ai/v1
|
|
70
|
+
docs_url: https://platform.reka.ai/api-keys
|
|
71
|
+
|
|
72
|
+
nvidia:
|
|
73
|
+
env_var: NVIDIA_API_KEY
|
|
74
|
+
base_url: https://integrate.api.nvidia.com/v1
|
|
75
|
+
docs_url: https://build.nvidia.com/explore/discover
|
|
76
|
+
|
|
77
|
+
sambanova:
|
|
78
|
+
env_var: SAMBANOVA_API_KEY
|
|
79
|
+
base_url: https://api.sambanova.ai/v1
|
|
80
|
+
docs_url: https://cloud.sambanova.ai/apis
|
|
81
|
+
|
|
82
|
+
# ═══════════════════════════════════════════
|
|
83
|
+
# Chinese Providers
|
|
84
|
+
# ═══════════════════════════════════════════
|
|
85
|
+
qwen:
|
|
86
|
+
env_var: QWEN_API_KEY
|
|
87
|
+
base_url: https://dashscope.aliyuncs.com/compatible-mode/v1
|
|
88
|
+
docs_url: https://dashscope.console.aliyun.com/apiKey
|
|
89
|
+
|
|
90
|
+
zhipu:
|
|
91
|
+
env_var: ZHIPU_API_KEY
|
|
92
|
+
base_url: https://open.bigmodel.cn/api/paas/v4
|
|
93
|
+
docs_url: https://open.bigmodel.cn/usercenter/apikeys
|
|
94
|
+
|
|
95
|
+
lingyiwanwu:
|
|
96
|
+
env_var: LINGYIWANWU_API_KEY
|
|
97
|
+
base_url: https://api.lingyiwanwu.com/v1
|
|
98
|
+
docs_url: https://platform.lingyiwanwu.com/apikeys
|
|
99
|
+
|
|
100
|
+
minimax:
|
|
101
|
+
env_var: MINIMAX_API_KEY
|
|
102
|
+
base_url: https://api.minimax.chat/v1
|
|
103
|
+
docs_url: https://platform.minimaxi.com/user-center/basic-information/interface-key
|
|
36
104
|
|
|
105
|
+
moonshot:
|
|
106
|
+
env_var: MOONSHOT_API_KEY
|
|
107
|
+
base_url: https://api.moonshot.cn/v1
|
|
108
|
+
docs_url: https://platform.moonshot.cn/console/api-keys
|
|
109
|
+
|
|
110
|
+
baidu:
|
|
111
|
+
env_var: BAIDU_API_KEY
|
|
112
|
+
base_url: https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop
|
|
113
|
+
docs_url: https://console.bce.baidu.com/qianfan/ais/console/onlineService
|
|
114
|
+
|
|
115
|
+
baichuan:
|
|
116
|
+
env_var: BAICHUAN_API_KEY
|
|
117
|
+
base_url: https://api.baichuan-ai.com/v1
|
|
118
|
+
docs_url: https://platform.baichuan-ai.com/console/apikey
|
|
119
|
+
|
|
120
|
+
stepfun:
|
|
121
|
+
env_var: STEPFUN_API_KEY
|
|
122
|
+
base_url: https://api.stepfun.com/v1
|
|
123
|
+
docs_url: https://platform.stepfun.com/interface-key
|
|
124
|
+
|
|
125
|
+
# ═══════════════════════════════════════════
|
|
126
|
+
# Local / Self-hosted
|
|
127
|
+
# ═══════════════════════════════════════════
|
|
37
128
|
ollama:
|
|
38
129
|
base_url: http://localhost:11434/v1
|
|
39
130
|
env_var: OLLAMA_HOST
|
|
131
|
+
|
|
132
|
+
lmstudio:
|
|
133
|
+
base_url: http://localhost:1234/v1
|
|
134
|
+
env_var: LMSTUDIO_HOST
|
|
135
|
+
|
|
136
|
+
vllm:
|
|
137
|
+
base_url: http://localhost:8000/v1
|
|
138
|
+
env_var: VLLM_HOST
|
|
139
|
+
|
|
140
|
+
litellm:
|
|
141
|
+
base_url: http://localhost:4000/v1
|
|
142
|
+
env_var: LITELLM_HOST
|
package/dist/agents/snow.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export declare class SnowAgent extends BaseAgent {
|
|
|
11
11
|
systemPrompt: string;
|
|
12
12
|
systemPromptEn: string;
|
|
13
13
|
orchestrate(goal: string): Promise<Task[]>;
|
|
14
|
+
/** Strict plan parse: throws on unparseable/invalid JSON or an empty plan. */
|
|
15
|
+
private parsePlanStrict;
|
|
14
16
|
private parseTaskPlan;
|
|
15
17
|
replanForMissing(goal: string, priorResults: any[], missing: string, existingIds?: Set<string>): Promise<Task[]>;
|
|
16
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"snow.d.ts","sourceRoot":"","sources":["../../src/agents/snow.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"snow.d.ts","sourceRoot":"","sources":["../../src/agents/snow.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAKhD,qBAAa,SAAU,SAAQ,SAAS;IACtC,IAAI,SAAU;IACd,WAAW,SAAO;IAClB,KAAK,SAAO;IACZ,SAAS,SAAU;IACnB,UAAU,WAAyE;IAEnF,YAAY,SAWJ;IAER,cAAc,SAQuG;IAE/G,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAyBhD,8EAA8E;IAC9E,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,aAAa;IAiBf,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;CASvH"}
|
package/dist/agents/snow.js
CHANGED
|
@@ -5,6 +5,7 @@ exports.SnowAgent = void 0;
|
|
|
5
5
|
* 雪 (Snow) — 架构规划型 Agent.
|
|
6
6
|
*/
|
|
7
7
|
const agent_1 = require("../core/agent");
|
|
8
|
+
const schemas_1 = require("../core/schemas");
|
|
8
9
|
const VALID_AGENTS = new Set(['fog', 'rain', 'frost', 'snow', 'dew']);
|
|
9
10
|
class SnowAgent extends agent_1.BaseAgent {
|
|
10
11
|
constructor() {
|
|
@@ -37,11 +38,41 @@ Do 90% yourself. When orchestrating, assign to fog/rain/frost/dew. Never assign
|
|
|
37
38
|
Like snow—silent but all-covering. Framework first, then detail. Note dependencies and risks. Prioritize and deliver.`;
|
|
38
39
|
}
|
|
39
40
|
async orchestrate(goal) {
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
const base = `请将以下目标分解为子任务,并分配给合适的 Agent。\n\n目标: ${goal}\n\n请严格按 JSON 格式输出:\n{"goal": "目标", "steps": [{"id": "1", "description": "任务", "agent": "fog|rain|frost|dew"}]}\n\n可用: fog(调研) rain(代码) frost(审查) dew(运维)。不要分配 fair。直接输出 JSON。`;
|
|
42
|
+
try {
|
|
43
|
+
// Structured-output retry: if the plan JSON is malformed, feed the parse
|
|
44
|
+
// error back and re-ask before falling back — a bad response no longer
|
|
45
|
+
// silently collapses a multi-step plan into a single task.
|
|
46
|
+
return await (0, schemas_1.parseWithRetry)(async (priorError) => {
|
|
47
|
+
const prompt = priorError
|
|
48
|
+
? `${base}\n\n[你上一次的输出无法解析:${priorError}。只输出严格合法的 JSON,不要任何额外文字、解释或 markdown 代码围栏。]`
|
|
49
|
+
: base;
|
|
50
|
+
this.memory.addMessage('user', prompt);
|
|
51
|
+
const response = await this.llmLoop();
|
|
52
|
+
this.memory.addMessage('assistant', response.content);
|
|
53
|
+
return response.content;
|
|
54
|
+
}, (raw) => this.parsePlanStrict(raw, goal), { retries: 2 });
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Every attempt failed → safe single-task fallback (prior behavior).
|
|
58
|
+
return [new agent_1.Task({ id: '1', description: goal, assignedTo: 'rain', metadata: { goal } })];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** Strict plan parse: throws on unparseable/invalid JSON or an empty plan. */
|
|
62
|
+
parsePlanStrict(content, goal) {
|
|
63
|
+
const data = (0, schemas_1.parseSchema)(content); // throws SchemaValidationError on bad JSON
|
|
64
|
+
if (data && typeof data.goal !== 'string')
|
|
65
|
+
data.goal = goal; // we already know the goal
|
|
66
|
+
const plan = (0, schemas_1.validateTaskPlan)(data); // throws on a malformed plan shape
|
|
67
|
+
const tasks = [];
|
|
68
|
+
for (const step of plan.steps) {
|
|
69
|
+
const a = VALID_AGENTS.has(String(step.agent)) ? String(step.agent) : 'rain';
|
|
70
|
+
const deps = Array.isArray(step.depends_on) ? step.depends_on : [];
|
|
71
|
+
tasks.push(new agent_1.Task({ id: String(step.id), description: step.description, assignedTo: a, dependsOn: deps, metadata: { goal } }));
|
|
72
|
+
}
|
|
73
|
+
if (!tasks.length)
|
|
74
|
+
throw new schemas_1.SchemaValidationError('plan has no steps');
|
|
75
|
+
return tasks;
|
|
45
76
|
}
|
|
46
77
|
parseTaskPlan(content, goal) {
|
|
47
78
|
try {
|
package/dist/agents/snow.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"snow.js","sourceRoot":"","sources":["../../src/agents/snow.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,yCAAgD;
|
|
1
|
+
{"version":3,"file":"snow.js","sourceRoot":"","sources":["../../src/agents/snow.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loom_chat.d.ts","sourceRoot":"","sources":["../../src/cli/loom_chat.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"loom_chat.d.ts","sourceRoot":"","sources":["../../src/cli/loom_chat.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA4PH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACpF,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACrD;AAED,wBAAsB,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAyf3F"}
|
package/dist/cli/loom_chat.js
CHANGED
|
@@ -23,6 +23,8 @@ const input_macros_1 = require("./input_macros");
|
|
|
23
23
|
const commands_md_1 = require("./commands_md");
|
|
24
24
|
const file_checkpoint_1 = require("../core/file_checkpoint");
|
|
25
25
|
const loom_1 = require("./loom");
|
|
26
|
+
const catalog_1 = require("../core/catalog");
|
|
27
|
+
const skill_1 = require("../core/skill");
|
|
26
28
|
const OK_HEX = "#3a7a6e"; // 石绿 — success
|
|
27
29
|
const ERR_HEX = "#b3342d"; // 朱砂 — failure
|
|
28
30
|
const AGENT_NAMES = ["fog", "rain", "frost", "snow", "dew", "fair"];
|
|
@@ -398,6 +400,26 @@ async function loomChat(ctx, startAgent, deps) {
|
|
|
398
400
|
ui.blank();
|
|
399
401
|
continue;
|
|
400
402
|
}
|
|
403
|
+
if (cmdL === "/trace") {
|
|
404
|
+
const trace = agent.getLastTrace?.();
|
|
405
|
+
if (!trace || !trace.spans?.length) {
|
|
406
|
+
dim("本会话还没有可追踪的运行(先对话一次)");
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
const { renderTrace } = require("../core/trace");
|
|
410
|
+
const t = (0, theme_1.agentTheme)(agent.name);
|
|
411
|
+
ui.blank();
|
|
412
|
+
say(" " + chalk_1.default.bold.hex(t.hex)(`${t.symbol} 运行追踪`) + chalk_1.default.dim(` · ${trace.label}`));
|
|
413
|
+
const rendered = renderTrace(trace, {
|
|
414
|
+
dim: (s) => chalk_1.default.dim(s),
|
|
415
|
+
ok: (s) => chalk_1.default.hex(OK_HEX)(s),
|
|
416
|
+
err: (s) => chalk_1.default.hex(ERR_HEX)(s),
|
|
417
|
+
});
|
|
418
|
+
for (const ln of rendered.split("\n"))
|
|
419
|
+
ui.line(" " + ln);
|
|
420
|
+
ui.blank();
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
401
423
|
if (cmdL === "/verify") {
|
|
402
424
|
const vc = (0, verify_1.resolveVerifyConfig)(ctx.config);
|
|
403
425
|
if (!vc.commands.length) {
|
|
@@ -527,6 +549,36 @@ async function loomChat(ctx, startAgent, deps) {
|
|
|
527
549
|
dim(`⚠ ${r.provider} 还没有 API key — /apikey set ${r.provider} <key> 或 /model key <key>`);
|
|
528
550
|
continue;
|
|
529
551
|
}
|
|
552
|
+
if (cmdL === "/models" || cmdL.startsWith("/models ")) {
|
|
553
|
+
const { listProviders, modelsFor, providerLabel } = require("../core/catalog");
|
|
554
|
+
const args = inp.split(/\s+/).slice(1);
|
|
555
|
+
const filter = args[0]?.toLowerCase() || "";
|
|
556
|
+
ui.blank();
|
|
557
|
+
say(" " + chalk_1.default.bold.hex("#3a7a6e")("✦ 模型目录 · Model Catalog"));
|
|
558
|
+
dim(" ─────────────────────────────────────────────");
|
|
559
|
+
const providers = listProviders();
|
|
560
|
+
let totalModels = 0;
|
|
561
|
+
for (const p of providers) {
|
|
562
|
+
const models = modelsFor(p);
|
|
563
|
+
if (!models.length)
|
|
564
|
+
continue;
|
|
565
|
+
if (filter && !p.toLowerCase().includes(filter) && !providerLabel(p).toLowerCase().includes(filter))
|
|
566
|
+
continue;
|
|
567
|
+
const label = providerLabel(p);
|
|
568
|
+
say(" " + chalk_1.default.bold.hex("#3a7a6e")(` ${label}`));
|
|
569
|
+
for (const m of models) {
|
|
570
|
+
totalModels++;
|
|
571
|
+
const costStr = m.costIn === 0 && m.costOut === 0 ? chalk_1.default.green("免费") : chalk_1.default.dim(`$${m.costIn.toFixed(2)}/$${m.costOut.toFixed(2)}`);
|
|
572
|
+
const ctxStr = m.context >= 1000000 ? chalk_1.default.cyan(`${(m.context / 1000000).toFixed(0)}M`) : m.context >= 1000 ? chalk_1.default.cyan(`${(m.context / 1000).toFixed(0)}K`) : chalk_1.default.cyan(`${m.context}`);
|
|
573
|
+
say(` ${chalk_1.default.dim("·")} ${chalk_1.default.white(m.id.padEnd(38))} ${ctxStr} ${chalk_1.default.dim(" ")} ${costStr} ${chalk_1.default.gray(m.desc)}`);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
dim(` ────────────────────────────────────────────`);
|
|
577
|
+
dim(` 共 ${providers.length} 个 Provider · ${totalModels} 个模型`);
|
|
578
|
+
dim(" 用法: /models [provider] 筛选 · /model <id> 切换");
|
|
579
|
+
ui.blank();
|
|
580
|
+
continue;
|
|
581
|
+
}
|
|
530
582
|
if (cmdL === "/sessions") {
|
|
531
583
|
lastSessions = await agent.memory.listSessions();
|
|
532
584
|
const active = agent.memory.getActiveSession();
|
|
@@ -623,7 +675,161 @@ async function loomChat(ctx, startAgent, deps) {
|
|
|
623
675
|
dim(f);
|
|
624
676
|
continue;
|
|
625
677
|
}
|
|
626
|
-
|
|
678
|
+
if (cmdL === "/undo" || cmdL.startsWith("/undo ")) {
|
|
679
|
+
const cp = (0, file_checkpoint_1.getFileCheckpoints)();
|
|
680
|
+
const arg = inp.slice(5).trim();
|
|
681
|
+
const n = /^\d+$/.test(arg) ? parseInt(arg, 10) : 1;
|
|
682
|
+
const r = cp.rewind(n);
|
|
683
|
+
if (r.turns === 0) {
|
|
684
|
+
const turns = cp.list();
|
|
685
|
+
if (!turns.length) {
|
|
686
|
+
dim("没有可撤销的文件改动");
|
|
687
|
+
continue;
|
|
688
|
+
}
|
|
689
|
+
say(" " + chalk_1.default.bold("检查点") + chalk_1.default.dim(` · ${turns.length} 轮可撤销`));
|
|
690
|
+
for (const t of turns.slice(0, 8))
|
|
691
|
+
dim(`${t.label} · ${t.files.length} 个文件`);
|
|
692
|
+
continue;
|
|
693
|
+
}
|
|
694
|
+
say(" " + chalk_1.default.hex(OK_HEX)(`↺ 已撤销 ${r.turns} 轮`) + chalk_1.default.dim(` · 恢复 ${r.restored.length} 个文件`));
|
|
695
|
+
for (const f of r.restored.slice(0, 10))
|
|
696
|
+
dim(f);
|
|
697
|
+
continue;
|
|
698
|
+
}
|
|
699
|
+
if (cmdL === "/redo") {
|
|
700
|
+
const cp = (0, file_checkpoint_1.getFileCheckpoints)();
|
|
701
|
+
const r = cp.redo();
|
|
702
|
+
if (r.turns === 0) {
|
|
703
|
+
dim("没有可重做的操作");
|
|
704
|
+
continue;
|
|
705
|
+
}
|
|
706
|
+
say(" " + chalk_1.default.hex(OK_HEX)(`↻ 已重做 ${r.turns} 轮`) + chalk_1.default.dim(` · 恢复 ${r.restored.length} 个文件`));
|
|
707
|
+
for (const f of r.restored.slice(0, 10))
|
|
708
|
+
dim(f);
|
|
709
|
+
continue;
|
|
710
|
+
}
|
|
711
|
+
if (cmdL === "/export" || cmdL.startsWith("/export ")) {
|
|
712
|
+
const filename = inp.slice(8).trim() || `skyloom-export-${Date.now()}.md`;
|
|
713
|
+
const msgs = agent.memory.shortTerm.filter((m) => m.role !== "system");
|
|
714
|
+
let md = `# Skyloom Session Export\n\n**Agent**: ${agent.name}\n**Date**: ${new Date().toISOString()}\n**Messages**: ${msgs.length}\n\n---\n\n`;
|
|
715
|
+
for (const m of msgs) {
|
|
716
|
+
const role = m.role === "user" ? "👤 User" : `🤖 ${agent.name}`;
|
|
717
|
+
md += `## ${role}\n\n${m.content}\n\n`;
|
|
718
|
+
}
|
|
719
|
+
require("fs").writeFileSync(filename, md, "utf-8");
|
|
720
|
+
say(" " + chalk_1.default.hex(OK_HEX)(`✓ 已导出到 ${filename}`) + chalk_1.default.dim(` · ${msgs.length} 条消息`));
|
|
721
|
+
continue;
|
|
722
|
+
}
|
|
723
|
+
if (cmdL === "/thinking") {
|
|
724
|
+
const cfg = ctx.config;
|
|
725
|
+
cfg.show_thinking = !cfg.show_thinking;
|
|
726
|
+
dim(`推理过程显示 → ${cfg.show_thinking ? "开启" : "关闭"}`);
|
|
727
|
+
continue;
|
|
728
|
+
}
|
|
729
|
+
if (cmdL === "/details") {
|
|
730
|
+
const cfg = ctx.config;
|
|
731
|
+
cfg.show_tool_details = !cfg.show_tool_details;
|
|
732
|
+
dim(`工具执行详情 → ${cfg.show_tool_details ? "开启" : "关闭"}`);
|
|
733
|
+
continue;
|
|
734
|
+
}
|
|
735
|
+
if (cmdL === "/skills") {
|
|
736
|
+
const skills = skill_1.globalSkillRegistry.getSkills();
|
|
737
|
+
ui.blank();
|
|
738
|
+
say(" " + chalk_1.default.bold.hex("#3a7a6e")("✦ 技能目录 · Skills"));
|
|
739
|
+
dim(" ─────────────────────────────────────────────");
|
|
740
|
+
for (const s of skills.slice(0, 20)) {
|
|
741
|
+
say(` ${chalk_1.default.dim("·")} ${chalk_1.default.white(s.name.padEnd(24))} ${chalk_1.default.gray(s.description.slice(0, 50))}`);
|
|
742
|
+
}
|
|
743
|
+
dim(` 共 ${skills.length} 个技能 · 使用时自动激活`);
|
|
744
|
+
ui.blank();
|
|
745
|
+
continue;
|
|
746
|
+
}
|
|
747
|
+
if (cmdL === "/review" || cmdL.startsWith("/review ")) {
|
|
748
|
+
const target = inp.slice(9).trim() || "uncommitted";
|
|
749
|
+
ui.blank();
|
|
750
|
+
say(" " + chalk_1.default.bold(" 代码审查 · Code Review"));
|
|
751
|
+
dim(` 目标: ${target}`);
|
|
752
|
+
ui.blank();
|
|
753
|
+
const reviewPrompt = `Please review the code changes for ${target}. Focus on:
|
|
754
|
+
1. Code quality and best practices
|
|
755
|
+
2. Potential bugs or issues
|
|
756
|
+
3. Security concerns
|
|
757
|
+
4. Performance implications
|
|
758
|
+
5. Suggestions for improvement
|
|
759
|
+
|
|
760
|
+
Provide specific, actionable feedback.`;
|
|
761
|
+
await loomStream(ui, agent, reviewPrompt);
|
|
762
|
+
continue;
|
|
763
|
+
}
|
|
764
|
+
if (cmdL === "/connect" || cmdL.startsWith("/connect ")) {
|
|
765
|
+
const provider = inp.slice(9).trim();
|
|
766
|
+
if (!provider) {
|
|
767
|
+
ui.blank();
|
|
768
|
+
say(" " + chalk_1.default.bold("✦ 配置 Provider"));
|
|
769
|
+
dim(" 用法: /connect <provider>");
|
|
770
|
+
dim(" 示例: /connect openai");
|
|
771
|
+
ui.blank();
|
|
772
|
+
continue;
|
|
773
|
+
}
|
|
774
|
+
const meta = catalog_1.PROVIDER_META[provider.toLowerCase()];
|
|
775
|
+
if (!meta) {
|
|
776
|
+
dim(`'${provider}' 不是已知 Provider`);
|
|
777
|
+
continue;
|
|
778
|
+
}
|
|
779
|
+
ui.blank();
|
|
780
|
+
say(" " + chalk_1.default.bold.hex("#3a7a6e")(meta.name));
|
|
781
|
+
dim(` 环境变量: ${meta.envVar || "(无)"}`);
|
|
782
|
+
dim(` 设置: /apikey set ${provider} <key>`);
|
|
783
|
+
ui.blank();
|
|
784
|
+
continue;
|
|
785
|
+
}
|
|
786
|
+
if (cmdL === "/warp" || cmdL.startsWith("/warp ")) {
|
|
787
|
+
const newPath = inp.slice(6).trim();
|
|
788
|
+
if (!newPath) {
|
|
789
|
+
dim("用法: /warp <path> — 切换工作区");
|
|
790
|
+
continue;
|
|
791
|
+
}
|
|
792
|
+
const resolved = require("path").resolve(newPath);
|
|
793
|
+
if (!require("fs").existsSync(resolved)) {
|
|
794
|
+
dim(`路径不存在: ${resolved}`);
|
|
795
|
+
continue;
|
|
796
|
+
}
|
|
797
|
+
ctx.workspacePath = resolved;
|
|
798
|
+
agent.reloadProjectMemory();
|
|
799
|
+
say(" " + chalk_1.default.hex(OK_HEX)(`✓ 工作区 → ${resolved}`));
|
|
800
|
+
continue;
|
|
801
|
+
}
|
|
802
|
+
if (cmdL === "/move" || cmdL.startsWith("/move ")) {
|
|
803
|
+
const newPath = inp.slice(6).trim();
|
|
804
|
+
if (!newPath) {
|
|
805
|
+
dim("用法: /move <path> — 移动会话到项目");
|
|
806
|
+
continue;
|
|
807
|
+
}
|
|
808
|
+
const resolved = require("path").resolve(newPath);
|
|
809
|
+
if (!require("fs").existsSync(resolved)) {
|
|
810
|
+
dim(`路径不存在: ${resolved}`);
|
|
811
|
+
continue;
|
|
812
|
+
}
|
|
813
|
+
ctx.workspacePath = resolved;
|
|
814
|
+
agent.reloadProjectMemory();
|
|
815
|
+
say(" " + chalk_1.default.hex(OK_HEX)(`✓ 工作区 → ${resolved}`));
|
|
816
|
+
continue;
|
|
817
|
+
}
|
|
818
|
+
if (cmdL === "/summarize") {
|
|
819
|
+
ui.busy = true;
|
|
820
|
+
ui.busyLabel = "压缩上下文";
|
|
821
|
+
try {
|
|
822
|
+
const r = await agent.compact();
|
|
823
|
+
say(" " + chalk_1.default.hex(OK_HEX)("✓ ") + chalk_1.default.dim(String(r)));
|
|
824
|
+
}
|
|
825
|
+
catch (e) {
|
|
826
|
+
say(" " + chalk_1.default.hex(ERR_HEX)("✗ ") + chalk_1.default.dim(String(e?.message || e)));
|
|
827
|
+
}
|
|
828
|
+
ui.busy = false;
|
|
829
|
+
ui.busyLabel = "";
|
|
830
|
+
continue;
|
|
831
|
+
}
|
|
832
|
+
// ── 自定义斜杠命令 ─
|
|
627
833
|
if (inp.startsWith("/")) {
|
|
628
834
|
const hit = (0, commands_md_1.resolveCustomCommand)(inp, customCommands);
|
|
629
835
|
if (hit) {
|