chainlesschain 0.46.0 → 0.47.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -5
- package/bin/chainlesschain.js +0 -0
- package/package.json +1 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{Analytics-C1AnPdMx.js → Analytics-DgypYeUB.js} +2 -2
- package/src/assets/web-panel/assets/AppLayout-DQyDwGut.css +1 -0
- package/src/assets/web-panel/assets/AppLayout-ZHpCFO_p.js +1 -0
- package/src/assets/web-panel/assets/{Backup-D31iZX3l.js → Backup-Ba9UybpT.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-DiXJ3TuK.js → Chat-BwXskT21.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-B8ZDdRm4.js → Cowork-UmOe7qvE.js} +1 -1
- package/src/assets/web-panel/assets/{Cron-DBt1ueXh.js → Cron-JHS-rc-4.js} +2 -2
- package/src/assets/web-panel/assets/Dashboard-BS-tzGNj.css +1 -0
- package/src/assets/web-panel/assets/{Dashboard-jt6XPIjB.js → Dashboard-CpWz2g0n.js} +2 -2
- package/src/assets/web-panel/assets/{Git-hwQ1oZHj.js → Git-CSYO0_zk.js} +2 -2
- package/src/assets/web-panel/assets/{Logs-4D9p6PRM.js → Logs-Hxw_K0km.js} +2 -2
- package/src/assets/web-panel/assets/{McpTools-CyAUjbbs.js → McpTools-DIE75TrB.js} +2 -2
- package/src/assets/web-panel/assets/{Memory-BMqOR7S-.js → Memory-C4KVnLlp.js} +2 -2
- package/src/assets/web-panel/assets/{Notes-Cmas8i4E.js → Notes-DuzrHMAk.js} +2 -2
- package/src/assets/web-panel/assets/{Organization-DnSa58Tl.js → Organization-DTq6uF82.js} +4 -4
- package/src/assets/web-panel/assets/{P2P-BxksIBWs.js → P2P-C0hjlhsR.js} +2 -2
- package/src/assets/web-panel/assets/{Permissions-Bq5Qn2s3.js → Permissions-Ec0NH-xC.js} +4 -4
- package/src/assets/web-panel/assets/{Projects-B7EM0uPg.js → Projects-U8D0asCS.js} +2 -2
- package/src/assets/web-panel/assets/{Providers-DAwgG5KV.js → Providers-BngtTLvJ.js} +2 -2
- package/src/assets/web-panel/assets/{RssFeed-HSZoRXvS.js → RssFeed-B9NbwCKM.js} +3 -3
- package/src/assets/web-panel/assets/{Security-Cz17qBny.js → Security-BL5Rkr1T.js} +3 -3
- package/src/assets/web-panel/assets/{Services-D2EsLq-v.js → Services-D4MJzLld.js} +2 -2
- package/src/assets/web-panel/assets/{Skills-C9v-f3vZ.js → Skills-CQTOMDwF.js} +1 -1
- package/src/assets/web-panel/assets/{Tasks-yMEcU0n7.js → Tasks-DepbJMnL.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-l7SvlKuB.js → Templates-C24PVZPu.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BHWhLWn9.js → Wallet-PQoSpN_P.js} +3 -3
- package/src/assets/web-panel/assets/{WebAuthn-kWhFYaUK.js → WebAuthn-BcuyQ4Lr.js} +4 -4
- package/src/assets/web-panel/assets/WorkflowEditor-C-SvXbHW.js +1 -0
- package/src/assets/web-panel/assets/WorkflowEditor-D5bX6woe.css +1 -0
- package/src/assets/web-panel/assets/{antd-D6h4fDFf.js → antd-DEjZPGMj.js} +82 -82
- package/src/assets/web-panel/assets/index-CLmYSvow.js +2 -0
- package/src/assets/web-panel/assets/{markdown-BZsB-Dsv.js → markdown-CusdXFxb.js} +1 -1
- package/src/assets/web-panel/index.html +2 -2
- package/src/commands/cowork.js +213 -41
- package/src/gateways/ws/action-protocol.js +140 -0
- package/src/gateways/ws/message-dispatcher.js +5 -0
- package/src/gateways/ws/ws-server.js +21 -0
- package/src/lib/cowork-evomap-adapter.js +121 -0
- package/src/lib/cowork-observe-html.js +108 -0
- package/src/lib/cowork-observe.js +160 -0
- package/src/lib/cowork-share.js +114 -10
- package/src/lib/provider-options.js +133 -0
- package/src/lib/skill-loader.js +65 -0
- package/src/lib/sub-agent-context.js +16 -4
- package/src/lib/sub-agent-profiles.js +164 -0
- package/src/lib/todo-manager.js +108 -0
- package/src/lib/turn-context.js +95 -0
- package/src/lib/web-fetch.js +224 -0
- package/src/repl/agent-repl.js +4 -0
- package/src/runtime/agent-core.js +135 -3
- package/src/runtime/coding-agent-contract-shared.cjs +131 -0
- package/src/runtime/coding-agent-policy.cjs +30 -0
- package/src/assets/web-panel/assets/AppLayout-BnvARObz.js +0 -1
- package/src/assets/web-panel/assets/AppLayout-cxfKLu-m.css +0 -1
- package/src/assets/web-panel/assets/Dashboard-CKeMmCoT.css +0 -1
- package/src/assets/web-panel/assets/index-C1SPm_5l.js +0 -2
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Web Fetch — agent-safe HTTP(S) GET with allowlist + size/timeout limits.
|
|
3
|
+
*
|
|
4
|
+
* Inspired by open-agents web_fetch tool. Guards against SSRF by rejecting
|
|
5
|
+
* private/loopback hosts unless explicitly allowlisted.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import http from "http";
|
|
9
|
+
import https from "https";
|
|
10
|
+
import { URL } from "url";
|
|
11
|
+
|
|
12
|
+
const DEFAULT_MAX_BYTES = 2_000_000;
|
|
13
|
+
const DEFAULT_TIMEOUT_MS = 15_000;
|
|
14
|
+
|
|
15
|
+
// RFC 1918 + loopback + link-local. Blocked by default unless config.allowPrivateHosts.
|
|
16
|
+
const PRIVATE_HOST_PATTERNS = [
|
|
17
|
+
/^127\./,
|
|
18
|
+
/^10\./,
|
|
19
|
+
/^192\.168\./,
|
|
20
|
+
/^172\.(1[6-9]|2\d|3[01])\./,
|
|
21
|
+
/^169\.254\./,
|
|
22
|
+
/^0\.0\.0\.0$/,
|
|
23
|
+
/^::1$/,
|
|
24
|
+
/^localhost$/i,
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
export function isPrivateHost(host) {
|
|
28
|
+
if (!host) return true;
|
|
29
|
+
return PRIVATE_HOST_PATTERNS.some((re) => re.test(host));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function checkAllowed(urlStr, config = {}) {
|
|
33
|
+
let parsed;
|
|
34
|
+
try {
|
|
35
|
+
parsed = new URL(urlStr);
|
|
36
|
+
} catch {
|
|
37
|
+
return { allowed: false, reason: "invalid URL" };
|
|
38
|
+
}
|
|
39
|
+
if (!/^https?:$/.test(parsed.protocol)) {
|
|
40
|
+
return {
|
|
41
|
+
allowed: false,
|
|
42
|
+
reason: `unsupported protocol: ${parsed.protocol}`,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (isPrivateHost(parsed.hostname) && !config.allowPrivateHosts) {
|
|
46
|
+
return {
|
|
47
|
+
allowed: false,
|
|
48
|
+
reason: `private/loopback host blocked: ${parsed.hostname}`,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const allowed = Array.isArray(config.allowedDomains)
|
|
52
|
+
? config.allowedDomains
|
|
53
|
+
: ["*"];
|
|
54
|
+
if (!allowed.includes("*")) {
|
|
55
|
+
const match = allowed.some((pattern) => {
|
|
56
|
+
if (pattern.startsWith("*.")) {
|
|
57
|
+
return parsed.hostname.endsWith(pattern.slice(1));
|
|
58
|
+
}
|
|
59
|
+
return parsed.hostname === pattern;
|
|
60
|
+
});
|
|
61
|
+
if (!match) {
|
|
62
|
+
return {
|
|
63
|
+
allowed: false,
|
|
64
|
+
reason: `host not in allowedDomains: ${parsed.hostname}`,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return { allowed: true, url: parsed };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function htmlToMarkdown(html) {
|
|
72
|
+
if (!html) return "";
|
|
73
|
+
let text = String(html);
|
|
74
|
+
// Strip scripts/styles entirely
|
|
75
|
+
text = text.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "");
|
|
76
|
+
text = text.replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, "");
|
|
77
|
+
text = text.replace(/<!--[\s\S]*?-->/g, "");
|
|
78
|
+
// Convert headings
|
|
79
|
+
text = text.replace(/<h([1-6])[^>]*>([\s\S]*?)<\/h\1>/gi, (_, n, inner) => {
|
|
80
|
+
return `\n\n${"#".repeat(Number(n))} ${inner.trim()}\n\n`;
|
|
81
|
+
});
|
|
82
|
+
// Paragraphs / breaks
|
|
83
|
+
text = text.replace(/<br\s*\/?>/gi, "\n");
|
|
84
|
+
text = text.replace(/<\/p>/gi, "\n\n");
|
|
85
|
+
// Links: [text](href)
|
|
86
|
+
text = text.replace(
|
|
87
|
+
/<a\b[^>]*href=["']([^"']+)["'][^>]*>([\s\S]*?)<\/a>/gi,
|
|
88
|
+
(_, href, inner) => `[${stripTags(inner).trim()}](${href})`,
|
|
89
|
+
);
|
|
90
|
+
// List items
|
|
91
|
+
text = text.replace(/<li[^>]*>([\s\S]*?)<\/li>/gi, (_, inner) => {
|
|
92
|
+
return `- ${stripTags(inner).trim()}\n`;
|
|
93
|
+
});
|
|
94
|
+
// Strip remaining tags
|
|
95
|
+
text = stripTags(text);
|
|
96
|
+
// Decode minimal HTML entities
|
|
97
|
+
text = text
|
|
98
|
+
.replace(/ /g, " ")
|
|
99
|
+
.replace(/&/g, "&")
|
|
100
|
+
.replace(/</g, "<")
|
|
101
|
+
.replace(/>/g, ">")
|
|
102
|
+
.replace(/"/g, '"')
|
|
103
|
+
.replace(/'/g, "'");
|
|
104
|
+
// Collapse whitespace
|
|
105
|
+
text = text.replace(/\n{3,}/g, "\n\n").replace(/[ \t]+/g, " ");
|
|
106
|
+
return text.trim();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function stripTags(html) {
|
|
110
|
+
return String(html).replace(/<[^>]+>/g, "");
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async function _doRequest(parsed, { maxBytes, timeout, headers }) {
|
|
114
|
+
const lib = parsed.protocol === "https:" ? https : http;
|
|
115
|
+
return new Promise((resolve, reject) => {
|
|
116
|
+
const req = lib.request(
|
|
117
|
+
{
|
|
118
|
+
method: "GET",
|
|
119
|
+
protocol: parsed.protocol,
|
|
120
|
+
hostname: parsed.hostname,
|
|
121
|
+
port: parsed.port || (parsed.protocol === "https:" ? 443 : 80),
|
|
122
|
+
path: parsed.pathname + parsed.search,
|
|
123
|
+
headers: {
|
|
124
|
+
"User-Agent": "ChainlessChain-Agent/1.0",
|
|
125
|
+
Accept: "*/*",
|
|
126
|
+
...headers,
|
|
127
|
+
},
|
|
128
|
+
timeout,
|
|
129
|
+
},
|
|
130
|
+
(res) => {
|
|
131
|
+
if (
|
|
132
|
+
res.statusCode >= 300 &&
|
|
133
|
+
res.statusCode < 400 &&
|
|
134
|
+
res.headers.location
|
|
135
|
+
) {
|
|
136
|
+
res.resume();
|
|
137
|
+
return resolve({ redirect: res.headers.location });
|
|
138
|
+
}
|
|
139
|
+
const chunks = [];
|
|
140
|
+
let size = 0;
|
|
141
|
+
res.on("data", (chunk) => {
|
|
142
|
+
size += chunk.length;
|
|
143
|
+
if (size > maxBytes) {
|
|
144
|
+
req.destroy(new Error(`response exceeds maxBytes (${maxBytes})`));
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
chunks.push(chunk);
|
|
148
|
+
});
|
|
149
|
+
res.on("end", () => {
|
|
150
|
+
resolve({
|
|
151
|
+
statusCode: res.statusCode,
|
|
152
|
+
headers: res.headers,
|
|
153
|
+
body: Buffer.concat(chunks).toString("utf8"),
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
res.on("error", reject);
|
|
157
|
+
},
|
|
158
|
+
);
|
|
159
|
+
req.on("error", reject);
|
|
160
|
+
req.on("timeout", () => req.destroy(new Error("request timeout")));
|
|
161
|
+
req.end();
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export async function webFetch(url, options = {}) {
|
|
166
|
+
const {
|
|
167
|
+
format = "markdown",
|
|
168
|
+
maxBytes = DEFAULT_MAX_BYTES,
|
|
169
|
+
timeout = DEFAULT_TIMEOUT_MS,
|
|
170
|
+
config = {},
|
|
171
|
+
headers = {},
|
|
172
|
+
maxRedirects = 3,
|
|
173
|
+
} = options;
|
|
174
|
+
|
|
175
|
+
const check = checkAllowed(url, config);
|
|
176
|
+
if (!check.allowed) {
|
|
177
|
+
return { error: `web_fetch blocked: ${check.reason}` };
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
let parsed = check.url;
|
|
181
|
+
let redirects = 0;
|
|
182
|
+
let response;
|
|
183
|
+
while (true) {
|
|
184
|
+
response = await _doRequest(parsed, { maxBytes, timeout, headers });
|
|
185
|
+
if (!response.redirect) break;
|
|
186
|
+
if (++redirects > maxRedirects) {
|
|
187
|
+
return { error: "too many redirects" };
|
|
188
|
+
}
|
|
189
|
+
const next = new URL(response.redirect, parsed);
|
|
190
|
+
const nextCheck = checkAllowed(next.toString(), config);
|
|
191
|
+
if (!nextCheck.allowed) {
|
|
192
|
+
return { error: `redirect blocked: ${nextCheck.reason}` };
|
|
193
|
+
}
|
|
194
|
+
parsed = nextCheck.url;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const { statusCode, headers: respHeaders, body } = response;
|
|
198
|
+
const contentType = String(respHeaders["content-type"] || "");
|
|
199
|
+
|
|
200
|
+
let output = body;
|
|
201
|
+
let outputFormat = format;
|
|
202
|
+
if (format === "markdown") {
|
|
203
|
+
output = /html/i.test(contentType) ? htmlToMarkdown(body) : body;
|
|
204
|
+
} else if (format === "text") {
|
|
205
|
+
output = /html/i.test(contentType) ? stripTags(body) : body;
|
|
206
|
+
} else if (format === "json") {
|
|
207
|
+
try {
|
|
208
|
+
output = JSON.parse(body);
|
|
209
|
+
} catch {
|
|
210
|
+
return { error: "response is not valid JSON", statusCode, body };
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
url: parsed.toString(),
|
|
216
|
+
statusCode,
|
|
217
|
+
contentType,
|
|
218
|
+
format: outputFormat,
|
|
219
|
+
bytes: Buffer.byteLength(body, "utf8"),
|
|
220
|
+
content: output,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export const _deps = { http, https };
|
package/src/repl/agent-repl.js
CHANGED
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
} from "../harness/jsonl-session-store.js";
|
|
40
40
|
import { storeMemory, consolidateMemory } from "../lib/hierarchical-memory.js";
|
|
41
41
|
import { CLIContextEngineering } from "../lib/cli-context-engineering.js";
|
|
42
|
+
import { defaultPrepareCall } from "../lib/turn-context.js";
|
|
42
43
|
import { createChatFn } from "../lib/cowork-adapter.js";
|
|
43
44
|
import {
|
|
44
45
|
detectTaskType,
|
|
@@ -1223,6 +1224,9 @@ export async function startAgentRepl(options = {}) {
|
|
|
1223
1224
|
apiKey,
|
|
1224
1225
|
contextEngine,
|
|
1225
1226
|
iterationBudget,
|
|
1227
|
+
sessionId,
|
|
1228
|
+
cwd: process.cwd(),
|
|
1229
|
+
prepareCall: defaultPrepareCall,
|
|
1226
1230
|
});
|
|
1227
1231
|
|
|
1228
1232
|
if (response) {
|
|
@@ -698,7 +698,10 @@ async function executeToolInner(
|
|
|
698
698
|
const shellPolicyOpts = shellPolicyOverrides
|
|
699
699
|
? { overrideRuleIds: shellPolicyOverrides }
|
|
700
700
|
: {};
|
|
701
|
-
const shellPolicy = evaluateShellCommandPolicy(
|
|
701
|
+
const shellPolicy = evaluateShellCommandPolicy(
|
|
702
|
+
args.command,
|
|
703
|
+
shellPolicyOpts,
|
|
704
|
+
);
|
|
702
705
|
const override = getRuntimeToolDescriptorByCommand(args.command);
|
|
703
706
|
if (!shellPolicy.allowed) {
|
|
704
707
|
return attachDescriptor(
|
|
@@ -784,6 +787,80 @@ async function executeToolInner(
|
|
|
784
787
|
);
|
|
785
788
|
}
|
|
786
789
|
|
|
790
|
+
case "web_fetch": {
|
|
791
|
+
try {
|
|
792
|
+
const { webFetch } = await import("../lib/web-fetch.js");
|
|
793
|
+
let webFetchConfig = {};
|
|
794
|
+
try {
|
|
795
|
+
const { loadProjectConfig: _lpc, findProjectRoot: _fpr } =
|
|
796
|
+
await import("../lib/project-detector.js");
|
|
797
|
+
const projectRoot = _fpr(cwd);
|
|
798
|
+
if (projectRoot) {
|
|
799
|
+
const cfg = _lpc(projectRoot);
|
|
800
|
+
webFetchConfig = cfg?.webFetch || {};
|
|
801
|
+
}
|
|
802
|
+
} catch (_err) {
|
|
803
|
+
// Config optional — use defaults
|
|
804
|
+
}
|
|
805
|
+
const result = await webFetch(args.url, {
|
|
806
|
+
format: args.format,
|
|
807
|
+
maxBytes: args.maxBytes,
|
|
808
|
+
timeout: args.timeout,
|
|
809
|
+
config: webFetchConfig,
|
|
810
|
+
});
|
|
811
|
+
return attachDescriptor(result);
|
|
812
|
+
} catch (err) {
|
|
813
|
+
return attachDescriptor({ error: `web_fetch failed: ${err.message}` });
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
case "todo_write": {
|
|
818
|
+
try {
|
|
819
|
+
const { writeTodos } = await import("../lib/todo-manager.js");
|
|
820
|
+
const result = writeTodos(sessionId, args.todos);
|
|
821
|
+
if (!result.success) {
|
|
822
|
+
return attachDescriptor({ error: result.error });
|
|
823
|
+
}
|
|
824
|
+
return attachDescriptor({
|
|
825
|
+
success: true,
|
|
826
|
+
count: result.count,
|
|
827
|
+
summary: result.summary,
|
|
828
|
+
});
|
|
829
|
+
} catch (err) {
|
|
830
|
+
return attachDescriptor({ error: `todo_write failed: ${err.message}` });
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
case "ask_user_question": {
|
|
835
|
+
if (!interaction || typeof interaction.askUser !== "function") {
|
|
836
|
+
return attachDescriptor({
|
|
837
|
+
error: "user_not_reachable",
|
|
838
|
+
hint: "Non-interactive context (headless/gateway). Proceed autonomously using best judgement.",
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
try {
|
|
842
|
+
const answer = await interaction.askUser({
|
|
843
|
+
question: args.question,
|
|
844
|
+
options: Array.isArray(args.options) ? args.options : null,
|
|
845
|
+
multiSelect: args.multiSelect === true,
|
|
846
|
+
timeoutMs:
|
|
847
|
+
typeof args.timeoutMs === "number" ? args.timeoutMs : 60000,
|
|
848
|
+
sessionId,
|
|
849
|
+
});
|
|
850
|
+
return attachDescriptor({ answer });
|
|
851
|
+
} catch (err) {
|
|
852
|
+
if (err && err.code === "USER_TIMEOUT") {
|
|
853
|
+
return attachDescriptor({
|
|
854
|
+
error: "user_timeout",
|
|
855
|
+
hint: "User did not respond in time. Proceed with best judgement.",
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
return attachDescriptor({
|
|
859
|
+
error: `ask_user_question failed: ${err.message}`,
|
|
860
|
+
});
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
|
|
787
864
|
case "search_sessions": {
|
|
788
865
|
try {
|
|
789
866
|
const { SessionSearchIndex } = await import("../lib/session-search.js");
|
|
@@ -1285,12 +1362,40 @@ async function _executeRunCode(args, cwd) {
|
|
|
1285
1362
|
* @returns {Promise<object>}
|
|
1286
1363
|
*/
|
|
1287
1364
|
async function _executeSpawnSubAgent(args, ctx) {
|
|
1288
|
-
const {
|
|
1365
|
+
const {
|
|
1366
|
+
role,
|
|
1367
|
+
task,
|
|
1368
|
+
context: inheritedContext,
|
|
1369
|
+
tools: explicitTools,
|
|
1370
|
+
profile: profileName,
|
|
1371
|
+
} = args;
|
|
1289
1372
|
|
|
1290
1373
|
if (!role || !task) {
|
|
1291
1374
|
return { error: "Both 'role' and 'task' are required for spawn_sub_agent" };
|
|
1292
1375
|
}
|
|
1293
1376
|
|
|
1377
|
+
// Phase 3: resolve declarative profile if requested. Explicit tools/context
|
|
1378
|
+
// override profile defaults; missing fields fall back to the profile.
|
|
1379
|
+
let profile = null;
|
|
1380
|
+
if (profileName) {
|
|
1381
|
+
try {
|
|
1382
|
+
const { getSubAgentProfile } =
|
|
1383
|
+
await import("../lib/sub-agent-profiles.js");
|
|
1384
|
+
profile = getSubAgentProfile(profileName);
|
|
1385
|
+
if (!profile) {
|
|
1386
|
+
return {
|
|
1387
|
+
error: `Unknown sub-agent profile: "${profileName}". Valid: explorer|executor|design`,
|
|
1388
|
+
};
|
|
1389
|
+
}
|
|
1390
|
+
} catch (_err) {
|
|
1391
|
+
// profile module optional — proceed without
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
const allowedTools = Array.isArray(explicitTools)
|
|
1396
|
+
? explicitTools
|
|
1397
|
+
: profile?.toolAllowlist || null;
|
|
1398
|
+
|
|
1294
1399
|
// Auto-condense parent context if caller didn't provide explicit context
|
|
1295
1400
|
let resolvedContext = inheritedContext || null;
|
|
1296
1401
|
if (!resolvedContext && Array.isArray(ctx.parentMessages)) {
|
|
@@ -1315,6 +1420,7 @@ async function _executeSpawnSubAgent(args, ctx) {
|
|
|
1315
1420
|
inheritedContext: resolvedContext,
|
|
1316
1421
|
allowedTools: allowedTools || null,
|
|
1317
1422
|
cwd: ctx.cwd,
|
|
1423
|
+
profile: profile || null,
|
|
1318
1424
|
});
|
|
1319
1425
|
|
|
1320
1426
|
const emit = (type, payload) => {
|
|
@@ -1723,7 +1829,33 @@ export async function* agentLoop(messages, options) {
|
|
|
1723
1829
|
};
|
|
1724
1830
|
}
|
|
1725
1831
|
|
|
1726
|
-
|
|
1832
|
+
// Turn-scoped context injection (open-agents prepareCall parity).
|
|
1833
|
+
// prepareCall runs fresh each iteration and returns an ephemeral
|
|
1834
|
+
// system-message supplement that is NOT persisted to messages history.
|
|
1835
|
+
let callMessages = messages;
|
|
1836
|
+
if (typeof options.prepareCall === "function") {
|
|
1837
|
+
try {
|
|
1838
|
+
const hook = await options.prepareCall({
|
|
1839
|
+
iteration: budget.consumed,
|
|
1840
|
+
cwd: toolContext.cwd,
|
|
1841
|
+
sessionId: toolContext.sessionId,
|
|
1842
|
+
});
|
|
1843
|
+
if (
|
|
1844
|
+
hook &&
|
|
1845
|
+
typeof hook.systemSuffix === "string" &&
|
|
1846
|
+
hook.systemSuffix
|
|
1847
|
+
) {
|
|
1848
|
+
callMessages = [
|
|
1849
|
+
...messages,
|
|
1850
|
+
{ role: "system", content: hook.systemSuffix },
|
|
1851
|
+
];
|
|
1852
|
+
}
|
|
1853
|
+
} catch (_e) {
|
|
1854
|
+
// prepareCall failures are non-critical — proceed with original messages
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
const result = await llmCall(callMessages, options);
|
|
1727
1859
|
throwIfAborted(signal);
|
|
1728
1860
|
const msg = result?.message;
|
|
1729
1861
|
|
|
@@ -390,6 +390,12 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
|
|
|
390
390
|
description:
|
|
391
391
|
'Optional tool whitelist for the sub-agent (e.g. ["read_file", "search_files"]). If omitted, all tools are available.',
|
|
392
392
|
},
|
|
393
|
+
profile: {
|
|
394
|
+
type: "string",
|
|
395
|
+
enum: ["explorer", "executor", "design"],
|
|
396
|
+
description:
|
|
397
|
+
"Optional declarative profile (from sub-agent-profiles). When set, seeds systemPrompt / tool allowlist / iteration cap. Explicit `tools` overrides the profile allowlist.",
|
|
398
|
+
},
|
|
393
399
|
},
|
|
394
400
|
required: ["role", "task"],
|
|
395
401
|
},
|
|
@@ -403,6 +409,131 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
|
|
|
403
409
|
tags: ["tool:spawn_sub_agent", "contract:coding-agent", "tier:extension"],
|
|
404
410
|
},
|
|
405
411
|
},
|
|
412
|
+
{
|
|
413
|
+
name: "web_fetch",
|
|
414
|
+
title: "Web Fetch",
|
|
415
|
+
kind: "network",
|
|
416
|
+
tier: "extension",
|
|
417
|
+
description:
|
|
418
|
+
"Fetch a web page or API endpoint over HTTP(S). Returns extracted markdown text by default. Honors allowlist from .chainlesschain/config.json:webFetch.",
|
|
419
|
+
inputSchema: {
|
|
420
|
+
type: "object",
|
|
421
|
+
properties: {
|
|
422
|
+
url: {
|
|
423
|
+
type: "string",
|
|
424
|
+
description: "Absolute http:// or https:// URL to fetch",
|
|
425
|
+
},
|
|
426
|
+
format: {
|
|
427
|
+
type: "string",
|
|
428
|
+
enum: ["markdown", "text", "html", "json"],
|
|
429
|
+
description: "Output format (default: markdown)",
|
|
430
|
+
},
|
|
431
|
+
maxBytes: {
|
|
432
|
+
type: "number",
|
|
433
|
+
description: "Maximum response size in bytes (default: 2000000)",
|
|
434
|
+
},
|
|
435
|
+
timeout: {
|
|
436
|
+
type: "number",
|
|
437
|
+
description: "Request timeout in ms (default: 15000)",
|
|
438
|
+
},
|
|
439
|
+
},
|
|
440
|
+
required: ["url"],
|
|
441
|
+
},
|
|
442
|
+
...TOOL_POLICY_METADATA.web_fetch,
|
|
443
|
+
permissions: {
|
|
444
|
+
level: "readonly",
|
|
445
|
+
scopes: ["network:read"],
|
|
446
|
+
},
|
|
447
|
+
telemetry: {
|
|
448
|
+
category: "network",
|
|
449
|
+
tags: ["tool:web_fetch", "contract:coding-agent", "tier:extension"],
|
|
450
|
+
},
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
name: "todo_write",
|
|
454
|
+
title: "Todo Write",
|
|
455
|
+
kind: "planning",
|
|
456
|
+
tier: "extension",
|
|
457
|
+
description:
|
|
458
|
+
"Write or update the session's TODO list. Use this to track multi-step work; exactly one item may be in_progress at a time.",
|
|
459
|
+
inputSchema: {
|
|
460
|
+
type: "object",
|
|
461
|
+
properties: {
|
|
462
|
+
todos: {
|
|
463
|
+
type: "array",
|
|
464
|
+
description: "Full TODO list (replaces any existing list)",
|
|
465
|
+
items: {
|
|
466
|
+
type: "object",
|
|
467
|
+
properties: {
|
|
468
|
+
id: { type: "string", description: "Stable identifier" },
|
|
469
|
+
content: { type: "string", description: "TODO description" },
|
|
470
|
+
status: {
|
|
471
|
+
type: "string",
|
|
472
|
+
enum: ["pending", "in_progress", "completed", "cancelled"],
|
|
473
|
+
description: "Item state",
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
required: ["id", "content", "status"],
|
|
477
|
+
},
|
|
478
|
+
},
|
|
479
|
+
},
|
|
480
|
+
required: ["todos"],
|
|
481
|
+
},
|
|
482
|
+
...TOOL_POLICY_METADATA.todo_write,
|
|
483
|
+
permissions: {
|
|
484
|
+
level: "session",
|
|
485
|
+
scopes: ["session:write"],
|
|
486
|
+
},
|
|
487
|
+
telemetry: {
|
|
488
|
+
category: "planning",
|
|
489
|
+
tags: ["tool:todo_write", "contract:coding-agent", "tier:extension"],
|
|
490
|
+
},
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
name: "ask_user_question",
|
|
494
|
+
title: "Ask User Question",
|
|
495
|
+
kind: "interaction",
|
|
496
|
+
tier: "extension",
|
|
497
|
+
description:
|
|
498
|
+
"Pause the agent and ask the user a structured question. In non-interactive contexts (headless, WS gateway), returns an error so the agent can proceed autonomously.",
|
|
499
|
+
inputSchema: {
|
|
500
|
+
type: "object",
|
|
501
|
+
properties: {
|
|
502
|
+
question: {
|
|
503
|
+
type: "string",
|
|
504
|
+
description: "Question to show the user",
|
|
505
|
+
},
|
|
506
|
+
options: {
|
|
507
|
+
type: "array",
|
|
508
|
+
items: { type: "string" },
|
|
509
|
+
description:
|
|
510
|
+
"Optional multiple-choice options. When provided, user picks one (or many if multiSelect=true)",
|
|
511
|
+
},
|
|
512
|
+
multiSelect: {
|
|
513
|
+
type: "boolean",
|
|
514
|
+
description: "Allow multiple selections (default: false)",
|
|
515
|
+
},
|
|
516
|
+
timeoutMs: {
|
|
517
|
+
type: "number",
|
|
518
|
+
description: "Max wait for user reply in ms (default: 60000)",
|
|
519
|
+
},
|
|
520
|
+
},
|
|
521
|
+
required: ["question"],
|
|
522
|
+
},
|
|
523
|
+
...TOOL_POLICY_METADATA.ask_user_question,
|
|
524
|
+
permissions: {
|
|
525
|
+
level: "readonly",
|
|
526
|
+
scopes: ["interaction:prompt"],
|
|
527
|
+
},
|
|
528
|
+
telemetry: {
|
|
529
|
+
category: "interaction",
|
|
530
|
+
tags: [
|
|
531
|
+
"tool:ask_user_question",
|
|
532
|
+
"contract:coding-agent",
|
|
533
|
+
"tier:extension",
|
|
534
|
+
],
|
|
535
|
+
},
|
|
536
|
+
},
|
|
406
537
|
{
|
|
407
538
|
name: "search_sessions",
|
|
408
539
|
title: "Search Sessions",
|
|
@@ -165,6 +165,36 @@ const TOOL_POLICY_METADATA = Object.freeze({
|
|
|
165
165
|
approvalFlow: "policy",
|
|
166
166
|
isReadOnly: false,
|
|
167
167
|
},
|
|
168
|
+
web_fetch: {
|
|
169
|
+
riskLevel: RISK_LEVELS.MEDIUM,
|
|
170
|
+
category: TOOL_CATEGORIES.READ,
|
|
171
|
+
availableInPlanMode: true,
|
|
172
|
+
planModeBehavior: "allow",
|
|
173
|
+
requiresPlanApproval: false,
|
|
174
|
+
requiresConfirmation: false,
|
|
175
|
+
approvalFlow: "auto",
|
|
176
|
+
isReadOnly: true,
|
|
177
|
+
},
|
|
178
|
+
todo_write: {
|
|
179
|
+
riskLevel: RISK_LEVELS.LOW,
|
|
180
|
+
category: TOOL_CATEGORIES.WRITE,
|
|
181
|
+
availableInPlanMode: true,
|
|
182
|
+
planModeBehavior: "allow",
|
|
183
|
+
requiresPlanApproval: false,
|
|
184
|
+
requiresConfirmation: false,
|
|
185
|
+
approvalFlow: "auto",
|
|
186
|
+
isReadOnly: false,
|
|
187
|
+
},
|
|
188
|
+
ask_user_question: {
|
|
189
|
+
riskLevel: RISK_LEVELS.LOW,
|
|
190
|
+
category: TOOL_CATEGORIES.READ,
|
|
191
|
+
availableInPlanMode: true,
|
|
192
|
+
planModeBehavior: "allow",
|
|
193
|
+
requiresPlanApproval: false,
|
|
194
|
+
requiresConfirmation: false,
|
|
195
|
+
approvalFlow: "auto",
|
|
196
|
+
isReadOnly: true,
|
|
197
|
+
},
|
|
168
198
|
});
|
|
169
199
|
|
|
170
200
|
function normalizeGitCommand(command) {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as fe,W as f,Z as t,X as d,$ as ve,a0 as ge,Y as i,k as e,a1 as a,a2 as w,a3 as r,a4 as S,F as j,u as s,a5 as g,G as l,a6 as be,a7 as Oe,f as Ce,c as m}from"./vendor-CN0Iv_qZ.js";import{u as we}from"./ws-Dma34ig_.js";import{u as je,T as Te}from"./index-C1SPm_5l.js";import{_ as Se}from"./_plugin-vue_export-helper-DlAUqK2U.js";import{F as B,G as x,D as M,M as F,R as K,C as P,b as A,c as G,d as I,e as W,B as D,f as V,h as z,T as E,S as U,L as $,W as H,i as X,j as Y,P as Z,k as q,l as J,m as Q,n as h,o as ee,K as te,I as Be}from"./antd-D6h4fDFf.js";const xe={key:0,class:"logo-text"},Le={key:0,class:"mode-banner project"},Ne={class:"banner-info"},Re={class:"banner-name"},Me={key:1,class:"mode-banner global"},Fe=["title"],Ke={key:0,class:"footer-text"},Pe={class:"header-left"},Ae={class:"header-right"},Ge={class:"theme-switcher"},Ie=["data-theme-key","onClick"],We={__name:"AppLayout",setup(De){const oe=ve(),se=ge(),b=we(),T=je(),u=Ce(!1),y=window.__CC_CONFIG__||{},p=m(()=>y.mode==="project"),ne=m(()=>T.current),le=m(()=>T.config.vars["--menu-mode"]),L=m(()=>{const c=se.name?.toLowerCase()||"dashboard";return[{mcptools:"mcp"}[c]||c]}),O=m(()=>b.status),ae=m(()=>({connected:"success",connecting:"processing",error:"error",disconnected:"default"})[b.status]||"default"),ie=m(()=>({connected:"已连接",connecting:"连接中...",error:"连接错误",disconnected:"未连接"})[b.status]||"未知");function de(c){T.setTheme(c)}function ue({key:c}){oe.push({mcp:"/mcp"}[c]||`/${c}`)}return fe(()=>b.connect()),(c,o)=>{const n=d("a-menu-item"),k=d("a-menu-item-group"),v=d("a-menu-divider"),re=d("a-menu"),ce=d("a-badge"),pe=d("a-layout-sider"),N=d("a-tooltip"),me=d("a-tag"),ye=d("a-layout-header"),ke=d("router-view"),_e=d("a-layout-content"),R=d("a-layout");return i(),f(R,{class:"app-root"},{default:t(()=>[e(pe,{collapsed:u.value,"onUpdate:collapsed":o[1]||(o[1]=_=>u.value=_),collapsible:"","collapsed-width":56,width:216,class:"sidebar"},{default:t(()=>[a("div",{class:w(["logo",{collapsed:u.value}])},[o[2]||(o[2]=a("span",{class:"logo-icon"},"⛓",-1)),u.value?S("",!0):(i(),r("span",xe,"ChainlessChain"))],2),u.value?(i(),r("div",{key:1,class:"mode-icon-sm",title:p.value?s(y).projectName:"全局模式"},[p.value?(i(),f(s(B),{key:0,style:{color:"#1677ff"}})):(i(),f(s(x),{key:1,style:{color:"#722ed1"}}))],8,Fe)):(i(),r(j,{key:0},[p.value?(i(),r("div",Le,[e(s(B),{class:"banner-icon"}),a("div",Ne,[a("div",Re,g(s(y).projectName||"项目"),1),o[3]||(o[3]=a("div",{class:"banner-sub"},"项目级面板",-1))])])):(i(),r("div",Me,[e(s(x),{class:"banner-icon"}),o[4]||(o[4]=a("span",{class:"banner-name"},"全局模式",-1))]))],64)),e(re,{selectedKeys:L.value,"onUpdate:selectedKeys":o[0]||(o[0]=_=>L.value=_),theme:le.value,mode:"inline","inline-collapsed":u.value,class:"side-menu",onClick:ue},{default:t(()=>[u.value?(i(),r(j,{key:1},[e(n,{key:"dashboard"},{icon:t(()=>[e(s(M))]),_:1}),e(n,{key:"chat"},{icon:t(()=>[e(s(F))]),_:1}),e(n,{key:"cowork"},{icon:t(()=>[e(s(K))]),_:1}),e(n,{key:"services"},{icon:t(()=>[e(s(P))]),_:1}),e(n,{key:"logs"},{icon:t(()=>[e(s(A))]),_:1}),e(v,{class:"divider-sm"}),e(n,{key:"skills"},{icon:t(()=>[e(s(G))]),_:1}),e(n,{key:"providers"},{icon:t(()=>[e(s(I))]),_:1}),e(n,{key:"mcp"},{icon:t(()=>[e(s(W))]),_:1}),e(v,{class:"divider-sm"}),e(n,{key:"notes"},{icon:t(()=>[e(s(D))]),_:1}),e(n,{key:"memory"},{icon:t(()=>[e(s(V))]),_:1}),e(n,{key:"cron"},{icon:t(()=>[e(s(z))]),_:1}),e(n,{key:"tasks"},{icon:t(()=>[e(s(E))]),_:1}),e(v,{class:"divider-sm"}),e(n,{key:"security"},{icon:t(()=>[e(s(U))]),_:1}),e(n,{key:"permissions"},{icon:t(()=>[e(s($))]),_:1}),e(n,{key:"p2p"},{icon:t(()=>[e(s(H))]),_:1}),e(n,{key:"backup"},{icon:t(()=>[e(s(X))]),_:1}),e(n,{key:"git"},{icon:t(()=>[e(s(Y))]),_:1}),e(n,{key:"projects"},{icon:t(()=>[e(s(Z))]),_:1}),e(v,{class:"divider-sm"}),e(n,{key:"wallet"},{icon:t(()=>[e(s(q))]),_:1}),e(n,{key:"organization"},{icon:t(()=>[e(s(J))]),_:1}),e(n,{key:"analytics"},{icon:t(()=>[e(s(Q))]),_:1}),e(n,{key:"templates"},{icon:t(()=>[e(s(h))]),_:1}),e(v,{class:"divider-sm"}),e(n,{key:"rssfeed"},{icon:t(()=>[e(s(ee))]),_:1}),e(n,{key:"webauthn"},{icon:t(()=>[e(s(te))]),_:1})],64)):(i(),r(j,{key:0},[e(k,null,{title:t(()=>[...o[5]||(o[5]=[a("span",{class:"group-label"},"概 览",-1)])]),default:t(()=>[e(n,{key:"dashboard"},{icon:t(()=>[e(s(M))]),default:t(()=>[o[6]||(o[6]=l("仪表板",-1))]),_:1}),e(n,{key:"chat"},{icon:t(()=>[e(s(F))]),default:t(()=>[o[7]||(o[7]=l("AI 对话",-1))]),_:1}),e(n,{key:"cowork"},{icon:t(()=>[e(s(K))]),default:t(()=>[o[8]||(o[8]=l("日常协作",-1))]),_:1}),e(n,{key:"services"},{icon:t(()=>[e(s(P))]),default:t(()=>[o[9]||(o[9]=l("服务管理",-1))]),_:1}),e(n,{key:"logs"},{icon:t(()=>[e(s(A))]),default:t(()=>[o[10]||(o[10]=l("日志查看",-1))]),_:1})]),_:1}),e(k,null,{title:t(()=>[...o[11]||(o[11]=[a("span",{class:"group-label"},"配 置",-1)])]),default:t(()=>[e(n,{key:"skills"},{icon:t(()=>[e(s(G))]),default:t(()=>[o[12]||(o[12]=l("技能管理",-1))]),_:1}),e(n,{key:"providers"},{icon:t(()=>[e(s(I))]),default:t(()=>[o[13]||(o[13]=l("LLM 配置",-1))]),_:1}),e(n,{key:"mcp"},{icon:t(()=>[e(s(W))]),default:t(()=>[o[14]||(o[14]=l("MCP 工具",-1))]),_:1})]),_:1}),e(k,null,{title:t(()=>[...o[15]||(o[15]=[a("span",{class:"group-label"},"数 据",-1)])]),default:t(()=>[e(n,{key:"notes"},{icon:t(()=>[e(s(D))]),default:t(()=>[o[16]||(o[16]=l("笔记管理",-1))]),_:1}),e(n,{key:"memory"},{icon:t(()=>[e(s(V))]),default:t(()=>[o[17]||(o[17]=l("记忆文件",-1))]),_:1}),e(n,{key:"cron"},{icon:t(()=>[e(s(z))]),default:t(()=>[o[18]||(o[18]=l("定时任务",-1))]),_:1}),e(n,{key:"tasks"},{icon:t(()=>[e(s(E))]),default:t(()=>[o[19]||(o[19]=l("后台任务",-1))]),_:1})]),_:1}),e(k,null,{title:t(()=>[...o[20]||(o[20]=[a("span",{class:"group-label"},"高 级",-1)])]),default:t(()=>[e(n,{key:"security"},{icon:t(()=>[e(s(U))]),default:t(()=>[o[21]||(o[21]=l("安全中心",-1))]),_:1}),e(n,{key:"permissions"},{icon:t(()=>[e(s($))]),default:t(()=>[o[22]||(o[22]=l("权限管理",-1))]),_:1}),e(n,{key:"p2p"},{icon:t(()=>[e(s(H))]),default:t(()=>[o[23]||(o[23]=l("P2P 网络",-1))]),_:1}),e(n,{key:"backup"},{icon:t(()=>[e(s(X))]),default:t(()=>[o[24]||(o[24]=l("备份同步",-1))]),_:1}),e(n,{key:"git"},{icon:t(()=>[e(s(Y))]),default:t(()=>[o[25]||(o[25]=l("Git 与数据",-1))]),_:1}),e(n,{key:"projects"},{icon:t(()=>[e(s(Z))]),default:t(()=>[o[26]||(o[26]=l("项目管理",-1))]),_:1})]),_:1}),e(k,null,{title:t(()=>[...o[27]||(o[27]=[a("span",{class:"group-label"},"企 业",-1)])]),default:t(()=>[e(n,{key:"wallet"},{icon:t(()=>[e(s(q))]),default:t(()=>[o[28]||(o[28]=l("钱包管理",-1))]),_:1}),e(n,{key:"organization"},{icon:t(()=>[e(s(J))]),default:t(()=>[o[29]||(o[29]=l("组织管理",-1))]),_:1}),e(n,{key:"analytics"},{icon:t(()=>[e(s(Q))]),default:t(()=>[o[30]||(o[30]=l("使用分析",-1))]),_:1}),e(n,{key:"templates"},{icon:t(()=>[e(s(h))]),default:t(()=>[o[31]||(o[31]=l("模板中心",-1))]),_:1})]),_:1}),e(k,null,{title:t(()=>[...o[32]||(o[32]=[a("span",{class:"group-label"},"扩 展",-1)])]),default:t(()=>[e(n,{key:"rssfeed"},{icon:t(()=>[e(s(ee))]),default:t(()=>[o[33]||(o[33]=l("RSS 订阅",-1))]),_:1}),e(n,{key:"webauthn"},{icon:t(()=>[e(s(te))]),default:t(()=>[o[34]||(o[34]=l("身份认证",-1))]),_:1})]),_:1})],64))]),_:1},8,["selectedKeys","theme","inline-collapsed"]),a("div",{class:w(["sidebar-footer",{collapsed:u.value}])},[e(ce,{status:ae.value},null,8,["status"]),u.value?S("",!0):(i(),r("span",Ke,g(ie.value),1))],2)]),_:1},8,["collapsed"]),e(R,{class:"main-area"},{default:t(()=>[e(ye,{class:"app-header"},{default:t(()=>[a("div",Pe,[a("div",{class:w(["scope-tag",p.value?"project":"global"])},[(i(),f(be(p.value?s(B):s(x)))),a("span",null,g(p.value?s(y).projectName||"项目":"全局模式"),1),p.value&&s(y).projectRoot?(i(),f(N,{key:0,title:s(y).projectRoot},{default:t(()=>[e(s(Be),{class:"info-icon"})]),_:1},8,["title"])):S("",!0)],2)]),a("div",Ae,[a("div",Ge,[(i(!0),r(j,null,Oe(s(Te),(_,C)=>(i(),f(N,{key:C,title:_.label},{default:t(()=>[a("button",{class:w(["theme-btn",{active:ne.value===C}]),"data-theme-key":C,onClick:Ve=>de(C)},g(_.icon),11,Ie)]),_:2},1032,["title"]))),128))]),o[35]||(o[35]=a("span",{class:"version-tag"},"v5.0.2.9",-1)),e(me,{color:O.value==="connected"?"green":O.value==="connecting"?"orange":"red",class:"ws-tag"},{default:t(()=>[l(g(O.value==="connected"?"已连接":O.value==="connecting"?"连接中":"断开"),1)]),_:1},8,["color"])])]),_:1}),e(_e,{class:"page-content"},{default:t(()=>[e(ke)]),_:1})]),_:1})]),_:1})}}},Xe=Se(We,[["__scopeId","data-v-2d496e96"]]);export{Xe as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.app-root[data-v-2d496e96]{min-height:100vh;background:var(--bg-base)}.sidebar[data-v-2d496e96]{background:var(--bg-sidebar)!important;border-right:1px solid var(--border-color);transition:background .25s}[data-v-2d496e96] .ant-layout-sider-children{display:flex;flex-direction:column;overflow:hidden}.main-area[data-v-2d496e96]{background:var(--bg-base)}.logo[data-v-2d496e96]{height:52px;display:flex;align-items:center;padding:0 18px;gap:10px;border-bottom:1px solid var(--border-color);overflow:hidden;white-space:nowrap;flex-shrink:0}.logo.collapsed[data-v-2d496e96]{padding:0;justify-content:center}.logo-icon[data-v-2d496e96]{font-size:20px;flex-shrink:0}.logo-text[data-v-2d496e96]{color:var(--logo-text);font-weight:700;font-size:14px;letter-spacing:.01em}.mode-banner[data-v-2d496e96]{display:flex;align-items:center;gap:8px;padding:7px 10px;margin:8px 8px 4px;border-radius:7px;overflow:hidden}.mode-banner.project[data-v-2d496e96]{background:#1677ff1a;border:1px solid rgba(22,119,255,.2)}.mode-banner.global[data-v-2d496e96]{background:#722ed11a;border:1px solid rgba(114,46,209,.2)}.banner-icon[data-v-2d496e96]{font-size:13px;flex-shrink:0;color:#1677ff}.mode-banner.global .banner-icon[data-v-2d496e96]{color:#722ed1}.banner-info[data-v-2d496e96]{flex:1;min-width:0}.banner-name[data-v-2d496e96]{font-size:12px;font-weight:600;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.banner-sub[data-v-2d496e96]{font-size:10px;color:#1677ff;margin-top:1px}.mode-banner.global .banner-name[data-v-2d496e96]{color:#c084fc}.mode-icon-sm[data-v-2d496e96]{display:flex;justify-content:center;padding:8px 0;font-size:14px}.side-menu[data-v-2d496e96]{border:none!important;margin-top:2px;-webkit-user-select:none;user-select:none;background:transparent!important;flex:1;overflow-y:auto;overflow-x:hidden}.group-label[data-v-2d496e96]{color:var(--group-title);font-size:10px;font-weight:700;letter-spacing:.12em;padding-left:6px}[data-v-2d496e96] .ant-menu-item-group-title{padding:8px 16px 2px!important}[data-v-2d496e96] .ant-menu-item{height:38px!important;line-height:38px!important;margin:1px 4px!important;border-radius:6px!important}.divider-sm[data-v-2d496e96]{margin:4px 0!important}.sidebar-footer[data-v-2d496e96]{flex-shrink:0;padding:8px 18px;display:flex;align-items:center;gap:8px;border-top:1px solid var(--border-color)}.sidebar-footer.collapsed[data-v-2d496e96]{justify-content:center;padding:8px 0}.footer-text[data-v-2d496e96]{color:var(--text-secondary);font-size:11px}.app-header[data-v-2d496e96]{background:var(--bg-header)!important;padding:0 20px!important;border-bottom:1px solid var(--border-color);height:50px!important;line-height:50px!important;display:flex!important;align-items:center!important;justify-content:space-between!important;box-shadow:0 1px 4px #0000000f}.header-left[data-v-2d496e96],.header-right[data-v-2d496e96]{display:flex;align-items:center;gap:10px}.scope-tag[data-v-2d496e96]{display:flex;align-items:center;gap:5px;padding:3px 10px;border-radius:5px;font-size:12px;font-weight:500}.scope-tag.project[data-v-2d496e96]{background:#1677ff1a;color:#1677ff;border:1px solid rgba(22,119,255,.2)}.scope-tag.global[data-v-2d496e96]{background:#722ed11a;color:#722ed1;border:1px solid rgba(114,46,209,.2)}.info-icon[data-v-2d496e96]{opacity:.45;cursor:help;margin-left:2px}.theme-switcher[data-v-2d496e96]{display:flex;align-items:center;gap:4px;background:var(--bg-card);border:1px solid var(--border-color);border-radius:20px;padding:3px 6px}.theme-btn[data-v-2d496e96]{width:26px;height:26px;border:none;border-radius:50%;cursor:pointer;background:transparent;font-size:14px;line-height:1;display:flex;align-items:center;justify-content:center;transition:background .15s,transform .15s;opacity:.55}.theme-btn[data-v-2d496e96]:hover{opacity:.9;transform:scale(1.15);background:var(--bg-card-hover)}.theme-btn.active[data-v-2d496e96]{opacity:1;transform:scale(1.1);background:var(--bg-card-hover);outline:2px solid var(--text-secondary)}.version-tag[data-v-2d496e96]{color:var(--text-muted);font-size:11px}.ws-tag[data-v-2d496e96]{margin:0!important;font-size:11px}.page-content[data-v-2d496e96]{padding:24px;overflow:auto;background:var(--bg-base);min-height:calc(100vh - 50px)}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.stat-card[data-v-c2d8ed1e]{background:var(--bg-card)!important;border-color:var(--border-color)!important;transition:border-color .2s}.stat-card[data-v-c2d8ed1e]:hover{border-color:var(--text-muted)!important}.stat-header[data-v-c2d8ed1e]{display:flex;justify-content:space-between;align-items:center;margin-bottom:6px}.stat-label[data-v-c2d8ed1e]{color:var(--text-secondary);font-size:12px}.stat-value[data-v-c2d8ed1e]{font-size:22px;font-weight:600;line-height:1.2;margin-bottom:4px}.stat-sub[data-v-c2d8ed1e]{color:var(--text-muted);font-size:11px}.gateway-card[data-v-c2d8ed1e]{border-left:3px solid #1677ff!important}.status-log[data-v-c2d8ed1e]{background:var(--bg-base);border:1px solid var(--border-color);border-radius:6px;padding:10px 14px;color:var(--text-secondary);font-size:11px;font-family:Consolas,monospace;max-height:200px;overflow-y:auto;white-space:pre-wrap;margin:0;line-height:1.6}.telemetry-card[data-v-c2d8ed1e]{background:var(--bg-base);border:1px solid var(--border-color);border-radius:8px;padding:14px;height:100%}.telemetry-filter[data-v-c2d8ed1e]{display:flex;flex-direction:column;gap:6px}.telemetry-filter-label[data-v-c2d8ed1e]{color:var(--text-muted);font-size:12px}.telemetry-label[data-v-c2d8ed1e]{color:var(--text-muted);font-size:12px;margin-bottom:6px}.telemetry-value[data-v-c2d8ed1e]{color:#91caff;font-size:24px;font-weight:600;line-height:1.2}.telemetry-sub[data-v-c2d8ed1e]{color:var(--text-secondary);font-size:11px;margin-top:4px}.telemetry-section[data-v-c2d8ed1e]{background:var(--bg-base);border:1px solid var(--border-color);border-radius:8px;padding:14px;min-height:140px}.telemetry-section-title[data-v-c2d8ed1e]{color:var(--text-secondary);font-size:12px;margin-bottom:10px}.telemetry-list[data-v-c2d8ed1e]{display:flex;flex-direction:column;gap:8px}.telemetry-row[data-v-c2d8ed1e]{display:flex;justify-content:space-between;gap:12px;color:var(--text-secondary);font-size:12px}.telemetry-empty[data-v-c2d8ed1e]{color:var(--text-muted);font-size:12px}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./AppLayout-BnvARObz.js","./vendor-CN0Iv_qZ.js","./ws-Dma34ig_.js","./_plugin-vue_export-helper-DlAUqK2U.js","./antd-D6h4fDFf.js","./AppLayout-cxfKLu-m.css","./Dashboard-jt6XPIjB.js","./chat-BYmuDvol.js","./Dashboard-CKeMmCoT.css","./Chat-DiXJ3TuK.js","./markdown-BZsB-Dsv.js","./Chat-DfR76jyX.css","./github-dark-Dfs9RUU9.css","./Cowork-B8ZDdRm4.js","./Cowork-CXuhlHew.css","./Services-D2EsLq-v.js","./Services-C8Qs6KXv.css","./Logs-4D9p6PRM.js","./Logs-Gf_Mv9Nx.css","./Skills-C9v-f3vZ.js","./parsers-DftYMnlk.js","./Skills-BdjRyorN.css","./Providers-DAwgG5KV.js","./Providers-BEakqcO5.css","./McpTools-CyAUjbbs.js","./McpTools-CyhSLDwf.css","./Notes-Cmas8i4E.js","./Notes-BG69sJKi.css","./Memory-BMqOR7S-.js","./Memory-DRghrGJr.css","./Cron-DBt1ueXh.js","./Tasks-yMEcU0n7.js","./Tasks-BJjN_YEm.css","./Security-Cz17qBny.js","./Security-Dwxw7rfP.css","./Permissions-Bq5Qn2s3.js","./Permissions-C9WlkGl-.css","./P2P-BxksIBWs.js","./P2P-OEzOeMZX.css","./Git-hwQ1oZHj.js","./Git-DGcuBXST.css","./Projects-B7EM0uPg.js","./Projects-DxKelI5h.css","./Wallet-BHWhLWn9.js","./Wallet-DnIumafl.css","./Organization-DnSa58Tl.js","./Organization-DdOOM4ic.css","./Analytics-C1AnPdMx.js","./Analytics-B4OM8S8X.css","./Templates-l7SvlKuB.js","./Templates-DOY_oZnm.css","./Backup-D31iZX3l.js","./Backup-fZqtfC1m.css","./RssFeed-HSZoRXvS.js","./RssFeed-BlFC20eg.css","./WebAuthn-kWhFYaUK.js","./WebAuthn-CNPl2VQR.css"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{S as B,U as L,V as I,f as T,c as E,o as R,W as O,u as k,X as y,Y as V,Z as x,k as D,R as S,_ as w}from"./vendor-CN0Iv_qZ.js";import{a as g,A as M}from"./antd-D6h4fDFf.js";(function(){const a=document.createElement("link").relList;if(a&&a.supports&&a.supports("modulepreload"))return;for(const t of document.querySelectorAll('link[rel="modulepreload"]'))m(t);new MutationObserver(t=>{for(const o of t)if(o.type==="childList")for(const n of o.addedNodes)n.tagName==="LINK"&&n.rel==="modulepreload"&&m(n)}).observe(document,{childList:!0,subtree:!0});function c(t){const o={};return t.integrity&&(o.integrity=t.integrity),t.referrerPolicy&&(o.referrerPolicy=t.referrerPolicy),t.crossOrigin==="use-credentials"?o.credentials="include":t.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function m(t){if(t.ep)return;t.ep=!0;const o=c(t);fetch(t.href,o)}})();const C="modulepreload",N=function(s,a){return new URL(s,a).href},P={},e=function(a,c,m){let t=Promise.resolve();if(c&&c.length>0){let b=function(i){return Promise.all(i.map(d=>Promise.resolve(d).then(p=>({status:"fulfilled",value:p}),p=>({status:"rejected",reason:p}))))};const n=document.getElementsByTagName("link"),r=document.querySelector("meta[property=csp-nonce]"),u=r?.nonce||r?.getAttribute("nonce");t=b(c.map(i=>{if(i=N(i,m),i in P)return;P[i]=!0;const d=i.endsWith(".css"),p=d?'[rel="stylesheet"]':"";if(m)for(let f=n.length-1;f>=0;f--){const _=n[f];if(_.href===i&&(!d||_.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${i}"]${p}`))return;const l=document.createElement("link");if(l.rel=d?"stylesheet":C,d||(l.as="script"),l.crossOrigin="",l.href=i,u&&l.setAttribute("nonce",u),document.head.appendChild(l),d)return new Promise((f,_)=>{l.addEventListener("load",f),l.addEventListener("error",()=>_(new Error(`Unable to preload CSS for ${i}`)))})}))}function o(n){const r=new Event("vite:preloadError",{cancelable:!0});if(r.payload=n,window.dispatchEvent(r),!r.defaultPrevented)throw n}return t.then(n=>{for(const r of n||[])r.status==="rejected"&&o(r.reason);return a().catch(o)})},U=[{path:"/",component:()=>e(()=>import("./AppLayout-BnvARObz.js"),__vite__mapDeps([0,1,2,3,4,5]),import.meta.url),children:[{path:"",redirect:"/dashboard"},{path:"dashboard",name:"Dashboard",component:()=>e(()=>import("./Dashboard-jt6XPIjB.js"),__vite__mapDeps([6,1,2,7,3,4,8]),import.meta.url)},{path:"chat",name:"Chat",component:()=>e(()=>import("./Chat-DiXJ3TuK.js"),__vite__mapDeps([9,1,10,4,7,2,3,11,12]),import.meta.url)},{path:"cowork",name:"Cowork",component:()=>e(()=>import("./Cowork-B8ZDdRm4.js"),__vite__mapDeps([13,1,10,4,2,7,3,14,12]),import.meta.url)},{path:"services",name:"Services",component:()=>e(()=>import("./Services-D2EsLq-v.js"),__vite__mapDeps([15,2,1,3,4,16]),import.meta.url)},{path:"logs",name:"Logs",component:()=>e(()=>import("./Logs-4D9p6PRM.js"),__vite__mapDeps([17,2,1,3,4,18]),import.meta.url)},{path:"skills",name:"Skills",component:()=>e(()=>import("./Skills-C9v-f3vZ.js"),__vite__mapDeps([19,1,2,20,7,3,4,21]),import.meta.url)},{path:"providers",name:"Providers",component:()=>e(()=>import("./Providers-DAwgG5KV.js"),__vite__mapDeps([22,1,2,20,3,4,23]),import.meta.url)},{path:"mcp",name:"McpTools",component:()=>e(()=>import("./McpTools-CyAUjbbs.js"),__vite__mapDeps([24,2,1,3,4,25]),import.meta.url)},{path:"notes",name:"Notes",component:()=>e(()=>import("./Notes-Cmas8i4E.js"),__vite__mapDeps([26,2,1,3,4,27]),import.meta.url)},{path:"memory",name:"Memory",component:()=>e(()=>import("./Memory-BMqOR7S-.js"),__vite__mapDeps([28,2,1,3,4,29]),import.meta.url)},{path:"cron",name:"Cron",component:()=>e(()=>import("./Cron-DBt1ueXh.js"),__vite__mapDeps([30,2,1,4]),import.meta.url)},{path:"tasks",name:"Tasks",component:()=>e(()=>import("./Tasks-yMEcU0n7.js"),__vite__mapDeps([31,1,2,3,4,32]),import.meta.url)},{path:"security",name:"Security",component:()=>e(()=>import("./Security-Cz17qBny.js"),__vite__mapDeps([33,2,1,3,4,34]),import.meta.url)},{path:"permissions",name:"Permissions",component:()=>e(()=>import("./Permissions-Bq5Qn2s3.js"),__vite__mapDeps([35,2,1,3,4,36]),import.meta.url)},{path:"p2p",name:"P2P",component:()=>e(()=>import("./P2P-BxksIBWs.js"),__vite__mapDeps([37,2,1,3,4,38]),import.meta.url)},{path:"git",name:"Git",component:()=>e(()=>import("./Git-hwQ1oZHj.js"),__vite__mapDeps([39,2,1,3,4,40]),import.meta.url)},{path:"projects",name:"Projects",component:()=>e(()=>import("./Projects-B7EM0uPg.js"),__vite__mapDeps([41,2,1,3,4,42]),import.meta.url)},{path:"wallet",name:"Wallet",component:()=>e(()=>import("./Wallet-BHWhLWn9.js"),__vite__mapDeps([43,2,1,3,4,44]),import.meta.url)},{path:"organization",name:"Organization",component:()=>e(()=>import("./Organization-DnSa58Tl.js"),__vite__mapDeps([45,1,2,3,4,46]),import.meta.url)},{path:"analytics",name:"Analytics",component:()=>e(()=>import("./Analytics-C1AnPdMx.js"),__vite__mapDeps([47,2,1,3,4,48]),import.meta.url)},{path:"templates",name:"Templates",component:()=>e(()=>import("./Templates-l7SvlKuB.js"),__vite__mapDeps([49,1,2,3,4,50]),import.meta.url)},{path:"backup",name:"Backup",component:()=>e(()=>import("./Backup-D31iZX3l.js"),__vite__mapDeps([51,2,1,3,4,52]),import.meta.url)},{path:"rssfeed",name:"RssFeed",component:()=>e(()=>import("./RssFeed-HSZoRXvS.js"),__vite__mapDeps([53,1,2,3,4,54]),import.meta.url)},{path:"webauthn",name:"WebAuthn",component:()=>e(()=>import("./WebAuthn-kWhFYaUK.js"),__vite__mapDeps([55,2,1,3,4,56]),import.meta.url)}]}],F=B({history:L(),routes:U}),A="cc_theme",v={dark:{label:"暗黑",icon:"🌑",antd:{algorithm:g.darkAlgorithm,token:{colorPrimary:"#1677ff",colorBgBase:"#141414",colorBgContainer:"#1f1f1f",colorBgElevated:"#2a2a2a",borderRadius:8,fontFamily:'system-ui, -apple-system, "Segoe UI", sans-serif'},components:{Layout:{siderBg:"#1c1c1c",headerBg:"#1c1c1c",bodyBg:"#141414"},Menu:{darkItemBg:"#1c1c1c",darkSubMenuItemBg:"#171717"}}},vars:{"--bg-base":"#141414","--bg-sidebar":"#1c1c1c","--bg-header":"#1c1c1c","--bg-card":"#1f1f1f","--bg-card-hover":"#262626","--border-color":"#252525","--border-subtle":"#1e1e1e","--text-primary":"#e0e0e0","--text-secondary":"#888","--text-muted":"#444","--logo-text":"#ffffff","--menu-mode":"dark","--shadow-card":"0 2px 8px rgba(0,0,0,.45)","--group-title":"#3a3a3a"}},light:{label:"亮白",icon:"☀️",antd:{algorithm:g.defaultAlgorithm,token:{colorPrimary:"#1677ff",colorBgBase:"#ffffff",colorBgContainer:"#ffffff",colorBgElevated:"#ffffff",borderRadius:8,fontFamily:'system-ui, -apple-system, "Segoe UI", sans-serif'},components:{Layout:{siderBg:"#ffffff",headerBg:"#ffffff",bodyBg:"#f4f6fb"},Menu:{itemBg:"#ffffff"}}},vars:{"--bg-base":"#f4f6fb","--bg-sidebar":"#ffffff","--bg-header":"#ffffff","--bg-card":"#ffffff","--bg-card-hover":"#f0f4ff","--border-color":"#e8edf5","--border-subtle":"#f0f0f0","--text-primary":"#1a1a2e","--text-secondary":"#5a6474","--text-muted":"#b0b8c8","--logo-text":"#1a1a2e","--menu-mode":"light","--shadow-card":"0 2px 12px rgba(0,0,0,.07)","--group-title":"#aab0bc"}},blue:{label:"深蓝",icon:"🌊",antd:{algorithm:g.darkAlgorithm,token:{colorPrimary:"#2f80ed",colorBgBase:"#0d1117",colorBgContainer:"#161b22",colorBgElevated:"#1c2230",borderRadius:8,fontFamily:'system-ui, -apple-system, "Segoe UI", sans-serif'},components:{Layout:{siderBg:"#0f1923",headerBg:"#0f1923",bodyBg:"#0d1117"},Menu:{darkItemBg:"#0f1923",darkSubMenuItemBg:"#0b1520"}}},vars:{"--bg-base":"#0d1117","--bg-sidebar":"#0f1923","--bg-header":"#0f1923","--bg-card":"#161b22","--bg-card-hover":"#1c2230","--border-color":"#21303f","--border-subtle":"#182030","--text-primary":"#c9d8ef","--text-secondary":"#6e8caa","--text-muted":"#2d4060","--logo-text":"#e0eeff","--menu-mode":"dark","--shadow-card":"0 2px 8px rgba(0,40,80,.5)","--group-title":"#2d4060"}},green:{label:"翠绿",icon:"🌿",antd:{algorithm:g.darkAlgorithm,token:{colorPrimary:"#29a270",colorBgBase:"#0a1a12",colorBgContainer:"#0f2318",colorBgElevated:"#152e20",borderRadius:8,fontFamily:'system-ui, -apple-system, "Segoe UI", sans-serif'},components:{Layout:{siderBg:"#0c1e14",headerBg:"#0c1e14",bodyBg:"#0a1a12"},Menu:{darkItemBg:"#0c1e14",darkSubMenuItemBg:"#091810"}}},vars:{"--bg-base":"#0a1a12","--bg-sidebar":"#0c1e14","--bg-header":"#0c1e14","--bg-card":"#0f2318","--bg-card-hover":"#152e20","--border-color":"#1a3828","--border-subtle":"#122a1c","--text-primary":"#c0e8c8","--text-secondary":"#5a9a6a","--text-muted":"#1e4028","--logo-text":"#d8f0e0","--menu-mode":"dark","--shadow-card":"0 2px 8px rgba(0,40,20,.5)","--group-title":"#1e4028"}}},j=I("theme",()=>{const s=T(localStorage.getItem(A)||"light"),a=E(()=>v[s.value]||v.dark),c=E(()=>a.value.antd),m=E(()=>s.value!=="light");function t(){const r=a.value.vars,u=document.documentElement;for(const[b,i]of Object.entries(r))u.style.setProperty(b,i);u.setAttribute("data-theme",s.value)}function o(r){v[r]&&(s.value=r,localStorage.setItem(A,r),t())}function n(){t()}return{current:s,config:a,antdTheme:c,isDark:m,setTheme:o,init:n}}),W={__name:"App",setup(s){const a=j();return R(()=>a.init()),(c,m)=>{const t=y("router-view"),o=y("a-config-provider");return V(),O(o,{theme:k(a).antdTheme},{default:x(()=>[D(t)]),_:1},8,["theme"])}}},h=S(W);h.use(w());h.use(F);h.use(M);h.mount("#app");export{v as T,j as u};
|