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.
Files changed (60) hide show
  1. package/README.md +16 -5
  2. package/bin/chainlesschain.js +0 -0
  3. package/package.json +1 -1
  4. package/src/assets/web-panel/.build-hash +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-C1AnPdMx.js → Analytics-DgypYeUB.js} +2 -2
  6. package/src/assets/web-panel/assets/AppLayout-DQyDwGut.css +1 -0
  7. package/src/assets/web-panel/assets/AppLayout-ZHpCFO_p.js +1 -0
  8. package/src/assets/web-panel/assets/{Backup-D31iZX3l.js → Backup-Ba9UybpT.js} +1 -1
  9. package/src/assets/web-panel/assets/{Chat-DiXJ3TuK.js → Chat-BwXskT21.js} +1 -1
  10. package/src/assets/web-panel/assets/{Cowork-B8ZDdRm4.js → Cowork-UmOe7qvE.js} +1 -1
  11. package/src/assets/web-panel/assets/{Cron-DBt1ueXh.js → Cron-JHS-rc-4.js} +2 -2
  12. package/src/assets/web-panel/assets/Dashboard-BS-tzGNj.css +1 -0
  13. package/src/assets/web-panel/assets/{Dashboard-jt6XPIjB.js → Dashboard-CpWz2g0n.js} +2 -2
  14. package/src/assets/web-panel/assets/{Git-hwQ1oZHj.js → Git-CSYO0_zk.js} +2 -2
  15. package/src/assets/web-panel/assets/{Logs-4D9p6PRM.js → Logs-Hxw_K0km.js} +2 -2
  16. package/src/assets/web-panel/assets/{McpTools-CyAUjbbs.js → McpTools-DIE75TrB.js} +2 -2
  17. package/src/assets/web-panel/assets/{Memory-BMqOR7S-.js → Memory-C4KVnLlp.js} +2 -2
  18. package/src/assets/web-panel/assets/{Notes-Cmas8i4E.js → Notes-DuzrHMAk.js} +2 -2
  19. package/src/assets/web-panel/assets/{Organization-DnSa58Tl.js → Organization-DTq6uF82.js} +4 -4
  20. package/src/assets/web-panel/assets/{P2P-BxksIBWs.js → P2P-C0hjlhsR.js} +2 -2
  21. package/src/assets/web-panel/assets/{Permissions-Bq5Qn2s3.js → Permissions-Ec0NH-xC.js} +4 -4
  22. package/src/assets/web-panel/assets/{Projects-B7EM0uPg.js → Projects-U8D0asCS.js} +2 -2
  23. package/src/assets/web-panel/assets/{Providers-DAwgG5KV.js → Providers-BngtTLvJ.js} +2 -2
  24. package/src/assets/web-panel/assets/{RssFeed-HSZoRXvS.js → RssFeed-B9NbwCKM.js} +3 -3
  25. package/src/assets/web-panel/assets/{Security-Cz17qBny.js → Security-BL5Rkr1T.js} +3 -3
  26. package/src/assets/web-panel/assets/{Services-D2EsLq-v.js → Services-D4MJzLld.js} +2 -2
  27. package/src/assets/web-panel/assets/{Skills-C9v-f3vZ.js → Skills-CQTOMDwF.js} +1 -1
  28. package/src/assets/web-panel/assets/{Tasks-yMEcU0n7.js → Tasks-DepbJMnL.js} +1 -1
  29. package/src/assets/web-panel/assets/{Templates-l7SvlKuB.js → Templates-C24PVZPu.js} +1 -1
  30. package/src/assets/web-panel/assets/{Wallet-BHWhLWn9.js → Wallet-PQoSpN_P.js} +3 -3
  31. package/src/assets/web-panel/assets/{WebAuthn-kWhFYaUK.js → WebAuthn-BcuyQ4Lr.js} +4 -4
  32. package/src/assets/web-panel/assets/WorkflowEditor-C-SvXbHW.js +1 -0
  33. package/src/assets/web-panel/assets/WorkflowEditor-D5bX6woe.css +1 -0
  34. package/src/assets/web-panel/assets/{antd-D6h4fDFf.js → antd-DEjZPGMj.js} +82 -82
  35. package/src/assets/web-panel/assets/index-CLmYSvow.js +2 -0
  36. package/src/assets/web-panel/assets/{markdown-BZsB-Dsv.js → markdown-CusdXFxb.js} +1 -1
  37. package/src/assets/web-panel/index.html +2 -2
  38. package/src/commands/cowork.js +213 -41
  39. package/src/gateways/ws/action-protocol.js +140 -0
  40. package/src/gateways/ws/message-dispatcher.js +5 -0
  41. package/src/gateways/ws/ws-server.js +21 -0
  42. package/src/lib/cowork-evomap-adapter.js +121 -0
  43. package/src/lib/cowork-observe-html.js +108 -0
  44. package/src/lib/cowork-observe.js +160 -0
  45. package/src/lib/cowork-share.js +114 -10
  46. package/src/lib/provider-options.js +133 -0
  47. package/src/lib/skill-loader.js +65 -0
  48. package/src/lib/sub-agent-context.js +16 -4
  49. package/src/lib/sub-agent-profiles.js +164 -0
  50. package/src/lib/todo-manager.js +108 -0
  51. package/src/lib/turn-context.js +95 -0
  52. package/src/lib/web-fetch.js +224 -0
  53. package/src/repl/agent-repl.js +4 -0
  54. package/src/runtime/agent-core.js +135 -3
  55. package/src/runtime/coding-agent-contract-shared.cjs +131 -0
  56. package/src/runtime/coding-agent-policy.cjs +30 -0
  57. package/src/assets/web-panel/assets/AppLayout-BnvARObz.js +0 -1
  58. package/src/assets/web-panel/assets/AppLayout-cxfKLu-m.css +0 -1
  59. package/src/assets/web-panel/assets/Dashboard-CKeMmCoT.css +0 -1
  60. 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(/&nbsp;/g, " ")
99
+ .replace(/&amp;/g, "&")
100
+ .replace(/&lt;/g, "<")
101
+ .replace(/&gt;/g, ">")
102
+ .replace(/&quot;/g, '"')
103
+ .replace(/&#39;/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 };
@@ -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(args.command, shellPolicyOpts);
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 { role, task, context: inheritedContext, tools: allowedTools } = args;
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
- const result = await llmCall(messages, options);
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};