chainlesschain 0.45.12 → 0.45.19

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 (78) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/assets/{AppLayout-BfLjLMsm.js → AppLayout-B00RARl2.js} +1 -1
  3. package/src/assets/web-panel/assets/{Chat-DP7PO9Li.js → Chat-DXtvKoM0.js} +1 -1
  4. package/src/assets/web-panel/assets/{Cron-DyQF-7R1.js → Cron-BJ4ODHOy.js} +1 -1
  5. package/src/assets/web-panel/assets/Dashboard-3iIpp3zd.js +3 -0
  6. package/src/assets/web-panel/assets/Dashboard-BS-tzGNj.css +1 -0
  7. package/src/assets/web-panel/assets/{Logs-BOii-AoO.js → Logs-CSeKZEG_.js} +1 -1
  8. package/src/assets/web-panel/assets/{McpTools-DmiJtJYr.js → McpTools-BYQAK11r.js} +1 -1
  9. package/src/assets/web-panel/assets/{Memory-CDRMMobU.js → Memory-gkUAPyuZ.js} +1 -1
  10. package/src/assets/web-panel/assets/{Notes-CVhqqoS1.js → Notes-bjNrQgAo.js} +1 -1
  11. package/src/assets/web-panel/assets/{Providers-Dkt7021l.js → Providers-Dbf57Tbv.js} +1 -1
  12. package/src/assets/web-panel/assets/{Services-DUDL_UGb.js → Services-CS0oMdxh.js} +1 -1
  13. package/src/assets/web-panel/assets/{Skills-DXXELJc3.js → Skills-B2fgruv8.js} +1 -1
  14. package/src/assets/web-panel/assets/Tasks-BJjN_YEm.css +1 -0
  15. package/src/assets/web-panel/assets/Tasks-qULws8pc.js +1 -0
  16. package/src/assets/web-panel/assets/chat-DnH09sSR.js +1 -0
  17. package/src/assets/web-panel/assets/{index-vW799KpE.js → index-CF2CqPYX.js} +2 -2
  18. package/src/assets/web-panel/assets/ws-DjelKkD6.js +1 -0
  19. package/src/assets/web-panel/index.html +1 -1
  20. package/src/commands/agent.js +7 -8
  21. package/src/commands/chat.js +9 -11
  22. package/src/commands/serve.js +11 -106
  23. package/src/commands/session.js +101 -0
  24. package/src/commands/ui.js +10 -151
  25. package/src/gateways/repl/agent-repl.js +1 -0
  26. package/src/gateways/repl/chat-repl.js +1 -0
  27. package/src/gateways/ui/web-ui-server.js +1 -0
  28. package/src/gateways/ws/action-protocol.js +83 -0
  29. package/src/gateways/ws/message-dispatcher.js +73 -0
  30. package/src/gateways/ws/session-protocol.js +396 -0
  31. package/src/gateways/ws/task-protocol.js +55 -0
  32. package/src/gateways/ws/worktree-protocol.js +315 -0
  33. package/src/gateways/ws/ws-server.js +4 -0
  34. package/src/gateways/ws/ws-session-gateway.js +1 -0
  35. package/src/harness/background-task-manager.js +506 -0
  36. package/src/harness/background-task-worker.js +48 -0
  37. package/src/harness/compression-telemetry.js +214 -0
  38. package/src/harness/feature-flags.js +157 -0
  39. package/src/harness/jsonl-session-store.js +452 -0
  40. package/src/harness/prompt-compressor.js +416 -0
  41. package/src/harness/worktree-isolator.js +845 -0
  42. package/src/lib/agent-core.js +246 -45
  43. package/src/lib/background-task-manager.js +1 -305
  44. package/src/lib/background-task-worker.js +1 -50
  45. package/src/lib/compression-telemetry.js +5 -0
  46. package/src/lib/feature-flags.js +7 -182
  47. package/src/lib/interaction-adapter.js +32 -6
  48. package/src/lib/jsonl-session-store.js +21 -237
  49. package/src/lib/prompt-compressor.js +10 -481
  50. package/src/lib/sub-agent-context.js +21 -1
  51. package/src/lib/worktree-isolator.js +13 -231
  52. package/src/lib/ws-agent-handler.js +1 -0
  53. package/src/lib/ws-server.js +138 -387
  54. package/src/lib/ws-session-manager.js +82 -1
  55. package/src/repl/agent-repl.js +11 -0
  56. package/src/runtime/agent-runtime.js +417 -0
  57. package/src/runtime/contracts/agent-turn.js +11 -0
  58. package/src/runtime/contracts/session-record.js +31 -0
  59. package/src/runtime/contracts/task-record.js +18 -0
  60. package/src/runtime/contracts/telemetry-record.js +23 -0
  61. package/src/runtime/contracts/worktree-record.js +14 -0
  62. package/src/runtime/index.js +13 -0
  63. package/src/runtime/policies/agent-policy.js +45 -0
  64. package/src/runtime/runtime-context.js +14 -0
  65. package/src/runtime/runtime-events.js +37 -0
  66. package/src/runtime/runtime-factory.js +50 -0
  67. package/src/tools/index.js +22 -0
  68. package/src/tools/legacy-agent-tools.js +171 -0
  69. package/src/tools/registry.js +141 -0
  70. package/src/tools/tool-context.js +28 -0
  71. package/src/tools/tool-permissions.js +28 -0
  72. package/src/tools/tool-telemetry.js +39 -0
  73. package/src/assets/web-panel/assets/Dashboard-BGGdnr6t.js +0 -3
  74. package/src/assets/web-panel/assets/Dashboard-CRFnDUFh.css +0 -1
  75. package/src/assets/web-panel/assets/Tasks-BwZ63-mq.js +0 -1
  76. package/src/assets/web-panel/assets/Tasks-Cr_XXNyQ.css +0 -1
  77. package/src/assets/web-panel/assets/chat-C_hu-qNs.js +0 -1
  78. package/src/assets/web-panel/assets/ws-DwluTqT5.js +0 -1
@@ -0,0 +1,13 @@
1
+ export { AgentRuntime } from "./agent-runtime.js";
2
+ export { createAgentRuntimeFactory } from "./runtime-factory.js";
3
+ export { createRuntimeContext } from "./runtime-context.js";
4
+ export {
5
+ RuntimeEventEmitter,
6
+ RUNTIME_EVENTS,
7
+ createRuntimeEvent,
8
+ } from "./runtime-events.js";
9
+ export { createAgentTurnRecord } from "./contracts/agent-turn.js";
10
+ export { createSessionRecord } from "./contracts/session-record.js";
11
+ export { createTaskRecord } from "./contracts/task-record.js";
12
+ export { createWorktreeRecord } from "./contracts/worktree-record.js";
13
+ export { createTelemetryRecord } from "./contracts/telemetry-record.js";
@@ -0,0 +1,45 @@
1
+ export function resolveAgentPolicy({
2
+ config = null,
3
+ overrides = {},
4
+ defaults = {},
5
+ } = {}) {
6
+ const llm = config?.llm || {};
7
+
8
+ return {
9
+ model: overrides.model || llm.model || defaults.model || "qwen2:7b",
10
+ provider:
11
+ overrides.provider || llm.provider || defaults.provider || "ollama",
12
+ baseUrl:
13
+ overrides.baseUrl !== undefined
14
+ ? overrides.baseUrl
15
+ : llm.baseUrl || defaults.baseUrl,
16
+ apiKey:
17
+ overrides.apiKey !== undefined
18
+ ? overrides.apiKey
19
+ : llm.apiKey || defaults.apiKey || null,
20
+ sessionId: overrides.sessionId || null,
21
+ };
22
+ }
23
+
24
+ export function resolveServerPolicy(overrides = {}) {
25
+ return {
26
+ port: overrides.port,
27
+ host: overrides.host,
28
+ token: overrides.token || null,
29
+ maxConnections: overrides.maxConnections,
30
+ timeout: overrides.timeout,
31
+ allowRemote: Boolean(overrides.allowRemote),
32
+ project: overrides.project || process.cwd(),
33
+ };
34
+ }
35
+
36
+ export function resolveUiPolicy(overrides = {}) {
37
+ return {
38
+ port: overrides.port,
39
+ wsPort: overrides.wsPort,
40
+ host: overrides.host,
41
+ open: overrides.open !== false,
42
+ token: overrides.token || null,
43
+ webPanelDir: overrides.webPanelDir || null,
44
+ };
45
+ }
@@ -0,0 +1,14 @@
1
+ export function createRuntimeContext({
2
+ kind,
3
+ policy,
4
+ config = null,
5
+ cwd = process.cwd(),
6
+ } = {}) {
7
+ return {
8
+ kind,
9
+ policy,
10
+ config,
11
+ cwd,
12
+ createdAt: Date.now(),
13
+ };
14
+ }
@@ -0,0 +1,37 @@
1
+ import { EventEmitter } from "node:events";
2
+
3
+ export const RUNTIME_EVENTS = {
4
+ RUNTIME_START: "runtime:start",
5
+ RUNTIME_STOP: "runtime:stop",
6
+ SESSION_START: "session:start",
7
+ SESSION_RESUME: "session:resume",
8
+ SESSION_END: "session:end",
9
+ SESSION_MESSAGE: "session:message",
10
+ TURN_START: "turn:start",
11
+ TURN_END: "turn:end",
12
+ TASK_CREATED: "task:created",
13
+ TASK_COMPLETED: "task:completed",
14
+ TASK_NOTIFICATION: "task:notification",
15
+ WORKTREE_DIFF_READY: "worktree:diff:ready",
16
+ WORKTREE_MERGED: "worktree:merge:completed",
17
+ COMPRESSION_APPLIED: "compression:applied",
18
+ COMPRESSION_SUMMARY: "compression:summary",
19
+ SERVER_START: "server:start",
20
+ SERVER_STOP: "server:stop",
21
+ ERROR: "runtime:error",
22
+ };
23
+
24
+ export function createRuntimeEvent(type, payload = {}, context = {}) {
25
+ return {
26
+ type,
27
+ toolDescriptor: payload.toolDescriptor || context.toolDescriptor || null,
28
+ toolTelemetryRecord:
29
+ payload.toolTelemetryRecord || context.toolTelemetryRecord || null,
30
+ kind: context.kind || payload.kind || null,
31
+ sessionId: context.sessionId || payload.sessionId || null,
32
+ timestamp: context.timestamp || Date.now(),
33
+ payload,
34
+ };
35
+ }
36
+
37
+ export class RuntimeEventEmitter extends EventEmitter {}
@@ -0,0 +1,50 @@
1
+ import { loadConfig } from "../lib/config-manager.js";
2
+ import { AgentRuntime } from "./agent-runtime.js";
3
+ import {
4
+ resolveAgentPolicy,
5
+ resolveServerPolicy,
6
+ resolveUiPolicy,
7
+ } from "./policies/agent-policy.js";
8
+
9
+ export function createAgentRuntimeFactory({
10
+ config = loadConfig(),
11
+ deps = {},
12
+ } = {}) {
13
+ return {
14
+ createAgentRuntime(overrides = {}) {
15
+ return new AgentRuntime({
16
+ kind: "agent",
17
+ policy: resolveAgentPolicy({ config, overrides }),
18
+ config,
19
+ deps,
20
+ });
21
+ },
22
+
23
+ createChatRuntime(overrides = {}) {
24
+ return new AgentRuntime({
25
+ kind: "chat",
26
+ policy: resolveAgentPolicy({ config, overrides }),
27
+ config,
28
+ deps,
29
+ });
30
+ },
31
+
32
+ createServerRuntime(overrides = {}) {
33
+ return new AgentRuntime({
34
+ kind: "server",
35
+ policy: resolveServerPolicy(overrides),
36
+ config,
37
+ deps,
38
+ });
39
+ },
40
+
41
+ createUiRuntime(overrides = {}) {
42
+ return new AgentRuntime({
43
+ kind: "ui",
44
+ policy: resolveUiPolicy(overrides),
45
+ config,
46
+ deps,
47
+ });
48
+ },
49
+ };
50
+ }
@@ -0,0 +1,22 @@
1
+ export {
2
+ ToolRegistry,
3
+ DEFAULT_TOOL_DESCRIPTORS,
4
+ createDefaultToolRegistry,
5
+ normalizeToolDescriptor,
6
+ } from "./registry.js";
7
+ export { createToolContext, extendToolContext } from "./tool-context.js";
8
+ export {
9
+ TOOL_PERMISSION_LEVELS,
10
+ normalizeToolPermissions,
11
+ isToolAllowed,
12
+ } from "./tool-permissions.js";
13
+ export {
14
+ createToolTelemetryRecord,
15
+ createToolTelemetryTags,
16
+ } from "./tool-telemetry.js";
17
+ export {
18
+ mapLegacyAgentToolDefinition,
19
+ createLegacyAgentToolRegistry,
20
+ listLegacyAgentToolNames,
21
+ getRuntimeToolDescriptor,
22
+ } from "./legacy-agent-tools.js";
@@ -0,0 +1,171 @@
1
+ import { ToolRegistry, createDefaultToolRegistry } from "./registry.js";
2
+
3
+ const LEGACY_TOOL_METADATA = {
4
+ read_file: {
5
+ title: "Read File",
6
+ kind: "filesystem",
7
+ permissions: {
8
+ level: "readonly",
9
+ scopes: ["filesystem:read"],
10
+ },
11
+ telemetry: {
12
+ category: "filesystem",
13
+ tags: ["tool:read_file", "legacy:agent-core"],
14
+ },
15
+ },
16
+ write_file: {
17
+ title: "Write File",
18
+ kind: "filesystem",
19
+ permissions: {
20
+ level: "elevated",
21
+ scopes: ["filesystem:write"],
22
+ },
23
+ telemetry: {
24
+ category: "filesystem",
25
+ tags: ["tool:write_file", "legacy:agent-core"],
26
+ },
27
+ },
28
+ edit_file: {
29
+ title: "Edit File",
30
+ kind: "filesystem",
31
+ permissions: {
32
+ level: "elevated",
33
+ scopes: ["filesystem:write"],
34
+ },
35
+ telemetry: {
36
+ category: "filesystem",
37
+ tags: ["tool:edit_file", "legacy:agent-core"],
38
+ },
39
+ },
40
+ run_shell: {
41
+ title: "Run Shell",
42
+ kind: "shell",
43
+ runtimeDescriptor: "shell",
44
+ permissions: {
45
+ level: "elevated",
46
+ scopes: ["process:spawn", "filesystem:workspace"],
47
+ },
48
+ telemetry: {
49
+ category: "shell",
50
+ tags: ["tool:run_shell", "legacy:agent-core"],
51
+ },
52
+ },
53
+ search_files: {
54
+ title: "Search Files",
55
+ kind: "filesystem",
56
+ permissions: {
57
+ level: "readonly",
58
+ scopes: ["filesystem:read", "search:content"],
59
+ },
60
+ telemetry: {
61
+ category: "filesystem",
62
+ tags: ["tool:search_files", "legacy:agent-core"],
63
+ },
64
+ },
65
+ list_dir: {
66
+ title: "List Directory",
67
+ kind: "filesystem",
68
+ permissions: {
69
+ level: "readonly",
70
+ scopes: ["filesystem:read"],
71
+ },
72
+ telemetry: {
73
+ category: "filesystem",
74
+ tags: ["tool:list_dir", "legacy:agent-core"],
75
+ },
76
+ },
77
+ run_skill: {
78
+ title: "Run Skill",
79
+ kind: "skill",
80
+ permissions: {
81
+ level: "standard",
82
+ scopes: ["skill:invoke"],
83
+ },
84
+ telemetry: {
85
+ category: "skill",
86
+ tags: ["tool:run_skill", "legacy:agent-core"],
87
+ },
88
+ },
89
+ list_skills: {
90
+ title: "List Skills",
91
+ kind: "skill",
92
+ permissions: {
93
+ level: "readonly",
94
+ scopes: ["skill:read"],
95
+ },
96
+ telemetry: {
97
+ category: "skill",
98
+ tags: ["tool:list_skills", "legacy:agent-core"],
99
+ },
100
+ },
101
+ run_code: {
102
+ title: "Run Code",
103
+ kind: "code",
104
+ permissions: {
105
+ level: "elevated",
106
+ scopes: ["process:spawn", "filesystem:workspace", "runtime:script"],
107
+ },
108
+ telemetry: {
109
+ category: "code",
110
+ tags: ["tool:run_code", "legacy:agent-core"],
111
+ },
112
+ },
113
+ spawn_sub_agent: {
114
+ title: "Spawn Sub Agent",
115
+ kind: "agent",
116
+ permissions: {
117
+ level: "elevated",
118
+ scopes: ["agent:spawn"],
119
+ },
120
+ telemetry: {
121
+ category: "agent",
122
+ tags: ["tool:spawn_sub_agent", "legacy:agent-core"],
123
+ },
124
+ },
125
+ };
126
+
127
+ export function mapLegacyAgentToolDefinition(definition = {}) {
128
+ const fn = definition.function || {};
129
+ const name = fn.name;
130
+ if (!name) {
131
+ throw new Error("Legacy agent tool definition requires function.name.");
132
+ }
133
+
134
+ const metadata = LEGACY_TOOL_METADATA[name] || {
135
+ title: name,
136
+ kind: "legacy",
137
+ permissions: { level: "standard", scopes: [] },
138
+ telemetry: { category: "legacy", tags: [`tool:${name}`, "legacy:agent-core"] },
139
+ };
140
+
141
+ return {
142
+ name,
143
+ title: metadata.title || name,
144
+ kind: metadata.kind,
145
+ description: fn.description || "",
146
+ schema: fn.parameters || { type: "object", properties: {} },
147
+ permissions: metadata.permissions,
148
+ telemetry: metadata.telemetry,
149
+ source: "agent-core",
150
+ };
151
+ }
152
+
153
+ export function createLegacyAgentToolRegistry(definitions = []) {
154
+ const registry = new ToolRegistry();
155
+ definitions.forEach((definition) => {
156
+ registry.register(mapLegacyAgentToolDefinition(definition));
157
+ });
158
+ return registry;
159
+ }
160
+
161
+ export function listLegacyAgentToolNames() {
162
+ return Object.keys(LEGACY_TOOL_METADATA);
163
+ }
164
+
165
+ const runtimeRegistry = createDefaultToolRegistry();
166
+
167
+ export function getRuntimeToolDescriptor(toolName) {
168
+ const descriptorName = LEGACY_TOOL_METADATA[toolName]?.runtimeDescriptor;
169
+ if (!descriptorName) return null;
170
+ return runtimeRegistry.get(descriptorName) || null;
171
+ }
@@ -0,0 +1,141 @@
1
+ function normalizeDescriptor(descriptor = {}) {
2
+ if (!descriptor || typeof descriptor !== "object") {
3
+ throw new Error("Tool descriptor must be an object.");
4
+ }
5
+
6
+ const name = String(descriptor.name || "").trim();
7
+ if (!name) {
8
+ throw new Error("Tool descriptor requires a name.");
9
+ }
10
+
11
+ return {
12
+ name,
13
+ title: descriptor.title || name,
14
+ kind: descriptor.kind || "custom",
15
+ description: descriptor.description || "",
16
+ schema: descriptor.schema || { type: "object", properties: {} },
17
+ permissions: {
18
+ level: descriptor.permissions?.level || "standard",
19
+ scopes: Array.isArray(descriptor.permissions?.scopes)
20
+ ? [...descriptor.permissions.scopes]
21
+ : [],
22
+ },
23
+ telemetry: {
24
+ category: descriptor.telemetry?.category || descriptor.kind || "custom",
25
+ tags: Array.isArray(descriptor.telemetry?.tags)
26
+ ? [...descriptor.telemetry.tags]
27
+ : [],
28
+ },
29
+ source: descriptor.source || "runtime",
30
+ enabled: descriptor.enabled !== false,
31
+ };
32
+ }
33
+
34
+ export class ToolRegistry {
35
+ constructor(seed = []) {
36
+ this._tools = new Map();
37
+ seed.forEach((descriptor) => this.register(descriptor));
38
+ }
39
+
40
+ register(descriptor) {
41
+ const normalized = normalizeDescriptor(descriptor);
42
+ this._tools.set(normalized.name, normalized);
43
+ return normalized;
44
+ }
45
+
46
+ has(name) {
47
+ return this._tools.has(name);
48
+ }
49
+
50
+ get(name) {
51
+ return this._tools.get(name) || null;
52
+ }
53
+
54
+ list({ enabledOnly = false, kind = null } = {}) {
55
+ return [...this._tools.values()].filter((descriptor) => {
56
+ if (enabledOnly && descriptor.enabled === false) return false;
57
+ if (kind && descriptor.kind !== kind) return false;
58
+ return true;
59
+ });
60
+ }
61
+
62
+ toJSON() {
63
+ return this.list();
64
+ }
65
+ }
66
+
67
+ export const DEFAULT_TOOL_DESCRIPTORS = [
68
+ {
69
+ name: "shell",
70
+ title: "Shell Command Runner",
71
+ kind: "shell",
72
+ description: "Execute shell commands with runtime-managed policy checks.",
73
+ schema: {
74
+ type: "object",
75
+ properties: {
76
+ command: { type: "string" },
77
+ cwd: { type: "string" },
78
+ },
79
+ required: ["command"],
80
+ },
81
+ permissions: {
82
+ level: "elevated",
83
+ scopes: ["process:spawn", "filesystem:workspace"],
84
+ },
85
+ telemetry: {
86
+ category: "shell",
87
+ tags: ["tool:shell", "runtime:managed"],
88
+ },
89
+ },
90
+ {
91
+ name: "git",
92
+ title: "Git Operation Runner",
93
+ kind: "git",
94
+ description: "Run git-oriented commands with runtime telemetry tagging.",
95
+ schema: {
96
+ type: "object",
97
+ properties: {
98
+ command: { type: "string" },
99
+ cwd: { type: "string" },
100
+ },
101
+ required: ["command"],
102
+ },
103
+ permissions: {
104
+ level: "elevated",
105
+ scopes: ["process:spawn", "filesystem:workspace", "vcs:git"],
106
+ },
107
+ telemetry: {
108
+ category: "git",
109
+ tags: ["tool:git", "runtime:managed"],
110
+ },
111
+ },
112
+ {
113
+ name: "mcp",
114
+ title: "MCP Tool Gateway",
115
+ kind: "mcp",
116
+ description: "Invoke MCP-managed capabilities through the runtime registry.",
117
+ schema: {
118
+ type: "object",
119
+ properties: {
120
+ server: { type: "string" },
121
+ tool: { type: "string" },
122
+ args: { type: "object" },
123
+ },
124
+ required: ["server", "tool"],
125
+ },
126
+ permissions: {
127
+ level: "standard",
128
+ scopes: ["mcp:invoke"],
129
+ },
130
+ telemetry: {
131
+ category: "mcp",
132
+ tags: ["tool:mcp", "runtime:managed"],
133
+ },
134
+ },
135
+ ];
136
+
137
+ export function createDefaultToolRegistry() {
138
+ return new ToolRegistry(DEFAULT_TOOL_DESCRIPTORS);
139
+ }
140
+
141
+ export { normalizeDescriptor as normalizeToolDescriptor };
@@ -0,0 +1,28 @@
1
+ export function createToolContext({
2
+ toolName = null,
3
+ cwd = process.cwd(),
4
+ sessionId = null,
5
+ runtimeKind = null,
6
+ policy = {},
7
+ metadata = {},
8
+ } = {}) {
9
+ return {
10
+ toolName,
11
+ cwd,
12
+ sessionId,
13
+ runtimeKind,
14
+ policy,
15
+ metadata,
16
+ };
17
+ }
18
+
19
+ export function extendToolContext(context, patch = {}) {
20
+ return {
21
+ ...context,
22
+ ...patch,
23
+ metadata: {
24
+ ...(context?.metadata || {}),
25
+ ...(patch.metadata || {}),
26
+ },
27
+ };
28
+ }
@@ -0,0 +1,28 @@
1
+ export const TOOL_PERMISSION_LEVELS = {
2
+ readonly: 0,
3
+ standard: 1,
4
+ elevated: 2,
5
+ };
6
+
7
+ export function normalizeToolPermissions(permissions = {}) {
8
+ return {
9
+ level: permissions.level || "standard",
10
+ scopes: Array.isArray(permissions.scopes) ? [...permissions.scopes] : [],
11
+ };
12
+ }
13
+
14
+ export function isToolAllowed(descriptor, policy = {}) {
15
+ const permissions = normalizeToolPermissions(descriptor?.permissions);
16
+ const allowlist = Array.isArray(policy.allowlist) ? policy.allowlist : null;
17
+ const denylist = Array.isArray(policy.denylist) ? policy.denylist : [];
18
+ const maxLevel = policy.maxLevel || "elevated";
19
+
20
+ if (!descriptor?.name) return false;
21
+ if (allowlist && !allowlist.includes(descriptor.name)) return false;
22
+ if (denylist.includes(descriptor.name)) return false;
23
+
24
+ return (
25
+ TOOL_PERMISSION_LEVELS[permissions.level] <=
26
+ TOOL_PERMISSION_LEVELS[maxLevel]
27
+ );
28
+ }
@@ -0,0 +1,39 @@
1
+ import { createTelemetryRecord } from "../runtime/contracts/telemetry-record.js";
2
+
3
+ export function createToolTelemetryTags(descriptor, extraTags = []) {
4
+ const baseTags = Array.isArray(descriptor?.telemetry?.tags)
5
+ ? descriptor.telemetry.tags
6
+ : [];
7
+ const tags = [
8
+ ...baseTags,
9
+ descriptor?.name ? `tool:${descriptor.name}` : null,
10
+ descriptor?.kind ? `kind:${descriptor.kind}` : null,
11
+ ...extraTags,
12
+ ].filter(Boolean);
13
+ return [...new Set(tags)];
14
+ }
15
+
16
+ export function createToolTelemetryRecord({
17
+ descriptor,
18
+ status = "completed",
19
+ durationMs = 0,
20
+ sessionId = null,
21
+ metadata = {},
22
+ } = {}) {
23
+ return {
24
+ ...createTelemetryRecord({
25
+ kind: "tool-execution",
26
+ source: descriptor?.source || "runtime",
27
+ }, {
28
+ ...metadata,
29
+ category: descriptor?.telemetry?.category || descriptor?.kind || "tool",
30
+ tags: createToolTelemetryTags(descriptor),
31
+ }),
32
+ toolName: descriptor?.name || null,
33
+ category: descriptor?.telemetry?.category || descriptor?.kind || "tool",
34
+ status,
35
+ durationMs,
36
+ sessionId,
37
+ metadata,
38
+ };
39
+ }
@@ -1,3 +0,0 @@
1
- import{o as V,a3 as W,a1 as o,a5 as n,u as l,k as s,Z as e,W as $,a4 as z,c as O,f as h,X as m,$ as E,Y as w,G as v,a8 as L}from"./vendor-CN0Iv_qZ.js";import{u as G}from"./ws-DwluTqT5.js";import{u as H}from"./chat-C_hu-qNs.js";import{_ as X}from"./_plugin-vue_export-helper-DlAUqK2U.js";import{R as Y,F as Z,i as j,c as R,M as D,j as q,k as J,b as N,S as K,d as Q}from"./antd-CJSBocer.js";const U={style:{display:"flex","align-items":"center","justify-content":"space-between","margin-bottom":"20px"}},tt={class:"page-sub"},st={style:{display:"flex","align-items":"center",gap:"12px","flex-wrap":"wrap"}},et={style:{color:"#91caff","font-weight":"600"}},ot={style:{color:"#4a6fa5","font-size":"11px","font-family":"monospace"}},lt={class:"stat-header"},at={class:"stat-sub"},nt={class:"stat-header"},rt={class:"stat-value",style:{color:"#91caff","font-size":"15px",overflow:"hidden","text-overflow":"ellipsis","white-space":"nowrap"}},ut={class:"stat-sub",style:{overflow:"hidden","text-overflow":"ellipsis","white-space":"nowrap"}},it={class:"stat-header"},dt={class:"stat-value",style:{color:"#1677ff"}},ct={class:"stat-header"},pt={class:"stat-value",style:{color:"#c084fc"}},vt={class:"stat-header"},ft={class:"stat-sub"},mt={class:"stat-header"},bt={class:"stat-value",style:{color:"#13c2c2"}},gt={class:"stat-header"},_t={class:"stat-value",style:{color:"#faad14"}},yt={class:"status-log"},kt={style:{color:"#91caff"}},Ct={style:{color:"var(--text-muted)","font-family":"monospace","font-size":"11px"}},wt={style:{color:"var(--text-secondary)","font-family":"monospace","font-size":"12px"}},xt={__name:"Dashboard",setup(St){const A=E(),b=G(),P=H(),c=window.__CC_CONFIG__||{},g=O(()=>c.mode==="project"),x=O(()=>b.status),k=h(!1),S=h(""),a=h({activeLlm:null,activeModel:null,skillCount:0,sessionCount:0,appRunning:!1,setupDone:!1,edition:"",mcpCount:null,noteCount:null});async function M(){k.value=!0,a.value.wsStatus=b.status,S.value="";try{const[r,t]=await Promise.allSettled([b.execute("status",15e3),b.listSessions()]);if(r.status==="fulfilled"){const u=r.value.output;S.value=u.split(`
2
- `).slice(0,20).join(`
3
- `),T(u)}t.status==="fulfilled"&&(a.value.sessionCount=t.value.length),Promise.allSettled([b.execute("skill sources",15e3),b.execute("llm providers",15e3)]).then(([u,p])=>{if(u.status==="fulfilled"){const i=u.value.output.match(/(\d+)\s*(?:skills|技能)/i);i&&(a.value.skillCount=parseInt(i[1]))}if(p.status==="fulfilled"){const C=p.value.output.match(/active[:\s]+(\S+)/i);C&&!a.value.activeLlm&&(a.value.activeLlm=C[1])}}),b.execute("mcp servers",1e4).then(({output:u})=>{const p=(u.match(/^[a-z]/gm)||[]).length;a.value.mcpCount=p}).catch(()=>{a.value.mcpCount=0})}catch{}finally{k.value=!1}}function T(r){a.value.appRunning=r.includes("Desktop app running"),a.value.setupDone=r.includes("Setup completed");const t=r.match(/Edition:\s+(\S+)/i);t&&(a.value.edition=t[1]);const u=r.match(/LLM:\s+(\S+)\s+\(([^)]+)\)/i);if(u)a.value.activeLlm=u[1],a.value.activeModel=u[2];else{const p=r.match(/LLM:\s+(\S+)/i);p&&(a.value.activeLlm=p[1])}}async function I(){await P.createSession("agent"),A.push("/chat")}return V(()=>setTimeout(M,300)),(r,t)=>{const u=m("a-button"),p=m("a-tag"),i=m("a-card"),C=m("a-badge"),d=m("a-col"),y=m("a-row"),B=m("a-space"),_=m("a-descriptions-item"),F=m("a-descriptions");return w(),W("div",null,[o("div",U,[o("div",null,[t[10]||(t[10]=o("h2",{class:"page-title"},"仪表板",-1)),o("p",tt,n(g.value?`项目「${l(c).projectName||"未命名"}」运行概览`:"ChainlessChain 全局运行状态"),1)]),s(u,{type:"primary",ghost:"",loading:k.value,onClick:M},{icon:e(()=>[s(l(Y))]),default:e(()=>[t[11]||(t[11]=v(" 刷新 ",-1))]),_:1},8,["loading"])]),g.value?(w(),$(i,{key:0,style:{background:"rgba(22,119,255,.08)","border-color":"rgba(22,119,255,.25)","margin-bottom":"16px"},size:"small"},{default:e(()=>[o("div",st,[s(l(Z),{style:{color:"#1677ff","font-size":"18px"}}),o("div",null,[o("div",et,n(l(c).projectName||"项目"),1),o("div",ot,n(l(c).projectRoot),1)]),s(p,{color:"blue",style:{"margin-left":"auto"}},{default:e(()=>[...t[12]||(t[12]=[v("项目级面板",-1)])]),_:1})])]),_:1})):z("",!0),s(y,{gutter:[12,12],style:{"margin-bottom":"16px"}},{default:e(()=>[s(d,{xs:24,sm:12,lg:6},{default:e(()=>[s(i,{class:"stat-card gateway-card",size:"small"},{default:e(()=>[o("div",lt,[t[13]||(t[13]=o("span",{class:"stat-label"},"WebSocket Gateway",-1)),s(C,{status:x.value==="connected"?"success":"error"},null,8,["status"])]),o("div",{class:"stat-value",style:L({color:x.value==="connected"?"#52c41a":"#888"})},n(x.value==="connected"?"运行中":"未连接"),5),o("div",at,"端口 "+n(l(c).wsPort||18800)+" · "+n(l(c).wsHost||"127.0.0.1"),1)]),_:1})]),_:1}),s(d,{xs:24,sm:12,lg:6},{default:e(()=>[s(i,{class:"stat-card",size:"small"},{default:e(()=>[o("div",nt,[t[14]||(t[14]=o("span",{class:"stat-label"},"主 LLM",-1)),s(l(j),{style:{color:"#1677ff"}})]),o("div",rt,n(a.value.activeLlm||"未配置"),1),o("div",ut,n(a.value.activeModel||"—"),1)]),_:1})]),_:1}),s(d,{xs:24,sm:12,lg:6},{default:e(()=>[s(i,{class:"stat-card",size:"small",style:{cursor:"pointer"},onClick:t[0]||(t[0]=f=>r.$router.push("/skills"))},{default:e(()=>[o("div",it,[t[15]||(t[15]=o("span",{class:"stat-label"},"可用技能",-1)),s(l(R),{style:{color:"#1677ff"}})]),o("div",dt,n(a.value.skillCount||"—"),1),t[16]||(t[16]=o("div",{class:"stat-sub"},"点击管理技能",-1))]),_:1})]),_:1}),s(d,{xs:24,sm:12,lg:6},{default:e(()=>[s(i,{class:"stat-card",size:"small",style:{cursor:"pointer"},onClick:t[1]||(t[1]=f=>r.$router.push("/chat"))},{default:e(()=>[o("div",ct,[t[17]||(t[17]=o("span",{class:"stat-label"},"AI 会话",-1)),s(l(D),{style:{color:"#722ed1"}})]),o("div",pt,n(a.value.sessionCount),1),t[18]||(t[18]=o("div",{class:"stat-sub"},"点击进入对话",-1))]),_:1})]),_:1})]),_:1}),s(y,{gutter:[12,12],style:{"margin-bottom":"16px"}},{default:e(()=>[s(d,{xs:24,sm:8},{default:e(()=>[s(i,{class:"stat-card",size:"small"},{default:e(()=>[o("div",vt,[t[19]||(t[19]=o("span",{class:"stat-label"},"应用状态",-1)),s(l(q),{style:L({color:a.value.appRunning?"#52c41a":"#888"})},null,8,["style"])]),o("div",{class:"stat-value",style:L({color:a.value.appRunning?"#52c41a":"#888",fontSize:"15px"})},n(a.value.appRunning?"运行中":a.value.setupDone?"已初始化":"未启动"),5),o("div",ft,n(a.value.edition||"Community")+" Edition",1)]),_:1})]),_:1}),s(d,{xs:24,sm:8},{default:e(()=>[s(i,{class:"stat-card",size:"small",style:{cursor:"pointer"},onClick:t[2]||(t[2]=f=>r.$router.push("/mcp"))},{default:e(()=>[o("div",mt,[t[20]||(t[20]=o("span",{class:"stat-label"},"MCP 工具",-1)),s(l(J),{style:{color:"#13c2c2"}})]),o("div",bt,n(a.value.mcpCount??"—"),1),t[21]||(t[21]=o("div",{class:"stat-sub"},"已挂载扩展",-1))]),_:1})]),_:1}),s(d,{xs:24,sm:8},{default:e(()=>[s(i,{class:"stat-card",size:"small",style:{cursor:"pointer"},onClick:t[3]||(t[3]=f=>r.$router.push("/notes"))},{default:e(()=>[o("div",gt,[t[22]||(t[22]=o("span",{class:"stat-label"},"知识库笔记",-1)),s(l(N),{style:{color:"#faad14"}})]),o("div",_t,n(a.value.noteCount??"—"),1),t[23]||(t[23]=o("div",{class:"stat-sub"},"点击管理笔记",-1))]),_:1})]),_:1})]),_:1}),s(y,{gutter:[16,16]},{default:e(()=>[s(d,{xs:24,lg:10},{default:e(()=>[s(i,{title:"快速操作",style:{background:"var(--bg-card)","border-color":"var(--border-color)",height:"100%"}},{default:e(()=>[s(B,{direction:"vertical",style:{width:"100%"},size:"middle"},{default:e(()=>[s(u,{type:"primary",block:"",onClick:t[4]||(t[4]=f=>r.$router.push("/chat"))},{icon:e(()=>[s(l(D))]),default:e(()=>[v(" "+n(g.value?"进入项目 Chat":"新建 AI 对话"),1)]),_:1}),s(u,{block:"",onClick:I,style:{background:"rgba(114,46,209,.12)","border-color":"#722ed1",color:"#722ed1"}},{icon:e(()=>[s(l(j))]),default:e(()=>[t[24]||(t[24]=v(" 启动 Agent 模式 ",-1))]),_:1}),s(y,{gutter:8},{default:e(()=>[s(d,{span:12},{default:e(()=>[s(u,{block:"",onClick:t[5]||(t[5]=f=>r.$router.push("/services")),style:{background:"var(--bg-card-hover)","border-color":"var(--border-color)"}},{icon:e(()=>[s(l(K))]),default:e(()=>[t[25]||(t[25]=v(" 服务管理 ",-1))]),_:1})]),_:1}),s(d,{span:12},{default:e(()=>[s(u,{block:"",onClick:t[6]||(t[6]=f=>r.$router.push("/logs")),style:{background:"var(--bg-card-hover)","border-color":"var(--border-color)"}},{icon:e(()=>[s(l(N))]),default:e(()=>[t[26]||(t[26]=v(" 查看日志 ",-1))]),_:1})]),_:1})]),_:1}),s(y,{gutter:8},{default:e(()=>[s(d,{span:12},{default:e(()=>[s(u,{block:"",onClick:t[7]||(t[7]=f=>r.$router.push("/skills")),style:{background:"var(--bg-card-hover)","border-color":"var(--border-color)"}},{icon:e(()=>[s(l(R))]),default:e(()=>[t[27]||(t[27]=v(" 技能管理 ",-1))]),_:1})]),_:1}),s(d,{span:12},{default:e(()=>[s(u,{block:"",onClick:t[8]||(t[8]=f=>r.$router.push("/providers")),style:{background:"var(--bg-card-hover)","border-color":"var(--border-color)"}},{icon:e(()=>[s(l(Q))]),default:e(()=>[t[28]||(t[28]=v(" LLM 配置 ",-1))]),_:1})]),_:1})]),_:1})]),_:1})]),_:1})]),_:1}),s(d,{xs:24,lg:14},{default:e(()=>[s(i,{title:"最近状态",style:{background:"var(--bg-card)","border-color":"var(--border-color)"},loading:k.value},{extra:e(()=>[s(u,{type:"link",size:"small",onClick:t[9]||(t[9]=f=>r.$router.push("/logs"))},{default:e(()=>[...t[29]||(t[29]=[v("查看更多 →",-1)])]),_:1})]),default:e(()=>[o("pre",yt,n(S.value||"点击刷新加载系统状态..."),1)]),_:1},8,["loading"])]),_:1})]),_:1}),s(i,{title:"运行信息",style:{background:"var(--bg-card)","border-color":"var(--border-color)","margin-top":"16px"}},{default:e(()=>[s(F,{column:{xs:1,sm:2,lg:3},size:"small"},{default:e(()=>[s(_,{label:"面板模式"},{default:e(()=>[s(p,{color:g.value?"blue":"purple"},{default:e(()=>[v(n(g.value?"项目级":"全局"),1)]),_:1},8,["color"])]),_:1}),g.value?(w(),$(_,{key:0,label:"项目名称"},{default:e(()=>[o("span",kt,n(l(c).projectName||"—"),1)]),_:1})):z("",!0),g.value?(w(),$(_,{key:1,label:"项目路径"},{default:e(()=>[o("span",Ct,n(l(c).projectRoot),1)]),_:1})):z("",!0),s(_,{label:"WebSocket"},{default:e(()=>[o("span",wt," ws://"+n(l(c).wsHost||"127.0.0.1")+":"+n(l(c).wsPort||18800),1)]),_:1}),s(_,{label:"认证"},{default:e(()=>[s(p,{color:l(c).wsToken?"green":"default",style:{"font-size":"11px"}},{default:e(()=>[v(n(l(c).wsToken?"已启用":"未启用"),1)]),_:1},8,["color"])]),_:1}),s(_,{label:"版本"},{default:e(()=>[...t[30]||(t[30]=[o("span",{style:{color:"var(--text-muted)"}},"v5.0.2.7",-1)])]),_:1})]),_:1})]),_:1})])}}},Ot=X(xt,[["__scopeId","data-v-2ac2518e"]]);export{Ot as default};
@@ -1 +0,0 @@
1
- .stat-card[data-v-2ac2518e]{background:var(--bg-card)!important;border-color:var(--border-color)!important;transition:border-color .2s}.stat-card[data-v-2ac2518e]:hover{border-color:var(--text-muted)!important}.stat-header[data-v-2ac2518e]{display:flex;justify-content:space-between;align-items:center;margin-bottom:6px}.stat-label[data-v-2ac2518e]{color:var(--text-secondary);font-size:12px}.stat-value[data-v-2ac2518e]{font-size:22px;font-weight:600;line-height:1.2;margin-bottom:4px}.stat-sub[data-v-2ac2518e]{color:var(--text-muted);font-size:11px}.gateway-card[data-v-2ac2518e]{border-left:3px solid #1677ff!important}.status-log[data-v-2ac2518e]{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}
@@ -1 +0,0 @@
1
- import{V as F,f as $,c as A,o as I,b as N,a3 as c,a1 as f,k as s,Z as o,u as l,W as T,a4 as S,X as g,Y as i,G as m,F as x,a7 as P,a5 as d}from"./vendor-CN0Iv_qZ.js";import{u as B}from"./ws-DwluTqT5.js";import{_ as R}from"./_plugin-vue_export-helper-DlAUqK2U.js";import{R as L}from"./antd-CJSBocer.js";const M=F("tasks",()=>{const y=$([]),e=$(!1);let k=null;const z=A(()=>y.value.filter(t=>t.status==="running")),C=A(()=>y.value.filter(t=>t.status==="pending")),w=A(()=>y.value.filter(t=>t.status==="completed"||t.status==="failed"||t.status==="timeout"));async function a(){const t=B();e.value=!0;try{const _=await t.execute("tasks-list");_&&Array.isArray(_.tasks)&&(y.value=_.tasks)}catch{}finally{e.value=!1}}async function r(t){const _=B();try{await _.sendRaw({type:"tasks-stop",taskId:t}),await a()}catch{}}function b(t=5e3){h(),a(),k=setInterval(a,t)}function h(){k&&(clearInterval(k),k=null)}function v(t){return!t||t<0?"-":t<1e3?`${t}ms`:t<6e4?`${(t/1e3).toFixed(1)}s`:`${(t/6e4).toFixed(1)}m`}function p(t){switch(t){case"running":return"processing";case"pending":return"default";case"completed":return"success";case"failed":return"error";case"timeout":return"warning";default:return"default"}}return{tasks:y,loading:e,running:z,pending:C,completed:w,fetchTasks:a,stopTask:r,startPolling:b,stopPolling:h,formatDuration:v,getStatusColor:p}}),U={style:{display:"flex","align-items":"center","justify-content":"space-between","margin-bottom":"24px"}},W={class:"task-header"},j={class:"task-desc"},E={class:"task-id"},G={class:"task-meta"},O=["title"],X={key:0,style:{color:"#ff4d4f"}},Y={key:1,style:{color:"#52c41a"}},Z={key:2,style:{color:"var(--text-tertiary)"}},q={__name:"Tasks",setup(y){const e=M(),k=[{title:"状态",key:"status",width:90},{title:"描述",key:"description",ellipsis:!0},{title:"类型",dataIndex:"type",width:80},{title:"耗时",key:"duration",width:90},{title:"创建时间",key:"createdAt",width:150},{title:"结果",key:"result",ellipsis:!0},{title:"操作",key:"action",width:80}];function z(a){return a.status==="running"&&a.startedAt?e.formatDuration(Date.now()-a.startedAt):a.completedAt&&a.startedAt?e.formatDuration(a.completedAt-a.startedAt):"-"}function C(a){return a?new Date(a).toLocaleString():"-"}function w(a,r){return a?a.length>r?a.slice(0,r)+"...":a:""}return I(()=>e.startPolling(5e3)),N(()=>e.stopPolling()),(a,r)=>{const b=g("a-button"),h=g("a-space"),v=g("a-statistic"),p=g("a-card"),t=g("a-col"),_=g("a-row"),D=g("a-tag"),V=g("a-table");return i(),c("div",null,[f("div",U,[r[2]||(r[2]=f("div",null,[f("h2",{class:"page-title"},"后台任务"),f("p",{class:"page-sub"},"Background Task Manager — 后台任务监控与管理")],-1)),s(h,null,{default:o(()=>[s(b,{ghost:"",loading:l(e).loading,onClick:r[0]||(r[0]=n=>l(e).fetchTasks())},{icon:o(()=>[s(l(L))]),default:o(()=>[r[1]||(r[1]=m(" 刷新 ",-1))]),_:1},8,["loading"])]),_:1})]),s(_,{gutter:[16,16],style:{"margin-bottom":"20px"}},{default:o(()=>[s(t,{xs:12,sm:6},{default:o(()=>[s(p,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"},size:"small"},{default:o(()=>[s(v,{title:"全部任务",value:l(e).tasks.length,"value-style":"color: var(--text-secondary); font-size: 18px;"},null,8,["value"])]),_:1})]),_:1}),s(t,{xs:12,sm:6},{default:o(()=>[s(p,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"},size:"small"},{default:o(()=>[s(v,{title:"运行中",value:l(e).running.length,"value-style":"color: #1677ff; font-size: 18px;"},null,8,["value"])]),_:1})]),_:1}),s(t,{xs:12,sm:6},{default:o(()=>[s(p,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"},size:"small"},{default:o(()=>[s(v,{title:"等待中",value:l(e).pending.length,"value-style":"color: #faad14; font-size: 18px;"},null,8,["value"])]),_:1})]),_:1}),s(t,{xs:12,sm:6},{default:o(()=>[s(p,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"},size:"small"},{default:o(()=>[s(v,{title:"已完成",value:l(e).completed.length,"value-style":"color: #52c41a; font-size: 18px;"},null,8,["value"])]),_:1})]),_:1})]),_:1}),l(e).running.length>0?(i(),T(p,{key:0,title:"运行中的任务",style:{background:"var(--bg-card)","border-color":"var(--border-color)","margin-bottom":"16px"},size:"small"},{default:o(()=>[(i(!0),c(x,null,P(l(e).running,n=>(i(),c("div",{key:n.id,class:"task-item running"},[f("div",W,[s(D,{color:l(e).getStatusColor(n.status)},{default:o(()=>[m(d(n.status.toUpperCase()),1)]),_:2},1032,["color"]),f("span",j,d(n.description),1),f("span",E,d(n.id.slice(0,16)),1)]),f("div",G,[f("span",null,"类型: "+d(n.type),1),f("span",null,"已运行: "+d(l(e).formatDuration(Date.now()-n.startedAt)),1),s(b,{size:"small",danger:"",onClick:u=>l(e).stopTask(n.id)},{default:o(()=>[...r[3]||(r[3]=[m("停止",-1)])]),_:1},8,["onClick"])])]))),128))]),_:1})):S("",!0),s(p,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:o(()=>[s(V,{columns:k,"data-source":l(e).tasks,pagination:{pageSize:15,size:"small"},loading:l(e).loading,"row-key":"id",size:"small"},{bodyCell:o(({column:n,record:u})=>[n.key==="status"?(i(),T(D,{key:0,color:l(e).getStatusColor(u.status)},{default:o(()=>[m(d(u.status),1)]),_:2},1032,["color"])):n.key==="description"?(i(),c("span",{key:1,title:u.command},d(u.description),9,O)):n.key==="duration"?(i(),c(x,{key:2},[m(d(z(u)),1)],64)):n.key==="createdAt"?(i(),c(x,{key:3},[m(d(C(u.createdAt)),1)],64)):n.key==="result"?(i(),c(x,{key:4},[u.error?(i(),c("span",X,d(w(u.error,60)),1)):u.result?(i(),c("span",Y,d(w(String(u.result),60)),1)):(i(),c("span",Z,"-"))],64)):n.key==="action"?(i(),c(x,{key:5},[u.status==="running"?(i(),T(b,{key:0,size:"small",danger:"",onClick:H=>l(e).stopTask(u.id)},{default:o(()=>[...r[4]||(r[4]=[m(" 停止 ",-1)])]),_:1},8,["onClick"])):S("",!0)],64)):S("",!0)]),_:1},8,["data-source","loading"])]),_:1})])}}},et=R(q,[["__scopeId","data-v-a8667a5d"]]);export{et as default};
@@ -1 +0,0 @@
1
- .task-item[data-v-a8667a5d]{padding:12px;border-radius:6px;margin-bottom:8px;background:var(--bg-card-hover, rgba(255, 255, 255, .04))}.task-item.running[data-v-a8667a5d]{border-left:3px solid #1677ff}.task-header[data-v-a8667a5d]{display:flex;align-items:center;gap:8px;margin-bottom:6px}.task-desc[data-v-a8667a5d]{flex:1;color:var(--text-primary);font-weight:500}.task-id[data-v-a8667a5d]{font-family:monospace;font-size:12px;color:var(--text-tertiary)}.task-meta[data-v-a8667a5d]{display:flex;gap:16px;align-items:center;font-size:12px;color:var(--text-secondary)}
@@ -1 +0,0 @@
1
- import{V as k,f as w,r as h}from"./vendor-CN0Iv_qZ.js";import{u as i}from"./ws-DwluTqT5.js";const A=k("chat",()=>{const u=w([]),f=w(null),s=h({}),o=h({}),r=h({}),p=w(!1);function v(t){return s[t]||(s[t]=[]),s[t]}async function q(){const t=i();u.value=await t.listSessions()}async function y(t="chat"){const e=i(),n=await e.createSession(t);return u.value.unshift({id:n,type:t,title:t==="chat"?"新对话":"新 Agent",createdAt:Date.now(),messageCount:0}),e.onSession(n,a=>S(n,a)),f.value=n,s[n]=[],o[n]={content:"",active:!1},n}function S(t,e){const n=v(t);if(e.type==="response-token")o[t]||(o[t]={content:"",active:!0}),o[t].content+=e.token||"",o[t].active=!0;else if(e.type==="response-complete"){const a=e.content||o[t]?.content||"";n.push({role:"assistant",content:a,timestamp:Date.now()}),o[t]&&(o[t].content="",o[t].active=!1);const c=u.value.find(l=>l.id===t);if(c&&c.title.startsWith("新")){const l=n.find(g=>g.role==="user");l&&(c.title=l.content.slice(0,30))}p.value=!1}else if(e.type==="tool-executing")n.push({role:"tool",tool:e.tool,input:e.input,status:"running",timestamp:Date.now()});else if(e.type==="tool-result"){const a=[...n].reverse().find(c=>c.role==="tool"&&c.tool===e.tool);a&&(a.result=e.result,a.status="done")}else e.type==="question"&&(r[t]={requestId:e.requestId||e.id,question:e.question,choices:e.choices||[]})}async function D(t,e){const n=i();v(t).push({role:"user",content:e,timestamp:Date.now()}),o[t]||(o[t]={content:"",active:!1}),o[t].active=!0,p.value=!0,n.sendSessionMessage(t,e)}function M(t,e){const n=i(),a=r[t];a&&(n.answerQuestion(t,a.requestId,e),delete r[t])}async function Q(t){f.value=t,s[t]||(s[t]=[],o[t]={content:"",active:!1},i().onSession(t,n=>S(t,n)))}return{sessions:u,currentSessionId:f,messages:s,streaming:o,pendingQuestion:r,isLoading:p,loadSessions:q,createSession:y,sendMessage:D,answerQuestion:M,switchSession:Q,getMessages:v}});export{A as u};
@@ -1 +0,0 @@
1
- import{V as _,f as m,c as $}from"./vendor-CN0Iv_qZ.js";let R=0;const f=()=>`wp-${++R}`,H=_("ws",()=>{const c=m(null),s=m("disconnected"),w=m(null),u=new Map,a=new Map;let h=null,v=1e3;const i=window.__CC_CONFIG__||{},g=$(()=>`ws://${i.wsHost||"127.0.0.1"}:${i.wsPort||18800}`);function p(){if(c.value?.readyState!==WebSocket.OPEN){s.value="connecting",w.value=null;try{const e=new WebSocket(g.value);c.value=e,e.onopen=()=>{v=1e3,i.wsToken?l({type:"auth",id:f(),token:i.wsToken}).then(()=>{s.value="connected"}).catch(()=>{s.value="connected"}):s.value="connected"},e.onmessage=n=>{let t;try{t=JSON.parse(n.data)}catch{return}N(t)},e.onerror=()=>{w.value="WebSocket error",s.value="error"},e.onclose=()=>{s.value="disconnected",c.value=null,u.forEach(({reject:n})=>n(new Error("WebSocket closed"))),u.clear(),h=setTimeout(()=>{v=Math.min(v*2,3e4),p()},v)}}catch(e){s.value="error",w.value=e.message}}}function E(){clearTimeout(h),c.value?.close(),c.value=null,s.value="disconnected"}function N(e){const{type:n,id:t}=e;if(t&&u.has(t)){const{resolve:o,reject:d,timeout:M}=u.get(t);clearTimeout(M),u.delete(t),n==="error"?d(new Error(e.message||"Unknown error")):o(e);return}const r=e.sessionId;r&&a.has(r)&&a.get(r).forEach(d=>d(e)),y.forEach(o=>o(e))}const y=new Set;function O(e){return y.add(e),()=>y.delete(e)}function W(e,n){return a.has(e)||a.set(e,new Set),a.get(e).add(n),()=>{a.get(e)?.delete(n),a.get(e)?.size===0&&a.delete(e)}}function l(e,n=15e3){return new Promise((t,r)=>{if(c.value?.readyState!==WebSocket.OPEN){r(new Error("WebSocket not connected"));return}const o=e.id||f(),d=setTimeout(()=>{u.delete(o),r(new Error("Request timeout"))},n);u.set(o,{resolve:t,reject:r,timeout:d}),c.value.send(JSON.stringify({...e,id:o}))})}function S(e=8e3){return s.value==="connected"?Promise.resolve():new Promise((n,t)=>{const r=Date.now()+e,o=()=>{if(s.value==="connected")return n();if(s.value==="error"||Date.now()>=r)return t(new Error(`WS not ready: ${s.value}`));setTimeout(o,150)};s.value==="disconnected"&&p(),o()})}async function k(e,n=3e4){await S(8e3);const t=await l({type:"execute",command:e},n),r=t.output??t.stdout??"",o=t.stderr??"";return{output:r||o,exitCode:t.exitCode??0}}async function b(e,n=3e4){const{output:t,exitCode:r}=await k(e,n);if(r!==0)throw new Error(`Command failed: ${t}`);try{return JSON.parse(t.trim())}catch{const o=t.match(/\{[\s\S]*\}|\[[\s\S]*\]/);if(o)return JSON.parse(o[0]);throw new Error(`Invalid JSON output: ${t.slice(0,200)}`)}}async function C(e="chat",n=null){await S(8e3);const t=f();return(await l({type:"session-create",id:t,sessionType:e,projectRoot:n||i.projectRoot||null})).sessionId}function J(e,n){c.value?.readyState===WebSocket.OPEN&&c.value.send(JSON.stringify({type:"session-message",id:f(),sessionId:e,content:n}))}function P(e,n,t){c.value?.readyState===WebSocket.OPEN&&c.value.send(JSON.stringify({type:"session-answer",id:f(),sessionId:e,requestId:n,answer:t}))}async function T(){return await S(8e3),(await l({type:"session-list"},1e4)).sessions||[]}async function x(e){try{await l({type:"session-close",sessionId:e},5e3)}catch{}}return{status:s,error:w,wsUrl:g,connect:p,disconnect:E,waitConnected:S,onMessage:O,onSession:W,execute:k,executeJson:b,createSession:C,sendSessionMessage:J,answerQuestion:P,listSessions:T,closeSession:x}});export{H as u};